/* ==========================================================================
   SolidW — Public Booking Page (/site)
   Premium glassmorphism profile card, redesigned per client reference.
   Layout stays a single narrow centered column so the page reads like one
   floating card rather than a dashboard. All IDs/classes referenced by
   site.js are preserved — this is a presentation-only redesign.
   ========================================================================== */

body {
  background: linear-gradient(160deg, var(--bg-canvas) 0%, var(--bg-canvas-alt) 100%);
  min-height: 100vh;
}

.public-topnav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-5);
  background-color: color-mix(in srgb, var(--color-white) 88%, transparent);
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  border-bottom: 1px solid var(--color-border);
  position: sticky;
  top: 0;
  z-index: 50;
}
.public-topnav a {
  font-weight: var(--fw-semibold);
  color: var(--color-text);
  font-size: var(--fs-sm);
}
.public-topnav a:hover { color: var(--color-accent); }

/* Screen-reader-only text — used on the icon-only contact buttons so they
   keep an accessible name without showing a visible label. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---- Page shell — everything lives inside this one narrow column ---- */
.public-page-shell {
  max-width: 600px;
  margin-inline: auto;
  padding-inline: var(--space-4);
  box-sizing: border-box;
}

@media (min-width: 768px) {
  .public-page-shell { max-width: 680px; padding-inline: var(--space-5); }
}

/* ==========================================================================
   Profile header — one seamless rounded card. The cover photo forms the
   top (rounded top corners only) and flows directly into the info panel
   below it (rounded bottom corners only, no gap) so together they read as
   a single card, not two separate pieces. Unlike a Twitter/X header, nothing
   bleeds past the shell's side padding — a visible gutter runs down both
   sides of the whole card, and the avatar sits as a normal row element
   inside the info panel instead of overlapping the cover/card seam.
   ========================================================================== */
.profile-header {
  position: relative;
  margin-top: -6px;
}

.profile-cover {
  position: relative;
  width: calc(100% + (2 * var(--space-4)));
  margin-inline: calc(-1 * var(--space-4));
  height: 155px;
  overflow: hidden;
  background: var(--gradient-accent);
  border-radius: 0;
}
.profile-cover-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 50%;
  transform-origin: center center;
}

@media (min-width: 480px) {
  .profile-cover { height: 190px; }
}
@media (min-width: 768px) {
  .profile-cover {
    height: 250px;
    width: calc(100% + (2 * var(--space-5)));
    margin-inline: calc(-1 * var(--space-5));
  }
}

/* Avatar + name/status sit side by side in one row at the top of the info
   panel — a normal card element, not something overlapping the cover. */
.profile-identity-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.profile-avatar-wrap {
  position: relative;
  z-index: 1;
  width: 56px;
  height: 56px;
  flex-shrink: 0;
  border-radius: var(--radius-full);
  overflow: hidden;
  background: var(--color-white);
  border: 3px solid var(--color-white);
  box-shadow: var(--shadow-md);
}
.public-business-logo {
  width: 100%;
  height: 100%;
  border-radius: var(--radius-full);
  object-fit: cover;
  object-position: 50% 50%;
  transform-origin: center center;
  flex-shrink: 0;
}

@media (min-width: 480px) {
  .profile-avatar-wrap { width: 64px; height: 64px; }
}
@media (min-width: 768px) {
  .profile-avatar-wrap { width: 88px; height: 88px; border-width: 4px; }
}

/* ---- The info panel — flush under the cover, so together they form one
   continuous rounded card rather than two separate floating pieces ---- */
.profile-header .profile-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  background-color: var(--glass-light-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-light-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-soft-lg), var(--shadow-inner-highlight);
  position: relative;
  z-index: 2;
  margin: -12px 0 0;
}

.public-business-info { min-width: 0; text-align: left; }
.about-address {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-3);
}
.public-business-info h1 {
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  color: #111111;
  line-height: var(--lh-tight);
  letter-spacing: -0.01em;
  overflow-wrap: break-word;
}
.public-business-info .address {
  color: #6B7280;
  font-size: var(--fs-sm);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (min-width: 480px) {
  .profile-header .profile-card { margin: -20px 0 0; }
}
@media (min-width: 768px) {
  .profile-header .profile-card { padding: var(--space-4) var(--space-5); margin: -28px 0 0; }
  .public-business-info h1 { font-size: var(--fs-2xl, 1.75rem); }
}

.public-status-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  align-self: flex-start;
  margin-top: var(--space-1);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-full);
  background-color: color-mix(in srgb, var(--color-ink) 5%, transparent);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: #6B7280;
}
.public-status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: var(--color-success);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-success) 18%, transparent);
}
.public-status-dot.closed {
  background-color: var(--color-danger);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-danger) 15%, transparent);
}
.public-status-dot.opening-soon {
  background-color: var(--color-warning);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-warning) 18%, transparent);
}

