/* ===========================================================================
   sheets-portal.css — bridge layer
   ---------------------------------------------------------------------------
   sheets-skin.css defines the design system. This file maps it onto the
   markup the compiled portal actually renders: a Material-UI chrome plus a
   react-data-table-component grid (the rdt_* class names are stable API of
   that library, not build hashes, so they are safe to target).

   Nothing here changes behaviour. Presentation only.
   =========================================================================== */

/* ---------- 1. Full-viewport shell ---------------------------------------- */

html, body { height: 100%; margin: 0; background: var(--canvas); }
body { font-family: var(--sans); color: var(--text); }

#app {
  min-height: 100vh;
  height: 100vh;
  border-radius: 0;
  border: 0;
  overflow: hidden;
}

/* The rail is gone: navigation lives in the top bar now, so the app is a
   single column and the grid gets the full width of the window. */
#app.skin-topnav {
  display: flex !important;
  flex-direction: column;
  grid-template-columns: none !important;
}

#app .main { min-width: 0; overflow: hidden; }

/* #root is relocated inside .body by the adapter. */
#app .body { padding: 0; overflow: auto; flex: 1; min-width: 0; }
#app .body > #root { min-height: 100%; }

/* The portal's own AppBar is replaced by .side + .top. Hidden, never removed —
   the adapter still reads its links to drive navigation. */
.skin-on header.MuiAppBar-root,
.skin-on .MuiAppBar-root.MuiPaper-root { display: none !important; }

/* The portal reserves vertical space for the AppBar that the rail and top bar
   now replace. Collapse it. The element stays in the DOM — the adapter still
   uses its account menu for logout. */
.skin-on #root > div > .header { display: none !important; }
.skin-on #root .bodyContent { margin-top: 0 !important; padding-top: 8px !important; }
.skin-on #root > div > .MuiContainer-root,
.skin-on #root .MuiToolbar-root.MuiToolbar-regular:empty { padding-top: 0 !important; }

/* ---------- 2. Icon rail -------------------------------------------------- */

.side { overflow-y: auto; overflow-x: hidden; }
.side .nav { position: relative; }
.side .nav .i { font-size: 18px; line-height: 1; }

/* Tooltip on hover, so a 58px rail is still navigable. */
.side .nav::after {
  content: attr(data-tip);
  position: absolute; left: calc(100% + 8px); top: 50%;
  transform: translateY(-50%) scale(.96);
  background: #05090b; color: #fff; font-size: 11.5px; font-weight: 600;
  padding: 5px 9px; border-radius: 6px; white-space: nowrap;
  opacity: 0; pointer-events: none; transition: .12s; z-index: 90;
}
.side .nav:hover::after { opacity: 1; transform: translateY(-50%) scale(1); }

/* ---------- 3. Top bar ---------------------------------------------------- */

.top { flex: 0 0 auto; min-height: 56px; padding: 9px 20px !important; }
.top h1 { line-height: 1.2; }
.userchip { flex-shrink: 0; gap: 9px; }
.userchip .uinfo { line-height: 1.15; }
.userchip .uinfo b { display: block; line-height: 1.2; white-space: nowrap; }
.userchip .uinfo br { display: none; }
.userchip .rolebadge { display: inline-block; margin-top: 1px; }

/* The portal's snackbars anchor to the top of the viewport, where the new top
   bar now lives. Nudge them clear of it. */
.skin-on .MuiSnackbar-anchorOriginTopRight,
.skin-on .MuiSnackbar-anchorOriginTopCenter,
.skin-on .MuiSnackbar-anchorOriginTopLeft { top: 74px !important; }

/* The portal's own row-expander sits next to the adapter's row actions.
   Mute it so the hide / history controls read as the primary actions. */
.rdt_TableRow > div:not(.rdt_TableCell) button { opacity: .45; }
.rdt_TableRow > div:not(.rdt_TableCell) button:hover { opacity: 1; }

/* ---------- 4. Page body padding ----------------------------------------- */

.skin-page { padding: 20px 22px 28px; }

/* ---------- 5. The grid --------------------------------------------------- */

.rdt_Table { font-family: var(--sans) !important; font-size: 15.5px !important; }

.rdt_TableHead,
.rdt_TableHeadRow {
  background: #fafbfa !important;
  border-bottom: 1px solid var(--line) !important;
  min-height: 0 !important;
}

.rdt_TableCol {
  font-size: 12px !important;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--muted) !important;
  font-weight: 700 !important;
  padding: 9px 8px !important;
  background: transparent;
}

.rdt_TableRow {
  border-bottom: 1px solid #eef1ee !important;
  min-height: 0 !important;
}
.rdt_TableRow:hover { background: #fbfcfb !important; }

/* Rows are kept tight like a spreadsheet cell: the type gets bigger, the
   padding gets smaller, so more leads fit on screen. */
.rdt_TableCell { padding: 2px 8px !important; color: var(--text); font-size: 15.5px; }
/* react-data-table pads each row 12px top and bottom, which was adding 24px of
   dead space to every line. Removing it is what actually gets the row down to
   spreadsheet height. */
.skin-on .rdt_TableRow { min-height: 40px !important; padding: 0 !important; }
.skin-on .rdt_TableHeadRow { padding: 0 !important; }

.skin-on .rdt_Table,
.skin-on div[role="table"] {
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--card);
  min-width: 1820px;
}

/* The rows are the flex containers that actually lay the columns out, so the
   floor has to sit on them — putting it only on the table let the rows shrink
   and the columns squash instead of the wrapper scrolling. */
.skin-on .rdt_TableHead,
.skin-on .rdt_TableHeadRow,
.skin-on .rdt_TableBody,
.skin-on .rdt_TableRow { min-width: 1820px; }

/* ---------- horizontal scrolling ----------------------------------------
   Columns are sized to their content, which makes the grid wider than the
   screen. Without a scroller the only way to reach Client / Created On / AI
   Call was to zoom the whole page out. */
/* The wrapper has to be held to the width of the page, otherwise it simply
   grows to fit the widest row and there is nothing to scroll — which is why
   the right-hand columns were only reachable by zooming the browser out. */
.skin-on .leadContent,
.skin-on .bodyContent,
.skin-on .tableBlock,
.skin-on .leadTableViewSec { max-width: 100%; min-width: 0; box-sizing: border-box; }

/* react-data-table already puts a horizontal scroller around the grid, but the
   table is ~2100px tall, so that scrollbar sat far below the fold — the only
   way to reach the right-hand columns was to zoom the browser out. Giving the
   grid its own viewport pins both scrollbars on screen. */
.skin-on .tableBlock > div {
  /* Measured, not guessed: 56px top bar + 10px gap + 33px toolbar + 20px gap
     above the scroller, and 56px of pagination below it. At 148px the
     pagination row was pushed 27px past the fold. */
  max-height: calc(100vh - 158px);
  overflow: auto !important;
}

/* With the grid scrolling vertically, the headings have to stay put. */
.skin-on .rdt_TableHead { position: sticky; top: 0; z-index: 3; }

