/* ============================================================================
   Rich-page layouts (Calendar + Payments) — inline so they ship with the page
   and never collide with the legacy calendar-fix.css / payments-fix.css files.
   Tokens are sourced from dashboard-v2.css :root.
   ========================================================================== */

/* Premium-polish foundations: layered surfaces, glass, easing, space tokens.
   Mirrors dashboard-v2.css :root additions; declared here defensively so this
   page renders correctly even if loaded with a stale cached external CSS.
   NOTE: Anthropic-grade restraint pass — dark is the default; tokens here
   only fill in what's not covered by dashboard-v2.css. */
:root {
  --glass-blur:        saturate(140%) blur(14px);
  --ease-out:          cubic-bezier(0.2, 0, 0, 1);
  --ease-in-out:       cubic-bezier(0.4, 0, 0.2, 1);
  --space-1:  4px;  --space-2:  8px;  --space-3: 12px;
  --space-4: 16px;  --space-5: 20px;  --space-6: 24px;
  --space-7: 32px;  --space-8: 40px;  --space-9: 48px; --space-10: 64px;
  --card-pad:          36px;
  --card-pad-tight:    22px;
  --card-radius:       12px;
  --card-radius-data:   8px;
  --content-max:        960px;
  --content-max-narrow: 720px;
}
@media (max-width: 700px) {
  :root { --card-pad: 22px; }
}

/* === Motion choreography (mirrored from dashboard-v2.css) ================ */
@keyframes bs-fade-up {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
[data-stagger] {
  opacity: 0;
  animation: bs-fade-up 0.5s var(--ease-out, cubic-bezier(0.2, 0, 0, 1)) forwards;
  animation-delay: calc(var(--bs-stagger-i, 0) * 60ms);
}
.metric-value, .pay-amt, .rec-hero-stat-value {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
}
.site-card.spotlight, .rec-hero.spotlight, .connect-card.spotlight {
  position: relative;
  isolation: isolate;
}
.site-card.spotlight::after,
.rec-hero.spotlight::after,
.connect-card.spotlight::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(circle at var(--bs-spot-x, 50%) var(--bs-spot-y, 50%), oklch(64.5% 0.16 38 / 0.10), transparent 40%);
  border-radius: inherit;
  opacity: 0;
  transition: opacity 0.3s var(--ease-out, cubic-bezier(0.2, 0, 0, 1));
  z-index: 1;
}
.site-card.spotlight:hover::after,
.rec-hero.spotlight:hover::after,
.connect-card.spotlight:hover::after { opacity: 1; }
.site-card.spotlight > *,
.rec-hero.spotlight > *,
.connect-card.spotlight > * { position: relative; z-index: 2; }
@keyframes bs-page-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}
main, .dash, .pg, .rich-page {
  animation: bs-page-in 0.32s var(--ease-out, cubic-bezier(0.2, 0, 0, 1));
}
@keyframes bs-shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}
.skeleton {
  background-color: var(--cream-2);
  background-image: linear-gradient(90deg, transparent, oklch(96% 0.012 80 / 0.55), transparent);
  background-size: 200% 100%;
  animation: bs-shimmer 1.6s linear infinite;
  border-radius: 6px;
  color: transparent !important;
  pointer-events: none;
}
.skeleton-line { height: 0.9em; display: inline-block; vertical-align: middle; min-width: 4ch; }
.skeleton-block { height: 100px; width: 100%; border-radius: 12px; }
@media (prefers-reduced-motion: reduce) {
  [data-stagger] { opacity: 1 !important; transform: none !important; animation: none !important; }
  .site-card.spotlight::after,
  .rec-hero.spotlight::after,
  .connect-card.spotlight::after { display: none; }
  main, .dash, .pg, .rich-page { animation: none; }
  .skeleton { animation: none; background: var(--cream-2); }
}

/* Paper-texture overlay on body — handled by dashboard-v2.css per theme.
   This rule is left intentionally empty so the inline style block does
   not override the theme-aware noise filter. */

/* Frosted decorative divider utility */
.frosted-rule {
  border: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--hairline-2) 18%, var(--hairline-2) 82%, transparent);
  margin: var(--space-6) 0;
}

/* Pulse-dot animation utility (live status) */
@keyframes bs-pulse-dot {
  0%, 100% { transform: scale(1); opacity: 1; }
  50%      { transform: scale(1.4); opacity: 0.55; }
}
.pulse-dot {
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  animation: bs-pulse-dot 2.4s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .pulse-dot { animation: none; }
}

/* Numbered section markers — removed in chrome-less restraint pass */
.section-marker { display: none; }

/* Editorial typography moments — Newsreader serif italic 500 only */
.serif-moment {
  font-family: 'Newsreader', Georgia, serif;
  font-style: italic;
  font-weight: 500;
  font-feature-settings: "liga", "dlig", "kern";
  letter-spacing: -0.005em;
}
.pull-quote {
  position: relative;
  padding: var(--space-3) var(--space-3) var(--space-3) var(--space-5);
  border-left: 2px solid var(--hairline-3);
  background: transparent;
  border-radius: 0 8px 8px 0;
  margin: var(--space-2) 0;
}
.pull-quote-text {
  font-family: 'Newsreader', Georgia, serif;
  font-style: italic;
  font-weight: 500;
  font-size: 1rem;
  color: var(--ink);
  line-height: 1.5;
}
.pull-quote-attribution {
  display: block;
  margin-top: var(--space-2);
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-style: normal;
  font-weight: 500;
}

/* Lead capture top-level page — split: Configure left, live preview right. */
main.dash:has(.lc-page),
.pg:has(.lc-page),
.rich-page:has(.lc-page) {
  max-width: 1500px;
}
.lc-page { padding-bottom: 64px; }
.lc-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 420px;
  gap: 32px;
  align-items: start;
}
@media (max-width: 1180px) {
  .lc-split { grid-template-columns: 1fr; }
}
.lc-config { min-width: 0; }
.lc-config .set-block { margin-top: 0; }
.lc-config .set-block .set-section + .set-section {
  border-top: 1px solid var(--ink-line);
  padding-top: 22px;
  margin-top: 18px;
}

/* Booking window grid — three card-like checkboxes for Morning/Afternoon/Evening */
.lc-window-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  width: 100%;
  max-width: 360px;
}
@media (max-width: 540px) {
  .lc-window-grid { grid-template-columns: 1fr; }
}
.lc-window {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--ink-line);
  border-radius: 8px;
  background: var(--cream-1, transparent);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.lc-window:hover { border-color: var(--ink-mute); }
.lc-window:has(input:checked) {
  border-color: var(--ink);
  background: var(--cream-2);
}
.lc-window input { margin-top: 2px; }
.lc-window-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.lc-window-name { font-size: 0.86rem; font-weight: 500; color: var(--ink); }
.lc-window-hours {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.72rem;
  color: var(--ink-mute);
}

.lc-preview { min-width: 0; }
.lc-preview-sticky {
  position: sticky;
  top: 24px;
  border: 1px solid var(--ink-line);
  border-radius: 14px;
  background: var(--cream-2, #FBFBFB);
  padding: 14px;
  display: flex; flex-direction: column; gap: 10px;
}
.lc-preview-tabs {
  display: inline-flex;
  gap: 4px;
  padding: 3px;
  background: var(--cream-3, rgba(0,0,0,0.05));
  border-radius: 999px;
  align-self: flex-start;
}
.lc-preview-tab {
  border: 0;
  background: transparent;
  padding: 6px 14px;
  font: inherit;
  font-size: 0.84rem;
  border-radius: 999px;
  color: var(--ink-mute);
  cursor: pointer;
  transition: background 0.16s, color 0.16s;
}
.lc-preview-tab.is-on {
  background: var(--ink, #1F1611);
  color: var(--cream-1, #FBFBFB);
}
.lc-preview-frame {
  width: 100%;
  height: 640px;
  border-radius: 10px;
  overflow: hidden;
  background: var(--cream-1, #FFFFFF);
  border: 1px solid var(--ink-line);
}
.lc-preview-frame iframe {
  width: 100%; height: 100%;
  border: 0; display: block;
}
.lc-preview-hint {
  font-size: 0.78rem;
  color: var(--ink-mute);
  text-align: center;
}
@media (max-width: 1180px) {
  .lc-preview-sticky { position: static; }
  .lc-preview-frame { height: 560px; }
}

/* Shared rich-page header */
.rich-head {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 14px;
  align-items: end;
  margin-bottom: 4px;
}
.rich-head-text { min-width: 0; }
.rich-eye {
  /* deprecated mono caps eyebrow — hidden in chrome-less restraint pass */
  display: none !important;
}
.rich-title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 1.6rem;
  font-weight: 500;
  margin: 0 0 6px;
  letter-spacing: -0.02em;
  line-height: 1.1;
  color: var(--ink);
}
.rich-subtitle {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 13px;
  letter-spacing: normal;
  text-transform: none;
  color: var(--ink-mute);
  display: flex; align-items: center; gap: 10px;
  flex-wrap: wrap;
}
.rich-subtitle .dot {
  display: inline-block; width: 3px; height: 3px;
  border-radius: 50%; background: var(--ink-faint);
}
.rich-actions { display: flex; gap: 8px; align-items: center; }

/* Toggle group: Today / Week / Month */
.toggle-group {
  display: inline-flex;
  background: var(--cream-2);
  border: 1px solid var(--hairline);
  border-radius: 8px;
  padding: 3px;
  gap: 2px;
}
.toggle-group button {
  background: transparent;
  border: 0;
  padding: 6px 12px;
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--ink-mute);
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.18s cubic-bezier(0.2, 0, 0, 1), color 0.18s cubic-bezier(0.2, 0, 0, 1);
}
.toggle-group button:hover { color: var(--ink); }
.toggle-group button.is-on {
  background: var(--ink);
  color: var(--cream);
  border-radius: 6px;
}

/* Filter chips: All / Sent / Paid / Overdue / Draft */
.chip-row {
  display: flex; gap: 6px; flex-wrap: wrap;
  margin: 4px 0 14px;
}
.chip {
  background: transparent;
  border: 1px solid var(--hairline-2);
  padding: 6px 12px;
  border-radius: 6px;
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--ink-mute);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.chip:hover { border-color: var(--hairline-3); color: var(--ink); }
.chip.is-on {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--cream);
}
.chip-count {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.6rem;
  margin-left: 6px;
  color: var(--ink-faint);
  font-weight: 600;
}
.chip.is-on .chip-count { color: rgba(255,255,255,0.6); }

/* ============================================================================
   Calendar — week grid
   ========================================================================== */
.cal-card {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--card-radius);
  overflow: hidden;
  transition: border-color 0.18s cubic-bezier(0.2, 0, 0, 1);
}
.cal-card:hover { border-color: var(--hairline-2); }
.cal-week-head {
  display: grid;
  grid-template-columns: 56px repeat(7, 1fr);
  border-bottom: 1px solid var(--hairline);
  background: var(--cream);
}
.cal-week-head-cell {
  padding: 12px 10px;
  border-left: 1px solid var(--hairline);
  text-align: left;
}
.cal-week-head-cell:first-child { border-left: 0; }
.cal-week-head-cell .cal-dow {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.56rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 600;
}
.cal-week-head-cell .cal-dom {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--ink);
  margin-top: 2px;
  letter-spacing: -0.01em;
}
.cal-week-head-cell.is-today .cal-dow { color: var(--ink); }
.cal-week-head-cell.is-today .cal-dom { color: var(--ink); }
.cal-week-head-cell.is-today {
  background: var(--cream-2);
}

.cal-grid {
  display: grid;
  grid-template-columns: 56px repeat(7, 1fr);
  position: relative;
}
.cal-time-col {
  border-right: 1px solid var(--hairline);
}
.cal-time-cell {
  height: 56px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.56rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding: 4px 8px 0;
  text-align: right;
}
.cal-day-col {
  border-left: 1px solid var(--hairline);
  position: relative;
  background-image: linear-gradient(to bottom, transparent calc(56px - 1px), var(--hairline) calc(56px - 1px), var(--hairline) 56px);
  background-size: 100% 56px;
  min-height: 616px; /* 11 hours × 56px */
}
.cal-day-col:first-of-type { border-left: 0; }
.cal-day-col.is-today { background-color: var(--cream-2); }

.cal-event {
  position: absolute;
  left: 4px; right: 4px;
  border-radius: var(--card-radius-data);
  padding: 6px 8px;
  font-size: 0.74rem;
  line-height: 1.3;
  cursor: pointer;
  border: 1px solid transparent;
  overflow: hidden;
  transition: border-color 0.12s, background 0.12s;
}
.cal-event:hover { border-color: var(--hairline-3); }
.cal-event-time {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.58rem;
  letter-spacing: 0.08em;
  font-weight: 600;
  margin-bottom: 2px;
}
.cal-event-name { font-weight: 600; line-height: 1.25; }
.cal-event-meta {
  font-size: 0.68rem;
  margin-top: 1px;
  opacity: 0.72;
  line-height: 1.25;
}
.cal-event.is-past {
  background: var(--ink);
  color: #fff;
  border-color: var(--ink);
}
.cal-event.is-past .cal-event-meta { opacity: 0.6; }
.cal-event.is-today {
  background: var(--orange);
  color: #fff;
  border-color: var(--orange-deep);
}
.cal-event.is-future {
  background: var(--cream-2);
  color: var(--ink);
  border-color: var(--hairline-2);
}

/* Calendar P1. Live grid event modifiers, working-hours bands, header nav.
   These rules sit alongside the legacy .cal-event styles above and only
   apply to elements that opt-in via the .cal-event--* modifier. */