.profile-bio {
  color: #4B5563;
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
  overflow-wrap: break-word;
}

/* ---- CTA + icon actions row ---- */
.profile-actions-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.profile-cta {
  flex: 1 1 auto;
  min-width: 140px;
  height: 40px;
  padding-inline: var(--space-4);
  border-radius: var(--radius-full);
  background-color: #111111;
  color: #FFFFFF;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  border: none;
  cursor: pointer;
  transition: transform var(--duration-fast) var(--ease-standard),
              background-color var(--duration-fast) var(--ease-standard);
}
.profile-cta:hover { background-color: #000000; }
.profile-cta:active { transform: scale(0.97); }

.profile-icon-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.contact-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-full);
  background-color: var(--glass-light-bg);
  backdrop-filter: var(--glass-blur-sm);
  -webkit-backdrop-filter: var(--glass-blur-sm);
  border: 1px solid var(--glass-light-border);
  box-shadow: var(--shadow-soft-xs);
  color: var(--color-text-muted);
  flex-shrink: 0;
  cursor: pointer;
  transition: transform var(--duration-fast) var(--ease-standard),
              background-color var(--duration-fast) var(--ease-standard),
              border-color var(--duration-fast) var(--ease-standard),
              box-shadow var(--duration-fast) var(--ease-standard),
              color var(--duration-fast) var(--ease-standard);
}
.contact-btn svg { width: 15px; height: 15px; transition: transform var(--duration-fast) var(--ease-standard); }
.contact-btn:hover {
  transform: translateY(-1px);
  background-color: color-mix(in srgb, var(--color-accent) 10%, var(--glass-light-bg));
  border-color: var(--color-accent-line);
  color: var(--color-accent);
  box-shadow: var(--shadow-soft-sm);
}
.contact-btn:hover svg { transform: scale(1.06); }
.contact-btn:active {
  transform: translateY(0) scale(0.94);
  background-color: color-mix(in srgb, var(--color-accent) 16%, var(--glass-light-bg));
  box-shadow: var(--shadow-soft-xs);
}
.contact-btn:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* ---- Location line (directly under the bio) ---- */
.profile-location-line {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin-top: calc(-1 * var(--space-2));
  color: #9CA3AF;
  font-size: var(--fs-xs);
  line-height: var(--lh-normal);
}
.profile-location-line svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  color: #9CA3AF;
}

/* ---- Sticky tabs ---- */
.public-tabs {
  margin: var(--space-4) auto var(--space-4);
  max-width: fit-content;
  position: sticky;
  top: calc(var(--header-height) * 0.6);
  z-index: 40;
  flex-wrap: wrap;
  justify-content: center;
  row-gap: var(--space-1);
  overflow-x: visible;
  padding: var(--space-1);
  gap: 2px;
}