.skin-on .tableBlock > div::-webkit-scrollbar { height: 12px; width: 12px; }
.skin-on .tableBlock > div::-webkit-scrollbar-track { background: var(--canvas); }
.skin-on .tableBlock > div::-webkit-scrollbar-thumb {
  background: #b9c6bf; border-radius: 8px; border: 3px solid var(--canvas);
}
.skin-on .tableBlock > div::-webkit-scrollbar-thumb:hover { background: var(--muted); }
.skin-on .tableBlock > div::-webkit-scrollbar-corner { background: var(--canvas); }
body.dark.skin-on .tableBlock > div::-webkit-scrollbar-track,
body.dark.skin-on .tableBlock > div::-webkit-scrollbar-corner { background: #10161a; }
body.dark.skin-on .tableBlock > div::-webkit-scrollbar-thumb { background: #3a4a54; border-color: #10161a; }

/* ---------- column widths ------------------------------------------------
   react-data-table gives every column the same percentage, which is what made
   the grid read as clumsy: a postcode and a full street address got identical
   space. Each column is sized to what it actually holds; Address and Comments
   are the only ones that flex, so they absorb the slack.
   `data-skin-col` is stamped by the adapter from the column's original heading. */

.skin-on [data-skin-col]            { flex: 0 0 auto !important; }
.skin-on [data-skin-col="sel"]      { min-width: 66px  !important; max-width: 66px  !important; }
.skin-on [data-skin-col="app-date"] { min-width: 150px !important; max-width: 150px !important; }
.skin-on [data-skin-col="app-time"] { min-width: 132px !important; max-width: 132px !important; }
.skin-on [data-skin-col="agent-id"] { min-width: 94px !important; max-width: 94px !important; }
/* Lead Type now reads CU / HB, so it needs only enough room for the caret. */
.skin-on [data-skin-col="lead-type"]{ min-width: 74px !important; max-width: 74px !important; }
.skin-on [data-skin-col="lead-type"] select { text-align: center; }
/* App Time is a slot picker now — the widest slot is "10am - 12am". */
.skin-on [data-skin-col="app-time"] select.skin-cell-ctl { width: 100%; }
.skin-on [data-skin-col="customer-name"]    { min-width: 166px !important; max-width: 166px !important; }
.skin-on [data-skin-col="customer-address"] {
  flex: 1 1 220px !important; min-width: 200px !important; max-width: none !important;
}
.skin-on [data-skin-col="city"]     { min-width: 128px !important; max-width: 128px !important; }
.skin-on [data-skin-col="phone"]    { min-width: 124px !important; max-width: 124px !important; }
.skin-on [data-skin-col="status"]   { min-width: 176px !important; max-width: 176px !important; }
.skin-on [data-skin-col="client-name"]  { min-width: 92px !important; max-width: 92px !important; }
.skin-on [data-skin-col="created-on"]   { min-width: 98px !important; max-width: 98px !important; }
.skin-on [data-skin-col="make-ai-call"] { min-width: 66px  !important; max-width: 66px  !important; }
.skin-on [data-skin-col="push-to-crm"]  { min-width: 76px  !important; max-width: 76px  !important; }

/* Injected columns size themselves the same way. */
.skin-on [data-skin-extra="age"]      { flex: 0 0 auto !important; min-width: 116px !important; max-width: 116px !important; }
.skin-on [data-skin-extra="gender"]   { flex: 0 0 auto !important; min-width: 108px !important; max-width: 108px !important; }
.skin-on [data-skin-extra="comments"] { flex: 1 1 200px !important; min-width: 180px !important; max-width: none !important; }

/* Long values wrap rather than stretching their column, and nothing spills
   into the column beside it. */
.skin-on .rdt_TableCell { white-space: normal; word-break: break-word; overflow: hidden; }
.skin-on .rdt_TableCol  { white-space: normal; line-height: 1.25; overflow: hidden; }
.skin-on .rdt_TableCell > * { max-width: 100%; }
.skin-on .rdt_TableCell .MuiFormControl-root,
.skin-on .rdt_TableCell .MuiInputBase-root { width: 100%; min-width: 0; }

/* The pagination bar shipped at 56px tall for one line of 12px text — nearly
   40px of it was empty. At 36px it still clears the controls and gives the
   grid the difference. */
.rdt_Pagination {
  border-top: 1px solid var(--line) !important;
  font-size: 12px !important;
  color: var(--muted) !important;
  background: var(--card) !important;
  min-height: 36px !important;
  height: 36px !important;
  padding: 0 10px !important;
}
.rdt_Pagination select { padding: 1px 16px 1px 4px !important; font-size: 12px !important; }

/* The paging arrows are SVGs filled with rgba(0,0,0,.54) — invisible against
   the dark canvas, which is why they read as an empty strip. Fill is what
   colours them, not `color`, and the disabled pair has to stay visibly
   disabled rather than simply vanishing. */
.rdt_Pagination button { fill: var(--muted) !important; color: var(--muted) !important; padding: 3px !important; }
.rdt_Pagination button:disabled { fill: var(--line) !important; color: var(--line) !important; }
.rdt_Pagination button:not(:disabled):hover {
  fill: var(--brand) !important; color: var(--brand) !important;
  background-color: rgba(0,118,201,.10) !important;
}
body.dark.skin-on .rdt_Pagination button { fill: #9fb0bb !important; color: #9fb0bb !important; }
body.dark.skin-on .rdt_Pagination button:disabled { fill: #3a4750 !important; color: #3a4750 !important; }
body.dark.skin-on .rdt_Pagination button:not(:disabled):hover {
  fill: #7dc0ee !important; color: #7dc0ee !important;
  background-color: rgba(47,149,220,.16) !important;
}

/* ---------- 6. THE RED LINE ---------------------------------------------- */
/* The adapter stamps data-skin="load" | "entry" | "cli" onto each header and
   cell by matching the header text, so the split survives column reordering. */

.rdt_TableCol[data-skin="load"]  { background: var(--load) !important; color: var(--loadtx) !important; }
.rdt_TableCol[data-skin="entry"] { background: #e8f3fb !important;     color: var(--green-dk) !important; }
.rdt_TableCol[data-skin="cli"]   { background: var(--cli) !important;  color: var(--clitx) !important; }

.rdt_TableCell[data-skin="load"] { background: #f4f8fc !important; color: #2a3f56; }
.rdt_TableCell[data-skin="cli"]  { background: var(--cli) !important; }
.rdt_TableRow:hover .rdt_TableCell[data-skin="load"] { background: #ecf3fa !important; }

/* Loaded cells are visually locked until the lead is confirmed. */
.rdt_TableRow[data-confirmed="0"] .rdt_TableCell[data-skin="load"] {
  color: #55708c;
}
.rdt_TableRow[data-confirmed="0"] .rdt_TableCell[data-skin="load"]::after {
  content: "";
}

/* A confirmed lead unlocks the loaded columns and turns them green.
   The hover state must stay inside its own confirmed/unconfirmed lane —
   painting every hovered row green would make an unconfirmed lead read as
   confirmed, which is exactly the signal this column split exists to carry. */
.rdt_TableRow[data-confirmed="1"] .rdt_TableCell[data-skin="load"] {
  background: #d9ecdf !important;
  color: #14432f;
}
.rdt_TableRow[data-confirmed="1"]:hover .rdt_TableCell[data-skin="load"] { background: #cfe6d6 !important; }

/* The client column is removed outright for the agent tier. */
.skin-role-agent .rdt_TableCol[data-skin="cli"],
.skin-role-agent .rdt_TableCell[data-skin="cli"] { display: none !important; }

/* Rows hidden from agents, as seen by a privileged user. */
.rdt_TableRow[data-hidden="1"] .rdt_TableCell { opacity: .42; }
.rdt_TableRow[data-hidden="1"] .rdt_TableCell:first-child { opacity: 1; }

/* ---------- 7. Inline editors inside the grid ---------------------------- */

/* IMPORTANT: background and colour are deliberately left alone here.
   The portal colour-codes Status, Client Name and City by putting an inline
   background on a wrapper around the control. Painting the control would
   erase that colour coding, which carries real meaning for the QC team. */
.rdt_TableCell select,
.rdt_TableCell input[type="text"] {
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 600;
  padding: 4px 7px;
  border: 1px solid rgba(0, 0, 0, .13);
  border-radius: 6px;
  background: transparent;
  color: inherit;
  cursor: pointer;
  /* Must be able to shrink to its column — a fixed minimum made narrow
     columns overflow into their neighbour. */
  min-width: 0;
  max-width: 100%;
}
.rdt_TableCell select:focus,
.rdt_TableCell input[type="text"]:focus { outline: 2px solid var(--focus); outline-offset: -1px; }
.rdt_TableCell select:disabled { background: #f2f3f1; color: #b4bdb6; cursor: not-allowed; border-style: dashed; }
.rdt_TableCell input[type="checkbox"] { width: 15px; height: 15px; accent-color: var(--green); cursor: pointer; }

/* ---------- 8. Row action buttons the adapter injects -------------------- */

.skin-rowacts { display: inline-flex; align-items: center; gap: 2px; margin-left: 2px; }
.skin-btn {
  border: 0; background: transparent; cursor: pointer; color: var(--muted);
  padding: 3px; border-radius: 6px; line-height: 0; position: relative;
  display: inline-grid; place-items: center; font-size: 13px;
}
.skin-btn:hover { background: var(--canvas); color: var(--green); }
.skin-btn.off { color: var(--danger); }
.skin-badge {
  position: absolute; top: -3px; right: -4px; background: var(--green); color: #fff;
  font-size: 8px; font-weight: 700; min-width: 13px; height: 13px; border-radius: 7px;
  display: grid; place-items: center; padding: 0 3px; line-height: 1;
}

/* ---------- 9. Toolbar the portal already renders ------------------------ */

.skin-on .MuiButton-root {
  text-transform: none !important;
  font-family: var(--sans) !important;
  border-radius: 8px !important;
  font-weight: 600 !important;
  font-size: 12.5px !important;
  box-shadow: none !important;
}
.skin-on .MuiButton-contained { background: var(--green) !important; color: #fff !important; }
.skin-on .MuiButton-contained:hover { background: var(--green-dk) !important; }
.skin-on .MuiButton-outlined { border-color: var(--line) !important; color: var(--text) !important; background: #fff !important; }
.skin-on .MuiPaper-root { box-shadow: none !important; }
.skin-on .MuiCard-root,
.skin-on .MuiPaper-elevation1 {
  border: 1px solid var(--line) !important;
  border-radius: 12px !important;
  background: var(--card) !important;
}
.skin-on .MuiInputBase-root { font-family: var(--sans) !important; font-size: 13px !important; }

/* Dashboard KPI cards */
.skin-on .MuiCard-root .MuiTypography-h5,
.skin-on .MuiCard-root .MuiTypography-h4 { font-family: var(--mono) !important; color: var(--green); }

/* ---------- 10. The leads toolbar, in Sheets order ----------------------- */

/* The Sheets build has no AutoLoad controls — it refreshes on its own and
   only reports when it last did. These are the portal's three equivalents,
   hidden once the adapter has switched auto-refresh on permanently. */
.skin-on .skin-autoload { display: none !important; }

/* One toolbar row, in Sheets order.

   The portal splits the toolbar into two MUI grid halves, which is what forced
   the controls onto separate lines. `display:contents` dissolves those
   wrappers so every control becomes a direct flex child of one row, and
   `order` then places them without moving a single node in the DOM — React
   keeps ownership of its own elements. */
.skin-on .headerBlock {
  display: flex !important;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  margin: 0 !important;
  width: 100% !important;
}
.skin-on .headerBlock > .MuiGrid-item { display: contents !important; }
.skin-on .headerBlock .FiltersLeadBtn > div { display: contents !important; }

/* Sheets order: search · bulk update · area ......... colour · export ·
   filters · clear · hidden · count · add lead.
   `order` is set on data-skin-slot, which the adapter puts on whichever
   element is the real flex item — several controls sit inside a wrapper. */
.skin-on [data-skin-slot="search"] { order: 1; min-width: 200px; margin: 0 !important; }
.skin-on [data-skin-slot="bulk"]   { order: 2; }
.skin-on #skinAreaWrap             { order: 3; }
.skin-on #skinColourWrap           { order: 4; margin-left: auto; }
.skin-on [data-skin-slot="export"] { order: 5; }
.skin-on #skinRight                { order: 6; }
.skin-on [data-skin-slot="add"]    { order: 7; }
.skin-on [data-skin-search]        { margin: 0 !important; }

/* Give the search field the bordered look the Sheets toolbar uses. */
.skin-on [data-skin-search] .MuiInput-underline:before,
.skin-on [data-skin-search] .MuiInput-underline:after { display: none !important; }
.skin-on [data-skin-search] .MuiInputBase-root {
  border: 1px solid var(--line); border-radius: 8px;
  padding: 2px 10px; background: #fff;
}
.skin-on [data-skin-search] .MuiInputBase-input { font-size: 13px; padding: 6px 0; }

/* MUI holds its placeholder at opacity 0 until its floating label shrinks, so
   the label — not the placeholder — is what carries the hint here. Keep the
   label and sit it inside the bordered box, which is how the Sheets search
   field reads. It lifts out of the way on focus, as MUI already handles. */
.skin-on [data-skin-search] { position: relative; justify-content: center; }
/* In MUI's standard variant the label sits in normal flow above the field, so
   it has to be lifted out and overlaid to read as placeholder text. */
.skin-on [data-skin-search] label {
  position: absolute !important;
  top: 0 !important; left: 0 !important;
  transform: translate(11px, 8px) scale(1) !important;
  transform-origin: top left;
  font-family: var(--sans) !important;
  font-size: 13px !important;
  color: var(--muted) !important;
  pointer-events: none;
  z-index: 1;
}
.skin-on [data-skin-search] label.MuiInputLabel-shrink,
.skin-on [data-skin-search] label.Mui-focused { opacity: 0 !important; }
.skin-on [data-skin-search] .MuiInputBase-root { margin-top: 0 !important; }

/* Sheets labels its bulk control with a bolt. */
.skin-on [data-skin-btn="bulk"] .MuiButton-label:before { content: "⚡ "; }

/* The portal's own filter buttons are replaced by the inline filter controls,
   but the drawer they open still owns the React state the fetch reads, so the
   Apply button stays in the DOM — just never seen. */
.skin-on [data-skin-btn="apply"],
.skin-on [data-skin-btn="clear"] { display: none !important; }
.skin-on .MuiDrawer-root { visibility: hidden !important; pointer-events: none !important; }

/* Reclaim the empty band between the top bar and the toolbar. */
.skin-on .leadContent,
.skin-on .leadTableViewSec { padding-top: 0 !important; margin-top: 0 !important; }
.skin-on .tableHeaderBlock { padding: 10px 0 8px !important; margin: 0 !important; }
.skin-on #root .bodyContent { padding-top: 0 !important; }

/* Colour moves to the toolbar; its grid column is dropped. */
.rdt_TableCol[data-skin-drop],
.rdt_TableCell[data-skin-drop] { display: none !important; }

/* The row expander is retired: everything it held — the under-80 question,
   the notes and the log — now lives in the row itself or behind the clock. */
.rdt_TableRow > div:not(.rdt_TableCell):not([data-skin-extra]),
.rdt_TableHeadRow > div:not(.rdt_TableCol):not([data-skin-extra]) { display: none !important; }
.rdt_ExpanderRow { display: none !important; }

/* ---------- Columns the adapter adds, and inline editing ----------------- */

.skin-extra-col {
  font-size: 12px !important;
  text-transform: uppercase;
  letter-spacing: .4px;
  font-weight: 700 !important;
  padding: 9px 8px !important;
  background: #eafaf3 !important;
  color: var(--green-dk) !important;
}
.skin-extra-cell { padding: 2px 8px !important; }

.skin-cell-ctl {
  width: 100%;
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
  font-family: var(--sans);
  font-size: 15px;
  padding: 4px 7px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fff;
  color: var(--text);
}
select.skin-cell-ctl { font-weight: 600; cursor: pointer; }
.skin-cell-ctl:focus { outline: 2px solid var(--focus); outline-offset: -1px; }

/* A cell that has unlocked because the lead is confirmed. */
.rdt_TableCell[data-skin-editable="1"] { padding: 2px 8px !important; }
.rdt_TableCell[data-skin-editable="1"] .skin-cell-ctl {
  background: #f2fbf6;
  border-color: #bcdccb;
}

body.dark .skin-extra-col { background: #14241d !important; color: #7fd3b3 !important; }
body.dark .skin-cell-ctl { background: #1c262c; color: var(--text); border-color: #31414a; }
body.dark .rdt_TableCell[data-skin-editable="1"] .skin-cell-ctl {
  background: #172a20; border-color: #2f5340;
}

/* No flicker: the backdrop is suppressed for refreshes the user did not ask
   for, so the 20-second cycle swaps rows silently. */
/* ---------- the routine "loaded successfully" popup ----------------------
   Hidden by default on the Lead Queue only, and revealed by the adapter for
   any message worth reading. Hidden-first is what keeps it from flickering:
   the popup is suppressed before the browser paints it, rather than being
   taken away again a frame later.

   Scoped to this one page on purpose. The same component carries the password
   and user-admin messages elsewhere, and those must never be at the mercy of
   this rule - if the adapter's script fails, they are untouched.

   visibility rather than display: the snackbar is fixed-position, so it costs
   no layout either way, and visibility leaves MUI's own transitions intact
   for the ones that do get shown. */
body.skin-leads-on .MuiSnackbar-root { visibility: hidden; }
body.skin-leads-on .MuiSnackbar-root.skin-snack-show { visibility: visible; }

/* ---------- the refresh gauge -------------------------------------------
   Replaces the "auto-refresh, last 16:14:30" text. Segments light up left to
   right across one refresh cycle and drop back to empty when the list
   reloads, so the question "is this still live" is answered by movement
   rather than by reading a clock and doing arithmetic.

   Segmented rather than a smooth bar on purpose: a continuous fill creeping a
   few pixels every half second is easy to mistake for a stationary one, while
   a segment lighting up is a discrete event the eye catches without looking
   for it. Fourteen segments over twenty seconds is roughly one every 1.4s.
------------------------------------------------------------------------ */
.skin-rbar {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  height: 14px;
  padding: 2px 3px;
  margin-left: 8px;
  border-radius: 4px;
  background: var(--rbar-well, rgba(120, 150, 180, .14));
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, .12);
  vertical-align: middle;
}

.skin-rbar i {
  display: block;
  width: 3px;
  height: 10px;
  border-radius: 1px;
  background: var(--rbar-off, rgba(120, 150, 180, .30));
  transition: background-color .18s ease, box-shadow .18s ease;
}

.skin-rbar i.on {
  background: var(--rbar-on, #0076c9);
  box-shadow: 0 0 4px var(--rbar-glow, rgba(0, 118, 201, .55));
}

body.dark .skin-rbar {
  --rbar-well: rgba(255, 255, 255, .07);
  --rbar-off:  rgba(255, 255, 255, .16);
  --rbar-on:   #38b6ff;
  --rbar-glow: rgba(56, 182, 255, .55);
}

/* While a refresh is actually in flight every segment lifts, so the moment of
   reloading is visible rather than just the waiting before it. */
body.skin-loading .skin-rbar i {
  background: var(--rbar-on, #0076c9);
  box-shadow: 0 0 5px var(--rbar-glow, rgba(0, 118, 201, .6));
}

@media (prefers-reduced-motion: reduce) {
  .skin-rbar i { transition: none; }
}

/* The dashboard's gauge sits at the end of the range line rather than in a
   toolbar, so it needs its own spacing and a slightly lighter well to sit on
   a card rather than on the bar. */
.skin-dash-title .skin-rbar {
  margin-left: 10px;
  transform: translateY(-1px);
}

/* ---------- the refresh indicator ---------------------------------------
   The portal signals loading with a full-screen backdrop. On a twenty-second
   auto-refresh that is not progress, it is a flicker: the table is still on
   screen and still correct, and the only thing the backdrop achieves is to
   grey it out and eat any click that lands during it. So the backdrop stays
   suppressed (below) and this takes its place.

   It sits in the toolbar beside the "last refreshed" time - where the eye
   already goes to ask that question - and reserves its own width whether or
   not it is spinning, so nothing shifts when it appears. Nothing is covered
   and nothing is blocked; the grid stays usable throughout.
------------------------------------------------------------------------ */
.skin-spin {
  width: 15px;
  height: 15px;
  flex: 0 0 15px;          /* the space is held even when invisible */
  border-radius: 50%;
  border: 2px solid var(--skin-spin-track, rgba(120, 150, 180, .28));
  border-top-color: var(--skin-spin-lead, #0076c9);
  opacity: 0;
  transition: opacity .18s ease;
  animation: skin-spin-turn .7s linear infinite;
  /* Never paints unless it is turning, so a paused tab costs nothing. */
  animation-play-state: paused;
}

body.skin-loading .skin-spin {
  opacity: 1;
  animation-play-state: running;
}

body.dark .skin-spin {
  --skin-spin-track: rgba(255, 255, 255, .18);
  --skin-spin-lead: #4aa8ff;
}

@keyframes skin-spin-turn { to { transform: rotate(360deg); } }

/* Someone who has asked their system not to animate gets a steady dot rather
   than a spinning ring - still an indicator, no motion. */
@media (prefers-reduced-motion: reduce) {
  .skin-spin { animation: none; border-top-color: var(--skin-spin-lead, #0076c9); }
}

body.skin-quiet-refresh .backDropLoader,
body.skin-quiet-refresh .MuiBackdrop-root { opacity: 0 !important; pointer-events: none !important; }
/* Driving the portal's filter drawer means opening it, and opening it puts a
   full-screen MUI backdrop over everything. Hiding it with opacity alone left
   that backdrop still catching clicks, so the portal looked frozen until a
   reload. pointer-events:none lets clicks fall through to the page underneath.
   Scripted .click() calls are unaffected, so the drawer can still be driven. */
body.skin-drawer-silent .MuiDrawer-root,
body.skin-drawer-silent .MuiBackdrop-root {
  opacity: 0 !important;
  pointer-events: none !important;
}

/* Area filter, sitting beside the search box on the top row. */
.skin-areafilter { display: inline-flex; align-items: center; gap: 7px; }
.skin-areafilter .flabel {
  font-size: 10px; text-transform: uppercase; letter-spacing: .6px; color: var(--muted);
}
.skin-areafilter select {
  font-family: var(--sans); font-size: 12px; font-weight: 600;
  padding: 6px 10px; border: 1px solid var(--line); border-radius: 8px;
  background: #fff; color: var(--text); cursor: pointer;
}

/* Hidden pill + status line, top right after the app's own buttons. */
.skin-right { display: inline-flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.skin-right .flabel {
  font-size: 10px; text-transform: uppercase; letter-spacing: .6px; color: var(--muted);
}
.skin-right select,
.skin-right input[type="date"] {
  font-family: var(--sans); font-size: 12px;
  padding: 6px 8px; border: 1px solid var(--line); border-radius: 7px;
  background: #fff; color: var(--text);
}
.skin-right select { cursor: pointer; font-weight: 600; }
.skin-right .skin-colour { border-color: var(--green); color: var(--green-dk); }
.skin-right .skin-fclear {
  border: 1px solid var(--line); background: #fff; border-radius: 7px;
  padding: 6px 10px; font-size: 12px; cursor: pointer; color: var(--muted);
  font-family: var(--sans);
}
.skin-right .skin-fclear:hover { background: var(--canvas); color: var(--text); }
.skin-right .pill {
  border: 1px solid var(--line); background: #fff; border-radius: 20px;
  padding: 6px 13px; font-size: 12px; cursor: pointer; color: var(--muted);
  font-weight: 600; white-space: nowrap;
}
.skin-right .pill.on { background: var(--ink); color: #fff; border-color: var(--ink); }
.skin-right .count { font-size: 11.5px; color: var(--muted); white-space: nowrap; }

/* The four toolbar actions, styled as the Sheets build styles them:
   bulk update reads as a control, export as a green outline action, the two
   filter buttons as quiet chrome, and Add Lead as the primary action. */
.skin-on [data-skin-btn] { text-transform: none !important; }

.skin-on [data-skin-btn="bulk"] {
  border: 1px solid var(--green) !important;
  color: var(--green-dk) !important;
  background: #fff !important;
  font-weight: 600 !important;
}
.skin-on [data-skin-btn="bulk"]:hover { background: #eef5f2 !important; }

.skin-on [data-skin-btn="export"] {
  border: 1px solid var(--green) !important;
  color: var(--green-dk) !important;
  background: #fff !important;
}
.skin-on [data-skin-btn="export"]:hover { background: #eef5f2 !important; }

.skin-on [data-skin-btn="apply"],
.skin-on [data-skin-btn="clear"] {
  border: 1px solid var(--line) !important;
  color: var(--muted) !important;
  background: #fff !important;
}
.skin-on [data-skin-btn="apply"]:hover,
.skin-on [data-skin-btn="clear"]:hover { background: var(--canvas) !important; color: var(--text) !important; }

.skin-on [data-skin-btn="add"] {
  background: var(--green) !important;
  border: 1px solid var(--green) !important;
}
.skin-on [data-skin-btn="add"] .MuiButton-label { color: #fff !important; }
.skin-on [data-skin-btn="add"]:hover { background: var(--green-dk) !important; }

body.dark .skin-areafilter select,
body.dark .skin-right .pill { background: #1a232a; color: var(--text); border-color: #2a343a; }
body.dark.skin-on [data-skin-btn="bulk"],
body.dark.skin-on [data-skin-btn="export"],
body.dark.skin-on [data-skin-btn="apply"],
body.dark.skin-on [data-skin-btn="clear"] { background: #1a232a !important; }
body.dark.skin-on [data-skin-btn="apply"] .MuiButton-label,
body.dark.skin-on [data-skin-btn="clear"] .MuiButton-label { color: var(--text) !important; }

/* ---------- 11. Area colour chips on the City cell ----------------------- */

.skin-area {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 3px 10px; border-radius: 6px; font-weight: 600; font-size: 12px;
  min-width: 84px;
}

/* ---------- 12. Audit history modal -------------------------------------- */

.skin-modal-overlay {
  position: fixed; inset: 0; background: rgba(15,26,23,.5);
  display: flex; align-items: center; justify-content: center; z-index: 3000; padding: 20px;
}
.skin-modal {
  background: var(--card); border-radius: 14px; width: 520px; max-width: 100%;
  max-height: 80vh; display: flex; flex-direction: column;
  box-shadow: 0 24px 70px rgba(0,0,0,.3); overflow: hidden; color: var(--text);
}
.skin-modal-hd {
  display: flex; justify-content: space-between; align-items: flex-start;
  padding: 17px 20px; border-bottom: 1px solid var(--line);
}
.skin-modal-hd b { font-size: 15px; }
.skin-modal-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.skin-modal-x {
  border: 0; background: transparent; font-size: 15px; cursor: pointer;
  color: var(--muted); border-radius: 6px; padding: 4px 8px;
}
.skin-modal-x:hover { background: var(--canvas); }
.skin-modal-body { padding: 8px; overflow: auto; }
.skin-hist-row { display: flex; gap: 11px; padding: 11px 12px; border-radius: 9px; }
.skin-hist-row:hover { background: var(--canvas); }
.skin-hist-av {
  width: 30px; height: 30px; border-radius: 50%; background: var(--ink); color: #fff;
  display: grid; place-items: center; font-size: 11px; font-weight: 700; flex-shrink: 0;
}
.skin-hist-act { font-size: 13px; font-weight: 500; }
.skin-hist-meta {
  font-size: 11.5px; color: var(--muted); margin-top: 3px;
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.skin-empty { color: var(--muted); font-size: 13px; padding: 30px; text-align: center; }

/* ---------- 13. Toast ---------------------------------------------------- */

.skin-toast {
  position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%);
  background: var(--ink); color: #fff; padding: 11px 18px; border-radius: 9px;
  font-size: 13px; font-weight: 500; opacity: 0; transition: .25s;
  pointer-events: none; z-index: 3100;
}
.skin-toast.show { opacity: 1; }
.skin-toast.err { background: var(--danger); }

/* ---------- 14. Sign in ---------------------------------------------------
   The form is the portal's own and is left alone. Everything around it is
   rebuilt: a split page with the brand on one side and the card on the other,
   which is what an operations tool is expected to look like and, more
   usefully, gives room to say plainly which copy of the system you are
   signing into.
   ------------------------------------------------------------------------ */

.skin-login #root {
  position: fixed; inset: 0; z-index: 100;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  background: #f4f7fa;
  padding: 0;
  overflow: auto;
}
.skin-login #app > .skin-topbar,
.skin-login .skin-toolbar { display: none !important; }

/* ---- the brand side ---- */

.skin-auth-aside {
  position: relative;
  display: flex; flex-direction: column; justify-content: space-between;
  padding: 44px 52px;
  color: #eaf3fb;
  background:
    radial-gradient(900px 600px at 15% 5%,  rgba(86,178,240,.30), transparent 60%),
    radial-gradient(700px 700px at 90% 90%, rgba(0,60,110,.55),   transparent 65%),
    linear-gradient(150deg, #0b6cb0 0%, #08558f 42%, #06375c 78%, #041f36 100%);
  overflow: hidden;
}
/* A faint grid, so the panel has some structure without a background image
   to load. */
.skin-auth-aside::before {
  content: ''; position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(255,255,255,.055) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.055) 1px, transparent 1px);
  background-size: 46px 46px;
  mask-image: radial-gradient(120% 100% at 20% 0%, #000 30%, transparent 78%);
  -webkit-mask-image: radial-gradient(120% 100% at 20% 0%, #000 30%, transparent 78%);
  pointer-events: none;
}
.skin-auth-aside > * { position: relative; z-index: 1; }

/* The wordmark's numerals are the brand blue, which disappears against a
   blue panel. Knocked out to solid white — the usual treatment for a logo on
   a coloured field, and it reads at any size. */
.skin-auth-brand img {
  height: 40px; width: auto; display: block;
  filter: brightness(0) invert(1);
  opacity: .97;
}

.skin-auth-pitch h1 {
  margin: 0 0 22px;
  font-size: 38px; line-height: 1.18; font-weight: 800;
  letter-spacing: -.4px; color: #fff;
}
.skin-auth-points { list-style: none; margin: 0; padding: 0; display: grid; gap: 11px; }
.skin-auth-points li {
  position: relative; padding-left: 26px;
  font-size: 14.5px; line-height: 1.45; color: rgba(233,243,251,.86);
}
.skin-auth-points li::before {
  content: ''; position: absolute; left: 0; top: 7px;
  width: 8px; height: 8px; border-radius: 50%;
  background: #6cc3f5; box-shadow: 0 0 0 4px rgba(108,195,245,.20);
}

.skin-auth-foot { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.skin-auth-copy { font-size: 12px; color: rgba(233,243,251,.55); }

/* The environment badge. Amber rather than red: this is information, not a
   fault — but it has to be impossible to miss, because the whole point of the
   mirror is that production is never touched by mistake. */
.skin-auth-env {
  font-size: 11.5px; font-weight: 800; letter-spacing: .4px; text-transform: uppercase;
  padding: 4px 10px; border-radius: 999px;
}
.skin-auth-env.mirror { background: rgba(255,196,0,.16); border: 1px solid rgba(255,196,0,.55); color: #ffd257; }
.skin-auth-env.other  { background: rgba(255,255,255,.10); border: 1px solid rgba(255,255,255,.28); color: #dbe8f3; }

/* ---- the form side ---- */

.skin-login #root .main-wrapper,
.skin-login #root .login_container_block {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  height: 100%; padding: 32px 24px; box-sizing: border-box; min-width: 0;
}

/* A line under the card for the person who cannot get in. Nothing here told
   them who to ask. */
.skin-login #root .login_container_block::after {
  content: 'Trouble signing in? Ask your team lead to check your account is active.';
  display: block; margin-top: 18px; max-width: 380px;
  font-size: 12.5px; line-height: 1.5; color: #7c8b95; text-align: center;
}

.skin-login #root .box,
.skin-login #root .MuiPaper-root {
  background: #fff !important;
  border: 1px solid #e3e9ef !important;
  border-radius: 14px !important;
  padding: 34px 34px 30px !important;
  box-shadow: 0 18px 50px rgba(9,40,66,.10) !important;
  width: 380px; max-width: 100%;
  margin: 0 !important;
}

/* The card carries the logo only when the brand panel is not on screen; on a
   wide window it would simply be the same mark twice. */
.skin-login #root .box-header { text-align: left; margin-bottom: 22px; }
.skin-login #root .box-header .logo { display: none; }
.skin-login #root .box-header h1 {
  margin: 0; font-size: 23px; font-weight: 800; letter-spacing: -.2px; color: #14202b;
}
.skin-login #root .box-header::after {
  content: 'Sign in to continue to the appointment portal.';
  display: block; margin-top: 7px;
  font-size: 13.5px; line-height: 1.45; color: #64757f; font-weight: 500;
}

.skin-login #root .box-form { display: block; }
.skin-login #root .material_input { margin-bottom: 16px !important; }
.skin-login #root .MuiFormLabel-root { font-size: 14px; color: #64757f; }
.skin-login #root .MuiFormLabel-root.Mui-focused { color: #0076c9; }
.skin-login #root .MuiOutlinedInput-root { border-radius: 10px; background: #fff; }
.skin-login #root .MuiOutlinedInput-input { padding: 14px 14px; font-size: 14.5px; color: #14202b; }
.skin-login #root .MuiOutlinedInput-notchedOutline { border-color: #d8e0e7; }
.skin-login #root .MuiOutlinedInput-root:hover .MuiOutlinedInput-notchedOutline { border-color: #b8c6d2; }
.skin-login #root .MuiOutlinedInput-root.Mui-focused .MuiOutlinedInput-notchedOutline {
  border-color: #0076c9; border-width: 2px;
}

/* Reveal control and Caps Lock warning, both injected by the adapter. */
.skin-pw-wrap { position: relative; }
.skin-eye {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  width: 32px; height: 32px; padding: 0;
  border: 0; border-radius: 8px; background: transparent;
  font-size: 15px; line-height: 1; cursor: pointer;
  opacity: .42; transition: opacity .12s ease, background .12s ease;
}
.skin-eye:hover { opacity: .8; background: #f1f5f8; }
.skin-eye.on { opacity: 1; }
.skin-login #root .skin-pw-wrap .MuiOutlinedInput-input { padding-right: 44px; }

.skin-caps {
  display: none;
  margin-top: 6px; font-size: 12px; font-weight: 700; color: #8a6100;
}
.skin-caps.on { display: block; }
.skin-caps::before { content: '⚠ '; }

.skin-login #root .formBtn { margin-top: 4px; }
.skin-login #root .submitBtn {
  background: #0076c9 !important; border: 1px solid #0076c9 !important;
  color: #fff !important;
  border-radius: 10px !important;
  padding: 12px 16px !important;
  font-size: 14.5px !important; font-weight: 700 !important;
  text-transform: none !important; letter-spacing: .2px;
  box-shadow: 0 6px 16px rgba(0,118,201,.24) !important;
}
.skin-login #root .submitBtn:hover { background: #005b9e !important; border-color: #005b9e !important; }
.skin-login #root .submitBtn:active { box-shadow: none !important; }

/* The error was bare red text with no room around it and was easy to miss. */
.skin-login #root .loginErrorMsg { min-height: 0; }
.skin-login #root .loginErrorMsg:not(:empty) {
  margin-top: 16px; padding: 10px 12px;
  border: 1px solid #f0c2ba; border-radius: 9px;
  background: #fdf1ef; color: #a5301f;
  font-size: 13px; font-weight: 600; line-height: 1.4;
}

/* ---- pinning down the app's own login layout ----------------------------
   Three things in the portal's stylesheet fight this layout, and all three
   have to be answered explicitly:
     - the card is absolutely positioned and translated to the centre of the
       WINDOW, so it ignored the column it was supposed to sit in;
     - a full-bleed background image is painted by a pseudo-element on the
       wrapper, which covered the brand panel;
     - the fields and the button are given fixed widths narrower than the card.
*/

.skin-login #root .login_container_block::before,
.skin-login #root .main-wrapper::before { display: none !important; content: none !important; }

.skin-login #root .box {
  position: static !important;
  transform: none !important;
  inset: auto !important;
  /* Not `auto`: in a centred flex column an auto margin eats the free space
     and pushes the help line to the very bottom of the page. */
  margin: 0 !important;
}

.skin-login #root .box-header { padding: 0 !important; }
.skin-login #root .box-header h1 { text-align: left !important; }

.skin-login #root .box-form .material_input,
.skin-login #root .box-form .MuiFormControl-root,
.skin-login #root .formBtn,
.skin-login #root .submitBtn {
  width: 100% !important; max-width: none !important;
}
.skin-login #root .formBtn { text-align: left !important; }
.skin-login #root .submitBtn { display: flex !important; }

/* ---- narrow windows ----
   Below a certain width the brand panel stops earning its space, so it goes
   and the card takes the logo back. */
@media (max-width: 900px) {
  .skin-login #root { grid-template-columns: 1fr; background: #0a5d99; }
  .skin-auth-aside { display: none; }
  .skin-login #root .box-header .logo { display: block; margin-bottom: 14px; }
  .skin-login #root .box-header .logo img { height: 34px; width: auto; }
}

/* ---------- 15. Dark mode ------------------------------------------------ */

body.dark { background: #0c1114; }
body.dark .rdt_Table,
body.dark div[role="table"] { background: var(--card); border-color: var(--line); }
body.dark .rdt_TableHead,
body.dark .rdt_TableHeadRow { background: #141b20 !important; border-color: var(--line) !important; }
body.dark .rdt_TableRow { background: var(--card) !important; border-color: var(--line) !important; color: var(--text) !important; }
body.dark .rdt_TableRow:hover { background: #1b242a !important; }
body.dark .rdt_TableCell { color: var(--text) !important; }
body.dark .rdt_TableCol[data-skin="entry"] { background: #14241d !important; color: #7fd3b3 !important; }
body.dark .rdt_TableCol[data-skin="cli"] { background: #241f12 !important; color: var(--clitx) !important; }
/* These need !important to beat the light-mode rules, which are themselves
   !important in order to beat react-data-table's own styled-components. */
body.dark .rdt_TableCell[data-skin="load"] { background: #141c24 !important; color: #c3d4e6 !important; }
body.dark .rdt_TableRow:hover .rdt_TableCell[data-skin="load"] { background: #18222c !important; }
body.dark .rdt_TableRow[data-confirmed="1"] .rdt_TableCell[data-skin="load"] { background: #1c3327 !important; color: #d6ecdd !important; }
body.dark .rdt_TableRow[data-confirmed="1"]:hover .rdt_TableCell[data-skin="load"] { background: #20402e !important; }
body.dark .rdt_TableCell[data-skin="cli"] { background: #241f12 !important; }
body.dark .rdt_Pagination { background: var(--card) !important; color: var(--muted) !important; border-color: var(--line) !important; }
body.dark .rdt_TableCell select,
body.dark .rdt_TableCell input[type="text"] { background: #1c262c; color: var(--text); border-color: #31414a; }
body.dark .skin-toolbar { background: var(--card); border-color: var(--line); }
body.dark .skin-toolbar select,
body.dark .skin-toolbar .pill { background: #1a232a; color: var(--text); border-color: #2a343a; }
body.dark.skin-on .MuiPaper-root,
body.dark.skin-on .MuiCard-root { background: var(--card) !important; color: var(--text) !important; border-color: var(--line) !important; }
body.dark.skin-on .MuiButton-outlined { background: #1a232a !important; color: var(--text) !important; border-color: #2a343a !important; }
body.dark.skin-on .MuiTypography-root { color: var(--text); }
body.dark.skin-on .MuiInputBase-input { color: var(--text) !important; }
body.dark .skin-modal-overlay { background: rgba(0,0,0,.62); }

/* ---------- dark mode: the surfaces the audit turned up -----------------
   Each of these paints its own light background in the portal's stylesheet,
   so on a dark canvas they came through as white slabs. Listed individually
   rather than blanket-overriding, so the deliberate colour chips on Status,
   City and Client keep their own fills. */

/* The panel behind the whole grid — the single largest offender. */
body.dark.skin-on .leadTableViewSec,
body.dark.skin-on .leadContent,
body.dark.skin-on .tableHeaderBlock { background: transparent !important; }

body.dark.skin-on .logout,
body.dark.skin-on .themebtn { background: #1a232a !important; color: var(--text) !important; border-color: #2a343a !important; }

/* The brand mark is a white tile by design in the reference; softened here so
   it does not glare against the dark rail. */
body.dark .bbadge { background: #1b3a30 !important; color: #7fd3b3 !important; }
body.dark .rolebadge.manager { background: #1c3327 !important; color: #7fd3b3 !important; }
body.dark .rolebadge.agent   { background: #222c30 !important; color: #b5c9c1 !important; }
body.dark .rolebadge.super   { background: #2a2340 !important; color: #cbb6f0 !important; }

/* Search field, filter selects, date inputs and the Clear button. */
body.dark.skin-on [data-skin-search] .MuiInputBase-root { background: #1c262c !important; border-color: #31414a !important; }
body.dark .skin-right select,
body.dark .skin-right input[type="date"],
body.dark .skin-right .skin-fclear,
body.dark .skin-areafilter select {
  background: #1a232a !important; color: var(--text) !important; border-color: #2a343a !important;
}
body.dark .skin-right .skin-colour { border-color: #2f5a49 !important; color: #7fd3b3 !important; }

/* Anything left inside the toolbar that still paints itself white. */
body.dark.skin-on .headerBlock input:not([type="checkbox"]),
body.dark.skin-on .headerBlock select { background: #1a232a !important; color: var(--text) !important; }

/* Injected cell controls, including the unlocked red-line inputs. */
body.dark .skin-cell-ctl { background: #1c262c !important; color: var(--text) !important; border-color: #31414a !important; }
body.dark .rdt_TableCell[data-skin-editable="1"] .skin-cell-ctl {
  background: #172a20 !important; border-color: #2f5340 !important; color: #d6ecdd !important;
}
body.dark .skin-cell-ctl::placeholder { color: var(--muted); opacity: 1; }
body.dark .skin-cell-ctl option { background: #1c262c; color: var(--text); }

/* ---------- The expanded lead panel ------------------------------------- */
/* Opened by the chevron beside App Date. It is the portal's own markup and was
   built for a light page, so on the dark canvas it came through as a stack of
   white slabs. */

.rdt_ExpanderRow {
  background: var(--canvas) !important;
  border-bottom: 1px solid var(--line);
}
.rdt_ExpanderRow .leadStatusBlock,
.rdt_ExpanderRow .leadStatusSection,
.rdt_ExpanderRow .leadViewDetailsQuestionBlock,
.rdt_ExpanderRow .leadViewDetailsLeftBlock,
.rdt_ExpanderRow .MuiPaper-root {
  background: var(--card) !important;
  border: 1px solid var(--line) !important;
  border-radius: 12px !important;
  box-shadow: none !important;
}
.rdt_ExpanderRow .leadViewDetails label { color: var(--muted) !important; font-weight: 600; }
.rdt_ExpanderRow .leadViewDetails span  { color: var(--text) !important; }

body.dark .rdt_ExpanderRow,
body.dark .rdt_ExpanderRow > div { background: #121a1f !important; }
/* These three carry a translucent near-white fill of their own, which on a
   dark canvas came through as pale grey slabs with unreadable labels. */
body.dark .rdt_ExpanderRow .leadStatusBlock,
body.dark .rdt_ExpanderRow .leadStatusSection,
body.dark .rdt_ExpanderRow .leadViewDetailsQuestionBlock,
body.dark .rdt_ExpanderRow .leadViewDetailsLeftBlock,
body.dark .rdt_ExpanderRow .MuiPaper-root { background: var(--card) !important; border-color: var(--line) !important; }
body.dark .rdt_ExpanderRow,
body.dark .rdt_ExpanderRow * { color: var(--text); }
body.dark .rdt_ExpanderRow label { color: var(--muted) !important; }
body.dark .rdt_ExpanderRow textarea,
body.dark .rdt_ExpanderRow input,
body.dark .rdt_ExpanderRow .MuiInputBase-root {
  background: #1c262c !important; color: var(--text) !important; border-color: #31414a !important;
}
body.dark .rdt_ExpanderRow .MuiSwitch-track { background: #46545c !important; }
/* The log-history entries carry their own light styling. */
body.dark .rdt_ExpanderRow a,
body.dark .rdt_ExpanderRow h1, body.dark .rdt_ExpanderRow h2,
body.dark .rdt_ExpanderRow h3, body.dark .rdt_ExpanderRow h4 { color: #7fd3b3 !important; }

/* The portal's compiled stylesheet hardcodes light surfaces throughout. This
   block is the safety net: it keeps every remaining MUI control legible in
   dark mode rather than leaving white-on-white. */
body.dark.skin-on .MuiButton-root:not(.MuiButton-contained) {
  background: #1a232a !important;
  color: var(--text) !important;
  border-color: #2a343a !important;
}
body.dark.skin-on input,
body.dark.skin-on textarea,
body.dark.skin-on select,
body.dark.skin-on .MuiInputBase-input,
body.dark.skin-on .MuiSelect-icon { color: var(--text) !important; }
body.dark.skin-on input::placeholder,
body.dark.skin-on textarea::placeholder { color: var(--muted) !important; opacity: 1; }
body.dark.skin-on .MuiInput-underline:before { border-bottom-color: #2a343a !important; }
body.dark.skin-on .MuiFormLabel-root,
body.dark.skin-on .MuiTypography-colorTextSecondary { color: var(--muted) !important; }
body.dark.skin-on .MuiTableCell-root { color: var(--text) !important; border-color: var(--line) !important; }
body.dark.skin-on .MuiDialog-paper,
body.dark.skin-on .MuiMenu-paper,
body.dark.skin-on .MuiPopover-paper { background: var(--card) !important; color: var(--text) !important; }
body.dark.skin-on .MuiMenuItem-root { color: var(--text) !important; }
body.dark.skin-on .MuiSvgIcon-root { color: var(--muted); }

/* Cells whose colour the portal sets inline (Status, Client, City) keep their
   own fill and text colour in dark mode — that colour coding is data, not
   decoration. Only the uncoloured controls get recoloured for the dark canvas.
   The adapter stamps data-skin-plain to tell the two apart. */
body.dark .rdt_TableCell select,
body.dark .rdt_TableCell input[type="text"] { background: transparent !important; }
body.dark .rdt_TableCell [data-skin-plain="1"] { color: var(--text) !important; }
body.dark .rdt_TableCell [data-skin-plain="1"] option { background: #1c262c; color: var(--text); }

/* MUI paints button text on an inner label span. */
body.dark.skin-on .MuiButton-root:not(.MuiButton-contained) .MuiButton-label { color: var(--text) !important; }
body.dark.skin-on .MuiIconButton-root { color: var(--muted) !important; }
body.dark.skin-on .MuiTypography-root:not([class*="color"]) { color: var(--text); }

/* ---------- 16. Small screens -------------------------------------------- */

@media (max-width: 1500px) {
  .skin-tab .t { display: none; }        /* labels give way to icons first */
  .skin-tab { padding: 7px 10px !important; }
}
@media (max-width: 860px) {
  .skin-topbar { padding: 6px 10px; gap: 8px; }
  .skin-logo img { height: 22px; }
  .skin-toolbar { padding: 8px 14px; }
  .userchip .uinfo { display: none; }
}


/* ---------- 17. Rail links, Age colours ---------------------------------- */

/* The rail items are anchors so they can be opened in their own tab; they must
   still look like the icon buttons they replace. */
/* The rail no longer exists; kept only so a stale cached bundle cannot leave
   an unstyled column on screen. */
#app .side { display: none !important; }

/* Age reads at a glance: green under 80, orange over. */
[data-skin-extra="age"][data-skin-val="Under 80"] .skin-cell-ctl {
  background: #e3f5e9 !important; border-color: #9ed3b4 !important; color: #14532d !important; font-weight: 700;
}
[data-skin-extra="age"][data-skin-val="Over 80"] .skin-cell-ctl {
  background: #fdeacd !important; border-color: #e8b063 !important; color: #7a4405 !important; font-weight: 700;
}
body.dark [data-skin-extra="age"][data-skin-val="Under 80"] .skin-cell-ctl {
  background: #16371f !important; border-color: #2f6b45 !important; color: #86e0a6 !important;
}
body.dark [data-skin-extra="age"][data-skin-val="Over 80"] .skin-cell-ctl {
  background: #3a2a10 !important; border-color: #8a5f1d !important; color: #f0b665 !important;
}

/* A date input needs room for dd-mm-yyyy plus the picker button, otherwise the
   value is clipped on confirmed rows where the column turns editable. */
.skin-on .rdt_TableCell input[type="date"].skin-cell-ctl { padding-right: 2px; }

/* ---------- 18. Status colours ------------------------------------------

   Status is styled exactly like the Age chip: a soft tinted fill, a matching
   border and bright text of the same hue — not a saturated block. Age is the
   reference because it already reads well against both canvases.

   Each rule is anchored on `body.skin-on` so it out-specifies the dark-mode
   rule that makes every in-cell control transparent; without that, only the
   statuses that happened to have their own dark override were being coloured.

   Shared shape, per-status hue:            fill      border    text
     Confirmed .......................... green tint
     QC-Confirmed / Scheduled / Visited .. deep green tint
     Cancel / Duplicate / DNC ............ red tint
     NA/VM ............................... yellow tint
     Over 80 ............................. orange tint
     Not Confirmed ....................... plain, so the rest stand out
*/

/* The portal paints some statuses via an inline background on a wrapper inside
   the cell; neutralise that so the control itself carries the colour. */
body.skin-on .rdt_TableCell[data-skin-status] div { background: transparent !important; }

body.skin-on .rdt_TableCell[data-skin-status] select {
  font-weight: 700 !important;
  font-size: 15px !important;
  padding: 4px 7px !important;
  border-radius: 6px !important;
  border-width: 1px !important;
  border-style: solid !important;
  text-align: left;
  -webkit-appearance: none;
  appearance: none;
}

/* ---- light ---- */
body.skin-on .rdt_TableCell[data-skin-status="Confirmed"] select {
  background: #e3f5e9 !important; border-color: #9ed3b4 !important; color: #14532d !important;
}
body.skin-on .rdt_TableCell[data-skin-status="QC - Confirmed"] select,
body.skin-on .rdt_TableCell[data-skin-status="Scheduled"] select,
body.skin-on .rdt_TableCell[data-skin-status="Appt Visited"] select {
  background: #d2ecdd !important; border-color: #6cb28d !important; color: #0c4a32 !important;
}
body.skin-on .rdt_TableCell[data-skin-status="Cancel"] select,
body.skin-on .rdt_TableCell[data-skin-status="Cancel-callback"] select,
body.skin-on .rdt_TableCell[data-skin-status="Customer Cancelled"] select,
body.skin-on .rdt_TableCell[data-skin-status="Duplicate"] select,
body.skin-on .rdt_TableCell[data-skin-status="DNC"] select {
  background: #fbe3e0 !important; border-color: #e09a91 !important; color: #7d1d13 !important;
}
body.skin-on .rdt_TableCell[data-skin-status="NA/VM - callback"] select {
  background: #fdf3cf !important; border-color: #e0c65e !important; color: #6b5406 !important;
}
body.skin-on .rdt_TableCell[data-skin-status="Over 80"] select {
  background: #fdeacd !important; border-color: #e8b063 !important; color: #7a4405 !important;
}
body.skin-on .rdt_TableCell[data-skin-status="Not Confirmed"] select,
body.skin-on .rdt_TableCell[data-skin-status=""] select {
  background: #ffffff !important; border-color: var(--line) !important; color: var(--text) !important;
}

/* ---- dark ---- */
body.dark.skin-on .rdt_TableCell[data-skin-status="Confirmed"] select {
  background: #16371f !important; border-color: #2f6b45 !important; color: #86e0a6 !important;
}
body.dark.skin-on .rdt_TableCell[data-skin-status="QC - Confirmed"] select,
body.dark.skin-on .rdt_TableCell[data-skin-status="Scheduled"] select,
body.dark.skin-on .rdt_TableCell[data-skin-status="Appt Visited"] select {
  background: #10301f !important; border-color: #2c6b47 !important; color: #6fd6a1 !important;
}
body.dark.skin-on .rdt_TableCell[data-skin-status="Cancel"] select,
body.dark.skin-on .rdt_TableCell[data-skin-status="Cancel-callback"] select,
body.dark.skin-on .rdt_TableCell[data-skin-status="Customer Cancelled"] select,
body.dark.skin-on .rdt_TableCell[data-skin-status="Duplicate"] select,
body.dark.skin-on .rdt_TableCell[data-skin-status="DNC"] select {
  background: #3a1512 !important; border-color: #8a3a30 !important; color: #f4a196 !important;
}
body.dark.skin-on .rdt_TableCell[data-skin-status="NA/VM - callback"] select {
  background: #3a3410 !important; border-color: #8a7a1d !important; color: #f0dd75 !important;
}
body.dark.skin-on .rdt_TableCell[data-skin-status="Over 80"] select {
  background: #3a2a10 !important; border-color: #8a5f1d !important; color: #f0b665 !important;
}
body.dark.skin-on .rdt_TableCell[data-skin-status="Not Confirmed"] select,
body.dark.skin-on .rdt_TableCell[data-skin-status=""] select {
  background: #1c262c !important; border-color: #31414a !important; color: var(--text) !important;
}

/* ---- the open dropdown -------------------------------------------------
   Chrome renders the list against the page, so without explicit colours it
   came out white on white the moment the control itself was recoloured. The
   same tints are used, so the list matches the rows. */
body.skin-on .rdt_TableCell select option { background: #ffffff !important; color: #182420 !important; font-weight: 600; }
body.skin-on .rdt_TableCell select option[value="Confirmed"] { background: #e3f5e9 !important; color: #14532d !important; }
body.skin-on .rdt_TableCell select option[value="QC - Confirmed"],
body.skin-on .rdt_TableCell select option[value="Scheduled"],
body.skin-on .rdt_TableCell select option[value="Appt Visited"] { background: #d2ecdd !important; color: #0c4a32 !important; }
body.skin-on .rdt_TableCell select option[value="Cancel"],
body.skin-on .rdt_TableCell select option[value="Customer Cancelled"],
body.skin-on .rdt_TableCell select option[value="Duplicate"],
body.skin-on .rdt_TableCell select option[value="DNC"] { background: #fbe3e0 !important; color: #7d1d13 !important; }
body.skin-on .rdt_TableCell select option[value="NA/VM - callback"] { background: #fdf3cf !important; color: #6b5406 !important; }
body.skin-on .rdt_TableCell select option[value="Over 80"] { background: #fdeacd !important; color: #7a4405 !important; }

body.dark.skin-on .rdt_TableCell select option { background: #1c262c !important; color: var(--text) !important; }
body.dark.skin-on .rdt_TableCell select option[value="Confirmed"] { background: #16371f !important; color: #86e0a6 !important; }
body.dark.skin-on .rdt_TableCell select option[value="QC - Confirmed"],
body.dark.skin-on .rdt_TableCell select option[value="Scheduled"],
body.dark.skin-on .rdt_TableCell select option[value="Appt Visited"] { background: #10301f !important; color: #6fd6a1 !important; }
body.dark.skin-on .rdt_TableCell select option[value="Cancel"],
body.dark.skin-on .rdt_TableCell select option[value="Customer Cancelled"],
body.dark.skin-on .rdt_TableCell select option[value="Duplicate"],
body.dark.skin-on .rdt_TableCell select option[value="DNC"] { background: #3a1512 !important; color: #f4a196 !important; }
body.dark.skin-on .rdt_TableCell select option[value="NA/VM - callback"] { background: #3a3410 !important; color: #f0dd75 !important; }
body.dark.skin-on .rdt_TableCell select option[value="Over 80"] { background: #3a2a10 !important; color: #f0b665 !important; }

/* Age keeps the same shape, so the two columns read as one system. */
[data-skin-extra="age"] .skin-cell-ctl { font-weight: 700; }
[data-skin-extra="age"] .skin-cell-ctl option { background: #fff !important; color: #182420 !important; }
body.dark [data-skin-extra="age"] .skin-cell-ctl option { background: #1c262c !important; color: var(--text) !important; }

/* ---- Colour Area on a confirmed row -------------------------------------
   Once City becomes an input the portal's coloured chip is gone, so the
   adapter hands the area's hex down as --area with a readable foreground in
   --area-text. The input is painted with it and keeps the chip's shape, so a
   confirmed row still reads area-wise at a glance. */
body.skin-on .rdt_TableCell[data-skin-area] .skin-cell-ctl {
  background: var(--area) !important;
  color: var(--area-text) !important;
  border-color: color-mix(in srgb, var(--area) 70%, #000) !important;
  font-weight: 700 !important;
  text-align: center;
}
body.skin-on .rdt_TableCell[data-skin-area] .skin-cell-ctl::selection {
  background: rgba(255,255,255,.35);
}
body.skin-on .rdt_TableCell[data-skin-area] .skin-cell-ctl:focus {
  outline: 2px solid var(--focus);
  outline-offset: -1px;
}

/* A city with no area colour: the portal draws it in near-black, which is
   invisible against the dark canvas. */
body.dark .rdt_TableCell[data-skin-plaincity="1"],
body.dark .rdt_TableCell[data-skin-plaincity="1"] * { color: var(--text) !important; }

/* ---------- 19. Dashboard -------------------------------------------------
   The portal's own dashboard markup stays mounted and is hidden, not removed,
   so its "View RealTime Panel" control keeps its handler; the button drawn in
   the header simply clicks it. Everything visible below is the overlay's. */

/* Scoped to the dashboard route by a body class, NOT by the presence of
   .skin-dash. The earlier version keyed on `.bodyContent > *:not(.skin-dash)`
   with no route condition, which hid the contents of every other page in the
   app — DNC, Clients, Centres, Users all rendered blank. The class is set and
   cleared in ensureDashboard(), so exactly one page can ever be affected. */
body.skin-on.skin-dashboard .bodyContent > *:not(.skin-dash) { display: none !important; }
body.skin-on.skin-dashboard .skin-dash ~ * { display: none !important; }

.skin-dash {
  display: block !important;
  padding: 18px 20px 32px;
  --donut-track: #e6ebe8;
}
body.dark.skin-on .skin-dash { --donut-track: #1e2a31; }

.skin-dash-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 16px;
}
.skin-dash-title h2 { margin: 0; font-size: 20px; font-weight: 700; color: var(--text); }
.skin-dash-title p  { margin: 3px 0 0; font-size: 12.5px; color: var(--muted); }

.skin-dash-controls { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.skin-preset {
  border: 1px solid var(--line); background: var(--card); color: var(--text);
  border-radius: 7px; padding: 6px 11px; font-size: 12.5px; font-weight: 600;
  cursor: pointer; transition: .15s;
}
.skin-preset:hover { border-color: var(--green); color: var(--green); }
/* --brand is not a token in this design system; --green is. The active
   preset was resolving to a transparent background with white text, which is
   invisible on the light canvas. */
.skin-preset.on { background: var(--green); border-color: var(--green); color: #fff; }
body.dark.skin-on .skin-preset:hover { border-color: #6fd6a1; color: #6fd6a1; }
body.dark.skin-on .skin-preset.on { background: var(--brand); border-color: var(--brand); color: #fff; }
.skin-dash-controls input[type="date"] {
  border: 1px solid var(--line); background: var(--card); color: var(--text);
  border-radius: 7px; padding: 5px 8px; font-size: 12.5px;
}

/* ---- KPI row ---- */
.skin-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin-bottom: 14px; }
.skin-kpi {
  background: var(--card); border: 1px solid var(--line); border-left: 4px solid var(--line);
  border-radius: 11px; padding: 14px 16px;
}
.skin-kpi .v { font-size: 30px; font-weight: 700; line-height: 1.05; color: var(--text); }
.skin-kpi .l { font-size: 12.5px; color: var(--muted); margin-top: 3px; font-weight: 600; }
.skin-kpi .n { font-size: 11.5px; color: var(--muted); margin-top: 5px; opacity: .85; }
.skin-kpi.good { border-left-color: #2f9e6a; } .skin-kpi.good .v { color: #2f9e6a; }
.skin-kpi.info { border-left-color: #2f7fd0; } .skin-kpi.info .v { color: #2f7fd0; }
.skin-kpi.warn { border-left-color: #e08a2e; } .skin-kpi.warn .v { color: #e08a2e; }
.skin-kpi.muted { border-left-color: var(--line); }
body.dark.skin-on .skin-kpi.good .v { color: #6fd6a1; }
body.dark.skin-on .skin-kpi.info .v { color: #7db6f0; }
body.dark.skin-on .skin-kpi.warn .v { color: #f0b665; }

/* ---- cards ---- */
.skin-dash-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; align-items: start; }
.skin-card {
  background: var(--card); border: 1px solid var(--line); border-radius: 12px;
  padding: 15px 16px; grid-column: span 2; min-width: 0;
}
.skin-card.wide { grid-column: span 2; }
.skin-card h3 { margin: 0 0 12px; font-size: 13px; font-weight: 700; color: var(--text); letter-spacing: .01em; }
.skin-note { margin: 10px 0 0; font-size: 12px; color: var(--muted); }

.skin-chart-row { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.skin-chart-col { display: flex; flex-direction: column; align-items: center; gap: 10px; }
/* Only the row layout wants the legend to flex. In the column layout the
   main axis is vertical, so a flex-basis of 200px was reserving 200px of
   HEIGHT for the legend and stretching the card well past its content. */
.skin-chart-row .skin-legend { flex: 1 1 200px; min-width: 190px; }
.skin-chart-col .skin-legend { flex: 0 0 auto; width: 100%; }

.skin-donut { flex: 0 0 auto; }
.skin-donut .skin-slice { transition: opacity .15s; }
.skin-donut:hover .skin-slice { opacity: .45; }
.skin-donut .skin-slice:hover { opacity: 1; }
.skin-donut-n { font-size: 30px; font-weight: 700; fill: var(--text); }
.skin-donut-l { font-size: 11px; fill: var(--muted); }

.skin-legend { list-style: none; margin: 0; padding: 0; }
.skin-legend li {
  display: grid; grid-template-columns: 12px 1fr auto auto; align-items: center;
  gap: 8px; padding: 4px 0; font-size: 12.5px; color: var(--text);
  border-bottom: 1px solid var(--line);
}
.skin-legend li:last-child { border-bottom: 0; }
.skin-legend .dot { width: 10px; height: 10px; border-radius: 3px; }
.skin-legend .k { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.skin-legend .n { font-weight: 700; }
.skin-legend .p { color: var(--muted); min-width: 34px; text-align: right; }

.skin-bars { list-style: none; margin: 0; padding: 0; }
.skin-bars li {
  display: grid; grid-template-columns: 108px 1fr 46px; align-items: center;
  gap: 10px; padding: 4px 0; font-size: 12.5px; color: var(--text);
}
.skin-bars .lbl { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.skin-bars .track { background: var(--donut-track); border-radius: 5px; height: 14px; overflow: hidden; }
.skin-bars .fill { display: block; height: 100%; border-radius: 5px; }
.skin-bars .val { font-weight: 700; text-align: right; }

/* The count and the label sit outside the bar, not on top of it. When they
   were inside, a stage with a value of zero drew no bar and its white number
   was left on the light track — invisible. Now contrast never depends on how
   far the bar reaches. */
.skin-funnel .rail {
  display: grid; grid-template-columns: 48px 1fr; align-items: center;
  gap: 10px; margin-bottom: 10px;
}
.skin-funnel .rail b {
  font-size: 15px; font-weight: 700; color: var(--text); text-align: right;
}
.skin-funnel .rail .bar {
  position: relative; height: 22px; background: var(--donut-track);
  border-radius: 6px; overflow: hidden;
}
.skin-funnel .rail span { position: absolute; inset: 0 auto 0 0; background: #7b8b95; border-radius: 6px; }
.skin-funnel .rail span.elig   { background: #2f7fd0; }
.skin-funnel .rail span.pushed { background: #2f9e6a; }
.skin-funnel .rail span.wait   { background: #e08a2e; }
.skin-funnel .rail i {
  display: block; font-style: normal; font-size: 11.5px;
  color: var(--muted); margin-top: 3px;
}

.skin-dash-empty, .skin-dash-loading {
  background: var(--card); border: 1px solid var(--line); border-radius: 12px;
  padding: 18px; font-size: 13px; color: var(--muted);
}

@media (max-width: 1200px) {
  .skin-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .skin-dash-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---------- 20. Top navigation and brand ---------------------------------
   The rail cost 46px of width permanently and the title strip 56px of height,
   on a page whose grid is 1,800px wide and whose every pixel is data. Both
   are replaced by this one bar. The active tab names the page, so no heading
   repeats it.

   Brand colours are taken from the 247 Support Services logo: #0076c9 for the
   blue and #221e1b for the wordmark. Only the chrome is rebranded — status,
   age and area colours are data, not decoration, and are left alone. */

body.skin-on {
  --brand: #0076c9;
  --brand-dk: #005b9e;
  --brand-lt: #4aa3e0;
  --brand-ink: #0d1b24;
  --focus: #0076c9;

  /* The chrome in this skin is written against --green, so redefining it here
     rebrands every accent — buttons, checkboxes, focus rings, the toolbar
     controls — in one place. Status, Age and Area colours are hardcoded hexes
     precisely because they are data rather than decoration, so none of them
     move. */
  --green: #0076c9;
  --green-dk: #005b9e;
}
body.dark.skin-on {
  --brand: #2f95dc;
  --brand-dk: #1f7ab8;
  --brand-ink: #0b141b;
  --green: #2f95dc;
  --green-dk: #7dc0ee;
}

/* Three columns rather than a flex row, so the tabs are centred on the PAGE
   rather than centred in whatever space the logo and the user block happen to
   leave. The two 1fr columns are equal by definition, which puts the auto
   column dead centre no matter how long the user's name is. */
.skin-topbar {
  display: grid;
  /* minmax(0, 1fr), not 1fr. A plain `fr` will not shrink a column below its
     own content, so once the tabs filled the bar the wide user block held the
     right column open while the left column gave way — and the tabs, which
     are supposed to be centred on the page, drifted off centre. Allowing both
     sides to shrink to nothing keeps them equal by definition, which is what
     actually centres the middle. */
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 14px;
  padding: 0 16px;
  height: 56px;
  flex: 0 0 56px;
  background: var(--card);
  border-bottom: 1px solid var(--line);
  position: relative;
  z-index: 40;
}
body.dark.skin-on .skin-topbar { background: #131c23; border-bottom-color: #223038; }

.skin-logo { display: flex; align-items: center; justify-self: start; text-decoration: none; }
.skin-logo img { height: 30px; width: auto; display: block; }

.skin-tabs {
  display: flex;
  align-items: center;
  gap: 2px;
  justify-self: center;
  min-width: 0;
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}
.skin-tabs::-webkit-scrollbar { height: 0; }

.skin-tab {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 12px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
  border: 1px solid transparent;
  transition: background .12s, color .12s, border-color .12s;
}
.skin-tab .i { font-size: 16px; line-height: 1; }
.skin-tab:hover { background: rgba(0,118,201,.08); color: var(--brand); }
.skin-tab.on {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}
body.dark.skin-on .skin-tab { color: #9fb0bb; }
body.dark.skin-on .skin-tab:hover { background: rgba(47,149,220,.14); color: #7dc0ee; }
body.dark.skin-on .skin-tab.on { background: var(--brand); border-color: var(--brand); color: #fff; }

.skin-topbar .userchip { justify-self: end; gap: 10px; }
.skin-topbar .userchip .uav {
  background: var(--brand); color: #fff; text-decoration: none;
  width: 32px; height: 32px; border-radius: 50%;
  display: grid; place-items: center; font-size: 12px; font-weight: 700;
}
.skin-topbar .userchip .uinfo b { font-size: 13px; color: var(--text); }

/* The role badge and the accent controls follow the logo, not the old green. */
body.skin-on .rolebadge.manager { background: rgba(0,118,201,.12); color: var(--brand-dk); }
body.dark.skin-on .rolebadge.manager { background: rgba(47,149,220,.18); color: #7dc0ee; }

body.skin-on .skin-preset:hover { border-color: var(--brand); color: var(--brand); }
body.skin-on .skin-preset.on { background: var(--brand); border-color: var(--brand); color: #fff; }
body.dark.skin-on .skin-preset:hover { border-color: var(--brand); color: #7dc0ee; }
body.dark.skin-on .skin-preset.on { background: var(--brand); border-color: var(--brand); color: #fff; }

body.skin-on .skin-cell-ctl:focus,
body.skin-on .rdt_TableCell select:focus,
body.skin-on .rdt_TableCell input:focus { outline-color: var(--brand) !important; }

/* The body had no padding to start with; with the rail gone the grid should
   sit flush to the window edge so nothing is spent on margin. */
#app.skin-topnav .body { padding: 0; }

/* ---------- 21. Dialogs and every native dropdown ------------------------
   The portal's dialogs (Add User, Add Client, Add Lead, Add Centre) were
   never restyled, so on the dark canvas they arrived as a near-black sheet
   with a near-black title on it — the "Add New User" heading was legible only
   because of its shadow. And every native <select> in the app inherits the
   browser's own popup colours unless both the control and its <option>
   children are given them, which is why some lists read white-on-white.

   Both are fixed here globally rather than per screen, so a section nobody
   has designed yet still opens something readable. */

body.skin-on .MuiDialog-paper,
body.skin-on .MuiPopover-paper,
body.skin-on .MuiMenu-paper {
  background: var(--card) !important;
  color: var(--text) !important;
  border: 1px solid var(--line) !important;
  border-radius: 14px !important;
  box-shadow: 0 24px 70px rgba(0,0,0,.28) !important;
}
body.dark.skin-on .MuiDialog-paper,
body.dark.skin-on .MuiPopover-paper,
body.dark.skin-on .MuiMenu-paper {
  background: #17222a !important;
  border-color: #2a3843 !important;
  box-shadow: 0 24px 70px rgba(0,0,0,.55) !important;
}

body.skin-on .MuiDialogTitle-root,
body.skin-on .MuiDialogTitle-root * {
  color: var(--text) !important;
  font-weight: 700 !important;
}
body.skin-on .MuiDialogContent-root,
body.skin-on .MuiDialogContent-root .MuiTypography-root { color: var(--text) !important; }
body.skin-on .MuiDialog-paper .MuiFormLabel-root,
body.skin-on .MuiDialog-paper .MuiInputLabel-root { color: var(--muted) !important; }
body.skin-on .MuiDialog-paper .MuiFormLabel-root.Mui-focused { color: var(--brand) !important; }
body.skin-on .MuiDialog-paper .MuiOutlinedInput-notchedOutline { border-color: var(--line) !important; }
body.skin-on .MuiDialog-paper .Mui-focused .MuiOutlinedInput-notchedOutline { border-color: var(--brand) !important; }
body.skin-on .MuiDialog-paper input,
body.skin-on .MuiDialog-paper select,
body.skin-on .MuiDialog-paper textarea { color: var(--text) !important; }
body.dark.skin-on .MuiDialog-paper input,
body.dark.skin-on .MuiDialog-paper select,
body.dark.skin-on .MuiDialog-paper textarea { background: #1c262c !important; }

/* Section headings inside the dialogs ("User Details", "Other Details"). */
body.skin-on .MuiDialog-paper h6,
body.skin-on .MuiDialog-paper .MuiTypography-subtitle1,
body.skin-on .MuiDialog-paper .MuiTypography-subtitle2 { color: var(--muted) !important; }

/* Dialog buttons follow the brand. */
body.skin-on .MuiDialog-paper .MuiButton-contained {
  background: var(--brand) !important; color: #fff !important;
}
body.skin-on .MuiDialog-paper .MuiButton-contained:hover { background: var(--brand-dk) !important; }

/* ---- native selects, everywhere -----------------------------------------
   The rule has to name `option` as well as the control. Chrome draws the open
   list from the option's own colours, so styling only the <select> leaves the
   popup at the browser default — which is white, on a page that is not. */
body.skin-on select { color: var(--text); }
body.skin-on select option,
body.skin-on select optgroup {
  background: #ffffff;
  color: #182420;
}
body.dark.skin-on select option,
body.dark.skin-on select optgroup {
  background: #1c262c;
  color: var(--text);
}
body.dark.skin-on select option:checked,
body.dark.skin-on select option:hover { background: #24323a; }

/* The pagination's own rows-per-page list sits outside .rdt_TableCell, so it
   needs the same treatment explicitly. */
body.dark.skin-on .rdt_Pagination select { background: #1c262c !important; color: var(--text) !important; }
body.dark.skin-on .rdt_Pagination select option { background: #1c262c; color: var(--text); }

/* A lead with no client: the portal draws the control's text white for the
   coloured chip it is not going to render, leaving "None" invisible on the
   light canvas. Only the cells with nothing behind them are corrected, so the
   CC and SH chips keep their white-on-colour. */
body.skin-on .rdt_TableCell[data-skin-plainclient="1"] select,
body.skin-on .rdt_TableCell[data-skin-plainclient="1"] select option {
  color: var(--text) !important;
}

/* ---------- 22. Users: edit and deactivate -------------------------------- */

.skin-useracts { display: flex; align-items: center; gap: 6px; }
.skin-ubtn {
  border: 1px solid var(--line); background: var(--card); color: var(--text);
  border-radius: 6px; padding: 4px 9px; font-size: 12px; font-weight: 600;
  cursor: pointer; white-space: nowrap; transition: .12s;
}
.skin-ubtn:hover { border-color: var(--brand); color: var(--brand); }
.skin-ubtn.off:hover { border-color: var(--danger); color: var(--danger); }
.skin-ubtn.on { border-color: #2f9e6a; color: #2f9e6a; }
body.dark.skin-on .skin-ubtn { background: #1c262c; border-color: #31414a; }

/* A deactivated account stays visible — that is the point of not deleting it —
   but must not read as a working one. */
.rdt_TableRow[data-skin-inactive="1"] { opacity: .55; }
.rdt_TableRow[data-skin-inactive="1"] .skin-ubtn { opacity: 1; }

/* ---- modal footer and forms ---- */
.skin-modal-ft {
  display: flex; justify-content: flex-end; gap: 8px;
  padding: 12px 16px; border-top: 1px solid var(--line);
}
.skin-mbtn {
  border-radius: 8px; padding: 7px 14px; font-size: 13px; font-weight: 600;
  cursor: pointer; border: 1px solid var(--line); background: var(--card); color: var(--text);
}
.skin-mbtn:hover { border-color: var(--brand); color: var(--brand); }
.skin-mbtn.primary { background: var(--brand); border-color: var(--brand); color: #fff; }
.skin-mbtn.primary:hover { background: var(--brand-dk); color: #fff; }
.skin-mbtn.danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.skin-mbtn.danger:hover { filter: brightness(.92); color: #fff; }
.skin-mbtn:disabled { opacity: .55; cursor: default; }
body.dark.skin-on .skin-mbtn { background: #1c262c; border-color: #31414a; }
body.dark.skin-on .skin-mbtn.primary { background: var(--brand); border-color: var(--brand); }
body.dark.skin-on .skin-mbtn.danger { background: var(--danger); border-color: var(--danger); }

.skin-form { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.skin-form label {
  display: flex; flex-direction: column; gap: 4px;
  font-size: 11.5px; font-weight: 600; color: var(--muted);
}
.skin-form input, .skin-form select {
  border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px;
  font-size: 13px; background: var(--card); color: var(--text); font-weight: 500;
}
.skin-form input:focus, .skin-form select:focus {
  outline: 2px solid var(--brand); outline-offset: -1px;
}
body.dark.skin-on .skin-form input,
body.dark.skin-on .skin-form select { background: #1c262c; border-color: #31414a; }
.skin-modal-body .skin-note { margin: 12px 0 0; font-size: 11.5px; color: var(--muted); }

/* ---------- 23. Notes in the Comments column ------------------------------
   The Comments box shows the newest note from the lead's thread; the count
   beside it opens the whole history. */

.skin-notecount {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  min-width: 18px; height: 18px; padding: 0 5px;
  border: 1px solid var(--line); border-radius: 9px;
  background: var(--chip); color: var(--muted);
  font-size: 10.5px; font-weight: 700; line-height: 16px;
  cursor: pointer; z-index: 2;
}
.skin-notecount:hover { border-color: var(--brand); color: var(--brand); }
body.dark.skin-on .skin-notecount { background: #24323a; border-color: #31414a; color: #9fb0bb; }
body.dark.skin-on .skin-notecount:hover { border-color: var(--brand); color: #7dc0ee; }

/* Room for the badge so it never sits on top of the text. */
[data-skin-extra="comments"] .skin-cell-ctl { padding-right: 26px !important; }

.skin-thread { list-style: none; margin: 0; padding: 0; }
.skin-thread li { padding: 9px 0; border-bottom: 1px solid var(--line); }
.skin-thread li:last-child { border-bottom: 0; }
.skin-thread .hd {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 10px; margin-bottom: 3px;
}
.skin-thread .hd b { font-size: 12.5px; color: var(--text); }
.skin-thread .hd span { font-size: 11.5px; color: var(--muted); white-space: nowrap; }
.skin-thread .tx { font-size: 13px; color: var(--text); white-space: pre-wrap; word-break: break-word; }

/* ---------- 24. The other four grids: DNC, Clients, Centres, Users --------
   These share the react-data-table component with the Lead Queue but were
   never designed: every column got an identical share of the width, so a
   phone number was given the same room as a full street address, and on
   Clients twelve columns each truncated equally badly.

   Sized from `data-skin-gcol`, which the adapter stamps from each column's
   own heading. Deliberately a different attribute from the queue's
   `data-skin-col`: nothing here can reach the Lead Queue, and the queue's
   rules cannot reach these pages.
   ------------------------------------------------------------------------ */

/* The queue is ~1820px wide and holds the table to that floor. On a four
   column page that floor is what stretched the columns in the first place,
   so each of these pages gets its own, measured from the widths below. */
body.skin-on[data-skin-grid] .rdt_Table,
body.skin-on[data-skin-grid] div[role="table"],
body.skin-on[data-skin-grid] .rdt_TableHead,
body.skin-on[data-skin-grid] .rdt_TableHeadRow,
body.skin-on[data-skin-grid] .rdt_TableBody,
body.skin-on[data-skin-grid] .rdt_TableRow { min-width: 0; }

body.skin-on[data-skin-grid="dnc"] .rdt_Table,
body.skin-on[data-skin-grid="dnc"] .rdt_TableHead,
body.skin-on[data-skin-grid="dnc"] .rdt_TableHeadRow,
body.skin-on[data-skin-grid="dnc"] .rdt_TableBody,
body.skin-on[data-skin-grid="dnc"] .rdt_TableRow { min-width: 760px; }

body.skin-on[data-skin-grid="clients"] .rdt_Table,
body.skin-on[data-skin-grid="clients"] .rdt_TableHead,
body.skin-on[data-skin-grid="clients"] .rdt_TableHeadRow,
body.skin-on[data-skin-grid="clients"] .rdt_TableBody,
body.skin-on[data-skin-grid="clients"] .rdt_TableRow { min-width: 1780px; }

body.skin-on[data-skin-grid="centres"] .rdt_Table,
body.skin-on[data-skin-grid="centres"] .rdt_TableHead,
body.skin-on[data-skin-grid="centres"] .rdt_TableHeadRow,
body.skin-on[data-skin-grid="centres"] .rdt_TableBody,
body.skin-on[data-skin-grid="centres"] .rdt_TableRow { min-width: 1360px; }

body.skin-on[data-skin-grid="users"] .rdt_Table,
body.skin-on[data-skin-grid="users"] .rdt_TableHead,
body.skin-on[data-skin-grid="users"] .rdt_TableHeadRow,
body.skin-on[data-skin-grid="users"] .rdt_TableBody,
body.skin-on[data-skin-grid="users"] .rdt_TableRow { min-width: 1320px; }

/* ---- column widths -------------------------------------------------------
   Fixed unless marked flex. The flex column on each page is the one holding
   free text — Reason, Address, Payment Details — so it absorbs the slack
   instead of every column absorbing a twelfth of it. */

.skin-on [data-skin-gcol] { flex: 0 0 auto !important; }

/* DNC */
body[data-skin-grid="dnc"] [data-skin-gcol="phone-number"] { min-width: 190px !important; max-width: 190px !important; }
body[data-skin-grid="dnc"] [data-skin-gcol="client-name"]  { min-width: 160px !important; max-width: 160px !important; }
body[data-skin-grid="dnc"] [data-skin-gcol="reason"]       { flex: 1 1 240px !important; min-width: 220px !important; max-width: none !important; }
body[data-skin-grid="dnc"] [data-skin-gcol="actions"]      { min-width: 130px !important; max-width: 130px !important; }

/* Clients */
body[data-skin-grid="clients"] [data-skin-gcol="company-name"]    { min-width: 150px !important; max-width: 150px !important; }
body[data-skin-grid="clients"] [data-skin-gcol="owner-name"]      { min-width: 150px !important; max-width: 150px !important; }
body[data-skin-grid="clients"] [data-skin-gcol="managers-name"]   { min-width: 150px !important; max-width: 150px !important; }
body[data-skin-grid="clients"] [data-skin-gcol="phone"]           { min-width: 140px !important; max-width: 140px !important; }
body[data-skin-grid="clients"] [data-skin-gcol="email"]           { min-width: 220px !important; max-width: 220px !important; }
body[data-skin-grid="clients"] [data-skin-gcol="address"]         { flex: 1 1 240px !important; min-width: 220px !important; max-width: none !important; }
body[data-skin-grid="clients"] [data-skin-gcol="appt-met"]        { min-width: 100px !important; max-width: 100px !important; }
body[data-skin-grid="clients"] [data-skin-gcol="sold-installed"]  { min-width: 120px !important; max-width: 120px !important; }
body[data-skin-grid="clients"] [data-skin-gcol="payment-terms"]   { min-width: 120px !important; max-width: 120px !important; }
body[data-skin-grid="clients"] [data-skin-gcol="payment-gateway"] { min-width: 140px !important; max-width: 140px !important; }
body[data-skin-grid="clients"] [data-skin-gcol="payment-details"] { min-width: 140px !important; max-width: 140px !important; }
body[data-skin-grid="clients"] [data-skin-gcol="created-on"]      { min-width: 110px !important; max-width: 110px !important; }

/* Centres */
body[data-skin-grid="centres"] [data-skin-gcol="centre-name"]     { min-width: 150px !important; max-width: 150px !important; }
body[data-skin-grid="centres"] [data-skin-gcol="location"]        { min-width: 140px !important; max-width: 140px !important; }
body[data-skin-grid="centres"] [data-skin-gcol="centre-owner"]    { min-width: 150px !important; max-width: 150px !important; }
body[data-skin-grid="centres"] [data-skin-gcol="service"]         { min-width: 130px !important; max-width: 130px !important; }
body[data-skin-grid="centres"] [data-skin-gcol="no-of-agents"]    { min-width: 110px !important; max-width: 110px !important; }
body[data-skin-grid="centres"] [data-skin-gcol="app-met"]         { min-width: 100px !important; max-width: 100px !important; }
body[data-skin-grid="centres"] [data-skin-gcol="sold-installed"]  { min-width: 120px !important; max-width: 120px !important; }
body[data-skin-grid="centres"] [data-skin-gcol="mode-of-payment"] { min-width: 150px !important; max-width: 150px !important; }
body[data-skin-grid="centres"] [data-skin-gcol="payment-details"] { flex: 1 1 220px !important; min-width: 200px !important; max-width: none !important; }
body[data-skin-grid="centres"] [data-skin-gcol="created-on"]      { min-width: 110px !important; max-width: 110px !important; }

/* Users & Roles */
body[data-skin-grid="users"] [data-skin-gcol="agent-name"]  { min-width: 180px !important; max-width: 180px !important; }
body[data-skin-grid="users"] [data-skin-gcol="email"]       { flex: 1 1 260px !important; min-width: 240px !important; max-width: none !important; }
body[data-skin-grid="users"] [data-skin-gcol="phone"]       { min-width: 170px !important; max-width: 170px !important; }
body[data-skin-grid="users"] [data-skin-gcol="gender"]      { min-width: 90px  !important; max-width: 90px  !important; }
body[data-skin-grid="users"] [data-skin-gcol="role"]        { min-width: 120px !important; max-width: 120px !important; }
body[data-skin-grid="users"] [data-skin-gcol="centre-name"] { min-width: 200px !important; max-width: 200px !important; }
body[data-skin-grid="users"] [data-skin-gcol="created-on"]  { min-width: 150px !important; max-width: 150px !important; }
body[data-skin-grid="users"] [data-skin-gcol="actions"]     { min-width: 150px !important; max-width: 150px !important; }

/* ---- how each kind of value reads --------------------------------------
   A phone number, a count and a currency amount are all "numbers" but want
   different treatment: a phone is read left to right, a count and an amount
   are compared down the column, so those two are right-aligned. Every one of
   them gets tabular figures, so the digits line up rather than drifting. */

.skin-on [data-skin-gkind="num"],
.skin-on [data-skin-gkind="money"],
.skin-on [data-skin-gkind="date"] { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }

.skin-on .rdt_TableCell[data-skin-gkind="money"] { justify-content: flex-end; text-align: right; }
.skin-on .rdt_TableCol[data-skin-gkind="money"]  { justify-content: flex-end; text-align: right; }

/* Dates are context, not the point of the row, so they sit back. */
.skin-on .rdt_TableCell[data-skin-gkind="date"] { color: var(--muted); font-size: 14px; }

/* The name is what the eye looks for when scanning, so it leads. */
.skin-on .rdt_TableCell[data-skin-gkind="strong"] { font-weight: 600; color: var(--text); }

/* Actions sit as a group, centred, and never wrap onto a second line. */
.skin-on .rdt_TableCell[data-skin-gkind="act"] {
  display: flex; align-items: center; gap: 6px;
  white-space: nowrap; overflow: visible;
}
.skin-on .rdt_TableCol[data-skin-gkind="act"] { justify-content: flex-start; }

/* ---- role chips ----------------------------------------------------------
   A role was bare lower-case text in a column of bare lower-case text. As a
   chip it reads at a glance, and it matches how Status already reads on the
   Lead Queue. Anything unrecognised keeps the neutral chip rather than
   disappearing. */

/* The original text is only hidden once a role has actually been read off the
   cell. If the stamp is missing for any reason the plain text stays visible,
   so a change to how the column renders can never blank the column out. */
body[data-skin-grid="users"] .rdt_TableCell[data-skin-role]:not([data-skin-role=""]) {
  font-size: 0;
  overflow: visible;
}
body[data-skin-grid="users"] .rdt_TableCell[data-skin-role]:not([data-skin-role=""])::before {
  content: attr(data-skin-role);
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--chip);
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .3px;
  text-transform: uppercase;
  white-space: nowrap;
}
/* Full access reads as the strongest chip; the rest step down from there. */
body[data-skin-grid="users"] .rdt_TableCell[data-skin-role="superadmin"]:not([data-skin-role=""])::before {
  content: 'SUPER ADMIN'; background: #e8f1fa; border-color: #b6d4ec; color: #14547f;
}
body[data-skin-grid="users"] .rdt_TableCell[data-skin-role="admin"]:not([data-skin-role=""])::before {
  background: #e8f1fa; border-color: #b6d4ec; color: #14547f;
}
body[data-skin-grid="users"] .rdt_TableCell[data-skin-role="manager"]:not([data-skin-role=""])::before {
  background: #eaf3ec; border-color: #bcdcc4; color: #2c6b3d;
}
body[data-skin-grid="users"] .rdt_TableCell[data-skin-role="tl"]:not([data-skin-role=""])::before {
  content: 'TEAM LEAD'; background: #fbf1e2; border-color: #e6cfa6; color: #85601c;
}
body[data-skin-grid="users"] .rdt_TableCell[data-skin-role="callback"]:not([data-skin-role=""])::before {
  background: #f3eefa; border-color: #d6c6ec; color: #5c3f8c;
}

body.dark[data-skin-grid="users"] .rdt_TableCell[data-skin-role]:not([data-skin-role=""])::before {
  background: #222c30; border-color: #31414a; color: #9fb0bb;
}
body.dark[data-skin-grid="users"] .rdt_TableCell[data-skin-role="superadmin"]:not([data-skin-role=""])::before,
body.dark[data-skin-grid="users"] .rdt_TableCell[data-skin-role="admin"]:not([data-skin-role=""])::before {
  background: #14273a; border-color: #2a4a68; color: #8fc4ee;
}
body.dark[data-skin-grid="users"] .rdt_TableCell[data-skin-role="manager"]:not([data-skin-role=""])::before {
  background: #162c1f; border-color: #2c4c37; color: #8fd0a4;
}
body.dark[data-skin-grid="users"] .rdt_TableCell[data-skin-role="tl"]:not([data-skin-role=""])::before {
  background: #2e2716; border-color: #4d4128; color: #dcbc76;
}
body.dark[data-skin-grid="users"] .rdt_TableCell[data-skin-role="callback"]:not([data-skin-role=""])::before {
  background: #251d33; border-color: #3f3255; color: #bda6e0;
}

/* ---- a deactivated person ------------------------------------------------
   Greyed rather than hidden: the row still has to be findable, and the state
   has to be obvious enough that nobody wonders why they cannot sign in. */
body[data-skin-grid="users"] .rdt_TableRow[data-skin-inactive="1"] { opacity: .55; }
body[data-skin-grid="users"] .rdt_TableRow[data-skin-inactive="1"]:hover { opacity: .8; }

/* ---- header alignment ---------------------------------------------------- */
.skin-on[data-skin-grid] .rdt_TableCol { padding: 9px 8px !important; }
.skin-on[data-skin-grid] .rdt_TableCell { padding: 4px 8px !important; }

/* ---- centre name on the Users grid ---------------------------------------
   The column selects `centre_id`, so it showed the generated identifier
   rather than the centre. When the adapter has resolved a name it is drawn
   over the id; the id itself stays on the tooltip. If the lookup has not
   resolved — the list is still loading, or the id belongs to a centre that no
   longer exists — the raw value stays visible, as before. */
body[data-skin-grid="users"] .rdt_TableCell[data-skin-centre] { font-size: 0; }
body[data-skin-grid="users"] .rdt_TableCell[data-skin-centre]::before {
  content: attr(data-skin-centre);
  font-size: 15.5px;
  color: var(--text);
  white-space: normal;
  word-break: break-word;
}

/* ---- the sign-in card is always light ------------------------------------
   The card is a fixed white panel, but the dark-mode rules still reached
   inside it: the heading came out white on white and the two fields came out
   near-black. Nobody is signed in on this page, so there is no theme to
   honour — the card is pinned to its light treatment regardless. */
body.dark.skin-login #root form,
body.dark.skin-login #root .MuiPaper-root,
body.dark.skin-login #root .MuiCard-root { background: #fff !important; color: #182420 !important; }

/* Scoped to the card. Unscoped, this also blackened the headline on the
   brand panel, which sits on deep blue. */
body.dark.skin-login #root .box .MuiTypography-root,
body.dark.skin-login #root .box h1,
body.dark.skin-login #root .box h2,
body.dark.skin-login #root .box label { color: #182420 !important; }

body.dark.skin-login #root .box input,
body.dark.skin-login #root .box .MuiInputBase-root,
body.dark.skin-login #root .box .MuiInputBase-input {
  background: #fff !important; color: #182420 !important;
  border-color: #d6ddd8 !important; -webkit-text-fill-color: #182420 !important;
}
body.dark.skin-login #root .box input::placeholder { color: #8b9993 !important; }

/* ---- corrections found on the first pass over the four grids -------------- */

/* The Actions column the adapter injects into Users carries .skin-extra-col,
   which paints the Lead Queue's green "entry zone" tint. On the queue that
   tint means something; here it just made one heading green for no reason. */
body[data-skin-grid] .skin-extra-col {
  background: transparent !important;
  color: var(--muted) !important;
}
body.dark[data-skin-grid] .skin-extra-col {
  background: transparent !important;
  color: var(--muted) !important;
}

/* Email was the only column allowed to grow, so on a wide screen it took the
   entire 700px of slack and sat next to columns that were still cramped.
   Sharing the slack between the two free-text columns, email growing faster,
   keeps both readable at any window width. */
body[data-skin-grid="users"] [data-skin-gcol="email"] {
  flex: 3 1 260px !important; min-width: 240px !important; max-width: none !important;
}
body[data-skin-grid="users"] [data-skin-gcol="centre-name"] {
  flex: 2 1 200px !important; min-width: 180px !important; max-width: none !important;
}

/* The search field, made to look like one. The box is drawn on the wrapper
   rather than on the input: Material-UI paints the floating label underneath
   the input, so an opaque background on the input itself hides the label. */
body[data-skin-grid] [data-skin-gsearch-box] {
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--card);
  padding: 3px 10px;
  min-width: 280px;
}
body[data-skin-grid] [data-skin-gsearch-box]:focus-within {
  border-color: var(--brand);
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}
body[data-skin-grid] input[data-skin-gsearch] {
  background: transparent !important;
  color: var(--text) !important;
  font-size: 13px !important;
  padding: 4px 0 !important;
}
/* Material-UI draws its own underline under the field; with a real border
   around the wrapper it doubles up. */
body[data-skin-grid] [data-skin-gsearch-box].MuiInput-underline:before,
body[data-skin-grid] [data-skin-gsearch-box].MuiInput-underline:after { display: none !important; }

/* The label is a SIBLING of the input wrapper and comes before it in the
   DOM, so the wrapper's new background painted straight over it — which is
   why the box looked empty however the placeholder was styled. Lifting the
   label above the wrapper is what actually makes the text appear. It sits
   inside the box at rest and rises above it once you start typing. */
body[data-skin-grid] label.MuiInputLabel-root {
  z-index: 2;
  font-size: 13px;
  color: var(--muted) !important;
  /* The label is positioned against the form control, not the input wrapper,
     so it does not inherit the wrapper's padding and sat on the border. */
  padding-left: 11px;
}
body[data-skin-grid] label.MuiInputLabel-root.Mui-focused { color: var(--brand) !important; }
body.dark[data-skin-grid] [data-skin-gsearch-box] { background: #1c262c; border-color: #31414a; }

/* Material-UI hides the placeholder of any field that sits next to a label,
   via `label[data-shrink=false] + .MuiInputBase-formControl .MuiInputBase-input
   { opacity: 0 !important }` — injected at runtime, so it also wins ties on
   cascade order. This field's label is empty, so the rule was hiding the only
   text the box had. Matched here with strictly higher specificity, on all
   three spellings of the pseudo-element. */
body[data-skin-grid] .MuiInputBase-formControl input.MuiInputBase-input[data-skin-gsearch]::placeholder,
body[data-skin-grid] .MuiInputBase-formControl input.MuiInputBase-input[data-skin-gsearch]::-webkit-input-placeholder,
body[data-skin-grid] .MuiInputBase-formControl input.MuiInputBase-input[data-skin-gsearch]::-moz-placeholder {
  color: var(--muted) !important; opacity: 1 !important;
}

/* A right-aligned heading that is one long unbreakable word overflows to the
   LEFT, where the cell clips it — "Sold/Installed" was reading as
   "old/Installed". Given the width to sit on one line instead. */
body[data-skin-grid="clients"] [data-skin-gcol="sold-installed"] { min-width: 150px !important; max-width: 150px !important; }
body[data-skin-grid="centres"] [data-skin-gcol="sold-installed"] { min-width: 150px !important; max-width: 150px !important; }
body[data-skin-grid] .rdt_TableCol[data-skin-gkind="money"] { line-height: 1.2; }

/* react-data-table's own title bar, which none of these pages gives a title
   to. Empty, it was 56px of white above the grid. */
body[data-skin-grid] .rdt_TableHeader[data-skin-empty="1"] { display: none !important; }
body[data-skin-grid] .rdt_TableHeader {
  background: var(--card) !important; color: var(--text) !important;
  min-height: 0 !important; padding: 8px 12px !important;
}

/* A count is compared down the column, like an amount, so it right-aligns —
   unlike a phone number, which is read left to right. */
.skin-on [data-skin-gkind="count"] { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }
.skin-on .rdt_TableCell[data-skin-gkind="count"],
.skin-on .rdt_TableCol[data-skin-gkind="count"] { justify-content: flex-end; text-align: right; }
body[data-skin-grid] .rdt_TableCol[data-skin-gkind="count"] { line-height: 1.2; }

/* ---------- 25. Areas ------------------------------------------------------
   The route used to embed two Google Sheets in iframes, one per tab. The
   sheets belong to an account nobody here can open, so the page rendered
   Google's "You need access" screen. The area list is drawn here instead, in
   the same column layout as the spreadsheet everyone already reads, and the
   Scheduling tab is gone with the sheet it pointed at.
   ------------------------------------------------------------------------ */

/* The app's own content on this route — the tab bar, the URL fields and both
   iframes. Scoped to the route by the body class, which the adapter clears on
   the way out; without that scoping every other page renders blank. */
body.skin-on.skin-areas-on .bodyContent > *:not(.skin-areas) { display: none !important; }

.skin-areas {
  display: flex; flex-direction: column;
  height: calc(100vh - 74px);
  padding: 0 16px 12px;
  box-sizing: border-box;
}

.skin-area-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; padding: 4px 0 12px;
}
.skin-area-title h2 { margin: 0; font-size: 20px; font-weight: 700; color: var(--text); }
.skin-area-title p  { margin: 3px 0 0; font-size: 12.5px; color: var(--muted); }

/* The match count sits under the box, not beside it — beside it, a long
   message ran off the right edge of the window. */
.skin-area-tools { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
#skinAreaFind {
  width: 260px; padding: 7px 11px; font-size: 13px; font-family: var(--sans);
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--card); color: var(--text);
}
#skinAreaFind:focus { outline: 2px solid var(--brand); outline-offset: -1px; border-color: var(--brand); }
body.dark.skin-on #skinAreaFind { background: #1c262c; border-color: #31414a; }

.skin-area-found { font-size: 12px; font-weight: 600; color: var(--brand); min-height: 15px; }
.skin-area-found.none { color: var(--danger); }

/* The sheet itself: one column per area, scrolling sideways exactly as the
   spreadsheet does, with each column scrolling on its own so the headings
   stay put no matter how long the longest area is. */
.skin-area-sheet {
  flex: 1; min-height: 0;
  display: flex; gap: 10px;
  overflow-x: auto; overflow-y: hidden;
  padding-bottom: 8px;
}
.skin-area-col {
  flex: 0 0 178px;
  display: flex; flex-direction: column; min-height: 0;
  border: 1px solid var(--line); border-radius: 10px;
  background: var(--card); overflow: hidden;
  transition: opacity .12s ease;
}
/* While a search is running, an area with no match steps back rather than
   disappearing — the columns keep their positions, so you do not lose your
   place in the sheet. */
.skin-area-col[data-dim="1"] { opacity: .35; }

/* Fixed height, not auto: an area whose name runs to two lines ("Area 22
   Sault Ste Marie") otherwise pushed its list down and the columns stopped
   lining up with each other across the sheet. */
/* Every heading in the spreadsheet is the same dark blue with white bold
   text; that is kept, so the sheet is recognisable at a glance. Fixed height,
   not auto: an area whose name runs to two lines ("Area 22 Sault Ste Marie")
   otherwise pushed its list down and the columns stopped lining up. */
.skin-area-hd {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  height: 42px; box-sizing: border-box;
  padding: 0 10px;
  background: #1F4E79; color: #fff; overflow: hidden;
}
.skin-area-hd b { line-height: 1.15; color: #fff; }
.skin-area-hd span {
  flex: 0 0 auto;
  background: rgba(255,255,255,.16); border-color: rgba(255,255,255,.28); color: #fff;
}
.skin-area-hd b {
  font-size: 11.5px; font-weight: 700; letter-spacing: .3px;
  text-transform: uppercase; color: var(--text);
}
.skin-area-hd span {
  font-size: 10.5px; font-weight: 700; color: var(--muted);
  background: var(--chip); border: 1px solid var(--line);
  border-radius: 9px; padding: 0 6px; line-height: 16px;
}

.skin-area-list {
  list-style: none; margin: 0; padding: 4px 0;
  overflow-y: auto; flex: 1; min-height: 0;
}
.skin-area-list li {
  padding: 3px 10px; font-size: 13px; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.skin-area-list li:hover { background: var(--chip); }

/* The cell colours from the spreadsheet, applied to the cities exactly as
   Excel fills them. Ten of the areas have no fill in the sheet and are left
   plain here for the same reason. */
.skin-area-col[data-filled="1"] .skin-area-list { padding: 0; }
/* Areas 6 and 11 are filled black in the sheet. On a white page that is
   obvious; on the dark canvas the column all but disappeared, so a filled
   column gets a visible edge to sit inside. */
body.dark.skin-on .skin-area-col[data-filled="1"] { border-color: rgba(255,255,255,.38); }
.skin-area-col[data-filled="1"] .skin-area-list li {
  background: var(--afill);
  color: var(--aink);
  border-bottom: 1px solid rgba(255,255,255,.22);
}
.skin-area-col[data-filled="1"] .skin-area-list li:last-child { border-bottom: 0; }
.skin-area-col[data-filled="1"] .skin-area-list li:hover { filter: brightness(1.12); }

/* A search hit has to read on a black cell, a yellow cell and no cell at all,
   so it is marked with a ring and weight rather than a background colour. */
.skin-area-list li.hit {
  font-weight: 800;
  box-shadow: inset 0 0 0 2px var(--brand);
  border-radius: 3px;
}
.skin-area-col:not([data-filled="1"]) .skin-area-list li.hit {
  background: rgba(0,118,201,.14); color: var(--brand);
}
body.dark.skin-on .skin-area-col:not([data-filled="1"]) .skin-area-list li.hit {
  background: rgba(47,149,220,.20); color: #7dc0ee;
}

.skin-area-sheet::-webkit-scrollbar,
.skin-area-list::-webkit-scrollbar { width: 10px; height: 10px; }
.skin-area-sheet::-webkit-scrollbar-track,
.skin-area-list::-webkit-scrollbar-track { background: transparent; }
.skin-area-sheet::-webkit-scrollbar-thumb,
.skin-area-list::-webkit-scrollbar-thumb { background: #b9c6bf; border-radius: 8px; border: 2px solid var(--canvas); }
body.dark.skin-on .skin-area-sheet::-webkit-scrollbar-thumb,
body.dark.skin-on .skin-area-list::-webkit-scrollbar-thumb { background: #3a4a54; border-color: #10161a; }

/* ---------- 26. Role permissions ------------------------------------------
   The adapter puts one class on <body> per capability the signed-in role
   has — skin-can-export, skin-can-search and so on — and these rules hide
   whatever the role does not have. Written as :not() so the DEFAULT is
   hidden: a capability has to be granted for the control to appear, which
   means a role the table does not know about, or a class that fails to be
   applied, errs towards showing less rather than more.

   Presentation only. It stops the wrong button being pressed; it does not
   stop the endpoint being called, which is a separate piece of work.
   ------------------------------------------------------------------------ */

/* Toolbar buttons the adapter has already tagged by their own label text. */
body.skin-on:not(.skin-can-export) [data-skin-slot="export"],
body.skin-on:not(.skin-can-export) [data-skin-btn="export"],
body.skin-on:not(.skin-can-addLead) [data-skin-slot="add"],
body.skin-on:not(.skin-can-addLead) [data-skin-btn="add"],
body.skin-on:not(.skin-can-bulk) [data-skin-slot="bulk"],
body.skin-on:not(.skin-can-bulk) [data-skin-btn="bulk"],
body.skin-on:not(.skin-can-search) [data-skin-slot="search"],
body.skin-on:not(.skin-can-search) [data-skin-search] { display: none !important; }

/* The three controls the adapter injects into the leads toolbar. */
body.skin-on:not(.skin-can-area) #skinAreaWrap,
body.skin-on:not(.skin-can-colour) #skinColourWrap,
body.skin-on:not(.skin-can-clientFilter) #skinFClient { display: none !important; }

/* The Comments cell for a role that may not read the thread. The column keeps
   its place in the grid so nothing shifts under people used to its position;
   only the note is withheld. */
.skin-cell-mute {
  display: block; width: 100%;
  padding: 6px 8px; font-size: 15.5px; color: var(--muted);
  text-align: center; user-select: none;
}
body.skin-on:not(.skin-can-comments) [data-skin-extra="comments"] .skin-notecount { display: none !important; }

/* Add Lead is the portal's primary action and sits in its own wrapper; when
   it goes, the wrapper should not leave a gap behind it. */
body.skin-on:not(.skin-can-addLead) .addLeadBtn:empty { display: none !important; }


/* ---------- 27. Embedded workspaces ---------------------------------------
   Frames around the other 247 tools — Sheets, Digi Market, AI Call. The
   portal's router does not know these as routes; they ride on the Lead
   Queue's route with a ?view= marker, and the panel is mounted beside #root
   rather than inside it, so nothing of ours is ever a child of a container
   React is managing.
   ------------------------------------------------------------------------ */

body.skin-on.skin-embed-on #root { display: none !important; }

.skin-embed {
  display: flex; flex-direction: column;
  height: calc(100vh - 66px);
  padding: 0 16px 12px;
  box-sizing: border-box;
}

.skin-embed-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 16px; padding: 4px 0 10px;
}
.skin-embed-head h2 { margin: 0; font-size: 20px; font-weight: 700; color: var(--text); }
.skin-embed-head p  { margin: 3px 0 0; font-size: 12.5px; color: var(--muted); }

/* Worth having even when the frame works: some things are easier in a full
   window, and if a site ever refuses to be framed this is the way through. */
.skin-embed-out {
  font-size: 12.5px; font-weight: 600; text-decoration: none;
  color: var(--brand); border: 1px solid var(--line); border-radius: 8px;
  padding: 6px 11px; white-space: nowrap; background: var(--card);
}
.skin-embed-out:hover { border-color: var(--brand); background: rgba(0,118,201,.08); }
body.dark.skin-on .skin-embed-out { background: #1c262c; border-color: #31414a; color: #7dc0ee; }

.skin-embed-frame {
  flex: 1; min-height: 0; width: 100%;
  border: 1px solid var(--line); border-radius: 12px;
  background: #fff;
}

/* Shown only while the portal and the framed site are different sites; the
   adapter works that out for itself, so it goes at go-live. */
.skin-embed-note {
  margin: 0 0 10px; padding: 9px 12px;
  border: 1px solid #e6cfa6; border-radius: 9px;
  background: #fbf4e6; color: #6f5314;
  font-size: 12.5px; line-height: 1.5;
}
.skin-embed-note b { font-weight: 700; }
body.dark.skin-on .skin-embed-note { background: #2b2413; border-color: #4d4128; color: #e0c684; }

/* A workspace whose address has not been given yet. An empty frame would
   read as broken; this reads as waiting. */
.skin-embed-empty {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; text-align: center;
  border: 1px dashed var(--line); border-radius: 12px; background: var(--card);
}
.skin-embed-empty b { font-size: 15px; color: var(--text); }
.skin-embed-empty span { font-size: 13px; color: var(--muted); max-width: 420px; line-height: 1.5; }


/* Eleven tabs at the larger size need most of the bar, so the block on the
   right gives way before the tabs do: the name and role step aside first,
   leaving the avatar and Log out, which is what people actually click. The
   name is still on the avatar's tooltip. */
@media (max-width: 1700px) {
  .skin-topbar .userchip .uinfo { display: none; }
}
@media (max-width: 1180px) {
  .skin-topbar .skin-tab .t { display: none; }   /* icons only, before scrolling */
  .skin-topbar .skin-tab { padding: 7px 9px; }
}
.skin-topbar .userchip { min-width: 0; }
.skin-topbar .userchip .uinfo { min-width: 0; overflow: hidden; }

/* ---------- 28. Narrow screens --------------------------------------------
   Below 820px the Lead Queue stops being a grid and becomes one card per
   lead. Everything above this point pulls the other way — tighter rows, more
   columns, more leads per screen — which is right at a desk and wrong on a
   phone, so this is a different layout rather than a squeezed one.

   The class is applied by the adapter, not by the media query alone, because
   only some roles get it. Callback keeps the desktop layout on a phone.
   ------------------------------------------------------------------------ */

/* ---- the top bar ---- */
@media (max-width: 820px) {
  body.skin-mobile .skin-topbar {
    grid-template-columns: auto minmax(0, 1fr) auto;
    height: 52px; flex-basis: 52px; padding: 0 8px; gap: 8px;
  }
  /* The wordmark overlapped the tabs at this width: the logo column could
     shrink to nothing but the image inside it could not. */
  body.skin-mobile .skin-logo { overflow: hidden; }
  body.skin-mobile .skin-logo img { height: 24px; }
  body.skin-mobile .skin-tabs { justify-self: stretch; overflow-x: auto; gap: 0; }
  body.skin-mobile .skin-tab { padding: 8px 10px; }
  body.skin-mobile .skin-tab .t { display: none; }
  body.skin-mobile .skin-tab .i { font-size: 18px; }
  body.skin-mobile .userchip .uinfo,
  body.skin-mobile .userchip .themebtn { display: none; }
  body.skin-mobile .skin-topbar .userchip .uav { width: 30px; height: 30px; }
  body.skin-mobile .userchip .logout { padding: 5px 8px; font-size: 11.5px; }
}

/* ---- the toolbar ---- */
@media (max-width: 820px) {
  /* The heavier actions are desk work and only crowd a phone. */
  body.skin-mobile [data-skin-slot="export"],
  body.skin-mobile [data-skin-slot="add"],
  body.skin-mobile [data-skin-slot="bulk"],
  body.skin-mobile #skinColourWrap { display: none !important; }

  body.skin-mobile .headerBlock { padding: 8px 10px !important; gap: 8px !important; }
  body.skin-mobile [data-skin-search] { width: 100% !important; }
  body.skin-mobile .skin-toolbar,
  body.skin-mobile .headerBlock > div { flex-wrap: wrap; }
  body.skin-mobile #skinRight,
  body.skin-mobile #skinAreaWrap { display: flex; flex-wrap: wrap; gap: 6px; }
  body.skin-mobile #skinRight select,
  body.skin-mobile #skinRight input[type="date"],
  body.skin-mobile #skinAreaWrap select { min-height: 34px; font-size: 13px; }
}

/* ---- the queue as cards ---- */
@media (max-width: 820px) {
  body.skin-mobile .rdt_TableHead { display: none !important; }

  /* Undo the floors the desktop grid stands on, or the cards inherit a
     1,820px minimum and the page scrolls sideways anyway. */
  body.skin-mobile .rdt_Table,
  body.skin-mobile .rdt_TableBody,
  body.skin-mobile .rdt_TableRow,
  body.skin-mobile div[role="table"] { min-width: 0 !important; }
  body.skin-mobile .rdt_Table { border: 0 !important; background: transparent !important; }
  body.skin-mobile .tableBlock > div { max-height: none; overflow: visible !important; }

  body.skin-mobile .rdt_TableRow {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
    gap: 6px 10px;
    align-items: start;
    padding: 12px !important;
    margin: 0 0 10px;
    border: 1px solid var(--line) !important;
    border-radius: 12px;
    background: var(--card) !important;
    min-height: 0 !important;
  }
  body.dark.skin-mobile .rdt_TableRow { background: #161f25 !important; }

  body.skin-mobile .rdt_TableCell,
  body.skin-mobile .skin-extra-cell {
    display: block !important;
    min-width: 0 !important; max-width: none !important;
    width: auto !important; flex: none !important;
    padding: 0 !important;
    font-size: 14px;
  }
  /* Columns the desktop hides stay hidden. The blanket display:block above
     is !important because react-data-table's own styles are, and without
     these two exceptions it would resurrect the dropped columns and the
     client columns an agent is not meant to see. Placed after it deliberately
     — same specificity, later wins. */
  body.skin-mobile .rdt_TableCell[data-skin-drop] { display: none !important; }
  body.skin-mobile.skin-role-agent .rdt_TableCell[data-skin="cli"] { display: none !important; }

  /* The heading is gone, so each field says what it is. */
  body.skin-mobile [data-skin-label]::before {
    content: attr(data-skin-label);
    display: block;
    font-size: 10.5px; font-weight: 700; letter-spacing: .4px;
    text-transform: uppercase; color: var(--muted);
    margin-bottom: 2px;
  }

  /* Reading order on a card, which is not the column order on a desk. */
  body.skin-mobile [data-skin-col="customer-name"]    { order: 1; grid-column: 1 / -1; }
  body.skin-mobile [data-skin-col="status"]           { order: 2; grid-column: 1 / -1; }
  body.skin-mobile [data-skin-col="phone"]            { order: 3; grid-column: 1 / -1; }
  body.skin-mobile [data-skin-col="customer-address"] { order: 4; grid-column: 1 / -1; }
  body.skin-mobile [data-skin-col="city"]             { order: 5; }
  body.skin-mobile [data-skin-col="lead-type"]        { order: 6; }
  body.skin-mobile [data-skin-col="app-date"]         { order: 7; }
  body.skin-mobile [data-skin-col="app-time"]         { order: 8; }
  body.skin-mobile [data-skin-extra="age"]            { order: 9; }
  body.skin-mobile [data-skin-extra="gender"]         { order: 10; }
  body.skin-mobile [data-skin-extra="comments"]       { order: 11; grid-column: 1 / -1; }
  body.skin-mobile [data-skin-col="client-name"]      { order: 12; }
  body.skin-mobile [data-skin-col="push-to-crm"]      { order: 13; }
  body.skin-mobile [data-skin-col="agent-id"]         { order: 14; }
  body.skin-mobile [data-skin-col="created-on"]       { order: 15; }
  body.skin-mobile [data-skin-col="make-ai-call"]     { order: 16; }
  body.skin-mobile [data-skin-col="sel"]              { order: 0; }

  /* The customer's name leads the card. */
  body.skin-mobile [data-skin-col="customer-name"] { font-size: 16px; font-weight: 700; }
  body.skin-mobile [data-skin-col="customer-name"]::before { display: none; }

  /* Controls sized for a thumb, not a mouse. Checkboxes and switches are
     excluded by name: stretched to full width, the row's select box came out
     as a large white slab across the top of every card. */
  body.skin-mobile .rdt_TableCell select,
  body.skin-mobile .rdt_TableCell input:not([type="checkbox"]):not([type="radio"]),
  body.skin-mobile .skin-cell-ctl:not([type="checkbox"]) {
    width: 100% !important; min-height: 38px; font-size: 14px !important;
    box-sizing: border-box;
  }
  body.skin-mobile .rdt_TableCell input[type="checkbox"] {
    width: 20px !important; height: 20px; min-height: 0;
  }

  /* The select box and the row expander are chrome, not fields. They sit on
     one compact line at the top of the card instead of a row each. */
  body.skin-mobile .rdt_TableRow > div:not([data-skin-col]):not([data-skin-extra]) {
    order: 0; grid-column: auto; width: auto !important; padding: 0 !important;
  }
  body.skin-mobile [data-skin-col="sel"] {
    grid-column: auto !important; width: auto !important;
  }
  body.skin-mobile [data-skin-col="sel"]::before { display: none; }

  /* The red line means nothing without columns to divide. */
  body.skin-mobile .rdt_TableCell[data-skin="load"],
  body.skin-mobile .rdt_TableCell[data-skin="cli"] { background: transparent !important; }

  body.skin-mobile .rdt_Pagination {
    height: auto !important; min-height: 44px !important;
    flex-wrap: wrap; justify-content: center; gap: 6px;
    border-radius: 10px; border: 1px solid var(--line) !important;
  }
}

/* The dial link, which is the whole point of a phone. */
.skin-callbtn { display: none; }
@media (max-width: 820px) {
  body.skin-mobile .skin-callbtn {
    display: inline-block; margin-left: 10px;
    padding: 3px 12px; border-radius: 999px;
    background: var(--brand); color: #fff; text-decoration: none;
    font-size: 12.5px; font-weight: 700;
  }
}

/* ---- dashboard and the embedded workspaces ---- */
@media (max-width: 820px) {
  body.skin-mobile .skin-dash { padding: 0 10px 12px; }
  body.skin-mobile .skin-dash-head { flex-direction: column; align-items: stretch; gap: 10px; }
  body.skin-mobile .skin-kpis,
  body.skin-mobile .skin-dash-grid { grid-template-columns: 1fr !important; }
  body.skin-mobile .skin-card { grid-column: 1 / -1 !important; }
  body.skin-mobile .skin-dash-controls { flex-wrap: wrap; gap: 6px; }

  body.skin-mobile .skin-embed { height: calc(100vh - 58px); padding: 0 10px 10px; }
  body.skin-mobile .skin-embed-head { flex-direction: column; align-items: stretch; gap: 8px; }
  body.skin-mobile .skin-embed-out { text-align: center; }
}