.cal-event-title {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cal-event--booking {
  background: var(--orange-deep);
  color: #fff;
  border-color: var(--orange-deep);
}
.cal-event--booking:hover {
  border-color: var(--orange-deep);
  box-shadow: 0 4px 12px rgba(31, 22, 17, 0.14);
  z-index: 3;
}
.cal-event--gcal {
  background: var(--orange-wash, rgba(200, 81, 30, 0.10));
  color: var(--orange-deep);
  border: 1px solid var(--orange-wash, rgba(200, 81, 30, 0.18));
  border-left: 3px solid var(--orange-deep);
}
.cal-event--gcal:hover {
  border-color: var(--orange-deep);
  z-index: 3;
}
.cal-event--block {
  background: repeating-linear-gradient(
    45deg,
    var(--cream-2) 0,
    var(--cream-2) 6px,
    var(--cream) 6px,
    var(--cream) 12px
  );
  color: var(--ink);
  border: 1px dashed var(--hairline-2);
}
.cal-event--sm8 {
  background: rgba(42, 159, 214, 0.10);
  color: #1B7CB0;
  border: 1px solid rgba(42, 159, 214, 0.22);
  border-left: 3px solid #2A9FD6;
}
.cal-event--sm8:hover {
  border-color: #2A9FD6;
  z-index: 3;
}

/* === Calendar month grid (P6) =========================================
   Day cells (not hour columns). 7 weekday-header cells + 42 day cells
   (6 weeks). Each cell shows day number, up to 3 event pills, and a
   "+N more" link if there's overflow. Click pill -> openEventModal,
   click day-num or "+N more" -> drop into today view, click empty cell
   area -> openNewJobModal pre-filled at 9am that day. */
.cal-month-card {
  border-radius: 14px;
  overflow: hidden;
  background: var(--paper);
  border: 1px solid var(--hairline-2);
}
.cal-month-head {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  background: var(--cream);
  border-bottom: 1px solid var(--hairline-2);
}
.cal-month-head-cell {
  padding: 10px 12px;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-mute);
  font-weight: 600;
  text-align: left;
}
.cal-month-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  grid-auto-rows: minmax(110px, 1fr);
}
.cal-month-cell {
  position: relative;
  padding: 8px;
  border-right: 1px solid var(--hairline-2);
  border-bottom: 1px solid var(--hairline-2);
  background: var(--paper);
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-height: 0;
  cursor: pointer;
  transition: background-color 100ms ease;
}
.cal-month-cell:hover { background: var(--cream); }
.cal-month-cell.is-weekend { background: var(--cream); }
.cal-month-cell.is-weekend:hover { background: var(--cream-2); }
.cal-month-cell.is-other { background: rgba(31, 22, 17, 0.015); }
.cal-month-cell.is-other .cal-month-day-num { color: rgba(31, 22, 17, 0.32); }
.cal-month-cell.is-other:hover { background: rgba(31, 22, 17, 0.04); }
.cal-month-cell.is-today { background: rgba(27, 22, 16, 0.03); }
.cal-month-cell.is-today .cal-month-day-num {
  background: var(--ink, #1F1611);
  color: var(--cream, #FAFAFA);
}
.cal-month-grid > .cal-month-cell:nth-child(7n) { border-right: none; }
.cal-month-grid > .cal-month-cell:nth-last-child(-n+7) { border-bottom: none; }

.cal-month-day-num {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border-radius: 11px;
  border: none;
  background: transparent;
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
  transition: background-color 100ms ease;
}
.cal-month-day-num:hover {
  background: var(--cream-2);
}
.cal-month-cell.is-today .cal-month-day-num:hover {
  background: var(--ink, #1F1611);
  filter: brightness(0.85);
}

.cal-month-pills {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 0;
  overflow: hidden;
}
.cal-month-pill {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 0.72rem;
  line-height: 1.4;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: filter 100ms ease;
}
.cal-month-pill:hover { filter: brightness(0.95); }
.cal-month-pill-time {
  font-weight: 600;
  font-size: 0.68rem;
  opacity: 0.85;
  flex-shrink: 0;
}
.cal-month-pill-title {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cal-month-pill.cal-event--booking {
  background: var(--ink, #1F1611);
  color: var(--cream, #FAFAFA);
}
.cal-month-pill.cal-event--gcal {
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--hairline-2);
  border-left: 3px solid var(--ink-soft);
  padding-left: 5px;
}
.cal-month-pill.cal-event--block {
  background: repeating-linear-gradient(45deg, var(--cream-2) 0, var(--cream-2) 4px, var(--cream) 4px, var(--cream) 8px);
  color: var(--ink-mute);
  border: 1px dashed var(--hairline-2);
}
.cal-month-pill.cal-event--sm8 {
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--hairline-2);
  border-left: 3px dotted var(--ink-soft);
  padding-left: 5px;
}

.cal-month-overflow {
  align-self: flex-start;
  border: none;
  background: transparent;
  font: inherit;
  font-size: 0.7rem;
  color: var(--ink-mute);
  cursor: pointer;
  padding: 2px 4px;
  border-radius: 3px;
  margin-top: 2px;
}
.cal-month-overflow:hover {
  color: var(--ink);
  background: var(--cream-2);
}

.cal-month-loading {
  min-height: 480px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

/* Mobile: collapse min-row-height a touch so 6 rows fit on tablet. */
@media (max-width: 720px) {
  .cal-month-grid { grid-auto-rows: minmax(80px, 1fr); }
  .cal-month-cell { padding: 6px 4px; }
  .cal-month-pill-title { display: none; }
  .cal-month-pill { padding: 2px 4px; }
}

/* === Calendar event detail modal (P2) ============================== */
.cem-backdrop { position: fixed; inset: 0; background: rgba(31, 22, 17, 0.45); backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); z-index: 9990; opacity: 0; transition: opacity 0.15s ease-out; }
.cem-backdrop.is-in { opacity: 1; }
.cem-card { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.98); background: var(--paper); color: var(--ink); border: 1px solid var(--hairline-2); border-radius: 12px; box-shadow: 0 18px 50px rgba(31, 22, 17, 0.28); width: calc(100% - 32px); max-width: 480px; max-height: calc(100vh - 64px); display: flex; flex-direction: column; z-index: 9991; opacity: 0; transition: opacity 0.18s ease-out, transform 0.18s ease-out; font-family: inherit; }
.cem-card.is-in { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.cem-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 22px 28px 12px; }
.cem-head-text { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.cem-title { font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif; font-size: 1.06rem; font-weight: 600; letter-spacing: -0.01em; color: var(--ink); margin: 0; word-break: break-word; }
.cem-pill { display: inline-flex; align-items: center; align-self: flex-start; padding: 2px 8px; font-size: 0.72rem; font-weight: 500; border-radius: 999px; border: 1px solid var(--hairline-2); color: var(--ink-mute); background: var(--cream-2); letter-spacing: 0.01em; }
.cem-pill.is-pending  { color: #8a5a00; border-color: rgba(200, 138, 0, 0.30); background: rgba(255, 200, 80, 0.14); }
.cem-pill.is-confirmed { color: var(--orange-deep); border-color: var(--orange-wash); background: var(--orange-wash); }
.cem-pill.is-cancelled { color: var(--ink-faint); text-decoration: line-through; }
.cem-pill.is-done      { color: var(--ink-mute); }
.cem-pill.is-gcal      { color: var(--orange-deep); border-color: var(--orange-wash); background: var(--orange-wash); }
.cem-close { width: 30px; height: 30px; border-radius: 6px; border: 1px solid transparent; background: transparent; color: var(--ink-mute); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; font-size: 1.1rem; flex-shrink: 0; transition: background 0.18s, color 0.18s, border-color 0.18s; }
.cem-close:hover { background: var(--cream-2); color: var(--ink); border-color: var(--hairline-2); }
.cem-body { padding: 8px 28px 16px; overflow-y: auto; flex: 1 1 auto; }
.cem-row { display: grid; grid-template-columns: 92px 1fr; gap: 12px; padding: 8px 0; font-size: 0.86rem; line-height: 1.55; border-top: 1px solid var(--hairline-2); }
.cem-row:first-child { border-top: 0; }
.cem-row-label { color: var(--ink-mute); font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.04em; padding-top: 2px; }
.cem-row-value { color: var(--ink); word-break: break-word; }
.cem-row-value a { color: var(--orange-deep); text-decoration: none; border-bottom: 1px solid transparent; transition: border-color 0.18s; }
.cem-row-value a:hover { border-bottom-color: var(--orange-deep); }
.cem-row-value .cem-multiline { white-space: pre-wrap; }
.cem-map-link { font-size: 0.78rem; color: var(--ink-mute); margin-left: 6px; }
.cem-source-line { font-size: 0.78rem; color: var(--ink-mute); padding: 10px 0 4px; border-top: 1px solid var(--hairline-2); margin-top: 6px; }
.cem-s8-badge { display: inline-flex; align-items: center; font-size: 0.74rem; color: var(--orange-deep); background: var(--orange-wash); border: 1px solid var(--orange-wash); padding: 2px 8px; border-radius: 999px; margin-top: 6px; }
.cem-foot { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 14px 28px 22px; border-top: 1px solid var(--hairline-2); flex-wrap: wrap; }
.cem-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 8px 14px; font-family: inherit; font-size: 0.84rem; font-weight: 500; border-radius: 8px; border: 1px solid var(--hairline-2); background: var(--paper); color: var(--ink); cursor: pointer; transition: background 0.18s, border-color 0.18s, color 0.18s; text-decoration: none; }
.cem-btn:hover { border-color: var(--hairline-3); background: var(--cream-2); }
.cem-btn[disabled] { opacity: 0.5; cursor: not-allowed; }
.cem-btn.is-primary { background: var(--orange); border-color: var(--orange); color: #fff; }
.cem-btn.is-primary:hover { background: var(--orange-deep); border-color: var(--orange-deep); }
.cem-btn.is-danger { color: #a83a14; }
.cem-btn.is-danger:hover { background: rgba(168, 58, 20, 0.06); border-color: rgba(168, 58, 20, 0.30); }
.cem-loading, .cem-error { padding: 32px 4px; text-align: center; color: var(--ink-mute); font-size: 0.88rem; }
.cem-error a { color: var(--orange-deep); cursor: pointer; border-bottom: 1px solid transparent; }
.cem-error a:hover { border-bottom-color: var(--orange-deep); }
.cem-spinner { display: inline-block; width: 18px; height: 18px; border: 2px solid var(--hairline-2); border-top-color: var(--orange-deep); border-radius: 50%; animation: cem-spin 0.7s linear infinite; margin-bottom: 10px; }
@keyframes cem-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .cem-backdrop, .cem-card { transition: none; } .cem-spinner { animation: none; } }

/* === Calendar working-hours + blocks slide-outs + integrations ===== */
.cal-actions-section { display: flex; flex-direction: column; gap: 14px; margin-top: 28px; }
.cal-actions-eyebrow { font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace; font-size: 0.7rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-faint); margin: 0; font-weight: 500; }
.cal-actions-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
@media (max-width: 720px) { .cal-actions-row { grid-template-columns: 1fr; } }
.cal-action-btn { display: flex; flex-direction: row; align-items: flex-start; gap: 12px; padding: 16px 18px; border: 1px solid var(--hairline-2); border-radius: 12px; background: var(--paper); color: var(--ink); text-align: left; text-decoration: none; font-family: inherit; cursor: pointer; transition: border-color 0.18s cubic-bezier(0.2, 0, 0, 1), transform 0.18s cubic-bezier(0.2, 0, 0, 1), box-shadow 0.18s cubic-bezier(0.2, 0, 0, 1); width: 100%; min-width: 0; }
.cal-action-btn:hover { border-color: var(--hairline-3); transform: translateY(-1px); box-shadow: 0 6px 18px rgba(31, 22, 17, 0.06); }
.cal-action-btn:focus-visible { outline: 2px solid var(--orange-deep); outline-offset: 2px; }
.cal-action-btn.is-connected { cursor: default; }
.cal-action-btn.is-connected:hover { transform: none; box-shadow: none; border-color: var(--hairline-2); }
.cal-action-btn-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
.cal-action-btn-title { font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif; font-size: 0.96rem; font-weight: 600; letter-spacing: -0.01em; color: var(--ink); }
.cal-action-btn-sub { font-size: 0.82rem; color: var(--ink-mute); line-height: 1.4; }
.cal-action-btn--link { color: var(--ink); }
.cal-action-btn-brand { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 8px; background: var(--cream); border: 1px solid var(--hairline); flex-shrink: 0; overflow: hidden; color: var(--ink-mute); }
.cal-action-btn-brand img { display: block; width: 28px; height: 28px; }
.cal-action-btn-brand svg { display: block; }
.cal-action-btn-status { display: flex; align-items: center; gap: 6px; font-size: 0.82rem; color: var(--ink); margin-top: 2px; min-width: 0; }
.cal-action-btn-status-email { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1; }
.cal-status-dot { width: 7px; height: 7px; border-radius: 50%; background: #2E7D32; display: inline-block; flex-shrink: 0; box-shadow: 0 0 0 2px rgba(46, 125, 50, 0.12); }
.cal-action-btn-meta { font-size: 0.78rem; color: var(--ink-mute); line-height: 1.4; font-variant-numeric: tabular-nums; }
.cal-action-btn-controls { display: inline-flex; align-items: center; gap: 6px; margin-top: 4px; font-size: 0.82rem; }
.cal-action-btn-controls-sep { color: var(--ink-faint); }
.cal-link-btn { background: transparent; border: 0; padding: 0; cursor: pointer; font: inherit; font-size: 0.82rem; color: var(--ink); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; transition: opacity 0.12s; }
.cal-link-btn:hover { opacity: 0.7; }
.cal-link-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.cal-action-btn-queued { color: var(--ink-mute); font-variant-numeric: tabular-nums; }
.cal-action-btn-warn { display: block; margin-top: 8px; padding: 7px 10px; background: rgba(217, 84, 30, 0.08); border-left: 2px solid var(--orange-deep, #B5532E); border-radius: 4px; font-size: 0.78rem; color: var(--ink); line-height: 1.4; }
.cal-action-btn-reconnect { display: inline-flex; align-items: center; gap: 6px; margin-top: 8px; padding: 7px 14px; background: var(--orange-deep, #B5532E); color: #fff; font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif; font-size: 0.82rem; font-weight: 600; text-decoration: none; border-radius: 8px; transition: background 0.18s, transform 0.18s; align-self: flex-start; }
.cal-action-btn-reconnect:hover { background: var(--orange, #C95C28); transform: translateY(-1px); }
.cal-action-btn-reconnect:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.cal-action-btn.is-needs-attention { border-color: var(--orange-deep, #B5532E); border-left-width: 3px; }
.cal-action-btn.is-needs-attention .cal-status-dot { background: var(--orange-deep, #B5532E); box-shadow: 0 0 0 2px rgba(181, 83, 46, 0.12); }

/* Slide-out backdrop + panel */
.cal-slideout-backdrop { position: fixed; inset: 0; background: rgba(31, 22, 17, 0.40); backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); z-index: 9990; opacity: 0; transition: opacity 0.20s ease-out; }
.cal-slideout-backdrop.is-in { opacity: 1; }
.cal-slideout { position: fixed; top: 0; right: 0; bottom: 0; width: 100%; max-width: 480px; background: var(--paper); color: var(--ink); border-left: 1px solid var(--hairline-2); box-shadow: -16px 0 40px rgba(31, 22, 17, 0.12); z-index: 9991; display: flex; flex-direction: column; transform: translateX(100%); transition: transform 0.22s ease-out; font-family: inherit; }
.cal-slideout.is-in { transform: translateX(0); }
.cal-slideout-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 20px 24px 14px; border-bottom: 1px solid var(--hairline-2); flex-shrink: 0; }
.cal-slideout-head-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.cal-slideout-title { font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif; font-size: 1.06rem; font-weight: 600; letter-spacing: -0.01em; color: var(--ink); margin: 0; }
.cal-slideout-sub { font-size: 0.82rem; color: var(--ink-mute); line-height: 1.45; margin: 0; }
.cal-slideout-close { width: 30px; height: 30px; border-radius: 6px; border: 1px solid transparent; background: transparent; color: var(--ink-mute); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; font-size: 1.1rem; flex-shrink: 0; transition: background 0.18s, color 0.18s, border-color 0.18s; }
.cal-slideout-close:hover { background: var(--cream-2); color: var(--ink); border-color: var(--hairline-2); }
.cal-slideout-body { padding: 16px 24px 24px; overflow-y: auto; flex: 1 1 auto; }
.cal-slideout-body p { font-size: 0.86rem; color: var(--ink-mute); line-height: 1.5; margin: 0 0 16px; }
.cal-slideout-foot { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 14px 24px; border-top: 1px solid var(--hairline-2); flex-shrink: 0; }
.cal-slideout-status { flex: 1 1 auto; font-size: 0.80rem; color: var(--ink-mute); }
.cal-slideout-status.is-error { color: #a83a14; }
.cal-slideout-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 8px 14px; font-family: inherit; font-size: 0.84rem; font-weight: 500; border-radius: 8px; border: 1px solid var(--hairline-2); background: var(--paper); color: var(--ink); cursor: pointer; transition: background 0.18s, border-color 0.18s, color 0.18s; }
.cal-slideout-btn:hover { border-color: var(--hairline-3); background: var(--cream-2); }
.cal-slideout-btn[disabled] { opacity: 0.5; cursor: not-allowed; }
.cal-slideout-btn.is-primary { background: var(--orange); border-color: var(--orange); color: #fff; }
.cal-slideout-btn.is-primary:hover { background: var(--orange-deep); border-color: var(--orange-deep); color: #fff; }

/* Working-hours rows */
.cal-hrs-list { display: flex; flex-direction: column; gap: 10px; }
.cal-hrs-row { display: grid; grid-template-columns: 56px 1fr auto auto; align-items: center; gap: 10px; padding: 10px 12px; border: 1px solid var(--hairline-2); border-radius: 10px; background: var(--paper); }
.cal-hrs-row.is-closed { background: var(--cream-2); opacity: 0.85; }
.cal-hrs-day { font-size: 0.86rem; font-weight: 600; color: var(--ink); letter-spacing: -0.005em; }
.cal-hrs-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 0.78rem; color: var(--ink-mute); cursor: pointer; user-select: none; }
.cal-hrs-toggle input { margin: 0; }
.cal-hrs-time { height: 32px; padding: 0 8px; border: 1px solid var(--hairline-2); border-radius: 6px; background: var(--paper); color: var(--ink); font-family: inherit; font-size: 0.84rem; width: 95px; }
.cal-hrs-time:disabled { opacity: 0.5; cursor: not-allowed; }
.cal-hrs-dash { color: var(--ink-mute); font-size: 0.82rem; }

/* Block-time-off form + list */
.cal-blk-form { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 14px; border: 1px solid var(--hairline-2); border-radius: 10px; background: var(--cream-2); margin-bottom: 18px; }
.cal-blk-form-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.cal-blk-form-field.is-full { grid-column: 1 / -1; }
.cal-blk-form-field label { font-size: 0.74rem; color: var(--ink-mute); text-transform: uppercase; letter-spacing: 0.04em; font-weight: 500; }
.cal-blk-input { height: 34px; padding: 0 10px; border: 1px solid var(--hairline-2); border-radius: 6px; background: var(--paper); color: var(--ink); font-family: inherit; font-size: 0.86rem; }
.cal-blk-input:disabled { opacity: 0.5; cursor: not-allowed; }
.cal-blk-form-allday { display: inline-flex; align-items: center; gap: 6px; font-size: 0.84rem; color: var(--ink); cursor: pointer; user-select: none; padding: 4px 0; }
.cal-blk-form-allday input { margin: 0; }
.cal-blk-form-actions { grid-column: 1 / -1; display: flex; justify-content: flex-end; }
.cal-blk-list { display: flex; flex-direction: column; gap: 8px; }
.cal-blk-row { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 12px; padding: 12px 14px; border: 1px solid var(--hairline-2); border-radius: 10px; background: var(--paper); }
.cal-blk-row-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cal-blk-row-date { font-size: 0.86rem; font-weight: 600; color: var(--ink); }
.cal-blk-row-meta { font-size: 0.78rem; color: var(--ink-mute); }
.cal-blk-row-del { width: 28px; height: 28px; border-radius: 6px; border: 1px solid transparent; background: transparent; color: var(--ink-mute); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; font-size: 0.96rem; transition: background 0.18s, border-color 0.18s, color 0.18s; }
.cal-blk-row-del:hover { background: rgba(168, 58, 20, 0.06); border-color: rgba(168, 58, 20, 0.30); color: #a83a14; }
.cal-blk-empty { text-align: center; font-size: 0.84rem; color: var(--ink-mute); padding: 18px 8px; border: 1px dashed var(--hairline-2); border-radius: 10px; background: var(--paper); }

@media (max-width: 540px) { .cal-slideout { max-width: 100%; } .cal-blk-form { grid-template-columns: 1fr; } .cal-hrs-row { grid-template-columns: 56px 1fr; row-gap: 6px; } .cal-hrs-row > .cal-hrs-toggle { grid-column: 1 / -1; justify-content: flex-end; } }
@media (prefers-reduced-motion: reduce) { .cal-slideout-backdrop, .cal-slideout { transition: none; } }

/* === Calendar new-job modal (P3) =================================== */
.nj-backdrop { position: fixed; inset: 0; background: rgba(31, 22, 17, 0.45); backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); z-index: 9990; opacity: 0; transition: opacity 0.15s ease-out; }
.nj-backdrop.is-in { opacity: 1; }
.nj-card { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.98); background: var(--paper); color: var(--ink); border: 1px solid var(--hairline-2); border-radius: 12px; box-shadow: 0 18px 50px rgba(31, 22, 17, 0.28); width: calc(100% - 32px); max-width: 480px; max-height: calc(100vh - 64px); display: flex; flex-direction: column; z-index: 9991; opacity: 0; transition: opacity 0.18s ease-out, transform 0.18s ease-out; font-family: inherit; }
.nj-card.is-in { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.nj-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 22px 28px 12px; }
.nj-head-text { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.nj-title { font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif; font-size: 1.06rem; font-weight: 600; letter-spacing: -0.01em; color: var(--ink); margin: 0; word-break: break-word; }
.nj-sub { font-size: 0.82rem; color: var(--ink-mute); line-height: 1.45; margin: 0; }
.nj-close { width: 30px; height: 30px; border-radius: 6px; border: 1px solid transparent; background: transparent; color: var(--ink-mute); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; font-size: 1.1rem; flex-shrink: 0; transition: background 0.18s, color 0.18s, border-color 0.18s; }
.nj-close:hover { background: var(--cream-2); color: var(--ink); border-color: var(--hairline-2); }
.nj-body { padding: 8px 28px 16px; overflow-y: auto; flex: 1 1 auto; }
.nj-form { display: flex; flex-direction: column; gap: 12px; }
.nj-row { display: flex; flex-direction: column; gap: 4px; }
.nj-row.is-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.nj-row.is-grid .nj-row-cell { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.nj-label { font-size: 0.74rem; color: var(--ink-mute); text-transform: uppercase; letter-spacing: 0.04em; font-weight: 500; }
.nj-label .nj-req { color: var(--orange-deep); margin-left: 2px; }
.nj-input, .nj-select, .nj-textarea { height: 36px; padding: 0 10px; border: 1px solid var(--hairline-2); border-radius: 6px; background: var(--paper); color: var(--ink); font-family: inherit; font-size: 0.88rem; }
.nj-textarea { height: auto; padding: 8px 10px; resize: vertical; min-height: 64px; line-height: 1.45; }
.nj-input:focus, .nj-select:focus, .nj-textarea:focus { outline: 2px solid var(--orange-deep); outline-offset: 1px; border-color: var(--orange-deep); }
.nj-input[disabled], .nj-select[disabled], .nj-textarea[disabled] { opacity: 0.5; cursor: not-allowed; }
.nj-help { font-size: 0.74rem; color: var(--ink-faint); line-height: 1.4; }
.nj-fielderr { font-size: 0.74rem; color: #a83a14; line-height: 1.4; }
.nj-row.has-error .nj-input, .nj-row.has-error .nj-select, .nj-row.has-error .nj-textarea, .nj-row-cell.has-error .nj-input, .nj-row-cell.has-error .nj-select { border-color: #a83a14; }
.nj-checkbox-row { display: flex; align-items: flex-start; gap: 8px; padding: 10px 12px; border: 1px solid var(--hairline-2); border-radius: 8px; background: var(--cream-2); margin-top: 4px; cursor: pointer; user-select: none; }
.nj-checkbox-row input { margin-top: 3px; flex-shrink: 0; cursor: pointer; }
.nj-checkbox-row-text { display: flex; flex-direction: column; gap: 2px; }
.nj-checkbox-label { font-size: 0.86rem; color: var(--ink); font-weight: 500; }
.nj-checkbox-sub { font-size: 0.76rem; color: var(--ink-mute); line-height: 1.4; }
.nj-foot { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 14px 28px 22px; border-top: 1px solid var(--hairline-2); flex-wrap: wrap; }
.nj-foot-status { flex: 1 1 auto; min-width: 0; font-size: 0.80rem; color: var(--ink-mute); }
.nj-foot-status.is-error { color: #a83a14; }
.nj-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 8px 14px; font-family: inherit; font-size: 0.84rem; font-weight: 500; border-radius: 8px; border: 1px solid var(--hairline-2); background: var(--paper); color: var(--ink); cursor: pointer; transition: background 0.18s, border-color 0.18s, color 0.18s; }
.nj-btn:hover { border-color: var(--hairline-3); background: var(--cream-2); }
.nj-btn[disabled] { opacity: 0.5; cursor: not-allowed; }
.nj-btn.is-primary { background: var(--orange); border-color: var(--orange); color: #fff; }
.nj-btn.is-primary:hover { background: var(--orange-deep); border-color: var(--orange-deep); color: #fff; }

/* Empty-cell click target inside a day column. Rendered first in the
   day column so events stack on top via document order (events have no
   explicit z-index either). Inside working-hours is subtly hoverable;
   outside-hours cells are not interactive. */
.cal-empty-cell { position: absolute; left: 0; right: 0; cursor: pointer; background: transparent; transition: background 0.12s; }
.cal-empty-cell.is-disabled { cursor: default; pointer-events: none; }
.cal-empty-cell:hover { background: rgba(200, 81, 30, 0.06); }

@media (max-width: 540px) { .nj-row.is-grid { grid-template-columns: 1fr; } }
@media (prefers-reduced-motion: reduce) { .nj-backdrop, .nj-card { transition: none; } }

.cal-hours-band {
  position: absolute;
  left: 0; right: 0;
  background: var(--cream-2);
  opacity: 0.55;
  pointer-events: none;
  z-index: 0;
}

/* Header navigation row (prev / today / next + range label) */
.cal-nav-row {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-right: 4px;
}
.cal-nav-btn {
  width: 30px; height: 30px;
  border-radius: 6px;
  border: 1px solid var(--hairline-2);
  background: var(--paper);
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--ink);
  font-family: inherit;
  font-size: 0.92rem;
  padding: 0;
  transition: border-color 0.18s cubic-bezier(0.2, 0, 0, 1);
}
.cal-nav-btn:hover { border-color: var(--hairline-3); color: var(--ink); }
.cal-today-btn {
  padding: 0 12px; height: 30px;
  border-radius: 6px;
  border: 1px solid var(--hairline-2);
  background: var(--paper);
  cursor: pointer;
  font-family: inherit;
  font-size: 0.82rem;
  color: var(--ink);
  transition: border-color 0.18s cubic-bezier(0.2, 0, 0, 1);
}
.cal-today-btn:hover { border-color: var(--hairline-3); }
.cal-range-label {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 0.86rem;
  color: var(--ink-mute);
  font-weight: 500;
  margin: 0 8px;
  letter-spacing: -0.005em;
}

/* ──────────────────────────────────────────────────────────────────
   Calendar — Style D (week density heat-strip + focused-day agenda)
   ────────────────────────────────────────────────────────────────── */

/* Keep the calendar header in title-left / pill-right at mobile too —
   the page only has one tiny "+ New job" button up top now. The
   Calendar's old mobile rule stacked .rich-actions vertically because
   it had to fit prev/today/next + segmented view toggle + CTA; with
   tabs + nav moved into their own .cal-controls row below, the
   header can keep its desktop layout on mobile. */
@media (max-width: 720px) {
  .rich-head--calendar { grid-template-columns: 1fr auto !important; align-items: start; gap: 12px; }
  .rich-head--calendar .rich-actions { flex-direction: row !important; align-items: flex-start !important; }
}

/* Calendar page — Cal.com-inspired layout. Day-grouped agenda
   (no pill strip, no hour-by-hour timeline). Display heading uses
   Cal Sans (the Cal.com signature pairing of Cal Sans display +
   Inter body). Status reads through ink-soft tinted chips with a
   filled dot, not coloured backgrounds — keeps the page monotone
   and matches the Anthropic register. */

/* Compact "+ New job" pill — mirrors .inbound-new-btn exactly so the
   two pages read as the same product. */
.cal-new-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 9px 14px; border-radius: 999px;
  background: var(--ink); color: var(--cream);
  font-family: inherit; font-size: 0.86rem; font-weight: 500;
  text-decoration: none; white-space: nowrap; cursor: pointer;
  align-self: flex-start;
  transition: background 0.15s ease, transform 0.15s ease;
}
.cal-new-btn:hover { background: var(--ink-2, #2A1F17); color: var(--cream); }
.cal-new-btn:active { transform: scale(0.98); }
.cal-new-btn svg { display: block; }

/* Controls strip (tabs + date nav). */
.cal-controls {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 4px 0 18px;
}

/* Tabs — exact copy of .inbound-tabs (cream-2 track, fully rounded
   pill, sliding glass-blur indicator). Same JS positioning logic
   already wires the indicator's transform + width on tab change. */
.cal-tabs {
  position: relative;
  display: inline-flex; padding: 4px;
  background: var(--cream-2); border-radius: 999px;
  border: 1px solid var(--hairline);
  isolation: isolate;
}
.cal-tab {
  position: relative; z-index: 1;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px; border-radius: 999px;
  font-family: inherit;
  font-size: 0.86rem; font-weight: 500;
  color: var(--ink-mute);
  background: transparent; border: 0; cursor: pointer;
  transition: color 0.22s ease;
  -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) { .cal-tab:hover { color: var(--ink); } }
.cal-tab.is-on { color: var(--ink); }

.cal-tabs__indicator {
  position: absolute;
  top: 4px; left: 0;
  height: calc(100% - 8px);
  width: 0;
  pointer-events: none; z-index: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.55);
  backdrop-filter: blur(16px) saturate(200%);
  -webkit-backdrop-filter: blur(16px) saturate(200%);
  border: 1px solid rgba(255, 255, 255, 0.75);
  box-shadow:
    0 1px 4px rgba(31, 22, 17, 0.10),
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    inset 0 -1px 0 rgba(31, 22, 17, 0.05);
  will-change: backdrop-filter, transform, width;
  transform: translate3d(0, 0, 0);
  transition:
    transform 0.32s cubic-bezier(0.32, 0.72, 0, 1),
    width 0.32s cubic-bezier(0.32, 0.72, 0, 1);
}
.cal-tabs__indicator::before {
  content: '';
  position: absolute;
  top: 1px; left: 1px; right: 1px;
  height: 50%;
  border-radius: 999px 999px 0 0;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.45) 0%,
    rgba(255, 255, 255, 0.08) 70%,
    transparent 100%
  );
  pointer-events: none;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .cal-tabs__indicator { background: rgba(255, 255, 255, 0.95); }
}

/* Week range row — Cal Sans label + ghost nav arrows. Replaces the
   prior cream-pill prev/today/next group. The data-cal-range span is
   still populated by JS (the date string). */
.cal-nav-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px;
  padding: 4px 2px;
  margin: 6px 0 4px;
}
.cal-nav-row .cal-range-label {
  font-family: 'Cal Sans', 'Inter Tight', 'Inter', sans-serif;
  font-size: 1.05rem; font-weight: 400;
  letter-spacing: -0.012em;
  color: var(--ink);
  order: -1;
  flex: 1;
}
.cal-nav-row .cal-today-btn { display: none; }
.cal-nav-row .cal-nav-btn {
  width: 30px; height: 30px;
  display: inline-grid; place-items: center;
  background: transparent; border: 0; border-radius: 7px;
  color: var(--ink-mute); cursor: pointer;
  font-family: inherit; font-size: 0.95rem;
  transition: background 0.12s, color 0.12s;
}
.cal-nav-row .cal-nav-btn:hover {
  background: rgba(27, 22, 16, 0.05);
  color: var(--ink);
}

/* Day-grouped agenda — one block per day with a Cal-Sans day number,
   day-of-week label, optional Today tag, and inline event rows or an
   "Open day" dashed band when free. */
/* Zoom segmented control (1× / 2× / 3×). Sits beside the
   Today/Week/Month tabs and controls vertical hour density. */
.cal-zoom {
  position: relative; display: inline-flex; gap: 2px; padding: 3px;
  background: rgba(27, 22, 16, 0.05); border-radius: 9px;
}
.cal-zoom__btn {
  padding: 5px 10px; border: 0; background: transparent;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.66rem; font-weight: 600; color: var(--ink-mute);
  letter-spacing: 0.04em;
  border-radius: 6px; cursor: pointer;
  transition: color 0.2s ease, background 0.2s ease;
  -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) { .cal-zoom__btn:hover { color: var(--ink); } }
.cal-zoom__btn.is-on {
  color: var(--ink); background: #FFFFFF;
  box-shadow: 0 1px 0 rgba(27, 22, 16, 0.04), 0 1px 3px rgba(27, 22, 16, 0.05);
}

/* Day-pill strip — horizontal navigator. Today is dark-filled, the
   focused day (whose hour grid is shown below) gets an orange ring.
   Days with jobs get a small pin dot under the date. */
.cal-date-strip {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px;
  margin: 10px 0 14px;
}
.cal-pill {
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  padding: 9px 0 11px;
  border-radius: 8px;
  background: transparent;
  border: 1px solid transparent;
  font-family: inherit; cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
  -webkit-tap-highlight-color: transparent;
}
.cal-pill__name {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.55rem; letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 500;
}
.cal-pill__num {
  font-size: 0.92rem; font-weight: 600; color: var(--ink);
  margin-top: 2px; letter-spacing: -0.02em; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.cal-pill__pin {
  position: absolute; bottom: 5px; left: 50%; transform: translateX(-50%);
  width: 3px; height: 3px; border-radius: 50%;
  background: var(--ink-soft); opacity: 0.6;
}
@media (hover: hover) {
  .cal-pill:hover { background: rgba(27, 22, 16, 0.04); }
}
/* Focused day — orange ring (only visible when not today). */
.cal-pill.is-on {
  border-color: var(--orange, #D9541E);
  background: transparent;
}
/* Today — solid dark fill. Wins over .is-on (dark + orange ring is noisy). */
.cal-pill.is-today {
  background: var(--ink); border-color: var(--ink);
}
.cal-pill.is-today .cal-pill__name { color: rgba(250, 250, 250, 0.55); }
.cal-pill.is-today .cal-pill__num { color: var(--cream); }
.cal-pill.is-today .cal-pill__pin { background: var(--cream); opacity: 0.75; }

/* Hour grid — Jobber's daily driver. Vertical hour axis on the left,
   slot column on the right. Slot height is driven by CSS var so the
   1×/2×/3× zoom control just rewrites one number. */
.cal-grid-wrap {
  --cal-slot-h: 56px;            /* 2× zoom default */
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: 12px; overflow: hidden;
}
.cal-grid-wrap[data-zoom="1"] { --cal-slot-h: 36px; }
.cal-grid-wrap[data-zoom="2"] { --cal-slot-h: 56px; }
.cal-grid-wrap[data-zoom="3"] { --cal-slot-h: 88px; }
.cal-grid-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid var(--hairline);
}
.cal-grid-head__day {
  font-size: 0.96rem; font-weight: 600;
  letter-spacing: -0.005em;
}
.cal-grid-head__day b { font-weight: 700; }
.cal-grid-head__cap {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.62rem; font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-faint);
}
/* Renamed from .cal-grid to avoid colliding with the old week-grid
   .cal-grid selector + its mobile media-query override above. */
.cal-hgrid {
  display: grid; grid-template-columns: 50px 1fr;
  background: transparent;
}
.cal-gh {
  padding: 12px 0 12px 14px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.6rem; font-weight: 500;
  color: var(--ink-faint);
  letter-spacing: 0.1em; text-transform: uppercase;
  border-bottom: 1px solid var(--hairline);
  min-height: var(--cal-slot-h);
  display: flex; align-items: flex-start;
}
.cal-gh:last-of-type { border-bottom: 0; }
.cal-gs {
  position: relative;
  border-bottom: 1px solid var(--hairline);
  border-left: 1px solid var(--hairline);
  min-height: var(--cal-slot-h);
}
.cal-gs:last-of-type { border-bottom: 0; }

/* Event block — solid ink-on-cream fill, brand-orange left bar for
   confirmed, paper left bar for new. Absolute-positioned inside the
   slot at its hour, height scaled by duration relative to slot. */
.cal-blk {
  position: absolute; left: 8px; right: 8px;
  background: var(--ink); color: var(--cream);
  border-radius: 8px;
  border-left: 3px solid var(--orange, #D9541E);
  padding: 9px 11px;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(27, 22, 16, 0.1);
  cursor: pointer;
}
.cal-blk.is-new { border-left-color: var(--cream, #FAFAFA); }
.cal-blk.is-past { opacity: 0.55; }
.cal-blk__ttl {
  font-size: 0.84rem; font-weight: 600;
  letter-spacing: -0.005em; line-height: 1.2;
}
.cal-blk__meta {
  font-size: 0.72rem; opacity: 0.78;
  margin-top: 2px; line-height: 1.3;
}
.cal-blk__time {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.6rem; font-weight: 500;
  letter-spacing: 0.06em;
  opacity: 0.7; margin-top: 4px;
  text-transform: uppercase;
}
.cal-blk__new {
  position: absolute; top: 8px; right: 9px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.55rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--cream); opacity: 0.85;
}

/* "Now" indicator inside a slot — horizontal orange hairline + dot. */
.cal-now-line {
  position: absolute; left: 0; right: 0; height: 2px;
  background: var(--orange, #D9541E); z-index: 4; pointer-events: none;
}
.cal-now-line:before {
  content: ""; position: absolute; left: -4px; top: -3px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--orange, #D9541E);
  box-shadow: 0 0 0 3px rgba(217, 84, 30, 0.18);
}

/* Mobile (≤720px): the .rich-actions toolbar (prev/today/next + range +
   Today/Week/Month + New job) can't fit beside the title at this width.
   .rich-head is grid `1fr auto`, so the auto column pins itself wide and
   starves the 1fr title column to 0px — title and subtitle then wrap one
   character per line because they live in a 0-width box. Stack the head
   to a single column and stack each toolbar group as its own full-width
   row: nav, segmented view toggle, primary CTA. */
@media (max-width: 720px) {
  .rich-head { grid-template-columns: 1fr; gap: 12px; }
  .rich-actions { flex-direction: column; align-items: stretch; gap: 10px; }
  .cal-nav-row { display: flex; width: 100%; margin-right: 0; }
  .cal-range-label { flex: 1; text-align: right; margin: 0 0 0 8px; }
  .rich-actions .toggle-group { width: 100%; }
  .rich-actions .toggle-group button { flex: 1; }
  .rich-actions > .btn { width: 100%; justify-content: center; }
}

/* Inline grid loading shimmer */
.cal-loading-row {
  height: 100%;
  background: linear-gradient(
    90deg,
    var(--cream-2) 0%,
    var(--cream-3) 50%,
    var(--cream-2) 100%
  );
  background-size: 200% 100%;
  animation: cal-shimmer 1.4s ease-in-out infinite;
  opacity: 0.6;
}
@keyframes cal-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* Inline status strip below grid */
.cal-status-row {
  margin-top: 12px;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.82rem;
  color: var(--ink-mute);
}
.cal-status-row .cal-status-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--ink-faint);
}
.cal-status-row.is-error { color: var(--orange-deep); }
.cal-status-row.is-error .cal-status-dot { background: var(--orange-deep); }

/* Sync status strip */
.cal-sync {
  background: var(--cream-2);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 12px 18px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  font-size: 0.82rem;
  color: var(--ink-mute);
}
.cal-sync-left {
  display: inline-flex; align-items: center; gap: 10px;
}
.cal-sync-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--green);
  animation: pulse 2.4s ease-in-out infinite;
}
.cal-sync-meta {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.cal-sync-meta strong { color: var(--green); font-weight: 700; }

/* ============================================================================
   Payments — booking-deposit summary + Stripe Connect deposit list
   ========================================================================== */
.pay-card {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--card-radius);
  overflow: hidden;
  transition: border-color 0.18s cubic-bezier(0.2, 0, 0, 1);
}
.pay-card:hover { border-color: var(--hairline-2); }
.pay-list-head {
  display: grid;
  grid-template-columns: 90px 1.4fr 1.6fr 90px 100px 90px 70px;
  gap: 12px;
  padding: 10px 18px;
  background: var(--cream);
  border-bottom: 1px solid var(--hairline);
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.54rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 600;
}
.pay-list-head .pay-amt-h { text-align: right; }

.pay-row {
  display: grid;
  grid-template-columns: 90px 1.4fr 1.6fr 90px 100px 90px 70px;
  gap: 12px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--hairline);
  align-items: center;
  font-size: 0.86rem;
}
.pay-row:last-child { border-bottom: 0; }
.pay-row:hover { background: rgba(31,22,17,0.015); }
.pay-inv {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0.04em;
}
.pay-cust { min-width: 0; }
.pay-cust-name {
  font-weight: 600;
  color: var(--ink);
  font-size: 0.9rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pay-cust-sub {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.58rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-top: 2px;
}
.pay-job {
  color: var(--ink-mute);
  font-size: 0.84rem;
  line-height: 1.4;
}
.pay-date {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
  text-transform: uppercase;
}
.pay-amt {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.01em;
  text-align: right;
}
.pay-pill {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.56rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 700;
  padding: 4px 8px;
  border-radius: 5px;
  text-align: center;
  display: inline-block;
}
.pay-pill.is-paid    { color: var(--green);  background: var(--green-soft); }
.pay-pill.is-sent    { color: var(--blue);   background: var(--blue-soft); }
.pay-pill.is-overdue { color: var(--orange); background: var(--orange-wash); }
.pay-pill.is-draft   { color: var(--ink-faint); background: var(--cream-2); }

.pay-row-action {
  background: transparent;
  border: 1px solid var(--hairline-2);
  border-radius: 7px;
  padding: 5px 9px;
  font-family: inherit;
  font-size: 0.72rem;
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
  text-align: center;
}
.pay-row-action:hover { background: var(--cream-2); border-color: var(--hairline-3); }

/* New-invoice CTA strip */
.pay-cta-strip {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px;
  padding: 18px 22px;
  background: var(--cream-2);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  flex-wrap: wrap;
}
.pay-cta-text {
  font-size: 0.88rem;
  color: var(--ink-mute);
}
.pay-cta-text strong { color: var(--ink); font-weight: 600; }

/* Responsive: stack invoice rows on narrow viewports */
@media (max-width: 980px) {
  .pay-list-head { display: none; }
  .pay-row {
    grid-template-columns: 1fr auto;
    gap: 6px 12px;
    padding: 14px 16px;
  }
  .pay-row .pay-inv { grid-column: 1; grid-row: 1; }
  .pay-row .pay-pill { grid-column: 2; grid-row: 1; justify-self: end; }
  .pay-row .pay-cust { grid-column: 1 / -1; grid-row: 2; }
  .pay-row .pay-job  { grid-column: 1 / -1; grid-row: 3; }
  .pay-row .pay-date { grid-column: 1; grid-row: 4; }
  .pay-row .pay-amt  { grid-column: 2; grid-row: 4; }
  .pay-row .pay-row-action { grid-column: 1 / -1; grid-row: 5; justify-self: start; }
}
@media (max-width: 880px) {
  .cal-week-head,
  .cal-grid { grid-template-columns: 44px repeat(7, minmax(80px, 1fr)); }
  .cal-card { overflow-x: auto; }
}

/* ============================================================================
   Booking requests + Conversations — rich-page layouts
   Same warm-stone tokens; uses .rp-* prefix to avoid clashing with .cal-/.pay-
   styles above.
   ========================================================================== */

.rp-page { display: flex; flex-direction: column; gap: 18px; }

/* === Filter chips (Booking requests) ==================================== */
.rp-chips {
  display: flex; gap: 6px; flex-wrap: wrap;
  margin: 4px 0 4px;
}

/* === Booking-request rows =============================================== */
.rp-list {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--card-radius);
  overflow: hidden;
  transition: border-color 0.18s cubic-bezier(0.2, 0, 0, 1);
}
.rp-list:hover { border-color: var(--hairline-2); }
.rp-row {
  display: grid;
  grid-template-columns: 36px 1fr auto;
  gap: 12px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--hairline);
  align-items: flex-start;
}
.rp-row:last-child { border-bottom: 0; }
.rp-row:hover { background: rgba(31,22,17,0.015); }
.rp-avatar {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: var(--cream-2);
  color: var(--ink);
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-weight: 600;
  font-size: 0.84rem;
  display: flex; align-items: center; justify-content: center;
  flex: 0 0 auto;
  letter-spacing: 0.01em;
}
.rp-avatar.is-orange { background: var(--orange-wash); color: var(--orange); }
.rp-avatar.is-green  { background: var(--green-soft);  color: var(--green); }
.rp-avatar.is-blue   { background: var(--blue-soft);   color: var(--blue); }
.rp-avatar.is-grey   { background: var(--cream-3);     color: var(--ink-mute); }

.rp-row-text { min-width: 0; }
.rp-row-name {
  font-weight: 600;
  color: var(--ink);
  font-size: 0.92rem;
  display: flex; align-items: center; gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}
.rp-pill {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.52rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  background: var(--cream-2);
  color: var(--ink-mute);
  padding: 2px 6px;
  border-radius: 4px;
  font-weight: 700;
}
.rp-pill.is-awaiting { background: var(--orange-wash); color: var(--orange); }
.rp-pill.is-quoted   { background: var(--blue-soft);   color: var(--blue); }
.rp-pill.is-booked   { background: var(--green-soft);  color: var(--green); }
.rp-pill.is-archived { background: var(--cream-3);     color: var(--ink-faint); }
.rp-pill.is-source   { background: var(--cream-2);     color: var(--ink-mute); font-weight: 600; }
.rp-pill.is-out-of-area { background: var(--cream-3); color: var(--ink-mute); font-weight: 600; }

.rp-row-meta {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.58rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.rp-row-quote {
  font-size: 0.84rem;
  color: var(--ink-mute);
  margin-top: 6px;
  line-height: 1.5;
}

.rp-row-actions {
  display: flex; gap: 6px; flex-wrap: wrap;
  align-items: center;
}
.rp-action {
  background: transparent;
  border: 1px solid var(--hairline-2);
  border-radius: 7px;
  padding: 6px 10px;
  font-family: inherit;
  font-size: 0.74rem;
  color: var(--ink);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
  white-space: nowrap;
}
.rp-action:hover { background: var(--cream-2); }
.rp-action.is-primary {
  background: var(--ink);
  color: #fff;
  border-color: var(--ink);
}
.rp-action.is-primary:hover { background: var(--ink-2); }

.rp-load-more {
  display: inline-flex; align-self: flex-start;
  align-items: center; gap: 8px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-mute);
  background: transparent;
  border: 1px solid var(--hairline-2);
  border-radius: 8px;
  padding: 8px 14px;
  cursor: pointer;
}
.rp-load-more:hover { background: var(--cream-2); color: var(--ink); }

/* === Conversations: two-pane layout ===================================== */
.rp-conv {
  display: grid;
  grid-template-columns: 320px 1fr;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--card-radius);
  overflow: hidden;
  min-height: 580px;
  transition: border-color 0.18s cubic-bezier(0.2, 0, 0, 1);
}
.rp-conv:hover { border-color: var(--hairline-2); }
.rp-conv-aside {
  border-right: 1px solid var(--hairline);
  display: flex; flex-direction: column;
  background: var(--cream);
  min-width: 0;
}
.rp-conv-aside-head {
  padding: 14px 16px 12px;
  border-bottom: 1px solid var(--hairline);
}
.rp-conv-search {
  width: 100%;
  background: var(--paper);
  border: 1px solid var(--hairline-2);
  border-radius: 8px;
  padding: 7px 12px;
  font-family: inherit;
  font-size: 0.82rem;
  color: var(--ink);
}
.rp-conv-search::placeholder { color: var(--ink-faint); }

.rp-thread-list {
  flex: 1 1 auto;
  overflow-y: auto;
  max-height: 520px;
}
.rp-thread {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--hairline);
  cursor: pointer;
  align-items: flex-start;
  background: transparent;
  border-left: 0; border-right: 0; border-top: 0;
  width: 100%;
  text-align: left;
  font-family: inherit;
  transition: background 0.12s;
}
.rp-thread:hover { background: var(--cream-2); }
.rp-thread.is-active { background: var(--paper); }
.rp-thread .rp-avatar {
  width: 32px; height: 32px;
  font-size: 0.74rem;
}
.rp-thread-text { min-width: 0; }
.rp-thread-name {
  font-weight: 600;
  font-size: 0.86rem;
  color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  margin-bottom: 2px;
}
.rp-thread-snippet {
  font-size: 0.78rem;
  color: var(--ink-mute);
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.rp-thread-side {
  display: flex; flex-direction: column; align-items: flex-end; gap: 4px;
  flex: 0 0 auto;
}
.rp-thread-time {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.54rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.rp-thread-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--orange);
}

/* === Conversations: detail pane ========================================= */
.rp-conv-main {
  display: flex; flex-direction: column;
  min-width: 0;
}
.rp-conv-head {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--hairline);
}
.rp-conv-head .rp-avatar {
  width: 38px; height: 38px;
  font-size: 0.86rem;
}
.rp-conv-head-text { min-width: 0; flex: 1 1 auto; }
.rp-conv-head-name {
  font-weight: 600;
  font-size: 0.96rem;
  color: var(--ink);
}
.rp-conv-head-meta {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.58rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-top: 2px;
}
.rp-conv-head-actions {
  display: flex; gap: 6px; flex: 0 0 auto;
}
.rp-conv-back-btn {
  display: none;
  background: transparent;
  border: 1px solid var(--hairline-2);
  border-radius: 7px;
  padding: 6px 10px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-mute);
  cursor: pointer;
}
.rp-conv-back-btn:hover { background: var(--cream-2); }

.rp-conv-stream {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 20px 22px;
  background: var(--cream);
  display: flex; flex-direction: column; gap: 10px;
}
.rp-day-divider {
  align-self: center;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.54rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-faint);
  background: transparent;
  padding: 4px 12px;
  margin: 4px 0;
}

.rp-msg {
  max-width: 78%;
  padding: 10px 14px;
  border-radius: 14px;
  font-size: 0.86rem;
  line-height: 1.45;
  position: relative;
}
.rp-msg-from {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 700;
  display: block;
  margin-bottom: 4px;
  opacity: 0.6;
}
.rp-msg-time {
  display: block;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-top: 5px;
  opacity: 0.7;
}
.rp-msg.is-customer {
  align-self: flex-start;
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-bottom-left-radius: 5px;
}
.rp-msg.is-customer .rp-msg-time { color: var(--ink-faint); }
.rp-msg.is-ai {
  align-self: flex-end;
  background: var(--ink);
  color: #fff;
  border-bottom-right-radius: 5px;
}
.rp-msg.is-ai .rp-msg-time { color: rgba(255,255,255,0.65); }
.rp-msg.is-tradie {
  align-self: flex-end;
  background: var(--orange);
  color: #fff;
  border-bottom-right-radius: 5px;
}
.rp-msg.is-tradie .rp-msg-time { color: rgba(255,255,255,0.7); }

.rp-system-note {
  align-self: center;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.54rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  background: var(--cream-2);
  border: 1px dashed var(--hairline-2);
  border-radius: 999px;
  padding: 5px 12px;
  max-width: 80%;
  text-align: center;
}

.rp-conv-compose {
  border-top: 1px solid var(--hairline);
  padding: 12px 16px;
  display: flex; gap: 8px; align-items: flex-end;
  background: var(--paper);
}
.rp-conv-compose textarea {
  flex: 1 1 auto;
  resize: none;
  min-height: 38px;
  max-height: 120px;
  border: 1px solid var(--hairline-2);
  border-radius: 8px;
  padding: 9px 12px;
  font-family: inherit;
  font-size: 0.88rem;
  color: var(--ink);
  background: var(--cream);
}
.rp-conv-compose textarea:focus {
  outline: none;
  border-color: var(--ink-mute);
  background: var(--paper);
}
.rp-conv-send {
  background: var(--ink);
  color: #fff;
  border: 0;
  border-radius: 8px;
  padding: 10px 16px;
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
  flex: 0 0 auto;
}
.rp-conv-send:hover { background: var(--ink-2); }

/* === Mobile: stack list above thread ==================================== */
@media (max-width: 880px) {
  .rp-conv {
    grid-template-columns: 1fr;
    min-height: 0;
  }
  .rp-conv-aside {
    border-right: 0;
    border-bottom: 1px solid var(--hairline);
  }
  .rp-thread-list { max-height: 420px; }
  /* Single-pane mobile mode: data-mobile-view swaps which pane is visible. */
  .rp-conv[data-mobile-view="list"] .rp-conv-main { display: none; }
  .rp-conv[data-mobile-view="thread"] .rp-conv-aside { display: none; }
  .rp-conv[data-mobile-view="thread"] .rp-conv-back-btn { display: inline-flex; }

  .rp-row { grid-template-columns: 32px 1fr; }
  .rp-row-actions { grid-column: 1 / -1; margin-top: 6px; justify-content: flex-end; }
  .rp-avatar { width: 32px; height: 32px; font-size: 0.78rem; }
}

/* === Conversations: filter chips, quick replies, meta sidebar =========== */
.rp-conv-filters {
  display: flex; flex-wrap: wrap; gap: 6px;
}
.rp-conv-filter {
  background: transparent;
  border: 1px solid var(--hairline-2);
  border-radius: 999px;
  padding: 4px 10px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.58rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-mute);
  cursor: pointer;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.rp-conv-filter:hover { background: var(--cream-2); color: var(--ink); }
.rp-conv-filter.is-on {
  background: var(--ink);
  color: #fff;
  border-color: var(--ink);
}
.rp-conv-aside-head { display: flex; flex-direction: column; gap: 10px; }

/* Conversations: thread row hidden by search */
.rp-thread.is-hidden { display: none; }

/* Quick-reply chip row above the textarea */
.rp-conv-compose-wrap {
  display: flex; flex-direction: column;
  border-top: 1px solid var(--hairline);
  background: var(--paper);
}
.rp-quick-replies {
  display: flex; gap: 6px; flex-wrap: wrap;
  padding: 10px 16px 0;
}
.rp-quick-reply {
  background: var(--cream-2);
  border: 1px solid var(--hairline-2);
  border-radius: 999px;
  padding: 4px 10px;
  font-size: 0.74rem;
  color: var(--ink);
  cursor: pointer;
  font-family: inherit;
  transition: background 0.12s;
}
.rp-quick-reply:hover { background: var(--cream-3); }
.rp-conv-compose-wrap .rp-conv-compose { border-top: 0; padding-top: 8px; }
.rp-compose-hint {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.54rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding: 0 16px 10px;
}
.rp-compose-attach {
  background: transparent;
  border: 1px solid var(--hairline-2);
  border-radius: 8px;
  width: 38px; height: 38px;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  color: var(--ink-mute);
  flex: 0 0 auto;
}
.rp-compose-attach:hover { background: var(--cream-2); color: var(--ink); }

/* Outbound delivery status */
.rp-msg-status {
  display: block;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-top: 3px;
  opacity: 0.75;
}
.rp-msg-status.is-failed { color: #d97757; opacity: 1; font-weight: 700; }

/* Thread head: info + 3-dot icon buttons */
.rp-icon-btn {
  background: transparent;
  border: 1px solid var(--hairline-2);
  border-radius: 7px;
  width: 30px; height: 30px;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  color: var(--ink-mute);
  position: relative;
}
.rp-icon-btn:hover { background: var(--cream-2); color: var(--ink); }
.rp-icon-btn svg { width: 14px; height: 14px; }

/* Thread actions popover */
.rp-actions-pop {
  position: absolute;
  top: calc(100% + 6px); right: 0;
  background: var(--paper);
  border: 1px solid var(--hairline-2);
  border-radius: var(--card-radius);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.32);
  padding: 6px;
  min-width: 220px;
  z-index: 30;
  display: none;
  flex-direction: column;
}
.rp-actions-pop.is-open { display: flex; }
.rp-actions-pop button {
  background: transparent;
  border: 0;
  text-align: left;
  padding: 8px 10px;
  border-radius: 6px;
  font-family: inherit;
  font-size: 0.82rem;
  color: var(--ink);
  cursor: pointer;
}
.rp-actions-pop button:hover { background: var(--cream-2); }
.rp-actions-pop button.is-danger { color: #c0392b; }
.rp-actions-menu-wrap { position: relative; }

/* Conversations: meta sidebar */
.rp-conv {
  grid-template-columns: 320px 1fr 0;
  transition: grid-template-columns 0.18s ease;
}
.rp-conv.is-meta-open { grid-template-columns: 320px 1fr 280px; }
.rp-meta {
  border-left: 1px solid var(--hairline);
  background: var(--cream);
  overflow-y: auto;
  display: flex; flex-direction: column;
  min-width: 0;
  max-height: 720px;
}
.rp-conv:not(.is-meta-open) .rp-meta { display: none; }
.rp-meta-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px;
  border-bottom: 1px solid var(--hairline);
}
.rp-meta-head-title {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.58rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 700;
}
.rp-meta-section {
  padding: 14px 16px;
  border-bottom: 1px solid var(--hairline);
  display: flex; flex-direction: column; gap: 8px;
}
.rp-meta-section:last-child { border-bottom: 0; }
.rp-meta-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.54rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 700;
}
.rp-meta-customer {
  display: flex; align-items: center; gap: 10px;
}
.rp-meta-customer-text { min-width: 0; }
.rp-meta-customer-name {
  font-weight: 600; font-size: 0.92rem; color: var(--ink);
}
.rp-meta-customer-meta {
  font-size: 0.76rem; color: var(--ink-mute); margin-top: 2px;
}
.rp-meta-booking {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--card-radius-data);
  padding: 8px 10px;
  font-size: 0.78rem;
  color: var(--ink);
}
.rp-meta-booking-status {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.54rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--green);
  font-weight: 700;
  margin-bottom: 2px;
  display: block;
}
.rp-meta-booking-status.is-quote { color: var(--blue); }
.rp-meta-summary {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-left: 2px solid var(--ink-mute);
  border-radius: var(--card-radius-data);
  padding: 10px 12px;
  font-size: 0.8rem;
  color: var(--ink);
  line-height: 1.5;
}
.rp-meta-summary strong {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.54rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mute);
  display: block;
  margin-bottom: 4px;
  font-weight: 700;
}
.rp-meta-notes {
  width: 100%;
  background: var(--paper);
  border: 1px solid var(--hairline-2);
  border-radius: var(--card-radius-data);
  padding: 8px 10px;
  font-family: inherit;
  font-size: 0.82rem;
  color: var(--ink);
  resize: vertical;
  min-height: 64px;
}
.rp-meta-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.rp-meta-tag {
  background: var(--paper);
  border: 1px solid var(--hairline-2);
  border-radius: 999px;
  padding: 3px 9px;
  font-size: 0.7rem;
  color: var(--ink);
}
.rp-meta-tag.is-vip { background: var(--orange-wash); color: var(--orange); border-color: transparent; font-weight: 600; }
.rp-meta-actions { display: flex; gap: 6px; }
.rp-meta-action {
  flex: 1 1 auto;
  background: transparent;
  border: 1px solid var(--hairline-2);
  border-radius: 7px;
  padding: 7px 10px;
  font-family: inherit;
  font-size: 0.76rem;
  color: var(--ink-mute);
  cursor: pointer;
}
.rp-meta-action:hover { background: var(--cream-2); color: var(--ink); }
.rp-meta-action.is-danger { color: #c0392b; }

@media (max-width: 880px) {
  .rp-conv, .rp-conv.is-meta-open {
    grid-template-columns: 1fr;
  }
  .rp-conv.is-meta-open .rp-meta {
    position: fixed; inset: 0;
    z-index: 60;
    max-height: none;
    border-left: 0;
    background: var(--paper);
  }
  .rp-conv.is-meta-open .rp-conv-aside,
  .rp-conv.is-meta-open .rp-conv-main { display: none; }
  .rp-conv-filters { overflow-x: auto; flex-wrap: nowrap; }
  .rp-conv-filter { white-space: nowrap; flex: 0 0 auto; }
}

/* ============================================================================
   Integrations + Settings + Notifications — page-specific layouts
   ========================================================================== */

/* Shared page header */
.pg-head { display: flex; flex-direction: column; gap: 6px; margin-bottom: 4px; }
.pg-eye {
  /* deprecated mono caps eyebrow — hidden in chrome-less restraint pass */
  display: none !important;
}
.pg-title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 1.6rem; font-weight: 500; margin: 0;
  letter-spacing: -0.02em; line-height: 1.1; color: var(--ink);
}
.pg-sub {
  font-size: 0.92rem; color: var(--ink-mute);
  margin: 0; max-width: 64ch; line-height: 1.55;
}
.pg-group-head {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 0.95rem; letter-spacing: -0.005em; text-transform: none;
  color: var(--ink); font-weight: 600;
  margin: 24px 0 10px; padding-bottom: 8px;
  border-bottom: 1px solid var(--hairline);
}

/* Integrations grid */
.intg-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px;
}
@media (max-width: 980px) { .intg-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) { .intg-grid { grid-template-columns: 1fr; } }

.intg-card {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--card-radius);
  padding: var(--card-pad);
  display: flex; flex-direction: column;
  min-height: 188px;
  transition: border-color 0.18s cubic-bezier(0.2, 0, 0, 1), background 0.18s cubic-bezier(0.2, 0, 0, 1);
}
.intg-card:hover {
  border-color: var(--hairline-2);
}
.intg-card.is-quiet {
  background: transparent;
  border: 1px dashed var(--hairline-2);
}
.intg-card-top { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.intg-tier {
  margin-left: auto;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.54rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 4px;
  white-space: nowrap;
  flex-shrink: 0;
}
.intg-tier--all      { color: var(--ink-mute); background: var(--cream-2); }
.intg-tier--recovery { color: var(--orange-deep, #B8420F); background: var(--orange-wash, rgba(217,84,30,0.10)); }
.intg-tier--builder  { color: var(--ink); background: var(--cream-3); }
.intg-logo {
  width: 36px; height: 36px;
  border-radius: 8px;
  background: var(--cream-2);
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto; overflow: hidden;
  padding: 6px;
}
.intg-logo svg, .intg-logo img { max-width: 100%; max-height: 100%; object-fit: contain; }
.intg-logo.is-twilio  { background: #F22F46; color: #fff; padding: 0; font-family: 'Newsreader', serif; font-weight: 700; font-size: 1.18rem; }
.intg-logo.is-openai  { background: #0F1820; color: #fff; padding: 7px; }
.intg-logo.is-gmail   { background: #fff; color: #EA4335; border: 1px solid var(--hairline); padding: 0; font-family: 'Newsreader', serif; font-weight: 700; font-size: 1.18rem; }
.intg-logo.is-xero    { background: #13B5EA; color: #fff; padding: 6px; font-family: 'Newsreader', serif; font-weight: 700; font-size: 1rem; }
.intg-logo.is-myob    { background: #6E2585; color: #fff; padding: 6px; font-family: 'Newsreader', serif; font-weight: 700; font-size: 0.96rem; }
.intg-logo.is-ms      { background: #0078D4; color: #fff; padding: 6px; font-family: 'Newsreader', serif; font-weight: 700; font-size: 1.05rem; }
.intg-card-title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 1.06rem; font-weight: 600;
  color: var(--ink); letter-spacing: -0.01em;
  flex: 1 1 auto; min-width: 0;
}
.intg-status {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.56rem; letter-spacing: 0.14em; text-transform: uppercase;
  font-weight: 600;
  padding: 3px 8px; border-radius: 5px;
  margin-bottom: 8px; align-self: flex-start;
}
.intg-status::before {
  content: ''; width: 6px; height: 6px;
  border-radius: 50%; flex: 0 0 auto;
}
.intg-status.is-on     { background: var(--green-soft); color: var(--green); }
.intg-status.is-on::before { background: var(--green); }
.intg-status.is-system { background: var(--cream-2); color: var(--ink-mute); }
.intg-status.is-system::before { background: var(--ink-faint); }
.intg-status.is-avail  { background: var(--cream-2); color: var(--ink-mute); }
.intg-status.is-avail::before { background: var(--ink-mute); }
.intg-status.is-soon   {
  background: transparent; color: var(--ink-faint);
  border: 1px dashed var(--hairline-2);
  padding: 2px 7px;
}
.intg-status.is-soon::before { display: none; }

.intg-desc {
  font-size: 0.84rem; color: var(--ink-mute);
  line-height: 1.5; margin: 0 0 14px;
  flex: 1 1 auto;
}
.intg-action {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 8px 12px;
  font-family: inherit; font-size: 0.78rem; font-weight: 500;
  border-radius: 8px;
  border: 1px solid var(--hairline-2);
  background: transparent; color: var(--ink);
  cursor: pointer; text-decoration: none;
  align-self: flex-start;
  transition: background 0.12s, border-color 0.12s;
}
.intg-action:hover { background: var(--cream-2); border-color: var(--hairline-3); }
.intg-action.is-disabled,
.intg-action[disabled] {
  color: var(--ink-faint); cursor: not-allowed;
  border-style: dashed;
}
.intg-action.is-disabled:hover,
.intg-action[disabled]:hover { background: transparent; border-color: var(--hairline-2); }
.intg-action.is-system {
  color: var(--ink-mute);
  border: 1px dashed var(--hairline-2);
  cursor: default;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.58rem; letter-spacing: 0.14em; text-transform: uppercase;
}
.intg-action.is-system:hover { background: transparent; border-color: var(--hairline-2); }

/* When the Settings page is mounted, the parent .dash / .pg / .rich-page
   wrapper's 940px max-width would otherwise cage the rail + content.
   Widen it just for settings routes via :has() so other pages keep their
   reading-width caps. */
main.dash:has(.set-shell),
.pg:has(.set-shell),
.rich-page:has(.set-shell) {
  /* Claude-style flush-left settings: drop the 1040px cap + the
     inherited centering so .set-shell hugs the first sidebar instead
     of floating in the middle of the page. The 32px horizontal padding
     on .dash is also zeroed so .set-shell controls its own gutter. */
  max-width: none;
  margin: 0;
  padding-left: 0;
  padding-right: 0;
}

/* Settings form — Claude.ai-style centred layout. Rail (180px) + 40px gap +
   content (max 720px) ≈ 940px content + 40px page padding either side
   ≈ 1020px total. Tightened 2026-05-13 (pm) from 240+40+760 / max 1120px
   — the rail itself read too wide vs. Claude's settings, and the founder
   asked for the second sidebar specifically to feel narrower. */
/* ── Booking-form Commit 3 (2026-05-20): mode picker + per-day windows
   editor. Replaces the deleted .route-opt-block (was here previously).
   Conditional section visibility is driven by [data-conditional-mode] on
   the parent + a [data-hidden] attribute toggled by the wire-up code
   when the user clicks a different mode tile. ───────────────────── */
[data-conditional-mode][data-hidden] { display: none; }

/* Mode picker — 4 tiles in a 2x2 grid (collapses to 1 col on narrow). */
.set-mode-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 4px 0 4px;
}
@media (max-width: 640px) { .set-mode-row { grid-template-columns: 1fr; } }
.set-mode-card {
  background: var(--cream);
  border: 1px solid var(--hairline-2);
  border-radius: 10px;
  padding: 14px 16px;
  cursor: pointer;
  display: flex; flex-direction: column; gap: 6px;
  text-align: left;
  font-family: inherit;
  transition: border-color 0.12s, background 0.12s;
}
.set-mode-card:hover { background: var(--paper); border-color: var(--ink-faint); }
.set-mode-card.is-on  { background: var(--paper); border-color: var(--ink); }
.set-mode-card-name {
  font-size: 0.95rem; color: var(--ink); font-weight: 600;
}
.set-mode-card-desc {
  font-size: 0.82rem; color: var(--ink-mute); line-height: 1.45;
}
.set-mode-card-preview {
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
  color: var(--ink-faint);
  letter-spacing: 0.02em;
  margin-top: 4px;
  padding-top: 8px;
  border-top: 1px dashed var(--hairline);
}

/* Per-day windows editor — repeating rows of label + from/to inputs,
   grouped by weekday. Lifts the visual rhythm from .set-hours-row and
   the dashed-button pattern from .set-add-row. */
.set-windows-block {
  margin-bottom: 8px;
}
.set-windows-editor {
  display: flex; flex-direction: column;
  gap: 0;
  border: 1px solid var(--hairline);
  border-radius: 10px;
  overflow: hidden;
}
.set-windows-day {
  padding: 12px 14px;
}
.set-windows-day + .set-windows-day { border-top: 1px solid var(--hairline); }
.set-windows-day-name {
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
  font-weight: 600;
  margin-bottom: 8px;
}
.set-windows-day-list {
  display: flex; flex-direction: column;
  gap: 6px;
}
.set-window-row {
  display: grid;
  grid-template-columns: 1fr 100px 18px 100px 28px;
  gap: 8px;
  align-items: center;
}
.set-window-row .set-window-label {
  font-size: 0.86rem;
}
.set-windows-add {
  margin-top: 8px;
  width: 100%;
  background: transparent;
  border: 1px dashed var(--hairline-2);
  color: var(--ink-mute);
  font-family: inherit;
  font-size: 0.8rem;
  padding: 7px 12px;
  border-radius: 8px;
  cursor: pointer;
  text-align: center;
}
.set-windows-add:hover { background: var(--cream-2); color: var(--ink); }
.set-windows-add:disabled { opacity: 0.4; cursor: not-allowed; }

@media (max-width: 540px) {
  .set-window-row {
    grid-template-columns: 1fr 1fr 28px;
    grid-template-areas: "label label x" "from sep to";
    row-gap: 6px;
  }
  .set-window-row .set-window-label { grid-area: label; }
  .set-window-row .set-hours-sep    { grid-area: sep; }
}

.set-shell {
  display: grid;
  grid-template-columns: 180px minmax(0, 1fr);
  /* Row 1 = "Settings" header spanning both columns; row 2 = rail + content. */
  grid-template-rows: auto 1fr;
  gap: 18px 40px;
  align-items: start;
  /* Flush-left layout (Claude-style). 32px left gutter from the first
     sidebar's right edge; 48px right gutter so cards don't kiss the
     viewport edge. */
  max-width: none;
  margin: 0;
  padding: 28px 48px 96px 32px;
}
.set-shell-head { grid-column: 1 / -1; }
.set-shell-title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 1.75rem;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.02em;
  margin: 0;
  line-height: 1.15;
}
@media (max-width: 1024px) {
  .set-shell {
    grid-template-columns: 180px minmax(0, 1fr);
    gap: 14px 32px;
    padding: 24px 32px 96px 24px;
  }
}
@media (max-width: 900px) {
  .set-shell {
    grid-template-columns: 1fr;
    gap: 10px 0;
    padding: 18px 18px 64px;
  }
  .set-shell-title { font-size: 1.4rem; }
}

.set-rail {
  position: sticky;
  top: 18px;
  display: flex;
  flex-direction: column;
  padding: 4px 0;
  max-height: calc(100vh - 36px);
  overflow-y: auto;
  scrollbar-width: thin;
}
@media (max-width: 900px) {
  /* === MOBILE SETTINGS RAIL === Restyled as a horizontal tab strip,
     matching the old "Settings mobile: clean tab strips + scrollbar" pattern.
     Desktop sidebar layout above 900px is untouched. */
  .set-rail {
    position: sticky;
    top: 56px;                                  /* sit just below the topbar */
    z-index: 5;
    flex-direction: row;
    border-bottom: 1px solid var(--hairline);
    overflow-x: auto;
    overflow-y: hidden;
    gap: 0;
    max-height: none;
    margin: 0 -18px 14px;                       /* bleed past .set-shell padding to viewport edges */
    padding: 6px 18px 14px;
    /* Use --topband (the same warm cream the mobile topbar above
       uses) so the rail blends seamlessly into the chrome strip
       above instead of reading as a whiter inset band. */
    background: var(--topband);
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    touch-action: pan-x;
    scrollbar-width: none;                      /* Firefox */
    /* Soft fade on the right edge as a scroll affordance */
    -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 28px), transparent);
            mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 28px), transparent);
  }
  .set-rail::-webkit-scrollbar { display: none; }  /* Safari/Chrome */
}
.set-rail-link {
  display: block;
  /* Airier padding to match Claude's settings rail rhythm (was 7px 10px). */
  padding: 9px 12px;
  font-size: 0.92rem;
  color: var(--ink-mute);
  text-decoration: none;
  border-radius: 8px;
  border: none;
  margin-left: 0;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.18s cubic-bezier(0.2, 0, 0, 1), color 0.18s cubic-bezier(0.2, 0, 0, 1);
}
/* Hover + active fills (Claude-style soft warm fill). Rail surface is
   transparent (= --cream page bg), so hover needs a slight overlay to
   be visible; active uses --cream-2 (clearly darker than the page).
   Active no longer bumps font-weight; selection reads through colour
   + fill delta alone so items don't shift width on click. */
.set-rail-link:hover     { background: rgba(31, 22, 17, 0.04); color: var(--ink); }
.set-rail-link.is-active { background: var(--cream-2); color: var(--ink); }
@media (max-width: 900px) {
  /* === MOBILE TAB === Each rail link styled as a real bottom-border tab
     so the strip reads as a tabbed nav, not a stack of pills. */
  .set-rail-link {
    padding: 8px 14px;
    border-radius: 8px;
    border-bottom: none;
    font-size: 0.875rem;
    min-height: 36px;
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    font-weight: 500;
    color: var(--ink-mute);
  }
  .set-rail-link:hover {
    background: rgba(31, 22, 17, 0.04);
    color: var(--ink);
  }
  .set-rail-link.is-active {
    background: rgba(31, 22, 17, 0.06);
    color: var(--ink);
    border-bottom: none;
    font-weight: 600;
  }
}
/* .set-rail-gap removed 2026-05-14 — the rail is now a single flat
   list with no visual separation between groups (founder preference). */
.set-content { min-width: 0; display: flex; flex-direction: column; gap: 16px; }
/* Chrome-less settings: no card borders, no padding-box. Each section is a
   long list of horizontal hairline-divided rows. */
.set-card, .set-block {
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 0;
  scroll-margin-top: 18px;
}
.set-card:hover, .set-block:hover { border-color: transparent; }
.set-section { padding: 0; border-bottom: 0; }
.set-section:last-child { border-bottom: 0; }
/* Visual separation between subsections inside a merged card. The first
   subsection has no top divider; every following subsection gets a hairline
   + extra spacing so the user can clearly see "this is a related-but-distinct
   group" within the same merged rail item. */
.set-card .set-section + .set-section,
.set-block .set-section + .set-section {
  margin-top: 32px;
  padding-top: 32px;
  border-top: 1px solid var(--hairline);
}
.set-section-title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 0.95rem; font-weight: 600;
  color: var(--ink); margin: 0;
  padding: 32px 0 8px;
  letter-spacing: -0.005em;
  text-transform: none;
}
/* Cross-reference pill at the top of a Settings rules panel. Tells the
   tradie which form(s) the rules in this panel govern, with a deep-link
   each way. Sits above the first set-section-title so it reads as the
   panel's contextual breadcrumb. */
.set-affects-pill {
  display: inline-block;
  font-size: 0.78rem;
  color: var(--ink-mute, #6b7280);
  background: rgba(0,0,0,0.03);
  border: 1px solid rgba(0,0,0,0.06);
  border-radius: 999px;
  padding: 4px 12px;
  margin: 0 0 4px;
}
.set-affects-pill a {
  color: var(--ink, #1c1917);
  text-decoration: none;
  border-bottom: 1px solid rgba(0,0,0,0.18);
}
.set-affects-pill a:hover { border-bottom-color: rgba(0,0,0,0.5); }
/* Hairline-divided horizontal flex rows. Label + sub-description on the left,
   control on the right. */
.set-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 32px;
  padding: 18px 0;
  border-bottom: 1px solid var(--hairline);
  margin: 0;
}
.set-row:last-child { border-bottom: none; }
.set-row-label {
  flex: 1;
  min-width: 0;
  max-width: 360px;
}
.set-row-name {
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 4px;
}
.set-row-sub {
  font-size: 0.82rem;
  color: var(--ink-mute);
  line-height: 1.5;
}
.set-row-control {
  flex-shrink: 0;
  min-width: 280px;
  max-width: 360px;
  text-align: right;
}
.set-row-control .set-input,
.set-row-control .set-select,
.set-row-control .set-textarea {
  text-align: left;
}
@media (max-width: 760px) {
  .set-row { flex-direction: column; gap: 8px; }
  .set-row-control { min-width: 0; max-width: 100%; width: 100%; text-align: left; }
}
/* Legacy .set-row.is-2col still used inside templates for two-input groupings —
   it wraps two .set-row children. Strip the outer's row chrome; let inner rows hairline. */
.set-row.is-2col {
  display: block;
  padding: 0;
  border-bottom: 0;
  gap: 0;
}
.set-row.is-2col > .set-row { padding: 18px 0; border-bottom: 1px solid var(--hairline); }
.set-row.is-2col > .set-row:last-child { border-bottom: none; }
.set-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.set-label {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 13px; letter-spacing: normal; text-transform: none;
  color: var(--ink-mute); font-weight: 500;
}
.set-input, .set-select {
  background: var(--cream-2);
  border: 0;
  border-radius: 8px;
  padding: 8px 12px;
  font-family: inherit; font-size: 0.9rem;
  color: var(--ink); width: 100%;
  transition: background 0.12s, box-shadow 0.12s;
}
.set-input:focus, .set-select:focus {
  outline: 0; background: var(--cream-3);
}
.set-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 4px 0; }
.set-chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--cream-2);
  border: 1px solid var(--hairline-2);
  color: var(--ink);
  font-family: inherit; font-size: 0.8rem;
  padding: 4px 10px; border-radius: 999px;
}
.set-chip-x {
  font-size: 0.95rem; color: var(--ink-faint);
  cursor: pointer; line-height: 1; user-select: none;
}
.set-chip-x:hover { color: var(--ink-mute); }
.set-chip-add {
  background: transparent;
  border: 1px dashed var(--hairline-2);
  color: var(--ink-mute);
  font-family: inherit; font-size: 0.8rem;
  padding: 4px 11px; border-radius: 999px;
  cursor: pointer;
}
.set-chip-add:hover { background: var(--cream-2); color: var(--ink); }
.set-pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.56rem; letter-spacing: 0.16em; text-transform: uppercase;
  font-weight: 600;
  color: var(--green); background: var(--green-soft);
  padding: 3px 8px; border-radius: 5px;
  margin-top: 4px; align-self: flex-start;
}
.set-pill::before {
  content: ''; width: 5px; height: 5px;
  border-radius: 50%; background: var(--green);
}
.set-pill.is-warn {
  color: var(--accent-orange, #D57529);
  background: rgba(213, 117, 41, 0.12);
}
.set-pill.is-warn::before { background: var(--accent-orange, #D57529); }
.set-pill.is-mute {
  color: var(--ink-mute);
  background: rgba(0, 0, 0, 0.05);
}
.set-pill.is-mute::before { background: var(--ink-mute); }
.set-pill.is-inline {
  margin-top: 0; margin-left: 8px; vertical-align: middle;
  align-self: center;
}
/* ── Plan & billing redesign ────────────────────────────────────────
   Sectioned layout, no dividers — whitespace only. Floating line-art
   icon (no card). Bordered ghost CTAs except the single red filled
   Cancel button. Matches Anthropic-billing aesthetic on warm-stone
   tokens.                                                            */
/* Two-column header: current plan (left) + status (right, free-tier only).
   Hydrator adds .is-single-col when plan !== free so the left card spans
   the full width on paid tiers. */
.set-billing-header {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 14px;
  padding: 4px 0 24px;
  border-bottom: 1px solid var(--hairline);
}
.set-billing-header.is-single-col {
  grid-template-columns: minmax(0, 1fr);
}
.set-billing-header-card {
  padding: 18px 20px;
  background: var(--paper, #FBFBFB);
  border: 1px solid var(--hairline, rgba(31,22,17,0.08));
  border-radius: 12px;
  display: flex; flex-direction: column; gap: 12px;
}
.set-billing-header-card--plan {
  flex-direction: row;
  align-items: center; justify-content: space-between;
  gap: 16px;
}
.set-billing-header-card-body {
  display: flex; flex-direction: column; gap: 3px;
  min-width: 0; flex: 1;
}
.set-billing-header-plan {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 1.4rem; font-weight: 600; color: var(--ink);
  letter-spacing: -0.012em; line-height: 1.18; margin: 0;
}
.set-billing-header-tagline {
  font-size: 0.96rem; color: var(--ink); margin: 4px 0 0;
  line-height: 1.45;
}
.set-billing-header-sub {
  font-size: 0.88rem; color: var(--ink-mute); margin: 0;
}
.set-billing-header-sub.is-warn { color: var(--accent-orange, #D57529); }
/* Status card sub-states (free tier only): default = credits + bar,
   warn = out-of-credits + upgrade CTA. */
.set-billing-status-title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 0.95rem; font-weight: 600; color: var(--ink);
  margin: 0 0 4px; letter-spacing: -0.005em;
}
.set-billing-status-title.is-warn { color: var(--orange-deep, #B8420F); }
.set-billing-status-warn { display: flex; flex-direction: column; gap: 10px; }
.set-billing-status-warn-sub {
  margin: 0; font-size: 0.9rem; line-height: 1.5; color: var(--ink-mute);
  max-width: 44ch;
}

.set-billing-section {
  padding: 28px 0;
  border-bottom: 1px solid var(--hairline);
}
.set-billing-section:last-of-type { border-bottom: 0; }
.set-billing-section-title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 0.98rem; font-weight: 600; color: var(--ink);
  margin: 0 0 18px; letter-spacing: -0.005em;
}
.set-billing-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
}
/* Free-tier credit display. Numbers are large + readable; bar is a thin
   warm-stone progress strip. No emojis, no greens — pure tradie tradesman
   stone palette per memory feedback rules. */
.set-billing-credits { display: flex; flex-direction: column; gap: 10px; }
.set-billing-credits-numbers {
  display: flex; align-items: baseline; gap: 8px;
  font-family: 'Geist', 'Inter Tight', sans-serif;
}
.set-billing-credits-remaining {
  font-size: 1.85rem; font-weight: 600; color: var(--ink);
  letter-spacing: -0.024em; line-height: 1;
}
.set-billing-credits-total { font-size: 0.95rem; color: var(--ink-mute); }
.set-billing-credits-bar {
  position: relative; height: 6px; border-radius: 999px;
  background: var(--cream-2, #F0F0F0);
  overflow: hidden;
}
.set-billing-credits-bar-fill {
  position: absolute; left: 0; top: 0; bottom: 0;
  background: var(--orange, #D9541E);
  width: 100%;
  border-radius: inherit;
  transition: width 0.32s cubic-bezier(0.2, 0.9, 0.3, 1.0);
}
.set-billing-credits-help {
  margin: 0; font-size: 0.86rem; line-height: 1.5;
  color: var(--ink-mute);
  max-width: 56ch;
}
/* Two-card upgrade row. Pro card has the warm-orange accent so it visually
   draws the eye, matching the pricing page Most-Popular treatment. */
.set-billing-upgrade-row {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}
@media (max-width: 720px) {
  .set-billing-upgrade-row { grid-template-columns: 1fr; }
}
.set-billing-upgrade-card {
  display: flex; flex-direction: column; gap: 8px;
  padding: 18px 20px;
  background: var(--paper, #FBFBFB);
  border: 1px solid var(--hairline, rgba(31,22,17,0.08));
  border-radius: 12px;
  text-decoration: none; color: inherit;
  transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}
.set-billing-upgrade-card:hover {
  transform: translateY(-2px);
  border-color: var(--hairline-2, rgba(31,22,17,0.14));
  box-shadow: 0 1px 2px rgba(31,22,17,0.05), 0 18px 36px -16px rgba(31,22,17,0.12);
}
.set-billing-upgrade-card--pro {
  border-color: rgba(217, 84, 30, 0.32);
  background: linear-gradient(180deg, rgba(217,84,30,0.04), transparent 60%), var(--paper, #FBFBFB);
}
.set-billing-upgrade-card-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
}
.set-billing-upgrade-card-name {
  font-family: 'Geist', 'Inter Tight', sans-serif;
  font-size: 1.05rem; font-weight: 600; color: var(--ink);
}
.set-billing-upgrade-card-price {
  font-family: 'Geist', 'Inter Tight', sans-serif;
  font-size: 0.92rem; font-weight: 500; color: var(--ink-mute);
}
.set-billing-upgrade-card-sub {
  margin: 0; font-size: 0.9rem; line-height: 1.5; color: var(--ink-mute);
}
.set-billing-upgrade-card-cta {
  margin-top: 6px;
  font-family: 'Geist', 'Inter Tight', sans-serif;
  font-size: 0.88rem; font-weight: 500;
  color: var(--orange-deep, #B8420F);
}
.set-billing-upgrade-card--pro .set-billing-upgrade-card-cta { color: var(--orange, #D9541E); }

.set-billing-pay {
  display: flex; align-items: center; gap: 12px; min-width: 0;
}
.set-billing-pay-icon {
  width: 32px; height: 22px; border-radius: 4px;
  background: var(--cream, #FAFAFA);
  border: 1px solid var(--hairline-2, rgba(31,22,17,0.14));
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--ink-mute); flex-shrink: 0;
  overflow: hidden;
}
.set-billing-pay-icon--visa     { background: #1A1F71; border-color: #1A1F71; color: #fff; }
.set-billing-pay-icon--amex     { background: #006FCF; border-color: #006FCF; color: #fff; }
.set-billing-pay-icon--mc       { background: #fff; border-color: var(--hairline-2, rgba(31,22,17,0.14)); }
.set-billing-pay-icon--link     { background: #00D924; border-color: #00D924; color: #1F1611; }
.set-billing-pay-icon-text {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-weight: 800; font-size: 0.56rem; letter-spacing: 0.06em;
  line-height: 1;
}
.set-billing-pay-icon-mc-dots {
  display: inline-flex; align-items: center;
}
.set-billing-pay-icon-mc-dots span {
  width: 11px; height: 11px; border-radius: 50%; display: inline-block;
}
.set-billing-pay-icon-mc-dots span:first-child {
  background: #EB001B;
}
.set-billing-pay-icon-mc-dots span:last-child {
  background: #F79E1B; margin-left: -4px; opacity: 0.92;
}
.set-billing-pay-text {
  font-size: 0.94rem; color: var(--ink);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
}

/* Ghost (bordered) button — canonical pattern from
   landing-frontier.html .btn-ghost: --hairline-2 border, ink hover. */
.set-btn-ghost {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 0.88rem; font-weight: 500; color: var(--ink);
  background: #fff;
  border: 1px solid var(--hairline-2, rgba(31,22,17,0.14));
  border-radius: 6px; padding: 8px 16px;
  cursor: pointer; transition: border-color .12s ease, background .12s ease;
  white-space: nowrap;
  box-shadow: 0 1px 0 rgba(255,255,255,0.4) inset;
}
.set-btn-ghost:hover  { border-color: var(--ink); background: rgba(255,255,255,0.6); }
.set-btn-ghost:disabled { opacity: 0.55; cursor: not-allowed; }

/* Warm primary — orange-filled CTA. Used for upgrade flows
   (out-of-credits, add-payment-method). Sits alongside the bordered
   ghost button + filled danger as the third button shape. */
.set-btn-primary-warm {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 0.9rem; font-weight: 500; color: #fff;
  background: var(--orange, #D9541E);
  border: 1px solid var(--orange, #D9541E);
  border-radius: 6px; padding: 9px 18px;
  cursor: pointer; transition: background .12s ease, border-color .12s ease;
  white-space: nowrap;
  text-decoration: none;
  align-self: flex-start;
}
.set-btn-primary-warm:hover {
  background: var(--orange-deep, #B8420F);
  border-color: var(--orange-deep, #B8420F);
}
.set-btn-primary-warm:disabled { opacity: 0.55; cursor: not-allowed; }

/* No-card payment sub-state — explicit "Add a payment method" affordance
   when /api/billing/card returns no last4. Replaces the previous "—"
   placeholder that read as broken. */
.set-billing-payment-none {
  display: flex; flex-direction: column; gap: 12px;
  align-items: flex-start;
}
.set-billing-payment-none-text {
  margin: 0; font-size: 0.92rem; line-height: 1.5;
  color: var(--ink-mute); max-width: 60ch;
}

/* Filled danger — the only red filled button on the page. Cancel
   subscription. Warm red rather than primary-bright. */
.set-btn-danger-filled {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 0.88rem; font-weight: 500; color: #fff;
  background: #B8421F;
  border: 1px solid #B8421F;
  border-radius: 6px; padding: 8px 18px;
  cursor: pointer; transition: background .12s ease;
  white-space: nowrap;
}
.set-btn-danger-filled:hover { background: #9A361A; border-color: #9A361A; }
.set-btn-danger-filled:disabled { opacity: 0.55; cursor: not-allowed; }

/* Invoices table — hairline-separated rows, generous spacing. */
.set-billing-invoices { display: flex; flex-direction: column; }
.set-invoice-grid {
  display: grid;
  grid-template-columns: minmax(110px, 1.2fr) minmax(90px, 1fr) minmax(70px, 0.8fr) auto;
  align-items: center; gap: 14px;
  padding: 11px 0;
  border-bottom: 1px solid var(--hairline);
  font-size: 0.92rem;
}
.set-invoice-grid:last-child { border-bottom: 0; }
.set-invoice-grid--head {
  padding: 2px 0 11px;
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 0.78rem; font-weight: 500;
  color: var(--ink-mute); letter-spacing: 0;
  border-bottom: 1px solid var(--hairline);
}
.set-invoice-date {
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
}
.set-invoice-amount {
  color: var(--ink); font-weight: 500;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
}
.set-invoice-status { color: var(--ink); }
.set-invoice-link {
  font-size: 0.88rem; color: var(--ink);
  text-decoration: underline; text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: opacity .12s ease;
  justify-self: end;
}
.set-invoice-link:hover { opacity: 0.7; }
.set-invoice-empty {
  padding: 14px 0; color: var(--ink-mute);
  font-size: 0.9rem;
}

@media (max-width: 720px) {
  .set-billing-header {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 12px;
  }
  .set-billing-header-card--plan {
    flex-direction: column;
    align-items: flex-start;
  }
  .set-billing-header-card--plan .set-btn-ghost { align-self: flex-start; }
}
@media (max-width: 640px) {
  .set-invoice-grid { grid-template-columns: 1fr auto; gap: 6px 14px; }
  .set-invoice-grid--head { display: none; }
  .set-invoice-amount { grid-column: 2; text-align: right; }
}

/* ── Stacked form field block ──────────────────────────────────────
   Label above, input below, full-width up to 480px max. Hairline
   between blocks. Replaces .set-row "label-left + input-right-fixed-
   width" pattern on tabs that benefit from a cleaner vertical
   rhythm (Business identity, etc.).                               */
.set-stack {
  padding: 20px 0;
  border-bottom: 1px solid var(--hairline);
}
.set-stack:last-child { border-bottom: 0; }
.set-stack-label {
  display: block;
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 0.86rem; font-weight: 500;
  color: var(--ink-mute);
  margin: 0 0 10px;
}
.set-stack > .set-input,
.set-stack > .set-select {
  width: 100%; max-width: 480px;
}
.set-stack-help {
  display: block;
  font-size: 0.82rem; color: var(--ink-mute);
  margin-top: 8px; max-width: 480px;
}
.set-stack-2col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  padding: 20px 0;
  border-bottom: 1px solid var(--hairline);
}
.set-stack-2col:last-child { border-bottom: 0; }
.set-stack-cell { display: flex; flex-direction: column; }
.set-stack-cell .set-stack-label { margin-bottom: 10px; }
.set-stack-cell .set-input,
.set-stack-cell .set-select { width: 100%; }
@media (max-width: 640px) {
  .set-stack-2col { grid-template-columns: 1fr; gap: 16px; }
}
.set-logo-row {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.set-logo-preview {
  width: 44px; height: 44px; border-radius: 8px;
  background: var(--ink, #1F1611);
  display: flex; align-items: center; justify-content: center;
  color: var(--paper, #fff); font-weight: 600; font-size: 1rem;
  overflow: hidden; flex-shrink: 0;
}
.set-logo-preview img { width: 100%; height: 100%; object-fit: cover; display: block; }
.set-logo-help { font-size: 0.82rem; color: var(--ink-mute); }
.set-link {
  background: transparent; border: 0;
  color: var(--ink-mute); font-family: inherit; font-size: 0.84rem;
  cursor: pointer; padding: 0;
  text-decoration: underline;
  text-decoration-color: var(--hairline-2);
  text-underline-offset: 3px;
}
.set-link:hover { color: var(--ink); text-decoration-color: var(--ink-mute); }
.set-account-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap;
}
.set-account-row + .set-account-row {
  margin-top: 12px; padding-top: 12px;
  border-top: 1px solid var(--hairline);
}
.set-account-label {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 13px; letter-spacing: normal; text-transform: none;
  color: var(--ink-mute); font-weight: 500;
  margin-bottom: 3px;
}
.set-account-val { font-size: 0.9rem; color: var(--ink); }
/* Sticky save bar at the bottom of every settings tab. Inline-style
   was stripped from the renderer; chrome lives here so it can be
   tuned without touching JS. Mobile media block in dashboard-v2.css
   stacks the bar vertically and adds horizontal margin so it sits
   inside the page padding. */
.set-actions {
  position: sticky;
  bottom: 12px;
  background: rgba(255, 255, 255, 0.96);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
  border: 1px solid var(--hairline-2);
  border-radius: 12px;
  padding: 10px 14px;
  box-shadow: 0 4px 12px rgba(31, 22, 17, 0.06);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 4px 0 0;
}
[data-theme="dark"] .set-actions {
  background: rgba(20, 16, 14, 0.96);
}
.btn-primary.is-disabled, .btn-ghost.is-disabled { opacity: 0.55; cursor: not-allowed; }
.btn-primary.is-disabled:hover { background: var(--ink); border-color: var(--ink); }
.btn-ghost.is-disabled:hover   { background: transparent; border-color: var(--hairline-2); }
.set-textarea {
  background: var(--cream-2);
  border: 0;
  border-radius: 8px;
  padding: 10px 12px;
  font-family: inherit; font-size: 0.9rem;
  color: var(--ink); width: 100%;
  resize: vertical;
  min-height: 84px;
  line-height: 1.5;
  transition: background 0.12s;
}
.set-textarea:focus { outline: 0; background: var(--cream-3); }
.set-help { font-size: 0.78rem; color: var(--ink-mute); margin-top: 2px; line-height: 1.5; }
.set-help.is-warn { color: var(--orange-deep); }
.set-switch {
  position: relative;
  display: inline-block;
  width: 38px; height: 22px;
  flex-shrink: 0;
}
.set-switch input { opacity: 0; width: 0; height: 0; }
.set-switch-slider {
  position: absolute; cursor: pointer; inset: 0;
  background: var(--cream-3);
  border-radius: 999px;
  transition: background 0.18s;
}
.set-switch-slider::before {
  content: ''; position: absolute;
  height: 16px; width: 16px;
  left: 3px; top: 3px;
  background: #fff; border-radius: 50%;
  transition: transform 0.18s;
  box-shadow: 0 1px 2px rgba(31, 22, 17, 0.2);
}
.set-switch input:checked + .set-switch-slider { background: var(--blue); }
.set-switch input:checked + .set-switch-slider::before { transform: translateX(16px); }
/* Usage progress bars + appearance toggle (Profile/Preferences/Usage sections) */
.usage-row { display: flex; flex-direction: column; gap: 6px; }
.usage-bar {
  height: 4px;
  background: var(--cream-3, rgba(31, 22, 17, 0.08));
  border-radius: 999px;
  overflow: hidden;
}
.usage-bar-fill {
  height: 100%;
  background: var(--ink, #1F1611);
  border-radius: 999px;
  transition: width 0.4s cubic-bezier(0.2, 0, 0, 1);
}
.usage-meta {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.72rem;
  color: var(--ink-mute, #6B5A4C);
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}
.appearance-toggle {
  display: inline-flex;
  background: var(--cream-2);
  border-radius: 8px;
  padding: 3px;
  gap: 2px;
}
.appearance-toggle button {
  background: transparent;
  border: 0;
  width: 32px; height: 28px;
  border-radius: 6px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--ink-mute);
  cursor: pointer;
  transition: background 0.18s cubic-bezier(0.2, 0, 0, 1), color 0.18s cubic-bezier(0.2, 0, 0, 1);
}
.appearance-toggle button:hover { color: var(--ink); }
.appearance-toggle button.is-on {
  background: var(--paper, #fff);
  color: var(--ink);
  box-shadow: 0 1px 2px rgba(31, 22, 17, 0.08);
}
.appearance-toggle button svg { width: 14px; height: 14px; }
/* Lead capture: segmented CTA chooser (mirrors .appearance-toggle structure). */
.cta-toggle {
  display: inline-flex;
  background: var(--cream-2);
  border-radius: 8px;
  padding: 3px;
  gap: 2px;
}
.cta-toggle button {
  background: transparent; border: 0;
  padding: 6px 12px;
  font-family: inherit; font-size: 0.85rem;
  color: var(--ink-mute);
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.18s cubic-bezier(0.2, 0, 0, 1);
}
.cta-toggle button:hover { color: var(--ink); }
.cta-toggle button.is-on {
  background: var(--paper, #fff);
  color: var(--ink);
  font-weight: 500;
  box-shadow: 0 1px 2px rgba(31, 22, 17, 0.06);
}
/* Tier-only reveal: hidden by default, shown when body[data-tier] matches
   the block's data-plan attribute. Set by dashboard-v2.js after the
   data-plan reveal pass.

   We match data-plan with attribute-contains (~"=") OR substring (*=) so a
   block tagged data-plan="recovery,recovery-only" shows for both tiers and
   data-plan="builder" shows only on Builder. This keeps the lead-capture
   page Builder-tier-clean (email-only) and Recovery-tier-rich (SMS screener
   block visible) without either tier seeing the other tier's controls. */
.set-tier-only { display: none; }
body[data-tier="builder"]       .set-tier-only[data-plan*="builder"],
body[data-tier="recovery"]      .set-tier-only[data-plan*="recovery"],
body[data-tier="recovery-only"] .set-tier-only[data-plan*="recovery-only"] { display: block; }
.set-tier-pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.6rem; letter-spacing: 0.16em; text-transform: uppercase;
  font-weight: 600;
  color: var(--orange);
  background: var(--orange-wash, rgba(217, 84, 30, 0.08));
  padding: 3px 8px;
  border-radius: 999px;
  margin-bottom: 10px;
}
.set-tier-divider {
  margin: 28px 0 18px;
  padding-top: 24px;
  border-top: 1px dashed var(--hairline-2);
}
.set-quiet-hours {
  display: inline-flex; align-items: center; gap: 8px;
}
.set-quiet-hours input[type="time"] {
  font-family: inherit;
}
.set-quiet-hours .qh-sep {
  color: var(--ink-mute);
  font-size: 0.85rem;
}
.set-avatar-circle {
  width: 44px; height: 44px;
  border-radius: 50%;
  background: var(--ink, #1F1611);
  color: var(--paper, #fff);
  display: inline-flex; align-items: center; justify-content: center;
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-weight: 600;
  font-size: 1.1rem;
  flex-shrink: 0;
}
.set-toggle-row {
  display: flex; align-items: flex-start;
  justify-content: space-between;
  gap: 16px; padding: 10px 0;
}
.set-toggle-row + .set-toggle-row { border-top: 1px solid var(--hairline); }
.set-toggle-text { flex: 1; min-width: 0; }
.set-toggle-name { font-size: 0.92rem; color: var(--ink); font-weight: 500; margin-bottom: 2px; }
.set-toggle-desc { font-size: 0.8rem; color: var(--ink-mute); line-height: 1.45; }
.set-hours-row {
  display: grid;
  grid-template-columns: 90px 1fr 14px 1fr 28px;
  gap: 10px; align-items: center;
  padding: 6px 0;
}
.set-hours-row + .set-hours-row { border-top: 1px solid var(--hairline); }
.set-hours-day { font-size: 0.88rem; color: var(--ink); font-weight: 500; }
.set-hours-sep { font-size: 0.78rem; color: var(--ink-faint); text-align: center; }
.set-hours-x {
  font-size: 0.86rem; color: var(--ink-faint);
  background: transparent; border: 0; cursor: pointer;
  padding: 2px 4px;
}
.set-hours-x:hover { color: var(--ink-mute); }
.set-hours-closed-row .set-hours-closed {
  color: var(--ink-faint); font-size: 0.84rem; font-style: italic;
  grid-column: 2 / 5;
}
.set-tier-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 28px;
  gap: 10px; align-items: center;
  padding: 6px 0;
}
.set-tier-row + .set-tier-row { border-top: 1px solid var(--hairline); }
.set-tier-row-head {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 28px;
  gap: 10px; padding: 6px 0;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.54rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 600;
  border-bottom: 1px solid var(--hairline);
}
.set-add-row {
  background: transparent;
  border: 1px dashed var(--hairline-2);
  color: var(--ink-mute);
  font-family: inherit; font-size: 0.84rem;
  padding: 8px 12px; border-radius: 8px;
  cursor: pointer;
  margin-top: 8px;
  width: 100%;
  text-align: left;
}
.set-add-row:hover { background: var(--cream-2); color: var(--ink); }
.set-tone-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
@media (max-width: 640px) { .set-tone-row { grid-template-columns: 1fr; } }
.set-tone-card {
  background: var(--cream);
  border: 1px solid var(--hairline-2);
  border-radius: 10px;
  padding: 10px 12px;
  cursor: pointer;
  display: flex; flex-direction: column; gap: 4px;
  transition: border-color 0.12s, background 0.12s;
}
.set-tone-card:hover { background: var(--paper); border-color: var(--ink-faint); }
.set-tone-card.is-on { background: var(--paper); border-color: var(--ink); }
.set-tone-name { font-size: 0.92rem; color: var(--ink); font-weight: 600; }
.set-tone-eg { font-size: 0.78rem; color: var(--ink-mute); line-height: 1.4; font-style: italic; }
.set-color-row { display: flex; align-items: center; gap: 12px; }
.set-color-sw {
  width: 36px; height: 36px;
  border-radius: 8px;
  border: 1px solid var(--hairline-2);
  flex-shrink: 0;
}
.set-danger {
  background: rgba(217, 84, 30, 0.04);
  border: 1px solid rgba(217, 84, 30, 0.18);
  border-radius: 10px;
  padding: 14px 16px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
}
.set-danger + .set-danger { margin-top: 10px; }
.set-danger-text strong { color: var(--orange-deep); font-weight: 600; }
.set-danger-text { font-size: 0.86rem; color: var(--ink); line-height: 1.45; max-width: 460px; }
.set-btn-danger {
  background: transparent;
  border: 1px solid var(--orange);
  color: var(--orange);
  font-family: inherit; font-size: 0.86rem; font-weight: 500;
  padding: 8px 14px; border-radius: 8px;
  cursor: pointer; flex-shrink: 0;
  transition: background 0.12s, color 0.12s;
}
.set-btn-danger:hover { background: var(--orange); color: #fff; }
.set-mini-intg {
  display: flex; flex-direction: column; gap: 4px;
}
.set-mini-intg-row {
  display: flex; justify-content: flex-start; align-items: center;
  gap: 12px;
  padding: 14px 0;
  font-size: 0.92rem;
}
.set-mini-intg-row + .set-mini-intg-row { border-top: 1px solid var(--hairline); }
.set-mini-intg-logo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 28px;
  flex-shrink: 0;
}
.set-mini-intg-logo svg,
.set-mini-intg-logo img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
.set-mini-intg-text {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 2px;
}
.set-mini-intg-name { color: var(--ink); font-weight: 500; }
.set-mini-intg-sub {
  font-size: 0.78rem;
  color: var(--ink-faint);
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 400;
}
.set-mini-intg-sub:empty { display: none; }
/* Legacy mono caps status — kept for backwards compat but hidden;
   the CTA pill now conveys connection state directly. */
.set-mini-intg-status { display: none; }
.set-mini-intg-cta {
  display: inline-flex; align-items: center;
  flex-shrink: 0;
}
.set-mini-intg-connect,
.set-mini-intg-disconnect {
  font-family: inherit; font-size: 0.86rem; font-weight: 600;
  padding: 7px 14px; border-radius: 999px;
  text-decoration: none; cursor: pointer;
  letter-spacing: -0.005em;
  border: 1px solid var(--hairline);
  background: transparent;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
  white-space: nowrap;
}
.set-mini-intg-connect {
  color: var(--cream, #FAFAFA);
  background: var(--ink, #1F1611);
  border-color: var(--ink, #1F1611);
}
.set-mini-intg-connect:hover {
  background: var(--ink-2, #2A1F17);
  color: var(--cream, #FAFAFA);
}
.set-mini-intg-disconnect {
  color: var(--ink-soft);
  background: transparent;
}
.set-mini-intg-disconnect:hover {
  color: var(--ink);
  background: rgba(27, 22, 16, 0.05);
}
.set-mini-intg-disconnect:disabled {
  opacity: 0.5; cursor: default;
}
.set-mini-intg-muted {
  font-size: 0.78rem;
  color: var(--ink-faint);
  font-weight: 500;
  letter-spacing: -0.005em;
}

/* Notifications */
.ntf-card {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--card-radius);
  padding: 12px var(--card-pad) 18px;
  transition: border-color 0.18s cubic-bezier(0.2, 0, 0, 1);
}
.ntf-card:hover { border-color: var(--hairline-2); }
.ntf-section {
  padding: 16px 0 10px;
  border-bottom: 1px solid var(--hairline);
}
.ntf-section:last-child { border-bottom: 0; }
.ntf-section-title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 1.02rem; font-weight: 600;
  color: var(--ink); margin: 0 0 4px;
}
.ntf-head {
  display: grid;
  grid-template-columns: 1fr 64px 64px 64px;
  gap: 10px; padding: 10px 0;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.54rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 600;
  border-bottom: 1px solid var(--hairline);
}
.ntf-head span:not(:first-child) { text-align: center; }
.ntf-row {
  display: grid;
  grid-template-columns: 1fr 64px 64px 64px;
  gap: 10px; padding: 12px 0;
  align-items: center;
  border-bottom: 1px solid var(--hairline);
}
.ntf-row:last-child { border-bottom: 0; }
.ntf-row-name { font-size: 0.9rem; color: var(--ink); font-weight: 500; }
.ntf-row-cell { display: flex; align-items: center; justify-content: center; }
@media (max-width: 640px) {
  .ntf-head { display: none; }
  .ntf-row { grid-template-columns: 1fr; gap: 6px; padding: 14px 0; }
  .ntf-row-cell { justify-content: space-between; padding: 4px 0; }
  .ntf-row-cell::before {
    content: attr(data-channel);
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.58rem; letter-spacing: 0.16em; text-transform: uppercase;
    color: var(--ink-faint); font-weight: 600;
  }
}
.ntf-toggle {
  width: 38px; height: 20px;
  background: var(--cream-2);
  border: 1px solid var(--hairline-2);
  border-radius: 999px;
  position: relative; cursor: pointer;
  transition: background 0.18s, border-color 0.18s;
  padding: 0;
}
.ntf-toggle::after {
  content: '';
  position: absolute; top: 1px; left: 1px;
  width: 16px; height: 16px;
  background: #fff;
  border-radius: 50%;
  box-shadow: 0 1px 2px rgba(31, 22, 17, 0.18);
  transition: transform 0.18s;
}
.ntf-toggle.is-on { background: var(--ink); border-color: var(--ink); }
.ntf-toggle.is-on::after { transform: translateX(18px); }
.ntf-toggle.is-na { opacity: 0.32; cursor: not-allowed; }

.ntf-quiet {
  background: var(--cream);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 14px 18px;
  margin-top: 16px;
  display: flex; align-items: center; gap: 16px;
  flex-wrap: wrap;
}
.ntf-quiet-text { flex: 1 1 240px; }
.ntf-quiet-title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 0.98rem; font-weight: 600;
  color: var(--ink);
}
.ntf-quiet-meta {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.58rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-faint); margin-top: 3px;
}
.ntf-quiet-range {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.74rem;
  background: var(--paper);
  border: 1px solid var(--hairline-2);
  border-radius: 8px;
  padding: 7px 12px;
  color: var(--ink); letter-spacing: 0.06em;
}

/* ============================================================================
   Job types page — list of per-job-type configuration cards
   ========================================================================== */
.jt-list { display: flex; flex-direction: column; gap: 12px; margin-top: 14px; }
.jt-card {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--card-radius);
  padding: var(--card-pad);
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) auto;
  grid-template-rows: auto auto auto auto;
  gap: 4px 14px;
  align-items: start;
  transition: border-color 0.18s cubic-bezier(0.2, 0, 0, 1), background 0.18s cubic-bezier(0.2, 0, 0, 1);
}
.jt-card:hover {
  border-color: var(--hairline-2);
}
.jt-card.is-fallback {
  background: transparent;
  border: 1px dashed var(--hairline-2);
}
.jt-icon {
  grid-row: 1 / 3;
  width: 44px; height: 44px;
  border-radius: 10px;
  background: var(--cream-2);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--ink-mute);
  flex: 0 0 auto;
}
.jt-icon svg { width: 22px; height: 22px; }
.jt-card.is-fallback .jt-icon { background: var(--cream-2); color: var(--ink-mute); }
.jt-head {
  grid-column: 2;
  grid-row: 1;
  min-width: 0;
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
}
.jt-name {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 1.06rem; font-weight: 600;
  color: var(--ink); letter-spacing: -0.01em;
  margin: 0;
}
.jt-pill {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.56rem; letter-spacing: 0.14em; text-transform: uppercase;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 5px;
}
.jt-pill.is-auto    { background: var(--green-soft); color: var(--green); }
.jt-pill.is-manual  { background: var(--cream-2); color: var(--ink-mute); }
.jt-pill.is-after   { background: var(--cream-2); color: var(--ink-mute); }
.jt-pill.is-emerg   { background: var(--cream-2); color: var(--ink-mute); }

.jt-stats {
  grid-column: 2;
  grid-row: 2;
  display: flex; gap: 14px; flex-wrap: wrap;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.62rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 500;
  margin-top: 3px;
}
.jt-stats strong {
  color: var(--ink);
  font-weight: 700;
  letter-spacing: 0.04em;
}
.jt-stats .dot {
  display: inline-block; width: 3px; height: 3px;
  border-radius: 50%; background: var(--hairline-3);
  align-self: center;
}

.jt-actions {
  grid-column: 3;
  grid-row: 1 / 3;
  display: flex; gap: 6px; align-items: center;
  align-self: start;
}
.jt-action {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 7px 11px;
  font-family: inherit; font-size: 0.78rem; font-weight: 500;
  border-radius: 8px;
  border: 1px solid var(--hairline-2);
  background: transparent; color: var(--ink);
  cursor: pointer; text-decoration: none;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.jt-action:hover { background: var(--cream-2); border-color: var(--hairline-3); }
.jt-action.is-quiet { color: var(--ink-mute); }
.jt-action.is-danger:hover { color: var(--orange); border-color: var(--orange-deep); }

.jt-fields {
  grid-column: 2 / 4;
  grid-row: 3;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--hairline);
}
@media (max-width: 760px) {
  .jt-fields { grid-template-columns: repeat(2, 1fr); }
}
.jt-field {
  display: flex; flex-direction: column; gap: 4px;
  min-width: 0;
}
.jt-field-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.56rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-mute); font-weight: 600;
}
.jt-field-value {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 0.94rem; font-weight: 500;
  color: var(--ink);
  display: flex; align-items: center; gap: 8px;
  min-height: 26px;
}
.jt-field-value.is-toggle { gap: 10px; }

.jt-keywords {
  grid-column: 2 / 4;
  grid-row: 4;
  display: flex; align-items: center; gap: 10px;
  flex-wrap: wrap;
  margin-top: 12px;
}
.jt-keywords-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.56rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-mute); font-weight: 600;
  flex: 0 0 auto;
}
.jt-keyword {
  background: var(--cream-2);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 4px 11px;
  font-size: 0.78rem;
  color: var(--ink);
  font-family: 'JetBrains Mono', monospace;
  letter-spacing: 0.02em;
}
.jt-keyword.is-add {
  background: transparent;
  border-style: dashed;
  color: var(--ink-faint);
  cursor: pointer;
}
.jt-keyword.is-add:hover { color: var(--orange); border-color: var(--orange); }

/* Per-job-type direct-booking toggle + bookable-price row */
.jt-booking-row {
  grid-column: 2 / 4;
  grid-row: 5;
  border-top: 1px solid var(--hairline);
  margin-top: 12px;
  padding-top: 8px;
}
.jt-price-row {
  display: grid;
  grid-template-columns: 140px 120px 1fr;
  gap: 12px;
  align-items: center;
  padding: 8px 0 4px;
}
.jt-price-row[data-hidden] { display: none; }
.jt-price-row label {
  font-size: 0.85rem; color: var(--ink-mute);
}
.jt-price-meta {
  font-size: 0.78rem; color: var(--ink-faint);
}
.jt-status-pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.58rem; letter-spacing: 0.14em; text-transform: uppercase;
  font-weight: 600;
  padding: 3px 8px; border-radius: 4px;
  margin-left: 8px;
}
.jt-status-pill.is-bookable { background: var(--green-soft); color: var(--green); }
.jt-status-pill.is-quote { background: var(--cream-3); color: var(--ink-mute); }


/* ==========================================================================
   AI builder split-pane styles — chat pane (left) + preview pane (right).
   Used by renderAiBuilder. Companion .builder-* rules also live in
   public/dashboard-v2.css.
   ========================================================================== */
.builder-preview-body {
  background: linear-gradient(135deg, oklch(15% 0.018 60) 0%, oklch(22% 0.02 38) 100%) !important;
  color: oklch(96% 0.02 80);
}
/* When the preview-body contains the editable template iframe, strip
   padding + centered layout so the iframe takes the full pane (same
   treatment as the published live-site iframe). The template iframe
   itself paints its own cream background, so the preview-body's dark
   linear-gradient stays hidden behind it. */
.builder-preview-body:has(iframe[data-builder-template-iframe]) {
  padding: 0 !important;
  background: var(--cream) !important;
  align-items: stretch !important;
  justify-content: stretch !important;
  display: block !important;
}
.builder-template-iframe {
  width: 100%;
  height: 100%;
  min-height: 100%;
  border: 0;
  display: block;
  background: var(--cream);
}
/* 2026-05-24: in cards-view the preview iframe is a non-interactive
   thumbnail — taps go to the card body for the zoom-back gesture,
   and the iframe's own swipe-forwarder must NOT fire (it would
   detect horizontal swipes on V5 content and postMessage them up,
   even though navSingleMode discards them in cards-view, the touches
   still scroll the iframe content which the founder reported as
   "I can swipe on the website page from the card view"). */
body.is-builder-cards-view .builder-template-iframe {
  pointer-events: none !important;
}
/* Sections-pane in single-mode: section-card list. Each .builder-
   sections-pane__item is a two-line card (label + preview snippet).
   Padding clears the 52px topbar at top + iOS Safari URL bar at
   bottom. Cards have hover lift + amber accent on tap (founder iter
   surface 2026-05-23). */
/* 2026-05-24 v2: the active-pane gate is restored (dropping it
   broke chat-mode containment — sections-pane styling started
   rendering in the chat view because the wrap is in flow even when
   inactive). Add a parallel is-builder-sliding selector so the
   styles ALSO apply during a pane slide, when the wrap is force-
   shown but the attribute still points at the from-pane. */
body:not(.is-builder-cards-view)[data-builder-active-pane="sections"] .builder-sections-pane__body,
body.is-builder-sliding:not(.is-builder-cards-view) .builder-sections-pane__body {
  padding: max(64px, env(safe-area-inset-top) + 64px) 16px max(env(safe-area-inset-bottom) + 90px, 110px) !important;
  background: var(--cream) !important;
}
body:not(.is-builder-cards-view)[data-builder-active-pane="sections"] .builder-sections-pane__item,
body.is-builder-sliding:not(.is-builder-cards-view) .builder-sections-pane__item {
  display: flex !important;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 14px 16px !important;
  border: 1px solid var(--hairline) !important;
  border-radius: 12px !important;
  background: #fff !important;
  transition: border-color 0.15s, box-shadow 0.15s;
}
body:not(.is-builder-cards-view)[data-builder-active-pane="sections"] .builder-sections-pane__item:hover,
body.is-builder-sliding:not(.is-builder-cards-view) .builder-sections-pane__item:hover {
  border-color: var(--ink-faint) !important;
}
/* 2026-05-24 dropdown previews — each section row collapses by
   default to [label + axis + A/B/C picker + chevron]. Tap the row
   to expand a clean iframe preview of just that section beneath
   the row. Only one row expanded at a time (siblings auto-collapse).
   Edits still happen in the main Preview pane (the "Open in
   preview" link inside the dropdown jumps + enters edit mode).
   is-builder-sliding selector duplicated below so the items keep
   their bg/border/radius DURING the slide too — otherwise the
   destination cards animate in without their styling and snap into
   look-correct only at slide-end. */
body:not(.is-builder-cards-view)[data-builder-active-pane="sections"] .builder-sections-pane__item,
body.is-builder-sliding:not(.is-builder-cards-view) .builder-sections-pane__item {
  display: block !important;
  padding: 0 !important;
  overflow: hidden;
  background: #fff !important;
  transition: box-shadow 0.18s ease;
}
body:not(.is-builder-cards-view)[data-builder-active-pane="sections"] .builder-sections-pane__item.is-open,
body.is-builder-sliding:not(.is-builder-cards-view) .builder-sections-pane__item.is-open {
  box-shadow: 0 8px 24px -8px rgba(31, 22, 17, 0.12);
}
.builder-sections-pane__item-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 14px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  background: transparent;
  border: 0;
  width: 100%;
  font: inherit;
}
.builder-sections-pane__item-row:hover { background: rgba(31, 22, 17, 0.02); }
.builder-sections-pane__item-main {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1 1 auto;
  text-align: left;
}
.builder-sections-pane__item-chev {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  color: var(--ink-mute, #6B5A4C);
  flex-shrink: 0;
  transition: transform 0.22s cubic-bezier(0.22, 1, 0.36, 1), color 0.15s;
}
.builder-sections-pane__item.is-open .builder-sections-pane__item-chev {
  transform: rotate(180deg);
  color: var(--accent, #FF5B00);
}

/* The dropdown preview frame — wraps an iframe of just this section
   (template-v5-variants.html?only=KEY). Iframe height is set via
   the postMessage height-back so it fits its section exactly, but
   capped at 360px for the list to stay scannable; taller sections
   get a fade-to-white at the bottom hinting "more in the preview". */
.builder-sections-pane__item-preview-drop {
  border-top: 1px solid var(--hairline, rgba(31,22,17,0.08));
  background: var(--paper-2, #F4F6FA);
  padding: 14px;
}
.builder-sections-pane__item-preview-drop[hidden] { display: none; }
.builder-sections-pane__item-preview-frame {
  position: relative;
  background: #fff;
  border-radius: 8px;
  border: 1px solid var(--rule, #DEE3EC);
  overflow: hidden;
  min-height: 120px;
  max-height: 360px;
}
.builder-sections-pane__item-preview-frame::after {
  /* Fade-to-white at the bottom — only visible when the iframe
     overflows the 360px cap. */
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 56px;
  background: linear-gradient(180deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.92) 92%);
  pointer-events: none;
  border-bottom-left-radius: 8px;
  border-bottom-right-radius: 8px;
}
.builder-sections-pane__item-preview-frame iframe {
  display: block;
  width: 100%;
  min-height: 120px;
  border: 0;
  pointer-events: none;
  background: #fff;
}
.builder-sections-pane__item-edit {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  margin-top: 12px;
  padding: 11px 14px;
  background: transparent;
  color: var(--ink, #16110A);
  border: 1px solid var(--rule-2, #C7CFDC);
  border-radius: 7px;
  font: inherit;
  font-size: 0.88rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
}
.builder-sections-pane__item-edit:hover {
  border-color: var(--accent, #FF5B00);
  background: var(--accent-soft, #FFF1E8);
  color: var(--accent-deep, #E04A00);
}

/* Variant picker — A/B/C buttons on the right side of each section row.
   Segmented-pill style; current pick is solid ink, others are quiet.
   Tap a button to update both the body data-attr (driving the preview
   iframe URL params) and the row's axis-description text below the
   section label. */
.builder-sections-pane__item-picker {
  display: flex;
  background: var(--paper-2, #F4F6FA);
  border-radius: 8px;
  padding: 3px;
  gap: 2px;
  flex-shrink: 0;
}
.builder-variant-btn {
  font: inherit;
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.05em;
  color: var(--ink-mute, #6B5A4C);
  background: transparent;
  border: 0;
  padding: 6px 11px;
  border-radius: 5px;
  cursor: pointer;
  min-width: 32px;
  transition: background 0.12s, color 0.12s;
}
.builder-variant-btn:hover {
  color: var(--ink);
  background: rgba(31, 22, 17, 0.04);
}
.builder-variant-btn.is-on {
  background: var(--ink, #16110A);
  color: #fff;
}
.builder-variant-btn.is-on:hover { background: var(--ink, #16110A); }

/* Form toggle (Quote / Booking) for hero + contact sections */
.builder-sections-pane__form-toggle {
  display: flex;
  gap: 8px;
  margin: 10px 16px 4px;
  padding: 0;
}
.builder-form-toggle-btn {
  font: inherit;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--ink-mute, #6B5A4C);
  background: var(--paper, #fff);
  border: 1.5px solid var(--hairline, rgba(31,22,17,0.10));
  padding: 7px 14px;
  border-radius: 8px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: background 0.15s, color 0.15s, border-color 0.15s, box-shadow 0.15s;
  box-shadow: 0 1px 2px rgba(31,22,17,0.04);
}
.builder-form-toggle-btn svg {
  flex-shrink: 0;
  opacity: 0.55;
  transition: opacity 0.15s;
}
.builder-form-toggle-btn:hover {
  border-color: var(--ink-soft, #8A7866);
  color: var(--ink, #16110A);
  box-shadow: 0 1px 4px rgba(31,22,17,0.08);
}
.builder-form-toggle-btn:hover svg { opacity: 0.8; }

/* Publish sheet */
.builder-publish-sheet {
  position: fixed; inset: 0; z-index: 9999;
  display: flex; align-items: flex-end; justify-content: center;
}
.builder-publish-sheet[hidden] { display: none !important; }
.builder-publish-sheet__backdrop {
  position: absolute; inset: 0;
  background: rgba(0,0,0,0.25);
}
.builder-publish-sheet__card {
  position: relative; z-index: 1;
  width: 100%; max-width: 420px;
  background: #fff;
  border-radius: 16px 16px 0 0;
  box-shadow: 0 -4px 24px rgba(0,0,0,0.12);
  overflow: hidden;
  animation: bs-pub-up 0.25s ease-out;
}
@keyframes bs-pub-up {
  from { transform: translateY(100%); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}
.builder-publish-sheet__header {
  display: flex; justify-content: space-between; align-items: center;
  padding: 20px 24px 0;
}
.builder-publish-sheet__title {
  font-size: 0.875rem; font-weight: 600; color: #171717; margin: 0;
  letter-spacing: -0.01em;
}
.builder-publish-sheet__close {
  background: none; border: 0; color: #bbb;
  cursor: pointer; padding: 2px; display: flex; border-radius: 6px;
}
.builder-publish-sheet__close:hover { color: #171717; background: #F5F5F5; }
.builder-publish-sheet__body { padding: 16px 24px 24px; }
/* Warning for existing live site */
.pub-warn {
  font-size: 0.8125rem; color: #666; line-height: 1.5;
  padding: 10px 12px; background: #FAFAFA; border-radius: 9px;
  margin-bottom: 14px;
}
.pub-warn strong { color: #171717; font-weight: 500; }
.pub-section { margin-bottom: 14px; }
.pub-label {
  font-size: 0.6875rem; font-weight: 500; color: #b5b0a8;
  margin-bottom: 5px; letter-spacing: 0.01em;
}
.pub-field {
  display: flex; align-items: center; height: 36px;
  border: 1px solid #e8e5e1; border-radius: 9px; overflow: hidden;
  margin-bottom: 4px;
}
.pub-field:focus-within { border-color: rgba(23,23,23,0.3); }
.pub-input {
  flex: 1; border: none; padding: 0 10px;
  font: inherit; font-size: 0.8125rem; color: #171717;
  outline: none; background: transparent; min-width: 0;
}
.pub-input::placeholder { color: #ccc; }
.pub-suffix {
  font-size: 0.6875rem; color: #b5b0a8;
  padding-right: 10px; white-space: nowrap; flex-shrink: 0;
}
.pub-hint { font-size: 0.6875rem; color: #ccc; }
/* Live URL strip */
.pub-live-url {
  display: flex; align-items: center; gap: 6px;
  padding: 9px 12px; background: #FAFAFA; border-radius: 9px;
  margin-bottom: 14px;
}
.pub-live-dot { width: 7px; height: 7px; border-radius: 50%; background: #16a34a; flex-shrink: 0; }
.pub-live-text { font-size: 0.8125rem; color: #171717; font-weight: 500; flex: 1; }
.pub-live-copy {
  font-size: 0.6875rem; color: #b5b0a8; font-weight: 500;
  background: none; border: none; cursor: pointer; font-family: inherit;
}
.pub-live-copy:hover { color: #171717; }
/* Action buttons */
.pub-actions { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.pub-btn-primary {
  width: 100%; height: 38px;
  border: 1px solid #171717; border-bottom-color: #0a0a0a; border-radius: 9px;
  background: linear-gradient(180deg, #2a2520, #171717);
  font: inherit; font-size: 0.8125rem; font-weight: 500; color: #fff;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(0,0,0,0.15), inset 0 1px 0 rgba(255,255,255,0.08);
}
.pub-btn-primary:hover { background: linear-gradient(180deg, #333, #1f1f1f); }
.pub-btn-primary:active { transform: translateY(0.5px); }
.pub-btn-primary:disabled { opacity: 0.6; cursor: wait; }
.pub-btn-secondary {
  width: 100%; height: 36px;
  border: 1px solid rgba(31,22,17,0.12); border-bottom-color: rgba(31,22,17,0.17); border-radius: 9px;
  background: linear-gradient(180deg, #fff, #F9F9F9);
  font: inherit; font-size: 0.8125rem; font-weight: 500; color: #171717;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(31,22,17,0.04), inset 0 1px 0 rgba(255,255,255,0.9);
}
.pub-btn-secondary:hover { border-color: rgba(31,22,17,0.2); }
.pub-btn-secondary:active { transform: translateY(0.5px); }
.pub-btn-danger {
  width: 100%; height: 36px; border-radius: 9px;
  background: #fff; color: #b91c1c; border: 1px solid #fecaca;
  font: inherit; font-size: 0.8125rem; font-weight: 500; cursor: pointer;
}
.pub-btn-danger:hover { background: #fef2f2; }
.pub-upsell {
  font-size: 0.75rem; color: #b5b0a8; text-align: center; margin-bottom: 0;
}
.pub-upsell a { color: #171717; font-weight: 500; text-decoration: none; }
.pub-upsell a:hover { text-decoration: underline; }
.pub-meta {
  font-size: 0.6875rem; color: #ccc; margin: 8px 0 0; text-align: center;
}
.builder-form-toggle-btn.is-on {
  background: var(--accent, #FF5B00);
  color: #fff;
  border-color: var(--accent, #FF5B00);
  box-shadow: 0 2px 6px rgba(255,91,0,0.2);
}
.builder-form-toggle-btn.is-on svg { stroke: #fff; }

.builder-sections-pane__item--variants .builder-sections-pane__item-main {
  min-width: 0;
}
.builder-sections-pane__item-preview[data-variant-axis] {
  /* The axis description swaps when the user picks a different variant
     so the row's preview text always reflects what they just picked.
     2026-06-03 (founder): non-italic to match the clean Templates tag style. */
  font-style: normal;
}
.builder-sections-pane__item-main {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  flex: 1 1 auto;
}
.builder-sections-pane__item-label {
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--ink);
}
.builder-sections-pane__item-preview {
  font-size: 0.78rem;
  color: var(--ink-mute);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
body:not(.is-builder-cards-view)[data-builder-active-pane="sections"] .builder-sections-pane__item svg,
body.is-builder-sliding:not(.is-builder-cards-view) .builder-sections-pane__item svg {
  color: var(--ink-mute);
  flex-shrink: 0;
}
/* AI builder live preview — loading + spinner shown while /api/auth/me
   resolves. Replaced by an iframe (or a CTA card) once we know the user. */
.builder-preview-loading {
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  color: oklch(85% 0.02 60); font-size: 0.92rem;
}
.builder-preview-loading-spinner {
  width: 22px; height: 22px;
  border-radius: 50%;
  border: 2px solid oklch(96% 0.02 80 / 0.18);
  border-top-color: oklch(96% 0.02 80 / 0.9);
  animation: builderSpin 800ms linear infinite;
}
@keyframes builderSpin { to { transform: rotate(360deg); } }
/* Once an iframe lives in the body, it takes the whole pane and loses the
   centered-content padding so the live site fills the available space. */
.builder-preview-body:has(iframe[data-builder-iframe]) {
  padding: 0;
  align-items: stretch; justify-content: stretch;
}

/* ────────────────────────────────────────────────────────────────────
   Preview empty state — text-only, italic-serif headline + dark pill
   ────────────────────────────────────────────────────────────────────
   The previous heavy v6 dark mark + radial-orange tint + icon block
   were "trying too hard". Reduced to: italic-serif title, brief lede,
   dark pill CTA. Centred vertically on a clean cream gradient.

   Gated on :not(:has(iframe)) so it auto-resets when
   shellRenderPreviewIframe mounts the iframe.
   ──────────────────────────────────────────────────────────────────── */
.builder-preview-body:not(:has(iframe[data-builder-iframe])):not(:has(iframe[data-builder-template-iframe])) {
  background: linear-gradient(180deg, #FFFFFF 0%, #F6F6F6 100%) !important;
  color: var(--ink) !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  padding: 32px 36px 110px !important;  /* bottom padding clears the dock */
  overflow: auto;
}
.builder-preview-empty {
  text-align: center;
  max-width: 300px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
/* Empty-state content stays visible in cards-view (the preview card
   shows a real preview of the empty state). It morphs with the
   wrap via the parent's JS FLIP transform — only opacity is faded
   here, for a soft "settle" feel arriving at fullscreen.
   Easings matched to JS flipMorph: easeOutExpo in (sharp burst →
   slow settle), easeInQuart out (slow → fast snap). All durations
   end at the same beat as the wrap morph (~640ms open / ~380ms close)
   so the whole transition lands as one cohesive moment. */
/* 2026-05-23 founder feedback: "make it feel so fluid that the card
   transforms mid-animation smoothly to match the correct state."
   The previous staggered delays (220-320ms) made the chrome catch up
   to the wrap morph AFTER it had nearly settled — eye perceived two
   separate motions. Dropped all delays, matched durations to the
   wrap morph (720ms), all using the same easing. Everything moves
   in lockstep now → reads as one fluid motion. */
.builder-preview-empty {
  opacity: 1;
  transition: opacity 720ms cubic-bezier(0.22, 1, 0.36, 1);
}
body:not(.is-builder-cards-view):not([data-builder-active-pane="preview"]) .builder-preview-empty {
  opacity: 0;
  transition: opacity 460ms cubic-bezier(0.22, 1, 0.36, 1);
}
.builder-preview-empty__title {
  font-family: 'Instrument Serif', 'Newsreader', Georgia, serif;
  font-style: italic;
  font-weight: 400;
  font-size: 2.4rem;
  letter-spacing: -0.018em;
  line-height: 1.0;
  color: var(--ink);
  margin: 0;
  max-width: 280px;
}
.builder-preview-empty__lede {
  font-size: 0.94rem;
  color: var(--ink-mute);
  line-height: 1.55;
  margin: 0;
  max-width: 260px;
}
.builder-preview-empty__cta {
  margin-top: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 10px 22px;
  background: linear-gradient(180deg, #2A211B 0%, #1F1611 100%);
  color: var(--cream);
  border: 0;
  border-radius: 999px;
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
  box-shadow:
    0 0 0 0.5px rgba(0, 0, 0, 0.3),
    0 2px 3px rgba(0, 0, 0, 0.18),
    0 8px 18px -4px rgba(0, 0, 0, 0.22),
    inset 0 1.5px 0 rgba(255, 255, 255, 0.12);
  transition: transform 0.16s cubic-bezier(0.2, 0, 0, 1);
}
.builder-preview-empty__cta:hover { transform: translateY(-1px); }
.builder-preview-empty__cta:active { transform: translateY(0); }

/* ────────────────────────────────────────────────────────────────────
   Sections empty state — restructured 2026-05-24 to include a
   "preview of the populated state" via greyed-out ghost rows that
   mirror the actual sections list shape (label + A/B/C picker +
   chevron). Top: tighter title/lede/CTA; bottom: ghost rows with a
   fade to the pane edge. Reads as "this is what's coming" instead
   of just "blank pane".
   ──────────────────────────────────────────────────────────────────── */
.builder-sections-emptystate {
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: 0;
  flex: 1 1 auto;
  position: relative;
}
.builder-sections-emptystate__head {
  text-align: center;
  max-width: 320px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 36px 24px 22px;
  flex: 0 0 auto;
}
.builder-sections-emptystate__title {
  font-family: 'Instrument Serif', 'Newsreader', Georgia, serif;
  font-style: italic;
  font-weight: 400;
  font-size: 1.9rem;
  letter-spacing: -0.018em;
  line-height: 1.05;
  color: var(--ink);
  margin: 0;
}
.builder-sections-emptystate__lede {
  font-size: 0.9rem;
  color: var(--ink-mute);
  line-height: 1.5;
  margin: 0;
  max-width: 280px;
}
.builder-sections-emptystate__cta {
  margin-top: 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 10px 22px;
  background: linear-gradient(180deg, #2A211B 0%, #1F1611 100%);
  color: var(--cream);
  border: 0;
  border-radius: 999px;
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
  box-shadow:
    0 0 0 0.5px rgba(0, 0, 0, 0.3),
    0 2px 3px rgba(0, 0, 0, 0.18),
    0 8px 18px -4px rgba(0, 0, 0, 0.22),
    inset 0 1.5px 0 rgba(255, 255, 255, 0.12);
  transition: transform 0.16s cubic-bezier(0.2, 0, 0, 1);
}
.builder-sections-emptystate__cta:hover { transform: translateY(-1px); }
.builder-sections-emptystate__cta:active { transform: translateY(0); }

/* Ghost rows — preview of the populated list, greyed out + inert.
   Container has a fade-to-cream mask at the bottom so the list
   appears to fade out into the pane (suggesting "more rows than
   fit"). */
.builder-sections-emptystate__ghosts {
  padding: 0 16px 24px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1 1 auto;
  min-height: 0;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 65%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 0%, #000 65%, transparent 100%);
  pointer-events: none;
  user-select: none;
}
.builder-sections-emptystate__ghost-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  background: rgba(255, 255, 255, 0.55);
  border: 1px solid rgba(31, 22, 17, 0.07);
  border-radius: 12px;
  flex: 0 0 auto;
}
.builder-sections-emptystate__ghost-label {
  flex: 1 1 auto;
  font-size: 0.96rem;
  font-weight: 600;
  color: rgba(31, 22, 17, 0.32);
  letter-spacing: -0.005em;
}
.builder-sections-emptystate__ghost-picker {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px;
  background: rgba(31, 22, 17, 0.04);
  border-radius: 10px;
  flex: 0 0 auto;
}
.builder-sections-emptystate__ghost-pick {
  width: 24px;
  height: 24px;
  border-radius: 7px;
  background: rgba(31, 22, 17, 0.08);
}
.builder-sections-emptystate__ghost-pick:first-child {
  background: rgba(31, 22, 17, 0.18);
}
.builder-sections-emptystate__ghost-chev {
  display: inline-flex;
  color: rgba(31, 22, 17, 0.18);
  flex: 0 0 auto;
}

/* ────────────────────────────────────────────────────────────────────
   2026-05-24 (rev 2): kill the mobile pull-up sheet AND stop the
   preview pane from bleeding through the chat pane in state="ready".
   The old design at dashboard-v2.css L7271 sets preview-pane to
   position:fixed top:0 bottom:0 z-index:1 whenever state="ready" —
   that was intentional under the sheet pattern (preview floated
   under the draggable chat sheet). With the sheet killed, the chat
   pane is position:static + z:auto so the position:fixed preview
   pane paints ON TOP of it, and the user sees V5 leak into the chat
   page after Build my site lands. Override BOTH:
     1. chat-pane stays a normal full-screen pane (sheet defang)
     2. preview-pane goes back to in-flow positioning UNLESS the
        active pane is actually preview (active-pane="preview" still
        wants the fullscreen iframe surface).
   Note: cards-view doesn't apply here — the cards-view rules at
   L7763 + L11760 are a separate ruleset and already override on
   their own. Only the single-mode state="ready" sheet is killed. */
@media (max-width: 720px) {
  body.is-builder-chat:not(.is-builder-cards-view) .builder-shell--centered[data-builder-state="ready"] .builder-chat-pane {
    position: static !important;
    bottom: auto !important;
    left: auto !important;
    right: auto !important;
    top: auto !important;
    height: auto !important;
    max-height: none !important;
    min-height: 0 !important;
    width: 100% !important;
    min-width: 0 !important;
    z-index: auto !important;
    background: transparent !important;
    border-top-left-radius: 0 !important;
    border-top-right-radius: 0 !important;
    box-shadow: none !important;
    overflow: hidden !important;
    flex: 1 1 0 !important;
    justify-content: flex-start !important;
    transition: none !important;
  }
  /* Belt-and-suspenders: hide the sheet handle even if the markup
     leaks back in via a stale cached renderer. */
  .builder-sheet-handle { display: none !important; }

  /* 2026-05-24 founder report: "preview brought to the chat page".
     The state="ready" rule at dashboard-v2.css L7271 sets preview-
     pane to position:fixed top:0 bottom:0 z-index:1 which under the
     old sheet design floated UNDER the chat sheet. With the sheet
     killed, preview-pane paints ON TOP of the chat pane (chat is
     z:auto static) — V5 bleeds through. Revert preview-pane to in-
     flow positioning unless active pane really is preview. */
  body.is-builder-chat:not(.is-builder-cards-view):not([data-builder-active-pane="preview"]) .builder-shell--centered[data-builder-state="ready"] .builder-preview-pane {
    position: static !important;
    top: auto !important;
    left: auto !important;
    right: auto !important;
    bottom: auto !important;
    z-index: auto !important;
  }

  /* 2026-05-24 (rev 2 — still bleeding). Even with preview-pane
     position:static, the parent .builder-card-wrap[data-pane-key=
     "preview"] is in flow below the chat-wrap. In state="empty" the
     shell is 100dvh + overflow:hidden so the preview-wrap is clipped
     below the viewport — but in state="ready" the shell sizing rule
     at L7395 stops firing (it gates on :not(state="ready")), so the
     shell falls back to auto height, the chat-wrap doesn't reach the
     viewport bottom, and the preview-wrap renders visible underneath.
     Fix: explicitly hide preview-wrap + sections-wrap whenever the
     user is on the chat pane (or no active-pane attr set). The
     is-builder-sliding rule already overrides display:none during
     pane transitions, so swipes between panes still show all three. */
  body.is-builder-chat:not(.is-builder-cards-view):not([data-builder-active-pane="preview"]):not([data-builder-active-pane="sections"]) .builder-card-wrap[data-pane-key="preview"],
  body.is-builder-chat:not(.is-builder-cards-view):not([data-builder-active-pane="preview"]):not([data-builder-active-pane="sections"]) .builder-card-wrap[data-pane-key="sections"] {
    display: none !important;
  }
}

/* ────────────────────────────────────────────────────────────────────
   State gating — `data-builder-state` on .builder-shell--centered
   flips between "empty" (initial) and "ready" (post chat-intro
   completion via shellTransitionToReady). When NOT ready: show the
   empty states, hide the populated content. When ready: reverse.
   Uses :not([data-builder-state="ready"]) so fresh shells (default
   data-builder-state="empty") AND any future transitional states
   both fall into the empty bucket.
   ──────────────────────────────────────────────────────────────────── */
.builder-shell--centered:not([data-builder-state="ready"]) .builder-template-iframe,
.builder-shell--centered:not([data-builder-state="ready"]) .builder-sections-pane__body {
  display: none !important;
}
.builder-shell--centered[data-builder-state="ready"] .builder-preview-empty,
.builder-shell--centered[data-builder-state="ready"] .builder-sections-emptystate {
  display: none !important;
}

/* Preview body centering — the existing :not(:has(iframe)) rule at
   ~line 4104 only fires when the iframe is absent from the DOM, but
   we keep the V5 iframe mounted always (display:none in empty state).
   This state-gated rule applies the same flex-centering when not
   ready so the empty title sits middle-of-pane instead of top-left. */
.builder-shell--centered:not([data-builder-state="ready"]) .builder-preview-body {
  display: flex !important;
  flex-direction: column !important;
  align-items: center !important;
  justify-content: center !important;
  padding: 32px 36px 110px !important;
  background: linear-gradient(180deg, #FFFFFF 0%, #F6F6F6 100%) !important;
  overflow: auto !important;
}

/* ────────────────────────────────────────────────────────────────────
   Preview floating dock (V1) — centred glass pill at the bottom of
   the preview pane. Always visible (empty state AND populated iframe),
   floats on top via position:absolute + high z-index.
   ──────────────────────────────────────────────────────────────────── */
.builder-preview-pane { position: relative; }
.builder-preview-dock {
  position: absolute;
  bottom: 16px;
  left: 50%;
  /* Visible default state — translate(-50%) centers, translateY(0) is
     at rest. The "hidden" state (in cards-view OR when preview isn't
     the active pane) slides down + fades via the transition below. */
  transform: translate(-50%, 0);
  z-index: 10;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 6px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.92) 0%, rgba(246, 246, 246, 0.92) 100%);
  -webkit-backdrop-filter: blur(16px) saturate(200%);
          backdrop-filter: blur(16px) saturate(200%);
  border: 1px solid rgba(31, 22, 17, 0.10);
  border-radius: 999px;
  box-shadow:
    0 0 0 0.5px rgba(0, 0, 0, 0.06),
    0 2px 4px rgba(20, 14, 8, 0.08),
    0 8px 24px -4px rgba(20, 14, 8, 0.18),
    0 20px 48px -12px rgba(20, 14, 8, 0.22),
    inset 0 1px 0 rgba(255, 255, 255, 0.9);
  opacity: 1;
  pointer-events: auto;
  /* Matched to OPEN_MS (720ms) and OPEN_EASE in dashboard-v2-page.html
     so the dock animates in lockstep with the wrap morph instead of
     catching up afterwards. */
  transition:
    opacity 720ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 720ms cubic-bezier(0.22, 1, 0.36, 1);
}
.builder-preview-dock__btn {
  width: 40px;
  height: 40px;
  border-radius: 999px;
  background: transparent;
  border: 0;
  color: var(--ink);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 0.12s ease;
}
.builder-preview-dock__btn:hover { background: rgba(31, 22, 17, 0.06); }
.builder-preview-dock__btn:active { background: rgba(31, 22, 17, 0.10); }
/* When the edit-toggle is pressed, give it a filled dark circle so
   the tradie sees that edit mode is on. Founder feedback 2026-05-24:
   "when it [is] selected give it a black circle". */
.builder-preview-dock__btn.is-on {
  background: var(--ink, #1F1611);
  color: var(--cream, #FAFAF8);
}
.builder-preview-dock__btn.is-on:hover,
.builder-preview-dock__btn.is-on:active {
  background: var(--ink-2, #2A211B);
}
.builder-preview-dock__divider {
  width: 1px;
  height: 22px;
  background: rgba(31, 22, 17, 0.10);
  margin: 0 3px;
}
.builder-preview-dock__publish {
  padding: 0 18px;
  height: 40px;
  min-width: 92px;
  background: linear-gradient(180deg, #2A211B 0%, #1F1611 100%);
  color: var(--cream);
  border: 0;
  border-radius: 999px;
  font-family: inherit;
  font-size: 0.86rem;
  font-weight: 500;
  cursor: pointer;
  box-shadow:
    0 0 0 0.5px rgba(0, 0, 0, 0.3),
    0 2px 3px rgba(0, 0, 0, 0.18),
    inset 0 1px 0 rgba(255, 255, 255, 0.12);
  transition: transform 0.16s cubic-bezier(0.2, 0, 0, 1);
}
.builder-preview-dock__publish:hover { transform: translateY(-1px); }
.builder-preview-dock__publish:active { transform: translateY(0); }

/* Slide-down + fade out when the dock shouldn't be visible (in
   cards-view OR when preview isn't the active fullscreen pane).
   pointer-events:none stops the invisible dock from intercepting
   taps. Faster decay than entry — out should snap, in should feel. */
body.is-builder-cards-view .builder-preview-dock,
body:not(.is-builder-cards-view):not([data-builder-active-pane="preview"]) .builder-preview-dock {
  opacity: 0;
  transform: translate(-50%, 28px);
  pointer-events: none;
  /* Matched to CLOSE_MS (460ms) and same easing — fluid exit. */
  transition:
    opacity 460ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 460ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* ────────────────────────────────────────────────────────────────────
   Preview status pill — top-right floating, Draft / Live
   ──────────────────────────────────────────────────────────────────── */
.builder-preview-status {
  /* 2026-05-24 (rev 2): pinned to the viewport at topbar height,
     positioned just to the LEFT of the cards-view button (which sits
     at right ~12-60px). Was position:absolute inside the preview
     pane; safe-area math + the pane's own padding put it right under
     the cards button on iOS. Fixed positioning + an explicit right
     offset that clears the 48px cards button gives a predictable
     gap. z-index above the topbar (.mob-topbar z:70 + .builder-
     preview-pill z:71) so it floats alongside, not behind. */
  position: fixed;
  top: calc(14px + env(safe-area-inset-top, 0px));
  right: calc(72px + env(safe-area-inset-right, 0px));
  z-index: 72;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 12px 5px 10px;
  background: rgba(255, 255, 255, 0.82);
  -webkit-backdrop-filter: blur(14px) saturate(180%);
          backdrop-filter: blur(14px) saturate(180%);
  border: 1px solid rgba(31, 22, 17, 0.08);
  border-radius: 999px;
  box-shadow: 0 2px 6px rgba(31, 22, 17, 0.08);
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
  /* Matched to OPEN_MS — no delay. */
  transition:
    opacity 720ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 720ms cubic-bezier(0.22, 1, 0.36, 1);
}
.builder-preview-status__dot {
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: var(--ink-faint);
}
.builder-preview-status[data-state="live"] .builder-preview-status__dot {
  background: #4a7c4a;
  box-shadow: 0 0 6px rgba(74, 124, 74, 0.5);
}
body.is-builder-cards-view .builder-preview-status,
body:not(.is-builder-cards-view):not([data-builder-active-pane="preview"]) .builder-preview-status {
  opacity: 0;
  transform: translateY(-14px);
  pointer-events: none;
  transition:
    opacity 460ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 460ms cubic-bezier(0.22, 1, 0.36, 1);
}

@media (prefers-reduced-motion: reduce) {
  .builder-preview-dock,
  .builder-preview-status,
  .builder-preview-empty {
    transition: none !important;
  }
}

/* ── Settings tab — Site Settings form (v2 premium) ────────────────────
   Hairline-separated sections, label-left / input-right rows, generous
   whitespace. No card chrome — sections are separated by space + a thin
   rule. AI reads these; tradie writes. */
.builder-settings-body {
  flex: 1;
  overflow-y: auto;
  background: var(--bs-paper, #FAFAFA);
}
.builder-settings-body[hidden] { display: none; }
.bsf-loading, .bsf-error {
  padding: 60px 40px;
  text-align: center;
  color: var(--bs-ink-mute, #6b5d50);
  font-size: 0.92rem;
}
.bsf-error { color: #b3261e; }
.bsf-wrap {
  max-width: 760px;
  margin: 0 auto;
  padding: 48px 40px 140px;
}
.bsf-head {
  margin: 0 0 40px;
  padding: 0 0 28px;
  border-bottom: 1px solid rgba(31, 22, 17, 0.08);
}
.bsf-title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 1.7rem;
  font-weight: 600;
  color: var(--bs-ink, #1f1611);
  letter-spacing: -0.022em;
  margin: 0 0 6px;
  line-height: 1.2;
}
.bsf-sub {
  font-size: 0.92rem;
  color: var(--bs-ink-mute, #6b5d50);
  line-height: 1.55;
  max-width: 56ch;
  margin: 0;
}
.bsf-form {
  display: flex;
  flex-direction: column;
}

/* Section: borderless. Each section sits in space, separated by a hairline. */
.bsf-section {
  margin: 0;
  padding: 32px 0;
  border-bottom: 1px solid rgba(31, 22, 17, 0.07);
}
.bsf-section:first-of-type { padding-top: 0; }
.bsf-section:last-of-type { border-bottom: none; }
.bsf-section-summary {
  cursor: pointer;
  list-style: none;
  user-select: none;
  padding: 0 0 4px;
  position: relative;
}
.bsf-section-summary::-webkit-details-marker { display: none; }
.bsf-section-summary::after {
  content: '';
  position: absolute;
  right: 4px;
  top: 8px;
  width: 8px;
  height: 8px;
  border-right: 1.5px solid rgba(31, 22, 17, 0.45);
  border-bottom: 1.5px solid rgba(31, 22, 17, 0.45);
  transform: rotate(45deg);
  transition: transform 180ms ease;
}
.bsf-section[open] > .bsf-section-summary::after {
  transform: rotate(-135deg);
  top: 12px;
}
.bsf-section-summary:hover::after {
  border-color: var(--bs-ink, #1f1611);
}
.bsf-section-title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--bs-ink, #1f1611);
  letter-spacing: -0.01em;
  margin: 0 0 4px;
  line-height: 1.3;
}
.bsf-section-desc {
  font-size: 0.85rem;
  color: var(--bs-ink-mute, #6b5d50);
  line-height: 1.5;
  max-width: 56ch;
  margin: 0;
}
.bsf-section-body {
  padding: 24px 0 4px;
  display: flex;
  flex-direction: column;
}

/* Field row: label LEFT (200px), input RIGHT (max 420px). */
.bsf-field {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: 24px;
  align-items: start;
  padding: 14px 0;
  border-bottom: 1px solid rgba(31, 22, 17, 0.05);
}
.bsf-field:last-child { border-bottom: none; }
.bsf-label {
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--bs-ink, #1f1611);
  letter-spacing: -0.005em;
  padding-top: 9px;
  line-height: 1.4;
}
.bsf-field-control { max-width: 460px; }
.bsf-input {
  font-family: inherit;
  font-size: 0.92rem;
  padding: 9px 12px;
  border: 1px solid rgba(31, 22, 17, 0.16);
  border-radius: 6px;
  background: white;
  color: var(--bs-ink, #1f1611);
  transition: border-color 120ms ease, box-shadow 120ms ease;
  width: 100%;
  min-width: 0;
  line-height: 1.4;
}
.bsf-input:hover { border-color: rgba(31, 22, 17, 0.28); }
.bsf-input:focus {
  outline: none;
  border-color: var(--bs-orange, #d9541e);
  box-shadow: 0 0 0 3px rgba(217, 84, 30, 0.10);
}
.bsf-textarea {
  resize: vertical;
  min-height: 88px;
  line-height: 1.55;
  font-family: inherit;
}
.bsf-hint {
  font-size: 0.78rem;
  color: var(--bs-ink-mute, #6b5d50);
  line-height: 1.45;
  margin-top: 8px;
  opacity: 0.85;
}
select.bsf-input {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5l3 3 3-3' stroke='%236b5d50' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 12px;
  padding-right: 32px;
}
.bsf-check-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  padding-top: 6px;
}
.bsf-check {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.88rem;
  cursor: pointer;
  padding: 4px 0;
  user-select: none;
  color: var(--bs-ink, #1f1611);
}
.bsf-check input { accent-color: var(--bs-orange, #d9541e); }

/* Curated swatch picker for accent colour. */
.bsf-swatch-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  padding: 4px 0;
}
.bsf-swatch {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  border: 1px solid rgba(31, 22, 17, 0.12);
  cursor: pointer;
  position: relative;
  transition: transform 120ms ease, box-shadow 120ms ease;
  padding: 0;
  background-clip: padding-box;
}
.bsf-swatch:hover {
  transform: scale(1.08);
  box-shadow: 0 4px 12px rgba(31, 22, 17, 0.12);
}
.bsf-swatch.is-on {
  box-shadow: 0 0 0 2px white, 0 0 0 4px var(--bs-ink, #1f1611);
}
.bsf-swatch[data-custom="1"] {
  background: linear-gradient(135deg, #ff6b6b, #4ecdc4 25%, #ffe66d 50%, #95e1d3 75%, #c7a3e0);
}
.bsf-swatch-text {
  font-family: 'SF Mono', Menlo, monospace;
  font-size: 0.82rem;
  color: var(--bs-ink-mute, #6b5d50);
  margin-left: 8px;
  letter-spacing: 0.02em;
}
.bsf-color-native {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}

/* Sticky save bar. Glass-look backdrop, full-width across the pane. */
.bsf-actions {
  position: sticky;
  bottom: 0;
  margin: 32px -40px 0;
  padding: 18px 40px;
  background: rgba(250, 250, 250, 0.92);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-top: 1px solid rgba(31, 22, 17, 0.08);
  display: flex;
  align-items: center;
  gap: 14px;
}
.bsf-save-btn {
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 500;
  padding: 9px 18px;
  border-radius: 8px;
  border: 1px solid var(--bs-ink, #1f1611);
  background: var(--bs-ink, #1f1611);
  color: white;
  cursor: pointer;
  transition: transform 80ms ease, opacity 120ms ease;
  letter-spacing: -0.005em;
}
.bsf-save-btn:hover { opacity: 0.93; }
.bsf-save-btn:active { transform: translateY(1px); }
.bsf-save-btn:disabled { opacity: 0.55; cursor: progress; }
.bsf-status {
  font-size: 0.85rem;
  color: var(--bs-ink-mute, #6b5d50);
  transition: opacity 200ms ease;
}
.bsf-status-ok { color: #2d6a3e; }
.bsf-status-err { color: #b3261e; }

@media (max-width: 720px) {
  .bsf-wrap { padding: 32px 20px 120px; }
  .bsf-field { grid-template-columns: 1fr; gap: 8px; }
  .bsf-label { padding-top: 0; }
  .bsf-actions { margin: 24px -20px 0; padding: 14px 20px; }
}
.builder-preview-content {
  max-width: 560px;
  text-align: center;
  padding: 30px;
}
.builder-preview-brand {
  font-family: 'Newsreader', Georgia, serif;
  font-style: italic;
  font-size: 0.95rem;
  color: oklch(80% 0.10 38);
  margin-bottom: 16px;
}
.builder-preview-headline {
  font-family: 'Geist', sans-serif;
  font-size: clamp(1.4rem, 2.4vw, 1.95rem);
  font-weight: 500;
  letter-spacing: -0.024em;
  line-height: 1.18;
  margin: 0 0 14px;
  color: #fff;
}
.builder-preview-sub {
  font-size: 0.92rem;
  color: oklch(85% 0.02 60);
  line-height: 1.55;
  margin: 0 0 28px;
}
.builder-preview-ctas {
  display: flex; flex-direction: column; align-items: center; gap: 14px;
}
.builder-preview-cta.is-primary {
  display: inline-block;
  background: oklch(64% 0.16 38);
  color: #fff;
  padding: 10px 22px;
  border-radius: 8px;
  font-size: 0.95rem; font-weight: 500;
  text-decoration: none;
  font-family: 'Geist', sans-serif;
}
.builder-preview-cta-or {
  font-size: 0.84rem;
  color: oklch(75% 0.02 60);
}
.builder-preview-cta-secondary {
  color: oklch(85% 0.10 38);
  text-decoration: underline;
}

/* ==========================================================================
   AI builder — 3-tab layout (Preview / Settings / AI Builder).
   Mobile-first, light-theme, white card. Replaces the older split-pane
   builder-shell layout. The .abx-* prefix keeps it scoped.
   ========================================================================== */
.abx { display: flex; flex-direction: column; gap: 14px; min-height: 0; }
.abx-tabs {
  display: flex; gap: 6px; padding: 4px; border-radius: 10px;
  background: var(--cream-2); border: 1px solid var(--hairline);
}
.abx-tab {
  flex: 1 1 0; min-width: 0;
  padding: 10px 12px; font-size: 0.92rem; font-weight: 500;
  color: var(--ink-mute); background: transparent; border: 0; border-radius: 8px;
  cursor: pointer; min-height: 44px; touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s, color 0.15s;
}
.abx-tab:hover { color: var(--ink); }
.abx-tab.is-on {
  background: var(--paper, #FFFFFF); color: var(--ink);
  box-shadow: 0 1px 2px rgba(31,22,17,0.06);
}
.abx-subtitle {
  font-size: 0.86rem; color: var(--ink-mute);
  font-family: 'Geist Mono', 'JetBrains Mono', ui-monospace, monospace;
}
.abx-panel { display: none; min-height: 0; }
.abx-panel.is-on { display: flex; flex-direction: column; gap: 12px; }

/* Preview panel: iframe of the live site (or empty state). */
.abx-preview-frame {
  position: relative;
  background: var(--paper, #FFFFFF);
  border: 1px solid var(--hairline); border-radius: 12px;
  min-height: 60vh; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.abx-iframe {
  width: 100%; height: 100%;
  min-height: 60vh; border: 0;
  background: var(--paper, #FFFFFF);
  display: block;
}
.abx-loading {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  color: var(--ink-mute); font-size: 0.9rem; padding: 32px;
}
.abx-spinner {
  width: 22px; height: 22px;
  border: 2px solid var(--hairline); border-top-color: var(--orange);
  border-radius: 50%; animation: abx-spin 0.7s linear infinite;
}
@keyframes abx-spin { to { transform: rotate(360deg); } }
.abx-empty {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  text-align: center; padding: 36px 24px; max-width: 420px;
}
.abx-empty-title { font-size: 1.15rem; font-weight: 500; color: var(--ink); }
.abx-empty-desc { font-size: 0.92rem; color: var(--ink-mute); margin: 0 0 8px; max-width: 36ch; line-height: 1.5; }
.abx-preview-actions {
  display: flex; gap: 8px; justify-content: flex-end;
}

/* Settings panel: stacked cards with site-only controls. */
.abx-card {
  background: var(--paper, #FFFFFF);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 18px;
  display: flex; flex-direction: column; gap: 8px;
}
.abx-card-title { font-size: 0.95rem; font-weight: 600; color: var(--ink); margin: 0 0 4px; }
.abx-card-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.abx-card-help { font-size: 0.84rem; color: var(--ink-mute); margin: 0; line-height: 1.5; }
.abx-card-help.is-error { color: var(--orange-deep, #B8420F); }
.abx-host {
  flex: 1 1 auto; min-width: 0;
  font-family: 'Geist Mono', 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.92rem; color: var(--ink);
  word-break: break-all;
}
.abx-input {
  flex: 1 1 auto; min-width: 0;
  padding: 10px 12px; border: 1px solid var(--hairline); border-radius: 8px;
  background: var(--paper, #FFFFFF); color: var(--ink);
  font: inherit; font-size: 16px;
}
.abx-input:focus { outline: 2px solid var(--orange); outline-offset: 2px; border-color: var(--ink); }
.abx-link {
  display: inline-block;
  font-size: 0.92rem; color: var(--orange-deep, #B8420F); text-decoration: none;
  padding: 6px 0;
}
.abx-link:hover { text-decoration: underline; }
.btn-sm { padding: 8px 14px; font-size: 0.86rem; min-height: 36px; }

/* AI Builder panel: white background, full available height. */
.abx-subtabs {
  display: flex; gap: 4px; padding: 3px;
  background: var(--cream-2); border: 1px solid var(--hairline); border-radius: 8px;
  margin-bottom: 8px; align-self: flex-start;
}
.abx-subtab {
  padding: 7px 14px; font-size: 0.85rem; font-weight: 500;
  color: var(--ink-mute); background: transparent; border: 0; border-radius: 6px;
  cursor: pointer; min-height: 36px; touch-action: manipulation;
}
.abx-subtab.is-on { background: var(--paper, #FFFFFF); color: var(--ink); box-shadow: 0 1px 2px rgba(31,22,17,0.06); }
.abx-subpanel { display: none; }
.abx-subpanel.is-on { display: block; }
.abx-builder-iframe {
  width: 100%;
  height: calc(100dvh - 200px);
  min-height: 600px;
  border: 1px solid var(--hairline); border-radius: 12px;
  background: #FFFFFF;
  display: block;
}
.abx-chat-card {
  background: var(--paper, #FFFFFF);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 16px;
  display: flex; flex-direction: column; gap: 12px;
  min-height: calc(100dvh - 240px);
}
.abx-chat-thread {
  flex: 1 1 auto; min-height: 200px;
  overflow-y: auto;
  display: flex; flex-direction: column; gap: 10px;
  padding: 4px;
}
.abx-chat-msg {
  max-width: 85%;
  padding: 10px 14px;
  border-radius: 12px;
  font-size: 0.92rem; line-height: 1.5;
  word-break: break-word;
}
.abx-chat-msg.is-ai {
  align-self: flex-start;
  background: var(--cream-2);
  color: var(--ink);
}
.abx-chat-msg.is-user {
  align-self: flex-end;
  background: var(--ink);
  color: var(--cream, #FAFAFA);
}
.abx-chat-quick {
  display: flex; flex-wrap: wrap; gap: 6px;
}
.abx-chat-chip {
  padding: 7px 12px; font-size: 0.85rem;
  background: var(--paper, #FFFFFF); color: var(--ink);
  border: 1px solid var(--hairline); border-radius: 999px;
  cursor: pointer; min-height: 36px; touch-action: manipulation;
}
.abx-chat-chip:hover { background: var(--cream-2); }
.abx-chat-compose {
  display: flex; gap: 8px; align-items: flex-end;
}
.abx-chat-input {
  flex: 1 1 auto; min-width: 0;
  padding: 10px 12px; border: 1px solid var(--hairline); border-radius: 8px;
  background: var(--paper, #FFFFFF); color: var(--ink);
  font: inherit; font-size: 16px; resize: vertical;
  min-height: 44px; max-height: 200px;
}
.abx-chat-input:focus { outline: 2px solid var(--orange); outline-offset: 2px; border-color: var(--ink); }

@media (max-width: 899.98px) {
  .abx { gap: 10px; width: 100%; }
  .abx-tabs { padding: 3px; }
  .abx-tab { padding: 9px 10px; font-size: 0.88rem; }
  .abx-card { padding: 14px; }
  .abx-preview-frame, .abx-iframe { min-height: 55vh; }

  /* All four panel states (Preview frame, Settings cards, AI Builder Form
     iframe, AI Builder Chat card) live inside the normal dashboard page
     padding (16px each side). Iframe + preview frame keep the rounded card
     border so they read as siblings of the Settings cards. */
  .abx-builder-iframe {
    width: 100%;
    max-width: 100%;
    height: calc(100dvh - 200px);
    min-height: 520px;
    border-radius: 12px;
    border: 1px solid var(--hairline);
    margin: 0;
  }
  .abx-preview-frame {
    width: 100%;
    max-width: 100%;
    border-radius: 12px;
    border: 1px solid var(--hairline);
    margin: 0;
  }

  /* The /builder iframe has an intrinsic 300px width that, in a flex column
     chain (.abx-subpanel > .abx-panel > .abx > main.dash), shrinks every
     parent to fit-content. Force the dash + abx tree to fill the grid track
     so the iframe's width:100% resolves against the full page-padded area
     (343px at 375 viewport) instead of the iframe's 300px intrinsic. */
  main.dash:has(.abx) {
    width: 100%;
    max-width: 100%;
  }
  .abx-panel,
  .abx-subpanel { width: 100%; }
}

.jt-card.is-fallback .jt-fallback-body {
  grid-column: 2 / 4;
  grid-row: 2 / 4;
  font-size: 0.9rem; color: var(--ink-mute); line-height: 1.55;
  margin-top: 4px;
}
.jt-card.is-fallback .jt-fallback-body strong { color: var(--ink); font-weight: 600; }

/* === Calendar empty state ============================================== */
.cal-empty {
  display: flex;
  flex-direction: column;
  gap: 22px;
  margin-top: 28px;
  margin-bottom: 24px;
}
.cal-empty-card {
  background: var(--paper, #fff);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 28px 32px;
}
.cal-empty-title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-weight: 500;
  font-size: 1.5rem;
  letter-spacing: -0.018em;
  color: var(--ink);
  margin: 0 0 8px;
}
.cal-empty-sub {
  font-size: 0.95rem;
  color: var(--ink-mute);
  line-height: 1.55;
  margin: 0;
  max-width: 64ch;
  text-wrap: pretty;
}
.cal-empty-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}
.cal-empty-action {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 18px;
  background: var(--paper, #fff);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  text-align: left;
  text-decoration: none;
  color: var(--ink);
  transition: border-color 0.18s cubic-bezier(0.2, 0, 0, 1), transform 0.18s cubic-bezier(0.2, 0, 0, 1);
}
.cal-empty-action:hover {
  border-color: var(--ink-mute);
  transform: translateY(-1px);
}
.cal-empty-action-icon {
  display: inline-flex;
  width: 32px;
  height: 32px;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: var(--cream-2);
  color: var(--ink);
  flex-shrink: 0;
}
.cal-empty-action-title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-weight: 500;
  font-size: 0.95rem;
  color: var(--ink);
  margin-bottom: 4px;
  line-height: 1.3;
  letter-spacing: -0.01em;
}
.cal-empty-action-sub {
  font-size: 0.82rem;
  color: var(--ink-mute);
  line-height: 1.45;
}
.cal-empty-preview { margin-top: 4px; }
.cal-empty-preview-eyebrow {
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 12px;
  font-weight: 500;
}
.cal-empty-preview-list {
  display: flex;
  flex-direction: column;
  background: var(--paper, #fff);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  overflow: hidden;
}
.cal-empty-preview-row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--hairline);
}
.cal-empty-preview-row:last-child { border-bottom: 0; }
.cal-empty-preview-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.78rem;
  font-weight: 500;
  padding: 5px 10px;
  border-radius: 6px;
  flex-shrink: 0;
  min-width: 130px;
}
.cal-empty-preview-pill.is-booking { background: var(--green-soft, rgba(46,125,50,0.12)); color: var(--green, #2E7D32); }
.cal-empty-preview-pill.is-block { background: var(--cream-2); color: var(--ink); }
.cal-empty-preview-pill.is-gcal { background: rgba(213,117,41,0.1); color: var(--accent-orange, #D57529); }
.cal-empty-preview-pill.is-sm8 { background: rgba(42, 159, 214, 0.12); color: #1B7CB0; }
.cal-empty-preview-text {
  font-size: 0.88rem;
  color: var(--ink-mute);
  line-height: 1.5;
}

/* The empty week-grid is the primary calendar surface — full-strength.
   Empty-state cards sit below as supportive guidance, not as a takeover. */

@media (max-width: 720px) {
  .cal-empty-grid { grid-template-columns: 1fr; }
  .cal-empty-card { padding: 22px; }
  .cal-empty-preview-pill { min-width: auto; }
}

/* === Forms tabs — Booking form / Quote form switcher ===================
   Glass-sliding segmented control matching Leads (All/Bookings/Quotes)
   and Calendar (Today/Week/Month) — cream-2 track + one absolutely-
   positioned glass pill that slides between active positions via JS-
   controlled transform + width. Both GPU-cheap properties so the 60fps
   slide stays smooth. See [data-forms-indicator] in dashboard-v2-page-
   wire.js for the positioning logic. */
.forms-tabs {
  position: relative;
  display: inline-flex;
  background: rgba(31, 22, 17, 0.04);
  border: 1px solid rgba(31, 22, 17, 0.04);
  border-radius: 10px;
  padding: 3px;
  gap: 2px;
  margin: 4px 0 16px;
  isolation: isolate;
}
.forms-tab {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 16px;
  border-radius: 8px;
  background: transparent;
  border: 0;
  font-family: inherit;
  font-size: 0.8125rem;
  font-weight: 500;
  color: #A39585;
  cursor: pointer;
  transition: color 0.22s ease;
  -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) { .forms-tab:hover { color: var(--ink); } }
.forms-tab.is-on { color: var(--ink); }
.forms-tab__count {
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
  font-size: 11px;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
.forms-tab.is-on .forms-tab__count { color: var(--ink-mute); }
.forms-tabs__indicator {
  position: absolute;
  top: 3px; left: 0;
  height: calc(100% - 6px);
  width: 0;
  pointer-events: none;
  z-index: 0;
  border-radius: 8px;
  background: linear-gradient(180deg, #FFFFFF 0%, #F8F8F8 100%);
  border: 1px solid rgba(31, 22, 17, 0.1);
  border-bottom-color: rgba(31, 22, 17, 0.15);
  box-shadow:
    0 1px 3px rgba(31, 22, 17, 0.07),
    0 2px 1px -1px rgba(31, 22, 17, 0.04),
    inset 0 1px 0 rgba(255, 255, 255, 0.9);
  will-change: transform, width;
  transform: translate3d(0, 0, 0);
  transition:
    transform 0.32s cubic-bezier(0.32, 0.72, 0, 1),
    width 0.32s cubic-bezier(0.32, 0.72, 0, 1);
}

/* === Form template — v6 hero card =====================================
   Holds the intro (Live pill + headline + sub + URL chip) and the
   form-rules sub-section. Editor + preview grid lives as a sibling
   below, untouched. One v6 light-gradient surface provides the depth;
   inside the card everything is hairline-divided (no nested boxes). */
.form-template {
  background: linear-gradient(180deg, #FFFFFF 0%, #F6F6F6 100%);
  border: 1px solid rgba(31, 22, 17, 0.10);
  border-radius: 18px;
  padding: 22px 22px 0;
  margin-bottom: 22px;
  box-shadow:
    0 0 0 0.5px rgba(0, 0, 0, 0.04),
    0 1px 2px rgba(20, 14, 8, 0.04),
    0 4px 10px -2px rgba(20, 14, 8, 0.10),
    0 12px 24px -6px rgba(20, 14, 8, 0.14),
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    inset 0 -1px 1px rgba(0, 0, 0, 0.03);
}
.form-template-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
}
.form-template-headline {
  font-size: 1.02rem;
  color: var(--ink);
  margin: 0 0 8px;
  line-height: 1.45;
}
.form-template-headline strong { font-weight: 600; }
.form-template-subline {
  font-size: 0.86rem;
  color: var(--ink-mute);
  margin: 0 0 16px;
  line-height: 1.5;
}
.form-template-subline a { color: var(--ink); border-bottom: 1px solid var(--hairline-2, var(--hairline)); text-decoration: none; }
.form-template-subline a:hover { border-bottom-color: var(--ink-mute); }

/* URL chip — small glass pill, the deliberate third v6 moment.
   The URL is the actual subject of the page so it gets surface depth
   even inside the already-v6 card. */
.form-template-url {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
  font-size: 0.82rem;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.78);
  backdrop-filter: blur(8px) saturate(160%);
  -webkit-backdrop-filter: blur(8px) saturate(160%);
  border: 1px solid rgba(31, 22, 17, 0.08);
  padding: 8px 8px 8px 12px;
  border-radius: 10px;
  box-shadow: 0 1px 2px rgba(31, 22, 17, 0.04);
}
.form-template-url-icon { display: inline-flex; color: var(--ink-faint); flex-shrink: 0; }
.form-template-url-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.form-template-url-copy {
  flex-shrink: 0;
  width: 26px; height: 26px;
  border-radius: 6px;
  background: rgba(31, 22, 17, 0.04);
  border: 0;
  color: var(--ink-mute);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.form-template-url-copy:hover { background: rgba(31, 22, 17, 0.10); color: var(--ink); }
.form-template-url-copy.is-copied { color: var(--green); background: var(--green-soft); }

/* Live pill — pulse-dot prepended, sits as the first element in the
   card head (mono caps eyebrow style). Pulse animation is tiny — gives
   "actually live" feel without being noisy. */
.form-template-status {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--green);
  background: var(--green-soft);
  padding: 5px 10px 5px 9px;
  border-radius: 999px;
  margin-bottom: 14px;
}
.form-status-dot {
  position: relative;
  width: 7px; height: 7px;
  border-radius: 999px;
  background: var(--green);
  flex-shrink: 0;
}
.form-status-dot::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 999px;
  animation: form-live-pulse 1.8s ease-out infinite;
}
@keyframes form-live-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(63, 122, 71, 0.55); }
  70%  { box-shadow: 0 0 0 7px rgba(63, 122, 71, 0); }
  100% { box-shadow: 0 0 0 0 rgba(63, 122, 71, 0); }
}

/* === Form rules — hairline-divided sub-section inside the v6 card ====
   Sits below the URL chip, separated by a hairline. Title is a mono-caps
   eyebrow with an "Adjust in Settings →" deep-link on the right. Rules
   render as a 2-column grid of compact text + dot rows — no chip pills
   (the v6 card already provides surface; chips on chips reads as nested
   boxes). Each row deep-links to its specific Settings panel. */
.form-setup-rail {
  margin: 22px -22px 0;
  padding: 16px 22px 22px;
  background: transparent;
  border: 0;
  border-top: 1px solid var(--hairline);
  border-radius: 0;
}
.form-setup-rail-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 4px;
}
.form-setup-rail-head {
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.form-setup-rail-cta {
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 0;
  border-bottom: 1px solid var(--hairline-2);
  transition: border-color 0.12s ease;
}
.form-setup-rail-cta:hover { border-bottom-color: var(--ink-mute); }
.form-setup-rail-cta svg { flex-shrink: 0; }
.form-setup-rail-chips {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px 18px;
}
.setup-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 0;
  font-size: 0.86rem;
  background: transparent;
  border: 0;
  color: var(--ink);
  text-decoration: none;
  transition: color 0.12s ease;
}
@media (hover: hover) { .setup-chip:hover .setup-chip-label { color: var(--ink); } }
.setup-chip-dot {
  width: 6px; height: 6px;
  border-radius: 999px;
  background: var(--ink-faint, #a8a29e);
  flex-shrink: 0;
}
.setup-chip[data-state="set"] .setup-chip-dot   { background: var(--green); }
.setup-chip[data-state="not-set"] .setup-chip-dot { background: var(--red); }
.setup-chip-label {
  flex: 1;
  font-weight: 500;
  color: var(--ink);
}
.setup-chip-state {
  color: var(--ink-mute);
  font-size: 0.78rem;
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
}
.setup-chip[data-state="not-set"] .setup-chip-state { color: var(--red); font-weight: 500; }
@media (max-width: 420px) {
  .form-setup-rail-chips { grid-template-columns: 1fr; }
}

/* Two-column grid: editor on left, customer preview on right. Stacks on
   mobile so the editor takes priority.
   Lives as a sibling of .form-template (the v6 hero card above it) — got
   its own paper surface so the visual treatment of the editor + preview
   content stays exactly as it was when the grid sat inside .form-template. */
.form-template-grid {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: 24px;
  align-items: start;
  background: var(--paper, #fff);
  border: 1px solid var(--hairline);
  border-radius: 14px;
  padding: 22px;
  margin-bottom: 24px;
}
@media (max-width: 880px) {
  .form-template-grid { grid-template-columns: 1fr; }
}

.form-template-editor { min-width: 0; }
.form-template-preview {
  min-width: 0;
  position: sticky;
  top: 24px;
}
.form-preview-eyebrow {
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 10px;
}
.form-preview-frame {
  background: #EEEEF0;
  border: 1px solid var(--hairline);
  border-radius: 14px;
  padding: 22px;
}

/* Customer-side mockup card — looks like the form on the embedded site. */
.fp-card {
  background: var(--paper, #fff);
  border-radius: 12px;
  padding: 20px 20px 18px;
  box-shadow: 0 8px 24px -10px rgba(31, 22, 17, 0.18), 0 1px 2px rgba(31, 22, 17, 0.04);
}
.fp-bizname {
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 4px;
}
.fp-title {
  font-family: 'Newsreader', Georgia, serif;
  font-style: italic;
  font-weight: 500;
  font-size: 1.35rem;
  color: var(--ink);
  margin-bottom: 16px;
  letter-spacing: -0.015em;
}
.fp-row {
  display: block;
  margin-bottom: 12px;
}
.fp-label {
  display: block;
  font-size: 0.78rem;
  color: var(--ink-mute);
  margin-bottom: 5px;
  font-weight: 500;
}
.fp-input, .fp-select, .fp-textarea, .fp-photo {
  background: var(--cream);
  border: 1px solid var(--hairline);
  border-radius: 7px;
  padding: 8px 10px;
  font-size: 0.78rem;
  color: var(--ink);
  min-height: 30px;
}
.fp-input--placeholder { color: var(--ink-faint); }
.fp-textarea { min-height: 56px; }
.fp-select {
  display: flex;
  align-items: center;
  justify-content: space-between;
  color: var(--ink-faint);
}
.fp-caret { color: var(--ink-mute); font-size: 0.7rem; }
.fp-slots { display: flex; gap: 6px; flex-wrap: wrap; }
.fp-slot {
  background: var(--cream);
  border: 1px solid var(--hairline);
  border-radius: 5px;
  padding: 4px 10px;
  font-size: 0.7rem;
  color: var(--ink);
}
.fp-slot.is-on { background: var(--ink); color: var(--cream, #FAFAFA); border-color: var(--ink); }
.fp-photo {
  text-align: center;
  color: var(--ink-faint);
  border-style: dashed;
  font-size: 0.74rem;
}
.fp-cta {
  width: 100%;
  background: var(--ink);
  color: var(--cream, #FAFAFA);
  border: 0;
  border-radius: 8px;
  padding: 10px;
  font-family: inherit;
  font-size: 0.86rem;
  font-weight: 500;
  margin-top: 8px;
  cursor: not-allowed;
  opacity: 0.95;
}
.fp-foot {
  text-align: center;
  font-size: 0.66rem;
  color: var(--ink-faint);
  margin-top: 10px;
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
  letter-spacing: 0.06em;
}
.form-template-section-title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-weight: 500;
  font-size: 0.95rem;
  color: var(--ink);
  margin: 0 0 4px;
}
.form-template-section-title--services {
  margin-top: 28px;
  padding-top: 18px;
  border-top: 1px solid var(--hairline);
}
.form-template-section-sub {
  font-size: 0.82rem;
  color: var(--ink-mute);
  margin: 0 0 12px;
  line-height: 1.45;
}

.form-fields-list {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--hairline);
  border-radius: 10px;
  overflow: hidden;
}
.form-field {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--hairline);
  background: var(--paper, #fff);
  transition: background 0.14s;
}
.form-field:last-child { border-bottom: 0; }
.form-field:hover { background: var(--cream); }
.form-field[data-hidden] { opacity: 0.5; }
.form-field[data-hidden] .form-field-label { text-decoration: line-through; }
.form-field-label {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: 1px solid transparent;
  padding: 5px 8px;
  border-radius: 6px;
  font-family: inherit;
  font-size: 0.92rem;
  color: var(--ink);
  outline: none;
  transition: background 0.14s, border-color 0.14s;
}
.form-field-label:hover { background: var(--cream-2); }
.form-field-label:focus {
  background: var(--paper, #fff);
  border-color: var(--ink-mute);
}
.form-field-type {
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  background: var(--cream-2);
  padding: 3px 8px;
  border-radius: 5px;
  flex-shrink: 0;
}
.form-field-meta {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
  font-size: 0.66rem;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
  text-transform: uppercase;
  flex-shrink: 0;
}
.form-field-toggle, .form-field-delete {
  background: transparent;
  border: 0;
  padding: 6px;
  border-radius: 6px;
  color: var(--ink-mute);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 0.14s, color 0.14s;
}
.form-field-toggle:hover { background: var(--cream-2); color: var(--ink); }
.form-field-delete:hover { background: rgba(199,74,28,0.1); color: var(--orange, #C74A1C); }

.form-field-add {
  margin-top: 12px;
  background: transparent;
  border: 1px dashed var(--hairline-2, var(--hairline));
  border-radius: 8px;
  padding: 10px 14px;
  font-family: inherit;
  font-size: 0.85rem;
  color: var(--ink-mute);
  cursor: pointer;
  width: 100%;
  text-align: center;
  transition: color 0.14s, border-color 0.14s, background 0.14s;
}
.form-field-add:hover {
  color: var(--ink);
  border-color: var(--ink-mute);
  background: var(--cream);
}

/* Service-picker row — clickable to expand the inline services panel. */
.form-field--picker { background: var(--cream); }
.form-field-services-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--paper, #fff);
  border: 1px solid var(--hairline);
  border-radius: 7px;
  padding: 5px 10px;
  font-family: inherit;
  font-size: 0.78rem;
  color: var(--ink);
  cursor: pointer;
  flex-shrink: 0;
  transition: border-color 0.14s, background 0.14s;
}
.form-field-services-btn:hover { border-color: var(--ink-mute); background: var(--cream-2); }
.form-field-services-count { font-weight: 500; }
.form-field-services-chev {
  display: inline-flex;
  color: var(--ink-mute);
  transition: transform 0.18s cubic-bezier(0.2, 0, 0, 1);
}
.form-field-services-btn[aria-expanded="true"] .form-field-services-chev {
  transform: rotate(180deg);
}

/* Services panel that expands under the picker row. Sits inside the
   field-list container, separated by hairlines from neighbour rows. */
.form-services-panel {
  background: var(--cream-2);
  border-bottom: 1px solid var(--hairline);
}
.form-services-panel-inner {
  padding: 18px 18px 18px;
}
.form-services-title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-weight: 500;
  font-size: 0.92rem;
  color: var(--ink);
  margin: 0 0 4px;
}
.form-services-sub {
  font-size: 0.8rem;
  color: var(--ink-mute);
  margin: 0 0 12px;
  line-height: 1.45;
}
.form-services-empty {
  font-size: 0.85rem;
  color: var(--ink-faint);
  margin: 0 0 14px;
  padding: 12px 0;
  text-align: center;
}
.form-services-list {
  display: flex;
  flex-direction: column;
  background: var(--paper, #fff);
  border: 1px solid var(--hairline);
  border-radius: 8px;
  overflow: hidden;
  margin-bottom: 14px;
}

/* jt-card list nested inside the inline services panel — slightly tighter
   spacing + drop the outer wrapper background since the panel already
   provides the cream tint. */
.jt-list--in-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 14px;
}

/* Compact card variant for the inline panel. The full .jt-card grid was
   designed for the standalone Job types page (~880px); inside the picker
   panel it's ~440px wide, so the head + actions overlap and stats wrap
   awkwardly. Override to a clean vertical flow with the duplicates hidden. */
.jt-list--in-panel .jt-card {
  display: block !important;
  padding: 14px 16px !important;
  background: var(--paper, #fff) !important;
  border-radius: 10px;
}
.jt-list--in-panel .jt-icon { display: none !important; }

/* Head: name + small status pill on one row, actions on the right. */
.jt-list--in-panel .jt-head {
  display: flex !important;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 8px;
}
.jt-list--in-panel .jt-name {
  font-size: 1rem !important;
  font-weight: 500;
  margin: 0;
  flex: 1 1 auto;
  min-width: 0;
}
/* Drop the AUTO-CONFIRM / BOOKABLE pills — same info shown by the toggles
   in .jt-fields below, no need to duplicate. */
.jt-list--in-panel .jt-pill { display: none !important; }
.jt-list--in-panel .jt-status-pill {
  font-size: 0.66rem;
  padding: 3px 8px;
  margin-left: 4px;
}

/* Stats row (Avg / Deposit) — sits inline under the name, compact. */
.jt-list--in-panel .jt-stats {
  display: flex !important;
  flex-wrap: nowrap;
  gap: 8px;
  font-size: 0.78rem;
  color: var(--ink-mute);
  margin: 0 0 10px;
}
.jt-list--in-panel .jt-stats strong {
  color: var(--ink);
  font-weight: 500;
}
.jt-list--in-panel .jt-stats .dot {
  display: inline-block;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--ink-faint);
  align-self: center;
}

/* Actions: small text buttons in the head row, right-aligned. */
.jt-list--in-panel .jt-actions {
  display: inline-flex !important;
  gap: 4px;
  margin: 0 0 0 auto;
  flex-shrink: 0;
}
.jt-list--in-panel .jt-action {
  font-size: 0.76rem !important;
  padding: 4px 10px !important;
  border-radius: 6px;
}

/* Fields grid (toggleable controls) — 2 columns when narrow. Hide the
   static Duration + Deposit fields since .jt-stats above already shows
   them; keep only the toggle fields. */
.jt-list--in-panel .jt-fields {
  grid-template-columns: repeat(2, 1fr) !important;
  gap: 8px !important;
  padding: 10px 0 !important;
  margin: 0 !important;
  border-top: 1px solid var(--hairline) !important;
  border-bottom: 1px solid var(--hairline) !important;
}
.jt-list--in-panel .jt-field {
  padding: 6px 0 !important;
}
/* Static Duration + Deposit fields are always the first two .jt-field
   children — they duplicate the .jt-stats row above. Hide so only the
   functional toggle fields (Auto-confirm + After-hours) remain. */
.jt-list--in-panel .jt-fields .jt-field:nth-child(1),
.jt-list--in-panel .jt-fields .jt-field:nth-child(2) { display: none !important; }

/* Keywords row + booking row stay but get tighter spacing. */
.jt-list--in-panel .jt-keywords {
  padding: 10px 0 6px !important;
  gap: 6px !important;
}
.jt-list--in-panel .jt-booking-row {
  padding: 8px 0 0 !important;
  border-top: 0 !important;
}
.jt-list--in-panel .jt-booking-row .set-toggle-name { font-size: 0.85rem; }
.jt-list--in-panel .jt-booking-row .set-toggle-desc { font-size: 0.75rem; }

/* Fallback card sits flush with the rest in the panel. */
.jt-list--in-panel .jt-card.is-fallback {
  background: var(--cream) !important;
  border: 1px dashed var(--hairline-2, var(--hairline));
}
.jt-list--in-panel .jt-card.is-fallback .jt-fallback-body {
  font-size: 0.82rem;
  margin-top: 8px;
}
.form-services-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--hairline);
}
.form-services-row:last-child { border-bottom: 0; }
.form-services-row-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.form-services-row-name {
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--ink);
}
.form-services-row-meta {
  font-size: 0.74rem;
  color: var(--ink-faint);
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
}
.form-services-row-remove {
  background: transparent;
  border: 0;
  padding: 6px;
  border-radius: 6px;
  color: var(--ink-mute);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
}
.form-services-row-remove:hover {
  background: rgba(199,74,28,0.1);
  color: var(--orange, #C74A1C);
}

.form-services-add-head {
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 8px;
}
.form-services-starters {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
  margin-bottom: 10px;
}
.form-services-starter {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 10px;
  background: var(--paper, #fff);
  border: 1px solid var(--hairline);
  border-radius: 7px;
  font-family: inherit;
  font-size: 0.82rem;
  color: var(--ink);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.14s, background 0.14s;
}
.form-services-starter:hover { border-color: var(--ink-mute); background: var(--cream); }
.form-services-starter svg { color: var(--ink-mute); flex-shrink: 0; }
.form-services-custom-add { margin-top: 0; }

/* === Forms tab — Lovable v2 redesign (cream cards, C2 buttons) ========== */

/* Warm border/shadow shorthand */
:root {
  --fd-border: rgba(31,22,17,0.06);
  --fd-border-btn: rgba(31,22,17,0.13);
  --fd-border-btn-bot: rgba(31,22,17,0.19);
  --fd-shadow-card: 0 1px 2px rgba(31,22,17,0.04);
  --fd-card-bg: #F5F5F5;
  --fd-card-radius: 12px;
}

/* Page title + subtitle */
.fd-page-title {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 4px;
}
.fd-page-sub {
  font-size: 0.875rem;
  color: #6B5A4C;
  margin: 0 0 16px;
  line-height: 1.5;
}

/* Generic bordered card (cream fill) */
.fd-card {
  background: var(--fd-card-bg);
  border: 1px solid var(--fd-border);
  border-radius: var(--fd-card-radius);
  box-shadow: var(--fd-shadow-card);
  overflow: hidden;
  margin-bottom: 8px;
}

/* C2 button — white gradient on cream, 3D feel */
.fd-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font-family: inherit; font-size: 0.8125rem; font-weight: 500;
  color: var(--ink);
  background: linear-gradient(180deg, #FFFFFF 0%, #F8F8F8 100%);
  border: 1px solid var(--fd-border-btn);
  border-bottom-color: var(--fd-border-btn-bot);
  border-radius: 8px;
  padding: 7px 14px;
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(31,22,17,0.07), 0 2px 1px -1px rgba(31,22,17,0.04), inset 0 1px 0 rgba(255,255,255,0.9);
  transition: all 0.15s ease;
  -webkit-tap-highlight-color: transparent;
  text-decoration: none;
}
.fd-btn:hover { border-color: rgba(31,22,17,0.2); border-bottom-color: rgba(31,22,17,0.26); box-shadow: 0 2px 5px rgba(31,22,17,0.09), 0 2px 1px -1px rgba(31,22,17,0.04), inset 0 1px 0 rgba(255,255,255,0.9); }
.fd-btn:active { transform: translateY(0.5px); box-shadow: 0 0 2px rgba(31,22,17,0.05), inset 0 1px 0 rgba(255,255,255,0.7); }
.fd-btn svg { width: 13px; height: 13px; }

/* Ghost button — transparent on cream */
.fd-btn--ghost {
  background: transparent;
  border: 1px solid rgba(31,22,17,0.1);
  box-shadow: none;
  color: #6B5A4C;
}
.fd-btn--ghost:hover { border-color: rgba(31,22,17,0.18); color: var(--ink); background: rgba(31,22,17,0.02); box-shadow: none; }
.fd-btn--ghost:active { box-shadow: none; }

/* Section link */
.fd-section-link {
  font-size: 0.8125rem;
  font-weight: 500;
  color: #6B5A4C;
  text-decoration: none;
}
.fd-section-link:hover { color: var(--ink); }

/* Rules rows */
.fd-rule {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 11px 16px;
  font-size: 0.875rem;
  color: var(--ink);
  text-decoration: none;
  transition: background 0.12s;
}
.fd-rule + .fd-rule { border-top: 1px solid var(--fd-border); }
@media (hover: hover) { .fd-rule:hover { background: rgba(31,22,17,0.02); } }
.fd-rule__dot { display: none; }
.fd-rule__label { font-weight: 500; }
.fd-rule__value {
  font-size: 0.875rem;
  color: #A39585;
  display: flex;
  align-items: center;
  gap: 4px;
}
.fd-rule__value::after {
  content: '\203A';
  font-size: 1.1rem;
  color: #CCC;
  line-height: 1;
  margin-left: 2px;
}
.fd-rule[data-state="not-set"] .fd-rule__value { color: var(--red, #C74A1C); }

/* Inline rules — flat rows without a card wrapper */
.fd-rules-inline .fd-rule { padding: 13px 0; }
.fd-rules-inline .fd-rule:first-child { border-top: 1px solid var(--fd-border); }

/* Connection card — three-state status dot (green / amber / gray)
   driven by data-dot, set by hydrateFdConnection() in wire.js. The two
   surfaces (embedded landing-page widget + standalone /book or /quote
   link) are rendered as a stack of label/value rows so the tradie can
   see at a glance which path is live. */
.fd-connection {
  background: var(--fd-card-bg);
  border: 1px solid var(--fd-border);
  border-radius: var(--fd-card-radius);
  box-shadow: var(--fd-shadow-card);
  padding: 14px 16px;
  margin-bottom: 0;
}
.fd-connection__status {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}
.fd-connection__dot {
  width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
  background: #A39585;
}
.fd-connection[data-dot="green"] .fd-connection__dot { background: #22C55E; }
.fd-connection[data-dot="amber"] .fd-connection__dot { background: #D97706; }
.fd-connection[data-dot="gray"]  .fd-connection__dot { background: #A39585; }
.fd-connection__title { font-size: 1.1rem; font-weight: 600; color: var(--ink); }
.fd-connection__surfaces {
  display: flex; flex-direction: column; gap: 8px;
  padding-top: 10px; margin-top: 4px;
  border-top: 1px solid var(--fd-border);
}
.fd-connection__surface {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px; font-size: 0.82rem;
}
.fd-connection__surface--url { align-items: flex-start; flex-direction: column; gap: 4px; }
.fd-connection__surface-label { color: #6B5A4C; }
.fd-connection__surface-val { color: var(--ink); font-weight: 500; }
.fd-connection[data-state="connected"] .fd-connection__surface-val { color: #16a34a; }
.fd-connection[data-state="wrong-flow"] .fd-connection__surface-val,
.fd-connection[data-state="paused"]     .fd-connection__surface-val { color: #92400E; }
.fd-connection__url-row {
  display: flex; align-items: center; gap: 8px;
  width: 100%;
  font-size: 0.82rem;
}
.fd-connection__url {
  flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--ink); text-decoration: none;
  font-family: 'JetBrains Mono', 'IBM Plex Mono', monospace;
  font-size: 0.78rem;
}
.fd-connection__url:hover { text-decoration: underline; }
.fd-connection__copy { padding: 5px 12px; font-size: 0.75rem; flex-shrink: 0; }
.fd-connection__count {
  margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--fd-border);
  font-family: 'Geist Mono', 'JetBrains Mono', monospace;
  font-size: 0.7rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: #A39585;
}
/* Action CTA — reuses .fd-btn for the 3d white-gradient look that
   matches every other primary action on the Forms page. Just add the
   margin-top to space it below the count line. */
.fd-connection__action { margin-top: 12px; }

/* Block section */
.fd-block { margin: 20px 0 10px; }
.fd-block__head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
}
.fd-block__title { font-size: 1rem; font-weight: 600; color: var(--ink); }
.fd-block__count { font-size: 0.8125rem; color: #A39585; font-weight: 400; margin-left: 8px; }
.fd-block__sub { font-size: 0.8125rem; color: #6B5A4C; margin: 4px 0 0; line-height: 1.45; }

/* Field rows — cream card */
.fd-field-list {
  background: var(--fd-card-bg);
  border: 1px solid var(--fd-border);
  border-radius: var(--fd-card-radius);
  box-shadow: var(--fd-shadow-card);
  overflow: hidden;
}
.fd-field {
  display: flex; flex-direction: column; gap: 0; padding: 0 18px;
}
.fd-field + .fd-field { border-top: 1px solid var(--fd-border); }
.fd-field[data-hidden] { opacity: 0.45; }
.fd-field__row { display: flex; align-items: center; gap: 8px; padding: 10px 0 3px; }
.fd-field:not(:has(.fd-field__hint)) .fd-field__row { padding-bottom: 10px; }
.fd-field__hint { font-size: 0.6875rem; color: #A39585; line-height: 1.3; padding: 0 0 9px 4px; }
.fd-field__hint-link { color: #6B5A4C; font-weight: 500; text-decoration: none; }
.fd-field__hint-link:hover { color: var(--ink); }
.fd-field__dot { display: none; }
.fd-field__name {
  flex: 1; min-width: 0; font-size: 0.8125rem; font-weight: 500; color: var(--ink);
  background: transparent; border: 1px solid transparent; padding: 2px 4px;
  border-radius: 4px; font-family: inherit; outline: none;
  transition: background 0.14s, border-color 0.14s;
}
.fd-field__name:hover { background: rgba(31,22,17,0.03); }
.fd-field__name:focus { background: transparent; border-color: rgba(31,22,17,0.15); }
.fd-field__type {
  font-size: 0.6875rem; font-weight: 500; letter-spacing: 0.04em;
  text-transform: uppercase; color: #A39585; flex-shrink: 0;
  min-width: 56px; text-align: right; margin-right: 4px;
}
.fd-field__lock {
  color: #CCC; display: flex; align-items: center; justify-content: center;
  width: 28px; flex-shrink: 0;
}
.fd-field__lock svg { width: 14px; height: 14px; }

/* Toggle — indigo */
.fd-toggle {
  position: relative; width: 40px; height: 22px; border-radius: 11px;
  background: #D1D5DB; border: 0; cursor: pointer; flex-shrink: 0;
  transition: background 0.2s; padding: 0;
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.08);
}
.fd-toggle::after {
  content: ''; position: absolute; top: 2px; left: 2px;
  width: 18px; height: 18px; border-radius: 50%;
  background: #FFFFFF; box-shadow: 0 1px 3px rgba(0,0,0,0.15);
  transition: transform 0.2s;
}
.fd-toggle.is-on { background: #4F46E5; box-shadow: none; }
.fd-toggle.is-on::after { transform: translateX(18px); }

/* Delete button */
.fd-field__delete {
  background: transparent; border: 0; padding: 4px; border-radius: 4px;
  color: #CCC; cursor: pointer; display: inline-flex; align-items: center;
  justify-content: center; transition: color 0.14s; flex-shrink: 0; margin-left: 2px;
}
.fd-field__delete:hover { color: var(--orange, #C74A1C); }
.fd-field__delete svg { width: 12px; height: 12px; }

/* Service cards — cream fill */
.fd-svc-list { display: flex; flex-direction: column; gap: 8px; }
.fd-svc {
  background: var(--fd-card-bg);
  border: 1px solid var(--fd-border);
  border-radius: var(--fd-card-radius);
  box-shadow: var(--fd-shadow-card);
  transition: border-color 0.14s;
  overflow: hidden;
}
.fd-svc:hover { border-color: rgba(31,22,17,0.12); }
.fd-svc__head {
  display: flex; align-items: center; gap: 12px; padding: 14px 18px;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.fd-svc__body { flex: 1; min-width: 0; }
.fd-svc__name { font-size: 0.9375rem; font-weight: 600; color: var(--ink); }
.fd-svc__meta { font-size: 0.8125rem; color: #6B5A4C; margin-top: 3px; }
.fd-svc__pill {
  font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: #22C55E;
  background: rgba(34,197,94,0.08); padding: 3px 8px;
  border-radius: 4px; flex-shrink: 0;
}
.fd-svc__pill.is-quote { background: rgba(31,22,17,0.04); color: #A39585; }
.fd-svc__chev { display: inline-flex; color: #CCC; flex-shrink: 0; transition: transform 0.2s; }
.fd-svc.is-open .fd-svc__chev { transform: rotate(180deg); }

/* Detail expand */
.fd-svc__detail-wrap {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows 0.28s cubic-bezier(0.2, 0, 0, 1);
}
.fd-svc.is-open .fd-svc__detail-wrap { grid-template-rows: 1fr; }
.fd-svc__detail { overflow: hidden; opacity: 0; transition: opacity 0.22s ease; }
.fd-svc.is-open .fd-svc__detail { opacity: 1; transition: opacity 0.22s ease 0.06s; }
.fd-svc__detail-inner { padding: 14px 18px 16px; border-top: 1px solid var(--fd-border); }
.fd-svc__stats { display: flex; gap: 14px; flex-wrap: wrap; font-size: 0.8125rem; color: #6B5A4C; padding: 8px 0; }
.fd-svc__stats strong { color: var(--ink); font-weight: 600; }
.fd-svc__stats .dot { display: inline-block; width: 3px; height: 3px; border-radius: 50%; background: #CCC; align-self: center; }
.fd-svc__toggles { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; padding: 10px 0; border-top: 1px solid var(--fd-border); border-bottom: 1px solid var(--fd-border); }
.fd-svc__toggles .jt-field { padding: 6px 0; }
.fd-svc__detail-inner .jt-booking-row { padding: 8px 0 0; border-top: 0; }
.fd-svc__detail-inner .set-toggle-name { font-size: 0.85rem; }
.fd-svc__detail-inner .set-toggle-desc { font-size: 0.75rem; }
.fd-svc__actions { display: flex; gap: 6px; padding-top: 12px; border-top: 1px solid var(--fd-border); margin-top: 8px; }
.fd-svc__btn {
  font-family: inherit; font-size: 0.8125rem; font-weight: 500;
  color: #6B5A4C; background: transparent;
  border: 1px solid rgba(31,22,17,0.1); border-radius: 6px;
  padding: 6px 12px; cursor: pointer;
  transition: all 0.14s;
}
.fd-svc__btn:hover { border-color: rgba(31,22,17,0.18); color: var(--ink); }
.fd-svc__btn.is-danger:hover { color: var(--orange); border-color: var(--orange-deep); }

/* Add service */
.fd-add-row {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 14px 18px;
  border: 1px dashed rgba(31,22,17,0.15); border-radius: var(--fd-card-radius);
  font-family: inherit; font-size: 0.875rem; font-weight: 500;
  color: #6B5A4C; cursor: pointer; background: transparent;
  width: 100%; box-sizing: border-box;
  transition: color 0.15s, border-color 0.15s;
}
.fd-add-row:hover { border-color: rgba(31,22,17,0.25); color: var(--ink); }
.fd-add-row svg { width: 14px; height: 14px; }

/* Quick-add chips — C2 pill style */
.fd-quick { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.fd-quick__chip {
  display: inline-flex; align-items: center;
  padding: 6px 16px;
  background: linear-gradient(180deg, #FFFFFF 0%, #F8F8F8 100%);
  border: 1px solid var(--fd-border-btn);
  border-bottom-color: var(--fd-border-btn-bot);
  border-radius: 100px;
  font-family: inherit; font-size: 0.8125rem; font-weight: 500;
  color: var(--ink); cursor: pointer;
  box-shadow: 0 1px 2px rgba(31,22,17,0.05), inset 0 1px 0 rgba(255,255,255,0.9);
  transition: all 0.15s;
}
.fd-quick__chip:hover { border-color: rgba(31,22,17,0.2); border-bottom-color: rgba(31,22,17,0.26); box-shadow: 0 2px 4px rgba(31,22,17,0.07), inset 0 1px 0 rgba(255,255,255,0.9); }

/* === Job types empty state — Builder-tier substantive markup ============ */
.jt-empty {
  display: flex;
  flex-direction: column;
  gap: 22px;
  padding: 8px 0 0;
}
.jt-empty-card {
  background: var(--paper, #fff);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 28px 32px;
}
.jt-empty-title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-weight: 500;
  font-size: 1.5rem;
  letter-spacing: -0.018em;
  color: var(--ink);
  margin: 0 0 8px;
}
.jt-empty-sub {
  font-size: 0.95rem;
  color: var(--ink-mute);
  line-height: 1.55;
  margin: 0;
  max-width: 64ch;
  text-wrap: pretty;
}
.jt-starter-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}
.jt-starter-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  background: var(--paper, #fff);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--ink);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.18s cubic-bezier(0.2, 0, 0, 1), background 0.18s cubic-bezier(0.2, 0, 0, 1), transform 0.18s cubic-bezier(0.2, 0, 0, 1);
}
.jt-starter-chip:hover {
  border-color: var(--ink-mute);
  background: var(--cream-2);
  transform: translateY(-1px);
}
.jt-starter-chip svg { color: var(--ink-mute); flex-shrink: 0; }
.jt-starter-chip:disabled { cursor: not-allowed; }
.jt-empty-foot {
  display: flex;
  align-items: center;
  gap: 14px;
  padding-top: 4px;
  flex-wrap: wrap;
}
.jt-empty-foot .btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.jt-empty-foot-meta {
  font-size: 0.85rem;
  color: var(--ink-mute);
  line-height: 1.4;
}
@media (max-width: 720px) {
  .jt-starter-row { grid-template-columns: 1fr; }
  .jt-empty-card { padding: 22px; }
}

@media (max-width: 640px) {
  .jt-card {
    grid-template-columns: 40px minmax(0, 1fr);
  }
  .jt-icon { grid-row: 1; width: 40px; height: 40px; }
  .jt-actions {
    grid-column: 1 / -1;
    grid-row: auto;
    margin-top: 8px;
    flex-wrap: wrap;
  }
  .jt-stats { grid-column: 1 / -1; }
  .jt-head { grid-column: 2; }
  .jt-fields, .jt-keywords { grid-column: 1 / -1; }
}

/* ============================================================================
   Phase 1 polish: focus rings, rp-chip pill, sticky save bar glass, tabular nums
   ========================================================================== */

/* rp-chip filter pills (Booking requests) — match .chip pattern */
.rp-chip {
  background: transparent;
  border: 1px solid var(--hairline-2);
  padding: 6px 12px;
  border-radius: 6px;
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--ink-mute);
  cursor: pointer;
  transition: background 0.18s cubic-bezier(0.2, 0, 0, 1), color 0.18s cubic-bezier(0.2, 0, 0, 1), border-color 0.18s cubic-bezier(0.2, 0, 0, 1);
}
.rp-chip:hover { border-color: var(--hairline-3); color: var(--ink); }
.rp-chip.is-active {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--cream);
}
.rp-chip-count {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.6rem;
  margin-left: 6px;
  color: var(--ink-faint);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
}
.rp-chip.is-active .rp-chip-count { color: rgba(255,255,255,0.6); }

/* Focus rings on settings inputs (theme-aware orange wash) */
.set-input:focus, .set-textarea:focus, .set-select:focus {
  box-shadow: 0 0 0 3px var(--orange-wash);
}
.set-input:focus-visible, .set-textarea:focus-visible, .set-select:focus-visible {
  outline: 0;
  border-color: var(--ink-mute);
  box-shadow: 0 0 0 3px var(--orange-wash);
}
.rp-conv-search:focus {
  outline: none;
  border-color: var(--ink-mute);
  box-shadow: 0 0 0 3px var(--orange-wash);
}
.rp-conv-compose textarea:focus {
  box-shadow: 0 0 0 3px var(--orange-wash);
}
.rp-meta-notes:focus {
  outline: none;
  border-color: var(--ink-mute);
  box-shadow: 0 0 0 3px var(--orange-wash);
}

/* Glass on sticky save bar. The base sticky/border/padding chrome is in
   dashboard-v2.css under "Settings sticky save bar" — this only paints the
   glass background so the rule sits next to the rest of the glass surfaces. */
.set-actions {
  background: var(--glass-bg) !important;
  backdrop-filter: saturate(140%) blur(14px) !important;
  -webkit-backdrop-filter: saturate(140%) blur(14px) !important;
}

/* Sticky settings rail — transparent on desktop so it reads as part
   of the page surface (Claude-style), not a separate white card.
   Hover + active fills on .set-rail-link still pop because they use
   warm cream tones darker than the page background. */
@media (min-width: 901px) {
  .set-rail {
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

/* Tabular numerals — sub-page-specific number-bearing classes */
.intg-status, .jt-stats, .jt-stats strong, .jt-pill, .jt-keyword,
.set-account-val, .set-mini-intg-status, .ntf-quiet-meta, .ntf-quiet-range,
.rp-row-meta, .rp-thread-time, .rp-msg-time, .rp-msg-status,
.rp-conv-head-meta, .rp-meta-customer-meta, .rp-meta-booking-status,
.cal-time-cell, .cal-event-time, .cal-event-meta, .cal-sync-meta,
.pay-cust-sub, .pay-amt, .pay-pill, .pay-date, .pay-inv,
.set-pill, .chip-count, .rich-subtitle, .pg-sub,
.set-account-label, .jt-field-value, .jt-field-label {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
}

/* === Print styles ======================================================== */
@media print {
  body { background: #fff !important; }
  .side, .mobile-nav, .upsell, .attention-strip, .empty-card-back, .btn, .pg-actions, .rich-actions, [data-no-print] { display: none !important; }
  .shell { grid-template-columns: 1fr !important; }
  .dash, .pg, .rich-page { padding: 24px !important; max-width: 720px; margin: 0 auto; }
  .metric, .set-card, .pay-card, .activity-feed, .rec-hero, .site-card, .panel, .upsell {
    box-shadow: none !important;
    border: 1px solid #ddd !important;
    page-break-inside: avoid;
    background: #fff !important;
  }
  .pg-head, .rich-head, .dash-greeting { border-bottom: 1px solid #999; padding-bottom: 12px; margin-bottom: 16px; }
  .pg-head::after { content: 'BookingSprint · Printed ' attr(data-print-date); display: block; font-size: 0.7rem; color: #666; margin-top: 6px; font-family: 'JetBrains Mono', monospace; }
  a { color: #1F1611 !important; text-decoration: underline; }
  a[href]::after { content: ' (' attr(href) ')'; font-size: 0.7em; color: #666; }
  /* Tabular alignment for printed lists */
  .pay-row, .activity-feed { font-variant-numeric: tabular-nums; }
}

/* ---------- Live AI choreography (Conversations) ---------- */

/* 1. Typewriter cursor */
.rp-msg-typer { display: inline; }
.rp-msg.is-typing::after {
  content: '';
  display: inline-block;
  width: 2px;
  height: 1em;
  background: currentColor;
  margin-left: 2px;
  vertical-align: text-bottom;
  animation: bs-cursor-blink 0.9s step-end infinite;
}
@keyframes bs-cursor-blink {
  50% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .rp-msg.is-typing::after { display: none; }
}

/* 3. Thinking-state diamond-rosette */
@keyframes bs-diamond-pulse-1 { 0%, 100% { opacity: 0.3; } 12% { opacity: 1; } }
@keyframes bs-diamond-pulse-2 { 0%, 100% { opacity: 0.3; } 24% { opacity: 1; } }
@keyframes bs-diamond-pulse-3 { 0%, 100% { opacity: 0.3; } 36% { opacity: 1; } }
@keyframes bs-diamond-pulse-4 { 0%, 100% { opacity: 0.3; } 48% { opacity: 1; } }
@keyframes bs-diamond-pulse-5 { 0%, 100% { opacity: 0.3; } 60% { opacity: 1; } }
@keyframes bs-diamond-pulse-6 { 0%, 100% { opacity: 0.3; } 72% { opacity: 1; } }
@keyframes bs-diamond-pulse-7 { 0%, 100% { opacity: 0.3; } 84% { opacity: 1; } }
@keyframes bs-diamond-pulse-8 { 0%, 100% { opacity: 0.3; } 96% { opacity: 1; } }
.bs-thinking-mark {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: var(--orange-wash, rgba(217, 84, 30, 0.08));
  border: 1px solid var(--hairline);
  border-radius: 12px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--orange);
  font-weight: 600;
}
.bs-thinking-mark svg { width: 16px; height: 16px; }
.bs-thinking-mark svg .d:nth-child(1) { animation: bs-diamond-pulse-1 1.6s ease-in-out infinite; transform-origin: center; }
.bs-thinking-mark svg .d:nth-child(2) { animation: bs-diamond-pulse-2 1.6s ease-in-out infinite; transform-origin: center; }
.bs-thinking-mark svg .d:nth-child(3) { animation: bs-diamond-pulse-3 1.6s ease-in-out infinite; transform-origin: center; }
.bs-thinking-mark svg .d:nth-child(4) { animation: bs-diamond-pulse-4 1.6s ease-in-out infinite; transform-origin: center; }
.bs-thinking-mark svg .d:nth-child(5) { animation: bs-diamond-pulse-5 1.6s ease-in-out infinite; transform-origin: center; }
.bs-thinking-mark svg .d:nth-child(6) { animation: bs-diamond-pulse-6 1.6s ease-in-out infinite; transform-origin: center; }
.bs-thinking-mark svg .d:nth-child(7) { animation: bs-diamond-pulse-7 1.6s ease-in-out infinite; transform-origin: center; }
.bs-thinking-mark svg .d:nth-child(8) { animation: bs-diamond-pulse-8 1.6s ease-in-out infinite; transform-origin: center; }
@media (prefers-reduced-motion: reduce) {
  .bs-thinking-mark svg .d { animation: none; opacity: 1; }
}
.rp-thinking-row {
  display: flex;
  justify-content: flex-start;
  margin: var(--space-3, 12px) 0;
  padding-left: var(--space-3, 12px);
}

/* 4. AI confidence bar */
.rp-msg-confidence {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  margin-top: 6px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.56rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 600;
  max-width: 320px;
  align-self: flex-end;
}
.rp-confidence-label { color: var(--ink-mute); }
.rp-confidence-bar {
  flex: 1;
  height: 4px;
  background: var(--cream-2);
  border-radius: 999px;
  overflow: hidden;
}
.rp-confidence-fill {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--orange-soft), var(--orange));
  border-radius: 999px;
  width: 0;
  transition: width 0.8s var(--ease-out, cubic-bezier(0.2, 0, 0, 1));
}
.rp-msg-confidence.is-low .rp-confidence-fill { background: linear-gradient(90deg, var(--ink-faint), var(--ink-mute)); }
.rp-confidence-value { color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
  .rp-confidence-fill { transition: none; }
}

/* 5. Thread header AI active pill */
.rp-thread-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.56rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--green);
  background: var(--green-soft);
  padding: 3px 8px;
  border-radius: 999px;
  font-weight: 600;
  margin-left: 8px;
  vertical-align: middle;
}

/* 6. Live AI choreography (typewriter caret + status pill + suggestions) */
.is-typing { position: relative; }
.is-typing::after {
  content: '';
  display: inline-block;
  width: 2px; height: 1em;
  background: var(--orange);
  margin-left: 2px;
  vertical-align: text-bottom;
  animation: bs-caret 0.9s ease-in-out infinite;
}
@keyframes bs-caret {
  0%, 50% { opacity: 1; }
  51%, 100% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .is-typing::after { display: none; }
}

.ai-status {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 10px;
  background: var(--orange-wash);
  border-radius: 999px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--orange-deep);
  font-weight: 600;
  transition: background 0.4s var(--ease-out, cubic-bezier(0.2, 0, 0, 1)), color 0.4s var(--ease-out, cubic-bezier(0.2, 0, 0, 1));
}
.ai-status-mark rect {
  transform-origin: center;
  animation: bs-diamond-pulse-status 1.6s ease-in-out infinite;
}
.ai-status-mark .d1 { animation-delay: 0.00s; }
.ai-status-mark .d2 { animation-delay: 0.10s; }
.ai-status-mark .d3 { animation-delay: 0.20s; }
.ai-status-mark .d4 { animation-delay: 0.30s; }
.ai-status-mark .d5 { animation-delay: 0.40s; }
.ai-status-mark .d6 { animation-delay: 0.50s; }
.ai-status-mark .d7 { animation-delay: 0.60s; }
.ai-status-mark .d8 { animation-delay: 0.70s; }
@keyframes bs-diamond-pulse-status {
  0%, 100% { opacity: 0.3; transform: scale(1); }
  20%      { opacity: 1;   transform: scale(1.15); }
  60%      { opacity: 0.3; transform: scale(1); }
}
.ai-status.is-idle .ai-status-mark rect { animation-play-state: paused; opacity: 1; }
.ai-status.is-idle { background: var(--green-soft); color: var(--green); }
@media (prefers-reduced-motion: reduce) {
  .ai-status-mark rect { animation: none; opacity: 1; }
}

.ai-suggest-block {
  padding: 14px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--card-radius);
}
.ai-suggest-title {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.56rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 600;
  margin-bottom: 10px;
}
.ai-suggest {
  display: block; width: 100%; text-align: left;
  background: transparent; border: 0;
  padding: 8px 0;
  cursor: pointer;
  border-top: 1px solid var(--hairline);
  transition: background 0.18s cubic-bezier(0.2, 0, 0, 1), padding 0.18s cubic-bezier(0.2, 0, 0, 1);
  font-family: inherit;
}
.ai-suggest:first-of-type { border-top: 0; }
.ai-suggest:hover { background: var(--cream-2); padding-left: 8px; padding-right: 8px; border-radius: 8px; }
.ai-suggest-text {
  font-size: 0.86rem; color: var(--ink); font-weight: 500;
  margin-bottom: 6px; line-height: 1.4;
}
.ai-suggest-bar {
  height: 3px; background: var(--cream-3); border-radius: 999px; overflow: hidden;
  margin-bottom: 4px;
}
.ai-suggest-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--orange-soft), var(--orange));
  border-radius: 999px;
  transition: width 0.6s cubic-bezier(0.2, 0, 0, 1);
}
.ai-suggest-meta {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.58rem; letter-spacing: 0.1em;
  color: var(--ink-faint); text-transform: uppercase;
}
.ai-suggest-meta span { color: var(--ink); font-weight: 600; }

@keyframes rp-compose-flash {
  0%   { box-shadow: 0 0 0 0 rgba(217, 84, 30, 0.32); }
  100% { box-shadow: 0 0 0 6px rgba(217, 84, 30, 0); }
}
.rp-compose-flash { animation: rp-compose-flash 0.6s cubic-bezier(0.2, 0, 0, 1); }

/* Sidebar footer account card overrides — two-line stack (business + email)
   plus an icon-only sign-out button. Falls back gracefully if the email
   field is empty (no extra row). */
.side-foot { align-items: center; }
.side-foot-name {
  display: flex; flex-direction: column; gap: 1px;
  flex: 1 1 auto; min-width: 0;
  white-space: normal; overflow: hidden;
}
.side-foot-name-business {
  font-size: 13px; line-height: 1.2;
  color: var(--ink); font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.side-foot-name-email {
  font-size: 11px; line-height: 1.2;
  color: var(--ink-mute);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.side-foot-name-email:empty { display: none; }
.side-foot-signout {
  flex: 0 0 auto;
  width: 24px; height: 24px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 0; padding: 0;
  border-radius: 6px; cursor: pointer;
  color: var(--ink-mute);
  transition: background 0.18s ease, color 0.18s ease;
}
.side-foot-signout:hover { background: var(--cream-2); color: var(--ink); }
.side-foot-signout:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ============================================================================
   Mobile shell — top bar + side drawer (visible only at <720px).
   Hidden by default on desktop. Drawer slides in from the left over a
   semi-transparent backdrop. Esc + backdrop tap + nav-link tap all close it.
   ========================================================================== */
.mob-topbar { display: none; }
.mob-drawer-backdrop { display: none; }
.mob-drawer-close { display: none; }

@media (max-width: 899.98px) {
  .mob-topbar {
    display: flex;
    align-items: center;
    gap: 10px;
    height: 52px;
    padding: 0 12px;
    background: var(--topband);
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 70;
    will-change: transform;
  }
  /* Burger inherits C2 styling from dashboard-v2.css — no override needed */
  .mob-topbar-glass { display: none; }
  body.is-builder-chat .mob-topbar-glass { display: block; }
  .mob-topbar-title {
    flex: 1 1 auto;
    min-width: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    color: var(--ink);
  }
  .mob-topbar-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    line-height: 0;
    flex-shrink: 0;
  }
  .mob-topbar-mark svg { width: 100%; height: 100%; display: block; }
  .mob-topbar-mark .bs-logo-mark__d { fill: var(--ink); }
  .mob-topbar-name {
    font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--ink);
    letter-spacing: -0.01em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .mob-topbar-spacer {
    flex: 0 0 auto;
    width: 48px; height: 48px;
    display: inline-block;
  }

  /* Card-slide drawer: sidebar parked at left:0 below the card; page
     surface slides right to reveal it. See dashboard-v2.css for the
     full commentary — kept in sync here for sub-route SPA shell. */
  body { --drawer-offset: 0px; }
  body.mob-drawer-open { --drawer-offset: min(360px, 84vw); }

  .side {
    position: fixed !important;
    top: 0; left: 0;
    height: 100vh;
    width: min(360px, 84vw);
    transform: none;
    z-index: 1;
    border-right: 1px solid var(--hairline-2);
    display: flex !important;
    background: var(--topband);
  }

  .mob-topbar,
  .shell > main.dash,
  .shell > .pg,
  .shell > .rich-page {
    transform: translateX(var(--drawer-offset));
    transition: transform 0.32s cubic-bezier(0.2, 0, 0, 1),
                border-radius 0.32s cubic-bezier(0.2, 0, 0, 1),
                box-shadow 0.32s cubic-bezier(0.2, 0, 0, 1);
  }
  .mob-topbar { z-index: 70; }
  .shell > main.dash,
  .shell > .pg,
  .shell > .rich-page {
    position: relative;
    z-index: 10;
    background: var(--topband);
    /* Cover the sidebar even when content is shorter than viewport. */
    min-height: calc(100dvh - 52px);
  }

  body.mob-drawer-open .mob-topbar {
    border-top-left-radius: 22px;
    overflow: hidden;
    padding-left: 22px;
    box-shadow:
      -1px 0 0 0 rgba(31, 22, 17, 0.08),
      -6px 0 22px -8px rgba(31, 22, 17, 0.18);
  }
  body.mob-drawer-open .shell > main.dash,
  body.mob-drawer-open .shell > .pg,
  body.mob-drawer-open .shell > .rich-page {
    border-bottom-left-radius: 22px;
    box-shadow:
      -1px 0 0 0 rgba(31, 22, 17, 0.08),
      -6px 0 22px -8px rgba(31, 22, 17, 0.18);
  }
  .side { border-right: 0 !important; }

  .mob-drawer-backdrop {
    display: block;
    position: fixed;
    top: 0;
    bottom: 0;
    left: var(--drawer-offset);
    right: 0;
    background: transparent;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.22s cubic-bezier(0.2, 0, 0, 1),
                left 0.32s cubic-bezier(0.2, 0, 0, 1);
    z-index: 80;
  }
  body.mob-drawer-open .mob-drawer-backdrop {
    opacity: 1;
    pointer-events: auto;
  }

  /* Close X inside the drawer (mobile only). */
  .mob-drawer-close {
    display: inline-flex;
    align-items: center; justify-content: center;
    position: absolute;
    top: 12px; right: 12px;
    width: 28px; height: 28px;
    background: transparent;
    border: 0;
    border-radius: 6px;
    color: var(--ink-mute);
    cursor: pointer;
    z-index: 1;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0.1);
    touch-action: manipulation;
    user-select: none;
    -webkit-user-select: none;
  }
  .mob-drawer-close:hover { background: var(--cream-3); color: var(--ink); }
  .mob-drawer-close:active { background: var(--cream-3); color: var(--ink); }
  .mob-drawer-backdrop { touch-action: manipulation; }

  /* Lock body scroll when drawer is open. */
  body.mob-drawer-open { overflow: hidden; }

  /* The desktop floating "open sidebar" button is irrelevant on mobile. */
  .side-opener { display: none !important; }

  /* Hide the existing bottom-tab nav at <720px — drawer replaces it. */
  .mobile-nav { display: none !important; }

  /* Mobile padding + spacing for the editorial column. */
  .dash, .pg, .rich-page { padding: 16px 16px 32px; gap: 16px; }
  .dash { gap: 16px; }
  .dash-greeting h1 { font-size: clamp(1.5rem, 6vw, 1.85rem); }

  /* Hide the per-plan footer (billing / support links) — same info available
     in the drawer. Decorative on mobile, eats vertical space. */
  .foot { display: none !important; }
}

/* ============================================================================
   Empty-state primitive — shared across My site, AI builder, Inbound,
   Job types, Lead capture (and Domain when it lands). Single centred panel
   with icon, headline, one-line description, single primary CTA. Match
   the .set-card chassis (border + radius). Warm-stone tokens only.
   ========================================================================== */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 48px 24px;
  text-align: center;
  background: var(--paper, #FFFFFF);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  max-width: 560px;
  margin: 24px auto;
}
.empty-state__icon {
  width: 36px; height: 36px;
  color: var(--ink-mute);
  display: block;
}
.empty-state__title {
  font-family: 'Geist', 'Inter Tight', 'Inter', sans-serif;
  font-size: 1.2rem;
  font-weight: 500;
  color: var(--ink);
  margin: 0;
  max-width: 30ch;
  text-wrap: balance;
  letter-spacing: -0.005em;
}
.empty-state__desc {
  font-size: 0.92rem;
  color: var(--ink-mute);
  margin: 0;
  max-width: 50ch;
  line-height: 1.5;
}
.empty-state__cta {
  margin-top: 8px;
}
@media (max-width: 899.98px) {
  .empty-state { padding: 32px 20px; margin: 16px auto; }
}

/* =====================================================================
   Missed call recovery — v4 (founder reqs 2026-05-20)
   - Read-only SMS preview replaces editable textarea
   - 3 iPhone forwarding screenshots in Setup section
   - 3-way mode picker (Pro) + lock card (Starter)
   - "Both" link target removed (Booking OR Quote only)
   ===================================================================== */
.set-section-intro {
  font-size: 0.85rem;
  color: var(--ink-mute);
  line-height: 1.55;
  margin: 0 0 18px;
  max-width: 60ch;
}


/* ============================================================================
   2026-05-22 v5 — Mobile AI builder chat thread layout (canonical block)
   ============================================================================
   Final structure after several iterations. The whole page scrolls (window
   owns scroll, not chat-body). Topbar + composer are position:fixed at the
   viewport edges; everything in between flows naturally and scrolls past
   them. Chat content visibly passes behind the floating topbar buttons as
   the user scrolls.

   Why this block lives here (and not in dashboard-v2.css): cascade. The
   inline <style> at dashboard-v2-page.html:124+ was winning every fight
   we tried in dashboard-v2.css. The page-specific stylesheet (this file)
   is loaded BEFORE the inline <style> block in the document head — so by
   itself, the inline still wins. The rules below use !important on layout-
   critical properties AND a tight selector specificity (~0,4,1+) to beat
   both the inline rules and the long-standing flex defaults in dashboard-
   v2.css. The mobile media-query + body class + state-attribute scoping
   keeps it out of desktop / cards-view / ready-state layouts.

   Bottom-anchor (latest message just above the composer) is NOT done via
   CSS margin:auto tricks any more — that was fragile and depended on a
   chain of containers respecting child min-heights, which iOS Safari was
   collapsing. Instead, JS calculates the precise window.scrollTo target
   in _shellScrollToEnd (dashboard-v2-page-builder.js): "scroll the page
   so the last message's BOTTOM edge sits composer-height + 12px above
   the viewport bottom". Predictable, works on every browser, no flex
   math. */
@media (max-width: 720px) {

  /* ---- 1A. Containers must NOT clip or own scroll. The whole document
     scrolls (html/body). Every ancestor between body and chat-body gets
     overflow:visible + height:auto + display:block so a long thread
     grows the document naturally and a short thread doesn't trigger
     scroll. display:block kills the flex math that the bottom-anchor
     attempts kept losing to. */
  body.is-builder-chat:not(.is-builder-cards-view) .shell,
  body.is-builder-chat:not(.is-builder-cards-view) .shell > main.dash,
  body.is-builder-chat:not(.is-builder-cards-view) [data-rich-mount],
  body.is-builder-chat:not(.is-builder-cards-view) .builder-shell,
  body.is-builder-chat:not(.is-builder-cards-view) .builder-shell--centered:not([data-builder-state="ready"]),
  body.is-builder-chat:not(.is-builder-cards-view) .builder-card-wrap,
  body.is-builder-chat:not(.is-builder-cards-view) .builder-shell--centered:not([data-builder-state="ready"]) .builder-chat-pane,
  body.is-builder-chat:not(.is-builder-cards-view) .builder-shell--centered:not([data-builder-state="ready"]) .builder-chat-body {
    overflow: visible !important;
    height: auto !important;
    min-height: 0 !important;
    max-height: none !important;
  }

  /* ---- 1B. Body owns the scroll. Top padding clears the fixed topbar
     (so content doesn't start under it on cold start); bottom padding
     clears the fixed composer (so the last item can sit ABOVE the
     composer at end-of-thread). The composer-h CSS variable is set by
     the JS shellSyncChatPanePadBot helper after measuring the composer's
     actual rendered height. */
  body.is-builder-chat:not(.is-builder-cards-view) {
    min-height: 100dvh !important;
    padding-top: calc(52px + env(safe-area-inset-top, 0px)) !important;
    padding-bottom: calc(var(--bs-composer-h, 128px) + env(safe-area-inset-bottom, 0px) + 12px) !important;
    overflow-x: hidden !important;
    overscroll-behavior-y: contain !important;
  }

  /* ---- 1C. Topbar fixed at viewport top. Some computed-style runs
     reported position:sticky which TAKES FLOW SPACE — that pushed
     main.dash down by 52px (verified via Playwright: paneRectTop=104
     instead of 52). Forcing fixed here ensures topbar is out of flow
     and the body padding-top reserve is the ONLY top-clearance for
     content. */
  body.is-builder-chat:not(.is-builder-cards-view) .mob-topbar {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
  }

  /* ---- 1C-bis. Frosted-glass blur band above the chat content. Sits
     BELOW the floating topbar buttons (which have z:71 + their own
     paper bg) but ABOVE chat content (default z:0). Backdrop-filter
     blurs whatever scrolls underneath; mask-image fades the blur
     intensity quadratically so the bottom of the band is invisible
     (content scrolls into a totally clear area) and the top is full
     frost (content disappears into the topbar). Gated on @supports
     so iOS Safari builds without backdrop-filter fall back to the
     existing transparent-topbar look (still works, just no blur).
     The band is on body::before because body::after may be used
     elsewhere — :before stays available for the builder page. */
  body.is-builder-chat:not(.is-builder-cards-view):not(.mob-drawer-open)::before {
    content: '';
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    /* Height = topbar visible height + ~64px ramp-out below it. */
    height: calc(52px + env(safe-area-inset-top, 0px) + 64px);
    z-index: 60;
    pointer-events: none;
    /* Tint = the topbar/chrome colour (--topband #FEFEFD) so the band fades
       INTO the chrome and is invisible over it. 2026-06-03: commit 0f212e2's
       de-cream pass changed this from warm cream rgba(253,251,246) to neutral
       rgba(253,253,253), which against the lightened #FEFEFD chrome read as a
       grey strip wherever the band leaked onto the sections view. Matching the
       chrome exactly makes the band invisible regardless of leak (belt-and-
       braces with the is-builder-sliding kill above). */
    background: linear-gradient(to bottom,
      rgba(254, 254, 253, 0.55) 0%,
      rgba(254, 254, 253, 0.28) 50%,
      rgba(254, 254, 253, 0) 100%);
  }
  /* The fade is meant for the chat pane (so chat messages scroll
     softly under the topbar). It bleeds into the preview + sections
     panes where the iframe / section-list start right at the top of
     the viewport — those don't want a fade. Founder feedback
     2026-05-24: "the page is fading at the top".
     2026-06-03 REGRESSION FIX: the kill only matched the EXACT attribute,
     but the sections pane is ALSO shown during is-builder-sliding (which
     forces all panes visible while active-pane already points at the slide
     TARGET — so sliding away from sections left this band painting over the
     still-visible sections pane). It was invisible until 0f212e2 retinted the
     band cream→neutral-grey; then it became the grey band the founder saw.
     The sections pane is visible ONLY when active-pane="sections" OR
     is-builder-sliding, so killing the band in both closes the leak while
     keeping the chat blur.
     2026-06-03 (founder): sections must match the PREVIEW pane — NO blur/fade.
     So the band is killed in sections AND preview (founder explicitly: "get rid
     of the blur on the sections page"). The grey that killing it exposed is now
     handled the preview way: the sections pane is position:fixed (like the
     preview pane), so as a positioned element it paints the iOS top safe-area
     strip cream — no blur, no separate cover layer. See the sections-pane
     fixed rule near the flatten block below. */
  body[data-builder-active-pane="preview"]::before,
  body[data-builder-active-pane="sections"]::before {
    display: none !important;
  }
  @supports ((-webkit-backdrop-filter: blur(0)) or (backdrop-filter: blur(0))) {
    body.is-builder-chat:not(.is-builder-cards-view):not(.mob-drawer-open)::before {
      -webkit-backdrop-filter: blur(18px) saturate(160%);
              backdrop-filter: blur(18px) saturate(160%);
      -webkit-mask-image: linear-gradient(to top,
        rgba(0, 0, 0, 0) 0%,
        rgba(0, 0, 0, 0.05) 25%,
        rgba(0, 0, 0, 0.22) 50%,
        rgba(0, 0, 0, 0.58) 75%,
        rgba(0, 0, 0, 1) 100%);
              mask-image: linear-gradient(to top,
        rgba(0, 0, 0, 0) 0%,
        rgba(0, 0, 0, 0.05) 25%,
        rgba(0, 0, 0, 0.22) 50%,
        rgba(0, 0, 0, 0.58) 75%,
        rgba(0, 0, 0, 1) 100%);
    }
  }

  /* ---- 1D. Composer fixed at viewport bottom. position:fixed already
     applied by the existing inline page CSS (see dashboard-v2-page.html
     for the rule keyed on .builder-shell--centered:not([data-builder-
     state="ready"]) .builder-input-wrap). Don't redeclare here — but DO
     re-assert z-index so the composer always covers any chat content
     that the page-scroll briefly slides under it during rubber-band. */
  body.is-builder-chat:not(.is-builder-cards-view) .builder-shell--centered:not([data-builder-state="ready"]) .builder-input-wrap {
    z-index: 65 !important;
  }

  /* ---- 1D. Chat-body styling. No padding-top / bottom (the body's
     padding handles topbar / composer clearance). Drop the legacy
     auto-margin on first-child — page-scroll mode positions the latest
     message via JS, not via CSS bottom-anchor. */
  body.is-builder-chat:not(.is-builder-cards-view) .builder-shell--centered:not([data-builder-state="ready"]) .builder-chat-body {
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    -webkit-mask-image: none !important;
            mask-image: none !important;
  }
  body.is-builder-chat:not(.is-builder-cards-view) .builder-shell--centered:not([data-builder-state="ready"]) .builder-chat-body > :first-child {
    margin-top: 0 !important;
  }

  /* ---- 1E. Cold-start (no messages yet, body lacks .has-chat-messages
     class — toggled by JS in _shellScrollToEnd). Keep the empty-hero
     centered between topbar and composer; no chat to bottom-anchor. */
  body.is-builder-chat:not(.is-builder-cards-view):not(.has-chat-messages) .builder-shell--centered:not([data-builder-state="ready"]) .builder-chat-pane {
    min-height: calc(100dvh - 52px - env(safe-area-inset-top, 0px) - var(--bs-composer-h, 128px) - env(safe-area-inset-bottom, 0px) - 12px) !important;
    display: flex !important;
    flex-direction: column !important;
    justify-content: center !important;
  }

  /* ============================================================
     2026-05-22 v9b — Card-slide drawer kept, containing-block bug fixed.
     ============================================================
     Founder: keep the card-slide animation (main.dash slides right
     revealing sidebar). The card-slide pattern was breaking the
     composer/cards-view because `transform: translateX(...)` on
     main.dash creates a containing block for position:fixed
     descendants — they re-anchored to main.dash instead of viewport.

     Fix: animate main.dash with `position: relative; left: var(
     --drawer-offset)` INSTEAD of transform. `left` doesn't create a
     containing block — fixed descendants stay anchored to viewport.
     Same visual (card slides right) without the containing-block
     side effect.

     Position:fixed elements that need to slide WITH the card
     (composer in chat mode, cards-view shell, frosted topbar overlay)
     get their own `transform: translateX(var(--drawer-offset))` rule
     gated on `.mob-drawer-open` so they animate in sync with main.dash.
     Each is GPU-smooth on its own; main.dash uses left which is a tad
     less smooth but acceptable.

     Verified via Playwright: chat mode composer stays at y=734
     (viewport bottom) whether drawer is open or closed — was y=612
     with the buggy transform approach. Cards-view pane stays at
     top=101 whether drawer is open or closed. */

  /* main.dash + sibling rich containers: use `left` instead of
     `transform` so they don't create a containing block for fixed
     descendants. The base rule's `transform: translateX(var(
     --drawer-offset))` is killed; left-animation produces the same
     visual slide. `will-change: left` + `backface-visibility: hidden`
     hint the browser to GPU-promote the layer so `left` is as smooth
     as `transform` (without creating a containing block — only
     `transform`/`filter`/`perspective` do that, will-change only
     opens an opportunity for the engine to optimise). */
  body.is-builder-chat .shell > main.dash,
  body.is-builder-chat .shell > .pg,
  body.is-builder-chat .shell > .rich-page,
  body.is-builder-chat [data-rich-mount] {
    transform: none !important;
    position: relative;
    left: var(--drawer-offset, 0px);
    transition: left 0.32s cubic-bezier(0.2, 0, 0, 1) !important;
    will-change: left;
    -webkit-backface-visibility: hidden;
            backface-visibility: hidden;
    animation: none !important;
    opacity: 1 !important;
  }
  /* Also GPU-promote the elements that DO use transform so the engine
     doesn't have to recompose them every frame. */
  body.is-builder-chat .mob-topbar,
  body.is-builder-chat .builder-input-wrap,
  body.is-builder-cards-view .builder-shell {
    will-change: transform;
    -webkit-backface-visibility: hidden;
            backface-visibility: hidden;
  }
  /* Composer (chat mode): position:fixed at viewport bottom. With
     main.dash no-longer-transformed, the composer correctly anchors
     to the viewport regardless of drawer state. But VISUALLY we want
     the composer to slide RIGHT with the card-slide so it doesn't
     stay behind on the left side of the screen. Add its own
     transform that follows --drawer-offset. */
  body.is-builder-chat .builder-shell--centered:not([data-builder-state="ready"]) .builder-input-wrap {
    transition: transform 0.32s cubic-bezier(0.2, 0, 0, 1) !important;
  }
  body.is-builder-chat.mob-drawer-open .builder-shell--centered:not([data-builder-state="ready"]) .builder-input-wrap {
    transform: translateX(var(--drawer-offset, 0px)) !important;
  }
  /* Cards-view shell (position:fixed inset:52,0,0,0): same pattern.
     Slide with the card so the sidebar reveals on the left. */
  body.is-builder-cards-view .builder-shell {
    transition: transform 0.32s cubic-bezier(0.2, 0, 0, 1) !important;
  }
  body.is-builder-cards-view.mob-drawer-open .builder-shell {
    transform: translateX(var(--drawer-offset, 0px)) !important;
  }
  /* Frosted-blur band (body::before, position:fixed at top): slides
     with the card too so the topbar's frosted region tracks the
     visible chat content. */
  body.is-builder-chat:not(.is-builder-cards-view):not(.mob-drawer-open)::before {
    transition: transform 0.32s cubic-bezier(0.2, 0, 0, 1);
  }
  body.is-builder-chat.mob-drawer-open::before {
    transform: translateX(var(--drawer-offset, 0px)) !important;
    transition: transform 0.32s cubic-bezier(0.2, 0, 0, 1);
  }

  /* ---- 1F. Has-chat-messages (set by JS once thread has any .builder-
     msg-row or form-card). Pane fills the visible chat area as a
     min-height and uses flex-end to BOTTOM-ANCHOR short threads (the
     chat-body, which is the only in-flow flex child here — empty-hero,
     instruction, suggestion-row, sections-body, publish-body are all
     display:none in this state, and input-wrap is position:fixed).
     - Short content (chat-body < min-height): chat-pane stays at
       min-height, slack is absorbed by justify-content:flex-end →
       chat-body anchored to bottom of chat-pane (just above composer).
     - Long content (chat-body > min-height): chat-pane.height = auto
       grows with chat-body; no slack to align; content fills naturally
       from top, document grows beyond viewport, page scrolls. JS
       _shellScrollToEnd auto-positions the last message above composer.
     Verified via Playwright on 390x844 viewport, post-commit 3b4e6b1
     pass — short thread message lands at y≈632-722 (12px above
     composer at y=734); long thread page-scrolls to last message
     bottom y=721.5 (12.5px above composer). */
  body.is-builder-chat.has-chat-messages:not(.is-builder-cards-view) .builder-shell--centered:not([data-builder-state="ready"]) .builder-chat-pane {
    min-height: calc(100dvh - 52px - env(safe-area-inset-top, 0px) - var(--bs-composer-h, 128px) - env(safe-area-inset-bottom, 0px) - 12px) !important;
    display: flex !important;
    flex-direction: column !important;
    justify-content: flex-end !important;
  }
  /* chat-body must NOT grow to fill chat-pane — the base rule has
     `flex: 1 1 auto` which made it size to chat-pane.height (670)
     instead of its content height, so justify-content:flex-end had
     nothing to push (chat-body already filled the pane). Setting
     flex:none sizes chat-body to its content; justify-content on the
     pane then bottom-anchors it. */
  body.is-builder-chat.has-chat-messages:not(.is-builder-cards-view) .builder-shell--centered:not([data-builder-state="ready"]) .builder-chat-body {
    flex: 0 0 auto !important;
  }

  /* ============================================================
     1G. Form-card redesign — bring back the card chrome on mobile.
     The Phase 4.3 (2026-05-17) rule at dashboard-v2.css:10368
     stripped the form's bg/border/shadow/radius/padding so it read
     as "Claude-style flowing content" — but the founder wants a
     compact card instead. Restore card chrome + tighten the spacing
     so the form feels like a small distinct surface, not a wall of
     fields.
     ============================================================ */
  body.is-builder-chat:not(.is-builder-cards-view) .builder-shell--centered:not([data-builder-state="ready"]) .builder-form-row,
  body.is-builder-chat:not(.is-builder-cards-view) .builder-shell--centered:not([data-builder-state="ready"]) .builder-msg-row {
    /* Side margin so the card doesn't go edge-to-edge — and so every
       message row (user bubble, thinking row, AI text reply, form-card)
       sits on the same x. Without this, the thinking row + user bubble
       sat at x=16 while the form-card sat at x=28, making the layout
       visibly shift when the AI's thinking finished and the form-card
       took over. Founder report 2026-05-28.
       Founder 2026-05-30: was 12px each side — combined with the
       chat-pane's own gutter that pushed bubbles ~28px in from each
       screen edge, which felt too inset for mobile. Drop to 0 so the
       only horizontal breathing room is the chat-pane gutter. */
    padding: 0 !important;
  }
  body.is-builder-chat .builder-shell--centered:not([data-builder-state="ready"]) .builder-form-card {
    background: var(--paper, #fff) !important;
    border: 1px solid var(--hairline) !important;
    border-radius: 16px !important;
    box-shadow:
      0 6px 22px -10px rgba(31, 22, 17, 0.10),
      0 1px 2px rgba(31, 22, 17, 0.04) !important;
    /* Compact: tighter padding + gap than the desktop card. */
    padding: 14px 14px 14px !important;
    gap: 9px !important;
    max-width: 100% !important;
  }
  /* Header: smaller + tighter than the desktop default. */
  body.is-builder-chat .builder-shell--centered:not([data-builder-state="ready"]) .builder-form-card .builder-form-header {
    font-size: 0.92rem !important;
    line-height: 1.35 !important;
    margin: 0 0 2px !important;
    font-weight: 600 !important;
  }
  /* Fields: tighten gap between fields + within field. */
  body.is-builder-chat .builder-shell--centered:not([data-builder-state="ready"]) .builder-form-card .builder-form-fields {
    gap: 10px !important;
  }
  body.is-builder-chat .builder-shell--centered:not([data-builder-state="ready"]) .builder-form-card .builder-form-field {
    gap: 3px !important;
  }
  /* Label: smaller + uppercased for a denser "spec sheet" feel. */
  body.is-builder-chat .builder-shell--centered:not([data-builder-state="ready"]) .builder-form-card .builder-form-label {
    font-size: 0.7rem !important;
    text-transform: uppercase !important;
    letter-spacing: 0.04em !important;
    color: var(--ink-mute) !important;
    font-weight: 600 !important;
  }
  /* Help text: kept (founder wants context) but smaller. */
  body.is-builder-chat .builder-shell--centered:not([data-builder-state="ready"]) .builder-form-card .builder-form-help {
    font-size: 0.72rem !important;
    margin-top: 1px !important;
    line-height: 1.35 !important;
  }
  /* Inputs: compact, 16px font kept (iOS-no-zoom requirement). */
  body.is-builder-chat .builder-shell--centered:not([data-builder-state="ready"]) .builder-form-card .builder-form-input,
  body.is-builder-chat .builder-shell--centered:not([data-builder-state="ready"]) .builder-form-card .builder-form-chip-input {
    font-size: 16px !important;
    padding: 6px 2px 7px !important;
  }
  /* Textarea: cap height tighter (was 80px on mobile, 60px reads
     leaner inside a smaller card). */
  body.is-builder-chat .builder-shell--centered:not([data-builder-state="ready"]) .builder-form-card .builder-form-textarea {
    height: 60px !important;
    min-height: 60px !important;
    max-height: 120px !important;
  }
  /* Segmented control: thinner buttons. */
  body.is-builder-chat .builder-shell--centered:not([data-builder-state="ready"]) .builder-form-card .builder-form-seg {
    padding: 8px 6px !important;
    font-size: 0.84rem !important;
  }
  /* Submit button: cleaner, slightly smaller. */
  body.is-builder-chat .builder-shell--centered:not([data-builder-state="ready"]) .builder-form-card .builder-form-submit {
    margin-top: 4px !important;
    padding: 12px 14px !important;
    font-size: 0.92rem !important;
    border-radius: 11px !important;
  }

  /* ============================================================
     2026-05-22 v12 — Flex-in-flow chat layout (Lovable-pattern).
     ============================================================
     Gated on body.is-flex-flow-chat. Replaces page-scroll + fixed
     composer with a viewport-tall flex column whose last child IS
     the composer (in flow, no position:fixed). Eliminates the
     transform-containing-block conflict — main.dash can now use
     `transform` for GPU-smooth drawer animation matching home page,
     without re-anchoring any descendant.

     Flip FLEX_FLOW = false in dashboard-v2-page-builder.js to revert
     to page-scroll behaviour instantly — the rules in this block
     simply don't fire when the body class isn't set.

     Specificity tie with the page-scroll rules above is broken by
     source order (this block is later in the file) so we win without
     needing crazy selector chains.
     ============================================================ */

  /* Body: viewport-fixed height, no scroll on body itself. */
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) {
    height: 100dvh !important;
    min-height: 0 !important;
    overflow: hidden !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
  }

  /* .shell, main.dash, rich-mount, builder-shell, card-wrap, chat-pane —
     all become flex columns that share viewport height. Chat-body is
     the only scroller. */
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .shell,
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .shell > main.dash,
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) [data-rich-mount],
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .builder-shell,
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .builder-shell--centered:not([data-builder-state="ready"]),
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .builder-card-wrap[data-pane-key="chat"] {
    display: flex !important;
    flex-direction: column !important;
    height: 100dvh !important;
    min-height: 0 !important;
    max-height: 100dvh !important;
    overflow: hidden !important;
  }
  /* chat-pane fills its parent flex slot. 16px horizontal gutter
     lives INSIDE the chat wrap (not on main.dash) so the chat-wrap
     itself stays a constant 100vw across the pane slide — otherwise
     the gutter snaps in/out at slide-end when main.dash padding
     would change. Founder report 2026-05-24. */
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .builder-shell--centered .builder-chat-pane {
    /* 2026-05-24: dropped the :not([data-builder-state="ready"]) gate.
       Under the old sheet design the ready state turned the chat pane
       into a bottom sheet with bespoke sizing. Sheet is dead (see kill
       commit), so chat-pane should keep its gutter + flex layout
       in BOTH states. Was clobbering the handoff card's left/right
       breathing room and making the card look like floating text.
       Founder 2026-05-30: was 16px each side — combined with the
       msg-row + chat-body padding it pushed bubbles ~46px inset which
       felt too far from screen edges. Tightened to 12px (tried 8px
       and 10px first; 12px is the sweet spot the founder picked). */
    flex: 1 1 0 !important;
    min-height: 0 !important;
    max-height: none !important;
    display: flex !important;
    flex-direction: column !important;
    padding: 0 12px !important;
    overflow: hidden !important;
  }
  /* chat-body owns the scroll. Top padding clears the fixed topbar
     (52px) so content visually starts below it but scrolls under it.
     Bottom padding gives breathing room above the in-flow composer.
     Messages stack from the TOP (founder preference) — natural flow. */
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .builder-shell--centered:not([data-builder-state="ready"]) .builder-chat-body {
    flex: 1 1 0 !important;
    min-height: 0 !important;
    max-height: none !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    overscroll-behavior: contain !important;
    -webkit-overflow-scrolling: touch !important;
    padding-top: calc(52px + env(safe-area-inset-top, 0px)) !important;
    padding-bottom: 12px !important;
    -webkit-mask-image: none !important;
            mask-image: none !important;
  }
  /* Composer becomes a flex child in normal flow. Kills position:fixed
     and the bottom/left/right anchors that the L10162 rule in
     dashboard-v2.css sets. */
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .builder-shell--centered:not([data-builder-state="ready"]) .builder-input-wrap {
    position: static !important;
    left: auto !important;
    right: auto !important;
    bottom: auto !important;
    z-index: auto !important;
    flex: 0 0 auto !important;
    margin-top: 0 !important;
    /* Safe-area on the composer itself (was on body padding before). */
    padding-bottom: max(12px, env(safe-area-inset-bottom, 0px)) !important;
    /* No fade gradient needed — composer no longer floats over content. */
    background: var(--topband, #FEFEFD) !important;
  }
  /* Suggestion row sits ABOVE the composer (DOM order: composer THEN
     suggestion-row; flex order flips visually). */
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .builder-shell--centered:not([data-builder-state="ready"]) .builder-input-wrap {
    order: 2;
  }
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .builder-shell--centered:not([data-builder-state="ready"]) .builder-suggestion-row {
    order: 1;
    flex: 0 0 auto !important;
  }
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .builder-shell--centered:not([data-builder-state="ready"]) .builder-chat-body {
    order: 0;
  }

  /* Drawer slide via GPU `transform` on main.dash (and rich containers).
     Beats the L6491 v9b override that uses `left:`. With composer no
     longer position:fixed in chat mode, transform creates no problem.
     EXCLUDED from cards-view (the cards shell is position:fixed and
     would re-anchor to main.dash if main.dash had transform). */
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .shell > main.dash,
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .shell > .pg,
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .shell > .rich-page,
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) [data-rich-mount] {
    transform: translateX(var(--drawer-offset, 0px)) !important;
    /* Match home-page transition exactly: transform + border-radius +
       box-shadow all animate together with the same 0.32s curve so the
       card-edge appears smoothly as the slide progresses. */
    transition:
      transform 0.32s cubic-bezier(0.2, 0, 0, 1),
      border-radius 0.32s cubic-bezier(0.2, 0, 0, 1),
      box-shadow 0.32s cubic-bezier(0.2, 0, 0, 1) !important;
    will-change: transform;
    -webkit-backface-visibility: hidden;
            backface-visibility: hidden;
    position: relative;
    left: auto !important;
    animation: none !important;
    opacity: 1 !important;
  }
  /* Cards-view: shell is position:fixed inset:52,0,0,0 of viewport. It
     needs its own transform to slide with the drawer. main.dash stays
     untransformed in this mode so it doesn't break the shell's CB. */
  body.is-flex-flow-chat.is-builder-cards-view .builder-shell {
    transform: translateX(var(--drawer-offset, 0px)) !important;
    transition:
      transform 0.32s cubic-bezier(0.2, 0, 0, 1),
      border-radius 0.32s cubic-bezier(0.2, 0, 0, 1),
      box-shadow 0.32s cubic-bezier(0.2, 0, 0, 1) !important;
    will-change: transform;
    -webkit-backface-visibility: hidden;
            backface-visibility: hidden;
  }
  /* Cards-shell gets the same card-edge treatment that main.dash gets
     in chat mode (dashboard-v2.css L1750): rounded bottom-left corner
     + left-edge shadow so the shell visibly stacks over the sidebar
     when drawer is open. */
  body.is-flex-flow-chat.is-builder-cards-view.mob-drawer-open .builder-shell {
    border-bottom-left-radius: 22px;
    box-shadow:
      -1px 0 0 0 rgba(31, 22, 17, 0.08),
      -6px 0 22px -8px rgba(31, 22, 17, 0.18) !important;
  }
  /* Cards-view: kill main.dash animation entirely. The v9b `left:` rule
     at L6491 fires here too (it's gated on body.is-builder-chat without
     :not(.is-builder-cards-view)), causing main.dash to animate via slow
     `left` while the cards-shell animates via GPU transform — desync =
     glitchy. main.dash has no visible content in cards-view (shell is
     position:fixed and floats above), so killing its animation is safe
     and removes the desync source. */
  body.is-flex-flow-chat.is-builder-cards-view .shell > main.dash,
  body.is-flex-flow-chat.is-builder-cards-view .shell > .pg,
  body.is-flex-flow-chat.is-builder-cards-view .shell > .rich-page,
  body.is-flex-flow-chat.is-builder-cards-view [data-rich-mount] {
    transform: none !important;
    left: auto !important;
    transition: none !important;
    will-change: auto !important;
    /* main.dash keeps its base z-index:10 (above sidebar's z-index:1)
       and is NOT static — but we make it visually transparent so the
       sidebar's content (BookingSprint logo, nav links) shows through
       when drawer is open. The cards-shell at z-index:60 is still above
       main.dash; the sidebar at z-index:1 shows through the transparent
       main.dash because main.dash has no opaque background. */
    background-color: transparent !important;
  }
  /* Cards-dock (Publish/Share): hide while drawer is open. The buttons
     are centered with full-width container; sliding the container by
     --drawer-offset puts the centered buttons off-screen entirely.
     Keeping it visible without sliding overlaps the sidebar footer
     awkwardly. Hiding while drawer is open keeps the UI clean — the
     user can't usefully tap dock buttons through the drawer anyway. */
  body.is-flex-flow-chat.is-builder-cards-view .builder-cards-dock {
    transition: opacity 0.2s ease;
  }
  body.is-flex-flow-chat.is-builder-cards-view.mob-drawer-open .builder-cards-dock {
    opacity: 0;
    pointer-events: none;
  }
  /* Topbar slides via its base rule transform — already GPU. */
  /* Composer is in flow inside main.dash now — it slides automatically
     with main.dash's transform. Kill the redundant composer-transform
     rule from v9b L6520+. */
  body.is-flex-flow-chat.is-builder-chat.mob-drawer-open .builder-shell--centered:not([data-builder-state="ready"]) .builder-input-wrap {
    transform: none !important;
  }

  /* Empty-state centering: chat-pane centers hero+chips when no chat
     content. The empty-hero remains an inline element of chat-pane. */
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view):not(.has-chat-messages) .builder-shell--centered:not([data-builder-state="ready"]) .builder-chat-body {
    flex: 1 1 0 !important;
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
}

/* ============================================================================
   2026-05-22 v6 — Cards-view redesign (tap-the-play-button view)
   ============================================================================
   Founder feedback: the cards-view "looks cheesy" — specifically the
   centered "Chat" label above the card reads as an afterthought, and the
   card chrome is plain. Replit reference uses a TAG PILL inside the card
   header (not floating above), softer card chrome, and a denser bottom
   action dock. Match that pattern.

   Scope: mobile + body.is-builder-cards-view only. */
@media (max-width: 720px) {

  /* Cards-view backdrop: --topband (#FEFEFD) to match the sidebar.
     Founder rule (CLAUDE.md): topbar + sidebar + chrome all read as
     one continuous warm panel. Cards-view backdrop joins the same
     surface — when the user opens the drawer over the cards, the
     two surfaces should be the same colour. Previous v6/v7/v8 used
     --cream which is slightly lighter / different tint and produced
     a visible seam against the sidebar. */
  body.is-builder-cards-view {
    background-color: var(--topband, #FEFEFD) !important;
  }
  body.is-builder-cards-view .builder-shell,
  body.is-builder-cards-view .mob-topbar {
    background-color: var(--topband, #FEFEFD) !important;
  }

  /* Card wrap: keep horizontal-snap layout but reset gap between label
     and card to 0 (label is going INSIDE the card now). */
  body.is-builder-cards-view .builder-shell--centered .builder-card-wrap {
    gap: 0 !important;
    position: relative !important;
  }
  /* Card label: from "floating centered small text above the card" to
     "pill tag absolutely positioned in the top-left of the card". Like
     the Replit "Agent" tag. Higher z-index so it sits above the pane's
     content + overflow:hidden. */
  body.is-builder-cards-view .builder-shell--centered .builder-card-label {
    position: absolute !important;
    top: 12px !important;
    left: 12px !important;
    z-index: 5 !important;
    display: inline-flex !important;
    align-items: center !important;
    gap: 5px !important;
    padding: 4px 10px 4px 8px !important;
    background: rgba(255, 255, 255, 0.78) !important;
    -webkit-backdrop-filter: blur(8px) saturate(160%);
            backdrop-filter: blur(8px) saturate(160%);
    border: 1px solid rgba(31, 22, 17, 0.06) !important;
    border-radius: 999px !important;
    color: var(--ink) !important;
    font-size: 0.72rem !important;
    font-weight: 600 !important;
    letter-spacing: 0.005em !important;
    box-shadow: 0 1px 2px rgba(31, 22, 17, 0.04) !important;
    text-transform: capitalize;
  }
  body.is-builder-cards-view .builder-shell--centered .builder-card-label svg {
    width: 12px !important;
    height: 12px !important;
    opacity: 0.7;
  }

  /* Pane (the card itself): bigger radius, much softer shadow, top
     padding-top to clear the absolute label pill. The Replit cards
     use a 16-20px radius + a very soft 1px hairline + a quiet shadow,
     not the aggressive 50% opacity drop-shadow we had. */
  body.is-builder-cards-view .builder-shell--centered .builder-pane {
    border-radius: 22px !important;
    /* 2026-05-22 V6 treatment — gradient surface + defined border +
       even edge shadows so the card reads as a floating element with
       depth, matching the topbar buttons / chat bar.
       2026-05-23 founder iteration: border + shadow bumped so cards
       lift more clearly off the cream-3 backdrop and read as
       distinct elevated panels (not flat panes blending into the
       page). Border opacity 0.12 → 0.18, shadow stack deepened. */
    background: linear-gradient(180deg, #FFFFFF 0%, #F6F6F6 100%) !important;
    border: 1px solid rgba(31, 22, 17, 0.18) !important;
    box-shadow:
      0 0 0 1px rgba(20, 14, 8, 0.05),
      0 0 24px rgba(20, 14, 8, 0.08),
      0 2px 4px rgba(20, 14, 8, 0.06),
      0 12px 32px -8px rgba(20, 14, 8, 0.18),
      0 32px 64px -16px rgba(20, 14, 8, 0.20),
      inset 0 1.5px 0 rgba(255, 255, 255, 0.9),
      inset 0 -1px 1px rgba(0, 0, 0, 0.04) !important;
    /* Slightly taller card so it has presence — was 42vh / 380px cap. */
    height: 52vh !important;
    max-height: 480px !important;
    padding-top: 0 !important;
  }

  /* Card head (for non-chat panes that have an internal head — Sections,
     Preview): left-pad to clear the absolute label pill at top:12/left:12
     (the pill is ~70px wide; add 78px left padding so the head's title
     and inner controls start to the RIGHT of the pill instead of
     overlapping it). */
  body.is-builder-cards-view .builder-pane__card-head {
    padding: 14px 14px 12px 78px !important;
    border-bottom: 1px solid rgba(31, 22, 17, 0.06) !important;
    font-size: 0.85rem !important;
    min-height: 46px !important;
  }
  /* Preview-pane head specifically — overflow:hidden any tab strip
     content that would otherwise clip the label region awkwardly. */
  body.is-builder-cards-view .builder-preview-pane > * {
    overflow: hidden !important;
  }

  /* Cards-view backdrop topbar: Back pill gets simple 3D style
     matching the project pill / preview pill so all topbar elements
     read as one matching set. */
  body.is-builder-cards-view .builder-cards-back {
    height: 44px !important;
    padding: 0 18px 0 14px !important;
    font-size: 14px !important;
    font-weight: 500 !important;
    background: linear-gradient(180deg, #FFFFFF 0%, #F8F8F8 100%) !important;
    border: 1px solid rgba(31, 22, 17, 0.13) !important;
    border-bottom-color: rgba(31, 22, 17, 0.19) !important;
    box-shadow:
      0 1px 3px rgba(31, 22, 17, 0.07),
      0 2px 1px -1px rgba(31, 22, 17, 0.04),
      inset 0 1px 0 rgba(255, 255, 255, 0.9) !important;
  }

  /* Bottom dock buttons: tighter, more elegant. The previous look had
     two big chunky pills; reduce padding and refine the shadow. */
  body.is-builder-cards-view .builder-cards-dock {
    background: linear-gradient(to bottom,
      rgba(248, 248, 248, 0) 0%,
      var(--cream) 32%) !important;
    padding: 28px 16px max(20px, env(safe-area-inset-bottom)) !important;
  }
  body.is-builder-cards-view .builder-cards-dock__btn {
    height: 44px !important;
    padding: 0 20px !important;
    font-size: 14px !important;
    font-weight: 500 !important;
    /* Simple 3D treatment for the Share (light) button — matches
       burger, project pill, preview pill, and back button. */
    background: linear-gradient(180deg, #FFFFFF 0%, #F8F8F8 100%) !important;
    border: 1px solid rgba(31, 22, 17, 0.13) !important;
    border-bottom-color: rgba(31, 22, 17, 0.19) !important;
    box-shadow:
      0 1px 3px rgba(31, 22, 17, 0.07),
      0 2px 1px -1px rgba(31, 22, 17, 0.04),
      inset 0 1px 0 rgba(255, 255, 255, 0.9) !important;
  }
  /* Publish (primary CTA): dark surface with simple 3D shadow. */
  body.is-builder-cards-view .builder-cards-dock__btn[data-cards-dock="publish"] {
    background: linear-gradient(180deg, #2A2520 0%, #1F1611 100%) !important;
    color: #FAFAFA !important;
    border-color: #1F1611 !important;
    border-bottom-color: #0F0B08 !important;
    box-shadow:
      0 1px 3px rgba(31, 22, 17, 0.2),
      inset 0 1px 0 rgba(255, 255, 255, 0.08) !important;
  }
}

/* ============================================================================
   2026-05-22 v7 — Cards-view refinement v2 (founder iteration on v6)
   ============================================================================
   - Cards too stubby → taller (70vh, max 620px)
   - Cards too narrow → wider (94vw, shell side padding 6vw → 3vw)
   - Heading should be OUTSIDE the card (not inside) but more premium →
     serif italic above the card, no pill bg, no generic icon
   - Open/close animations should be clean + consistent → mirror enter /
     exit with one shared easing + duration, no stagger
   ============================================================================ */
@media (max-width: 720px) {

  /* Shell: tighter side padding, bottom padding sized to clear the
     fixed dock entirely. Card should NOT extend under the Publish/
     Share buttons (founder feedback 2026-05-22 v8b: 'I need them not
     to go past the publish and share button'). Dock height ≈ 14 (top
     pad) + 42 (button) + max(16, safe-area-bot) ≈ 92px, so 100px +
     safe-area-bot bottom padding gives the dock breathing room. */
  body.is-builder-cards-view .builder-shell {
    padding: 16px 6vw calc(100px + env(safe-area-inset-bottom, 0px)) !important;
    gap: 12px !important;
  }

  /* Card wrap: thinner per founder ref (Replit screenshot) so the
     card reads as a distinct object with breathing room either side
     and a clearer peek of the next card. 94vw -> 82vw; shell side
     padding lifts from 3vw to 6vw to centre the row. */
  body.is-builder-cards-view .builder-shell--centered .builder-card-wrap {
    width: 82vw !important;
    max-width: 82vw !important;
    flex: 0 0 82vw !important;
    gap: 12px !important;
    position: static !important;
  }

  /* Label: from "absolute pill inside the card" back to "elegant serif
     italic above the card" — no pill, no backdrop blur, no generic icon.
     Reads as a premium chapter title rather than a UI tag. */
  body.is-builder-cards-view .builder-shell--centered .builder-card-label {
    position: static !important;
    display: flex !important;
    align-items: baseline !important;
    justify-content: flex-start !important;
    gap: 0 !important;
    padding: 0 4px !important;
    margin: 0 !important;
    background: transparent !important;
    -webkit-backdrop-filter: none !important;
            backdrop-filter: none !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-weight: 500 !important;
    font-size: 1.1rem !important;
    letter-spacing: -0.012em !important;
    line-height: 1.1 !important;
    color: var(--ink) !important;
    opacity: 0.88 !important;
    text-transform: none !important;
    user-select: none;
    -webkit-user-select: none;
  }
  /* Drop the generic chat/grid/screen icon next to the label — the
     serif italic word stands on its own. */
  body.is-builder-cards-view .builder-shell--centered .builder-card-label svg {
    display: none !important;
  }

  /* Pane (card body): much taller — fills almost all the vertical
     space between the topbar bottom and viewport bottom. The card
     extends UNDER the dock area; the dock's own gradient mask + the
     pane's overflow:hidden + the scaled-content padding produce a
     soft fade-out at the bottom of the card, so the dock buttons
     read as floating over the card edge rather than cutting it off.
     calc breakdown: 100dvh - 52 (topbar) - safe-area-top - 32 (label
     + gap above card). No dock subtraction — that's the intentional
     'card goes behind dock' trick to maximize visible card area. */
  body.is-builder-cards-view .builder-shell--centered .builder-pane {
    /* calc breakdown (matches shell padding 16 top + 100+safe-bot
       bottom — the bottom reserve clears the fixed dock so the card
       does NOT extend under the Publish/Share buttons):
         100dvh             viewport
         - 52               fixed topbar above shell
         - safe-area-top    iPhone notch
         - 16               shell padding-top
         - 100              shell padding-bottom (clears dock)
         - safe-area-bot    home-indicator inset
         - 24               label height above the card
         - 12               gap between label and card
       On 844-tall iPhone with no notch:  640px card
       On 844-tall iPhone with notch (47/34): 559px card
       Still significantly taller than v7's 581px; now bounded above
       the dock instead of overlapping it. */
    height: calc(100dvh - 52px - env(safe-area-inset-top, 0px) - 16px - 100px - env(safe-area-inset-bottom, 0px) - 24px - 12px) !important;
    max-height: 720px !important;
    border-radius: 24px !important;
    overflow: hidden !important;
  }
  body.is-builder-cards-view .builder-pane__card-head {
    padding-left: 16px !important;
  }
  /* Tighter dock — was 28+20 padding; trim to 14+max(16,safe-bot) so the
     dock takes less vertical space and the card extension under it is
     a clean fade rather than a chunky bar over the card. */
  body.is-builder-cards-view .builder-cards-dock {
    padding: 14px 16px max(16px, env(safe-area-inset-bottom)) !important;
    /* Dock gradient ends in --topband (#FEFEFD) to match the cards-view
       backdrop — single continuous surface from cards down through the
       dock and out to the safe-area inset. */
    background: linear-gradient(to bottom,
      rgba(253, 253, 253, 0) 0%,
      var(--topband, #FEFEFD) 60%) !important;
  }

  /* "Zoomed-out app preview" — scale the pane's INNER content to ~0.7
     so the full chat thread / preview iframe / sections list reads as
     a shrunken thumbnail of the live pane.
     Use `zoom` (vs transform:scale) because zoom actually changes the
     LAYOUT — the content's children re-flow at the smaller size, so
     right-aligned message bubbles land correctly inside the card and
     the width-compensation math (153.85% + margin-left tricks) isn't
     needed. zoom is non-standard but supported in every WebKit /
     Blink browser; Firefox does not, but mobile Firefox is <1% share.
     IMPORTANT: target only the INNER content elements (chat-body /
     preview-body / sections-list), NOT the .builder-preview-pane
     itself — scaling the pane would also scale its bg/border/radius
     and break the card chrome. Founder report 2026-05-22: the v7
     attempt scaled `.builder-preview-pane` and the card rendered as
     a tiny dark rectangle with the label "Preview" stacked vertically. */
  /* Zoom EVERY direct child of each pane so the head (tab strip, URL
     bar, publish button — for preview pane) AND the body content
     (iframe, chat thread, sections list) ALL render as a uniform
     thumbnail. Without this, the head stays full-width and its
     contents get squashed (Pr/ev/iew tabs stacked vertically because
     the tab buttons are narrower than their text — the founder
     screenshot showed exactly this). */
  body.is-builder-cards-view .builder-shell--centered .builder-pane > *,
  body.is-builder-cards-view .builder-shell--centered .builder-chat-pane .builder-chat-body {
    zoom: 0.7 !important;
    pointer-events: none !important;
    transform: none !important;
    width: auto !important;
    margin-left: 0 !important;
  }
  /* Strip chat-body's page-scroll min-height so the zoomed view doesn't
     carry a viewport-sized empty area under the messages. */
  /* Founder feedback 2026-05-23: at 16px CSS × zoom 0.7 (~11px visual)
     the content text sat too close to the card edges and read as flush.
     Bumped to 28px horizontal (~20px visual at zoom 0.7) to match the
     visible inset of the input-wrap below (which has margin: 0 14px,
     un-zoomed = 14px visual). Same "slight inset from card edge"
     treatment for both rows. */
  body.is-builder-cards-view .builder-shell--centered .builder-chat-body {
    min-height: 0 !important;
    height: auto !important;
    max-height: none !important;
    padding: 12px 28px !important;
  }
  /* dashboard-v2.css:10420 strips chat-body left/right padding when the
     business-info form-card is mounted (so the edge-to-edge form fills
     the chat-pane in single-mode). In cards-view we WANT the inset back
     so the form-card sits off the card edges with breathing room.
     Match its :has() selector + add body.is-builder-cards-view scope. */
  body.is-builder-cards-view .builder-shell--centered .builder-chat-body:has(.builder-form-card:not(.builder-choice-card)) {
    padding-left: 28px !important;
    padding-right: 28px !important;
  }

  /* ────────────────────────────────────────────────────────────
     Chat card layout: chat-body fills, input-wrap pins to bottom
     ────────────────────────────────────────────────────────────
     Without this, the chat-body takes its natural (tall) height
     and pushes the input-wrap + suggestion-row OUT of the bottom
     of the chat-pane (overflow:hidden then clips them). The
     founder asked for the input bar + chips to be visible inside
     the chat card as part of the 1:1 preview, so we make the
     chat-pane a flex column with the chat-body flex:1 (clipped
     by overflow) and the bottom rows flex:0 (always visible).
     ──────────────────────────────────────────────────────────── */
  body.is-builder-cards-view .builder-shell--centered .builder-chat-pane {
    display: flex !important;
    flex-direction: column !important;
    overflow: hidden !important;
  }
  body.is-builder-cards-view .builder-shell--centered .builder-chat-pane > .builder-chat-body {
    /* flex-basis: 0 (not auto) so chat-body ignores its intrinsic
       (empty) size and aggressively grows to fill available space —
       otherwise an empty chat would collapse to 0 and the input-wrap
       would float right under the hero instead of pinning to the
       card bottom. */
    flex: 1 1 0 !important;
    min-height: 0 !important;
    overflow: hidden !important;
    /* Override the global ".builder-chat-body:empty { display: none }"
       rule — in cards-view we need chat-body to occupy its flex slot
       even when empty so the input-wrap below it pins to the card
       bottom (otherwise empty chats collapse and the composer floats
       to the middle of the card). */
    display: block !important;
  }
  body.is-builder-cards-view .builder-shell--centered .builder-chat-pane > .builder-input-wrap,
  body.is-builder-cards-view .builder-shell--centered .builder-chat-pane > .builder-suggestion-row {
    flex: 0 0 auto !important;
    /* Inset from the card edges so the input-wrap's own rounded
       background doesn't merge into the card's rounded edge and read
       as the card border. Founder feedback 2026-05-23: at 100% width
       the input bar's bottom-corners hit the card's bottom-corners
       and the two boundaries blur together. 14px inset gives a clean
       gap on both sides + bottom. */
    margin: 0 14px 14px !important;
    max-width: calc(100% - 28px) !important;
    width: calc(100% - 28px) !important;
    /* CRITICAL OVERRIDE: dashboard-v2.css:10192 sets
       `.builder-shell--centered:not([data-builder-state="ready"]) .builder-input-wrap
       { position: fixed; bottom: 0; }` — that makes the composer pin
       to the viewport bottom in single mode (correct) and ALSO in
       cards-view (wrong — it escapes the chat-pane and floats below
       the card). Force back to normal flow inside the chat-pane so
       flex-column places it at the bottom of the card. */
    position: relative !important;
    left: auto !important;
    right: auto !important;
    bottom: auto !important;
    z-index: auto !important;
    /* Composer in single-mode has paper bg + warm gradient + heavy
       safe-area padding (matches viewport-bottom chrome). Inside the
       card those styles look like a second "viewport composer"
       glued to the card bottom — kill them so the composer just
       looks like part of the card. */
    background: transparent !important;
    padding: 8px 0 0 !important;
  }
  /* Same override for the position:fixed rule — silence its margin-top:auto
     so the input doesn't try to push itself further than its flex slot. */
  body.is-builder-cards-view .builder-shell--centered .builder-input-wrap {
    margin-top: 0 !important;
  }

  /* ────────────────────────────────────────────────────────────
     Open / close animation — JS-driven FLIP morph
     ────────────────────────────────────────────────────────────
     The actual morph is driven by JS in dashboard-v2-page.html
     (wireCardsView → flipMorph). It captures the chat card-wrap's
     position before + after the body-class change and animates a
     CSS transform between the two rects. Chat content stays 100%
     solid the entire morph — no crossfade, no fade overlap.

     This block silences every CSS keyframe animation that used to
     run on .builder-shell or .builder-card-wrap when the cards-view
     class lands. The previous iterations (v6/v7 staggered scale in
     dashboard-v2.css, v8 symmetric scale here, view-transition
     crossfade) would all double-animate over the top of the JS
     transform — they're all neutralised below.

     Sibling cards (Sections / Preview) + dock fade in/out via the
     separate keyframes further down so they don't snap.
     ──────────────────────────────────────────────────────────── */
  body.is-builder-cards-view .builder-shell,
  body.is-builder-cards-view .builder-shell--centered .builder-card-wrap,
  body.is-builder-cards-closing .builder-shell,
  body.is-builder-cards-closing .builder-shell--centered .builder-card-wrap {
    animation: none !important;
  }

  /* Pane chrome transitions — without this, the .builder-pane's
     border-radius / box-shadow / border-color SNAP at t=0 when the
     body class flips (they're applied by CSS at different selectors
     per mode). With this, they morph smoothly over the same 720ms
     window as the JS FLIP transform on the wrap, so the chat content
     reads as one continuous element scaling down.

     Gradient backgrounds can't be CSS-transitioned (browser limit) so
     background-image still snaps — usually invisible since the
     cards-mode gradient is subtle white→cream and the single-mode
     pane already sits on a white-ish surface.

     Applied to all panes so close (cards → single) also morphs the
     chrome back smoothly, not just open. */
  body.is-builder-chat .builder-shell--centered .builder-pane,
  body.is-builder-cards-view .builder-shell--centered .builder-pane {
    transition:
      border-radius 720ms cubic-bezier(0.22, 1, 0.36, 1),
      border-color 720ms cubic-bezier(0.22, 1, 0.36, 1),
      box-shadow 720ms cubic-bezier(0.22, 1, 0.36, 1),
      background-color 720ms cubic-bezier(0.22, 1, 0.36, 1) !important;
  }
  @media (prefers-reduced-motion: reduce) {
    body.is-builder-chat .builder-shell--centered .builder-pane,
    body.is-builder-cards-view .builder-shell--centered .builder-pane {
      transition: none !important;
    }
  }

  /* ────────────────────────────────────────────────────────────
     Active-pane swap (single-mode)
     ────────────────────────────────────────────────────────────
     When NOT in cards-view, only the active pane's card-wrap is
     visible — others are display:none. Default active pane is
     "chat" (set on body as data-builder-active-pane="chat") so
     out-of-the-box behaviour is identical to before this feature
     landed. Tapping the Sections or Preview card in cards-view
     flips the attribute to that pane key, and on close the morph
     puts THAT pane into the chat's slot fullscreen.

     dashboard-v2-page.html wireCardsView controls the JS side.
     ──────────────────────────────────────────────────────────── */
  /* Specificity has to MATCH the is-flex-flow-chat rule at line ~6782
     that sets chat-wrap to display:flex !important. Two-classes-on-body
     here so we tie the score, then win by source order (later in file). */
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view)[data-builder-active-pane="sections"] .builder-card-wrap[data-pane-key="chat"],
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view)[data-builder-active-pane="preview"]  .builder-card-wrap[data-pane-key="chat"],
  body:not(.is-builder-cards-view)[data-builder-active-pane="sections"] .builder-card-wrap[data-pane-key="preview"],
  body:not(.is-builder-cards-view)[data-builder-active-pane="preview"]  .builder-card-wrap[data-pane-key="sections"] {
    display: none !important;
  }
  /* Non-chat active pane wraps fill the shell like chat does.
     Specificity matches the is-flex-flow-chat chat-wrap rule at
     line ~6782 (2 classes on body) so source order wins. NOT
     position:fixed — a transformed ancestor breaks it (the shell's
     drawer transform), pushing the wrap down past the topbar. */
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view)[data-builder-active-pane="sections"] .builder-card-wrap[data-pane-key="sections"],
  body.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view)[data-builder-active-pane="preview"]  .builder-card-wrap[data-pane-key="preview"] {
    display: flex !important;
    flex-direction: column !important;
    height: 100dvh !important;
    min-height: 0 !important;
    max-height: 100dvh !important;
    overflow: hidden !important;
    /* --topband (not --cream): the wrap paints the top safe-area on iOS; a
       greyer cream read as a grey band / card edge behind the sections
       (founder-reported). Keep it identical to the pane + chrome. */
    background: var(--topband) !important;
  }
  /* The pane inside (the actual sections-list / preview-iframe
     container) needs to take the wrap's full space.
     2026-05-24 v2: active-pane gate restored + is-builder-sliding
     parallel selector so the styles apply during the slide too. */
  body:not(.is-builder-cards-view)[data-builder-active-pane="sections"] .builder-sections-pane,
  body:not(.is-builder-cards-view)[data-builder-active-pane="preview"]  .builder-preview-pane,
  body.is-builder-sliding:not(.is-builder-cards-view) .builder-sections-pane,
  body.is-builder-sliding:not(.is-builder-cards-view) .builder-preview-pane {
    display: flex !important;
    flex-direction: column !important;
    flex: 1 1 auto !important;
    min-height: 0 !important;
    width: 100% !important;
  }
  /* Preview pane goes truly fullscreen (full-bleed iframe) in single-
     mode regardless of builder-state, so the template iframe fills the
     viewport below the topbar without the rounded card chrome around
     it. Mirrors the existing data-builder-state="ready" fullscreen
     rule but doesn't gate on the AI having generated a site. The dock
     + DRAFT pill float on top via their own position:fixed/absolute. */
  body:not(.is-builder-cards-view)[data-builder-active-pane="preview"] .builder-preview-pane,
  body.is-builder-sliding:not(.is-builder-cards-view) .builder-preview-pane {
    padding: 0 !important;
    margin: 0 !important;
    border: 0 !important;
    border-radius: 0 !important;
    background: var(--topband) !important;
  }
  /* 2026-06-03 GREY-BAR ROOT CAUSE + FIX (founder: "use the exact same
     method as the preview page").
     The preview pane has NO grey at the top; the sections pane did. The
     ONLY structural difference: the preview pane is `position: fixed`
     (dashboard-v2.css ~L7768) while the sections pane was in-flow.
     On iOS Safari with viewport-fit=cover, an IN-FLOW element's
     background is NOT painted into the top safe-area / notch strip —
     so the bare canvas shows through there as a grey band behind the
     floating topbar buttons. A POSITIONED (fixed) element's background
     IS painted into that zone (which is exactly why the fixed preview
     pane is clean). So give the sections pane the preview pane's exact
     fixed full-bleed model: it becomes a positioned cream surface that
     paints the safe-area strip, with the section list scrolling inside
     its __body. Fixed is relative to the transformed main.dash ancestor
     (same containing block as the preview pane), so the geometry matches
     preview 1:1. No card, no margin, no rounded corners, no grey. */
  body:not(.is-builder-cards-view)[data-builder-active-pane="sections"] .builder-sections-pane,
  body.is-builder-sliding:not(.is-builder-cards-view) .builder-sections-pane {
    position: fixed !important;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: auto !important;
    height: auto !important;
    min-height: 0 !important;
    z-index: 1;
    margin: 0 !important;
    border: 0 !important;
    border-radius: 0 !important;
    background: var(--cream) !important;
    display: flex !important;
    flex-direction: column !important;
    overflow: hidden !important;
  }
  /* The section list scrolls INSIDE the fixed pane (mirrors the preview
     pane's flex:1 body holding the iframe). flex:1 + min-height:0 lets
     it take the remaining height; overflow-y:auto makes only the list
     scroll, leaving the fixed cream surface (incl. the painted safe-area
     strip) stationary behind the topbar. */
  body:not(.is-builder-cards-view)[data-builder-active-pane="sections"] .builder-sections-pane__body,
  body.is-builder-sliding:not(.is-builder-cards-view) .builder-sections-pane__body {
    flex: 1 1 auto !important;
    min-height: 0 !important;
    overflow-y: auto !important;
    -webkit-overflow-scrolling: touch;
  }
  body:not(.is-builder-cards-view)[data-builder-active-pane="preview"] .builder-preview-body,
  body.is-builder-sliding:not(.is-builder-cards-view) .builder-preview-body {
    flex: 1 1 auto !important;
    padding: 0 !important;
    margin: 0 !important;
    border: 0 !important;
    border-radius: 0 !important;
    width: 100% !important;
    height: 100% !important;
  }
  /* main.dash has padding: 0 16px globally for the dashboard content
     gutter — but the AI builder wants edge-to-edge for the preview
     iframe, and during a pane slide all 3 wraps are visible at once.
     If chat keeps its gutter (16px each side) and preview doesn't,
     when the slide ends and the attribute flips to "chat", the gutter
     comes back and the chat pane snaps 32px narrower in one frame.
     Founder feedback 2026-05-24: "when it's ended and im back on the
     chat page the chat page will snap into position". Fix: zero the
     gutter for ALL builder single-mode panes so widths stay constant
     across the slide and into the resting state. */
  body.is-builder-chat:not(.is-builder-cards-view) main.dash {
    padding: 0 !important;
  }
  /* Hide the cards-view-only card-label when the pane is fullscreen
     in single mode — labels only belong in cards-view chrome. */
  body:not(.is-builder-cards-view) .builder-card-label {
    display: none !important;
  }

  /* ────────────────────────────────────────────────────────────
     Single-mode pane slide animation (founder 2026-05-23)
     ────────────────────────────────────────────────────────────
     When the user swipes between chat / preview / sections in
     single-mode, JS adds body.is-builder-sliding for the duration
     of the morph + sets inline translateX on the from- and to-
     wraps. This block forces ALL three wraps + panes visible and
     pinned over the area below the topbar, regardless of the
     current data-builder-active-pane attribute — so both the
     out-going and in-coming panes are on screen at the same time.
     JS strips the class on transitionend, returning to the normal
     active-pane CSS (which hides the from-pane via display:none).

     Specificity gotcha: the active-pane hide rules at ~7676 use
     `body.<2-classes>:not(.is-builder-cards-view)[data-active-pane=..]
     .builder-card-wrap[data-pane=..]` = 2 cls + 1 :not + 1 attr +
     1 cls + 1 attr = (0,6,0). We match that by stacking 3 body
     classes + :not here (no body attr — the boot code only sets
     [data-builder-active-pane] when a saved non-chat pane is
     restored, so on fresh "active=chat" the attr is MISSING and a
     rule requiring it never fires; that's the original "to-pane
     stays display:none during the slide" bug). 3 classes + :not =
     (0,4,0); + wrap (0,2,0) = (0,6,0). Same specificity, mine
     comes later in source so wins on tiebreak.
     ──────────────────────────────────────────────────────────── */
  body.is-builder-sliding.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .builder-card-wrap[data-pane-key="chat"],
  body.is-builder-sliding.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .builder-card-wrap[data-pane-key="preview"],
  body.is-builder-sliding.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .builder-card-wrap[data-pane-key="sections"] {
    display: flex !important;
    flex-direction: column !important;
    position: fixed !important;
    /* main.dash + the rich-mount wrapper both have transform:translateX
       (drawer-offset animation) which makes them containing blocks for
       position:fixed descendants. The nearest one (rich-mount) starts
       at the natural top of the wrap area (~97px below viewport top,
       i.e. below the mob-topbar + any banner). So top:0 here = natural
       wrap top, NOT viewport top. Don't use 52px — that would push
       the slide 52px LOWER than its natural resting position and the
       wrap would snap up by 52px on cleanup. */
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    bottom: 0 !important;
    width: 100% !important;
    height: auto !important;
    min-height: 0 !important;
    max-height: none !important;
    z-index: 12 !important;
    background: var(--cream) !important;
    overflow: hidden !important;
  }
  /* Force the inner pane visible — preview-pane + sections-pane default
     to display:none until their wrap's active-pane attr matches. */
  body.is-builder-sliding.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .builder-pane[data-pane-key="chat"],
  body.is-builder-sliding.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .builder-pane[data-pane-key="preview"],
  body.is-builder-sliding.is-flex-flow-chat.is-builder-chat:not(.is-builder-cards-view) .builder-pane[data-pane-key="sections"] {
    display: flex !important;
    flex-direction: column !important;
    flex: 1 1 auto !important;
    min-height: 0 !important;
    width: 100% !important;
  }
  /* Preview chrome (empty hero / dock / status pill) fades opacity 0
     when active-pane ≠ preview — that fade is what makes the new pane
     look blank during the slide and then snap in at the end (founder
     report 2026-05-23 "pages only load after the swipe animation is
     completed"). Override during the slide so they paint immediately
     at full opacity alongside the moving wrap. The opacity rules at
     ~3887 / ~4019 / ~4071 are (0,3,0) (1 :not + 1 :not + 1 class +
     1 class); our (0,5,0) selector beats them. */
  body.is-builder-sliding .builder-preview-empty,
  body.is-builder-sliding .builder-preview-dock,
  body.is-builder-sliding .builder-preview-status {
    opacity: 1 !important;
    transition: none !important;
  }

  /* Sibling cards + dock fade in alongside the JS morph so they
     don't pop into existence. The chat card-wrap is explicitly
     excluded — JS handles its transform animation.
     Duration synced to the JS OPEN_MS (720ms) so the whole
     transition lands together — no competing rhythms. */
  body.is-builder-cards-view .builder-shell--centered .builder-card-wrap:not([data-pane-key="chat"]),
  body.is-builder-cards-view .builder-cards-dock,
  body.is-builder-cards-view .builder-cards-back {
    animation: bsCardsSiblingFadeIn 720ms cubic-bezier(0.22, 1, 0.36, 1) both;
  }
  @keyframes bsCardsSiblingFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  @media (prefers-reduced-motion: reduce) {
    body.is-builder-cards-view .builder-shell--centered .builder-card-wrap:not([data-pane-key="chat"]),
    body.is-builder-cards-view .builder-cards-dock,
    body.is-builder-cards-view .builder-cards-back {
      animation: none !important;
    }
  }
}