nav.public-tabs button.glass-tab {
  padding: 0.4rem 0.9rem;
  min-height: 32px;
  font-size: var(--fs-sm);
  display: inline-flex;
  align-items: center;
  background-color: transparent !important;
  color: var(--color-text-muted, #5C5A75) !important;
  -webkit-text-fill-color: var(--color-text-muted, #5C5A75);
  transition: background-color var(--duration-base) var(--ease-standard),
              color var(--duration-base) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard),
              transform var(--duration-fast) var(--ease-standard);
}
nav.public-tabs button.glass-tab:hover {
  color: var(--color-text, #201F33) !important;
  -webkit-text-fill-color: var(--color-text, #201F33);
  transform: translateY(-1px);
}
nav.public-tabs button.glass-tab:active {
  transform: translateY(0) scale(0.96);
}
nav.public-tabs button.glass-tab.active {
  background-color: var(--color-ink, #24223B) !important;
  color: var(--color-paper, #FCFBFC) !important;
  -webkit-text-fill-color: var(--color-paper, #FCFBFC);
  box-shadow: var(--shadow-soft-md), inset 0 1px 0 rgba(255, 255, 255, 0.14);
}
nav.public-tabs button.glass-tab.active:hover {
  color: var(--color-paper, #FCFBFC) !important;
  -webkit-text-fill-color: var(--color-paper, #FCFBFC);
}

/* ---- Content sections below the profile card ---- */
.public-content-shell {
  width: 100%;
}

.public-gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: var(--space-3);
}
.public-gallery-grid img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: transform var(--duration-base) var(--ease-standard);
}
.public-gallery-grid img:hover { transform: scale(1.02); }

.public-service-card {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3);
  background-color: var(--glass-light-bg);
  backdrop-filter: var(--glass-blur-sm);
  -webkit-backdrop-filter: var(--glass-blur-sm);
  border: 1px solid var(--glass-light-border);
  border-radius: var(--radius-lg);
  transition: box-shadow var(--duration-base) var(--ease-standard),
              border-color var(--duration-base) var(--ease-standard);
}
.public-service-card:hover {
  box-shadow: var(--shadow-md);
  border-color: color-mix(in srgb, var(--color-accent) 35%, var(--color-border));
}
.public-service-thumb {
  width: 68px;
  height: 68px;
  border-radius: var(--radius-md);
  object-fit: cover;
  flex-shrink: 0;
}
.public-service-info { flex: 1; min-width: 0; }
.public-service-card .name {
  font-weight: var(--fw-semibold);
  font-size: var(--fs-sm);
  line-height: var(--lh-tight);
}
.public-service-duration {
  font-size: var(--fs-xs);
  color: var(--color-text-muted, #6B7280);
  line-height: var(--lh-tight);
  margin-top: 2px;
}
.public-service-desc {
  font-size: var(--fs-xs);
  color: var(--color-text-muted, #6B7280);
  line-height: var(--lh-normal);
  margin-top: 2px;
}
.public-service-card .price {
  color: var(--color-accent);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-sm);
}

/* ---- Selectable service cards (Services tab) ---- */
.service-select-col {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: space-between;
  align-self: stretch;
  gap: var(--space-2);
  flex-shrink: 0;
}
.service-add-btn {
  width: 25px;
  height: 25px;
  border-radius: var(--radius-full);
  border: 1.5px solid var(--color-border);
  background: var(--color-white);
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-standard),
              border-color var(--duration-fast) var(--ease-standard),
              color var(--duration-fast) var(--ease-standard),
              transform var(--duration-fast) var(--ease-standard);
}
.service-add-btn svg { width: 13px; height: 13px; }
.service-add-btn .icon-check { display: none; }
.service-add-btn:hover { border-color: var(--color-accent); color: var(--color-accent); }
.service-add-btn:active { transform: scale(0.92); }

.selectable-service.selected {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 1px var(--color-accent);
}
.selectable-service.selected .service-add-btn {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #FFFFFF;
}
.selectable-service.selected .service-add-btn .icon-plus { display: none; }
.selectable-service.selected .service-add-btn .icon-check { display: block; }
.service-unbookable .service-select-col { opacity: 0.5; }

/* ---- Selected-services cart, shown in the Book Now panel ---- */
.selected-services-box {
  padding: var(--space-4);
  margin-bottom: var(--space-4);
  background-color: color-mix(in srgb, var(--color-accent) 5%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-accent) 20%, var(--color-border));
  border-radius: var(--radius-lg);
}
.selected-services-header {
  font-weight: var(--fw-semibold);
  font-size: var(--fs-sm);
  margin-bottom: var(--space-3);
}

/* ---- Required-field error state — text color only, no layout shift.
   Applied to a <label> when the customer tries to submit the booking
   form with something missing. The "no services selected" message keeps
   its normal muted-purple color even in this state. ---- */
.form-label.field-error {
  color: var(--color-danger);
}

.selected-services-list {
  flex-direction: column;
  gap: var(--space-2);
}
.selected-service-chip {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-size: var(--fs-sm);
}
.selected-service-chip span:first-child { flex: 1; min-width: 0; }
.selected-service-price { color: var(--color-accent); font-weight: var(--fw-semibold); }
.selected-service-remove {
  width: 22px;
  height: 22px;
  border-radius: var(--radius-full);
  border: none;
  background: var(--color-surface-alt);
  color: var(--color-text-muted);
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
}
.selected-service-remove:hover { background: var(--color-danger); color: #FFFFFF; }
.selected-services-total {
  display: flex;
  justify-content: flex-end;
  margin-top: var(--space-3);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-sm);
}
.public-tab-inline-link { color: var(--color-accent); font-weight: var(--fw-medium); -webkit-tap-highlight-color: transparent; }

/* ---- Provider selection (Book Now panel, after services are picked) ---- */
.provider-select-box {
  padding: var(--space-4);
  margin-bottom: var(--space-4);
  background-color: var(--glass-light-bg);
  backdrop-filter: var(--glass-blur-sm);
  -webkit-backdrop-filter: var(--glass-blur-sm);
  border: 1px solid var(--glass-light-border);
  border-radius: var(--radius-lg);
}
.provider-select-grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.provider-select-card {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3) var(--space-2) var(--space-2);
  border-radius: var(--radius-full);
  border: 1.5px solid var(--color-border);
  background: var(--color-white);
  color: var(--color-text);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  cursor: pointer;
  box-shadow: var(--shadow-soft-xs);
  transition: border-color var(--transition-fast), color var(--transition-fast),
    background-color var(--transition-fast), box-shadow var(--transition-fast), transform var(--transition-fast);
}
.provider-select-card:hover {
  border-color: var(--border-brand);
  color: var(--color-accent);
  box-shadow: var(--shadow-soft-sm);
}
.provider-select-card:active { transform: scale(0.96); }
.provider-select-card.selected {
  background: linear-gradient(180deg, #6D7CFF 0%, #5567F2 100%);
  border-color: transparent;
  color: #FFFFFF;
  box-shadow: 0 8px 20px rgba(85, 103, 242, 0.3);
}
.provider-avatar {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-full);
  flex-shrink: 0;
  object-fit: cover;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  background: var(--color-surface-alt);
  color: var(--color-text-muted);
}
.provider-select-card.selected .provider-avatar-initial,
.provider-select-card.selected .provider-avatar-any {
  background: rgba(255, 255, 255, 0.25);
  color: #FFFFFF;
}
.provider-select-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 140px;
}

.public-hours-table { width: 100%; border-collapse: collapse; }
.public-hours-table td {
  padding: var(--space-3) var(--space-2);
  border-bottom: 1px solid var(--color-border);
  font-size: var(--fs-sm);
}
.public-hours-table tr:last-child td { border-bottom: none; }
.public-hours-table td:first-child { font-weight: var(--fw-medium); color: var(--color-text-muted); }
.public-hours-table td:last-child { text-align: right; }
.public-hours-table .today {
  color: var(--color-accent);
  font-weight: var(--fw-semibold);
}

.booking-form-card {
  width: 100%;
  box-sizing: border-box;
  background-color: var(--glass-light-bg);
  backdrop-filter: var(--glass-blur-sm);
  -webkit-backdrop-filter: var(--glass-blur-sm);
  border: 1px solid var(--glass-light-border);
  border-radius: 30px;
  box-shadow: var(--shadow-soft-lg);
}

/* Date/Time row — some browsers (Android Chrome especially) give native
   date/time pickers a hard-coded minimum width that CSS "width" can't
   shrink below, no matter how narrow the column is. Relying on shrinking
   alone can still overflow the screen on those devices. flex-wrap is the
   one thing every phone/every browser respects identically: if both
   fields don't actually fit side by side at a sane minimum width, they
   drop to their own full-width line instead of spilling off-screen. */
.booking-datetime-row {
  flex-wrap: wrap;
}
.booking-datetime-row > .form-group {
  flex: 1 1 140px;
  min-width: 140px;
}
.booking-datetime-row input[type="date"],
.booking-datetime-row input[type="time"] {
  width: 100%;
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
  /* Do NOT set -webkit-appearance/appearance: none here. On iOS Safari
     that strips the native date/time control's own rendering — the
     mm/dd/yyyy placeholder text and the calendar icon both disappear,
     leaving a blank box even though the field still technically works.
     Keeping the native appearance is what actually shows the placeholder
     and icon; we only need to control sizing, not appearance. */
  /* Match the size of the Name/Phone inputs so Date/Time don't look
     shrunken next to them. 16px+ prevents iOS Safari zoom-on-focus. */
  font-size: 17px;
  padding: var(--space-3) var(--space-4);
  min-height: 52px;
  line-height: 1.4;
  color: var(--color-text);
}

/* ==========================================================================
   Date strip — premium, mobile-first, horizontally swipeable date picker
   that replaces the native <input type="date"> on the booking form.
   ========================================================================== */
.date-strip-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.date-strip {
  display: flex;
  gap: var(--space-2);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scroll-behavior: smooth;
  padding: var(--space-1) var(--space-1) var(--space-2);
  -webkit-overflow-scrolling: touch;
  /* Hide the scrollbar but keep native touch/trackpad scrolling — the
     chevrons + swipe gesture are the intended controls, not a visible bar. */
  scrollbar-width: none;
}
.date-strip::-webkit-scrollbar { display: none; }

.date-strip-nav {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border);
  background: var(--color-white);
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: var(--shadow-soft-xs);
  transition: border-color var(--transition-fast), color var(--transition-fast), transform var(--transition-fast);
}
.date-strip-nav svg { width: 16px; height: 16px; }
.date-strip-nav:hover { border-color: var(--color-accent); color: var(--color-accent); }
.date-strip-nav:active { transform: scale(0.92); }

.date-card {
  scroll-snap-align: start;
  flex: 0 0 auto;
  width: 64px;
  min-height: 84px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: var(--space-2) var(--space-1) var(--space-3);
  border-radius: var(--radius-lg);
  border: 1.5px solid var(--color-border);
  background: var(--color-white);
  cursor: pointer;
  transition: border-color var(--transition-fast), background-color var(--transition-fast),
    box-shadow var(--transition-fast), transform var(--transition-fast), opacity var(--transition-fast);
}
.date-card:hover:not(:disabled) {
  border-color: var(--border-brand);
  transform: translateY(-1px);
}
.date-card:active:not(:disabled) { transform: scale(0.96); }

.date-card-day {
  font-size: 11px;
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
}
.date-card.is-today .date-card-day {
  color: var(--color-accent);
}
.date-card-num {
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  line-height: 1.1;
  color: var(--color-text);
}
.date-card-month {
  font-size: 10px;
  color: var(--color-text-faint);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.date-card-indicator {
  min-height: 14px;
  display: flex;
  align-items: center;
  gap: 3px;
  margin-top: 1px;
}
.date-card-availability-text {
  font-size: 9px;
  font-weight: var(--fw-medium);
  color: var(--color-text-faint);
  line-height: 1.15;
  /* Was nowrap — fine for "Plenty"/"Few left" but "Fully booked" (and any
     future longer translation) overflowed the fixed 64px pill. Wrapping
     onto 2 lines keeps every label contained regardless of length. */
  white-space: normal;
  overflow-wrap: break-word;
  text-align: center;
}
.date-dot {
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  flex: 0 0 auto;
}
.date-dot.dot-plenty { background: var(--color-success); box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-success) 18%, transparent); }
.date-dot.dot-few { background: var(--color-warning); box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-warning) 18%, transparent); }
.date-dot.dot-full,
.date-dot.dot-closed { background: var(--color-text-faint); }

