/* ======================================================================
   Clean SaaS — white background, Inter sans-serif, one blue accent.
   Simple, predictable, easy to scan.
   ====================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');

:root {
  --bg:            #ffffff;
  --surface:       #ffffff;
  --surface-2:     #f7f8fa;
  --surface-3:     #eef0f4;
  --text:          #0f172a;
  --text-2:        #334155;
  --muted:         #64748b;
  --border:        #e5e7eb;
  --border-strong: #cbd5e1;

  --primary:       #0062ff;
  --primary-700:   #0050d4;
  --primary-50:    #e6f0ff;

  --danger:        #dc2626;
  --danger-50:     #fef2f2;
  --success:       #16a34a;

  --radius-sm:     6px;
  --radius:        10px;
  --radius-lg:     14px;

  --shadow-sm:     0 1px 2px rgba(15, 23, 42, 0.06);
  --shadow:        0 1px 3px rgba(15, 23, 42, 0.08), 0 1px 2px rgba(15, 23, 42, 0.04);
  --shadow-lg:     0 8px 24px -10px rgba(15, 23, 42, 0.18), 0 2px 6px -2px rgba(15, 23, 42, 0.08);

  --font:          'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: "cv11";
}

.container { max-width: 1080px; margin: 0 auto; padding: 0 24px; }

/* ----- Typography ---------------------------------------------------- */

h1, h2, h3, h4 {
  color: var(--text);
  font-weight: 600;
  letter-spacing: -0.015em;
  margin: 0 0 12px;
  line-height: 1.25;
}
h1 { font-size: 32px; letter-spacing: -0.02em; }
h2 { font-size: 22px; }
h3 { font-size: 17px; }

p { margin: 0 0 12px; color: var(--text-2); }
.muted { color: var(--muted); }
small { color: var(--muted); font-size: 13px; }

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

code {
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', monospace;
  font-size: 0.88em;
  background: var(--surface-2);
  padding: 2px 6px;
  border-radius: 4px;
  color: var(--text-2);
}

/* ----- Topbar -------------------------------------------------------- */

.topbar {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 20;
}
.topbar .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* min-height (not height) so the bar grows cleanly instead of the nav
     spilling over the page content if it ever wraps to a second row. */
  min-height: 64px;
  padding-top: 8px;
  padding-bottom: 8px;
}
/* Topbar brand — matches the OtterFlow marketing nav: circular logo
   mark + two-tone wordmark. Colors mirror otterflow-home.css. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: #1F2937;
  text-decoration: none;
}
.brand__mark {
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: #FFFFFF;
  box-shadow: 0 0 0 1px #E8E2D2, 0 1px 2px rgba(31, 41, 55, 0.05);
  overflow: hidden;
  flex: 0 0 32px;
}
.brand__mark img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}
.brand__wordmark {
  font-family: "Sora", var(--font);
  font-weight: 700;
  font-size: 18px;
  letter-spacing: -0.025em;
  line-height: 1;
}
.brand__wordmark .otter { color: #8B6F47; }
.brand__wordmark .flow  { color: #4FA8C5; }
.nav {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px 12px;
  font-size: 14px;
  flex-wrap: wrap;
}
.nav a {
  color: var(--text-2);
  font-weight: 500;
  text-decoration: none;
  position: relative;
  padding: 6px 2px;
  white-space: nowrap;
}
.nav a:hover { color: var(--text); }
.nav a.is-active {
  color: var(--text);
  font-weight: 600;
}
.nav a.is-active::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -6px;
  height: 2px;
  border-radius: 2px;
  background: var(--primary);
}
.inline-form { display: inline; margin: 0; }
.link-btn {
  background: none;
  border: 0;
  padding: 0;
  color: var(--text-2);
  cursor: pointer;
  font: inherit;
  font-weight: 500;
  white-space: nowrap;
}
.link-btn:hover { color: var(--text); }

/* Hamburger button (mobile only) */
.nav-toggle {
  display: none;
  width: 40px;
  height: 40px;
  padding: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  position: relative;
  align-items: center;
  justify-content: center;
}
.nav-toggle:hover { background: var(--surface-2); }
.nav-toggle:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
.nav-toggle-bars,
.nav-toggle-bars::before,
.nav-toggle-bars::after {
  display: block;
  width: 18px;
  height: 2px;
  background: var(--text);
  border-radius: 1px;
  transition: transform 180ms ease, opacity 140ms ease;
}
.nav-toggle-bars { position: relative; }
.nav-toggle-bars::before {
  content: "";
  position: absolute;
  left: 0;
  top: -6px;
}
.nav-toggle-bars::after {
  content: "";
  position: absolute;
  left: 0;
  top: 6px;
}
/* X animation when menu is open */
.nav.is-open ~ .nav-toggle .nav-toggle-bars,
.nav-toggle[aria-expanded="true"] .nav-toggle-bars { background: transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars::before { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars::after { transform: translateY(-6px) rotate(-45deg); }

/* Collapse the logged-out top bar (Log in / Sign up) into the hamburger
   dropdown on small screens. Signed-in views use the sidebar drawer instead
   (see the app-shell section). Keep in sync with the matchMedia breakpoint
   in static/js/nav.js. */
@media (max-width: 900px) {
  .nav-toggle { display: inline-flex; }
  .topbar { position: relative; }
  .nav {
    position: absolute;
    top: 64px;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow-lg);
    padding: 8px 24px 16px;
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    pointer-events: none;
    transition: max-height 220ms ease, opacity 160ms ease, padding 220ms ease;
  }
  .nav.is-open {
    max-height: 80vh;
    opacity: 1;
    pointer-events: auto;
  }
  .nav a,
  .nav .link-btn {
    width: 100%;
    padding: 12px 8px;
    border-radius: var(--radius-sm);
    text-align: left;
    font-size: 15px;
  }
  .nav a:hover,
  .nav .link-btn:hover { background: var(--surface-2); }
  .nav a.is-active {
    background: var(--surface-2);
    box-shadow: inset 3px 0 0 var(--primary);
  }
  .nav a.is-active::after { display: none; }
  .nav .inline-form { width: 100%; display: block; }
  .nav .nav-search { width: 100%; margin: 4px 0; }
  .nav .nav-search input[type="search"] { width: 100%; }
  .nav .btn-primary {
    margin-top: 8px;
    width: 100%;
    padding: 12px 16px;
  }
}

/* ----- Buttons ------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 18px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  font-family: var(--font);
  font-weight: 500;
  font-size: 14px;
  cursor: pointer;
  text-decoration: none;
  transition: background 140ms ease, border-color 140ms ease, color 140ms ease, box-shadow 140ms ease;
}
.btn:hover { background: var(--surface-2); text-decoration: none; border-color: var(--border-strong); }
.btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

.btn-primary {
  background: var(--primary);
  color: #fff;
  border-color: var(--primary);
}
.btn-primary:hover {
  background: var(--primary-700);
  border-color: var(--primary-700);
  color: #fff;
}
.btn-ghost {
  background: transparent;
  border-color: var(--border);
  color: var(--text-2);
}
.btn-ghost:hover { background: var(--surface-2); color: var(--text); }
.btn-danger {
  color: var(--danger);
  border-color: var(--border-strong);
  background: var(--surface);
}
.btn-danger:hover { background: var(--danger-50); border-color: var(--danger); }

/* ----- Cards --------------------------------------------------------- */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 24px;
  box-shadow: var(--shadow-sm);
  margin: 16px 0;
}

