/* Lacak's additions, loaded after the CRM's own stylesheets (pr20.css and the six index.html
   sheets, copied unchanged). Nothing here restyles the CRM's chat or panel, and the list only loses
   its channel mark; these rules cover only what the CRM does not have, each drawn from the nearest
   thing the CRM does: the list's loading row (the CRM's row),
   the message menu and the sale popover (the CRM's message menu and stage picker, Lite's sheet), the panel's
   Penjualan (Lite's summary card, form and sale cards, with a delivery chip in the CRM's pill form),
   its journey's Lacak tone, the source dialog's touch rows, the chat's loading pills, the return
   control's motion and the viewer's video and file stages (the CRM's date pill, round control and
   viewer frame), Lite's sale form, source trail
   and name edit, the account menu's entries (the CRM's message menu rows), and the no-Business
   page (the CRM's access card). */
:root {
  --yellow: #f5c33b;
  --yellow-wash: #fff5d6;
  --yellow-edge: #e3ac2c;
  --yellow-ink: #5c3f00;
  --menu-shadow: 0 16px 40px rgba(42, 38, 32, .12);
  /* Pelanggan's one motion family: in on the CRM's decelerating curve (stage picker, context panel),
     out on its accelerating one (context panel close); colour and opacity on ease. */
  --m-in: cubic-bezier(.22, .8, .25, 1);
  --m-out: cubic-bezier(.4, 0, 1, 1);
  --m-hover: 120ms;
  --m-pop: 160ms;
  --m-move: 220ms;
  --m-exit: 140ms;
  /* The one look for anything that opens on hover or focus: the Dashboard's explanation card (dashboard.css
     .dx-def, the CRM's .db-chart-tooltip). White, a hairline edge, 10px corners, its soft drop shadow; a name
     in ink over muted 12px text; it fades in and rises 7px over 120ms, and goes the same way. */
  --hover-card-bg: #fff;
  --hover-card-edge: 1px solid #dde3eb;
  --hover-card-radius: 10px;
  --hover-card-shadow: 0 14px 30px -14px rgba(23, 41, 68, .32);
  --hover-card-ink: #5c6a86;
  --hover-card-title: #172033;
  --hover-card-size: 12px;
  --hover-card-title-size: 12.5px;
  --hover-card-leading: 1.45;
  --hover-card-rise: 7px;
}
[hidden] { display: none !important; }
.brand-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.brand-icon { width: 16px; height: 16px; flex: 0 0 16px; }
.spinner { width: 14px; height: 14px; flex: 0 0 14px; border: 2px solid var(--line-strong); border-top-color: var(--navy); border-radius: 50%; animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- Shell: Business switcher, account menu, title-only pages ---------- */
.tenant-shell .rail-account { cursor: pointer; color: inherit; }
/* Without the CRM bell, the Business card's third column holds Lite's chevron (shell.css); collapsed, the
   card keeps its building mark so it is not an empty box. */
.tenant-shell .rail-workspace { grid-template-columns: 40px minmax(0, 1fr) 16px; }
.tenant-shell.rail-collapsed .rail-workspace-icon { opacity: 1; pointer-events: auto; }
/* The switcher's trigger: the Business name in the card, its hit area spread over the whole card (shell.css). */
.lacak-business-trigger { display: block; min-width: 0; text-align: left; cursor: pointer; }
.lacak-business-trigger span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tenant-shell .rail-workspace-copy #g5-business-select { display: block; max-width: 100%; line-height: 1.2; }
/* A Business the person cannot open: the brand stays, going nowhere. */
.tenant-shell .brand-block:disabled { cursor: default; opacity: 1; background: transparent; transform: none; }

/* The account menu and the phone's frame are Lite's (shell.css). */
.login-card > p { margin-bottom: 1em; }
.main-content { outline: none; }

/* A person in no Business, on the CRM's access card. */
.lacak-handoff p { display: flex; align-items: center; justify-content: center; gap: 10px; }
.g5-access-main { outline: none; }

/* Subscription ended: Lite's access card (lite-merged.html .no-seat-*, .service-*), its
   tokens set on the scope, centred in the CRM's content frame. */
.lacak-access { --ink: #172033; --muted: #687386; --line: #e5e3df; --navy: #18243a; --blue: #2f62a4; --blue-soft: #edf3fb; min-height: 100dvh; padding: 28px; color: var(--ink); background: #f7f7f5; }
.lacak-access .no-seat-page { display: grid; min-height: min(620px, 75vh); place-items: center; }
.lacak-access .no-seat-card { width: min(480px, 100%); padding: 36px 28px; border: 1px solid var(--line); border-radius: 16px; background: #fff; text-align: center; }
.lacak-access .no-seat-icon { display: grid; width: 52px; height: 52px; place-items: center; margin: 0 auto 20px; border-radius: 14px; background: var(--blue-soft); color: var(--blue); }
.lacak-access .no-seat-icon svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.lacak-access .service-ended-icon { color: #976322; background: #fff4e3; }
.lacak-access .eyebrow { color: var(--muted); font-size: 9px; font-weight: 820; text-transform: uppercase; letter-spacing: .06em; }
.lacak-access .no-seat-card h1 { margin: 10px 0 12px; font-size: 24px; line-height: 1.25; letter-spacing: -.025em; }
.lacak-access .no-seat-card h1:focus { outline: none; }
.lacak-access .no-seat-card p { margin: 0 auto 22px; color: var(--muted); font-size: 12px; line-height: 1.7; }
.lacak-access .service-retention { display: grid; gap: 7px; margin: 0 0 24px; padding: 17px; border: 1px solid #e3e8ef; border-radius: 10px; background: #f7f9fc; }
.lacak-access .service-retention small { color: var(--muted); font-size: 11px; }
.lacak-access .service-retention strong { color: var(--ink); font-size: 18px; font-variant-numeric: tabular-nums; }
.lacak-access .service-retention span { color: var(--muted); font-size: 11px; line-height: 1.6; }
.lacak-access .no-seat-action { display: inline-flex; align-items: center; justify-content: center; gap: 10px; min-height: 44px; max-width: 100%; padding: 11px 20px; border: 1px solid var(--navy); border-radius: 10px; background: var(--navy); color: #fff; font: inherit; font-size: 12px; font-weight: 700; line-height: 1.4; cursor: pointer; box-shadow: 0 3px 8px rgba(23, 32, 51, .12); transition: background .15s, box-shadow .15s; }
.lacak-access .no-seat-action:hover { background: #293e5b; box-shadow: 0 5px 12px rgba(23, 32, 51, .18); }
.lacak-access .no-seat-action:focus-visible { outline: 3px solid rgba(47, 98, 164, .35); outline-offset: 2px; }
.lacak-access .no-seat-action svg { flex: 0 0 16px; width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
@media (max-width: 640px) {
  .lacak-access { min-height: calc(100dvh - 64px); padding: 14px; }
}

/* ---------- Pelanggan: the list ---------- */
/* The CRM's row (product-ui.css .conversation-list .conversation-row) with WhatsApp Web's round avatar
   in WhatsApp's proportions, scaled to the CRM's 54px row: WhatsApp's 49px circle fills 68% of its 72px
   row, sits 13px (18%) from the left edge and 15px (21%) from the copy. Here that is a 37px circle, 10px
   from the edge, 11px from the copy (its column is the circle and 5px more, plus the row's 6px gap),
   with 8.5px of the row clear above and below. The circle holds the panel's mark for the customer
   (app.js cxpAvatar): the same tint and initials, the initials scaled with the circle. A press, hover or
   the selected row changes the row behind it, never the mark: a white rim, unseen on a white row, keeps
   the circle's edge on the blue of the selected row. The list's column and the chat keep their widths;
   the copy and the time keep their order and their lines in the row, one line each, cut with an ellipsis. */
.conversation-list .conversation-row { grid-template-columns: 42px minmax(0, 1fr) auto !important; padding-left: 10px !important; }
.conversation-list .conversation-row .lacak-row-avatar { display: grid; place-items: center; align-self: center; width: 37px; height: 37px; border-radius: 50%; box-shadow: 0 0 0 1.5px #fff; font-size: 11px; font-weight: 820; letter-spacing: 0; line-height: 1; }
/* The panel's four tints (product-ui.css .cxp .cxp-avatar.tint-*), as they are. */
.conversation-row .lacak-row-avatar.tint-blue { background: linear-gradient(145deg, #e8effa, #f6f9fd); color: #2a5896; }
.conversation-row .lacak-row-avatar.tint-green { background: linear-gradient(145deg, #e4f4ec, #f5fbf8); color: #12704a; }
.conversation-row .lacak-row-avatar.tint-purple { background: linear-gradient(145deg, #f0eafa, #faf7fe); color: #63428f; }
.conversation-row .lacak-row-avatar.tint-amber { background: linear-gradient(145deg, #fcf1db, #fffaf0); color: #8a5709; }
/* A long name keeps to its row: cut with an ellipsis before the time, said whole on hover (app.js tooltips). */
.conversation-list .conversation-copy, .conversation-list .conversation-name-line { min-width: 0; }
.conversation-list .conversation-name-line strong { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Loading and failure take a row's place: its height, its inset, its rule; the text is the preview's. */
.conversation-list .conversation-list-state { min-height: 54px; display: flex; align-items: center; gap: 8px; padding: 2px 13px; border-bottom: 1px solid var(--line); background: #fff; color: var(--muted); font-size: 10px; line-height: 1.4; }
.conversation-list .conversation-list-state.error { justify-content: space-between; color: var(--danger); }
.conversation-list-state .quiet-button { flex: 0 0 auto; min-height: 32px; padding: 0 4px; font-size: 11px; }
.conversation-list-state .spinner { width: 12px; height: 12px; flex-basis: 12px; }
@media (max-width: 390px) {
  /* The same proportions in the CRM's 52px phone row: a 35px circle, 9px from the edge, 11px from the copy. */
  .conversation-list .conversation-row { grid-template-columns: 40px minmax(0, 1fr) auto !important; padding-left: 9px !important; }
  .conversation-list .conversation-row .lacak-row-avatar { width: 35px; height: 35px; font-size: 10.5px; }
  .conversation-list .conversation-list-state { min-height: 52px; padding-inline: 11px; }
}

/* ---------- Pelanggan: the chat's canvas ----------
   WhatsApp Business's chat screen: its light beige ground (#efeae2, the CRM's own) under a faint doodle
   pattern of Lacak's own (assets/chat-wallpaper.svg, a 300px tile of line drawings at 16% of a warm brown),
   low enough that the bubbles read first. It stays put while the messages scroll over it, as WhatsApp's does. */
.room-body .messages-scroll { background: #efeae2 url("../assets/chat-wallpaper.svg") 0 0 / 300px 300px repeat; }

/* ---------- Pelanggan: chat states ---------- */
.list-state, .chat-state { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 10px; padding: 16px; color: var(--muted); font-size: 12px; text-align: center; }
.list-state.error, .chat-state.error { color: var(--danger); }
.chat-state { align-self: center; border-radius: 8px; background: rgba(255, 255, 255, .9); }
.conversation-room-pane > .empty-action { margin: 16px; }

/* Loading and failure inside the chat take the date pill's form, so they read as part of the canvas:
   at the top while earlier messages load, at the bottom for later ones, centred while a window loads. */
.messages-scroll .chat-state { align-self: center; flex-wrap: nowrap; gap: 8px; min-height: 30px; margin: 1rem auto; padding: .36rem .8rem; border-radius: .45rem; background: #fff; box-shadow: 0 1px .5px rgb(11 20 26 / .13); color: #54656f; font-size: .78rem; line-height: 1.3; }
.messages-scroll .chat-state .spinner { width: 12px; height: 12px; flex-basis: 12px; border-top-color: #54656f; }
.messages-scroll .chat-state.whole { margin: auto; }
.messages-scroll .chat-state.error { color: var(--danger); }
.messages-scroll .chat-state.error .secondary-button { min-height: 30px; padding: 0 10px; font-size: .78rem; }
/* A conversation that did not load: the CRM's empty form (base.css .empty-action) with Coba lagi, centred
   on the canvas where the messages would be. */
.messages-scroll .empty-action.chat-failed { align-self: center; width: min(300px, 100%); margin: auto; text-align: center; }
.chat-failed .secondary-button { min-height: 36px; }

/* The CRM's round control to the latest message, lifted above Lite's reply line instead of the composer. */
.message-column .scroll-bottom-fab { bottom: calc(var(--reply-line, 34px) + 16px); }
.scroll-bottom-fab:hover { color: #3b4a54; background: #f7f8f9; }
.scroll-bottom-fab:focus-visible { outline: 3px solid rgba(47, 98, 164, .35); outline-offset: 2px; }

.media-preview-image { object-fit: cover; }
/* WhatsApp's filenames are long; the attachment row is wide enough to show one whole where the chat allows. */
#messages { container-type: inline-size; }
.message-line .message-media { min-width: min(18rem, calc(72cqw - 2.5rem)); }

/* ---------- The media viewer: what the CRM's does not show ---------- */
.media-viewer-stage > img { border-radius: 0; }
.media-viewer-stage .media-viewer-sticker { width: min(60vmin, 22rem); height: min(60vmin, 22rem); font-size: min(44vmin, 16rem); }
/* A video plays in the photo's frame: as large as the stage allows, with the browser's own controls. */
.media-viewer-video { position: relative; display: grid; place-items: center; max-width: min(1100px, 94vw); }
.media-viewer-video video { display: block; max-width: 100%; max-height: calc(100dvh - 106px); background: #000; box-shadow: 0 12px 45px rgb(0 0 0 / .34); }
.media-viewer-video .spinner { position: absolute; width: 28px; height: 28px; flex-basis: 28px; border-color: rgb(255 255 255 / .25); border-top-color: #fff; opacity: 0; pointer-events: none; }
.media-viewer-video.is-loading .spinner { opacity: 1; }
/* A file that has no preview: what it is, and Unduh. Name and size stay in the header, as for a photo. */
.media-viewer-file { display: grid; justify-items: center; gap: 14px; width: min(320px, 100%); padding: 30px 24px 24px; border-radius: 16px; background: #1f2c33; border: 1px solid rgb(255 255 255 / .08); box-shadow: 0 12px 45px rgb(0 0 0 / .34); text-align: center; }
.media-viewer-file > .icon { width: 56px; height: 56px; padding: 14px; border-radius: 14px; background: #dbe7e4; color: #49645e; }
.media-viewer-file > strong { color: #e9edef; font-size: 14px; font-weight: 650; line-height: 1.45; }
.media-viewer-file[role="alert"] > strong { color: #f1d4d4; font-weight: 600; }
.media-viewer a.media-viewer-download { min-width: 160px; min-height: 44px; border-color: #fff; background: #fff; color: #111b21; text-decoration: none; }
.media-viewer a.media-viewer-download:hover { background: #e9edef; }
.media-viewer-download .icon { width: 16px; height: 16px; }
.media-viewer-close:focus-visible, .media-viewer-download:focus-visible { outline: 3px solid rgb(255 255 255 / .55); outline-offset: 2px; }

.sales-jump { min-width: 52px; height: 36px; display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 0 11px; border: 1px solid var(--line); border-radius: 999px; background: #fff; color: var(--muted); font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums; }
.sales-jump .icon { width: 15px; height: 15px; }
.sales-jump.has-sales { border-color: var(--yellow-edge); background: var(--yellow); color: var(--yellow-ink); }
.sales-jump.has-sales:hover, .sales-jump.has-sales[aria-expanded="true"] { background: #f2b820; }
.sales-jump.has-sales[aria-expanded="true"] { box-shadow: inset 0 1px 2px rgb(92 63 0 / .22); }
.sales-jump:focus-visible { outline: 3px solid rgba(47, 98, 164, .35); outline-offset: 2px; }

/* ---------- The header's sales list ----------
   WhatsApp Web's starred messages for one chat, in its own surface: white, WhatsApp's dropdown shadow
   and dividers, rows that go #f5f6f6 under the pointer with a chevron to say they lead somewhere. Each
   row leads with the amount and the date; under them, the message in a small copy of its marked bubble,
   on the side it sits in the chat; then Lite's source path at the panel card's size. Anchored under the
   header's mark (app.js positionSaleList); on a phone, the sale form's bottom sheet. */
.sale-list { position: fixed; z-index: 108; display: flex; flex-direction: column; overflow: hidden; border: 1px solid #e9edef; border-radius: 12px; background: #fff; box-shadow: 0 2px 5px rgb(11 20 26 / .2), 0 12px 32px rgb(11 20 26 / .16); color: #111b21; outline: none; }
/* The list itself takes focus only when a pointer opened it; its rows show focus. */
#sale-list:focus, #sale-list:focus-visible { outline: none; }
.sale-list.entering { transform-origin: top right; animation: lacak-list-in var(--m-pop) var(--m-in); }
@keyframes lacak-list-in { from { opacity: 0; transform: translateY(-4px) scale(.97); } }
.sale-list > header { display: flex; flex: 0 0 auto; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 8px 10px 16px; border-bottom: 1px solid #e9edef; }
.sale-list h2 { margin: 0; font-size: 15px; font-weight: 700; letter-spacing: -.01em; }
.sale-list-close { display: grid; width: 34px; height: 34px; place-items: center; padding: 0; border: 0; border-radius: 50%; background: transparent; color: #54656f; cursor: pointer; }
.sale-list-close:hover { background: #f0f2f5; }
.sale-list-close .icon { width: 18px; height: 18px; }
.sale-list-close:focus-visible { outline: 2px solid rgba(47, 98, 164, .55); outline-offset: 0; }
.sale-list-rows { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.sale-row { display: grid; gap: 7px; width: 100%; padding: 12px 14px 13px 16px; border: 0; border-bottom: 1px solid #e9edef; background: #fff; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.sale-row:last-of-type { border-bottom: 0; }
.sale-row:hover { background: #f0f2f5; }
.sale-row:focus-visible { outline: 2px solid rgba(47, 98, 164, .55); outline-offset: -2px; }
.sale-row-head { display: grid; grid-template-columns: minmax(0, 1fr) auto 14px; align-items: center; gap: 8px; }
.sale-row-head b { font-size: 15px; font-weight: 800; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
.sale-row-head time { color: #667781; font-size: 12px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.sale-row-head .icon { width: 14px; height: 14px; color: #8696a0; }
.sale-row:hover .sale-row-head .icon { color: #3b4a54; }
/* The message, as its marked bubble: Lacak's wash, the yellow bar on the side the bubble sits on. */
.sale-row-quote { justify-self: start; display: inline-flex; align-items: baseline; gap: 10px; max-width: 88%; min-width: 0; padding: 5px 8px 6px 10px; border-radius: 7.5px; background: var(--yellow-wash); box-shadow: inset 3px 0 0 var(--yellow), 0 1px .5px rgb(11 20 26 / .13); font-size: 13px; line-height: 1.35; white-space: nowrap; }
.sale-row-quote > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* The bubble's clock, at the chat footer's size and colour. */
.sale-row-quote time { flex: 0 0 auto; color: #667781; font-size: 11px; font-variant-numeric: tabular-nums; }
.sale-row-quote.outgoing { justify-self: end; box-shadow: inset -3px 0 0 var(--yellow), 0 1px .5px rgb(11 20 26 / .13); }
.sale-row-panel { display: inline-flex; align-items: center; gap: 6px; color: #667781; font-size: 12.5px; }
.sale-row-panel .icon { width: 13px; height: 13px; }
.sale-row-source { min-width: 0; }
.sale-row-source .trail { gap: 3px 6px; font-size: 11.5px; }
.sale-row-source .trail .source-icon, .sale-row-source .trail .brand-icon { width: 14px; height: 14px; flex: 0 0 14px; }
.sale-list .sale-list-state { padding: 14px; font-size: 12px; }
/* Empty: WhatsApp's empty starred list, a centred line and what to do next. */
.sale-list .empty-action { margin: 0; padding: 28px 28px 30px; border: 0; background: none; text-align: center; }
.sale-list .empty-action strong { color: #111b21; font-size: 14px; font-weight: 700; }
.sale-list .empty-action span { margin: 5px 0 0; color: #667781; font-size: 12.5px; line-height: 1.45; }
/* On a phone: the sale form's sheet, its title bar and ✕. */
.sale-list.is-sheet { z-index: 110; inset: auto 0 0 0; width: 100%; max-height: min(82dvh, 650px); padding-bottom: env(safe-area-inset-bottom); border-width: 1px 0 0; border-radius: 18px 18px 0 0; box-shadow: 0 -18px 50px rgba(23, 32, 51, .18); }
.sale-list.is-sheet.entering { transform-origin: bottom center; animation: lacak-sheet-in var(--m-move) var(--m-in); }
.sale-list.is-sheet > header { padding: 15px 18px 13px; }
.sale-list.is-sheet h2 { font-size: 17px; }
.sale-list.is-sheet .sale-list-close { width: 36px; height: 36px; border: 1px solid var(--line); border-radius: 9px; background: #fff; color: var(--ink); }
.sale-list.is-sheet .sale-row { padding: 14px 18px; }

/* The reply line holds the place of the CRM's reply state. */
.g4-reply-state .brand-icon { width: 14px; height: 14px; flex-basis: 14px; }

/* ---------- The message menu ----------
   The CRM's trigger and menu (product-ui.css .message-menu-trigger, .wa-message-menu), in WhatsApp
   Web's shape: the chevron sits inside the bubble's top corner on a wash of the bubble's own colour, so
   the text under it fades rather than being cut; it shows while the pointer is on the bubble, while it
   has keyboard focus, and while its menu or its form is open. After a touch it does not show: a long
   press opens the menu (app.js). The menu stays anchored under the chevron at every width, opening
   upward when the room has no space below (.open-up). */
.message-line .message-menu-trigger { top: .14rem; right: .14rem; opacity: 0; color: #667781; background: radial-gradient(circle at 62% 38%, #fff 48%, rgb(255 255 255 / 0) 74%); transition: opacity var(--m-hover) ease; }
.message-line.outgoing .message-menu-trigger { background: radial-gradient(circle at 62% 38%, #d9fdd3 48%, rgb(217 253 211 / 0) 74%); }
.message-line.marked .message-menu-trigger { background: radial-gradient(circle at 62% 38%, var(--yellow-wash) 48%, rgb(255 245 214 / 0) 74%); }
.message-line .message-bubble:has(.message-sticker) .message-menu-trigger { background: rgb(255 255 255 / .92); box-shadow: 0 1px .5px rgb(11 20 26 / .13); }
.message-menu-trigger .icon { width: 18px; height: 18px; }
.message-line .message-menu-trigger:focus-visible { opacity: 1; outline: 2px solid rgba(47, 98, 164, .55); outline-offset: 1px; }
.message-line.menu-open .message-menu-trigger, .message-line.popover-open .message-menu-trigger { opacity: 1; }
.touch-input .message-line .message-menu-trigger:not(:focus-visible) { opacity: 0; pointer-events: none; }
.message-line .wa-message-menu { position: absolute; top: 1.65rem; bottom: auto; min-width: 14.5rem; max-height: none; overflow: visible; transform-origin: top left; animation: lacak-menu-in var(--m-pop) var(--m-in); }
.message-line.outgoing .wa-message-menu { left: auto; right: .25rem; transform-origin: top right; }
.message-line .wa-message-menu.open-up { top: auto; bottom: calc(100% - .1rem); transform-origin: bottom left; }
.message-line.outgoing .wa-message-menu.open-up { transform-origin: bottom right; }
.wa-message-menu button { min-height: 40px; font-weight: 500; }
.wa-message-menu button .icon { width: 16px; height: 16px; flex: 0 0 16px; color: #54656f; }
.wa-message-menu button:focus-visible { outline: 2px solid rgba(47, 98, 164, .45); outline-offset: -2px; background: #f0f2f5; }
@keyframes lacak-menu-in { from { opacity: 0; transform: translateY(-4px) scale(.985); } }
.message-line .wa-message-menu.open-up { animation-name: lacak-menu-in-up; }
@keyframes lacak-menu-in-up { from { opacity: 0; transform: translateY(4px) scale(.985); } }
/* A long press marks the whole message line, as WhatsApp marks a selected message. */
.message-line.selected { isolation: isolate; }
.message-line.selected::before { content: ""; position: absolute; z-index: -1; inset: -3px -10px; border-radius: 6px; background: rgb(0 168 132 / .14); pointer-events: none; }
/* Bubbles leave vertical panning to the chat. Only the message a finger is resting on, and the one whose
   menu that press opened, hold back text selection; every other message selects as the browser lets it. */
@media (hover: none) { #messages .message-bubble { touch-action: pan-y; } }
.message-line.pressing .message-bubble, .touch-input .message-line.selected .message-bubble { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }

/* Marked messages: Lacak yellow, the one bold thing on the screen. */
.message-line.marked { flex-wrap: wrap; }
.message-line.marked .message-bubble.incoming, .message-line.marked .message-bubble.outgoing { background: var(--yellow-wash); box-shadow: inset 4px 0 0 var(--yellow), 0 1px .5px rgb(11 20 26 / .13); }
.message-line.outgoing.marked .message-bubble.outgoing { box-shadow: inset -4px 0 0 var(--yellow), 0 1px .5px rgb(11 20 26 / .13); }
.message-line.marked .message-bubble.incoming.group-start::before, .message-line.marked .message-bubble.outgoing.group-start::before { background: var(--yellow-wash); }
.sale-marks { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: 4px; margin: 4px 0 6px; }
.message-line.outgoing .sale-marks { justify-content: flex-end; }
/* One mark per message: the amount, or the total and, after a rule, the count. */
.sale-mark { display: inline-flex; align-items: center; gap: 6px; min-height: 24px; padding: 0 10px 0 8px; border-radius: 999px; background: var(--yellow); color: var(--yellow-ink); font-size: 12px; font-variant-numeric: tabular-nums; }
.sale-mark b { font-weight: 800; }
.sale-mark span { padding-left: 7px; border-left: 1px solid rgb(92 63 0 / .28); font-weight: 650; }
.sale-mark .icon { width: 13px; height: 13px; }
.sale-mark.is-new { animation: lacak-mark-in var(--m-pop) var(--m-in); }
@keyframes lacak-mark-in { from { opacity: 0; transform: scale(.94); } }
/* The message a jump lands on, or a sale was just saved on: a yellow band behind its line, the shape of a
   touch selection (.message-line.selected), held a moment and then faded (1200ms). */
.message-line.pulse { isolation: isolate; }
.message-line.pulse::after { content: ""; position: absolute; z-index: -1; inset: -3px -10px; border-radius: 6px; background: rgb(245 195 59 / .2); pointer-events: none; animation: lacak-wash-band 1.2s ease-out forwards; }
@keyframes lacak-wash-band { 0%, 35% { opacity: 1; } 100% { opacity: 0; } }
.message-bubble:focus { outline: none; }
.message-bubble:focus-visible { outline: 3px solid rgba(47, 98, 164, .28); outline-offset: 2px; }

/* ---------- The sale popover ----------
   The CRM's stage picker surface (product-ui.css .stage-picker) with the arrow of its activity menu
   (.cxp-activity-options::after), pointing at the bubble from whichever side it opened on. It holds
   Lite's form at Lite's sizes (below, with the panel's). On a phone it is Lite's bottom sheet
   (lite-merged.html .dashboard-filter-menu at 760px and below). */
/* Inside it, Lite's own tokens (lite-merged.html :root), so the form is Lite's to the colour. */
.sale-popover { --soft: #f7f7f5; --line: #e5e3df; --navy: #18243a; --navy-hover: #23324d; }
.sale-popover { position: fixed; z-index: 110; top: 0; left: 0; width: min(336px, calc(100vw - 16px)); padding: 12px; border: 1px solid #d4deea; border-radius: 14px; background: #fff; box-shadow: 0 18px 46px rgba(23, 32, 51, .19); color: var(--ink); }
.sale-popover.entering { animation: lacak-pop-in var(--m-pop) var(--m-in); }
.sale-popover > header { padding: 2px 2px 10px; }
.sale-popover > header strong { font-size: 12px; font-weight: 820; letter-spacing: -.01em; }
/* In a room narrower than the form, Batal and Simpan penjualan wrap instead of passing its edge. */
.sale-popover .form-actions { flex-wrap: wrap; }
.sale-popover-arrow { position: absolute; width: 11px; height: 11px; border: 1px solid #d4deea; background: #fff; transform: rotate(45deg); }
.sale-popover[data-side="bottom"] .sale-popover-arrow { top: -6px; left: calc(var(--arrow) - 6px); border-right: 0; border-bottom: 0; }
.sale-popover[data-side="top"] .sale-popover-arrow { bottom: -6px; left: calc(var(--arrow) - 6px); border-left: 0; border-top: 0; }
.sale-popover[data-side="right"] .sale-popover-arrow { left: -6px; top: calc(var(--arrow) - 6px); border-top: 0; border-right: 0; }
.sale-popover[data-side="left"] .sale-popover-arrow { right: -6px; top: calc(var(--arrow) - 6px); border-left: 0; border-bottom: 0; }
.sale-popover[data-side="none"] .sale-popover-arrow, .sale-popover:not([data-side]) .sale-popover-arrow { display: none; }
@keyframes lacak-pop-in { from { opacity: 0; transform: translateY(4px) scale(.985); } }
.sale-sheet-backdrop { position: fixed; z-index: 109; inset: 0; background: rgba(23, 32, 51, .38); }
.sale-sheet-backdrop.entering { animation: lacak-fade-in var(--m-move) ease; }
.sale-popover.is-sheet { inset: auto 0 0 0; width: 100%; max-height: min(82dvh, 650px); overflow-y: auto; padding: 0 0 calc(10px + env(safe-area-inset-bottom)); border-width: 1px 0 0; border-radius: 18px 18px 0 0; box-shadow: 0 -18px 50px rgba(23, 32, 51, .18); }
.sale-popover.is-sheet.entering { animation: lacak-sheet-in var(--m-move) var(--m-in); }
.sale-popover.is-sheet > header { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 17px 18px 13px; border-bottom: 1px solid var(--line); }
.sale-popover.is-sheet > header strong { font-size: 17px; font-weight: 700; letter-spacing: 0; }
.sale-sheet-close { display: grid; width: 36px; height: 36px; place-items: center; padding: 0; border: 1px solid var(--line); border-radius: 9px; background: #fff; color: var(--ink); }
.sale-sheet-close .icon { width: 17px; height: 17px; }
.sale-popover.is-sheet .purchase-form { margin: 14px 15px 4px; }
@keyframes lacak-sheet-in { from { transform: translateY(100%); } }
@keyframes lacak-fade-in { from { opacity: 0; } }

/* ---------- Panel: the customer's ledger ---------- */
/* The customer card is not one control here; its name edit and source row are. */
.cxp div.lacak-identity { cursor: default; }
.cxp div.lacak-identity:hover { border-color: var(--line); box-shadow: 0 5px 16px rgba(23, 32, 51, .04); }
.cxp div.lacak-identity:hover .cxp-identity-name { color: inherit; }
.cxp .lacak-name-row { display: flex; align-items: center; gap: 4px; }
/* A long name wraps under itself rather than losing its end; the pencil follows its last word. */
.cxp .lacak-name-row { align-items: flex-start; }
.lacak-name-row strong { min-width: 0; overflow-wrap: break-word; white-space: normal; font: inherit; }
/* In the phone's narrowest panel the pill goes under the name, so the name keeps its words whole. */
@media (max-width: 360px) {
  .cxp .cxp-identity.lacak-identity { grid-template-columns: auto minmax(0, 1fr); grid-template-areas: "avatar name" "avatar pill" "avatar phone" "foot foot"; }
  .cxp .cxp-identity.lacak-identity > .cxp-badge { justify-self: start; margin: 4px 0 2px; }
}
/* The name is the edit's button: the name, then the pencil that says so. A dashed underline and a
   darker pencil under the pointer; the pencil stays shown for touch, which has no hover. */
.lacak-name-button { display: inline-flex; align-items: flex-start; gap: 6px; min-width: 0; max-width: 100%; margin: -2px -4px; padding: 2px 4px; border: 0; border-radius: 6px; background: transparent; color: inherit; font: inherit; text-align: left; cursor: text; }
.lacak-name-button strong { min-width: 0; overflow-wrap: break-word; white-space: normal; font: inherit; text-decoration: underline dashed transparent; text-decoration-thickness: 1px; text-underline-offset: 4px; transition: text-decoration-color var(--m-hover) ease; }
.lacak-name-button .icon { width: 13px; height: 13px; flex: 0 0 13px; margin-top: 2px; color: #9aa5b5; transition: color var(--m-hover) ease; }
.lacak-name-button:hover strong { text-decoration-color: #9aa5b5; }
.lacak-name-button:hover .icon { color: var(--ink); }
.lacak-name-button:focus-visible { outline: 3px solid rgba(47, 98, 164, .24); outline-offset: 1px; }
/* A saved name washes yellow a moment: what changed, where it changed. */
.lacak-name-button strong.is-renamed { border-radius: 3px; animation: lacak-renamed 1.2s ease-out; }
@keyframes lacak-renamed { 0%, 35% { background: var(--yellow-wash); box-shadow: 0 0 0 3px var(--yellow-wash); } 100% { background: transparent; box-shadow: 0 0 0 3px transparent; } }
/* While editing, the input takes the name's place, size and weight; the pill gives it the row. Under the
   number: the refusal, then Batal and Simpan. */
.cxp .cxp-identity.lacak-name-editing { cursor: default; border-color: #c9d6e6; }
.cxp .lacak-name-editing > .name-inline { grid-area: name / name / name / pill; align-self: center; min-width: 0; }
.name-inline input { width: 100%; min-width: 0; height: 32px; margin: -3px 0 -3px -7px; padding: 0 6px; border: 1px solid #b8c7da; border-radius: 7px; background: #fff; color: var(--ink); font: inherit; font-size: 13px; font-weight: 820; letter-spacing: -.01em; box-shadow: 0 0 0 3px rgba(47, 98, 164, .1); outline: none; }
.name-inline input[aria-invalid="true"] { border-color: var(--danger); box-shadow: 0 0 0 3px rgba(165, 61, 61, .12); }
.name-edit-foot { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 6px 10px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
.name-edit-foot .field-error { flex: 1 1 100%; margin: 0; }
.name-edit-foot .field-error:empty { display: none; }
.name-edit-actions { display: flex; gap: 6px; margin-left: auto; }
.name-edit-actions button { min-height: 32px; padding: 0 12px; border-radius: 8px; font-size: 12px; font-weight: 760; }
.field-error { margin: 0 0 10px; color: var(--danger); font-size: 12px; line-height: 1.5; }
.empty-inline { color: var(--muted); font-size: 12px; }
.more-marker { height: 1px; }

/* Penjualan: Lite's summary card (lite-merged.html .customer-overview), the total and the count on
   its navy band, Catat penjualan at its right, Lite's form inside it below the band. */
.cxp .customer-overview { overflow: hidden; border: 1px solid #dfe4eb; border-radius: 14px; background: #fff; box-shadow: 0 8px 24px rgba(23, 32, 51, .06); }
.cxp .overview-main { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 14px; padding: 17px; background: var(--navy); color: #fff; }
.cxp .purchase-state > div { display: grid; gap: 3px; }
.cxp .purchase-state b { font-size: 20px; font-weight: 800; line-height: 1.15; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.cxp .purchase-state b.is-empty { font-size: 14px; letter-spacing: -.01em; }
.cxp .purchase-state small { color: rgb(255 255 255 / .74); font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; }
.cxp .overview-main .btn { min-height: 38px; gap: 6px; padding: 0 12px; border-color: #fff; background: #fff; color: var(--navy); font-size: 12px; font-weight: 780; white-space: nowrap; }
.cxp .overview-main .btn:hover { background: #eef2f8; }
.cxp .overview-main .btn .icon { width: 14px; height: 14px; }
/* Lite's form inside the card, at Lite's own sizes (lite-merged.html .purchase-form and its fields). */
.cxp .customer-overview .purchase-form { margin: 0 14px 14px; padding: 15px; border-radius: 12px; background: var(--soft); }
.sale-popover .purchase-form { padding: 15px; border-radius: 12px; background: var(--soft); }
/* A room too short for the whole form: the form scrolls inside the popover (app.js positionPopover). */
.sale-popover:not(.is-sheet) .purchase-form { overflow-y: auto; overscroll-behavior: contain; }
.sale-popover .purchase-form .money-input, .sale-popover .purchase-form .time-fields input { border-color: var(--line); }
.sale-popover .purchase-form .money-input:focus-within, .sale-popover .purchase-form .time-fields input:focus-visible { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(47, 98, 164, .15); outline: none; }
.sale-popover .purchase-form .purchase-preview > span { margin-bottom: 7px; }
/* Lite's source trail in its preview (.purchase-preview .source-trail): 16px marks, 9px gaps. */
.sale-popover .purchase-preview .trail { gap: 5px 9px; }
.sale-popover .purchase-preview .trail-seg { gap: 7px; }
.sale-popover .purchase-preview .trail .source-icon, .sale-popover .purchase-preview .trail .brand-icon { width: 16px; height: 16px; flex: 0 0 16px; }
@media (max-width: 760px) { .sale-popover .purchase-preview .trail .source-icon, .sale-popover .purchase-preview .trail .brand-icon { width: 14px; height: 14px; flex-basis: 14px; } }
.sale-popover .money-input:has([aria-invalid="true"]), .sale-popover .time-fields input[aria-invalid="true"] { border-color: var(--danger); }
:is(.customer-overview, .sale-popover) .purchase-form .field { gap: 6px; margin-bottom: 12px; }
:is(.customer-overview, .sale-popover) .purchase-form .field > span { font-size: 10px; font-weight: 800; }
:is(.customer-overview, .sale-popover) .purchase-form .money-input span { font-size: 11px; }
:is(.customer-overview, .sale-popover) .purchase-form .time-summary { margin-bottom: 12px; font-size: 11px; }
:is(.customer-overview, .sale-popover) .purchase-form .time-summary button { min-height: 0; padding: 0; font-size: 11px; font-weight: 800; }
:is(.customer-overview, .sale-popover) .purchase-form .time-fields { grid-template-columns: 1fr; gap: 9px; margin-bottom: 12px; }
:is(.customer-overview, .sale-popover) .purchase-form .time-fields input { min-height: 40px; padding: 0 9px; font-size: 11px; }
:is(.customer-overview, .sale-popover) .purchase-form .purchase-preview > span { margin-bottom: 0; font-size: 10px; font-weight: 800; }
:is(.customer-overview, .sale-popover) .purchase-form .purchase-preview .trail { font-size: 9px; font-weight: 400; }
:is(.customer-overview, .sale-popover) .purchase-form .form-error { min-height: 16px; margin: -5px 0 5px; font-size: 10px; }
:is(.customer-overview, .sale-popover) .purchase-form .form-error:empty { display: block; }
:is(.customer-overview, .sale-popover) .purchase-form .btn { min-height: 38px; padding: 0 13px; border-color: var(--line); font-size: 10px; font-weight: 780; }
:is(.customer-overview, .sale-popover) .purchase-form .btn.primary { border-color: var(--navy); }
/* Lite's phone drawer (lite-merged.html, max-width 760px): the total over a full-width action, 44px controls. */
@media (max-width: 760px) {
  .cxp .overview-main { flex-direction: column; flex-wrap: nowrap; align-items: stretch; }
  .cxp .overview-main .btn { width: 100%; min-height: 44px; }
  :is(.customer-overview, .sale-popover) .purchase-form .btn, :is(.customer-overview, .sale-popover) .purchase-form .time-summary button { min-height: 44px; }
  :is(.customer-overview, .sale-popover) .purchase-form .money-input input, :is(.customer-overview, .sale-popover) .purchase-form .time-fields input { min-height: 44px; }
}

/* Lite's sale cards (.purchase-list, .purchase-item): amount and date, a rule, the source path. The
   platform's answer sits at the card's right; a card recorded on a message opens it. */
.cxp .purchase-list { display: grid; gap: 9px; margin-top: 10px; }
.cxp .purchase-item { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: 10px 12px; padding: 13px; border: 1px solid var(--line); border-radius: 11px; background: #fff; }
.cxp .purchase-main { display: grid; gap: 4px; min-width: 0; }
.cxp .purchase-amount { font-size: 14px; font-weight: 820; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
.cxp .purchase-meta { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.cxp .purchase-source { grid-column: 1 / -1; min-width: 0; padding-top: 10px; border-top: 1px solid var(--line); }
.cxp .purchase-source .trail { gap: 3px 6px; font-size: 11.5px; }
.cxp .purchase-source .trail .source-icon, .cxp .purchase-source .trail .brand-icon { width: 14px; height: 14px; flex: 0 0 14px; }
.cxp .purchase-item.has-message:hover { border-color: #c5d3e6; }
.purchase-open { position: absolute; z-index: 1; inset: 0; width: 100%; padding: 0; border: 0; border-radius: inherit; background: transparent; cursor: pointer; }
.purchase-open:focus-visible { outline: 3px solid rgba(47, 98, 164, .28); outline-offset: 1px; }
.cxp .purchase-item.is-new { animation: lacak-card-new 1.2s ease-out; }
@keyframes lacak-card-new { 0%, 40% { border-color: var(--yellow-edge); background: var(--yellow-wash); } 100% { border-color: var(--line); background: #fff; } }

/* A corrected or voided sale. The figure every total reads leads; the first one sits struck after it,
   smaller and grey. A voided card goes quiet: its amount struck, the Dibatalkan pill (the CRM's
   .cxp-badge form, grey), a paler face. Its history is a ladder under the source, the source card's
   left rule, newest first: what happened, when, the change, and the reason in the person's words. */
.sale-figure { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; }
.sale-figure s { text-decoration-thickness: 1.5px; }
.sale-original { color: var(--muted); font-size: 12px; font-weight: 600; }
.sale-figure.is-void { align-items: center; color: var(--muted); }
.void-chip { display: inline-flex; align-items: center; min-height: 20px; padding: 0 8px; border-radius: 999px; background: #eceef2; color: #4a5568; font-size: 10.5px; font-weight: 760; letter-spacing: 0; text-decoration: none; }
.cxp .purchase-item.is-void { background: #fafafa; }
/* Above the card's jump, as the delivery chip is, so the pointer reaches it and it can say what it is. */
.cxp .purchase-item .void-chip { position: relative; z-index: 2; }
.cxp .purchase-item.is-void .purchase-source { opacity: .72; }
.sale-history { grid-column: 1 / -1; display: grid; gap: 9px; margin: 0; padding: 1px 0 1px 13px; border-left: 1.5px solid #dbe3ee; list-style: none; }
.sale-history li { display: grid; gap: 3px; min-width: 0; }
.sale-history-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; }
.sale-history-head b { color: #24334e; font-size: 11.5px; font-weight: 780; }
.sale-history-head time { color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; }
.sale-history-change { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px; font-size: 12px; font-variant-numeric: tabular-nums; }
.sale-history-change s { color: var(--muted); }
.sale-history-change > span { color: #9aa5b5; }
.sale-history-change b { color: var(--ink); font-weight: 760; }
.sale-history p { margin: 0; color: #46536a; font-size: 12px; line-height: 1.45; overflow-wrap: anywhere; }
/* Two quiet actions at the card's foot, above the card's own jump to its message. */
/* The history's next page: the panel's loading row, inset to the ladder. */
.sale-history .more-marker { height: 0; margin-top: -9px; }
.sale-history-state { min-height: 0; padding: 2px 0; font-size: 11px; }
.sale-actions { position: relative; z-index: 2; grid-column: 1 / -1; display: flex; align-items: center; justify-content: flex-end; gap: 2px; margin: -4px -6px -6px 0; pointer-events: none; }
.sale-actions > * { pointer-events: auto; }
.sale-actions .quiet-button { min-height: 32px; padding: 0 8px; border-radius: 7px; color: #4a5872; font-size: 12px; font-weight: 680; }
.sale-actions .quiet-button:hover { background: #eef2f8; color: var(--blue); }
.sale-actions .quiet-button:focus-visible { outline: 2px solid rgba(47, 98, 164, .55); outline-offset: 0; }
@media (max-width: 760px) { .sale-actions .quiet-button { min-height: 40px; } }
/* The platform keeps what it received: the chip names it and the figure, on its own line of the card. */
.cxp .purchase-item.has-kept > .delivery-chip { grid-column: 1 / -1; justify-self: start; max-width: 100%; min-height: 0; padding: 5px 10px 5px 8px; border-radius: 8px; line-height: 1.35; white-space: normal; text-align: left; }
.delivery-chip.tone-kept { background: #eef1f6; color: #34435c; font-variant-numeric: tabular-nums; }
/* The header list: a voided row reads struck and quiet; a corrected one keeps its first figure beside it. */
.sale-row-head .sale-original { font-size: 12px; }
.sale-row.is-void .sale-row-quote { background: #f4f5f7; box-shadow: inset 3px 0 0 #c7ced9, 0 1px .5px rgb(11 20 26 / .13); }
.sale-row.is-void .sale-row-quote.outgoing { box-shadow: inset -3px 0 0 #c7ced9, 0 1px .5px rgb(11 20 26 / .13); }
.sale-row.is-void .sale-row-head b { font-weight: 700; }
/* The bubble of a voided sale loses Lacak yellow; its mark stays, grey and struck. */
.message-line.marked.void-only .message-bubble.incoming, .message-line.marked.void-only .message-bubble.outgoing { background: #fff; box-shadow: 0 1px .5px rgb(11 20 26 / .13); }
.message-line.marked.void-only .message-bubble.outgoing { background: #d9fdd3; }
.message-line.marked.void-only .message-bubble.incoming.group-start::before { background: #fff; }
.message-line.marked.void-only .message-bubble.outgoing.group-start::before { background: #d9fdd3; }
.message-line.void-only .message-menu-trigger { background: radial-gradient(circle at 62% 38%, #fff 48%, rgb(255 255 255 / 0) 74%); }
.message-line.outgoing.void-only .message-menu-trigger { background: radial-gradient(circle at 62% 38%, #d9fdd3 48%, rgb(217 253 211 / 0) 74%); }
.sale-mark.is-void { background: #eceef2; color: #5b6578; }
.sale-mark.is-void s { font-weight: 700; text-decoration-thickness: 1.5px; }

/* The sales CSV: the CRM's quiet button (base.css .quiet-button: no border, no ground, blue; its soft blue
   ground on hover) holding only its icon, beside the list's search, square and as tall as a touch needs;
   its name is its tooltip. It opens Lacak's dialog (dialogs.css). */
.conversation-list-controls:has(.lacak-csv-button) { display: flex; align-items: center; gap: 4px; }
.conversation-list-controls:has(.lacak-csv-button) .search-field { flex: 1 1 auto; min-width: 0; margin-bottom: 0; }
.lacak-csv-button { flex: 0 0 40px; display: grid; place-items: center; width: 40px; height: 40px; padding: 0; border-radius: 9px; }
.lacak-csv-button .icon { width: 17px; height: 17px; }
.lacak-csv-button:focus-visible { outline: 2px solid rgba(47, 98, 164, .55); outline-offset: 0; }

/* The delivery chip: a state pill in the CRM's .cxp-badge form. Menunggu is grey, Terkirim green with
   the platform's mark, Tidak diterima red; that one is a control and shows its reason while hovered
   or focused, in the hover card (:root --hover-card-*), below the chip and aligned to its right edge. */
.delivery-wrap, .delivery-chip { position: relative; z-index: 2; }
.delivery-chip { display: inline-flex; align-items: center; gap: 5px; min-height: 24px; padding: 0 9px 0 7px; border: 0; border-radius: 999px; font-size: 11px; font-weight: 760; line-height: 1; white-space: nowrap; }
.delivery-chip .icon, .delivery-chip .brand-icon { width: 13px; height: 13px; flex: 0 0 13px; }
.delivery-chip.tone-sent { background: var(--green-soft); color: var(--green); }
.delivery-chip.tone-pending { background: #f1f2f4; color: var(--muted); }
.delivery-chip.tone-rejected { background: #fbeded; color: var(--danger); cursor: help; }
.delivery-chip.tone-rejected:hover { background: #f7e1e1; }
.delivery-chip.tone-rejected:focus-visible { outline: 3px solid rgba(165, 61, 61, .25); outline-offset: 2px; }
.delivery-reason { position: absolute; z-index: 6; top: calc(100% + 6px); right: 0; width: max-content; max-width: min(232px, 70vw); padding: 9px 11px; border: var(--hover-card-edge); border-radius: var(--hover-card-radius); background: var(--hover-card-bg); box-shadow: var(--hover-card-shadow); color: var(--hover-card-ink); font-size: var(--hover-card-size); font-weight: 400; line-height: var(--hover-card-leading); white-space: normal; opacity: 0; visibility: hidden; pointer-events: none; transform: translateY(var(--hover-card-rise)); transition: opacity var(--m-hover) ease, transform var(--m-hover) ease, visibility 0s linear var(--m-hover); }
/* Its reason shows under a mouse or the keyboard's focus with no wait, as the tooltips do, and never from a
   touch's hover or focus. A press opens it (.is-open) and a second press, Esc or a press elsewhere closes it:
   on a phone that is the only way to it. */
:root:not(.touch-input) .delivery-chip:hover + .delivery-reason, .delivery-chip:focus-visible + .delivery-reason, .delivery-wrap.is-open > .delivery-reason { opacity: 1; visibility: visible; transform: none; transition: opacity var(--m-hover) ease, transform var(--m-hover) var(--m-in), visibility 0s linear; }
@media (hover: none) { .delivery-wrap:not(.is-open) > .delivery-reason { opacity: 0; visibility: hidden; } }

/* Riwayat: the CRM's journey (pages-customers.css .contact-detail-comp .contact-lifeline, loaded as it is)
   in the panel's card. Sales take Lacak yellow. The tooltip also opens on a tap's focus, and is no wider
   than the panel's plot. */
.cxp .lacak-journey { position: relative; z-index: 3; padding: 14px 12px 12px; border: 1px solid var(--line); border-radius: 14px; background: #fff; box-shadow: 0 5px 16px rgba(23, 32, 51, .04); }
.lacak-journey .tone-sale { --lifeline-tone: var(--yellow); }
/* Its tooltip in the hover card (:root --hover-card-*): the CRM's 12px corners, deeper shadow, tinted head and
   98% scale give way to the card's; a name takes the card's name type, the rest its body type. It keeps the
   CRM's timing (150ms fade, 160ms rise, gone at once on leave). */
.lacak-journey .lifeline-event-menu { min-width: 216px; max-width: 262px; border: var(--hover-card-edge); border-radius: var(--hover-card-radius); background: var(--hover-card-bg); box-shadow: var(--hover-card-shadow); color: var(--hover-card-title); line-height: var(--hover-card-leading); transform: translate(-50%, var(--hover-card-rise)); }
.lacak-journey .lifeline-event.align-start .lifeline-event-menu, .lacak-journey .lifeline-event.align-end .lifeline-event-menu { transform: translate(0, var(--hover-card-rise)); }
.lacak-journey .lifeline-menu-head { background: var(--hover-card-bg); }
.lacak-journey .lifeline-menu-head strong, .lacak-journey .lifeline-menu-row strong { color: var(--hover-card-title); font-size: var(--hover-card-title-size); font-weight: 650; line-height: var(--hover-card-leading); }
.lacak-journey .lifeline-menu-head small, .lacak-journey .lifeline-menu-row small, .lacak-journey .lifeline-menu-row b { color: var(--hover-card-ink); font-size: var(--hover-card-size); font-weight: 400; letter-spacing: 0; line-height: var(--hover-card-leading); text-transform: none; }
.lacak-journey .lifeline-menu-row > i { margin-top: 6px; }
.lacak-journey .lifeline-event:focus { z-index: 12; }
.lacak-journey .lifeline-event:focus .lifeline-event-marker { transform: translate(-50%, -50%) scale(1.48); }
.lacak-journey .lifeline-event:focus .lifeline-event-menu { opacity: 1; pointer-events: auto; transform: translate(-50%, 0) scale(1); visibility: visible; }
.lacak-journey .lifeline-event.align-start:focus .lifeline-event-menu, .lacak-journey .lifeline-event.align-end:focus .lifeline-event-menu { transform: translate(0, 0) scale(1); }
.lacak-journey .lifeline-menu-row small { font-variant-numeric: tabular-nums; }
.lacak-journey .lifeline-legend { gap: 6px 14px; }
.lacak-journey .lifeline-hint { flex-basis: 100%; margin-left: 0; }
/* A tooltip's next page: the marker it loads at, then its loading row. */
.lacak-journey .lifeline-more { display: block; height: 1px; }
.lacak-journey .lifeline-more.is-loading { display: flex; height: auto; align-items: center; gap: 8px; padding: 9px 12px 11px; color: var(--muted); font-size: 11px; }
.lacak-journey .lifeline-more .spinner { width: 14px; height: 14px; }

/* ---------- The panel's Sumber card ----------
   The identity card's surface (white, the panel's hairline and corner), under it in the customer section.
   The latest arrival leads: its mark and kind, its time at the right, then its path as a ladder of
   Detail sumber's labels and values. Earlier arrivals follow in the same form, a step quieter. */
.cxp .lacak-attribution { margin-top: 10px; padding: 13px 14px 12px; border: 1px solid var(--line); border-radius: 14px; background: #fff; box-shadow: 0 5px 16px rgba(23, 32, 51, .04); }
.attr-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.attr-head h3 { margin: 0; color: var(--muted); font-size: 10px; font-weight: 800; letter-spacing: .01em; }
.attr-head small { color: var(--muted); font-size: 10.5px; font-variant-numeric: tabular-nums; }
.attr-line { display: grid; grid-template-columns: 16px minmax(0, 1fr) auto; align-items: center; gap: 8px; }
.attr-line > strong { min-width: 0; color: var(--ink); font-size: 13px; font-weight: 780; letter-spacing: -.01em; }
.attr-line > time { color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.lacak-attribution .brand-icon, .lacak-attribution .source-icon { width: 16px; height: 16px; flex: 0 0 16px; }
.lacak-attribution .source-icon { color: #2d68b2; }
.lacak-attribution .source-icon.organic { color: #219065; }
/* The ladder: a thin rule down the left from the mark, labels in a fixed column, values wrapping. */
.attr-path { display: grid; gap: 5px; margin: 9px 0 0 7px; padding: 1px 0 1px 15px; border-left: 1.5px solid #dbe3ee; }
.attr-path > div { display: grid; grid-template-columns: 62px minmax(0, 1fr); gap: 10px; align-items: baseline; }
.attr-path dt { color: var(--muted); font-size: 10.5px; font-weight: 650; white-space: nowrap; }
.attr-path dd { min-width: 0; margin: 0; color: #24334e; font-size: 12px; font-weight: 650; line-height: 1.4; overflow-wrap: anywhere; }
.attr-earlier { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line); }
.attr-earlier h4 { margin: 0 0 4px; color: var(--muted); font-size: 10px; font-weight: 800; }
.attr-row { padding: 8px 0 9px; }
.attr-row + .attr-row { border-top: 1px solid #eef1f5; }
.attr-row .attr-line > strong { color: #24334e; font-size: 12px; font-weight: 700; }
.attr-row .attr-path { margin-top: 7px; }
.attr-all { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: calc(100% + 12px); min-height: 36px; margin: 4px -6px 0; padding: 6px; border: 0; border-top: 1px solid #eef1f5; border-radius: 0 0 8px 8px; background: transparent; color: var(--blue); font: inherit; font-size: 12px; font-weight: 760; text-align: left; cursor: pointer; }
.attr-all:hover { background: var(--blue-soft); }
.attr-all .icon { width: 13px; height: 13px; }
.attr-all:focus-visible { outline: 2px solid #82aef1; outline-offset: -2px; }
.lacak-attribution > .attr-all { margin-top: 10px; }
/* Each arrival opens its Detail sumber: a button laid over it, as the sale cards' .purchase-open; the
   arrival tints on hover and the chevron after its time says it opens. */
.attr-arrival { position: relative; margin: 0 -6px; padding-left: 6px; padding-right: 6px; border-radius: 8px; }
.attr-latest.attr-arrival { padding-top: 4px; padding-bottom: 6px; margin-top: -4px; }
.attr-arrival .attr-line { grid-template-columns: 16px minmax(0, 1fr) auto 12px; }
.attr-arrival .attr-line > .icon { width: 12px; height: 12px; color: #9aa5b5; }
.attr-open { position: absolute; inset: 0; z-index: 1; width: 100%; padding: 0; border: 0; border-radius: inherit; background: transparent; cursor: pointer; }
.attr-arrival:hover { background: #f5f8fc; }
.attr-arrival:hover .attr-line > .icon { color: var(--blue); }
.attr-open:focus-visible { outline: 2px solid #82aef1; outline-offset: -2px; }
.attr-empty { display: grid; grid-template-columns: 16px minmax(0, 1fr); gap: 8px; color: var(--muted); }
.attr-empty .source-icon { color: #8a95a6; }
.attr-empty span { display: grid; gap: 3px; }
.attr-empty strong { color: var(--ink); font-size: 12.5px; font-weight: 760; }
.attr-empty small { font-size: 11.5px; line-height: 1.45; }

/* ---------- The collapsed rail and its popovers (app.js railHelpersHtml) ----------
   The rail is the CRM's (product-ui.css .context-rail-helper, .context-rail-trigger, .context-rail-count) as
   loaded: 36px round-cornered buttons in the panel's order, Penjualan's carrying its count. Each opens its
   popover where the CRM opens its preview: 10px to the rail's left, its top 4px above the button's, moving
   in 7px from the rail as it fades over 120ms and going the same way in 140ms. Its surface is the
   hover card (:root --hover-card-*): white, its hairline, 10px corners, its soft drop. It holds the section's
   preview at the panel's own card width, 304px (the customer's as wide as its card needs, up to that), as
   tall as its contents, lifted (app.js placeRailPop) so it never passes the composer; taller than the
   messages' view, it scrolls within itself, its scroll kept from the chat behind it.
   It opens on .is-open (app.js), not on :hover, so Esc can close it under a resting pointer; the button
   keeps its CRM hover face while its popover is open. A strip over the gap, the popover's height, keeps the
   pointer inside while it crosses. */
.cxp .context-rail-helper > .lacak-rail-pop { top: calc(-4px - var(--rail-pop-lift, 0px)); display: grid; align-content: start; gap: 10px; width: 304px; padding: 12px; overflow: hidden; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: #cbd2dc transparent; border: var(--hover-card-edge); border-radius: var(--hover-card-radius); background: var(--hover-card-bg); box-shadow: var(--hover-card-shadow); color: var(--hover-card-ink); cursor: pointer; transition: opacity var(--m-exit) var(--m-out), transform var(--m-exit) var(--m-out), visibility 0s linear var(--m-exit); }
.cxp .context-rail-helper:not(.is-open) > .lacak-rail-pop { opacity: 0; visibility: hidden; pointer-events: none; transform: translateX(7px); }
.cxp .context-rail-helper.is-open > .lacak-rail-pop { opacity: 1; visibility: visible; pointer-events: auto; transform: none; transition: opacity var(--m-hover) ease, transform var(--m-hover) var(--m-in), visibility 0s; }
.cxp .context-rail-helper.is-swapping > .lacak-rail-pop { transition: none; }
.cxp .context-rail-helper > .lacak-rail-pop.is-scrolling { overflow-y: auto; }
.cxp .context-rail-helper.is-open > .context-rail-trigger { border-color: #d8e0ea; background: #fff; color: var(--navy); box-shadow: 0 4px 12px rgba(23, 32, 51, .08); }
.cxp .context-rail-helper:not(.is-open)::before { pointer-events: none; }
.lacak-rail-pop::after { content: ""; position: absolute; top: -1px; bottom: -1px; left: 100%; width: 12px; }
.context-rail-count { font-variant-numeric: tabular-nums; }
/* The previews (app.js railPreviewHtml): the panel's own cards with their frames given to the hover card, so
   one white surface holds them; nothing in them reacts to the pointer but the card as a whole. */
.lacak-rail-pop :is(.cxp-identity, .lacak-journey, .lacak-attribution) { margin: 0; padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none; }
.cxp .lacak-rail-pop .cxp-identity:hover { border: 0; box-shadow: none; }
.lacak-rail-pop :is(.lifeline-event, .delivery-chip, .void-chip) { cursor: inherit; }
/* Pelanggan: the identity card as the panel has it, as wide as it needs. */
.cxp .context-rail-helper > .lacak-rail-pop.rail-preview-customer { width: max-content; min-width: 240px; max-width: 304px; }
.lacak-rail-pop .cxp-identity { gap: 2px 12px; color: var(--ink); }
/* Penjualan: the navy card a step tighter, its corners inside the card's; then the sales' heads, hairline apart. */
.cxp .lacak-rail-pop .customer-overview { border: 0; border-radius: 8px; box-shadow: none; }
.cxp .lacak-rail-pop .overview-main { padding: 12px 14px; }
.cxp .lacak-rail-pop .purchase-state b:not(.is-empty) { font-size: 18px; }
.rail-sales { display: grid; margin-bottom: -4px; }
.rail-sale { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: 4px 12px; padding: 9px 2px; }
.rail-sale + .rail-sale { border-top: 1px solid #eef1f5; }
.cxp .rail-sale .purchase-amount { color: var(--ink); font-size: 13.5px; }
.cxp .rail-sale .purchase-meta { font-size: 11.5px; }
/* A kept figure's long chip takes its own line, as on the card. */
.rail-sale > .delivery-chip.tone-kept { grid-column: 1 / -1; justify-self: start; max-width: 100%; min-height: 0; padding: 5px 10px 5px 8px; border-radius: 8px; line-height: 1.35; white-space: normal; }
/* Riwayat: the journey at the panel's size, its tooltips' room not needed. */
.cxp .lacak-rail-pop .lacak-journey { z-index: auto; }
.lacak-rail-pop .lifeline-legend { margin-top: 6px; }
/* Sumber: the card's ladder as it is. */
.lacak-rail-pop .attr-earlier { margin-top: 10px; }
.lacak-rail-pop .attr-row:last-of-type { padding-bottom: 2px; }
/* The next page loading at a list's foot: the panel's loading row, a hairline above it. */
.lacak-rail-pop .rail-state { padding: 12px 0 6px; border-top: 1px solid #eef1f5; }
.lacak-rail-pop .lacak-empty.compact { padding: 6px 4px 4px; }
/* A section's heading takes focus when the rail opens the panel at it; it shows only for the keyboard. */
.cxp .section-heading h2:focus, .cxp .attr-head h3:focus { outline: none; }
.cxp .section-heading h2:focus-visible, .cxp .attr-head h3:focus-visible { outline: 3px solid rgba(47, 98, 164, .24); outline-offset: 3px; border-radius: 4px; }

/* ---------- The list's purchase pill ----------
   The panel's .cxp-badge.buyer in the row's status column, under the time, where the CRM's row keeps its
   unread count: green, at the badge's 9.5px weight 800, short enough that the row keeps its height. */
.conversation-list .conversation-status { gap: 3px; }
.lacak-row-bought { display: inline-flex; align-items: center; height: 16px; margin-top: auto; padding: 0 6px; border-radius: 999px; background: var(--green-soft); color: var(--green); font-size: 9.5px; font-weight: 800; line-height: 1; white-space: nowrap; font-variant-numeric: tabular-nums; }

/* Riwayat sumber: Lacak's dialog (dialogs.css), its arrivals in Lite's touch rows (.touch-list,
   .touch-row), each a row that opens Detail sumber. */
.lacak-touch-list { display: grid; overflow: hidden; border: 1px solid var(--line); border-radius: 10px; }
.lacak-touch-list .touch-row { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 52px; padding: 11px 12px; border: 0; border-top: 1px solid var(--line); background: #fff; color: var(--muted); font-size: 12px; text-align: left; cursor: pointer; }
.lacak-touch-list .touch-row:first-child { border-top: 0; }
.lacak-touch-list .touch-row .trail { flex: 1; font-size: 12px; }
.lacak-touch-list .touch-row > time { flex: 0 0 auto; font-variant-numeric: tabular-nums; white-space: nowrap; }
.lacak-touch-list .touch-row > .icon { color: #8a95a6; }
.lacak-touch-list .touch-row:hover { background: var(--soft); }
.lacak-touch-list .touch-row:hover > .icon { color: var(--blue); }
.lacak-touch-list .touch-row:focus-visible { outline: 2px solid #82aef1; outline-offset: -2px; }
/* On a phone the path takes the row's width and its time sits under it, as the CRM's rows do. */
@media (max-width: 640px) {
  .lacak-touch-list .touch-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px 10px; }
  .lacak-touch-list .touch-row .trail { grid-column: 1; grid-row: 1; }
  .lacak-touch-list .touch-row > time { grid-column: 1; grid-row: 2; }
  .lacak-touch-list .touch-row > .icon { grid-column: 2; grid-row: 1 / 3; }
}

/* Lite sale form */
.purchase-form { padding: 15px; border-radius: 12px; background: var(--soft); color: var(--ink); }
.field { display: grid; gap: 7px; margin-bottom: 12px; font-size: 12px; font-weight: 650; }
.money-input { display: flex; align-items: center; border: 1px solid var(--line-strong); border-radius: 9px; background: #fff; }
.money-input:focus-within { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(47, 98, 164, .15); }
.money-input span { padding-left: 11px; color: var(--muted); font-size: 13px; }
/* Lite's amount input (lite-merged.html .money-input input): 43px tall, 15px figures. */
.money-input input { width: 100%; min-width: 0; min-height: 43px; border: 0; background: transparent; padding: 0 11px 0 7px; font-size: 15px; font-weight: 760; font-variant-numeric: tabular-nums; }
.money-input input:focus-visible { box-shadow: none; outline: none; }
.time-summary { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; font-size: 13px; }
.time-summary b { font-variant-numeric: tabular-nums; }
.time-summary button { min-height: 36px; padding: 0 6px; border: 0; background: transparent; color: var(--blue); font-size: 13px; font-weight: 700; white-space: nowrap; }
.time-fields { display: grid; grid-template-columns: 1.4fr 1fr; gap: 8px; margin-bottom: 12px; }
.time-fields input { width: 100%; min-width: 0; min-height: 44px; padding: 0 10px; border: 1px solid #d6dce5; border-radius: 9px; background: #fff; font-size: 14px; }
.purchase-preview { display: grid; gap: 7px; margin-bottom: 12px; padding: 11px; border: 1px solid var(--line); border-radius: 10px; background: #fff; }
.purchase-preview > span { color: var(--muted); font-size: 11px; font-weight: 700; }
.form-error { margin: 0 0 10px; color: var(--danger); font-size: 12px; line-height: 1.5; }
.form-error:empty { display: none; }
.form-actions { display: flex; justify-content: flex-end; gap: 8px; }
.btn { min-height: 40px; display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 0 14px; border: 1px solid var(--line-strong); border-radius: 9px; background: #fff; color: var(--ink); font-size: 13px; font-weight: 650; cursor: pointer; }
.btn:hover { background: var(--soft); }
.btn.primary { border-color: var(--navy); background: var(--navy); color: #fff; }
.btn.primary:hover { background: var(--navy-hover); }
.btn.danger { border-color: #efd5d5; color: var(--danger); }

/* Lite source trail */
.trail { min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 7px; color: #46536a; font-size: 12px; }
.trail-seg { min-width: 0; display: inline-flex; align-items: center; gap: 6px; }
.trail .source-icon { width: 15px; height: 15px; color: #2d68b2; }
.trail .source-icon.organic { color: #219065; }
.trail-chevron { width: 11px; height: 11px; flex: 0 0 11px; fill: none; stroke: #7b8798; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.trail-organic { color: #22754f; font-weight: 650; }

/* The CRM's toast as product-ui.css's final layer draws it, on every page: centred 84px above the bottom
   (74px and the safe area on a phone), #202c33, 8px corners, 12px white at 500, rising 5px over 160ms. */
#toast.crm-toast .toast { position: fixed !important; z-index: 230 !important; top: auto !important; right: 0 !important; bottom: 84px !important; left: 0 !important; width: max-content !important; margin-inline: auto !important; max-width: min(360px, calc(100vw - 32px)) !important; padding: 9px 14px !important; border: 0 !important; border-radius: 8px !important; background: #202c33 !important; color: #fff !important; box-shadow: 0 2px 8px rgb(11 20 26 / .28) !important; font-size: 12px !important; font-weight: 500 !important; line-height: 1.35 !important; text-align: center !important; animation: lacak-toast-in .16s ease-out !important; }
@keyframes lacak-toast-in { from { opacity: 0; translate: 0 5px; } }
/* It leaves the way it came: sinking the same 5px as it fades. */
#toast.crm-toast .toast.is-leaving { animation: lacak-toast-out var(--m-exit) var(--m-out) forwards !important; }
@keyframes lacak-toast-out { to { opacity: 0; translate: 0 5px; } }

/* ---------- Phone: the CRM's 640px layout under Lite's top bar (shell.css) ---------- */
@media (max-width: 640px) {
  /* The CRM's phone page and room fill the screen below the top; Lite's top bar takes 64px of it, and
     with no bottom bar nothing is kept below. */
  .tenant-shell .conversation-page { height: calc(100dvh - 64px); }
  .tenant-shell .conversation-workspace.mobile-room-open .conversation-room-pane { top: 64px; height: calc(100dvh - 64px); }
  /* The panel lies over the chat's right side and always leaves a strip of the chat in view: the CRM's
     350px, but never closer than 40px to the left edge (at 320 the CRM's panel covers the whole chat). */
  /* Closed, it slides off the screen as the CRM's does: a phone has no rail; the header's Detail Pelanggan opens it. */
  .conversation-context-panel.collapsed, .conversation-context-panel:not(.collapsed) { width: min(calc(100% - 40px), 350px); }
  .page:not(.full-bleed) { padding: 22px 16px; }
  #toast.crm-toast .toast { right: 0 !important; bottom: calc(env(safe-area-inset-bottom) + 74px) !important; left: 0 !important; max-width: calc(100vw - 24px) !important; }
}

/* ---------- Pelanggan: motion, hover, decoration (one family, lacak.css :root --m-*) ---------- */
/* Every number on the page is set in tabular figures, so times, amounts and counts line up in columns. */
.conversation-page, #popover, #sale-list-root, #layer .media-viewer, .lacak-tip { font-variant-numeric: tabular-nums; }

/* One icon weight: every line icon on the page draws its stroke at the same width on screen, whatever its
   size (they ranged from 0.75px at 10px to 1.2px at 16px), matching the rail's navigation icons. */
:is(.conversation-page, #popover, #sale-list-root, #layer) :is(svg.icon, svg.trail-chevron) :is(path, circle, rect, line, polyline, ellipse) { vector-effect: non-scaling-stroke; }
:is(.conversation-page, #popover, #sale-list-root, #layer) :is(svg.icon, svg.trail-chevron) { stroke-width: var(--icon-weight, 1.35px); }

/* Hover and focus: rows, cards, chips and controls change colour over 120ms; nothing lifts or slides.
   Zero specificity, so any transition the CRM's own rules give a control still wins. Focus rings appear at once. */
:where(.conversation-page, #popover, #sale-list-root, #layer) :where(button, a, .purchase-item, .attr-arrival, .delivery-chip, .sale-row) { transition: background-color var(--m-hover) ease, border-color var(--m-hover) ease, color var(--m-hover) ease, box-shadow var(--m-hover) ease; }
:where(.conversation-page, #popover, #sale-list-root, #layer) :where(svg.icon) { transition: color var(--m-hover) ease; }

/* Loading rows and pills fade in where the page will arrive; what arrives fades in in their place. Rows
   already on screen do not move. */
:is(.conversation-list-state, .messages-scroll .chat-state, .list-state, .lacak-journey .lifeline-more.is-loading) { animation: lacak-fade-in var(--m-pop) ease both; }
.conversation-row.is-arrived, .message-line.is-arrived { animation: lacak-fade-in var(--m-pop) ease both; }
.messages-scroll > .empty-action.chat-failed { animation: lacak-fade-in var(--m-pop) ease both; }

/* Exits: every temporary surface leaves the way it came, in 140ms on the accelerating curve. */
@keyframes lacak-fade-out { to { opacity: 0; } }
.sale-list.is-leaving { transform-origin: top right; animation: lacak-list-out var(--m-exit) var(--m-out) forwards; }
@keyframes lacak-list-out { to { opacity: 0; transform: translateY(-4px) scale(.985); } }
.sale-popover.is-leaving { animation: lacak-pop-out var(--m-exit) var(--m-out) forwards; }
@keyframes lacak-pop-out { to { opacity: 0; transform: translateY(4px) scale(.985); } }
.message-line .wa-message-menu.is-leaving { animation: lacak-menu-out var(--m-exit) var(--m-out) forwards; pointer-events: none; }
@keyframes lacak-menu-out { to { opacity: 0; transform: translateY(-4px) scale(.985); } }
.sale-list.is-sheet.is-leaving, .sale-popover.is-sheet.is-leaving { animation: lacak-sheet-out var(--m-exit) var(--m-out) forwards; }
@keyframes lacak-sheet-out { to { transform: translateY(100%); } }
.sale-sheet-backdrop.is-leaving { animation: lacak-fade-out var(--m-exit) ease forwards; }

/* The dialogs open and close as dialogs.css sets out. The media viewer: its dark ground and bar fade (160ms in, 140ms out); a photo flies to and from its
   thumbnail (app.js viewerFlight); a video, file or sticker rises 8px as it fades in. */
#layer > .media-viewer.entering { animation: lacak-fade-in var(--m-pop) ease both; }
#layer > .media-viewer.rise .media-viewer-stage > :first-child { animation: lacak-rise-in var(--m-move) var(--m-in) both; }
@keyframes lacak-rise-in { from { opacity: 0; transform: translateY(8px) scale(.98); } }
#layer > .media-viewer.is-leaving { animation: lacak-fade-out var(--m-exit) var(--m-out) forwards; }

/* ---------- The label tooltip ----------
   The hover card (:root --hover-card-*) holding one name, set as the card's name: 7px from its control, at
   most 220px. It fades in and rises 7px with no wait, and glides from one control to the next. */
.lacak-tip { position: fixed; z-index: 260; top: 0; left: 0; width: max-content; max-width: 220px; padding: 6px 9px; border: var(--hover-card-edge); border-radius: var(--hover-card-radius); background: var(--hover-card-bg); color: var(--hover-card-title); box-shadow: var(--hover-card-shadow); font-size: var(--hover-card-title-size); font-weight: 650; line-height: var(--hover-card-leading); overflow-wrap: anywhere; pointer-events: none; opacity: 0; visibility: hidden; transform: translate(var(--x, 0), calc(var(--y, 0) + var(--hover-card-rise))); transition: opacity var(--m-hover) ease, transform var(--m-hover) ease, visibility 0s linear var(--m-hover); }
.lacak-tip.shown { opacity: 1; visibility: visible; transform: translate(var(--x, 0), var(--y, 0)); transition: opacity var(--m-hover) ease, transform var(--m-hover) var(--m-in), visibility 0s; }
@media (hover: none) { .lacak-tip { display: none; } }


/* ---------- Empty states: the CRM's form with its mark ----------
   pages-conversations.css .conversation-empty and .conversation-empty-mark (the soft square, navy icon) as
   loaded; in the list it sits at the top, where the rows would start; compact inside the panel and the sales list. */
.conversation-list > .lacak-empty { min-height: 0; padding: 40px 24px 28px; }
.conversation-room-pane > .lacak-empty, .messages-scroll > .lacak-empty { flex: 1; margin: auto; }
.lacak-empty .conversation-empty-mark .icon { width: 20px; height: 20px; }
.lacak-empty > span:last-child { color: var(--muted); }
.lacak-empty.compact { min-height: 0; padding: 16px 12px 12px; }
.lacak-empty.compact .conversation-empty-mark { width: 34px; height: 34px; margin-bottom: 8px; border-radius: 9px; }
.lacak-empty.compact .conversation-empty-mark .icon { width: 16px; height: 16px; }
.lacak-empty.compact strong { font-size: 12.5px; }
.lacak-attribution .lacak-empty.compact { padding: 6px 8px 4px; }
.cxp .lacak-empty.compact:not(.lacak-attribution *) { border: 1px solid var(--line); border-radius: 14px; background: #fff; box-shadow: 0 5px 16px rgba(23, 32, 51, .04); }
.sale-list .lacak-empty.compact { padding: 28px 28px 30px; }
.sale-list .lacak-empty.compact strong { color: #111b21; font-size: 14px; }
.sale-list .lacak-empty.compact > span:last-child { font-size: 12.5px; }

/* ---------- One baseline across the top ----------
   The list's title and the room's name share a baseline, and both bands are 66px. Above the phone layout the
   room's channel sits on the name's line, after it, so the name keeps one line. */
@media (min-width: 641px) {
  .conversation-list-head { box-sizing: border-box; height: 66px; padding-top: 0; padding-bottom: 0; }
  .conversation-list-head .conversation-list-title, .conversation-list-head .conversation-list-title > div { height: 100%; }
  .conversation-list-head h1 { margin: 0; padding-top: 15.1px; line-height: 27.6px; }
  .room-header { box-sizing: border-box; height: 66px; min-height: 66px; }
  .room-identity-copy { display: flex; flex: 1 1 auto; align-items: baseline; gap: 8px; min-width: 0; overflow: hidden; }
  .room-identity-copy strong { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .room-identity-copy small { flex: 0 0 auto; }
}

@media (prefers-reduced-motion: reduce) {
  /* Every transition and animation on Pelanggan is off; a wash shows still for its 1200ms instead. */
  :is(.conversation-page, #popover, #sale-list-root, #layer, #toast) *, :is(.conversation-page, #popover, #sale-list-root, #layer, #toast) *::before, :is(.conversation-page, #popover, #sale-list-root, #layer, #toast) *::after, .lacak-tip { animation: none !important; transition: none !important; }
  .message-line.pulse::after { opacity: 1; }
  .sale-popover.entering, .sale-popover.is-sheet.entering, .sale-sheet-backdrop.entering, .wa-message-menu, .sale-mark.is-new, .sale-list.entering, .sale-list.is-sheet.entering { animation: none; }
  .message-line .message-menu-trigger { transition: none; }
  .cxp .purchase-item.is-new { animation: none; border-color: var(--yellow-edge); }
  .delivery-reason { transition: none; }
  .spinner { animation: none; border-top-color: var(--line-strong); }
  #toast.crm-toast .toast, .lacak-name-button strong.is-renamed { animation: none !important; }
  .lacak-name-button strong, .lacak-name-button .icon { transition: none; }
}