.date-card.dot-plenty .date-card-availability-text { color: var(--color-success); }
.date-card.dot-few .date-card-availability-text { color: var(--color-warning); }

/* Selected — prominent lavender/purple accent with a soft glow, per spec */
.date-card.selected {
  border-color: transparent;
  background: linear-gradient(180deg, #6D7CFF 0%, #5567F2 100%);
  box-shadow: 0 10px 28px rgba(85, 103, 242, 0.32);
  transform: translateY(-1px);
}
.date-card.selected .date-card-day,
.date-card.selected .date-card-num,
.date-card.selected .date-card-month,
.date-card.selected .date-card-availability-text {
  color: #FFFFFF;
}
.date-card.selected .date-dot { background: #FFFFFF; box-shadow: none; }

/* Fully booked / closed — muted, disabled, but still legible */
.date-card:disabled {
  cursor: not-allowed;
  background: var(--color-surface-alt);
  border-color: var(--color-border);
  opacity: 0.55;
}
.date-card:disabled:hover { transform: none; border-color: var(--color-border); }
.date-card:disabled .date-card-num { color: var(--color-text-muted); }

/* ---- Confirmation summary — tiny, reassuring, sits above Book Now ---- */
.appointment-summary {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--color-accent) 6%, var(--color-white));
  border: 1px solid color-mix(in srgb, var(--color-accent) 18%, var(--color-border));
}
.appointment-summary-icon {
  flex: 0 0 auto;
  color: var(--color-accent);
  font-size: var(--fs-lg);
}
.appointment-summary-heading {
  font-size: 11px;
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
}
.appointment-summary-detail {
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--color-text);
}