/* ----- Hero ---------------------------------------------------------- */

.hero {
  padding: 80px 0 40px;
  text-align: center;
  max-width: 760px;
  margin: 0 auto;
}
.hero h1 {
  font-size: clamp(36px, 5vw, 52px);
  line-height: 1.1;
  letter-spacing: -0.025em;
  margin-bottom: 20px;
}
.hero .lead {
  color: var(--muted);
  font-size: 18px;
  max-width: 560px;
  margin: 0 auto 28px;
  line-height: 1.55;
}
.hero-cta { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

/* ----- Flashes ------------------------------------------------------- */

.flashes {
  list-style: none;
  padding: 0;
  margin: 16px 0 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.flash {
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface-2);
  font-size: 14px;
  color: var(--text-2);
}
.flash-success { background: #ecfdf5; border-color: #a7f3d0; color: #065f46; }
.flash-error { background: var(--danger-50); border-color: #fecaca; color: var(--danger); }

/* ----- Footer -------------------------------------------------------- */

.footer {
  margin-top: 80px;
  padding: 28px 0;
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: 13px;
}
/* The privacy link sits here rather than in the nav because this footer is the
   only chrome a public booking page renders (hide_topbar hides everything
   else), and the notice has to be reachable from the page carrying the form. */
.footer a { color: inherit; text-decoration: underline; }
.footer a:hover { color: var(--text, inherit); }
.footer__sep { margin: 0 8px; opacity: 0.6; }

/* ----- Forms --------------------------------------------------------- */

form.stack { display: flex; flex-direction: column; gap: 32px; }
label {
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
}
label > span {
  font-weight: 600;
  color: var(--text);
  font-size: 13px;
  letter-spacing: 0.01em;
}
/* Help text under inputs gets its own visual band so it doesn't run
   into the next field's bold label. The margin-bottom is on the
   <small> itself which extends the label container, adding distance
   above the next sibling label. */
label > small {
  margin-top: 2px;
  margin-bottom: 6px;
  line-height: 1.45;
  display: block;
}

input[type="text"], input[type="email"], input[type="password"],
input[type="number"], input[type="date"], input[type="time"],
input[type="tel"],
select, textarea {
  width: 100%;
  padding: 10px 12px;
  font-size: 14px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-family: var(--font);
  color: var(--text);
  transition: border-color 140ms ease, box-shadow 140ms ease;
}
input::placeholder, textarea::placeholder { color: #94a3b8; }
input:focus, select:focus, textarea:focus {
  outline: 0;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(0, 98, 255, 0.12);
}

input[type="checkbox"] {
  appearance: none;
  width: 18px;
  height: 18px;
  border: 1.5px solid var(--border-strong);
  border-radius: 4px;
  background: var(--surface);
  cursor: pointer;
  position: relative;
  padding: 0;
  vertical-align: -4px;
}
input[type="checkbox"]:checked {
  background: var(--primary);
  border-color: var(--primary);
}
input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 5px;
  top: 2px;
  width: 5px;
  height: 9px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.form-error {
  color: var(--danger);
  font-size: 13px;
  font-weight: 500;
}

/* ----- Image upload field (offer form) ------------------------------ */

.image-field {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.image-field__label {
  font-weight: 600;
  color: var(--text);
  font-size: 13px;
  letter-spacing: 0.01em;
}

/* Current image preview shown in edit mode */
.image-field__current {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
}
.image-field__current img {
  width: 88px;
  height: 88px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  display: block;
  flex: 0 0 auto;
}
.image-field__current-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}
.image-field__current-tag {
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.image-field__remove {
  flex-direction: row;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-2);
  cursor: pointer;
}

/* Click-or-drop upload zone — the native file input is hidden and
   triggered by this label. */
.image-field__dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 26px 20px;
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--muted);
  text-align: center;
  cursor: pointer;
  transition: border-color 140ms ease, background 140ms ease, color 140ms ease;
}
.image-field__dropzone:hover,
.image-field__dropzone.is-dragover {
  border-color: var(--primary);
  background: var(--primary-50);
  color: var(--text-2);
}
.image-field__dropzone .image-field__icon {
  width: 26px;
  height: 26px;
  color: var(--primary);
}
.image-field__dropzone-title {
  font-weight: 600;
  font-size: 14px;
  color: var(--text);
  word-break: break-word;
}
.image-field__dropzone-title em {
  color: var(--primary);
  font-style: normal;
}
.image-field__dropzone-hint {
  font-size: 12px;
}
.image-field__dropzone input[type="file"] {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
}
.image-field__preview {
  max-width: 100%;
  max-height: 180px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  margin-top: 6px;
  display: block;
}
.image-field__preview[hidden] { display: none; }

/* ----- Data tables --------------------------------------------------- */

table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
table.data th, table.data td {
  padding: 12px 14px;
  text-align: left;
  border-bottom: 1px solid var(--border);
}
table.data th {
  color: var(--muted);
  font-weight: 500;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: var(--surface-2);
}
table.data tbody tr:hover { background: var(--surface-2); }

fieldset {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
  background: var(--surface-2);
}
fieldset legend {
  padding: 0 6px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
}

/* ----- Breadcrumb --------------------------------------------------- */

.crumbs {
  padding: 20px 0 4px;
  font-size: 13px;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.crumbs a {
  color: var(--muted);
  text-decoration: none;
}
.crumbs a:hover { color: var(--text); text-decoration: underline; }
.crumbs .sep { color: var(--border-strong); }
.crumbs .current { color: var(--text); font-weight: 500; }

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

.page-header {
  padding: 32px 0 20px;
}
.page-header h1 { margin-bottom: 4px; }
.page-header p { color: var(--muted); margin: 0; }

/* ----- Booking page layout ------------------------------------------ */

.booking-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow);
  margin: 24px 0;
}
@media (min-width: 900px) {
  .booking-layout { grid-template-columns: 340px 1fr; }
}

.booking-info {
  padding: 28px;
  border-bottom: 1px solid var(--border);
}
@media (min-width: 900px) {
  .booking-info { border-bottom: 0; border-right: 1px solid var(--border); }
}
.booking-info .host {
  color: var(--muted);
  font-size: 13px;
  font-weight: 500;
  margin-bottom: 8px;
}
.booking-info h1 {
  font-size: 24px;
  margin-bottom: 16px;
}
.booking-info .duration {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 14px;
}
.booking-info .duration::before {
  content: "⏱";
  font-size: 16px;
}
.booking-info .description {
  color: var(--text-2);
  font-size: 14px;
  line-height: 1.55;
}
.offer-address {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.offer-address-label {
  color: var(--muted);
  font-size: 12px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 4px;
}
.offer-address-body {
  color: var(--text-2);
  font-size: 14px;
  line-height: 1.5;
  white-space: pre-line;
}
.offer-media {
  position: relative;
  margin-bottom: 18px;
}
.booking-info .offer-hero {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  display: block;
  background: var(--surface-2);
}
.offer-media .offer-hero { margin-bottom: 0; }

/* Tenant logo layered over the bottom-left corner of the offer image,
   like an avatar over a cover photo. Lifts on hover to signal it's a
   distinct, separate image. */
.offer-media-logo {
  position: absolute;
  left: 12px;
  bottom: 12px;
  height: 56px;
  width: 56px;
  object-fit: contain;
  background: #fff;
  border-radius: 12px;
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  padding: 5px;
  transition: transform 180ms ease, box-shadow 180ms ease;
}
.offer-media:hover .offer-media-logo {
  transform: translateY(-5px);
  box-shadow: var(--shadow-lg);
}
@media (prefers-reduced-motion: reduce) {
  .offer-media-logo { transition: none; }
  .offer-media:hover .offer-media-logo { transform: none; }
}

/* Logo shown on its own when the offer has no image. */
.tenant-logo-standalone {
  height: 48px;
  width: 48px;
  object-fit: contain;
  background: #fff;
  border-radius: 8px;
  border: 1px solid var(--border);
  display: block;
  margin-bottom: 8px;
}

.booking-picker { padding: 28px; }
.booking-picker h2 { font-size: 17px; margin-bottom: 16px; }

.picker-controls {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 20px;
}
@media (max-width: 600px) { .picker-controls { grid-template-columns: 1fr; } }

/* ----- Dashboard booking calendar ---------------------------------- */

.dcal-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
}
@media (min-width: 820px) {
  .dcal-layout { grid-template-columns: minmax(320px, 420px) 1fr; }
}
.dcal-side {
  border-top: 1px solid var(--border);
  padding-top: 16px;
}
@media (min-width: 820px) {
  .dcal-side {
    border-top: 0;
    border-left: 1px solid var(--border);
    padding-top: 0;
    padding-left: 24px;
    min-height: 280px;
  }
}

/* Pending dot on dashboard calendar */
.cal-day.is-available.has-pending::after {
  background: #f59e0b;          /* amber */
  box-shadow: 0 0 0 3px #fef3c7;
}

/* Day-fragment layout */
.dcal-day-title {
  font-size: 16px;
  font-weight: 600;
  margin: 0 0 12px;
}
.dcal-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.dcal-item {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  transition: border-color 140ms ease, box-shadow 140ms ease;
}
.dcal-item:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-sm);
}
.dcal-item-link {
  display: grid;
  grid-template-columns: 150px 1fr;
  gap: 16px;
  padding: 12px 14px;
  align-items: center;
  text-decoration: none;
  color: inherit;
}
.dcal-item-time {
  font-family: 'SFMono-Regular', Consolas, monospace;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-2);
}
/* Keep a clock reading whole: the range may break at the separator,
   never in the middle of "12:15 PM". */
