/* Local additions to the vendored back office.

   Loaded AFTER the kit's style.css and scoped under .bo like it is. Nothing
   here edits the contractor's file, so a later archive can be dropped in and
   this still applies — the same arrangement as the public shell.

   Colours come from the tenant theme the renderer already puts on the page;
   where a token might be absent, every var() carries a fallback, so a tenant
   with a partial theme degrades to something deliberate instead of to
   transparent. */

/* ── Inbox: the thread list scrollbar ─────────────────────────────────────
   The channel list is ~650px of content in a 290px box, and the platform
   scrollbar sits on top of the card like a piece of chrome from another
   program. Thin, in the page's own ink, and only while it is wanted. */
.bo .bo-thread-list {
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--site-ink, #1A1A1A) 18%, transparent) transparent;
  scrollbar-gutter: stable;
}
.bo .bo-thread-list::-webkit-scrollbar { width: 6px; }
.bo .bo-thread-list::-webkit-scrollbar-track { background: transparent; }
.bo .bo-thread-list::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--site-ink, #1A1A1A) 16%, transparent);
  border-radius: 999px;
}
.bo .bo-thread-list::-webkit-scrollbar-thumb:hover {
  background: color-mix(in srgb, var(--site-ink, #1A1A1A) 30%, transparent);
}

/* ── Inbox: channel icons ─────────────────────────────────────────────────
   The channel chips were text only — "line", "facebook", "instagram" — which
   is the one place in an inbox where a glyph reads faster than a word. The
   renderer already puts the channel in the class name, so each mark goes on
   as a masked background: one element, no markup change, and it inherits the
   chip's own colour rather than introducing five brand palettes. */
.bo [class*="bo-channel"]::before {
  content: "";
  display: inline-block;
  width: 1em;
  height: 1em;
  margin-inline-end: 0.4em;
  vertical-align: -0.14em;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
.bo .bo-channel.line::before {
  -webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .5C5.6.5.5 4.8.5 10.1c0 4.7 4.2 8.7 9.9 9.4.4.1.9.3 1 .6.1.3.1.8 0 1.1l-.2 1c-.1.3-.2 1.2 1 .6 1.3-.5 6.9-4 9.4-6.9 1.7-1.9 2.4-3.8 2.4-5.8C23.5 4.8 18.4.5 12 .5z"/></svg>');
          mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .5C5.6.5.5 4.8.5 10.1c0 4.7 4.2 8.7 9.9 9.4.4.1.9.3 1 .6.1.3.1.8 0 1.1l-.2 1c-.1.3-.2 1.2 1 .6 1.3-.5 6.9-4 9.4-6.9 1.7-1.9 2.4-3.8 2.4-5.8C23.5 4.8 18.4.5 12 .5z"/></svg>');
}
.bo .bo-channel.facebook::before {
  -webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M24 12c0-6.6-5.4-12-12-12S0 5.4 0 12c0 6 4.4 11 10.1 11.9v-8.4H7.1V12h3V9.4c0-3 1.8-4.7 4.5-4.7 1.3 0 2.7.2 2.7.2V8h-1.5c-1.5 0-2 .9-2 1.9V12h3.3l-.5 3.5h-2.8v8.4C19.6 23 24 18 24 12z"/></svg>');
          mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M24 12c0-6.6-5.4-12-12-12S0 5.4 0 12c0 6 4.4 11 10.1 11.9v-8.4H7.1V12h3V9.4c0-3 1.8-4.7 4.5-4.7 1.3 0 2.7.2 2.7.2V8h-1.5c-1.5 0-2 .9-2 1.9V12h3.3l-.5 3.5h-2.8v8.4C19.6 23 24 18 24 12z"/></svg>');
}
.bo .bo-channel.instagram::before {
  -webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2"><rect x="2.5" y="2.5" width="19" height="19" rx="5.5"/><circle cx="12" cy="12" r="4.2"/><circle cx="17.6" cy="6.4" r="1.2" fill="black" stroke="none"/></svg>');
          mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2"><rect x="2.5" y="2.5" width="19" height="19" rx="5.5"/><circle cx="12" cy="12" r="4.2"/><circle cx="17.6" cy="6.4" r="1.2" fill="black" stroke="none"/></svg>');
}
.bo .bo-channel.whatsapp::before {
  -webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2a10 10 0 00-8.6 15L2 22l5.2-1.4A10 10 0 1012 2zm5.1 14.1c-.2.6-1.2 1.2-1.7 1.2-.5 0-.9.2-3-.9-2.6-1.3-4.2-4-4.3-4.2-.1-.2-1-1.4-1-2.6 0-1.2.6-1.8.9-2 .2-.3.5-.3.7-.3h.5c.2 0 .4 0 .6.5l.8 2c.1.2.1.4 0 .5l-.3.5-.3.3c-.1.1-.3.3-.1.6.2.3.8 1.3 1.7 2.1 1.2 1 2.1 1.4 2.4 1.5.3.1.4.1.6-.1l.9-1c.2-.2.3-.2.6-.1l2 1c.3.1.5.2.5.3.1.2.1.8-.1 1.4z"/></svg>');
          mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2a10 10 0 00-8.6 15L2 22l5.2-1.4A10 10 0 1012 2zm5.1 14.1c-.2.6-1.2 1.2-1.7 1.2-.5 0-.9.2-3-.9-2.6-1.3-4.2-4-4.3-4.2-.1-.2-1-1.4-1-2.6 0-1.2.6-1.8.9-2 .2-.3.5-.3.7-.3h.5c.2 0 .4 0 .6.5l.8 2c.1.2.1.4 0 .5l-.3.5-.3.3c-.1.1-.3.3-.1.6.2.3.8 1.3 1.7 2.1 1.2 1 2.1 1.4 2.4 1.5.3.1.4.1.6-.1l.9-1c.2-.2.3-.2.6-.1l2 1c.3.1.5.2.5.3.1.2.1.8-.1 1.4z"/></svg>');
}
.bo .bo-channel.website::before {
  -webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2"><circle cx="12" cy="12" r="9.5"/><path d="M2.5 12h19M12 2.5c2.5 2.6 3.8 6 3.8 9.5S14.5 18.9 12 21.5c-2.5-2.6-3.8-6-3.8-9.5S9.5 5.1 12 2.5z"/></svg>');
          mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2"><circle cx="12" cy="12" r="9.5"/><path d="M2.5 12h19M12 2.5c2.5 2.6 3.8 6 3.8 9.5S14.5 18.9 12 21.5c-2.5-2.6-3.8-6-3.8-9.5S9.5 5.1 12 2.5z"/></svg>');
}
/* The "all channels" control is a filter, not a channel: no mark. */
.bo .bo-channel-filter::before { display: none; }

/* ── The channel filter, with the same marks ──────────────────────────────
   These are real buttons carrying `data-channel`, so each gets the glyph its
   chip already has. "All channels" stays a word, because it is not one. */
.bo .bo-channel-filter button { display: inline-flex; align-items: center; gap: 5px; }
.bo .bo-channel-filter button[data-channel="line"]::before,
.bo .bo-channel-filter button[data-channel="facebook"]::before,
.bo .bo-channel-filter button[data-channel="instagram"]::before,
.bo .bo-channel-filter button[data-channel="whatsapp"]::before,
.bo .bo-channel-filter button[data-channel="website"]::before {
  content: "";
  width: 0.95em;
  height: 0.95em;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: contain; mask-size: contain;
}


/* ── Categories ───────────────────────────────────────────────────────────
   A row above the channels: what is unread, waiting, a group, or assigned. */
.hl-categories { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.hl-categories button {
  font-size: 10px;
  padding: 5px 9px;
  border-radius: 999px;
  border: 1px solid var(--border, #E8E4DE);
  background: var(--surface, #fff);
  color: var(--site-muted, #83867e);
  cursor: pointer;
}
.hl-categories button:hover { border-color: var(--gold, #C9A84C); }
.hl-categories button.active {
  background: color-mix(in srgb, var(--gold, #C9A84C) 14%, white);
  border-color: var(--gold, #C9A84C);
  color: var(--gold-deep, #A6843B);
  font-weight: 600;
}
.hl-empty-category { padding: 18px 16px; font-size: 11.5px; color: var(--site-muted, #83867e); text-align: center; }

/* ── The brand, top left ──────────────────────────────────────────────────
   The tenant's mark replaces the placeholder glyph inside the rail's own
   brand block. No second block, so no second logo and no second name. */
.bo .bo-brand { align-items: center; }
.bo .bo-brand .bo-mark { display: inline-flex; align-items: center; justify-content: center; }
.bo .bo-mark img.hl-logo {
  width: 26px;
  height: 26px;
  object-fit: contain;
  display: block;
}

/* ── Collapsed: the 3rem icon rail ───────────────────────────────────────
   One width on one element. The earlier version pushed `!important` at every
   selector that looked like a sidebar, which is why collapsing felt unsteady
   — two rules were fighting over the same box. */
.bo.hl-rail-collapsed .bo-side { width: 48px !important; min-width: 48px !important; padding-inline: 4px !important; }
.bo.hl-rail-collapsed nav a span,
.bo.hl-rail-collapsed nav button span,
.bo.hl-rail-collapsed .bo-brand .brand-words,
.bo.hl-rail-collapsed .bo-side-foot strong,
.bo.hl-rail-collapsed .bo-side-foot small { display: none; }
.bo.hl-rail-collapsed nav a,
.bo.hl-rail-collapsed nav button { justify-content: center; padding: 0; }
.bo.hl-rail-collapsed .bo-brand { justify-content: center; padding-inline: 0; gap: 0; }
.bo.hl-rail-collapsed .bo-side-foot { justify-content: center; text-align: center; padding-inline: 4px; }
.bo.hl-rail-collapsed .hl-account-menu { left: calc(100% + 6px); right: auto; bottom: 8px; width: 170px; }

@media (prefers-reduced-motion: no-preference) {
  .bo .bo-side { transition: width 160ms ease, min-width 160ms ease; }
}


/* ══ RAIL SPEC ════════════════════════════════════════════════════════════
   The rail, to the existing product's sidebar, measured from
   components/ui/sidebar.tsx and AppSidebar.tsx: 16rem expanded, 3rem
   collapsed, 32px rows at 12.5px, 16px icons, a hairline down the edge and
   a bordered footer pinned to the bottom.

   `!important` is deliberate and confined to this block. The kit sets the
   same properties on its own single-class selectors; without it the two sets
   land between the two specs, which is what made collapsing feel unsteady.
   Every value here is the product's, not a nudge. */
.bo .bo-side {
  width: 256px !important;
  min-width: 256px !important;
  padding: 16px 8px !important;
  gap: 10px !important;
  border-right: 1px solid var(--sidebar-border, var(--border, #E8E4DE)) !important;
  display: flex !important;
  flex-direction: column !important;
}
.bo .bo-side nav a,
.bo .bo-side nav button,
.bo .bo-nav a,
.bo .bo-nav button {
  height: 32px !important;
  min-height: 32px !important;
  padding: 0 8px !important;
  gap: 8px !important;
  border-radius: 6px !important;
  font-size: 12.5px !important;
  line-height: 1 !important;
}
.bo .bo-side nav svg,
.bo .bo-nav svg {
  width: 16px !important;
  height: 16px !important;
  flex: 0 0 auto !important;
}
.bo .bo-side-foot {
  position: sticky !important;
  bottom: 0 !important;
  margin-top: auto !important;
  padding: 10px 8px !important;
  background: var(--sidebar-bg, var(--surface, #fff)) !important;
  border-top: 1px solid var(--sidebar-border, var(--border, #E8E4DE)) !important;
  cursor: pointer;
}
.bo.hl-rail-collapsed .bo-side {
  width: 48px !important;
  min-width: 48px !important;
  padding-inline: 4px !important;
}


/* ══ SHELL TRACK ═══════════════════════════════════════════════════════════
   The rail is a GRID TRACK, not just a box: `.bo-shell` declares
   `235px minmax(0,1fr)`. Resizing only the rail left the track at 235px, so
   collapsing opened a 235px hole down the left of the workspace instead of
   giving the space to the content. The track is what has to move. */
.bo .bo-shell { grid-template-columns: 256px minmax(0, 1fr) !important; }
.bo.hl-rail-collapsed .bo-shell { grid-template-columns: 48px minmax(0, 1fr) !important; }
@media (prefers-reduced-motion: no-preference) {
  .bo .bo-shell { transition: grid-template-columns 160ms ease; }
}

/* Collapsed, the group heading has nothing to label and no room to sit in:
   "WORKSPACE" at 11px with 1.7px of tracking does not fit 48px, so it spilled
   over the icons. The kit hides it in its own narrow mode; this matches. */
.bo.hl-rail-collapsed .bo-side .eyebrow { display: none !important; }

/* ══ NO TOP STRIP ══════════════════════════════════════════════════════════
   Removed in local.js; hidden here too so it cannot flash during a render.
   The page heading takes its place and sticks instead, so the search and the
   title stay reachable while a long list scrolls under them. */
.bo .bo-topbar { display: none !important; }
.bo .bo-heading {
  position: sticky !important;
  top: 0;
  z-index: 30;
  padding-block: 10px !important;
  margin-bottom: 12px !important;
  background: var(--bo-bg, #f7f8f4);
  gap: 12px !important;
}
.bo .hl-head-tools { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }
.bo .hl-head-tools .bo-search { margin: 0; }
.bo .hl-head-tools .bo-search input { height: 32px; font-size: 12.5px; }
.bo .hl-head-tools .bo-button { height: 32px; font-size: 12px; display: inline-flex; align-items: center; }

/* The demo notice is a toast now, not a strip: it said the same sentence on
   every screen and cost a row of height to do it. Hidden in case a render
   puts it back before the script removes it. */
.bo .bo-demo { display: none !important; }

.hl-toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  z-index: 60;
  max-width: min(560px, calc(100vw - 32px));
  padding: 11px 16px;
  border-radius: 999px;
  border: 1px solid var(--border, #E8E4DE);
  background: var(--surface, #fff);
  color: var(--site-ink, #1A1A1A);
  box-shadow: 0 10px 34px rgba(0, 0, 0, 0.14);
  font-size: 12.5px;
  text-align: center;
  cursor: pointer;
  transform: translate(-50%, 12px);
  opacity: 0;
  transition: opacity 180ms ease, transform 180ms ease;
}
.hl-toast.is-in { opacity: 1; transform: translate(-50%, 0); }
@media (prefers-reduced-motion: reduce) {
  .hl-toast { transition: none; }
}


/* ══ ACCOUNT BLOCK, COLLAPSED ══════════════════════════════════════════════
   The markup is `.bo-avatar` plus `.user-words` ("Demo operator" / "Owner"),
   and it was the words that spilled past a 48px rail — my earlier rule hid
   `strong`/`small`, which this markup does not use. Only the avatar survives
   the collapse, centred, and the block refuses to overflow. */
.bo.hl-rail-collapsed .bo-side-foot .user-words { display: none !important; }
.bo.hl-rail-collapsed .bo-side-foot {
  gap: 0 !important;
  padding-inline: 4px !important;
  justify-content: center !important;
  overflow: hidden;
}
.bo.hl-rail-collapsed .bo-side-foot .bo-avatar { flex: 0 0 auto; }

/* Nothing in the rail may paint outside it at either width. */
.bo .bo-side { overflow-x: hidden; }


/* ══ PAGE HEADER ═══════════════════════════════════════════════════════════
   The kit opens every screen with 34px of padding, a 30px title and 28px
   beneath the block — around 140px before the first row of content, on a
   screen whose job is a list. The product gives the same three elements
   roughly half that.

   The eyebrow and the sentence stay: the eyebrow says where you are and the
   sentence is the only place a screen explains itself. They are just sized
   like labels instead of like a landing page. */
.bo .bo-body { padding-top: 18px !important; padding-bottom: 24px !important; }
.bo .bo-heading { margin-bottom: 16px !important; align-items: flex-start; }
.bo .bo-body h1 { font-size: 22px !important; letter-spacing: -0.3px !important; line-height: 1.2 !important; }
.bo .bo-heading p { font-size: 12.5px !important; margin-top: 2px !important; }
.bo .bo-body > .eyebrow,
.bo .bo-heading .eyebrow {
  font-size: 9.5px !important;
  letter-spacing: 0.16em !important;
  margin-bottom: 1px !important;
}


/* ══ PROPERTY GRID ═════════════════════════════════════════════════════════
   The grid exists in the renderer (`state.view==='grid'`); this brings it to
   the product's own card: a photo with a fixed ratio so a row of cards lines
   up whatever shape the photographs are, tight type, and the price as the
   loudest thing after the picture. */
.bo .bo-grid {
  grid-template-columns: repeat(auto-fill, minmax(248px, 1fr)) !important;
  gap: 16px !important;
}
.bo .bo-listing {
  border: 1px solid var(--border, #E8E4DE);
  border-radius: 12px;
  overflow: hidden;
  background: var(--surface, #fff);
  cursor: pointer;
  transition: box-shadow 140ms ease, border-color 140ms ease;
}
.bo .bo-listing:hover {
  border-color: var(--gold, #C9A84C);
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.08);
}
.bo .bo-listing > img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  background: var(--cream-100, #F6F4F0);
  cursor: zoom-in;           /* the photo opens the photos, not the record */
}
.bo .bo-listing .pad { padding: 12px 13px 14px !important; }
.bo .bo-listing h3 { font-size: 13.5px !important; line-height: 1.3 !important; margin: 4px 0 2px !important; }
.bo .bo-listing .small { font-size: 11.5px !important; }
.bo .bo-listing .price { font-size: 15px !important; font-weight: 600 !important; margin-top: 8px !important; }
.bo .bo-listing .price small { font-weight: 400; opacity: 0.7; }
/* The card is the control now, so its button is a quiet confirmation of
   that rather than the only way in. */
.bo .bo-listing .bo-button.secondary { width: 100%; margin-top: 10px; font-size: 12px; }
.bo .bo-thumb { cursor: zoom-in; }
.bo .bo-table tbody tr { cursor: pointer; }

/* ══ PHOTO GALLERY ═════════════════════════════════════════════════════════
   The product's full-screen viewer, to its own measurements: controls pinned
   to the viewport edges rather than to the image, so they stay in one place
   while photos of different shapes come and go. 44px at left/right 20, close
   top right, counter top centre, image capped at 88vw / 84vh, thumbnails
   along the bottom. */
.hl-lightbox {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(16, 16, 16, 0.92);
  backdrop-filter: blur(2px);
}
.hl-lightbox figure {
  margin: 0;
  max-width: 88vw;
  max-height: 84vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
.hl-lightbox img {
  display: block;
  max-width: 88vw;
  max-height: 84vh;
  object-fit: contain;
  border-radius: 8px;
  box-shadow: 0 32px 80px -20px rgba(0, 0, 0, 0.8);
}
.hl-lightbox figcaption {
  position: absolute;
  top: 22px;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 11px;
  letter-spacing: 0.14em;
  color: rgba(255, 255, 255, 0.6);
}
.hl-lightbox button {
  position: absolute;
  width: 44px;
  height: 44px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  z-index: 2;
}
.hl-lightbox button:hover { background: rgba(255, 255, 255, 0.2); }
.hl-lightbox .hl-lb-prev { left: 20px; }
.hl-lightbox .hl-lb-next { right: 20px; }
.hl-lightbox .hl-lb-close { top: 20px; right: 20px; width: 38px; height: 38px; font-size: 15px; }

.hl-lb-strip {
  position: absolute;
  bottom: 18px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 6px;
  max-width: 88vw;
  overflow-x: auto;
  padding: 4px;
  scrollbar-width: thin;
}
.hl-lb-strip img {
  width: 54px;
  height: 40px;
  object-fit: cover;
  border-radius: 4px;
  opacity: 0.45;
  cursor: pointer;
  box-shadow: none;
  transition: opacity 120ms ease;
}
.hl-lb-strip img.is-active, .hl-lb-strip img:hover { opacity: 1; }

@media (max-width: 600px) {
  .hl-lightbox .hl-lb-prev { left: 10px; }
  .hl-lightbox .hl-lb-next { right: 10px; }
}
}


/* ══ HEADING ROW ═══════════════════════════════════════════════════════════
   Everything on one left-aligned line rather than title left / tools pushed
   to the far right, where the search sat a screen-width away from the list
   it filters. */
.bo .bo-heading { justify-content: flex-start !important; flex-wrap: wrap; }
/* Far right on every screen. With a section's own actions present they take
   the slack first and this sits just after them, so the "View website" icon
   is the last thing on the row wherever you are — Leads and Activity have no
   actions of their own, and it used to drift left to the title there. */
.bo .hl-head-tools { margin-inline-start: auto; }

/* The search had `border:0` on a tinted fill, so on the grey workspace it
   read as a gap rather than a control. */
.bo .bo-search { width: 260px !important; }
.bo .bo-search input {
  border: 1px solid var(--border, #E8E4DE) !important;
  border-radius: 8px !important;
  background: var(--surface, #fff) !important;
  width: 100%;
}
.bo .bo-search input:focus-visible {
  outline: 2px solid var(--gold, #C9A84C);
  outline-offset: 1px;
  border-color: var(--gold, #C9A84C) !important;
}

/* ══ UNREAD ════════════════════════════════════════════════════════════════
   The count belongs on the Inbox in the rail, where it is useful from any
   screen — not restated in the header of the screen you are already on. */
.bo .bo-nav .bo-count {
  margin-left: auto;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: #ef4444 !important;
  color: #fff !important;
  font-size: 10.5px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
/* Collapsed, there is no room beside the icon: a dot on the corner instead. */
.bo.hl-rail-collapsed .bo-nav .bo-count {
  position: absolute;
  top: 2px;
  right: 6px;
  min-width: 8px;
  height: 8px;
  padding: 0;
  font-size: 0;
  border: 1.5px solid var(--sidebar-bg, #fff);
}
.bo.hl-rail-collapsed .bo-nav { position: relative; }


/* ══ NARROW HEADER ═════════════════════════════════════════════════════════
   One short line, the way the product's header is: label, title, controls.
   The sentence under each title ("One inbox. Every channel…") explained the
   screen on every visit and cost a row of height to do it — it is a tagline,
   not information, so it goes. */
.bo .bo-heading p { display: none !important; }
.bo .bo-body h1 { font-size: 18px !important; }
.bo .bo-heading {
  padding-block: 8px !important;
  margin-bottom: 10px !important;
  align-items: center !important;
}

/* The section's own actions — Add property, New lead — sit at the far right,
   in the same place on every screen, so the control you want is where you
   left it. */
.bo .bo-heading .hl-head-actions { margin-inline-start: auto !important; display: flex; gap: 8px; align-items: center; }
.bo .bo-heading .bo-button { height: 32px !important; font-size: 12px !important; display: inline-flex; align-items: center; gap: 6px; }

/* "View website" leaves the site and comes back; it does not need a sentence. */
.bo .hl-icon-only {
  width: 32px;
  padding: 0 !important;
  justify-content: center;
}
.bo .hl-icon-only svg { width: 15px; height: 15px; }


/* ══ INBOX HEIGHT ══════════════════════════════════════════════════════════
   Two separate faults made the inbox short AND cropped.

   1 · `height: calc(100vh - 234px)` was measured against the old chrome — a
       78px strip, a 34px gutter, a tall heading and the demo banner. Those
       are gone, so the box was ~120px shorter than its space while still
       behaving as though the space were taken.
   2 · A grid or flex child defaults to `min-height: auto`, which means "at
       least as tall as my content". Each pane declared `overflow:auto` and
       none of them could honour it: the content set the height, the pane
       grew past the box, and the bottom was clipped instead of scrolling.

   `dvh` rather than `vh` so a mobile browser's collapsing toolbar does not
   leave the composer under the edge of the screen. */
.bo .bo-inbox {
  height: calc(100dvh - 124px) !important;
  min-height: 440px !important;
}
.bo .bo-inbox > * { min-height: 0 !important; }
.bo .bo-conversation { min-height: 0 !important; }
.bo .bo-messages { min-height: 0 !important; }
.bo .bo-thread-list { max-height: none !important; }
.bo .bo-context { min-height: 0 !important; overflow-y: auto !important; }

/* Each pane gets the same quiet scrollbar as the thread list, so three
   scrolling columns do not produce three different pieces of chrome. */
.bo .bo-messages, .bo .bo-context {
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--site-ink, #1A1A1A) 18%, transparent) transparent;
}
.bo .bo-messages::-webkit-scrollbar, .bo .bo-context::-webkit-scrollbar { width: 6px; }
.bo .bo-messages::-webkit-scrollbar-thumb, .bo .bo-context::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--site-ink, #1A1A1A) 16%, transparent);
  border-radius: 999px;
}

/* More of the window goes to the work. */
.bo .bo-body { padding-inline: 22px !important; }

.bo .bo-channel-filter button[data-channel="line"]::before {
  -webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .5C5.6.5.5 4.8.5 10.1c0 4.7 4.2 8.7 9.9 9.4.4.1.9.3 1 .6.1.3.1.8 0 1.1l-.2 1c-.1.3-.2 1.2 1 .6 1.3-.5 6.9-4 9.4-6.9 1.7-1.9 2.4-3.8 2.4-5.8C23.5 4.8 18.4.5 12 .5z"/></svg>');
          mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .5C5.6.5.5 4.8.5 10.1c0 4.7 4.2 8.7 9.9 9.4.4.1.9.3 1 .6.1.3.1.8 0 1.1l-.2 1c-.1.3-.2 1.2 1 .6 1.3-.5 6.9-4 9.4-6.9 1.7-1.9 2.4-3.8 2.4-5.8C23.5 4.8 18.4.5 12 .5z"/></svg>');
}

.bo .bo-channel-filter button[data-channel="facebook"]::before {
  -webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M24 12c0-6.6-5.4-12-12-12S0 5.4 0 12c0 6 4.4 11 10.1 11.9v-8.4H7.1V12h3V9.4c0-3 1.8-4.7 4.5-4.7 1.3 0 2.7.2 2.7.2V8h-1.5c-1.5 0-2 .9-2 1.9V12h3.3l-.5 3.5h-2.8v8.4C19.6 23 24 18 24 12z"/></svg>');
          mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M24 12c0-6.6-5.4-12-12-12S0 5.4 0 12c0 6 4.4 11 10.1 11.9v-8.4H7.1V12h3V9.4c0-3 1.8-4.7 4.5-4.7 1.3 0 2.7.2 2.7.2V8h-1.5c-1.5 0-2 .9-2 1.9V12h3.3l-.5 3.5h-2.8v8.4C19.6 23 24 18 24 12z"/></svg>');
}

.bo .bo-channel-filter button[data-channel="instagram"]::before {
  -webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2"><rect x="2.5" y="2.5" width="19" height="19" rx="5.5"/><circle cx="12" cy="12" r="4.2"/><circle cx="17.6" cy="6.4" r="1.2" fill="black" stroke="none"/></svg>');
          mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2"><rect x="2.5" y="2.5" width="19" height="19" rx="5.5"/><circle cx="12" cy="12" r="4.2"/><circle cx="17.6" cy="6.4" r="1.2" fill="black" stroke="none"/></svg>');
}

.bo .bo-channel-filter button[data-channel="whatsapp"]::before {
  -webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2a10 10 0 00-8.6 15L2 22l5.2-1.4A10 10 0 1012 2zm5.1 14.1c-.2.6-1.2 1.2-1.7 1.2-.5 0-.9.2-3-.9-2.6-1.3-4.2-4-4.3-4.2-.1-.2-1-1.4-1-2.6 0-1.2.6-1.8.9-2 .2-.3.5-.3.7-.3h.5c.2 0 .4 0 .6.5l.8 2c.1.2.1.4 0 .5l-.3.5-.3.3c-.1.1-.3.3-.1.6.2.3.8 1.3 1.7 2.1 1.2 1 2.1 1.4 2.4 1.5.3.1.4.1.6-.1l.9-1c.2-.2.3-.2.6-.1l2 1c.3.1.5.2.5.3.1.2.1.8-.1 1.4z"/></svg>');
          mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2a10 10 0 00-8.6 15L2 22l5.2-1.4A10 10 0 1012 2zm5.1 14.1c-.2.6-1.2 1.2-1.7 1.2-.5 0-.9.2-3-.9-2.6-1.3-4.2-4-4.3-4.2-.1-.2-1-1.4-1-2.6 0-1.2.6-1.8.9-2 .2-.3.5-.3.7-.3h.5c.2 0 .4 0 .6.5l.8 2c.1.2.1.4 0 .5l-.3.5-.3.3c-.1.1-.3.3-.1.6.2.3.8 1.3 1.7 2.1 1.2 1 2.1 1.4 2.4 1.5.3.1.4.1.6-.1l.9-1c.2-.2.3-.2.6-.1l2 1c.3.1.5.2.5.3.1.2.1.8-.1 1.4z"/></svg>');
}

.bo .bo-channel-filter button[data-channel="website"]::before {
  -webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2"><circle cx="12" cy="12" r="9.5"/><path d="M2.5 12h19M12 2.5c2.5 2.6 3.8 6 3.8 9.5S14.5 18.9 12 21.5c-2.5-2.6-3.8-6-3.8-9.5S9.5 5.1 12 2.5z"/></svg>');
          mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2"><circle cx="12" cy="12" r="9.5"/><path d="M2.5 12h19M12 2.5c2.5 2.6 3.8 6 3.8 9.5S14.5 18.9 12 21.5c-2.5-2.6-3.8-6-3.8-9.5S9.5 5.1 12 2.5z"/></svg>');
}


/* ══ THREAD ROWS ═══════════════════════════════════════════════════════════
   Narrower blocks: more conversations visible without scrolling, which is
   the whole point of a list. */
.bo .bo-thread { padding: 9px 12px !important; gap: 9px !important; }
.bo .bo-thread .bo-row-info strong { font-size: 12.5px !important; }
.bo .bo-thread .bo-row-info small { font-size: 11px !important; }
.bo .bo-thread .bo-avatar { width: 30px !important; height: 30px !important; font-size: 11px !important; }

/* The photo sits over the initials rather than replacing them, so an expired
   URL falls back to a letter instead of an empty circle. */
.bo .bo-avatar, .bo .big-avatar { position: relative; overflow: hidden; }
.hl-avatar-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}


/* ══ CONVERSATION ══════════════════════════════════════════════════════════
   A photo or a sticker IS the message: a card border, padding and a white
   ground around it make it look like an attachment to something else. The
   image sits on its own, rounded, with nothing drawn around it — a sticker
   especially, which is meant to read as a drawing on the page. */
.bo .bo-messages img,
.bo .bo-messages .bo-attachment {
  border: 0 !important;
  background: transparent !important;
  padding: 0 !important;
  border-radius: 10px;
  display: block;
}
.bo .bo-messages .bo-attachment { box-shadow: none !important; }
/* A sticker is small and square; it should not be blown up to photo width. */
.bo .bo-messages img[src*="stickershop"] {
  width: 112px !important;
  height: auto !important;
  border-radius: 0 !important;
}
.bo .bo-messages > * { max-width: 78%; }
.bo .bo-messages { gap: 12px !important; padding: 18px 20px !important; }


/* ══ CUSTOMER CARD ═════════════════════════════════════════════════════════
   Folded away, the third track goes to zero and the conversation takes the
   width — the panel is not merely hidden behind a column that still exists. */
.bo.hl-context-collapsed .bo-inbox {
  grid-template-columns: 290px minmax(280px, 1fr) 0 !important;
}
.bo.hl-context-collapsed .bo-context {
  display: none !important;
}
.bo .hl-context-toggle {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  border: 1px solid var(--border, #E8E4DE);
  background: var(--surface, #fff);
  color: var(--site-ink, #1A1A1A);
  cursor: pointer;
}
.bo .hl-context-toggle:hover { border-color: var(--gold, #C9A84C); }
.bo .hl-context-toggle:focus-visible { outline: 2px solid var(--gold, #C9A84C); outline-offset: 2px; }
@media (prefers-reduced-motion: no-preference) {
  .bo .bo-inbox { transition: grid-template-columns 150ms ease; }
}


/* == MAP VIEW ==============================================================
   Area pins, not addresses - see the note in local.js. */
.bo .hl-map { margin-top: 4px; }
.bo .hl-map-canvas {
  height: calc(100dvh - 210px);
  min-height: 420px;
  border-radius: 12px;
  border: 1px solid var(--border, #E8E4DE);
  overflow: hidden;
}
.bo .hl-map-note { margin: 8px 2px 0; font-size: 11px; color: var(--site-muted, #83867e); }
.bo .hl-map-btn.active {
  background: color-mix(in srgb, var(--gold, #C9A84C) 16%, white);
  border-color: var(--gold, #C9A84C);
}
.hl-map-list { margin: 6px 0; padding-left: 16px; }
.hl-map-list button {
  border: 0; background: none; padding: 0; cursor: pointer;
  color: var(--gold-deep, #A6843B); text-align: left; font-size: 12px;
}
.hl-map-count { font-size: 11px; color: #666; }

/* == CHANNEL COLOURS =======================================================
   Each channel in its own brand colour, in the filter and on the thread
   chips, so the row is scanned by colour before it is read. */
.bo .bo-channel.line::before,
.bo .bo-channel-filter button[data-channel="line"]::before { background-color: #06C755 !important; }
.bo .bo-channel.facebook::before,
.bo .bo-channel-filter button[data-channel="facebook"]::before { background-color: #1877F2 !important; }
.bo .bo-channel.instagram::before,
.bo .bo-channel-filter button[data-channel="instagram"]::before { background-color: #E1306C !important; }
.bo .bo-channel.whatsapp::before,
.bo .bo-channel-filter button[data-channel="whatsapp"]::before { background-color: #25D366 !important; }
.bo .bo-channel.website::before,
.bo .bo-channel-filter button[data-channel="website"]::before { background-color: var(--gold, #C9A84C) !important; }

/* == CATEGORY CHIPS, MINIMISED =============================================
   Channels alone by default; the rest appear on request. */
.hl-categories button[data-category] { display: none; }
.hl-categories.is-open button[data-category] { display: inline-flex; }
.hl-categories button[data-category="all"] { display: inline-flex; }
.hl-categories .hl-more {
  font-size: 10px;
  padding: 5px 9px;
  border-radius: 999px;
  border: 1px dashed var(--border, #E8E4DE);
  background: transparent;
  color: var(--site-muted, #83867e);
  cursor: pointer;
}
.hl-categories .hl-more:hover { border-color: var(--gold, #C9A84C); color: var(--gold-deep, #A6843B); }


/* == BRAND CARET ===========================================================
   Emptying `.bo-mark` to drop in the logo leaves a text node the browser can
   put a caret in, so clicking around the rail parked an I-beam in the logo.
   Nothing in the brand block is text to select. */
.bo .bo-brand, .bo .bo-mark { user-select: none; -webkit-user-select: none; cursor: default; }
.bo .bo-mark img.hl-logo { pointer-events: none; }

/* Every screen's heading starts at the left edge, whatever its contents. */
.bo .bo-heading > :first-child { text-align: left; margin-inline-end: 0; }


/* == NO FLASH ==============================================================
   The renderer rebuilds the shell on every selection. Two things made that
   visible: the strip we remove in script was painted first (now never
   displayed at all, from the stylesheet), and the message list animated its
   incoming content. Selecting a conversation should look like a swap, not a
   transition. */
.bo .bo-messages, .bo .bo-messages > *, .bo .bo-thread { animation: none !important; }
.bo .bo-messages { scroll-behavior: auto; }
.bo .bo-thread, .bo .bo-thread * { transition: none !important; }