/* Subtle "ready to book" glow once service + date + time are all picked */
#bookingSubmitBtn.btn-primed {
  box-shadow: 0 16px 40px rgba(85, 103, 242, 0.32);
}

/* ---- Real-time slot picker (Book Now panel) ---- */
.slots-hint {
  font-size: var(--fs-sm);
  color: var(--color-text-muted);
  padding: var(--space-3) 0 0;
  margin: 0;
}
.slots-hint .spinner { margin-inline-end: var(--space-2); }

#slotsSections {
  margin-top: var(--space-2);
  animation: slotsFadeIn var(--transition-slow);
}
@keyframes slotsFadeIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}
.slots-section + .slots-section { margin-top: var(--space-5); }
.slots-section-label {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
  margin-bottom: var(--space-3);
}
.slots-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2);
}
@media (max-width: 360px) {
  .slots-grid { grid-template-columns: repeat(2, 1fr); }
}
.slot-btn {
  padding: var(--space-2) var(--space-1);
  min-height: 46px;
  border-radius: var(--radius-md);
  border: 1.5px solid var(--color-border);
  background: var(--color-white);
  color: var(--color-text);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  cursor: pointer;
  box-shadow: var(--shadow-soft-xs);
  transition: border-color var(--transition-fast), color var(--transition-fast),
    background-color var(--transition-fast), box-shadow var(--transition-fast), transform var(--transition-fast);
}
.slot-btn:hover {
  border-color: var(--border-brand);
  color: var(--color-accent);
  box-shadow: var(--shadow-soft-sm);
}
.slot-btn:active { transform: scale(0.95); }
.slot-btn.selected {
  background: linear-gradient(180deg, #6D7CFF 0%, #5567F2 100%);
  border-color: transparent;
  color: #FFFFFF;
  box-shadow: 0 8px 20px rgba(85, 103, 242, 0.3);
}

/* Used by this page's own loading label, and reused by several dashboard
   pages that already reference class="spinner" without ever having a
   definition for it — this is the first stylesheet that defines it. */
.spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid color-mix(in srgb, currentColor 25%, transparent);
  border-top-color: currentColor;
  border-radius: 50%;
  vertical-align: -2px;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.lightbox-overlay {
  position: fixed;
  inset: 0;
  background-color: color-mix(in srgb, black 85%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: var(--z-modal);
  padding: var(--space-5);
}
.lightbox-overlay img {
  max-width: 100%;
  max-height: 90vh;
  border-radius: var(--radius-md);
}
.lightbox-close {
  position: absolute;
  top: var(--space-5);
  right: var(--space-5);
  color: var(--color-paper);
  font-size: var(--fs-xl);
}

.public-footer {
  text-align: center;
  padding: var(--space-5) var(--space-4);
  color: var(--color-text-faint);
  font-size: var(--fs-xs);
}

@media (max-width: 640px) {
  .public-tabs {
    max-width: 100%;
    justify-content: flex-start;
    top: 0;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .public-tabs::-webkit-scrollbar { display: none; }
  nav.public-tabs button.glass-tab {
    padding: 0.4rem 0.85rem;
    min-height: 32px;
    font-size: var(--fs-xs);
    white-space: nowrap;
    flex-shrink: 0;
  }
  .profile-cta { min-width: 100%; order: -1; }
  .profile-actions-row {
    justify-content: center;
    row-gap: var(--space-3);
  }
  .profile-icon-actions { justify-content: center; }
}

@media (max-width: 479px) {
  .profile-header .profile-card {
    padding: var(--space-3);
    margin: -12px 0 0;
  }
}

/* ==========================================================================
   Reviews panel
   ========================================================================== */
.reviews-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-3);
  padding: var(--space-8) var(--space-4);
  color: var(--color-text-muted);
}
.reviews-empty-state svg {
  width: 32px;
  height: 32px;
  stroke: var(--color-accent);
  opacity: 0.6;
}
.reviews-empty-title {
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  color: var(--color-text);
  margin: 0;
}
.reviews-empty-subtitle {
  font-size: var(--fs-sm);
  max-width: 32ch;
  margin: 0;
}
.reviews-summary-card {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
  padding: var(--space-5);
}
.reviews-summary-score {
  font-size: 2.25rem;
  font-weight: var(--fw-semibold);
  color: var(--color-text);
  line-height: 1;
}
.reviews-summary-meta {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.reviews-summary-stars {
  display: inline-flex;
  gap: 2px;
}
.reviews-summary-stars svg,
.review-card-stars svg {
  width: 16px;
  height: 16px;
}
.star-icon {
  stroke: var(--color-gold);
  fill: none;
}
.star-icon.filled {
  fill: var(--color-gold);
}

/* Public review-card list (site.js renderReviews/starsHtml) renders each
   row of 5 stars as <div class="review-stars"><svg class="review-star">.
   These are a different, older set of class names than .review-card-stars
   / .star-icon above, and had no sizing rules of their own — the svgs
   fell back to an unconstrained default size, which is what caused the
   oversized-stars bug on the public review list. */
.review-stars {
  display: inline-flex;
  gap: 2px;
}
.review-stars .review-star {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  stroke: var(--color-gold);
  fill: none;
}
.review-stars .review-star.filled {
  fill: var(--color-gold);
}
.reviews-summary-count {
  font-size: var(--fs-sm);
}
.reviews-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.review-card {
  padding: var(--space-5);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
  box-shadow: var(--shadow-soft-xs);
  background: var(--color-surface);
}
.review-card-top {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}
.review-card-identity {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: var(--space-2);
}
.review-card-name-row {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}
.review-card-name {
  font-weight: var(--fw-semibold);
  color: var(--color-text);
  font-size: var(--fs-md);
}
.review-card-date {
  font-size: var(--fs-xs);
  color: var(--color-text-faint);
  white-space: nowrap;
}
.review-verified-badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 10px;
  font-weight: var(--fw-semibold);
  color: var(--color-success);
  background: rgba(31, 139, 92, 0.1);
  border-radius: var(--radius-full);
  padding: 2px 7px;
  width: fit-content;
  flex-shrink: 0;
}
.review-verified-badge svg {
  width: 9px;
  height: 9px;
  flex-shrink: 0;
}
.review-card-body {
  font-size: var(--fs-sm);
  color: var(--color-text-muted);
  line-height: 1.6;
  margin: 0;
}
.review-card-reply {
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--color-surface-alt);
  border-left: 2px solid var(--color-accent);
}
.review-card-reply-label {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: var(--color-text);
  margin: 0 0 4px;
}
.review-card-reply-text {
  font-size: var(--fs-sm);
  color: var(--color-text-muted);
  margin: 0;
}