.dcal-time-start,
.dcal-time-end { white-space: nowrap; }
.dcal-item-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.dcal-item-title {
  font-weight: 600;
  color: var(--text);
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  min-width: 0;
  overflow-wrap: anywhere;
}
.dcal-item-sub {
  font-size: 13px;
  color: var(--muted);
  min-width: 0;
  overflow-wrap: anywhere;
}

/* Narrow screens: stack the range so the start time sits above the end
   time, which keeps the time column short and leaves room for the title. */
@media (max-width: 640px) {
  .dcal-item-link {
    grid-template-columns: 68px 1fr;
    gap: 12px;
    align-items: start;
    padding: 12px;
  }
  .dcal-item-time {
    display: flex;
    flex-direction: column;
    line-height: 1.35;
    white-space: nowrap;
  }
  .dcal-time-sep { display: none; }
}

/* ----- Inline calendar --------------------------------------------- */

.cal {
  user-select: none;
}
.cal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}
.cal-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}
.cal-nav {
  display: flex;
  gap: 6px;
}
.cal-nav-btn {
  width: 32px;
  height: 32px;
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: var(--radius-sm);
  color: var(--text-2);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 140ms ease, border-color 140ms ease, color 140ms ease;
}
.cal-nav-btn:hover:not(:disabled) {
  background: var(--surface-2);
  border-color: var(--border-strong);
  color: var(--text);
}
.cal-nav-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.cal-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  margin-bottom: 6px;
}
.cal-weekdays div {
  text-align: center;
  font-size: 11px;
  font-weight: 500;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 4px 0;
}
.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}
.cal-day {
  aspect-ratio: 1 / 1;
  border: 0;
  background: transparent;
  border-radius: 999px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
  cursor: pointer;
  position: relative;
  transition: background 140ms ease, color 140ms ease;
  padding: 0;
}
.cal-day.is-blank {
  visibility: hidden;
  pointer-events: none;
}
.cal-day.is-disabled {
  color: #cbd5e1;
  cursor: not-allowed;
  text-decoration: line-through;
  text-decoration-color: #e2e8f0;
  text-decoration-thickness: 1px;
}
.cal-day.is-available {
  color: var(--primary);
  font-weight: 600;
}
.cal-day.is-available::after {
  content: "";
  position: absolute;
  bottom: 18%;
  left: 50%;
  width: 4px;
  height: 4px;
  margin-left: -2px;
  border-radius: 50%;
  background: var(--primary);
}
.cal-day.is-available:hover {
  background: var(--primary-50);
}
.cal-day.is-selected,
.cal-day.is-selected.is-available {
  background: var(--primary);
  color: #fff;
}
.cal-day.is-selected::after { background: #fff; }
.cal-day.is-today:not(.is-selected) {
  outline: 1px solid var(--border-strong);
  outline-offset: -1px;
}

.cal-legend {
  display: flex;
  gap: 14px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  font-size: 12px;
  color: var(--muted);
  flex-wrap: wrap;
}
.cal-legend .item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.cal-legend .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
}
.cal-legend .dot-available { background: var(--primary); }
.cal-legend .dot-unavailable { background: #e2e8f0; }

.cal-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 240px;
  color: var(--muted);
  font-size: 14px;
}

/* ----- Calendar + slots split ------------------------------------- */

.booking-split {
  display: grid;
  grid-template-columns: 1fr;
  gap: 20px;
}
@media (min-width: 780px) {
  .booking-split { grid-template-columns: minmax(280px, 360px) 1fr; }
}