/* ---- Interactive star-rating input (review submission page) ----
   Reuses the .star-icon / .star-icon.filled color pattern already
   defined above for read-only star displays. ---- */
.review-rating-input {
  display: flex;
  justify-content: center;
  gap: var(--space-2);
}
.rating-star-btn {
  background: none;
  border: none;
  padding: 4px;
  cursor: pointer;
  line-height: 0;
}
.rating-star-btn .star-icon {
  width: 32px;
  height: 32px;
  transition: transform var(--duration-base) var(--ease-standard);
}
.rating-star-btn:hover .star-icon {
  transform: scale(1.1);
}

/* ---- Post-review "share SolidW" prompt ----
   Sits on the thank-you screen only, after the review has already been
   submitted, so it never competes with the review form itself. Kept
   deliberately quiet: small muted text, an outline (not filled) primary
   action, and a plain-text dismiss — no banner, no color pop, no urgency. */
.review-share-prompt {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
  text-align: center;
}
.review-share-text {
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
  line-height: 1.5;
  margin: 0 0 var(--space-3);
}
.review-share-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}
.review-share-dismiss {
  background: none;
  border: none;
  padding: 4px;
  font-size: var(--fs-xs);
  color: var(--color-text-faint);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.review-share-dismiss:hover {
  color: var(--color-text-muted);
}

/* ==========================================================================
   Manage-reservation page (/manage/:token) — cancel / reschedule by link.
   Reuses the .auth-page / .auth-card / .auth-header shell from auth.css,
   same as the reviews page; these rules only cover the parts unique to
   this page (reservation summary card, status badge, action buttons,
   inline confirm/reschedule panels).
   ========================================================================== */
.mg-card {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  margin-bottom: var(--space-5);
}
.mg-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 7px 0;
  font-size: var(--fs-sm);
}
.mg-row + .mg-row { border-top: 1px solid var(--color-border); }
.mg-row span:first-child { color: var(--color-text-muted); }
.mg-row span:last-child { color: var(--color-text); font-weight: var(--fw-medium); text-align: right; }