.slots-panel {
  border-left: 0;
  padding-left: 0;
}
@media (min-width: 780px) {
  .slots-panel {
    border-left: 1px solid var(--border);
    padding-left: 20px;
  }
}
.slots-panel-head { margin-bottom: 14px; }
.slots-panel-head h3 { margin: 0; font-size: 15px; }

/* ----- Slot grid ---------------------------------------------------- */

.slots-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
  gap: 8px;
}
.slot-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 12px 8px;
  background: var(--surface);
  border: 1px solid var(--primary);
  border-radius: var(--radius-sm);
  color: var(--primary);
  cursor: pointer;
  font-family: var(--font);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  transition: background 140ms ease, color 140ms ease, transform 140ms ease;
}
.slot-btn:hover {
  background: var(--primary);
  color: #fff;
}
.slot-btn.is-selected {
  background: var(--primary);
  color: #fff;
}

.slots-footer {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: 13px;
}
.slots-empty {
  padding: 40px 20px;
  text-align: center;
  color: var(--muted);
}
.slots-empty strong { color: var(--text); display: block; font-size: 16px; margin-bottom: 4px; }

/* ----- Dashboard stat cards ---------------------------------------- */

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 14px;
  margin: 24px 0;
}
.stat {
  padding: 20px 22px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.stat .label {
  color: var(--muted);
  font-size: 13px;
  font-weight: 500;
  margin-bottom: 6px;
}
.stat .value {
  font-size: 30px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text);
  line-height: 1.1;
}
.stat-sub {
  color: var(--muted);
  font-size: 13px;
  font-weight: 500;
  margin-top: 6px;
}
a.stat-link {
  text-decoration: none;
  color: inherit;
  display: block;
  transition: border-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
}
a.stat-link:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow);
  transform: translateY(-1px);
  text-decoration: none;
}
.stat-highlight {
  background: #fffbeb;
  border-color: #fde68a;
}
.stat-highlight .label { color: #92400e; }
.stat-highlight .value { color: #78350f; }
.stat-highlight .stat-sub { color: #92400e; font-weight: 600; }
a.stat-link.stat-highlight:hover { border-color: #fbbf24; }

.danger-zone {
  border-color: #fecaca;
  background: #fffaf9;
  margin-top: 24px;
}
.danger-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 0;
  border-top: 1px solid #fecaca;
}
.danger-row:first-of-type { border-top: 0; padding-top: 0; }
.danger-row:last-of-type { padding-bottom: 0; }
.danger-row-text strong {
  display: block;
  color: var(--text);
  font-weight: 600;
  margin-bottom: 4px;
}
.danger-row-text p {
  margin: 0;
  font-size: 13px;
  color: var(--text-2);
  max-width: 520px;
}
@media (max-width: 600px) {
  .danger-row { flex-direction: column; align-items: flex-start; }
}

/* ----- Analytics ---------------------------------------------------- */

.analytics-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 14px;
  margin: 24px 0;
}
.analytics-card .label {
  color: var(--muted);
  font-size: 12px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 10px;
}
.analytics-card .value {
  font-size: 32px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text);
  line-height: 1;
  margin-bottom: 6px;
}
.analytics-card .value.analytics-small {
  font-size: 22px;
}
.analytics-card .sub {
  color: var(--muted);
  font-size: 13px;
  font-weight: 500;
}

.chart-wrap { width: 100%; }
.chart {
  width: 100%;
  height: 220px;
  display: block;
}
.chart-bar {
  fill: var(--primary);
  opacity: 0.85;
  transition: opacity 140ms ease, fill 140ms ease;
}
.chart-bar:hover {
  opacity: 1;
}
.chart-bar.is-peak {
  fill: var(--primary-700);
  opacity: 1;
}
.chart-axis {
  display: flex;
  justify-content: space-between;
  margin-top: 8px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 500;
}

/* ----- Offer list (public tenant page) ----------------------------- */

.offer-cards {
  display: grid;
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.offer-cards li { margin: 0; }
.offer-cards a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 20px 22px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  text-decoration: none;
  transition: border-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
}
.offer-cards a:hover {
  border-color: var(--primary);
  box-shadow: var(--shadow-lg);
  transform: translateY(-1px);
  text-decoration: none;
}
.offer-cards .offer-thumb {
  width: 72px;
  height: 72px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  display: block;
  flex: 0 0 auto;
}
.offer-cards .offer-card-body { flex: 1 1 auto; min-width: 0; }
.offer-cards .title { font-weight: 600; font-size: 16px; }
.offer-cards .meta { color: var(--muted); font-size: 13px; margin-top: 4px; }
.offer-cards .arrow { color: var(--primary); font-weight: 600; font-size: 14px; white-space: nowrap; }

/* ----- Tenant header (public) -------------------------------------- */

.tenant-header {
  padding: 40px 0 20px;
  text-align: center;
}
.tenant-header .avatar {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: var(--primary);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 28px;
  font-weight: 600;
  margin-bottom: 16px;
}
.tenant-header h1 {
  font-size: 28px;
  margin-bottom: 4px;
}
.tenant-header .handle {
  color: var(--muted);
  font-size: 14px;
}

/* ----- Auth ---------------------------------------------------------- */

.auth-shell {
  max-width: 420px;
  margin: 64px auto;
}
.auth-shell .card { padding: 32px; }
.auth-shell h1 { font-size: 24px; margin-bottom: 4px; }
.auth-shell .sub { color: var(--muted); margin-bottom: 24px; }
.auth-shell .alt {
  text-align: center;
  margin-top: 20px;
  color: var(--muted);
  font-size: 14px;
}

/* ----- Utility ------------------------------------------------------ */

.row-between {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 12px;
  font-weight: 500;
}
.pill-success { background: #ecfdf5; color: #065f46; }
.pill-muted { background: var(--surface-2); color: var(--muted); }
.pill-pending { background: #fef3c7; color: #92400e; }
.pill-error { background: #fee2e2; color: #991b1b; }

/* Compact button variant for inline row actions */
.btn-sm {
  padding: 6px 12px;
  font-size: 13px;
}

/* Highlight pending-approval rows in the bookings table */
.row-pending {
  background: #fffbeb;
}
.row-pending:hover { background: #fef3c7; }
.row-pending td { border-bottom-color: #fde68a; }

/* Inline search box in the tenant top nav. */
.nav-search {
  display: inline-flex;
}
.nav-search input[type="search"] {
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface, #fff);
  font-size: 13px;
  width: 110px;
  transition: border-color 140ms ease, width 140ms ease;
}
.nav-search input[type="search"]:focus {
  outline: none;
  border-color: #3b82f6;
}
/* Only grow the search box on focus when the row has slack — on
   narrower desktops the extra width would wrap the nav. */
@media (min-width: 1200px) {
  .nav-search input[type="search"]:focus { width: 170px; }
}

/* Offer form toggles — big touch targets, clear description */
.offer-toggles {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.offer-toggle {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  cursor: pointer;
  transition: border-color 140ms ease, background 140ms ease;
}
.offer-toggle:hover {
  border-color: var(--border-strong);
  background: var(--surface-2);
}
/* A toggle the tenant cannot currently change, because a platform switch has
   taken it out of their hands. Their setting is still shown, and still stored,
   so the control keeps its state -- but it must not look pressable, and the
   hover response has to go with it. Without this the control reads as fully
   live and the click that does nothing reads as a broken page. */
.offer-toggle.is-disabled,
.offer-toggle.is-disabled:hover {
  opacity: 0.6;
  cursor: not-allowed;
  background: var(--surface-2);
  border-color: var(--border);
}
.offer-toggle.is-disabled input[type="checkbox"] {
  cursor: not-allowed;
}
.offer-toggle input[type="checkbox"] {
  margin: 3px 0 0;
  flex: 0 0 auto;
}
.offer-toggle-body {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.offer-toggle-title {
  font-weight: 600;
  font-size: 14px;
  color: var(--text);
}
.offer-toggle-sub {
  font-size: 13px;
  color: var(--muted);
}

/* Weekly availability editor */
.wk-grid {
  border-top: 1px solid var(--border);
}
.wk-day {
  display: grid;
  grid-template-columns: 110px 1fr;
  gap: 20px;
  align-items: start;
  padding: 16px 0;
  border-bottom: 1px solid var(--border);
}
.wk-day-name {
  font-weight: 600;
  color: var(--text);
  padding-top: 10px;
}
.wk-day-body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}
.wk-rows {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
}
.wk-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.wk-time {
  min-width: 128px;
  padding: 8px 10px;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}
select.wk-time {
  /* Native select needs room for the chevron + longest label. */
  padding-right: 28px;
}
.wk-sep {
  color: var(--muted);
  font-size: 13px;
  font-weight: 500;
}
.wk-remove {
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--muted);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
  font-family: inherit;
  transition: background 140ms ease, color 140ms ease, border-color 140ms ease;
}
.wk-remove:hover {
  color: var(--danger);
  border-color: var(--danger);
  background: var(--danger-50);
}
.wk-empty {
  font-size: 13px;
  color: var(--muted);
  font-style: italic;
  padding: 6px 0;
}
.wk-add {
  background: transparent;
  border: 0;
  color: var(--primary);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  padding: 4px 0;
}
.wk-add:hover { text-decoration: underline; }

@media (max-width: 640px) {
  .wk-day { grid-template-columns: 1fr; gap: 8px; }
  .wk-day-name { padding-top: 0; }
}

/* Date override form */
.override-form { display: flex; flex-direction: column; gap: 16px; }

.override-row {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: flex-end;
}
.override-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 160px;
  flex: 0 0 auto;
  margin: 0;
}
.override-field > span {
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  line-height: 1.2;
}
.override-field input[type="date"],
.override-field select {
  height: 38px;
  padding: 7px 10px;
  font-size: 14px;
  min-width: 160px;
}
.override-check {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 8px;
  height: 38px;               /* baseline with inputs */
  padding: 0 4px;
  margin: 0;
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
}
.override-check input[type="checkbox"] { margin: 0; vertical-align: middle; }
.override-check > span { color: var(--text); font-weight: 500; }

.override-help {
  font-size: 13px;
  line-height: 1.55;
  margin: 0;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text-2);
}
.override-help strong { color: var(--text); font-weight: 600; }

@media (max-width: 640px) {
  .override-row { gap: 10px; }
  .override-field { min-width: 140px; flex: 1 1 calc(50% - 10px); }
  .override-check { height: auto; padding: 8px 0; width: 100%; }
}

/* Clickable URL chip on the offers list — keeps the <code> look but
   communicates "this opens in a new tab" via cursor + a small arrow. */
.offer-url-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  text-decoration: none;
  background: none;
  vertical-align: middle;
}
.offer-url-link code {
  transition: background 140ms ease, color 140ms ease, border-color 140ms ease;
}
.offer-url-link:hover code {
  background: var(--primary-50);
  color: var(--primary);
  border-color: #c7dafc;
}
.offer-url-arrow {
  font-size: 12px;
  color: var(--muted);
  transition: color 140ms ease, transform 140ms ease;
}
.offer-url-link:hover .offer-url-arrow {
  color: var(--primary);
  transform: translate(1px, -1px);
}

/* Copy-link button — inline compact variant that matches the primary
   button system (.btn / .btn-ghost). Sits next to <code> blocks and
   inherits the same border-strong, radius-sm, surface-2 hover language. */
.btn-copy {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  margin-left: 10px;
  font-family: var(--font);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.3;
  background: var(--surface);
  color: var(--text-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-decoration: none;
  transition: background 140ms ease, color 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
  vertical-align: 1px;
}
.btn-copy:hover {
  background: var(--surface-2);
  color: var(--text);
  border-color: var(--border-strong);
  text-decoration: none;
}
.btn-copy:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
.btn-copy:active { background: var(--surface-3); }
.btn-copy .btn-copy-icon {
  width: 13px;
  height: 13px;
  flex: 0 0 13px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.btn-copy.is-copied {
  background: #ecfdf5;
  color: var(--success);
  border-color: #a7f3d0;
}
.btn-copy.is-copy-failed {
  background: var(--danger-50);
  color: var(--danger);
  border-color: #fecaca;
}

/* Location / embedded map */
.location-block { margin-top: 20px; text-align: left; }
.location-block .location-label {
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 6px;
}
.location-block .location-text {
  font-size: 14px;
  color: var(--text);
  line-height: 1.45;
  margin-bottom: 10px;
}
.location-map {
  width: 100%;
  height: 280px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  display: block;
}
/* Compact variant — fits inside the narrow offer-info aside */
.location-block-compact { margin-top: 18px; }
.location-map-compact { height: 180px; }
.location-open-link {
  display: inline-block;
  margin-top: 10px;
  font-size: 13px;
  font-weight: 500;
  color: var(--primary);
}

/* Confirmation card */
.confirm-check {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: #ecfdf5;
  color: var(--success);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 28px;
  margin-bottom: 16px;
}

.meta-list {
  display: grid;
  grid-template-columns: 120px 1fr;
  gap: 10px 16px;
  font-size: 14px;
  margin: 0;
  padding: 0;
}
.meta-list dt { color: var(--muted); font-weight: 500; }
.meta-list dd { margin: 0; color: var(--text); }

/* ----- Responsive ---------------------------------------------------- */

@media (max-width: 640px) {
  .container { padding: 0 16px; }
  h1 { font-size: 26px; }
  .hero { padding: 56px 0 32px; }
  .booking-info, .booking-picker { padding: 22px; }
  .card { padding: 18px; }
  .page-header { padding: 24px 0 14px; }

  /* Reusable 2-column form grid that stacks on mobile. The offer form
     uses grid-template-columns: 1fr 1fr inline; this catches it via
     attribute selector so we don't have to update every template. */
  [style*="grid-template-columns: 1fr 1fr"] {
    grid-template-columns: 1fr !important;
  }

  /* iOS zooms on focus when input font-size < 16. Bump on mobile only. */
  input[type="text"], input[type="email"], input[type="password"],
  input[type="number"], input[type="date"], input[type="time"],
  select, textarea {
    font-size: 16px;
  }
  /* Compact form selects (availability time pickers) keep their look
     but pick up the 16px size from the rule above. */
  .wk-time { min-width: 0; width: 100%; }

  /* ---- Data tables stack as cards on phones ----
     Squeezing 4-5 columns into a 360px viewport produces unreadable
     text wrapping. Convert each row to a stacked block instead so
     every value gets its own line. Column headers are hidden because
     status pills, times, offer titles, and client info are already
     self-evident on their own. Action buttons (right-aligned on
     desktop) become a left-aligned row at the bottom of each card. */
  table.data { display: block; min-width: 0; border: 0; }
  table.data thead { display: none; }
  table.data tbody { display: block; }
  table.data tr {
    display: block;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    padding: 14px;
    margin: 0 0 10px;
  }
  table.data tr:last-child { margin-bottom: 0; }
  table.data tr:hover { background: var(--surface); }
  table.data td {
    display: block;
    padding: 0;
    border: 0;
    text-align: left;
    line-height: 1.45;
  }
  table.data td + td { margin-top: 4px; }
  /* Right-aligned action cells become a left-aligned button row. */
  table.data td[style*="text-align: right"],
  table.data td[style*="text-align:right"] {
    text-align: left !important;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--border);
  }
  table.data td[style*="text-align: right"] > div,
  table.data td[style*="text-align:right"] > div {
    justify-content: flex-start !important;
  }
  /* Pending row highlight still applies. */
  table.data tr.row-pending {
    background: #fffbeb;
    border-color: #fde68a;
  }
}

/* ======================================================================
   Signed-in app shell — fixed left sidebar (tenant & admin).
   Pairs with _sidebar.html and the .app-topbar / .sidebar-overlay markup in
   base.html. Logged-out and hide_topbar pages do NOT use these styles.
   ====================================================================== */
:root { --sidebar-w: 240px; }

/* Push page content right of the fixed sidebar on desktop. The existing
   .container (max-width + margin:0 auto) re-centers within the inset body. */
body.has-sidebar { padding-left: var(--sidebar-w); }
body.has-sidebar main.container { padding-top: 24px; }

.sidebar {
  position: fixed;
  top: 0; left: 0; bottom: 0;
  width: var(--sidebar-w);
  display: flex;
  flex-direction: column;
  padding: 16px 12px;
  background: var(--surface);
  border-right: 1px solid var(--border);
  overflow-y: auto;
  z-index: 30;
}
.sidebar__brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 6px 14px;
  text-decoration: none;
}
.sidebar__search {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  margin-bottom: 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.sidebar__search-icon { display: inline-flex; color: var(--muted); }
.sidebar__search-icon svg { width: 16px; height: 16px; }
.sidebar__search input[type="search"] {
  width: 100%;
  border: 0;
  padding: 0;
  outline: none;
  background: transparent;
  font: inherit;
  font-size: 14px;
  color: var(--text);
}
.sidebar__nav { flex: 1; display: flex; flex-direction: column; gap: 1px; }
.sidebar__group-label {
  margin: 14px 0 4px;
  padding: 0 10px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
}
.sidebar__link {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  color: var(--text-2);
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
}
.sidebar__link svg { width: 18px; height: 18px; color: var(--muted); flex: 0 0 18px; }
.sidebar__link:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
.sidebar__link.is-active { background: var(--primary-50); color: var(--primary); font-weight: 600; }
.sidebar__link.is-active svg { color: var(--primary); }

.sidebar__footer {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.sidebar__avatar {
  flex: 0 0 30px;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--primary-50);
  color: var(--primary);
  font-size: 12px;
  font-weight: 700;
}
.sidebar__user { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
.sidebar__user-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sidebar__user-role { font-size: 11px; color: var(--muted); }
.sidebar__logout-form { margin: 0 0 0 auto; display: inline-flex; }
.sidebar__logout {
  display: inline-flex;
  padding: 6px;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--muted);
  cursor: pointer;
}
.sidebar__logout:hover { background: var(--surface-2); color: var(--text); }
.sidebar__logout svg { width: 18px; height: 18px; }

/* Mobile top bar + overlay are hidden on desktop; shown only in the drawer
   media query below. */
.app-topbar { display: none; }
.sidebar-overlay { display: none; }

/* Drawer mode: below 900px the sidebar slides in over the content. Keep this
   breakpoint in sync with the matchMedia value in static/js/nav.js. */
@media (max-width: 900px) {
  body.has-sidebar { padding-left: 0; }
  body.has-sidebar main.container { padding-top: 16px; }

  .app-topbar {
    display: flex;
    align-items: center;
    gap: 12px;
    position: sticky;
    top: 0;
    z-index: 20;
    min-height: 56px;
    padding: 8px 16px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
  }
  .app-topbar .nav-toggle { display: inline-flex; }

  .sidebar {
    transform: translateX(-100%);
    transition: transform 220ms ease;
    box-shadow: var(--shadow-lg);
  }
  .sidebar.is-open { transform: translateX(0); }

  .sidebar-overlay {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 25;
    background: rgba(15, 23, 42, 0.4);
    opacity: 0;
    pointer-events: none;
    transition: opacity 160ms ease;
  }
  .sidebar-overlay.is-visible { opacity: 1; pointer-events: auto; }
}

/* ==========================================================================
   SMS reminders (tenant) — reminders / drafts / people
   ========================================================================== */

/* Tab strip shared by the three sections. */
.rem-tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 16px;
  overflow-x: auto;
}
.rem-tab {
  padding: 9px 14px;
  border-bottom: 2px solid transparent;
  color: var(--muted);
  text-decoration: none;
  font-weight: 500;
  font-size: 14px;
  white-space: nowrap;
}
.rem-tab:hover { color: var(--text); }
.rem-tab.is-active { color: var(--primary); border-bottom-color: var(--primary); }

/* Platform-wide SMS is off: reminders save, nothing sends. */
.rem-warning {
  margin: 0 0 16px;
  padding: 10px 14px;
  border: 1px solid #fcd34d;
  background: #fffbeb;
  color: #78350f;
  border-radius: var(--radius);
  font-size: 13px;
}

.rem-toolbar { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 4px; }

.rem-empty { margin-top: 16px; text-align: center; padding: 32px 20px; }
.rem-empty h2 { margin: 0 0 8px; font-size: 17px; }
.rem-empty p { max-width: 46ch; margin: 0 auto 16px; }
.rem-empty .btn { margin: 0 4px; }

.rem-list { list-style: none; margin: 0; padding: 0; }
.rem-item {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  justify-content: space-between;
  padding: 12px 0;
  border-top: 1px solid var(--border);
}
.rem-item:first-child { border-top: 0; }
.rem-item__main { min-width: 0; }
.rem-title { font-weight: 600; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.rem-meta { font-size: 13px; margin-top: 2px; word-break: break-word; }
.rem-error { font-size: 13px; color: var(--danger); margin-top: 4px; }
.rem-item__actions { display: flex; gap: 6px; align-items: center; flex-shrink: 0; flex-wrap: wrap; }

/* Draft cards on the reminder form — the two-click path. */
.draft-picker { display: flex; gap: 10px; flex-wrap: wrap; }
.draft-card {
  flex: 0 1 auto;
  min-width: 160px;
  text-align: left;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  cursor: pointer;
  font: inherit;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.draft-card:hover { border-color: var(--border-strong); }
.draft-card.is-active { border-color: var(--primary); background: var(--primary-50); }
.draft-card__name { font-weight: 600; font-size: 14px; }
.draft-card__rhythm { font-size: 12px; }
.draft-card--blank { border-style: dashed; }

.starter-list { list-style: none; margin: 0; padding: 0; }
.starter-item {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  justify-content: space-between;
  padding: 12px 0;
  border-top: 1px solid var(--border);
}
.starter-item:first-child { border-top: 0; }
.starter-item__main { min-width: 0; }
.starter-name { font-weight: 600; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.starter-preview { font-size: 13px; margin-top: 3px; }

/* Person picker: one field, results underneath, add-in-place at the bottom. */
.person-picker { position: relative; }
.person-results {
  list-style: none;
  margin: 4px 0 0;
  padding: 4px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  max-height: 260px;
  overflow-y: auto;
}
.person-result {
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 14px;
}
.person-result:hover, .person-result:focus { background: var(--surface-2); outline: none; }
.person-result--add { color: var(--primary); font-weight: 500; }
.person-manual { margin-top: 12px; }

.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.repeat-row { display: flex; gap: 8px; align-items: center; }
.repeat-row input { max-width: 90px; }
/* The global `label` rule is flex-column, so a checkbox row has to say
   row explicitly or the box stacks above its text. */
/* The label is the hit area — clicking the text toggles the box — so the 44px
   touch-target floor is met here rather than on the 18px control.
   flex-direction is explicit because the base `label` rule is a column, which
   otherwise stacks the box above its own text. */
.checkbox-row {
  display: flex;
  flex-direction: row;
  gap: 8px;
  align-items: center;
  min-height: 44px;
}
.checkbox-row input[type="checkbox"] { flex: 0 0 auto; margin: 0; }
.checkbox-row span { font-weight: 500; }

@media (max-width: 640px) {
  .two-col { grid-template-columns: 1fr; }
  .rem-item, .starter-item { flex-direction: column; align-items: stretch; }
  .rem-item__actions { justify-content: flex-start; }
  .draft-card { flex: 1 1 100%; }
}

/* ----- Booking messages (per-tenant SMS wording) -------------------------- */

/* A form, not a dashboard, so it stops rather than stretching: wording set on a
   1440px line is unreadable and does not resemble the 160-character text it
   will become. */
.bmsg-form { max-width: 720px; }

.bmsg-keys { font-size: 13px; margin: 0 0 20px; line-height: 1.7; }
.bmsg-keys code { white-space: nowrap; }

.bmsg-group {
  border: 0;
  /* The global `fieldset` rule fills with --surface-2. Left on, it tints the
     whole group and the follow-up timing box below loses the contrast that is
     what marks it as belonging to the follow-up. */
  background: transparent;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.bmsg-group > legend {
  font-weight: 600;
  font-size: 14px;
  padding: 0;
  margin-bottom: 16px;
}

.bmsg-field { display: flex; flex-direction: column; gap: 8px; }
.bmsg-field__head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.bmsg-field__head label { font-weight: 500; font-size: 14px; margin: 0; }
/* Pushes the pill and the reset to the right edge, so the label reads as the
   start of the row rather than one of three things competing in the middle. */
.bmsg-field__head [data-bmsg-status] { margin-left: auto; }
/* `.btn` sets display:inline-flex, which outranks the browser's
   `[hidden] { display: none }` on specificity -- so the plain attribute left a
   "Use the default" button sitting on every field that was ALREADY on the
   default, offering to undo nothing. Needs a selector that outranks .btn. */
.bmsg-reset[hidden] { display: none; }
/* .btn-sm paints 30px tall, which is the app's convention and fine to keep --
   but 30px is under the 44px touch floor, and this is a thumb target on a page
   built to be edited on a phone. Grows the HIT area without changing the look. */
.bmsg-reset { position: relative; }
.bmsg-reset::after { content: ""; position: absolute; inset: -7px -4px; }

/* 16px because below it mobile Safari zooms the page on focus and leaves the
   user scrolled sideways -- on a page that is almost entirely textareas, that
   is the whole experience. The app-wide input rule is still 14px; this only
   raises it here rather than restyling every form in the product. */
.bmsg-field textarea,
.bmsg-lag select { font-size: 16px; }
/* min-height, not rows: the script grows the box to fit what is in it, and
   without a floor an empty one would collapse to a single line. */
.bmsg-field textarea {
  line-height: 1.5;
  resize: vertical;
  min-height: 92px;
  overflow-y: hidden;
}

.bmsg-hint { line-height: 1.5; }

.bmsg-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 13px;
  color: var(--muted);
}
.bmsg-preview { line-height: 1.5; word-break: break-word; }
.bmsg-count { font-variant-numeric: tabular-nums; }
/* Past one segment every send costs double. Amber, not --danger: nothing is
   broken and nothing will be rejected, it just costs twice as much. Red here
   reads as "you have made a mistake", which is wrong even on the site default
   wording a tenant has not touched. */
.bmsg-count.is-over { color: #92400e; font-weight: 500; }

.bmsg-lag {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 14px 16px;
  background: var(--surface-2);
  border-radius: var(--radius-sm);
}
.bmsg-lag label { font-weight: 500; font-size: 14px; margin: 0; }
.bmsg-lag select { max-width: 280px; }
.bmsg-lag select:disabled { opacity: 0.6; cursor: not-allowed; }

.bmsg-more > summary {
  cursor: pointer;
  font-weight: 600;
  font-size: 14px;
  padding: 12px 0;
  list-style-position: inside;
}
.bmsg-more > summary:hover { color: var(--primary); }
.bmsg-more > summary span { font-weight: 400; }
.bmsg-more[open] > summary { margin-bottom: 8px; }

.bmsg-actions { display: flex; flex-direction: column; gap: 8px; }
.bmsg-actions .btn { align-self: flex-start; }

@media (max-width: 640px) {
  /* The pill stops being pushed right once the head wraps -- at that width the
     label owns its own line and the auto margin just strands it. */
  .bmsg-field__head [data-bmsg-status] { margin-left: 0; }
  .bmsg-lag select { max-width: none; }
  .bmsg-actions .btn { align-self: stretch; }
}

/* ----- Message modal (admin SMS outbox + tenant Sent tab) ----------------- */

/* The trigger is a button but has to read as table text, so it gives back
   every button default except the pointer and the focus ring.

   Flex rather than a plain block: the preview is the only part allowed to be
   clipped. Putting the ellipsis on the button itself would truncate the failure
   flag along with the text, hiding the one marker that says this row is worth
   opening. min-width:0 is what lets the preview shrink below its content width
   inside a flex parent — without it the flag is pushed out of the cell instead. */
.msg-trigger {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  max-width: 340px;
  text-align: left;
  background: none;
  border: 0;
  padding: 2px 0;
  margin: 0;
  font: inherit;
  font-size: 13px;
  color: var(--text-2);
  cursor: pointer;
}
.msg-trigger__preview {
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.msg-trigger:hover { color: var(--primary); text-decoration: underline; }
.msg-trigger:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
.msg-trigger__flag {
  flex: 0 0 auto;
  display: inline-block;
  width: 15px;
  height: 15px;
  line-height: 15px;
  text-align: center;
  border-radius: 50%;
  background: var(--danger-50);
  color: var(--danger);
  font-size: 11px;
  font-weight: 700;
}

.msg-modal {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(15, 23, 42, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}
/* The display:flex above outranks the UA stylesheet's [hidden] rule, so the
   dialog would render open without this. Same trap as admin/deploy.html. */
.msg-modal[hidden] { display: none !important; }

.msg-modal__box {
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: 20px;
  width: 100%;
  max-width: 540px;
  max-height: 85vh;
  overflow: auto;
}
.msg-modal__box:focus { outline: none; }
.msg-modal__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}
.msg-modal__head h3 { margin: 0; font-size: 16px; }
.msg-modal__close {
  background: none;
  border: 0;
  padding: 0 4px;
  font-size: 22px;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
}
.msg-modal__close:hover { color: var(--text); }

.msg-modal__meta {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 16px;
  margin: 14px 0 0;
}
.msg-modal__meta dt {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.msg-modal__meta dd { margin: 2px 0 0; font-size: 13px; word-break: break-word; }

.msg-modal__label {
  margin: 16px 0 6px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
/* pre-wrap, because a two-line reminder that renders as one line is not the
   message that was sent. */
.msg-modal__body, .msg-modal__error {
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 14px;
  line-height: 1.5;
  padding: 12px;
  border-radius: var(--radius-sm);
  max-height: 45vh;
  overflow: auto;
}
.msg-modal__body { background: var(--surface-2); color: var(--text); }
.msg-modal__error {
  background: var(--danger-50);
  color: var(--danger);
  font-size: 13px;
}

@media (max-width: 640px) {
  .msg-modal__meta { grid-template-columns: 1fr; }
  .msg-trigger { max-width: none; }
}

/* ----- Privacy notice on the booking form ---------------------------- */
/* Two quiet lines above the submit button, not a panel. §16(a) is a right to
   be informed before handing data over, and a layered notice satisfies it: the
   link is on the form, above the button, and the notice itself is a page
   (public.offer_privacy). The panel this replaced was the heaviest element on
   a form that asks for four fields, which is what made people scroll past the
   thing it existed to show them. */
/* Sits outside the card, under the submit button, right-aligned. Quiet on
   purpose: it is not part of the task, it is the notice the task has to be
   reachable from. The form's own flex gap would put 28px above it, which reads
   as a separate block, so the margin pulls it back under the card it belongs
   to. */
.privacy-link {
  margin: -16px 0 0;
  text-align: right;
  font-size: 13px;
}
/* Same treatment as the footer's privacy link (`.footer a`): muted and
   underlined rather than the blue link colour, so it does not compete with the
   submit button sitting directly above it. */
.privacy-link a { color: var(--muted); text-decoration: underline; }
.privacy-link a:hover { color: var(--text); }

/* ---- Daily summary (reminders/daily_summary.html) ---- */

/* Two independent blocks, not a control row: each carries its own caption, so
   they are laid out as grid cells rather than flex items sharing an edge. */
.dg-fields {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}
.dg-field { display: flex; flex-direction: column; gap: 4px; }
.dg-field__label { font-weight: 500; font-size: 13px; }
/* A time input sized to its content rather than the full column: a stretched
   HH:MM box reads as accepting more than it does. */
.dg-field input[type="time"] { max-width: 180px; }

@media (max-width: 640px) {
  .dg-fields { grid-template-columns: 1fr; }
  .dg-field input[type="time"] { max-width: none; }
}

.dg-state {
  margin: 0;
  padding: 12px 14px;
  background: var(--surface-2);
  border-radius: var(--radius-sm);
  font-size: 14px;
}

.dg-preview {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.dg-preview__head {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  align-items: baseline;
  justify-content: space-between;
  padding: 10px 14px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}
.dg-preview__label { font-weight: 600; font-size: 13px; }
.dg-preview__cost { font-size: 13px; }
.dg-preview__body {
  margin: 0;
  padding: 14px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13px;
  line-height: 1.55;
  white-space: pre-wrap;
  word-break: break-word;
  background: var(--surface);
}

.dg-test {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 16px;
  align-items: center;
  justify-content: space-between;
}
.dg-test__body { flex: 1 1 260px; }
.dg-test__title { margin: 0 0 4px; font-size: 15px; }
.dg-test__sub { margin: 0; font-size: 13px; }
.dg-last { margin-top: 12px; font-size: 13px; }

/* ---- Availability outcome strip -------------------------------------- */
/* Fourteen days of "what your settings actually produce". Reads as status,
   not as a control, so: no shadow (nothing here is interactive) and a quieter
   surface than the cards it sits above. */
.day-strip {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.day-chip {
  flex: 1 1 116px;
  min-width: 116px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
}
/* Closed days are told apart by their WORDS first — the tint only reinforces
   what "Closed" / "Time off" already says, so this survives a colourblind
   reader and a greyscale screenshot. */
.day-chip.is-closed {
  background: var(--surface-2);
  border-color: var(--border);
}
.day-chip-date {
  display: block;
  font-size: 14px;
  color: var(--muted);
}
.day-chip-today {
  text-transform: uppercase;
  font-size: 11px;
  letter-spacing: .04em;
  color: var(--primary);
}
.day-chip-state {
  display: block;
  font-size: 16px;
  color: var(--text);
}
.day-chip.is-closed .day-chip-state { color: var(--muted); }