/* Rejection reason can run longer than the other row values (price, date,
   status), so it gets its own layout: label above, full-width wrapped text
   below, left-aligned — instead of squeezing long prose into the narrow
   right-hand column every other row uses. */
.mg-row--reason {
  flex-direction: column;
  align-items: stretch;
  gap: 3px;
}
.mg-row--reason span:last-child {
  text-align: left;
  font-weight: var(--fw-normal, 400);
  white-space: pre-wrap;
  word-break: break-word;
}

.mg-status-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: var(--radius-full);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  text-transform: capitalize;
  border: 1px solid transparent;
}
.mg-status-badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}
.mg-status-badge--pending {
  color: var(--color-warning);
  background: color-mix(in srgb, var(--color-warning) 12%, white);
  border-color: color-mix(in srgb, var(--color-warning) 20%, transparent);
}
.mg-status-badge--confirmed {
  color: var(--color-brand-primary);
  background: color-mix(in srgb, var(--color-brand-primary) 10%, white);
  border-color: color-mix(in srgb, var(--color-brand-primary) 18%, transparent);
}
.mg-status-badge--completed {
  color: var(--color-success);
  background: color-mix(in srgb, var(--color-success) 12%, white);
  border-color: color-mix(in srgb, var(--color-success) 20%, transparent);
}
.mg-status-badge--cancelled {
  color: var(--color-text-muted);
  background: var(--color-pastel-bg-soft);
  border-color: var(--color-border);
}
.mg-status-badge--rejected {
  color: var(--color-danger);
  background: color-mix(in srgb, var(--color-danger) 12%, white);
  border-color: color-mix(in srgb, var(--color-danger) 20%, transparent);
}

.mg-services {
  margin-top: var(--space-2);
  padding-top: var(--space-2);
}
.mg-service-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
  padding: 3px 0;
}

.mg-actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.mg-actions-row {
  display: flex;
  gap: var(--space-3);
}
.mg-actions-row .btn { flex: 1; }

.mg-panel {
  margin-top: var(--space-4);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  background: var(--color-pastel-bg-soft);
  border: 1px solid var(--color-border);
}
.mg-panel p {
  font-size: var(--fs-sm);
  color: var(--color-text);
  margin: 0 0 var(--space-3);
}
.mg-panel-actions {
  display: flex;
  gap: var(--space-3);
}
.mg-panel-actions .btn { flex: 1; }

.mg-note {
  font-size: var(--fs-xs);
  color: var(--color-text-faint);
  text-align: center;
  margin-top: var(--space-4);
}

/* Manage-link box shown under the success banner right after a booking is
   submitted (site/index.html) — this is the ONE time the link is ever
   shown; there's no login to recover it later, so it's presented plainly
   and made trivially copyable. */
.mg-link-box {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  margin-bottom: var(--space-4);
  background: var(--color-pastel-bg-soft);
}
.mg-link-box p {
  font-size: var(--fs-sm);
  color: var(--color-text);
  margin: 0 0 var(--space-3);
}
.mg-link-row {
  display: flex;
  gap: var(--space-2);
}
.mg-link-row input {
  flex: 1;
  min-width: 0;
  font-size: var(--fs-sm);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  color: var(--color-text-muted);
}
.mg-link-row .btn { flex-shrink: 0; }

/* The reschedule slot grid lives inside .auth-card (max-width 420px) —
   narrower than the public booking page's container (600px) that
   .slots-grid's 3-column layout was designed for. 2 columns keeps the
   buttons comfortably tappable here without needing a viewport-width
   media query. */
.mg-panel .slots-grid {
  grid-template-columns: repeat(2, 1fr);
}

/* Reschedule "New date" field only — a compact custom-styled trigger that
   replaces the raw native <input type="date">. Mobile browsers (iOS Safari
   especially) render that control with their own oversized chrome that
   ignores most CSS, which is what made it balloon to ~80px tall with a
   giant pill radius. The fix: show a small, on-brand "fake input" (icon +
   formatted date + chevron) and layer the real <input type="date"> on top
   of it at opacity:0, filling the exact same box. Tapping/clicking anywhere
   on the visible field taps the real input underneath, so the OS date
   sheet / calendar dropdown still opens exactly as before — only the
   at-rest appearance changes. formatDate/manage.js keeps the two in sync. */
.mg-date-field {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: 46px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-md);
  border: 1.5px solid var(--color-border);
  background: var(--color-white);
  box-shadow: var(--shadow-soft-xs);
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--ease-standard),
              box-shadow var(--duration-fast) var(--ease-standard);
}
.mg-date-field:hover {
  border-color: var(--border-brand, var(--color-accent));
}
.mg-date-field:focus-within {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 20%, transparent);
}
.mg-date-field-icon {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  color: var(--color-accent);
}
.mg-date-field-value {
  flex: 1;
  min-width: 0;
  font-size: 0.9rem;
  font-weight: var(--fw-medium);
  color: var(--color-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mg-date-field-chevron {
  width: 13px;
  height: 13px;
  flex-shrink: 0;
  color: var(--color-text-faint);
}
/* The real control — invisible but present and tappable, exactly covering
   the fake field above it. Left with its native appearance (not
   display:none) so it stays a genuine, accessible, keyboard-operable
   date input; only its paint is hidden. */
.mg-date-field-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  cursor: pointer;
}

/* ==========================================================================
   RTL support (Arabic, Persian)
   ==========================================================================
   Most of this page is already dir-aware for free — flexbox rows, tab
   strips, and form layouts all mirror automatically once <html dir="rtl">
   is set by site.js. Only the handful of rules below hardcode a physical
   left/right instead of a logical start/end, so only those need a mirrored
   counterpart here.
   ========================================================================== */
html[dir="rtl"] .public-business-info {
  text-align: right;
}
html[dir="rtl"] .public-hours-table td:last-child {
  text-align: left;
}
html[dir="rtl"] .lightbox-close {
  right: auto;
  left: var(--space-5);
}
html[dir="rtl"] .review-card-reply {
  border-left: none;
  border-right: 2px solid var(--color-accent);
}
