/* Suhbat operator console.

   Palette, type and chrome are Reveo's owner-react design system copied
   token-for-token from ai-manager-srvr/web/owner-react/src/styles/{kit,dark}.css
   rather than re-derived. This is another Reveo product and a manager moving
   between the two panels should not feel they changed vendor. When kit.css
   moves, THIS BLOCK is the thing to re-sync — keep it a copy, not a variation.

   The layout rule here is summary-first: a manager opens a call to answer two
   questions — was this good, and what do I tell the seller. Those two answers
   are the top of the page at full size. Everything measurable is real but
   secondary, so it lives behind tabs rather than in a wall of cards. */

:root {
  color-scheme: light;

  /* ---- surfaces ---- */
  --bg:#F4F6F8;
  --surface:#FFFFFF;
  --surface-2:#FAFBFC;
  --surface-hover:#F6F8F9;

  --line:#E9EDF0;
  --line-2:#DEE4E8;
  --line-strong:#CDD5DA;

  /* ---- brand ---- */
  --brand:#07B17F;
  --brand-ink:#05926A;
  --brand-deep:#04654B;
  --brand-soft:#E7F7F0;
  --brand-soft-2:#D5F0E4;
  /* A border that reads as brand rather than as the grey rules around it.
     --line-strong on a --brand-soft fill looks like a disabled control; this
     is the same green at the weight a 1px edge needs to be seen at. */
  --brand-line:#A9DFC9;
  /* Foreground on a --brand fill. Brand green is dark enough in both themes
     that this stays white either way; naming it stops the bare #fff literal
     spreading to every new filled button. */
  --on-brand:#FFFFFF;

  /* ---- ink ---- */
  --ink:#16221D;
  --ink-2:#566159;
  --ink-3:#85928A;
  --ink-4:#A9B3AC;

  /* ---- channel colours ----
     Suhbat has no Telegram/WhatsApp/Instagram surface yet. They are carried
     anyway because a partial copy is how two palettes quietly drift apart. */
  --tg:#27A7E7; --tg-soft:#E4F3FC;
  --wa:#22C55E; --wa-soft:#E4F8EC;
  --ig:#E1306C; --ig-soft:#FCE7EF;

  /* ---- status ---- */
  --blue:#3B82F6;  --blue-soft:#E8F0FE;
  --amber:#E59312; --amber-soft:#FCF1DF;
  --green:#0EA371; --green-soft:#E5F6EF;
  --red:#E5484D;   --red-soft:#FCEAEA;
  /* --red is tuned for fills and reads at 3.4:1 on a card, under the 4.5:1 a
     label needs. Text takes --red-ink instead. */
  --red-ink:#B42318;
  --violet:#7C5CFC; --violet-soft:#EFEBFE;

  /* ---- shape ---- */
  --radius:20px;
  --radius-sm:14px;
  --radius-xs:12px;
  --pill:999px;

  --shadow-xs:0 1px 2px rgba(16,24,40,.05);
  --shadow-sm:0 1px 2px rgba(16,24,40,.05),0 1px 3px rgba(16,24,40,.04);
  --shadow:0 2px 6px -2px rgba(16,24,40,.08),0 4px 14px -6px rgba(16,24,40,.08);
  --shadow-lg:0 16px 40px -16px rgba(16,24,40,.22),0 4px 12px -6px rgba(16,24,40,.10);
  --shadow-pop:0 18px 50px -12px rgba(16,24,40,.26);

  --ease:cubic-bezier(.22,1,.36,1);

  /* ---- type ----
     The same two families owner-react loads: Space Grotesk carries headings
     and the brand, Manrope carries everything else. Mono is the system stack,
     as it is there — no third webfont, and every platform's own mono is the
     one its readers parse fastest. --sans/--mono remain as aliases so the
     rules further down this file keep resolving. */
  --font-d:"Space Grotesk",system-ui,sans-serif;
  --font-b:"Manrope",system-ui,sans-serif;
  --font-m:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace;
  --sans:var(--font-b);
  --mono:var(--font-m);

  /* 266px is kit.css's --sidebar-w, 72px its --topbar-h. Suhbat has no topbar,
     but the brand row is that height so the two products line up at the fold. */
  --rail:266px;
  --brandbar:72px;

  /* One type scale, used everywhere. The jump from --t-lede to --t-body is
     deliberately large: the summary sentence is the page, the rest is support.
     Every size below is kit.css's own value for the same job, so the two
     products set the same thing at the same size:
       --t-h1      .tb-title h1   21px   the page title
       --t-h2      .card-head h3  16.5px a card or section heading
       --t-small   .card-head .cs 12.5px a heading's supporting line
       --t-eyebrow .sb-sectlabel  11px   an uppercase micro-label */
  --t-lede: clamp(19px, 1.15vw + 13px, 26px);
  --t-h1: 21px;
  --t-h2: 16.5px;
  --t-body: 14.5px;
  --t-small: 12.5px;
  --t-eyebrow: 11px;
}

/* Dark is an EXPLICIT attribute, never a bare media query, because that is how
   owner-react does it and the choice has to survive a reload the same way in
   both products. The bootstrap script in index.html always writes data-theme
   before first paint — from localStorage('reveo_theme') when the user has
   chosen, from prefers-color-scheme when they have not — so this single block
   covers both and no value is ever left hardcoded against the wrong ground. */
:root[data-theme='dark'] {
  color-scheme: dark;

  --bg:#0E1512;
  --surface:#161E1A;
  --surface-2:#131A16;
  --surface-hover:#1C2620;

  --line:#243029;
  --line-2:#2C3A31;
  --line-strong:#38473D;

  --brand:#15C68F;
  --brand-ink:#2FD7A2;
  --brand-deep:#6FE9C2;
  --brand-soft:#14271F;
  --brand-soft-2:#18342A;
  --brand-line:#20493A;

  --ink:#E8EFEA;
  --ink-2:#AEB8B1;
  --ink-3:#7E8A82;
  --ink-4:#5C665F;

  --tg:#3BB4F0; --tg-soft:#142430;
  --wa:#2FCB6A; --wa-soft:#122A1B;
  --ig:#EE4F84; --ig-soft:#2C1620;

  --blue:#5B9BFF;  --blue-soft:#16243C;
  --amber:#F0A93A; --amber-soft:#2E2210;
  --green:#1BB47E; --green-soft:#122A20;
  --red:#F0666B;   --red-soft:#2E1517;
  /* On the dark card --red already clears 4.5:1, so the text grade matches it. */
  --red-ink:#F0666B;
  --violet:#9A82FF; --violet-soft:#20193C;

  --shadow-xs:0 1px 2px rgba(0,0,0,.3);
  --shadow-sm:0 1px 2px rgba(0,0,0,.3),0 1px 3px rgba(0,0,0,.25);
  --shadow:0 2px 6px -2px rgba(0,0,0,.4),0 4px 14px -6px rgba(0,0,0,.45);
  --shadow-lg:0 16px 40px -16px rgba(0,0,0,.6),0 4px 12px -6px rgba(0,0,0,.5);
  --shadow-pop:0 18px 50px -12px rgba(0,0,0,.7);
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--font-b);
  font-size: var(--t-body);
  line-height: 1.5;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1, h2, h3 { margin: 0; font-family: var(--font-d); font-weight: 600; letter-spacing: -0.015em; }
a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }
::selection { background: var(--brand-soft-2); color: var(--brand-deep); }
:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 6px; }

/* Tabular numerals wherever a figure has to line up column-to-column. */
.tnum { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }

*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 10px; border: 3px solid transparent; background-clip: content-box; }
*::-webkit-scrollbar-thumb:hover { background: var(--ink-4); background-clip: content-box; }
*::-webkit-scrollbar-track { background: transparent; }

/* ---------------------------------------------------------------- shell */
/* The rail is kit.css's .sb, metric for metric: 266px wide, a 72px brand row
   with a rule under it, 44px nav rows on --radius-sm. Suhbat's nav is buttons
   rather than links and lives in its own <nav>, so the rules are re-stated
   here against Suhbat's class names instead of importing kit.css — one
   product's stylesheet reaching into another's is how both become impossible
   to change. */
.shell { display: grid; grid-template-columns: var(--rail) 1fr; min-height: 100vh; }

.rail {
  background: var(--surface);
  border-right: 1px solid var(--line);
  padding: 0;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  /* dvh where the browser has it: on a phone 100vh includes the ground under
     the retracting URL bar, and the rail's foot sat beneath it. */
  height: 100vh;
  height: 100dvh;
}

/* Scoped to the rail, because `.brand` is not only a component here — it is
   also a TONE on the tinted icon squares (`.tico.brand`), and an unscoped
   `.brand` reached them: the funnel on «Lid konversiyasi» and the checklist on
   «Tahlil qilingan» inherited this block's `padding: 0 20px`, which pushed the
   glyph 8px right of centre and stretched the 34px square to 40. Every other
   tone was fine only because no component happens to be called `.violet`. */
.rail .brand {
  display: flex; align-items: center; gap: 10px;
  height: var(--brandbar); flex-shrink: 0;
  padding: 0 20px;
  border-bottom: 1px solid var(--line);
}
.rail .brand .mark { width: 30px; height: 30px; flex: none; display: grid; place-items: center; }
.rail .brand .mark img { width: 30px; height: 30px; display: block; }
.rail .brand .name { min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 2px; }
/* kit.css pins the product name to #000 and patches it back in dark.css.
   --ink renders the same on light and needs no second rule to keep in step. */
.rail .brand .name b {
  font-family: var(--font-d); font-weight: 700; font-size: 14px;
  letter-spacing: -0.01em; line-height: 1; white-space: nowrap;
  color: var(--ink);
}
.rail .brand .name span {
  font-size: 9px; font-weight: 600; letter-spacing: .13em;
  color: var(--ink-3); text-transform: uppercase;
  line-height: 1; white-space: nowrap;
}
/* A company name is not a wordmark. «REVEO» is four letters and carries .13em
   tracking as a logo treatment; «C-Space» at the same tracking reads as a
   ransom note and «Bioflex» overflows the 68px collapsed rail. Kept uppercase
   so the block still reads as a label under the product name, and allowed to
   ellipsis rather than push the mark out of line. */
.rail .brand .name span.is-tenant {
  font-size: 10px; letter-spacing: .04em;
  overflow: hidden; text-overflow: ellipsis; max-width: 140px;
}

.nav { flex: 1; overflow-y: auto; padding: 16px 14px; display: flex; flex-direction: column; gap: 3px; }
.nav button {
  all: unset;
  display: flex; align-items: center; gap: 12px;
  box-sizing: border-box;
  height: 44px; padding: 0 12px;
  border-radius: var(--radius-sm);
  font-size: 14.5px; font-weight: 600;
  color: var(--ink-2);
  cursor: pointer;
  transition: background .18s var(--ease), color .18s var(--ease);
}
/* `all: unset` above wipes the UA's display:none for [hidden], so the rule
   must be restated or a hidden rail item renders anyway — which is how every
   manager saw «Natijalarim», an operator-only view that 404s without a seat. */
.nav button[hidden] { display: none; }
.nav button .ic { width: 20px; height: 20px; flex: none; color: var(--ink-3); transition: color .18s var(--ease); }
.nav button .ic svg { width: 20px; height: 20px; display: block; }
.nav button .lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav button:hover .ic { color: var(--ink-2); }
.nav button[aria-current="page"] .ic { color: var(--brand); }
.nav button:hover { background: var(--surface-hover); color: var(--ink); }
.nav button[aria-current="page"] { background: var(--brand-soft); color: var(--brand-deep); }
.nav button:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.nav .count {
  font-family: var(--font-b); font-variant-numeric: tabular-nums;
  font-size: 12px; font-weight: 700;
  min-width: 22px; height: 22px; padding: 0 7px;
  border-radius: var(--pill);
  display: grid; place-items: center;
  background: var(--surface-hover); color: var(--ink-2);
}
.nav button[aria-current="page"] .count { background: var(--surface); color: var(--brand-deep); }
/* The counts are filled in after the first fetch. An empty pill is a grey
   lozenge next to a label, which reads as a broken badge rather than a
   pending one. */
.nav .count:empty { display: none; }

/* ---- the assistant, pinned to the foot ----

   The one rail item with a border, and the only one that is not a page of the
   client's data — it is the way to ASK about them. Both facts are why it sits
   below the list rather than at the end of it: a manager who has never pressed
   it would not discover it as the eleventh identical row in a column of ten.

   The treatment is a brand-tinted card, not a bright button. The rail is a
   quiet surface a person looks at all day and something shouting in it stops
   being read within a week; the border and the tint are enough to separate it
   from ten borderless rows, which is the whole job. */
.rail-foot {
  flex: none;
  padding: 10px 14px 4px;
  border-top: 1px solid var(--line);
}

.rail-ai {
  all: unset;
  box-sizing: border-box;
  display: flex; align-items: center; gap: 12px;
  width: 100%;
  height: 46px; padding: 0 12px;
  border: 1px solid var(--brand-line);
  border-radius: var(--radius-sm);
  background: var(--brand-soft);
  color: var(--brand-deep);
  font-size: 14.5px; font-weight: 600;
  cursor: pointer;
  transition: background .18s var(--ease), border-color .18s var(--ease),
    transform .12s var(--ease);
}
/* `all: unset` wipes the UA's display:none for [hidden] — the same trap the
   nav rows already carry a rule for, and the reason every manager once saw an
   operator-only item. */
.rail-ai[hidden] { display: none; }
.rail-ai:hover { background: var(--brand); border-color: var(--brand); color: var(--on-brand); }
.rail-ai:active { transform: translateY(1px); }
.rail-ai:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.rail-ai[aria-current="page"] { background: var(--brand); border-color: var(--brand); color: var(--on-brand); }

.rail-ai .ic { width: 20px; height: 20px; flex: none; display: grid; place-items: center; }
.rail-ai .ic svg { width: 20px; height: 20px; display: block; }
.rail-ai .lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The chevron says «this opens a page», which distinguishes it from the topbar
   button that opens the drawer over the page you are already on. */
.rail-ai-go { width: 16px; height: 16px; flex: none; opacity: .55; display: grid; place-items: center; }
.rail-ai-go svg { width: 16px; height: 16px; display: block; }
.rail-ai:hover .rail-ai-go { opacity: 1; }

/* ---- collapse ----
   owner-react's own affordance, ported: the attribute lives on <html> so the
   rail width is one token override rather than a second layout, and the choice
   is read before first paint so a collapsed rail never renders wide and snaps.
   68px is kit.css's collapsed --sidebar-w. */
.rail-collapse {
  all: unset;
  box-sizing: border-box;
  display: flex; align-items: center; gap: 12px;
  margin: 2px 14px 12px; padding: 9px 12px;
  border-radius: var(--radius-sm);
  color: var(--ink-3);
  font-size: 13px; line-height: 1;
  cursor: pointer;
  transition: color .15s var(--ease), background .15s var(--ease);
}
.rail-collapse:hover { color: var(--ink-2); background: var(--surface-hover); }
.rail-collapse:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.rail-collapse .ic { width: 20px; height: 20px; flex: none; display: grid; place-items: center; }
.rail-collapse .ic svg { width: 20px; height: 20px; display: block; transition: transform .2s var(--ease); }

:root[data-rail='collapsed'] { --rail: 68px; }
:root[data-rail='collapsed'] .rail .brand .name,
:root[data-rail='collapsed'] .nav button .lbl,
:root[data-rail='collapsed'] .nav .count,
:root[data-rail='collapsed'] .rail-collapse .lbl,
:root[data-rail='collapsed'] .rail-ai .lbl,
:root[data-rail='collapsed'] .rail-ai-go { display: none; }
:root[data-rail='collapsed'] .rail .brand { padding: 0; justify-content: center; }
:root[data-rail='collapsed'] .nav { padding: 16px 14px; }
:root[data-rail='collapsed'] .nav button { justify-content: center; padding: 0; }
:root[data-rail='collapsed'] .rail-collapse { justify-content: center; padding: 9px 0; }
/* Square and centred at 68px: the border still marks it out from the icons
   above, which is the whole point of the treatment. */
:root[data-rail='collapsed'] .rail-foot { padding: 10px 12px 4px; }
:root[data-rail='collapsed'] .rail-ai { justify-content: center; padding: 0; height: 40px; }
:root[data-rail='collapsed'] .rail-collapse .ic svg { transform: rotate(180deg); }

/* ---- topbar ----
   kit.css's `.tb`, metric for metric: 72px, translucent surface over a blur,
   a rule under it. The page title lives here rather than in the scroll area,
   so it survives scrolling and the signed-in member has somewhere to sit that
   is not the bottom of the rail. */
.pane { display: flex; flex-direction: column; min-width: 0; height: 100vh; height: 100dvh; overflow: hidden; }

.tb {
  display: flex; align-items: center; gap: 18px;
  height: var(--brandbar); flex-shrink: 0;
  padding: 0 30px;
  /* Opaque first: a browser without color-mix gets a solid bar rather than a
     transparent one with the page scrolling through it. */
  background: var(--surface);
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter: blur(12px) saturate(140%);
  border-bottom: 1px solid var(--line);
  z-index: 15;
}
.tb-title { min-width: 0; }
.tb-title h1 { font-size: var(--t-h1); line-height: 1.15; letter-spacing: -0.02em; }
.tb-title p { margin: 2px 0 0; font-size: 13px; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tb-spacer { flex: 1; }

/* The phone drawer's handle and scrim. Both exist at every width and are
   DRAWN at none of them until the drawer breakpoint at the end of this file
   switches them on — the markup stays one shape and the cascade decides. */
.tb-menu {
  display: none; align-items: center; justify-content: center;
  width: 38px; height: 38px; flex: none;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--ink-2); cursor: pointer;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.tb-menu svg { width: 20px; height: 20px; display: block; }
.tb-menu:hover { background: var(--surface-hover); color: var(--ink); }
.tb-menu:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.rail-backdrop { display: none; }

/* Search + assistant as one unit (Metasell): a single bordered, rounded
   container holding the search pill and the «AI yordamchi» segment, split by a
   thin divider. The container owns the border and the radius; the two buttons
   inside carry neither. */
.tb-searchgroup {
  display: inline-flex; align-items: stretch; height: 38px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface-2); overflow: hidden;
  transition: border-color .18s var(--ease);
}
.tb-searchgroup:hover, .tb-searchgroup:focus-within { border-color: var(--line-strong); }
.tb-searchgroup-div { width: 1px; align-self: stretch; background: var(--line); flex: none; }

/* Search trigger in the bar: looks like a search field, opens the palette. The
   left segment of the group, taking the slack so the assistant sits flush
   right. */
.tb-searchbtn {
  display: inline-flex; align-items: center; gap: 9px;
  height: 100%; padding: 0 10px 0 13px;
  flex: 1 1 auto; width: min(340px, 32vw); min-width: 180px;
  border-radius: 0; background: transparent; border: 0;
  color: var(--ink-4); font: inherit; font-size: 14px; cursor: pointer;
  transition: background .18s var(--ease);
}
.tb-searchbtn:hover { background: var(--surface); }
/* Inside the group the outline draws INWARD, or overflow:hidden clips it. */
.tb-searchbtn:focus-visible, .tb-ai:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.tb-searchbtn-ic { display: grid; place-items: center; color: var(--ink-4); flex: none; }
.tb-searchbtn-ic svg { width: 17px; height: 17px; display: block; }
.tb-searchbtn-lbl { flex: 1; text-align: left; }
.tb-searchbtn-kbd {
  font: inherit; font-size: 11px; font-weight: 600; color: var(--ink-4);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 5px; padding: 1px 6px;
}

/* «AI yordamchi»: the right segment of the group, the kit's brand accent set
   against the search pill's plain surface. No border or radius of its own — the
   group clips its right corners round. */
.tb-ai {
  display: inline-flex; align-items: center; gap: 8px; flex: none;
  height: 100%; padding: 0 14px;
  border-radius: 0; border: 0;
  background: linear-gradient(135deg, var(--brand-soft), var(--brand-soft-2));
  color: var(--brand-deep); font: inherit; font-size: 13.5px; font-weight: 600;
  cursor: pointer; white-space: nowrap;
  transition: filter .18s var(--ease);
}
.tb-ai:hover { filter: brightness(1.04); }
.tb-ai-ic { display: grid; place-items: center; color: var(--brand); flex: none; }
.tb-ai-ic svg { width: 17px; height: 17px; display: block; }

/* Command palette: a dialog over a dimmed backdrop, results grouped by kind,
   each row built from the same helpers a calls row uses. */
.cmdk { position: fixed; inset: 0; z-index: 100; display: flex; align-items: flex-start; justify-content: center; }
.cmdk[hidden] { display: none; }
.cmdk-backdrop {
  position: absolute; inset: 0;
  background: color-mix(in srgb, var(--ink) 42%, transparent);
  backdrop-filter: blur(2px);
}
.cmdk-panel {
  position: relative; margin-top: 9vh; width: min(680px, 92vw);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  overflow: hidden; animation: cmdkIn .14s var(--ease);
}
@keyframes cmdkIn { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
.cmdk-top { display: flex; align-items: center; gap: 11px; padding: 14px 16px; border-bottom: 1px solid var(--line); }
.cmdk-ic { display: grid; place-items: center; color: var(--ink-3); flex: none; }
.cmdk-ic svg { width: 19px; height: 19px; display: block; }
.cmdk-top input { flex: 1; min-width: 0; border: 0; background: none; font: inherit; font-size: 16px; color: var(--ink); outline: none; }
.cmdk-top input::placeholder { color: var(--ink-4); }
.cmdk-esc {
  font: inherit; font-size: 11px; font-weight: 600; color: var(--ink-4);
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 5px; padding: 2px 7px; flex: none;
}
.cmdk-results { max-height: min(56vh, 460px); overflow-y: auto; padding: 6px; }
.cmdk-group { padding: 10px 10px 5px; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-4); }
.cmdk-item {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 9px 11px; border-radius: var(--radius-sm);
  background: none; border: 0; cursor: pointer; text-align: left; color: inherit;
}
.cmdk-item:hover, .cmdk-item[aria-selected="true"] { background: var(--surface-hover); }
.cmdk-main { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 3px; }
.cmdk-name { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: 14px; min-width: 0; }
.cmdk-name .mono { overflow: hidden; text-overflow: ellipsis; }
.cmdk-sub { font-size: 12.5px; color: var(--ink-3); display: flex; align-items: center; gap: 7px; }
.cmdk-time { margin-left: auto; font-size: 11.5px; color: var(--ink-4); white-space: nowrap; align-self: center; flex: none; }
.cmdk-empty, .cmdk-hint { padding: 28px 16px; text-align: center; color: var(--ink-3); font-size: 13.5px; }
.cmdk-loading { padding: 30px; display: grid; place-items: center; }
.cmdk-spin {
  width: 22px; height: 22px; border-radius: 50%;
  border: 2.5px solid var(--line); border-top-color: var(--brand);
  animation: cmdkSpin .7s linear infinite;
}
@keyframes cmdkSpin { to { transform: rotate(360deg); } }
/* A page row carries an arrow where the other rows carry an avatar, so the
   four groups keep one left edge and the eye can run straight down it. */
.cmdk-pg {
  width: 32px; height: 32px; flex: none; display: grid; place-items: center;
  border-radius: 50%; background: var(--surface-hover); color: var(--ink-3);
}
.cmdk-pg svg { width: 16px; height: 16px; display: block; }
/* What Enter does, said once at the bottom rather than guessed. The palette
   answers six rows per group; the call list answers all of them. */
.cmdk-foot {
  padding: 10px 12px; margin-top: 4px; border-top: 1px solid var(--line);
  font-size: 12px; color: var(--ink-4);
}
.cmdk-name .chip.sm { font-size: 10.5px; padding: 1px 6px; }

@media (max-width: 760px) {
  .tb-searchbtn-lbl, .tb-searchbtn-kbd, .tb-ai-lbl { display: none; }
  .tb-searchbtn { width: auto; min-width: 0; padding: 0 10px; }
  .tb-ai { padding: 0 11px; }
}

.tb-warn {
  display: inline-flex; align-items: center;
  height: 24px; padding: 0 10px;
  border-radius: var(--pill);
  background: var(--red-soft); color: var(--red-ink);
  font-size: var(--t-small); font-weight: 600;
  white-space: nowrap;
}
.tb-warn[hidden] { display: none; }


/* ----------------------------------------------------------------- main */
/* `min-width: 0` is load bearing, not tidying. A grid item's automatic minimum
   size is its content's min-content width, so ONE wide table — the 10-column
   team ranking, the 24-column heatmap — stretched the 1fr column past the
   viewport and the whole page scrolled sideways, .wrap and its overflow-x
   included. With the floor at 0 the track keeps the viewport's width and the
   scrolling happens inside .wrap, where it was designed to. */
/* No width cap. The cap left a wide monitor with a column of content and a
   band of empty page beside it, while the competitor fills the window. Nothing
   here is prose that needs a measure — it is tables, tiles and charts, and they
   all read better with the room. The few blocks that ARE prose set their own
   `max-width` in ch (`.gap-body`, the empty states). */
main { flex: 1; overflow-y: auto; padding: 26px 30px 60px; min-width: 0; }
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; margin-bottom: 20px; }
.page-head h1 { font-size: var(--t-h1); }
.page-head p { margin: 3px 0 0; color: var(--ink-3); font-size: 13px; }

.seg { display: inline-flex; background: var(--line); border-radius: 7px; padding: 2px; gap: 2px; }
.seg button {
  all: unset; padding: 5px 12px; border-radius: 5px; font-size: var(--t-small);
  color: var(--ink-2); cursor: pointer;
  /* A segment is one word or a number and a word; letting it wrap turned
     «3 kun» into a two-line sliver on a phone and the whole control into a
     ragged block. The row around it wraps instead. */
  white-space: nowrap;
}
.seg button[aria-pressed="true"] { background: var(--surface); color: var(--ink); font-weight: 600; box-shadow: 0 1px 2px rgba(0,0,0,.07); }
.seg button:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }

/* The panel's first real button pair. Almost everything here reads, so a
   filled «do it» button had nowhere to appear until Sozlamalar → Profil got a
   field somebody can actually change. Two tones only: `primary` commits,
   `ghost` walks away. Both take the gate button's shape so the one filled
   control in the product and the one on the sign-in card are the same object. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 9px 16px; border: 1px solid transparent; border-radius: var(--radius-xs);
  font: 600 13px/1.2 var(--font-b); cursor: pointer;
  transition: background .16s var(--ease), border-color .16s var(--ease), color .16s var(--ease);
}
.btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.btn:disabled { opacity: .55; cursor: default; }
.btn.primary { background: var(--brand); color: var(--on-brand); }
.btn.primary:hover:not(:disabled) { background: var(--brand-ink); }
.btn.ghost { background: none; border-color: var(--line-2); color: var(--ink-2); }
.btn.ghost:hover:not(:disabled) { background: var(--surface-hover); color: var(--ink); }

/* ---- period control: inline presets + «Boshqa» calendar popover ----------
   Metasell's shape. The presets are the segment above; «Boshqa» opens a popover
   with named ranges on the left and, under «Maxsus», a one-month range calendar
   on the right. */
.period { display: inline-flex; align-items: center; gap: 10px; }
.period-more { position: relative; display: inline-flex; align-items: center; gap: 4px; }
/* «x» to drop an applied custom range, shown only when one is in force. */
.period-clear {
  all: unset; box-sizing: border-box;
  display: grid; place-items: center; width: 26px; height: 26px;
  border-radius: 6px; color: var(--ink-4); cursor: pointer;
  transition: background .14s var(--ease), color .14s var(--ease);
}
.period-clear:hover { background: var(--red-soft); color: var(--red-ink); }
.period-clear:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.period-clear svg { width: 14px; height: 14px; display: block; }
.period-more-btn {
  all: unset; box-sizing: border-box;
  display: inline-flex; align-items: center; gap: 7px;
  height: 32px; padding: 0 11px;
  border-radius: 7px; border: 1px solid var(--line);
  background: var(--surface); color: var(--ink-2);
  font-size: var(--t-small); cursor: pointer;
  transition: border-color .15s var(--ease), background .15s var(--ease), color .15s var(--ease);
}
.period-more-btn:hover { border-color: var(--line-strong); }
.period-more-btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.period-more-btn[aria-pressed="true"] { border-color: var(--brand); color: var(--brand-deep); background: var(--brand-soft-2); font-weight: 600; }
.period-more-ic { display: grid; place-items: center; color: var(--ink-4); flex: none; }
.period-more-btn[aria-pressed="true"] .period-more-ic { color: var(--brand); }
.period-more-ic svg { width: 15px; height: 15px; display: block; }
.period-more-lbl { font-variant-numeric: tabular-nums; }

.period-pop {
  /* Opens LEFTWARD from the «Sana» button, which sits at the RIGHT end of the
     filter bar. Anchored left:0 the ~400px popover ran off the right edge of the
     viewport and clipped the calendar (the reported "opening incorrectly").
     right:0 pins its right edge to the button and opens into the wide content
     area to the left, so the whole calendar stays on screen.
     right:0 is only the STARTING point: on Analitika the button sits near the
     left of <main>, which clips its overflow, and the preset column went under
     the rail. `positionPeriodPop` measures on open and writes an inline `right`
     that shifts it back inside. */
  position: absolute; top: calc(100% + 8px); right: 0; left: auto; z-index: 60;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  overflow: hidden; animation: cmdkIn .13s var(--ease);
}
.period-pop[hidden] { display: none; }
.dp-body { display: flex; align-items: stretch; }
.dp-presets { display: flex; flex-direction: column; gap: 2px; padding: 8px; min-width: 150px; border-right: 1px solid var(--line); }
.dp-preset {
  all: unset; box-sizing: border-box;
  padding: 8px 11px; border-radius: var(--radius-sm);
  font-size: 13px; color: var(--ink-2); white-space: nowrap; cursor: pointer;
  transition: background .14s var(--ease), color .14s var(--ease);
}
.dp-preset:hover { background: var(--surface-hover); color: var(--ink); }
.dp-preset:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.dp-preset.is-active { background: var(--brand-soft-2); color: var(--brand-deep); font-weight: 600; }

.dp-cal { padding: 12px 14px 14px; width: 252px; }
.dp-cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.dp-cal-title { font-size: 13.5px; font-weight: 600; color: var(--ink); }
.dp-nav {
  all: unset; box-sizing: border-box;
  display: grid; place-items: center; width: 28px; height: 28px;
  border-radius: 6px; color: var(--ink-3); cursor: pointer;
}
.dp-nav:hover { background: var(--surface-hover); color: var(--ink); }
.dp-nav:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.dp-nav svg { width: 16px; height: 16px; display: block; }
.dp-weekdays, .dp-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.dp-weekdays { margin-bottom: 4px; }
.dp-weekdays span { text-align: center; font-size: 10.5px; font-weight: 600; color: var(--ink-4); padding: 2px 0; }
.dp-cell {
  all: unset; box-sizing: border-box;
  display: grid; place-items: center; height: 30px;
  font-size: 12.5px; color: var(--ink-2); border-radius: 6px; cursor: pointer;
  transition: background .12s var(--ease), color .12s var(--ease);
}
.dp-empty { cursor: default; }
button.dp-day:hover { background: var(--surface-hover); color: var(--ink); }
.dp-day.dp-future { color: var(--ink-4); opacity: .45; cursor: default; }
/* The selected edges and the in-range fill must WIN over :hover — otherwise
   hovering the day you just picked repaints it white and reads as a glitch. */
.dp-day.in-range, .dp-day.in-range:hover { background: var(--brand-soft); color: var(--brand-deep); border-radius: 0; }
.dp-day.is-edge, .dp-day.is-edge:hover { background: var(--brand); color: #fff; border-radius: 6px; font-weight: 600; }
.dp-day:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }

.dp-hint { margin: 10px 0 0; font-size: 11.5px; color: var(--ink-4); }
.dp-hint-warn { color: var(--red-ink); }
.dp-cal-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
.dp-range-label { font-size: 12px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.dp-actions { display: flex; gap: 6px; flex: none; }
.dp-clear, .dp-apply {
  all: unset; box-sizing: border-box;
  padding: 6px 11px; border-radius: 6px; font-size: 12.5px; font-weight: 600; cursor: pointer;
}
.dp-clear { color: var(--ink-3); }
.dp-clear:hover { background: var(--surface-hover); color: var(--ink); }
.dp-apply { background: var(--brand); color: #fff; }
.dp-apply:hover { filter: brightness(1.05); }
.dp-apply[disabled] { opacity: .45; cursor: default; pointer-events: none; }
.dp-clear:focus-visible, .dp-apply:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* The narrow shape: the presets wrap into a row above the calendar, so the
   popover is one calendar wide. `positionPeriodPop` adds `is-stacked` whenever
   the scroll area is too narrow for the wide shape — a collapsed window, a
   full-width rail — which the viewport media query below cannot see. */
.period-pop.is-stacked .dp-body { flex-direction: column; }
.period-pop.is-stacked .dp-presets {
  flex-direction: row; flex-wrap: wrap; min-width: 0;
  border-right: 0; border-bottom: 1px solid var(--line);
}

@media (max-width: 560px) {
  .dp-body { flex-direction: column; }
  .dp-presets { flex-direction: row; flex-wrap: wrap; min-width: 0; border-right: 0; border-bottom: 1px solid var(--line); }
  .dp-cal { width: auto; }
  .period-pop { right: 0; left: auto; }
}

/* KPI band — deliberately not equal cards: the lead number is bigger. */
/* Four tiles instead of five. A class rather than an inline style, because an
   inline grid-template beats the responsive media query below and the band then
   stays four columns wide on a phone. */
.kpis.four { grid-template-columns: 1.5fr 1fr 1fr 1fr; }
.kpis.three { grid-template-columns: 1fr 1fr 1fr; }
.kpis { display: grid; grid-template-columns: 1.5fr 1fr 1fr 1fr 1fr; gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; margin-bottom: 22px; }
.kpi { background: var(--surface); padding: 15px 17px; }
.kpi dt { font-size: var(--t-eyebrow); font-weight: 700; text-transform: uppercase; letter-spacing: .10em; color: var(--ink-3); margin: 0 0 6px; }
.kpi dd { margin: 0; font-family: var(--font-d); font-weight: 600; font-size: 26px; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.kpi:first-child dd { font-size: 30px; }
.kpi .sub { display: block; font-family: var(--font-b); font-weight: 400; font-size: 13px; color: var(--ink-3); margin-top: 7px; }

/* ------------------------------------------------------------- «Bugun» */

/* The one block on a window-scoped page that is pinned to today, and on the
   employee card the one block that is not all-time. It is a CARD rather than
   the `.kpis` band the surfaces below it use, precisely so the two do not read
   as one row of figures under one period: the header carries the word «Bugun»
   and the caption says the period button does not reach it. */
.today-bar { margin-bottom: 18px; }
/* Dividers are BORDERS on the cells, not the 1px-gap-over-a-tinted-container
   trick `.kpis` uses. Five cells do not divide into two columns, so the gap
   trick painted the unused slot of the last row as a grey block that reads as
   a sixth, broken figure. */
.tdy { display: grid; grid-template-columns: repeat(5, 1fr); background: var(--surface); }
.tdy-cell { padding: 13px 17px; display: flex; flex-direction: column; gap: 5px; border-left: 1px solid var(--line); }
.tdy-cell:first-child { border-left: 0; }
.tdy-label { font-size: var(--t-eyebrow); font-weight: 700; text-transform: uppercase; letter-spacing: .10em; color: var(--ink-3); }
.tdy-value { font-family: var(--font-d); font-weight: 600; font-size: 22px; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.tdy-sub { font-size: 13px; color: var(--ink-3); }
/* Under «Baholandi»: what the answered, ungraded calls are. Quiet, because it
   explains the number above it rather than competing with it. */
.tdy-why { display: flex; flex-wrap: wrap; gap: 2px 10px; font-size: 12px; line-height: 1.35; color: var(--ink-3); }
.tdy-why-item { white-space: nowrap; }
.tdy-why-item b { font-weight: 600; color: var(--ink-2); font-variant-numeric: tabular-nums; }

/* «Qo‘ng‘iroqlar kesimi» — three small tables side by side, the shape the
   client's own telephony panel draws. Dividers are borders on the columns, the
   same choice `.tdy` makes and for the same reason. Each column is its own
   table so the four rows line up across all three at any width. */
.dirs-card { margin-bottom: 18px; }
.dirs { display: grid; grid-template-columns: repeat(3, 1fr); background: var(--surface); }
/* Two panels, and the left one is the wide one: it carries five columns and
   the reasons table under them, against the outcome column's three. */
.dirs.dirs-2 { grid-template-columns: minmax(0, 1.9fr) minmax(0, 1fr); }
/* One panel: the qabul board since «Yakuni» folded into the stage table's
   own columns (4 Oct 2026). */
.dirs.dirs-1 { grid-template-columns: minmax(0, 1fr); }
.dirs-col h3.dirs-sub { margin: 15px 0 8px; }
/* A figure that opens its own list, inside a row that opens a different one.
   NOT `.cell-open`: that name is already the absolutely-positioned chevron a
   card corner carries, and reusing it moved every drill-down number to the
   top-right of the page — visible only in a browser, which is where it was
   caught. The hint is the underline on hover; the row already carries the
   pointer, so a second cursor change would say nothing. */
.dirs-table td.num-open { cursor: pointer; }
.dirs-table td.num-open:hover { text-decoration: underline; }
.dirs-col { padding: 13px 17px 15px; border-left: 1px solid var(--line); min-width: 0; }
.dirs-col:first-child { border-left: 0; }
.dirs-col h3 { font-size: var(--t-eyebrow); font-weight: 700; text-transform: uppercase; letter-spacing: .10em; color: var(--ink-3); margin: 0 0 8px; }
/* The column's own heading row: the label left, its «i» against the far edge,
   over the table it explains. */
.dirs-col h3.dirs-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.dirs-table { width: 100%; border-collapse: collapse; }
.dirs-table td { padding: 6px 8px; font-size: 14px; border-bottom: 1px solid var(--line); }
.dirs-table tr:last-child td { border-bottom: 0; }
.dirs-table td.num { text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; }
/* The answered/unanswered tint is the client's own reading aid, and it is the
   panel's existing good/bad pair rather than a second green and a second red. */
.dirs-table tr.is-yes td { background: var(--green-soft); }
.dirs-table tr.is-no td { background: var(--red-soft); }
.dirs-table tr.dirs-sub-head td { padding-top: 14px; font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-2); }
.dirs-table tr.dirs-sub td { font-size: 13px; padding-top: 4px; padding-bottom: 4px; }
.dirs-table tr.dirs-sub a { color: var(--ink-2, inherit); text-decoration: none; }
.dirs-table tr.dirs-sub a:hover { text-decoration: underline; }
.dirs-table tr.dirs-sub .dim { font-weight: 400; }
/* The total row on the qabul board's «Yakuni» column. A rule above it rather
   than a tint: the two tints above already mean «sold» and «closed», and a
   third colour on a sum would read as a third outcome. */
.dirs-table tr.is-total td { border-top: 2px solid var(--line); font-weight: 600; }
/* A row of the qabul board that has leads behind it uses the product's own
   clickable-row rule (`tbody tr.row`), not `.can-open`: that one is written
   for a CELL — it lifts on hover and paints a shadow, neither of which a
   `<tr>` in a collapsed-border table renders honestly. What the tinted rows
   need on top is only that the tint survives the hover, so «Sotildi» stays
   green while the pointer is on it. */
.dirs-table tbody tr.is-yes.row:hover td { background: var(--green-soft); filter: brightness(.98); }
.dirs-table tbody tr.is-no.row:hover td { background: var(--red-soft); filter: brightness(.98); }
.dirs-table thead th { padding: 0 8px 6px; font-size: var(--t-eyebrow); font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em; color: var(--ink-3); text-align: left; }
.dirs-table thead th.num { text-align: right; }

/* The funnel's rung bars. A bar beside the number, not instead of it: the
   count is the fact and the bar is only the shape, so it is the last column
   and carries no label of its own. */
.fnl-table { width: 100%; }
.fnl-table td.fnl-bar { width: 40%; padding-right: 0; }
.fnl-bar i {
  display: block;
  height: 8px;
  border-radius: 4px;
  background: var(--green-soft);
  box-shadow: inset 0 0 0 1px var(--line);
  min-width: 2px;
}
.fnl-name { font-weight: 600; }

/* A total that is not the whole floor has to say so, wherever it is drawn. */
.plan-scoped { margin: 0 0 14px; }

@media (max-width: 760px) {
  .dirs { grid-template-columns: 1fr; }
  .dirs-col { border-left: 0; border-top: 1px solid var(--line); }
  .dirs-col:first-child { border-top: 0; }
}

/* Five cells is a comfortable row on a laptop and five slivers on a phone.
   The row borders move with the columns: on two columns every cell past the
   first pair grows a top rule, and the left-hand column loses its left one. */
@media (max-width: 900px) {
  .tdy { grid-template-columns: repeat(2, 1fr); }
  .tdy-cell { border-top: 1px solid var(--line); }
  .tdy-cell:nth-child(-n+2) { border-top: 0; }
  .tdy-cell:nth-child(odd) { border-left: 0; }
}

.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; align-items: start; }
.sales-board { min-width: 0; }
.sales-board > header .hint { white-space: normal; text-align: right; }
/* Two boards share a row only when a WHOLE board fits in a track. At 540px
   each of these seven columns — a name, five counts and a summa carrying its
   «230/234 ma'lum» note, none of which may wrap — overflowed its own `.wrap`
   by a little, so both halves of a side-by-side pair hid their last column
   behind a scrollbar. The track floor is the table's own min-content width
   instead: under it the boards stack and each one is drawn in full. */
.sales-board-groups { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 720px), 1fr)); gap: 18px; align-items: start; }
/* The function filter sat flush on the first group's card (Bioflex, 15 Oct 2026). */
.seg.sales-fn { margin-bottom: 16px; }
.sales-detail { margin: 18px 0; }
.sales-detail > summary { cursor: pointer; font-weight: 600; padding: 12px 0; }
/* The reconciliation between «Jami» and the client's own pipeline. It sits
   ABOVE the board rather than in the audit trail below it, because it is the
   sentence that stops the total reading as the whole day — so its summary is
   ruled off and indented away from the tables it is explaining. */
.sales-offboard > summary {
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 11px 14px; font-weight: 500; color: var(--ink-2);
  font-size: var(--t-small);
}
.sales-offboard[open] > summary { margin-bottom: 10px; }
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; }
.card > header { padding: 13px 17px; border-bottom: 1px solid var(--line); display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.card > header h2 { font-size: var(--t-h2); }
.card > header .hint { font-size: var(--t-small); color: var(--ink-3); }
/* A hint that ends in an «i». The header is `align-items: baseline`, so the
   mark has to sit inside the hint rather than beside it: as a third flex child
   a 14px circle baselines against a line of text and rides two pixels low. */
.card > header .hint-info { display: inline-flex; align-items: center; gap: 6px; }
.card .body { padding: 15px 17px; }

/* --------------------------------------------------------------- tables */
table { width: 100%; border-collapse: collapse; }
thead th {
  text-align: left; font-size: var(--t-eyebrow); text-transform: uppercase; letter-spacing: .08em;
  color: var(--ink-3); font-weight: 600; padding: 9px 12px; border-bottom: 1px solid var(--line);
  background: var(--surface-hover); position: sticky; top: 0; z-index: 1;
}
tbody td { padding: 11px 12px; border-bottom: 1px solid var(--line); vertical-align: middle; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr.row { cursor: pointer; }
tbody tr.row:hover { background: var(--surface-hover); }
tbody tr.row:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.num { font-family: var(--font-b); font-variant-numeric: tabular-nums; text-align: right; }
/* Tabular figures WITHOUT right alignment. A timestamp or a phone number is an
   identifier you read left-to-right, not a magnitude you compare down a
   column — right-aligning them left the headers stranded over empty space. */
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* A colleague on the far end of an internal call. Deliberately NOT `.mono`:
   the cell holds a person's name, and a name is not an identifier you scan
   down a column. It keeps the body face and only loses a little weight so the
   client rows around it stay the ones that read as numbers. */
.peer-seat { color: var(--ink-2); }

/* The floor's own row under a per-operator table. Sticky to the bottom of the
   scroll box so the comparison stays on screen while the reader scrolls the
   rows it is there to be compared against — a benchmark that scrolls away is
   a benchmark nobody uses. */
/* The period control on the employee card sits at the end of the identity row
   rather than in a header of its own: the card opens with a written verdict,
   and a control above that sentence would push the one thing the page exists
   to say below the fold. */
.lede-eyebrow .period { margin-left: auto; }
@media (max-width: 720px) {
  .lede-eyebrow .period { margin-left: 0; width: 100%; }
}

/* Group blocks on the Operatorlar table.
 *
 * Bioflex reads their own sheet as four group sections, so the rows are banded
 * by team. The heading is a th spanning the row rather than a separate table,
 * which keeps every group on ONE set of columns and one scale -- four tables
 * would let two groups drift into two different-width layouts on the same page.
 * The subtotal is quieter than the floor row below it, because it is a sum of
 * the rows drawn and not the tenant's own total. */
tbody.group + tbody.group .group-head th { padding-top: 18px; }
.group-head th {
  text-align: left;
  font: 600 12px/1.4 var(--font-display, inherit);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-2);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  padding: 12px 12px 6px;
}
.group-head .dim {
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
  margin-left: 8px;
}
.group-sub td {
  background: color-mix(in oklab, var(--surface-hover) 55%, transparent);
  border-top: 1px solid var(--line);
}

tfoot .floor-row td {
  padding: 11px 12px;
  position: sticky;
  bottom: 0;
  background: var(--surface-hover);
  border-top: 1px solid var(--line);
  border-bottom: 0;
}
.peer-arrow { color: var(--ink-3); }
/* Headers must sit over their own data. */
thead th.num { text-align: right; }

/* A sortable header is a control, so it looks like one on hover and focus. The
   button inherits the header's type rather than growing its own, and the active
   column is the only one that goes to full ink. */
thead th button.sort {
  all: unset; cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px;
  color: inherit; font: inherit; letter-spacing: inherit; text-transform: inherit;
  white-space: nowrap;
}
thead th.num { white-space: nowrap; }
thead th button.sort:hover { color: var(--ink); }
thead th button.sort:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; border-radius: 3px; }
thead th[aria-sort]:not([aria-sort="none"]) button.sort { color: var(--ink); }
thead th button.sort .caret { font-size: 9px; color: var(--brand-ink); }

/* Eight columns is more than an eye tracks unaided, so a row lights up under the
   pointer even though there is nowhere to click through to. */
table.sortable tbody tr:hover { background: var(--surface-hover); }

/* An abandoned call is the one row in the list a manager must not scroll past.
   The chip says it in words; this says it before the words are read. */
tbody tr.lost td:first-child { box-shadow: inset 3px 0 0 var(--red); }
.dim { color: var(--ink-3); }
.wrap { overflow-x: auto; }

/* Sticky header, Metasell's shape: the wrap is the scroll container, bounded so
   the rows scroll under a header pinned to its top (thead th already declares
   `position: sticky; top: 0`, which only works once something can scroll behind
   it). Used on the operators and calls tables. */
.wrap-scroll { max-height: calc(100vh - 232px); overflow: auto; }
.wrap-scroll thead th { z-index: 2; }
@media (max-width: 900px) {
  .wrap-scroll { max-height: calc(100vh - 268px); }
}

/* A side-by-side pair where one table dwarfs the other: 46 operators next to
   7 source numbers left the right card floating over a page of empty space,
   and the pair's height was whatever the long side wanted. `match` makes the
   pair share ONE bounded height — the tall table scrolls inside its card
   under the sticky header, the short one stretches to the same edge. */
.grid.match { align-items: stretch; }
.grid.match > .card { display: flex; flex-direction: column; max-height: 560px; }
.grid.match > .card > .wrap { flex: 1; min-height: 0; overflow: auto; }
.grid.match > .card > .wrap thead th { z-index: 2; }

/* score + state chips — colour is always paired with text */
.chip {
  box-shadow: var(--shadow-xs); display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px; border-radius: 999px; font-size: 11.5px; font-weight: 600; white-space: nowrap; }
.chip.good { background: var(--green-soft); color: var(--green); }
.chip.warn { background: var(--amber-soft); color: var(--amber); }
.chip.bad  { background: var(--red-soft);  color: var(--red-ink); }
.chip.mute { background: var(--surface-hover); color: var(--ink-3); box-shadow: none; }
.chip.accent { background: var(--brand-soft); color: var(--brand-ink); }
.dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }

.bar { height: 5px; border-radius: 3px; background: var(--line); overflow: hidden; min-width: 54px; }
.bar > i { display: block; height: 100%; border-radius: 3px; }

/* ---------------------------------------------------------- filter bar --- */
/* Search first, then the three narrowings, then a way out. Segmented controls
   rather than dropdown chips: each of these has three or four values, and a
   popover to choose one of three is a click and a wait in place of a click.
   The bar wraps rather than scrolling, so nothing is hidden off the right
   edge on a laptop. */
.filterbar {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 10px 14px;
  margin-bottom: 18px;
}
.filterbar-segs { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 10px; flex: 1 1 auto; }
/* `.linkish` is the gate's full-width form button. Left alone it takes a line
   of its own here and centres itself under the segments. */
.filterbar .linkish { display: inline-block; width: auto; margin: 0; padding: 6px 10px; }
.filterbar-label {
  font-size: var(--t-eyebrow); font-weight: 700;
  letter-spacing: .10em; text-transform: uppercase;
  color: var(--ink-4);
}

/* ------------------------------------------------------ person + row ---- */
/* A table of 91 operators is scanned for a person, not read name by name. The
   disc gives each one a stable shape to find; the tint is a hash of the name so
   it survives sorting, filtering and reloads. Soft ground with the strong ink
   on top, as kit.css builds `.stat-ic` — a saturated fill with white initials
   would be the loudest thing on a page whose subject is the score. */
.who { display: inline-flex; align-items: center; gap: 10px; min-width: 0; }
.who-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.who-note { display: block; font-size: 12px; margin-top: 4px; padding-left: 38px; }

.avatar {
  width: 28px; height: 28px; flex: none;
  border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--font-d);
  font-size: 11px; font-weight: 700; letter-spacing: .02em;
  text-transform: uppercase;
  user-select: none;
}
.avatar.t0 { background: var(--brand-soft); color: var(--brand-deep); }
.avatar.t1 { background: var(--blue-soft);  color: var(--blue); }
.avatar.t2 { background: var(--violet-soft); color: var(--violet); }
.avatar.t3 { background: var(--amber-soft); color: var(--amber); }
.avatar.t4 { background: var(--green-soft); color: var(--green); }
.avatar.none { background: var(--surface-hover); color: var(--ink-4); }

/* Direction is glanced at, not compared, so it carries a glyph. The tints stay
   quiet on purpose: this column must not outrank the score two columns over. */
.dirchip {
  display: inline-flex; align-items: center; gap: 6px;
  height: 24px; padding: 0 9px;
  border-radius: var(--pill);
  font-size: var(--t-small); font-weight: 600;
  white-space: nowrap;
}
.dirchip svg { flex: none; }
.dirchip.in { background: var(--blue-soft); color: var(--blue); }
.dirchip.out { background: var(--brand-soft); color: var(--brand-deep); }
.dirchip.internal { background: var(--surface-hover); color: var(--ink-2); }
.dirchip.unknown { background: var(--surface-hover); color: var(--ink-3); }
/* Icon and tint only — the word is dropped so the row stops pushing the table
   past the viewport. A fixed square keeps the column narrow and aligned. */
.dirchip-ic { width: 26px; padding: 0; gap: 0; justify-content: center; }
.cell-dir { text-align: center; }

/* The call list is nine columns wide, so it is compacted to fit rather than left
   to scroll sideways: a smaller body face and tighter cells, the direction cut
   to its glyph. Only this table — the operator and source tables have room. */
.filterbar-calls { gap: 8px 10px; }
.filterbar-calls .seg button { padding: 5px 9px; }

/* Inline search — the first control on the bar, Metasell's shape. A quiet field
   with a leading magnifier that grows to take the slack so the chips sit tight
   to the right. */
.calls-search {
  display: inline-flex; align-items: center; gap: 7px;
  height: 32px; padding: 0 11px;
  border-radius: 7px; border: 1px solid var(--line);
  background: var(--surface);
  flex: 1 1 220px; max-width: 340px; min-width: 170px;
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.calls-search:focus-within { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft-2); }
.calls-search-ic { display: grid; place-items: center; color: var(--ink-4); flex: none; }
.calls-search-ic svg { width: 15px; height: 15px; display: block; }
.calls-search-in {
  all: unset; box-sizing: border-box;
  flex: 1 1 auto; min-width: 0;
  font-size: var(--t-small); color: var(--ink);
}
.calls-search-in::placeholder { color: var(--ink-4); }
.calls-search-in::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }

/* Filter chips — a labelled pill that opens a dropdown, styled to match the
   «Sana» button (.period-more-btn) so the whole bar reads as one control set. */
.chip-wrap { position: relative; display: inline-flex; }
.filter-chip {
  all: unset; box-sizing: border-box;
  display: inline-flex; align-items: center; gap: 6px;
  height: 32px; padding: 0 10px;
  border-radius: 7px; border: 1px solid var(--line);
  background: var(--surface); color: var(--ink-2);
  font-size: var(--t-small); cursor: pointer;
  transition: border-color .15s var(--ease), background .15s var(--ease), color .15s var(--ease);
}
.filter-chip:hover { border-color: var(--line-strong); }
.filter-chip:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.filter-chip.is-active { border-color: var(--brand); color: var(--brand-deep); background: var(--brand-soft-2); font-weight: 600; }
.chip-badge {
  display: inline-grid; place-items: center;
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: var(--pill);
  background: var(--brand); color: #fff;
  font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.chip-caret { display: grid; place-items: center; color: var(--ink-4); flex: none; }
.filter-chip.is-active .chip-caret { color: var(--brand); }
.chip-caret svg { width: 14px; height: 14px; display: block; transition: transform .15s var(--ease); }
.filter-chip[aria-expanded="true"] .chip-caret svg { transform: rotate(180deg); }

.chip-pop {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 60;
  min-width: 210px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  overflow: hidden; animation: cmdkIn .13s var(--ease);
}
.chip-pop[hidden] { display: none; }
.chip-menu { display: flex; flex-direction: column; gap: 2px; padding: 6px; }
.chip-menu-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 4px 8px 6px; margin-bottom: 2px;
  border-bottom: 1px solid var(--line);
  font-size: var(--t-eyebrow); font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-4);
}
.chip-menu-head .linkish { width: auto; margin: 0; padding: 0; font-size: 11.5px; }
.chip-opt {
  all: unset; box-sizing: border-box;
  display: flex; align-items: center; gap: 9px;
  padding: 7px 9px; border-radius: var(--radius-sm);
  font-size: 13px; color: var(--ink-2); white-space: nowrap; cursor: pointer;
  transition: background .14s var(--ease), color .14s var(--ease);
}
.chip-opt:hover { background: var(--surface-hover); color: var(--ink); }
.chip-opt:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.chip-opt.is-on { color: var(--ink); font-weight: 600; }
/* The tick sits in a fixed box so labels align whether ticked or not; empty
   rows show a quiet outline, ticked rows the brand fill. */
.chip-tick {
  display: grid; place-items: center; flex: none;
  width: 18px; height: 18px; border-radius: 5px;
  border: 1.5px solid var(--line-strong); color: transparent;
  transition: background .14s var(--ease), border-color .14s var(--ease), color .14s var(--ease);
}
.chip-tick svg { width: 13px; height: 13px; display: block; }
.chip-opt.is-on .chip-tick { background: var(--brand); border-color: var(--brand); color: #fff; }
/* The single-select direction menu reads as radios, so its tick box is round. */
[data-chip-pop="dir"] .chip-tick { border-radius: 50%; }
/* Operatorlar's three chips are single-select too, so they wear the same round
   tick. Guruh can hold a group per row, so its menu scrolls rather than growing
   past the viewport on a tenant with many teams. */
[data-chip-pop="opteam"] .chip-tick,
[data-chip-pop="opanalyzed"] .chip-tick,
[data-chip-pop="opband"] .chip-tick { border-radius: 50%; }
[data-chip-pop="opteam"] .chip-menu { max-height: 320px; overflow-y: auto; }

/* How many rows the table is showing, pushed to the far end of the bar. A
   filtered table looks exactly like a small floor; this line is what tells the
   two apart, so it sits on the bar rather than under the table. */
.filter-count {
  margin-left: auto;
  font-size: var(--t-small); color: var(--ink-4);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

@media (max-width: 560px) {
  .chip-pop { left: 0; right: auto; }
  .calls-search { flex-basis: 100%; max-width: none; }
}
.calls-table thead th { padding: 7px 9px; }
/* 6px, not 8: at ~50px a row the two vertical pixels are a whole extra row
   per screenful, and the row still clears the 28px avatar comfortably. */
.calls-table tbody td { padding: 6px 9px; font-size: 13px; }
.calls-table .cell-when span { font-size: 11px; }
.cell-dir .dirchip { gap: 5px; }
/* The direction shows its word when the table has room and drops to the glyph
   only when the viewport is tight, so a wide screen reads «Kiruvchi/Chiquvchi»
   and a laptop still fits nine columns without a sideways scroll. */
@media (max-width: 1400px) {
  .calls-table .cell-dir .dir-word { display: none; }
  .calls-table .cell-dir .dirchip { width: 26px; padding: 0; gap: 0; justify-content: center; }
}

/* The infinite-scroll sentinel: a quiet loading strip under the table, shown
   only while another cursor page remains. It carries a spinner that spins only
   while a page is actually in flight (`.is-loading`), so at rest it reads as a
   calm «more below» rather than a permanent busy state. */
.load-more { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 14px 0 2px; color: var(--ink-4); font-size: var(--t-small); }
.load-more[hidden] { display: none; }
.load-spin {
  width: 14px; height: 14px; flex: none; border-radius: 50%;
  border: 2px solid var(--line-strong); border-top-color: var(--brand);
  opacity: 0;
}
.load-more.is-loading .load-spin { opacity: 1; animation: callsSpin .7s linear infinite; }
@keyframes callsSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .load-more.is-loading .load-spin { animation: none; }
}

/* Loading skeleton, painted the instant a view changes so a tap never feels
   ignored while its data is in flight. The SHAPE is built in skeleton.js out of
   the page's own containers — `.card`, `.grid`, `.kpis`, a real `<table>` — so
   the geometry comes from the rules above and stays right when they change.
   All this needs to add is the shimmer itself.

   Block, not inline: a bar is a stand-in for a line of text or a whole figure,
   and inline ones collapsed a four-line hero into one grey stripe. The bottom
   margin is what separates two stacked bars; it costs 8px inside a flex ROW,
   which is a price worth paying for not needing a rule per container. */
.sk-bar {
  display: block;
  max-width: 100%;
  height: 12px;
  border-radius: 6px;
  margin-bottom: 8px;
  /* Keyed off `--line`, not `--surface-hover`. A bar drawn in the lighter tone
     is invisible against the page background and against a table header, which
     are both within a shade of it — the call detail's lede sits directly on
     `--bg` and read as a blank screen while it loaded. */
  background: linear-gradient(90deg, var(--line) 25%, var(--line-2) 37%, var(--line) 63%);
  background-size: 400% 100%;
  animation: sk-shimmer 1.4s ease infinite;
}
.sk-bar:last-child { margin-bottom: 0; }
/* A bar inside a flex ROW — a badge strip, a card header, a filter bar. The
   bottom margin would otherwise become 8px of extra height on the whole row,
   which is a period switcher rendering 41px tall against the real 33px. */
.sk-bar.row { margin-bottom: 0; }
/* A text line: the box keeps the leading, the bar inside draws only the ink. */
.sk-line { display: flex; align-items: center; }
/* A table cell is one value on one line: a bar there must not push the row
   taller than the real row it stands in for. */
td > .sk-bar, th > .sk-bar { margin-bottom: 0; }
/* Nothing in a skeleton is pressable. The tab strip is rendered with real
   buttons so it keeps the real strip's height and underline. */
.tabs button:disabled { cursor: default; }
@keyframes sk-shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }
@media (prefers-reduced-motion: reduce) { .sk-bar { animation: none; } }

/* The clock leads and the date supports it. A call list is almost always one
   day, so the time is the value being compared and the date is context; on one
   line they competed and the seconds got lost at the end of the string. */
.cell-when { white-space: nowrap; }
.cell-when b { display: block; font-weight: 600; font-variant-numeric: tabular-nums; }
.cell-when span { display: block; font-size: 11.5px; font-variant-numeric: tabular-nums; margin-top: 2px; }

/* ====================================================== call detail ==== */
.crumb { all: unset; cursor: pointer; color: var(--ink-3); font-size: var(--t-small); display: inline-block; }
/* The way back and the label of where you are belong on one line: stacked,
   they cost a whole row of vertical space above the sentence that matters. */
.lede-eyebrow .crumb { padding-right: 12px; border-right: 1px solid var(--line); }
.crumb:hover { color: var(--brand-ink); }
.crumb:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* The lede. Two columns: what happened on the left at full size, how it scored
   on the right. Nothing else competes with these until you pick a tab. */
.lede {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 264px;
  gap: 34px;
  align-items: stretch;
  margin-bottom: 26px;
}
/* The scoreboard is usually the taller column. Bottom-aligning the player
   against it turns what was a stranded band of white into a deliberate edge. */
.lede > div:first-child { display: flex; flex-direction: column; }
/* No score, no lead, no deal — nothing to put in the rail, so it goes away. */
.lede.solo { grid-template-columns: minmax(0, 1fr); }
/* No audio player to bottom-align against, so the columns simply start
   together rather than stretching a hundred pixels of void under the facts. */
.lede.compact { align-items: start; }
/* The employee card: its rail (score, weak calls, CRM deals) is far taller
   than a three-line headline, which stranded a band of dead white between
   the facts and «Bugun». The today bar climbs into that band — left column's
   second row, pinned to the grid's bottom edge, while the rail spans both
   rows. The stacked breakpoint resets the placements below. */
.lede.has-today { grid-template-rows: auto 1fr; }
.lede.has-today > div:first-child { grid-row: 1; grid-column: 1; }
.lede.has-today > .scoreboard { grid-row: 1 / 3; grid-column: 2; }
.lede.has-today > .today-bar { grid-row: 2; grid-column: 1; align-self: end; margin-bottom: 0; }
.lede.solo .facts { margin-bottom: 0; }
/* ...but only when nothing follows them.
   The rule above exists so a bottom-aligned player does not sit under a double
   gap. In SOLO there is no scoreboard to bottom-align against, so the player's
   `margin-top: auto` resolves to zero — and with the facts' own margin already
   removed, the chip strip ended up flush against the player, play button
   touching the chips. Two spacing mechanisms cancelling each other out leaves
   none, so this puts one back for exactly that case. */
.lede.solo .facts + .player { margin-top: 18px; }
/* Wraps, because the judgement beside the label is a sentence and a long stage
   name pushes the lead chip past the edge of a laptop column. */
.lede-eyebrow { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 10px; margin-bottom: 12px; }
.lede-eyebrow span.label {
  font-size: var(--t-eyebrow); text-transform: uppercase; letter-spacing: .13em;
  color: var(--ink-3); font-weight: 600;
}

/* The derived judgement: where the call left the customer, in one clause.
   Deliberately NOT a chip. It sits directly above the summary sentence, and two
   filled pills stacked on one sentence would read as two headlines; the dot
   carries the tone and the text stays quiet enough to stay subordinate. */
.judgement {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--t-small); color: var(--ink-2); font-weight: 500;
}
.judgement.good .dot { background: var(--green); }
.judgement.warn .dot { background: var(--amber); }
.judgement.bad .dot { background: var(--red-ink); }
.lede h1 {
  font-size: var(--t-lede);
  line-height: 1.32;
  letter-spacing: -0.022em;
  max-width: 56ch;
  font-weight: 600;
}
.lede h1.quiet { color: var(--ink-2); font-weight: 500; }

/* Facts about the call, not about its quality. Small, grey, one line. */
.facts { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 16px; margin-bottom: 22px; }
.fact {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; border-radius: var(--pill);
  border: 1px solid var(--line); background: var(--surface);
  font-size: var(--t-small); color: var(--ink-2); white-space: nowrap;
}
.fact.mono { font-family: var(--mono); }
.fact.ok { border-color: transparent; background: var(--green-soft); color: var(--green); font-weight: 600; }
.fact.miss { border-color: transparent; background: var(--surface-hover); color: var(--ink-3); }
/* A call the customer gave up on is not a neutral non-event, so it does not get
   the grey the other unreached calls get. */
.fact.lost { border-color: transparent; background: var(--red-soft); color: var(--red-ink); font-weight: 600; }
.fact b { font-family: var(--font-b); font-variant-numeric: tabular-nums; font-weight: 600; color: var(--ink); }
/* The one fact that leaves the product. It is a link, so it behaves like one:
   the brand colour and the glyph say the click ends up somewhere else. */
.fact.link { text-decoration: none; color: var(--brand-ink); border-color: var(--brand-soft); background: var(--brand-soft); }
.fact.link b { color: inherit; }
.fact.link svg { opacity: .7; }
/* Deepens the tint rather than inverting to the brand fill: --on-brand is white
   in both themes and white on the dark --brand is a 2.4:1 label. */
.fact.link:hover { background: var(--brand-soft-2); border-color: var(--brand); }
.fact.link:hover svg { opacity: 1; }
.fact.link:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* The scoreboard: the one place the page raises its voice. */
.scoreboard { border-left: 1px solid var(--line); padding-left: 26px; }
.scoreboard .label {
  display: block; font-size: var(--t-eyebrow); text-transform: uppercase;
  letter-spacing: .13em; color: var(--ink-3); font-weight: 600; margin-bottom: 8px;
}
.scoreboard .value { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.scoreboard .value b {
  font-family: var(--font-d); font-size: 38px; line-height: 1;
  letter-spacing: -0.045em; font-weight: 600; font-variant-numeric: tabular-nums;
}
.scoreboard .value .of { font-family: var(--font-b); font-variant-numeric: tabular-nums; font-size: 15px; color: var(--ink-3); }
.scoreboard .bar { margin-top: 14px; height: 4px; }
.scoreboard .lead { margin-top: 22px; padding-top: 20px; border-top: 1px solid var(--line); }
.scoreboard .lead p { margin: 9px 0 0; font-size: var(--t-small); color: var(--ink-2); }

/* -------------------------------------------------------- audio player */
/* The player is vidstack — the same one the Reveo workspace uses for «Разбор
   звонка» — vendored under /vendor/vidstack and loaded only when a call is
   opened. Its own theme.css ships the control grammar; everything below is
   the Reveo skin over it, so the most-used control on the page belongs to the
   palette rather than sitting in it as a foreign object.

   Range requests are served by the API, which is what makes seeking work. */
.player { margin-top: auto; position: relative; border-radius: var(--radius-sm); }

/* The skin is the AUDIO strip's alone, and it is written against the LAYOUT
   element rather than the player.

   Two things make that necessary. vidstack names its palette twice —
   `--audio-*` first, `--default-*` as the fallback — and the layout sets its
   OWN `--default-*` from a `light`/`dark` class it adds to itself at runtime,
   so a value declared on the ancestor <media-player> is a value the closer
   rule overwrites: the strip rendered stock black inside a white card with a
   full set of declarations above it that nothing read. (The set before this
   one was worse — `--media-audio-bg` and its siblings are names vidstack has
   never had.) And the strip's own background and border are plain properties
   on that element, not tokens at all.

   `--audio-slider-track-bg` is deliberately absent: the layout spells the
   FILL as `var(--audio-slider-track-bg, var(--media-brand))`, so setting the
   track paints the played part the same colour as the unplayed one and the
   progress vanishes. `--media-slider-track-bg` is set directly instead.

   Menus and tooltips are NOT skinned: the layout portals them to the body, so
   nothing scoped here reaches them — and dark menus over a player is the
   grammar this control was adopted for. */
.player:not(.has-video) {
  --audio-font-family: var(--font-b);
  --audio-border-radius: var(--radius-sm);
  --audio-brand: var(--brand);
  /* Every control's icon colour comes off this one token; the layout's own
     `color` is only the title's. */
  --audio-controls-color: var(--ink-2);
  --audio-play-button-bg: var(--brand);
  --audio-play-button-color: var(--on-brand);
  --media-focus-ring-color: var(--brand);
}
/* The scrubber is ALWAYS there, and the title is never.

   vidstack's audio layout draws the call's title across the middle of the row
   and keeps the seek bar at `max-width: 0` until playback starts — the title
   slides out, the bar slides in. That is a music player's bargain and it is
   the wrong one here: this control exists to be dragged to minute four of a
   conversation, a manager should not have to start playing to find out they
   can, and the transcript seeks into a bar the reader has never seen. The
   title is redundant besides — the fact chips directly above the player
   already name who the call was with. The `title` ATTRIBUTE stays: it is what
   the layout announces to a screen reader and shows in fullscreen. */
.player:not(.has-video) .vds-title { display: none; }
.player:not(.has-video) .vds-time-slider {
  opacity: 1;
  max-width: 100%;
  transform: none;
  visibility: visible;
  transition: none;
}
.player:not(.has-video) .vds-audio-layout {
  background-color: var(--surface);
  border: 1px solid var(--line);
  /* The stock drop-shadow is sized for a control floating on a page; this one
     sits in a card that already has one. */
  filter: none;
  --media-slider-track-bg: var(--line-2);
  --media-time-color: var(--ink-2);
}
/* A demo is WATCHED, so its chrome is the one everybody already knows: white
   controls over the picture, dark menus, the way YouTube draws them in either
   theme. The video layout keeps vidstack's own palette for exactly that
   reason — the panel's light surface behind a control that sits ON a black
   frame would be the foreign object here, not the other way round. */
.player.has-video {
  --video-font-family: var(--font-b);
  --video-brand: var(--brand);
  --video-border: 1px solid var(--line);
  --video-border-radius: var(--radius-sm);
  /* The cap is on the WIDTH, and that is the whole trick. vidstack gives a
     video player `aspect-ratio: 16/9` and the <video> inside it
     `height: auto; object-fit: contain`, so a `max-height` does not shrink the
     picture — it shortens the BOX while the video keeps its full height, and
     `overflow: hidden` then crops the frame rather than letterboxing it, with
     the control row auto-hiding somewhere under the cut. Capping the width at
     the same ratio makes the height follow on its own: a demo is never taller
     than the fold, nothing is cropped, and the controls stay inside the box
     they are positioned against. The background, the border and the radius
     are vidstack's own tokens — it paints the frame itself. */
  max-width: calc(70vh * 16 / 9);
}
/* What stands where the player would have been: a sentence when there is
   nothing to play, the browser's own control when only OUR player failed. */
.player-empty { margin: 0; font-size: var(--t-small); color: var(--ink-3); }
.player-fallback { margin-top: auto; width: 100%; }

/* The timecode is the one figure in this control a reader compares down a
   column — 0:24 against 3:28 — so it gets the tabular numerals the rest of
   the panel's figures get. */
.player [class*='vds-time'] { font-variant-numeric: tabular-nums; }

/* «Yuklash» and the loading note are ours, not vidstack's, and they sit under
   the control rather than inside its bar: the layout owns its own row and
   anything pushed into it gets laid out as a control it does not know. */
.player .dl {
  all: unset; cursor: pointer; font-size: var(--t-small); color: var(--ink-2);
  padding: 4px 9px; border-radius: 6px;
  position: absolute; right: 10px; bottom: -30px;
}
.player .dl:hover { background: var(--surface-hover); color: var(--ink); }
.player .dl:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.player-note {
  font-size: var(--t-small); color: var(--ink-4); white-space: nowrap;
  position: absolute; left: 10px; bottom: -30px;
}

/* -------------------------------------------------------------- tabs */
.tabs { display: flex; gap: 30px; border-bottom: 1px solid var(--line); margin-bottom: 24px; }
.tabs button {
  all: unset; cursor: pointer;
  padding: 0 0 13px; margin-bottom: -1px;
  font-size: var(--t-small); font-weight: 600;
  text-transform: uppercase; letter-spacing: .11em;
  color: var(--ink-3);
  border-bottom: 2px solid transparent;
  display: flex; align-items: center; gap: 8px;
}
.tabs button:hover { color: var(--ink-2); }
.tabs button[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--brand); }
.tabs button:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; border-radius: 3px; }
.tabs button .count { font-family: var(--font-b); font-variant-numeric: tabular-nums; font-size: 11px; font-weight: 500; letter-spacing: 0; color: var(--ink-3); }

/* -------------------------------------------------------- xulosa panel */
/* Did-well / to-improve sit side by side with a hairline between them, not in
   two boxes: they are one judgement read across, not two unrelated readings. */
.verdicts {
  display: grid; grid-template-columns: 1fr 1fr; gap: 0;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-sm); overflow: hidden;
}
.verdicts > div { padding: 20px 24px; }
.verdicts > div + div { border-left: 1px solid var(--line); }
.verdicts h3 {
  display: flex; align-items: center; gap: 8px;
  font-size: var(--t-h2); margin-bottom: 14px;
}
.verdicts h3.good { color: var(--green); }
.verdicts h3.bad { color: var(--amber); }
.verdicts ul { margin: 0; padding: 0; list-style: none; }
.verdicts li {
  position: relative; padding-left: 16px; margin-bottom: 11px;
  font-size: 14.5px; line-height: 1.55; color: var(--ink-2);
}
.verdicts li:last-child { margin-bottom: 0; }
.verdicts li::before {
  content: ""; position: absolute; left: 0; top: .62em;
  width: 5px; height: 5px; border-radius: 50%; background: currentColor; opacity: .45;
}
.verdicts li.good::before { background: var(--green); opacity: 1; }
.verdicts li.bad::before { background: var(--amber); opacity: 1; }

.phrase {
  margin: 18px 0 0; padding: 18px 22px;
  border-radius: var(--radius-sm); background: var(--brand-soft);
  font-size: 15px; line-height: 1.55; color: var(--ink);
}
.phrase b {
  display: flex; align-items: center; gap: 8px;
  font-size: var(--t-eyebrow); text-transform: uppercase; letter-spacing: .11em;
  color: var(--brand-ink); margin-bottom: 8px;
}
.phrase svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.7; }

/* The stages of the call, one row each, the verdict word pinned right.
   Read DOWN, unlike the dynamics strip beside it: these are the same question
   asked of six different minutes of one conversation, so the eye wants a
   column of answers to run past, and the value chips line up into it. */
.dims {
  margin: 0; padding: 0; list-style: none;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-sm); overflow: hidden;
}
.dims li {
  display: grid; grid-template-columns: minmax(0, 12rem) minmax(0, 1fr) auto;
  align-items: center; gap: 6px 18px;
  padding: 12px 18px;
}
.dims li + li { border-top: 1px solid var(--line); }
.dims li:hover { background: var(--surface-hover); }
.dims .dim-name { font-weight: 600; font-size: 14px; }
.dims .dim-detail { font-size: var(--t-small); color: var(--ink-3); font-variant-numeric: tabular-nums; }
/* Narrow: the name keeps its line and the count drops under it, rather than
   the three columns crushing the verdict word into two lines. */
@media (max-width: 720px) {
  .dims li { grid-template-columns: minmax(0, 1fr) auto; }
  .dims .dim-name { grid-area: 1 / 1; }
  .dims .dim-detail { grid-area: 2 / 1; }
  .dims li .chip { grid-area: 1 / 2 / 3 / 3; align-self: center; }
}

/* Deterministic voice metrics, read across as a strip rather than down as a
   list: they are all the same kind of fact and none deserves its own row. */
/* The separators are drawn BY THE CELLS and pulled 1px under the frame, not
   by a 1px gap over a `--line` ground. A strip holds whatever number of facts
   its card has — «Lidlar» has nine — so auto-fit routinely leaves a tail of
   empty track on the last row, and with the ground showing through, that tail
   was a wide grey block hanging off the one cell that wrapped. Painted this
   way an unused tail is simply card, and the rule count no longer has to
   divide by the column count. */
/* A GRID, AND THE BORDERS POINT FORWARD — RIGHT AND BOTTOM, NOT TOP AND LEFT.
   The separators are drawn by each cell's own borders; the container has no
   rule of its own between rows. Two constraints meet here:
   — Rows must share tracks. Wrapping flex sizes every row independently, so a
     nine-figure card broke 5 over 4 with the bottom row's dividers landing
     nowhere near the top row's, and the strip read as broken.
   — The rule under a full row must not depend on the row BELOW it. With
     top-and-left borders that rule was drawn by the next row's cells, so a
     short last row left it stopping two columns in.
   Right-and-bottom borders satisfy both: a full row closes its own underline,
   a short last row's blank tail still sits under an unbroken rule and reads as
   an empty cell behind the divider its neighbour draws. The -1px margins push
   the outermost borders under the container's own, clipped by overflow. */
.stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden;
}
.stats > div {
  background: var(--surface); padding: 14px 16px;
  border-right: 1px solid var(--line); border-bottom: 1px solid var(--line);
  margin: 0 -1px -1px 0;
}
.stats dt { font-size: 11px; color: var(--ink-3); margin-bottom: 5px; }
.stats dd {
  margin: 0; font-family: var(--font-d); font-weight: 600; font-size: 19px;
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
}
.stats dd small { font-family: var(--sans); font-size: 11.5px; color: var(--ink-3); letter-spacing: 0; }

/* Internal calls are printed beside the inbound numbers because a manager will
   ask where they went, but they are not volume. The muted ground and the chip
   under the figure keep it from being added to anything. */
.stats > div.off { background: var(--surface-hover); }
.stats > div.off dd { color: var(--ink-3); }
.stats > div .chip { margin-top: 7px; }

/* «Ishlangan kategoriyalar» and «Kontaktlar bazasi» on a baza card: each
   is one card, a strip of figures, then its table. */
.baza-card { margin-bottom: 22px; }
.baza-card .note.bare-in { background: none; border: 0; margin: 0; padding: 12px 17px; }
/* The headline figures: the employee card's own tile type, in one row. */
.baza-strip {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  border-bottom: 1px solid var(--line);
}
.baza-strip > div {
  padding: 13px 17px; display: flex; flex-direction: column; gap: 5px;
  border-left: 1px solid var(--line);
}
.baza-strip > div:first-child { border-left: 0; }
.cat-table th:first-child, .cat-table td:first-child { padding-left: 17px; }
.cat-table th:last-child, .cat-table td:last-child { padding-right: 17px; }
.cat-table td { vertical-align: top; }
.cat-table td.cat-name { font-weight: 600; width: 260px; }
.cat-table td.num small { display: block; font-weight: 400; font-size: 11.5px; margin-top: 2px; }
.cat-table tr.cat-stage td:first-child { padding-left: 33px; color: var(--ink-2); }
/* One block per funnel: a tinted row naming it, its stages under it. */
.cat-table tr.cat-group td { background: var(--surface-hover); font-weight: 600; }
/* Every non-zero figure opens its leads: the same dotted underline the
   sales board's cells wear, so the two read as one kind of control. */
.cat-table td.can-open { text-decoration: underline dotted var(--ink-4); text-underline-offset: 4px; }
.cat-table td.can-open:hover { text-decoration-color: var(--brand); }
.baza-strip > div.can-open .tdy-label { padding-right: 18px; }
/* «Kontaktlar bazasi» by funnel: one card per amoCRM funnel, its stages as
   rows with a bar for the stage's share of that funnel. */
.seat-funnels {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 12px;
}
.seat-funnel {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 14px 16px;
}
.seat-funnel > header { display: flex; align-items: baseline; gap: 6px; margin-bottom: 10px; }
.seat-funnel > header h3 { margin: 0 auto 0 0; font-size: 13.5px; font-weight: 600; }
.seat-funnel > header b { font-family: var(--font-d); font-size: 17px; font-variant-numeric: tabular-nums; }
.seat-funnel ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.seat-funnel li {
  display: grid; grid-template-columns: 1fr auto; column-gap: 10px; row-gap: 3px;
  font-size: 12.5px;
}
.seat-funnel-name { color: var(--ink-2); min-width: 0; overflow-wrap: anywhere; }
.seat-funnel-n { font-variant-numeric: tabular-nums; font-weight: 600; }
.seat-funnel-bar {
  grid-column: 1 / -1; height: 4px; border-radius: 2px; background: var(--line);
  overflow: hidden;
}
.seat-funnel-bar i { display: block; height: 100%; background: var(--brand); }
.modal-body .baza-strip { margin: 0 -20px; }
.modal-body .cat-table tbody tr { cursor: default; }
.modal-body .cat-table tbody tr:hover { background: none; }

/* The transfer chain: who picked up, who ended up doing the talking, and which
   of the two the score was written to. Laid out as a sequence because that is
   what it is, and because two fields in the meta strip did not stop a
   transferred call reading as one person's work. */
.chain {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 16px 20px 18px; margin-bottom: 18px;
}
.chain header { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; margin-bottom: 14px; }
.chain h2 { font-size: var(--t-h2); }
.chain .hint { font-size: 11.5px; color: var(--ink-3); }
.chain ol { display: flex; flex-wrap: wrap; align-items: stretch; gap: 10px 0; margin: 0; padding: 0; list-style: none; }
.chain li {
  display: flex; flex-direction: column; gap: 2px;
  padding: 9px 15px; border: 1px solid var(--line);
  border-radius: var(--radius-xs); background: var(--surface-hover);
}
.chain li + li { margin-left: 36px; position: relative; }
.chain li + li::before {
  content: "→"; position: absolute; left: -25px; top: 50%;
  transform: translateY(-50%); color: var(--ink-3);
}
.chain li b { font-size: 16px; letter-spacing: -0.02em; }
.chain li span { font-size: var(--t-small); color: var(--ink-3); }
.chain li.credited { border-color: var(--brand); background: var(--brand-soft); }
.chain li.credited b, .chain li.credited span { color: var(--brand-ink); }
.chain p { margin: 14px 0 0; font-size: var(--t-small); color: var(--ink-2); }
.chain p b { font-family: var(--font-b); font-variant-numeric: tabular-nums; font-weight: 600; color: var(--ink); }

.section-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  margin: 30px 0 12px;
}
.section-head h2 { font-size: var(--t-h2); }
.section-head .hint { font-size: 11.5px; color: var(--ink-3); }

/* ------------------------------------------------------- call profile */
/* Radar of per-group scores against the team. The chart carries the shape;
   the table beside it carries the numbers and the order to fix them in. */
.profile {
  margin: 0 0 18px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(260px, 0.85fr);
  gap: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.profile figcaption {
  grid-column: 1 / -1;
  padding: 13px 17px; border-bottom: 1px solid var(--line);
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
}
.profile figcaption h2 { font-size: var(--t-h2); }
.profile figcaption .hint { font-size: 11.5px; color: var(--ink-3); }

.profile .plot { padding: 8px 10px 16px; display: grid; align-content: center; justify-items: center; }
.profile svg { width: 100%; max-width: 560px; height: auto; display: block; }
.profile .ring { fill: none; stroke: var(--line); stroke-width: 1; }
.profile .ring:last-of-type { stroke: var(--line-strong); }
.profile .spoke { stroke: var(--line); stroke-width: 1; }
.profile .team {
  fill: none; stroke: var(--ink-3); stroke-width: 1.6;
  stroke-dasharray: 6 5; stroke-linejoin: round;
}
.profile .mine {
  fill: var(--brand); fill-opacity: .12;
  stroke: var(--brand); stroke-width: 2.2; stroke-linejoin: round;
}
.profile .dot { fill: var(--brand); }
.profile .axis-label { font-size: 16px; fill: var(--ink-3); font-family: var(--sans); }
.profile .axis-value { font-size: 17px; font-family: var(--font-b); font-variant-numeric: tabular-nums; font-weight: 600; fill: var(--ink); }

.profile .legend {
  display: flex; gap: 20px; margin-top: 6px;
  font-size: var(--t-small); color: var(--ink-3);
}
.profile .legend span { display: inline-flex; align-items: center; gap: 7px; }
.profile .legend .key { width: 18px; height: 0; border-top: 2px solid currentColor; }
.profile .legend .key.mine { color: var(--brand); }
.profile .legend .key.team { color: var(--ink-3); border-top-style: dashed; }

.profile .breakdown { border-left: 1px solid var(--line); padding: 0 0 14px; }
.profile .breakdown .note { padding: 12px 17px 0; }
.profile .breakdown td.up { color: var(--green); }
.profile .breakdown td.down { color: var(--red-ink); }

/* ------------------------------------------------------- employee card */
/* A figure is only meaningful next to the team's, so the comparison is part
   of the number rather than a separate column you have to hunt for. */
.vs { font-family: var(--sans); font-size: 11.5px; font-weight: 500; white-space: nowrap; }
.vs.up { color: var(--green); }
.vs.down { color: var(--red-ink); }
.vs.dim { color: var(--ink-3); }
.scoreboard .vs-line { margin: 10px 0 0; font-size: var(--t-small); color: var(--ink-3); }
.scoreboard .vs-line b { font-family: var(--font-b); font-variant-numeric: tabular-nums; color: var(--ink-2); }
td.up { color: var(--green); font-weight: 600; }
td.down { color: var(--red-ink); font-weight: 600; }
/* `.vs` is nowrap because a comparison («jamoa 10%») broken in half reads as
   two facts. Under a figure in the strip it is a SENTENCE — «25/115 bitimda
   dona soni bor» — and nowrap ran it straight out of the card, where the
   frame's `overflow: hidden` cut it off mid-word. */
.stats dd .vs { display: block; margin-top: 2px; white-space: normal; }
tbody td .hint { font-size: 11.5px; color: var(--ink-3); font-weight: 400; margin-top: 2px; }
/* Too few calls to be a finding: present, legible, and visibly not the point. */
tbody tr.thin td { opacity: .62; }

/* ------------------------------------------------------ mezonlar panel */

.criterion {
  padding: 18px 24px; border-bottom: 1px solid var(--line);
  display: grid; grid-template-columns: 26px minmax(0,1fr) auto; gap: 16px; align-items: start;
}
.criterion:last-child { border-bottom: 0; }
.criterion .mark {
  width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center; font-size: 13px; font-weight: 700; flex: none;
}
.criterion .mark.good { background: var(--green-soft); color: var(--green); }
.criterion .mark.warn { background: var(--amber-soft); color: var(--amber); }
.criterion .mark.bad  { background: var(--red-soft); color: var(--red-ink); }
.criterion .mark.mute { background: var(--surface-hover); color: var(--ink-3); }
.criterion .grp { font-size: var(--t-eyebrow); text-transform: uppercase; letter-spacing: .1em; color: var(--ink-3); }
.criterion h3 { font-size: 15px; font-weight: 600; margin-top: 2px; line-height: 1.4; }
/* The grader's sentence about THIS call under a failed criterion (`mezon_izoh`). */
.criterion .crit-note { margin-top: 4px; font-size: var(--t-small); line-height: 1.45; color: var(--ink-2); }
.criterion .weight { font-family: var(--font-b); font-variant-numeric: tabular-nums; font-size: var(--t-small); color: var(--ink-3); padding-top: 3px; }

/* A quote is evidence with a timestamp, so it seeks the recording. */
.quote {
  all: unset; display: block; cursor: pointer;
  margin: 10px 0 0; padding: 10px 14px;
  border-left: 2px solid var(--line-strong);
  background: var(--surface-hover);
  font-size: 13.5px; line-height: 1.55; color: var(--ink-2);
  border-radius: 0 6px 6px 0;
}
.quote:hover { border-left-color: var(--brand); color: var(--ink); }
.quote:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.quote cite {
  display: inline-flex; align-items: center; gap: 5px;
  font-style: normal; font-family: var(--font-b); font-variant-numeric: tabular-nums; font-size: 11px;
  color: var(--ink-3); margin-top: 6px;
}
.quote:hover cite { color: var(--brand-ink); }

/* ----------------------------------------------------- transkript panel */
.transcript { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; }
.turn {
  display: grid; grid-template-columns: 116px minmax(0,1fr); gap: 18px;
  padding: 13px 24px; border-bottom: 1px solid var(--line);
}
.turn:last-child { border-bottom: 0; }
.turn:hover { background: var(--surface-hover); }
.turn .who { display: grid; gap: 2px; }
.turn .who b { font-size: 11px; text-transform: uppercase; letter-spacing: .07em; color: var(--ink-3); }
.turn.op .who b { color: var(--brand-ink); }
.turn .who time { font-family: var(--font-b); font-variant-numeric: tabular-nums; font-size: 11px; color: var(--ink-3); cursor: pointer; }
.turn .who time:hover { color: var(--brand-ink); }
.turn p { margin: 0; font-size: 14.5px; line-height: 1.6; color: var(--ink-2); }
.turn.op p { color: var(--ink); }

/* ----------------------------------------------------------- meta strip */
/* Identifiers a manager needs about twice a month. Present, quiet, last. */
.meta-strip {
  display: flex; flex-wrap: wrap; gap: 8px 28px;
  margin-top: 30px; padding-top: 18px; border-top: 1px solid var(--line);
  font-size: var(--t-small); color: var(--ink-3);
}
.meta-strip span b { font-weight: 500; color: var(--ink-2); font-family: var(--font-b); font-variant-numeric: tabular-nums; }

.kv { display: grid; grid-template-columns: auto 1fr; gap: 7px 14px; font-size: 13px; }
.kv dt { color: var(--ink-3); }
.kv dd { margin: 0; font-family: var(--font-b); font-variant-numeric: tabular-nums; }

.empty { padding: 44px 20px; text-align: center; color: var(--ink-3); }
.empty b { display: block; color: var(--ink-2); margin-bottom: 4px; font-size: 14px; }
/* «Raqamni kim berdi» — who supplied a seat's numbers.

   A list and not a `.stats` strip: the answer is a distribution, and one row
   per supplier is what tells «one manager feeds this seller everything» apart
   from «five feed them equally». The name leads, the count is the figure the
   eye lands on, and the handover/creator split trails behind in the quiet
   colour — it qualifies the count rather than competing with it. */
.src-list { list-style: none; margin: 0; padding: 0; border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; }
.src-list li {
  display: grid; grid-template-columns: 1fr auto; gap: 2px 12px;
  align-items: baseline; padding: 10px 16px; background: var(--surface);
}
.src-list li + li { border-top: 1px solid var(--line); }
.src-who { font-weight: 600; }
.src-n { font-family: var(--font-b); font-variant-numeric: tabular-nums; white-space: nowrap; }
.src-how { grid-column: 1 / -1; font-size: 11.5px; }

.note { margin: 0; font-size: 12px; color: var(--ink-3); padding: 10px 17px; background: var(--surface-hover); border-top: 1px solid var(--line); }
.note.bare { background: none; border: 0; padding: 12px 2px 0; }

/* settings — a full-height section rail against one pane.

   The subjects on this page are unrelated: who you are, how the panel looks,
   what is plugged in, who may sign in, what grading is allowed to spend.
   Stacked as cards they read as one setting with twelve rows and the reader
   scrolls past the block they came for.

   The rail is a SECOND sidebar rather than a floating column: it takes its own
   surface, runs the full height of the scroll box, and sits flush against the
   main rail with no gutter between them, so the eye reads one navigation
   structure that got deeper rather than two lists that happen to be near each
   other. That is what the negative margins are for — they cancel `main`'s
   padding so the rail can reach three edges — and `set-main` puts the padding
   back for the content beside it.

   236px because «Baholash mezonlari» is the longest label the page has and it
   must not wrap: a settings rail that reflows as you move down it is worse than
   no rail. Below 900px it becomes a horizontal strip, because two columns of
   that width leave the pane too narrow for a four-column table. */
.settings {
  display: grid;
  grid-template-columns: 236px minmax(0, 1fr);
  align-items: stretch;
  margin: -26px -30px -60px;
  /* Fills the scroll box even when the open section is short, so the rail's
     surface never stops halfway down the page with the ground showing under it. */
  min-height: calc(100% + 86px);
}
.set-main { padding: 26px 30px 60px; min-width: 0; }

/* STICKY, because the sections are not all short. «MCP» is a page of prose,
   snippets and a table, and «Harakatlar tarixi» is 200 rows: scrolling either
   one took the rail off the top of the window, so moving to another section
   meant scrolling all the way back up first. A rail you have to hunt for is a
   rail the reader stops using.

   `align-self: start` is what actually makes it stick — the grid sets
   `align-items: stretch`, and a stretched item is already as tall as the track,
   so it has nowhere to slide and `position: sticky` does nothing at all. The
   explicit height then puts the FULL scrollport back, which is what the
   stretch was there for: without it the rail's surface stops at its last item
   and the page ground shows under it. `main` is the scrollport and it is
   exactly the viewport less the topbar, so that is the height. */
.set-nav {
  position: sticky;
  top: 0;
  align-self: start;
  height: calc(100vh - var(--brandbar));
  /* A rail taller than the window — a future section list, or a large font —
     scrolls inside itself rather than being clipped. */
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 1px;
  padding: 6px 0 30px;
  background: var(--surface);
  border-right: 1px solid var(--line);
}
.set-nav-group { padding: 16px 20px 6px; }
.set-nav-group:first-child { padding-top: 8px; }
.set-nav-group button {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; padding: 0; border: 0; background: none; cursor: pointer;
  font: 700 var(--t-eyebrow)/1.2 var(--font-b); text-transform: uppercase;
  letter-spacing: .09em; color: var(--ink-4); text-align: left;
}
.set-nav-group button:hover { color: var(--ink-3); }
.set-nav-group button:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; border-radius: 4px; }
.set-nav-group .chev { display: grid; place-items: center; flex: none; }
.set-nav-group .chev svg { width: 15px; height: 15px; display: block; transition: transform .16s var(--ease); }
.set-nav-group button[aria-expanded="false"] .chev svg { transform: rotate(180deg); }
.set-nav-items { display: flex; flex-direction: column; gap: 1px; }
.set-nav-items[hidden] { display: none; }

/* Full-bleed rows with an accent bar on the open one: the row is the width of
   the sidebar, the way the main rail's rows are, so a selected section reads as
   part of the navigation rather than as a pill floating inside it. */
.set-nav-items button {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 10px 20px 10px 17px;
  border: 0; border-left: 3px solid transparent; background: none; cursor: pointer;
  font: 500 13.5px/1.3 var(--font-b); color: var(--ink-2); text-align: left;
}
.set-nav-items button:hover { background: var(--surface-hover); color: var(--ink); }
.set-nav-items button:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.set-nav .ic { display: grid; place-items: center; width: 19px; height: 19px; flex: none; color: var(--ink-4); }
.set-nav .ic svg { width: 19px; height: 19px; display: block; }
.set-nav .lbl { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The count is what the section is reporting, not a notification: it stays
   quiet ink so a roster of 91 people does not read as 91 unread things. */
.set-nav-n {
  margin-left: auto; flex: none; font-size: 11.5px; font-variant-numeric: tabular-nums;
  color: var(--ink-4); background: var(--surface-hover); border-radius: var(--pill); padding: 1px 7px;
}
.set-nav-items button[aria-current="page"] {
  background: var(--brand-soft); border-left-color: var(--brand);
  color: var(--brand-deep); font-weight: 600;
}
.set-nav-items button[aria-current="page"] .ic { color: var(--brand); }
.set-nav-items button[aria-current="page"] .set-nav-n { background: var(--brand-soft-2); color: var(--brand-ink); }

/* A row, so a section that owns a control can put it here. Sections without
   one render nothing and the title is simply the only child — no empty slot
   holding the layout open. */
.set-pane-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  padding: 18px 22px 14px; border-bottom: 1px solid var(--line);
}
.set-pane-title { min-width: 0; }
.set-pane-head h2 { font-size: 18px; }
.set-pane-head p { margin: 3px 0 0; font-size: var(--t-small); color: var(--ink-3); }
.set-pane-head > .btn { flex: none; white-space: nowrap; }
@media (max-width: 620px) {
  .set-pane-head { flex-direction: column; gap: 10px; }
}
.set-pane-body { padding: 20px 22px 22px; }
/* A list, a table and an empty state each own their edges. Inside the padded
   pane they would sit inset from the rule above them, so they take it back. */
.set-pane-body > .set-list,
.set-pane-body > .wrap,
.set-pane-body > .empty { margin: -20px -22px 0; }
.set-pane-body > .wrap + .note.bare { padding-top: 14px; }
.set-pane-body > .set-list + .note.bare { padding-top: 16px; }
/* The -20px above assumes these are the pane's FIRST child, bleeding to its
   edges. They are not any more: on «Qo‘llab-quvvatlash» the list follows the
   contact rows, and on «Jamoa» the table follows the Add button — in both cases
   the pull dragged the block 20px ON TOP of what came before it. Anything
   preceding them restores the gap, and only the TOP margin is touched so the
   horizontal bleed to the pane edges survives. */
.set-pane-body > * + .set-list,
.set-pane-body > * + .wrap,
.set-pane-body > * + .empty { margin-top: 18px; }

/* ---- ko‘rinish ---- */
/* The sound row: the switch first, because it is the control and the words
   beside it are the explanation of what it does — the same order the seat
   switches on /operators put them in. */
.set-switch {
  display: flex; align-items: center; gap: 12px;
  margin-top: 12px; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface);
}
.set-switch-txt { flex: 1; min-width: 0; }
.set-switch-txt b { display: block; font-size: 13.5px; font-weight: 600; color: var(--ink); }
.set-switch-txt span { display: block; margin-top: 2px; font-size: var(--t-small); color: var(--ink-3); }

.set-block h3 { font-size: 15px; margin: 0; }
.set-block > p { margin: 4px 0 0; font-size: var(--t-small); color: var(--ink-3); }
.theme-row { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 14px; }
.theme-card {
  display: grid; gap: 9px; justify-items: center; padding: 0;
  border: 0; background: none; cursor: pointer; font: inherit; color: var(--ink-2);
}
.theme-name { font-size: 13px; }
.theme-card.is-on .theme-name { color: var(--ink); font-weight: 600; }
.theme-card:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; border-radius: var(--radius-xs); }

/* A miniature of the panel: title bar, then two rows of a disc and a line.
   Drawn from tokens rather than a screenshot, so it can never show a palette
   the product no longer has — and the two fixed halves are the LITERAL light
   and dark values, because a preview of «Yorug‘» painted in the current theme
   would be the same tile three times. */
.theme-prev {
  position: relative; display: block; width: 124px; height: 82px; overflow: hidden;
  border: 2px solid var(--line-2); border-radius: 10px; padding: 9px;
  background: #FFFFFF;
}
.theme-card.is-on .theme-prev { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
.theme-prev i { display: block; }
.theme-prev .tp-bar { height: 11px; border-radius: 3px; background: #16221D; }
.theme-prev .tp-row { display: flex; align-items: center; gap: 6px; margin-top: 9px; }
.theme-prev .tp-row b { width: 11px; height: 11px; border-radius: 50%; background: #16221D; flex: none; }
.theme-prev .tp-row s { height: 9px; border-radius: 3px; background: #566159; flex: 1; }
.theme-prev.tp-dark { background: #161E1A; }
.theme-prev.tp-dark .tp-bar,
.theme-prev.tp-dark .tp-row b { background: #E8EFEA; }
.theme-prev.tp-dark .tp-row s { background: #7E8A82; }
/* «Tizim» is the dark tile laid over the light one and cut on the diagonal —
   the only honest way to draw «whichever your machine says» in one card. */
.theme-prev.tp-system::after {
  content: ''; position: absolute; inset: 0; background: #161E1A;
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
  mix-blend-mode: normal;
}
.theme-prev.tp-system .tp-bar,
.theme-prev.tp-system .tp-row b,
.theme-prev.tp-system .tp-row s { position: relative; z-index: 1; }

/* ---- read-only values, drawn as the fields they would be if editable ---- */
.set-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px 18px; }
.set-field.wide { grid-column: 1 / -1; }
.set-field > label { display: block; font-size: 12.5px; font-weight: 600; color: var(--ink-2); margin-bottom: 6px; }
.set-field > small { display: block; margin-top: 6px; font-size: 12px; color: var(--ink-3); line-height: 1.45; }
.set-input, .set-input-el {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 42px; padding: 9px 12px;
  border: 1px solid var(--line-2); border-radius: var(--radius-xs); background: var(--surface-2);
  font-family: var(--font-b); font-size: 13.5px; color: var(--ink);
}
.set-input > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.set-input.mono > span { font-family: var(--font-m); font-size: 12.5px; }
.set-input.is-empty > span { color: var(--ink-4); }
.set-input .lock { margin-left: auto; flex: none; display: grid; place-items: center; color: var(--ink-4); cursor: help; }
.set-input .lock svg { width: 15px; height: 15px; display: block; }
/* The editable one takes the panel's own focus ring and a lighter ground, so
   «you may type here» is visible before the cursor is in it. */
.set-input-el { background: var(--surface); }
.set-input-el:hover { border-color: var(--line-strong); }
.set-input-el:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }

.set-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--line); }
.set-actions[hidden] { display: none; }
/* The phone row: a field and the button that acts on it, on one line. The
   input takes the slack so the button never moves as the number is typed. */
.phone-row { display: flex; gap: 8px; align-items: center; }
.phone-row + .phone-row { margin-top: 8px; }
.phone-row[hidden] { display: none; }
.phone-row .set-input-el { flex: 1 1 auto; min-width: 0; }
.phone-row .btn { flex: none; }
.set-input .linkish { display: inline-block; width: auto; margin: 0 0 0 auto; padding: 0; flex: none; font-size: 12.5px; }
.set-input .linkish.danger { color: var(--red-ink); }
.set-err { margin: 12px 0 0; font-size: 12.5px; color: var(--red-ink); }
.set-err[hidden] { display: none; }

/* Who is signed in, at the head of Profil. */
.set-ident { display: flex; align-items: center; gap: 14px; margin-bottom: 20px; }
.set-ident > div { min-width: 0; }
.set-ident b { display: block; font-family: var(--font-d); font-size: 17px; font-weight: 600; }
.set-ident-sub { display: block; margin-top: 1px; font-family: var(--font-m); font-size: 12.5px; color: var(--ink-3); }
.set-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.avatar.lg { width: 52px; height: 52px; font-size: 17px; flex: none; }

/* Counts that describe the workspace rather than a period — no delta, no floor. */
.set-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-top: 20px; }
.set-stats > div {
  padding: 13px 15px; border: 1px solid var(--line); border-radius: var(--radius-xs); background: var(--surface-2);
}
.set-stats dt { font-size: var(--t-eyebrow); text-transform: uppercase; letter-spacing: .07em; color: var(--ink-3); font-weight: 600; }
.set-stats dd { margin: 5px 0 0; font-family: var(--font-d); font-size: 24px; font-weight: 600; font-variant-numeric: tabular-nums; }
.set-stats span { display: block; margin-top: 3px; font-size: 12px; color: var(--ink-3); }

/* A connected system: mark, name, verdict — the shape an account row has. */
.conn-list { display: flex; flex-direction: column; gap: 10px; }
.conn {
  display: flex; align-items: center; gap: 13px; padding: 13px 15px;
  border: 1px solid var(--line); border-radius: var(--radius-xs); background: var(--surface-2);
}
.conn-mark {
  display: grid; place-items: center; width: 38px; height: 38px; flex: none;
  border-radius: var(--radius-xs); background: var(--brand-soft); color: var(--brand-ink);
}
.conn.off .conn-mark { background: var(--surface-hover); color: var(--ink-4); }
.conn-mark svg { width: 20px; height: 20px; display: block; }
.conn-txt { min-width: 0; }
.conn-txt b { display: block; font-size: 13.5px; }
.conn-txt small { display: block; margin-top: 2px; font-size: 12px; color: var(--ink-3); }
.conn .chip { margin-left: auto; flex: none; }

/* The reference seller, and why the page is comparing against them. */
.set-bench {
  padding: 15px 16px; margin-bottom: 18px;
  border: 1px solid var(--brand-soft-2); border-radius: var(--radius-xs); background: var(--brand-soft);
}
.set-bench.is-team { border-color: var(--line); background: var(--surface-2); }
.set-bench-lbl {
  display: block; font-size: var(--t-eyebrow); text-transform: uppercase; letter-spacing: .07em;
  color: var(--ink-3); font-weight: 600; margin-bottom: 4px;
}
.set-bench b { font-family: var(--font-d); font-size: 17px; font-weight: 600; }
.set-bench .mono { margin-left: 8px; font-size: 12.5px; }
.set-bench p { margin: 8px 0 0; font-size: 12.5px; line-height: 1.55; color: var(--ink-2); }

.set-rubric {
  display: flex; align-items: center; gap: 12px; padding: 14px 16px;
  border: 1px solid var(--line); border-radius: var(--radius-xs); background: var(--surface-2);
}
.set-rubric b { display: block; font-family: var(--font-d); font-size: 16px; font-weight: 600; }
.set-rubric span { display: block; margin-top: 2px; font-size: 12.5px; color: var(--ink-3); }
.set-rubric .set-link { margin-left: auto; flex: none; }
.set-copy { margin: 14px 0 0; font-size: 13.5px; line-height: 1.6; color: var(--ink-2); }
.set-pane-body > .set-copy + .wrap { margin: 16px -22px 0; }

/* The criteria list on Sozlamalar → Baholash mezonlari. A reference table, so
   the group is a RULE across the row rather than a repeated column: the same
   label on four consecutive rows is noise, and the eye needs the break more
   than it needs the word. Reuses the page's own table styling — no second
   look for the same kind of data. */
.set-rubric-items tbody .grp-row td {
  padding-top: 16px; font-size: var(--t-eyebrow); text-transform: uppercase;
  letter-spacing: .07em; color: var(--ink-3); border-bottom: 1px solid var(--line);
}
.set-rubric-items tbody tr:first-child .grp-row td,
.set-rubric-items tbody .grp-row:first-child td { padding-top: 6px; }
.set-rubric-items td .chip { margin-left: 6px; vertical-align: middle; }

@media (max-width: 900px) {
  /* Folded to a strip, the rail keeps its own surface and its bottom rule but
     stops being a column, so the pane below it gets the full width back. */
  .settings { grid-template-columns: minmax(0, 1fr); min-height: 0; margin-bottom: -60px; }
  .set-nav {
    flex-direction: row; flex-wrap: wrap; gap: 6px; align-items: center;
    padding: 12px 20px; border-right: 0; border-bottom: 1px solid var(--line);
    /* Folded to a strip it is no longer a column beside the content, so there
       is nothing for it to stay level with; sticking it would cover the pane. */
    position: static; height: auto; overflow: visible;
  }
  /* The group headings cannot survive the fold: a horizontal strip has no
     column for them to head, and their chevron would hide items sideways. */
  .set-nav-group { display: none; }
  .set-nav-items { flex-direction: row; flex-wrap: wrap; gap: 6px; }
  .set-nav-items[hidden] { display: flex; }
  .set-nav-items button {
    width: auto; padding: 8px 12px; border-left: 0;
    border: 1px solid var(--line); border-radius: var(--pill); background: var(--surface-2);
  }
  .set-nav-items button[aria-current="page"] { border-color: var(--brand-soft-2); }
  .set-nav-n { margin-left: 4px; }
  .set-main { padding: 20px 20px 60px; }
}
@media (max-width: 620px) {
  .set-fields, .set-stats { grid-template-columns: minmax(0, 1fr); }
  .set-pane-head, .set-pane-body { padding-left: 16px; padding-right: 16px; }
  .set-pane-body > .set-list, .set-pane-body > .wrap, .set-pane-body > .empty { margin-left: -16px; margin-right: -16px; }
  .set-main { padding: 16px 14px 60px; }
}

/* settings — a status list of configured/absent rows, and the value rows beside them */
.set-list { display: flex; flex-direction: column; }
.set-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 12px 17px; border-top: 1px solid var(--line); }
.set-row:first-child { border-top: 0; }
.set-row .k { font-size: 13.5px; color: var(--ink); }
.set-row .k small { display: block; margin-top: 2px; font-size: 12px; color: var(--ink-3); }
.set-row .v { font-size: 13.5px; color: var(--ink-2); font-variant-numeric: tabular-nums; text-align: right; }
/* Keeps the .chip.accent pill look; only strips the native button chrome. */
.set-link { border: 0; cursor: pointer; font-family: inherit; }
.set-link:hover { background: var(--brand-soft-2); }
.set-link:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* criteria overview + coaching anchors */
.anchor { margin: 0 0 8px; padding: 8px 11px; border-radius: var(--radius-xs); font-size: var(--t-small); }
.anchor b { display: block; font-size: var(--t-eyebrow); text-transform: uppercase; letter-spacing: .07em; margin-bottom: 2px; }
.anchor.fail { background: var(--red-soft); color: var(--ink-2); }
.anchor.fail b { color: var(--red-ink); }
.anchor.target { background: var(--green-soft); color: var(--ink-2); }
.anchor.target b { color: var(--green); }
.card > header .grp { display: block; font-size: var(--t-eyebrow); text-transform: uppercase; letter-spacing: .07em; color: var(--ink-3); margin-bottom: 2px; }
.danger { color: var(--red-ink); }

/* «Hozir tahlil qilish» — the way past the hourly grading batch for the one
   call a manager is actually looking at. Deliberately quiet: it spends money
   and it is an exception, not the normal way a call gets graded. */
.analyse { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 14px; }
.analyse .hint { font-size: var(--t-small); color: var(--ink-3); }
.analyse .hint.fail { color: var(--red-ink); }
.analyse-btn {
  all: unset; cursor: pointer; padding: 6px 13px; border-radius: var(--radius-xs);
  font-size: var(--t-small); font-weight: 600; color: var(--brand-ink);
  background: var(--brand-soft); border: 1px solid var(--brand-soft-2);
  transition: background 120ms ease, color 120ms ease;
}
.analyse-btn:hover:not(:disabled) { background: var(--brand-soft-2); color: var(--brand-deep); }
.analyse-btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
/* Disabled for the length of the request, because a second click is a second
   audio bill and a second grade for the same call. */
.analyse-btn:disabled { cursor: default; color: var(--ink-3); background: var(--surface-2); border-color: var(--line); }

@media (max-width: 1180px) {
  .profile { grid-template-columns: 1fr; }
  .profile .breakdown { border-left: 0; border-top: 1px solid var(--line); padding-top: 4px; }
  .lede { grid-template-columns: 1fr; gap: 24px; }
  /* One column again: the explicit two-row placements above would pin the
     rail into a phantom second column, so everything returns to source
     order — headline, rail, «Bugun». */
  .lede.has-today { grid-template-rows: none; }
  .lede.has-today > div:first-child,
  .lede.has-today > .scoreboard,
  .lede.has-today > .today-bar { grid-row: auto; grid-column: auto; }
  .scoreboard { border-left: 0; padding-left: 0; border-top: 1px solid var(--line); padding-top: 20px; }
  .scoreboard .value b { font-size: 38px; }
}
@media (max-width: 1080px) {
  .shell { grid-template-columns: 1fr; }
  /* Same reason as `main`: the rail turns into a horizontal scroller here, and
     without a zero floor its eight buttons set the grid column's width and the
     whole page scrolls sideways behind them. */
  .rail { position: static; height: auto; flex-direction: row; align-items: center; overflow-x: auto; min-width: 0; }
  .nav { flex-direction: row; }
  .kpis, .kpis.four, .kpis.three, .grid { grid-template-columns: 1fr; }
  .verdicts { grid-template-columns: 1fr; }
  .verdicts > div + div { border-left: 0; border-top: 1px solid var(--line); }
}
@media (max-width: 700px) {
  main { padding: 20px 16px 50px; }
  /* The period switcher drops under the title rather than pushing it off the
     screen: at 320px the two together are wider than the viewport. */
  .page-head { flex-wrap: wrap; }
  /* The chain turns vertical rather than wrapping: a wrapped row puts the
     arrow at the start of a line, pointing at nothing. */
  .chain ol { flex-direction: column; align-items: flex-start; }
  .chain li + li { margin-left: 0; margin-top: 26px; }
  .chain li + li::before { left: 22px; top: -20px; transform: rotate(90deg); }
  .turn { grid-template-columns: 1fr; gap: 4px; }
  .turn .who { display: flex; gap: 10px; align-items: baseline; }
  /* Five analitika tabs are wider than a 320px phone. The bar scrolls rather
     than wrapping: on a second line the active tab's underline sits away from
     the border it is supposed to be part of. */
  .tabs { gap: 18px; overflow-x: auto; }
  .tabs button { flex: none; }
  .player .dl { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* The kind of call a score was judged under. Distinct from the status facts:
   it is a classification, not a verdict, so it carries no good/bad colour. */
.fact.kind {
  background: var(--surface-hover);
  color: var(--ink-2);
  text-transform: lowercase;
}

/* ------------------------------------------------------------------ sign-in */

/*
 * The gate covers the shell rather than replacing it, so a session that expires
 * mid-use does not tear down the page underneath and lose what was on screen.
 *
 * Every colour here is a token. The first draft hardcoded a dark input
 * background and shipped grey blocks onto a light palette, because this panel
 * defaults to light and only goes dark when data-theme says so.
 */
.gate {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 24px;
  background: var(--bg);
}

.gate[hidden] { display: none; }

.gate-card {
  width: min(392px, 100%);
  padding: 36px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
}

/* The sign-in card wears the same mark as the rail. It is the first Reveo
   surface a new manager sees and the only one they see signed out. */
.gate-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 30px;
}
.gate-brand .mark { width: 34px; height: 34px; flex: none; display: grid; place-items: center; }
.gate-brand .mark img { width: 34px; height: 34px; display: block; }
.gate-brand .name { display: flex; flex-direction: column; justify-content: center; gap: 3px; }
.gate-brand .name b {
  font-family: var(--font-d); font-size: 15px; font-weight: 700;
  letter-spacing: -0.01em; line-height: 1; color: var(--ink);
}
.gate-brand .name span {
  font-size: 9px; font-weight: 600; letter-spacing: 0.13em;
  text-transform: uppercase; line-height: 1; color: var(--ink-3);
}


.gate-form h1 {
  margin: 0 0 6px;
  font-size: 21px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.gate-sub {
  margin: 0 0 24px;
  font-size: var(--t-body);
  line-height: 1.5;
  color: var(--ink-2);
}
.gate-form[hidden] { display: none; }

.gate-form label {
  display: block;
  margin-bottom: 6px;
  font-size: var(--t-small);
  font-weight: 500;
  color: var(--ink-2);
}

.gate-form input,
.gate-form textarea {
  width: 100%;
  margin-bottom: 18px;
  padding: 11px 13px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-xs);
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  font-size: var(--t-body);
  transition: border-color 150ms ease, box-shadow 150ms ease;
}
.gate-form textarea { resize: vertical; min-height: 76px; }

.gate-form input::placeholder,
.gate-form textarea::placeholder { color: var(--ink-3); }

.gate-form input:focus,
.gate-form textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-soft);
}

.gate-form button[type='submit'] {
  width: 100%;
  padding: 12px;
  border: 0;
  border-radius: var(--radius-xs);
  background: var(--brand);
  color: var(--on-brand);
  font: inherit;
  font-size: var(--t-body);
  font-weight: 600;
  cursor: pointer;
  transition: background 150ms ease, transform 120ms ease;
}
.gate-form button[type='submit']:hover:not(:disabled) { background: var(--brand-ink); }
.gate-form button[type='submit']:active:not(:disabled) { transform: translateY(1px); }
.gate-form button[type='submit']:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
}
.gate-form button[type='submit']:disabled { opacity: 0.5; cursor: default; }

.gate-error,
.gate-ok {
  margin: -8px 0 16px;
  padding: 10px 12px;
  border-radius: var(--radius-xs);
  font-size: var(--t-small);
  line-height: 1.45;
}
.gate-error { background: var(--red-soft); color: var(--red-ink); }
.gate-ok { background: var(--green-soft); color: var(--green); }
.gate-error[hidden], .gate-ok[hidden] { display: none; }

/* -------------------------------------------------------- notifications */

/* Cards that arrive while somebody is reading something else.
 *
 * Bottom-RIGHT, and away from the toast: a toast confirms an action the person
 * just took and belongs where their attention already is, while these arrive
 * unprompted and must not land on top of the control that was about to be
 * pressed. Newest is prepended, so the stack grows upward and an arriving card
 * never pushes the one being read out from under the cursor. */
.notifs {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 90;
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: min(360px, calc(100vw - 40px));
  /* The container spans the cards but must not swallow clicks meant for the
     page behind the gaps between them. */
  pointer-events: none;
}

.notif {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 12px 12px 12px 13px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--ink-3);
  border-radius: var(--radius-sm);
  background: var(--surface);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .2s var(--ease), transform .2s var(--ease);
}
.notif.show { opacity: 1; transform: none; }

/* The severity lives on the left edge and nowhere else. A whole card in red
   for a medium finding is how a list stops being read — the same reasoning the
   alert rules themselves are written under. */
.notif.warn { border-left-color: var(--amber); }
.notif.bad { border-left-color: var(--red); }

.notif-ic { width: 20px; height: 20px; flex: none; color: var(--ink-3); }
.notif.warn .notif-ic { color: var(--amber); }
.notif.bad .notif-ic { color: var(--red); }
.notif-ic svg { width: 20px; height: 20px; display: block; }

.notif-txt { flex: 1; min-width: 0; }
.notif-txt b {
  display: block;
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--ink);
}
.notif-txt small {
  display: block;
  margin-top: 2px;
  font-size: var(--t-small);
  color: var(--ink-3);
}

.notif-x {
  all: unset;
  flex: none;
  width: 22px; height: 22px;
  display: grid; place-items: center;
  border-radius: 6px;
  color: var(--ink-3);
  cursor: pointer;
}
.notif-x:hover { background: var(--surface-hover); color: var(--ink-2); }
.notif-x:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.notif-x svg { width: 14px; height: 14px; display: block; }

/* «Hammasini tozalash» — drawn only from the second card, and kept at the foot
   of the stack so it does not move while cards arrive above it. */
.notifs-bar { pointer-events: auto; display: flex; justify-content: flex-end; }
.notifs-clear {
  all: unset;
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.1);
  font-size: var(--t-small);
  font-weight: 600;
  color: var(--ink-2);
  cursor: pointer;
}
.notifs-clear:hover { border-color: var(--line-strong); color: var(--ink); }
.notifs-clear:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

.notif.is-link { cursor: pointer; }
.notif.is-link:hover { border-color: var(--line-strong); }
.notif.is-link:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Under the breakpoint the pane scrolls with the document and a fixed stack in
   the corner covers the content it is describing. Full width at the foot
   instead, which is where a phone expects it. */
@media (max-width: 620px) {
  .notifs { left: 12px; right: 12px; bottom: 12px; width: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .notif { transition: none; transform: none; }
}

/* ------------------------------------------------------------ panel til */

/* The three languages as cards rather than a <select>, for the reason the
   theme is: the choice is small, permanent and worth seeing all of at once.
   Each is named in its own script, so the row is also its own demonstration. */
.lang-row { display: flex; flex-wrap: wrap; gap: 10px; }

.lang-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-xs);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
  transition: border-color 150ms ease, background 150ms ease;
}
.lang-card:hover { border-color: var(--line-strong); background: var(--surface-2); }
.lang-card.is-on { border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand); }
.lang-card:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

.lang-tag {
  display: grid;
  place-items: center;
  min-width: 34px;
  padding: 3px 6px;
  border-radius: 6px;
  background: var(--surface-2);
  color: var(--ink-3);
  font-size: var(--t-small);
  font-weight: 700;
  letter-spacing: 0.02em;
}
.lang-card.is-on .lang-tag { background: var(--brand); color: var(--on-brand); }
.lang-name { font-weight: 500; }

/* The same choice in the profile dropdown, because Sozlamalar is a manager
   surface and almost every login here is an operator. Three tags in a row: the
   menu has no space for names, and the tag is each language's own script. */
/* The language chooser inside the profile menu: a row showing the current
   choice, which expands into the three. Three bare abbreviations asked the
   reader to decode a code before choosing; a flag and the language's own name
   are the thing itself. */
.tb-profile-lang {
  padding: 6px 8px;
  border-bottom: 1px solid var(--line);
}

/* The theme row, directly under language and on the same rhythm. A segmented
   control rather than that row's dropdown: three mutually exclusive options
   that fit on one line, where a dropdown would hide two behind a click to save
   no space. */
.tb-profile-theme {
  padding: 8px 10px 10px;
  border-bottom: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.tb-theme-label {
  font-size: var(--t-eyebrow);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .10em;
  color: var(--ink-3);
}
.tb-theme-seg {
  display: flex;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: 7px;
  overflow: hidden;
}
.tb-theme-seg button {
  all: unset;
  box-sizing: border-box;
  flex: 1;
  text-align: center;
  padding: 6px 4px;
  font-size: 12.5px;
  color: var(--ink-2);
  background: var(--surface);
  cursor: pointer;
}
.tb-theme-seg button:hover { background: var(--surface-hover); }
.tb-theme-seg button:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.tb-theme-seg button[aria-pressed="true"] {
  background: var(--brand);
  color: #fff;
  font-weight: 600;
}

.tb-lang-cur,
.tb-lang-list button {
  all: unset;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border-radius: 7px;
  font-size: 13.5px;
  color: var(--ink);
  cursor: pointer;
  transition: background .14s var(--ease);
}
.tb-lang-cur:hover,
.tb-lang-list button:hover { background: var(--surface-hover); }
.tb-lang-cur:focus-visible,
.tb-lang-list button:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }

/* Emoji flags render in the system's colour font, so they must not inherit the
   text colour or they come out as monochrome boxes on some platforms. */
.tb-lang-flag { font-size: 15px; line-height: 1; flex: none; }
.tb-lang-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.tb-lang-caret { width: 16px; height: 16px; flex: none; color: var(--ink-3); }
.tb-lang-caret svg { width: 16px; height: 16px; display: block; transition: transform .18s var(--ease); }
.tb-lang-cur[aria-expanded="true"] .tb-lang-caret svg { transform: rotate(180deg); }

.tb-lang-list { margin-top: 2px; }
.tb-lang-list[hidden] { display: none; }
/* No selected state in the list: the current language is the row above it, so
   the list only ever holds the ones you can change to. */

/* ---------------------------------------------------------------- jamoa */

/* The add form sits ABOVE the roster, not behind a modal: adding a colleague
   is the reason a manager opens this section, and a dialog would hide the very
   list they need to check they are not adding somebody twice. */
/* The form lives behind a button. The roster is what a manager comes here to
   read, and a permanently open five-field form pushes it below the fold. */
.team-head { display: flex; justify-content: flex-end; margin-bottom: 14px; }
.team-head .btn { display: inline-flex; align-items: center; gap: 7px; }
.team-open-ic { width: 16px; height: 16px; display: grid; place-items: center; }
.team-open-ic svg { width: 16px; height: 16px; display: block; transition: transform .18s var(--ease); }
[data-team-open][aria-expanded="true"] .team-open-ic svg { transform: rotate(45deg); }

.team-add {
  margin-bottom: 20px;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}
.team-add[hidden] { display: none; }
/* `minmax` and not bare fractions: a fr column can be squeezed below its
   content, and «Руководитель» is half as long again as «Rahbar» — the select
   rendered as «Руководител» with the last letter cut off. The floors are the
   widest label each field has to hold in any of the three languages. */
.team-add-fields {
  display: grid;
  grid-template-columns:
    minmax(150px, 1.1fr) minmax(180px, 1.3fr)
    minmax(150px, 1fr) minmax(140px, 0.8fr) auto;
  gap: 12px 14px;
  align-items: end;
}
/* Below that the five columns no longer fit; two rows beat five squeezed
   fields, and the button goes full width rather than orphaned in a corner. */
@media (max-width: 1180px) {
  .team-add-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .team-add-fields > [data-team-submit] { grid-column: 1 / -1; }
}
@media (max-width: 700px) {
  .team-add-fields { grid-template-columns: minmax(0, 1fr); }
}
.team-add-fields .set-input-el:disabled { opacity: .5; cursor: not-allowed; }
@media (max-width: 900px) {
  .team-add-fields { grid-template-columns: 1fr; }
}
.team-add .set-field { margin: 0; }

.team-table td { vertical-align: middle; }
.team-table tr.is-off td { opacity: 0.55; }
.team-self { margin-left: 8px; }
.team-act { text-align: right; white-space: nowrap; }

.team-role {
  padding: 5px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: var(--t-small);
}
.team-role:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.team-role:disabled { opacity: 0.5; }

.btn.sm { padding: 5px 10px; font-size: var(--t-small); }

/* ------------------------------------------------------ harakatlar tarixi */

/* The log's own filter, deliberately not `.seg`: that class belongs to the
   period picker, whose delegated handler matches `.seg button` before the
   chain ever reaches [data-act-group] — so sharing the markup turned every
   filter click into a period change. */
.logfilter {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 8px;
  padding: 4px;
  border-radius: 9px;
  background: var(--surface-2);
  border: 1px solid var(--line);
}
.logfilter button {
  all: unset;
  display: flex;
  align-items: center;
  /* The count used to sit against the last letter: «Kirish va chiqish8». */
  gap: 8px;
  padding: 7px 12px;
  border-radius: 6px;
  font-size: var(--t-small);
  color: var(--ink-2);
  cursor: pointer;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.logfilter button:hover { background: var(--surface-hover); color: var(--ink); }
.logfilter button[aria-pressed="true"] {
  background: var(--surface);
  color: var(--ink);
  font-weight: 600;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .07);
}
.logfilter button:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }

.logfilter-n {
  font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums;
  min-width: 20px; padding: 1px 6px;
  border-radius: var(--pill);
  text-align: center;
  background: var(--line);
  color: var(--ink-3);
}
.logfilter button[aria-pressed="true"] .logfilter-n {
  background: var(--brand-soft); color: var(--brand-ink);
}


/* A list and not a table. Every row is one sentence — «<who> <did what> — <to
   whom>» — and a table would break that sentence across four columns for the
   reader to reassemble. */
.actlog { list-style: none; margin: 0; padding: 0; }

.actlog-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line);
}
.actlog-row:last-child { border-bottom: 0; }

.actlog-txt { flex: 1; min-width: 0; }
.actlog-txt p { margin: 0; font-size: var(--t-body); line-height: 1.4; }
.actlog-txt small {
  display: block;
  margin-top: 3px;
  color: var(--ink-3);
  font-size: var(--t-small);
  font-variant-numeric: tabular-nums;
}

/* A quiet left edge on the lines that are about who can see the recordings.
   Not red: none of these is a fault, and colouring an ordinary grant as an
   error is how a manager learns to stop reading the list. */
.actlog-row.is-sensitive { border-left: 2px solid var(--brand); padding-left: 12px; margin-left: -14px; }

/* ---------------------------------------------------------------- yordam */

/* The connection row, made clickable. Same shape as the read-only ones on
   «Ulanish» so the page reads as one page, with a hover that says this one
   goes somewhere. */
.conn-link { text-decoration: none; color: inherit; }
.conn-link:hover { border-color: var(--line-strong); background: var(--surface-2); }
.conn-link:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* ------------------------------------------------ other ways to sign in */

/* The alternatives sit BELOW the password form and behind a rule, because they
   are alternatives: the client's ninety-one operators all have an address and a
   password, and putting a social row on top would make the path almost nobody
   takes look like the main one. The whole block stays hidden until
   /api/auth/providers answers, so a provider Reveo has switched off is never
   drawn and nothing flickers away on load. */
.gate-alt { margin-top: 18px; }
.gate-alt[hidden] { display: none; }

.gate-or {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
  color: var(--ink-3);
  font-size: var(--t-small);
}
.gate-or::before,
.gate-or::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--line);
}

.gate-social {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 11px;
  border: 1px solid var(--line);
  border-radius: var(--radius-xs);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: var(--t-body);
  font-weight: 500;
  cursor: pointer;
  transition: background 150ms ease, border-color 150ms ease;
}
.gate-social[hidden] { display: none; }
.gate-social:hover:not(:disabled) { background: var(--surface-2); border-color: var(--line-strong); }
.gate-social:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.gate-social:disabled { opacity: 0.6; cursor: default; }
.gate-social .ic { display: grid; place-items: center; width: 20px; height: 20px; }
.gate-social .ic svg { width: 20px; height: 20px; }
/* Telegram's own blue, which is what makes the button recognisable at a
   glance — the same reason the Google button is Google's and not ours. */
.gate-social.tg .ic { color: #29a9eb; }

/* Waiting for the person to press Start in Telegram. The dots say the page is
   still listening; without them a button that went quiet reads as broken. */
.gate-social.waiting::after {
  content: '…';
  font-weight: 600;
}

/* Google renders its own button into this mount and sizes it itself; centring
   is all that is left to do. */
.gate-google { margin-top: 10px; display: flex; justify-content: center; max-width: 100%; }
/* Belt to the width the render call measures: Google re-renders the iframe at
   its own moments, and an iframe that came back wide must not hand the login
   page a sideways scroll again. */
.gate-google iframe { max-width: 100%; }
.gate-google[hidden] { display: none; }

.linkish {
  display: block;
  width: 100%;
  margin-top: 14px;
  padding: 6px;
  border: 0;
  background: none;
  color: var(--ink-3);
  font: inherit;
  font-size: var(--t-small);
  cursor: pointer;
  transition: color 150ms ease;
}
.linkish:hover { color: var(--ink); }
.linkish:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: 6px;
}

/* owner-react's ProfileMenu, ported: one avatar button that opens identity and
   sign-out together. The first pass put the name, the role and a loose
   "Chiqish" side by side in the bar, which read as three unrelated pieces of
   text rather than one control. */
.tb-profile { position: relative; flex: none; }
.tb-profile[hidden] { display: none; }

.tb-ava-btn {
  all: unset;
  box-sizing: border-box;
  display: inline-flex; align-items: center; gap: 9px;
  height: 40px; padding: 0 10px 0 4px;
  border-radius: var(--pill);
  border: 1px solid var(--line);
  background: var(--surface);
  cursor: pointer;
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.tb-ava-btn:hover { border-color: var(--line-strong); }
.tb-ava-btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.tb-profile.open .tb-ava-btn { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft-2); }
.avatar.tb-ava { width: 32px; height: 32px; font-size: 12.5px; flex: none; }

/* Name over role, beside the avatar. The name truncates rather than pushing the
   bar wide; the role is the eyebrow beneath it. */
.tb-profile-me { display: flex; flex-direction: column; gap: 1px; min-width: 0; text-align: left; line-height: 1.15; }
.tb-profile-me b {
  font-size: 13px; font-weight: 600; color: var(--ink);
  max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tb-profile-me span {
  font-size: 10.5px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-3);
}
.tb-profile-caret { display: grid; place-items: center; color: var(--ink-4); flex: none; transition: transform .16s var(--ease); }
.tb-profile-caret svg { width: 14px; height: 14px; display: block; }
.tb-profile.open .tb-profile-caret { transform: rotate(180deg); }

/* Under 900px the identity collapses to the avatar disc; the dropdown still
   names the member. */
@media (max-width: 900px) {
  .tb-profile-me, .tb-profile-caret { display: none; }
  .tb-ava-btn { width: 40px; padding: 0; justify-content: center; border-radius: 50%; }
}

.tb-profile-pop {
  position: absolute;
  top: calc(100% + 10px); right: 0;
  z-index: 50;
  width: 268px;
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-pop);
  opacity: 0; visibility: hidden;
  transform: translateY(-4px);
  transition: opacity .16s var(--ease), transform .16s var(--ease), visibility .16s;
}
.tb-profile.open .tb-profile-pop { opacity: 1; visibility: visible; transform: none; }

.tb-profile-id { padding: 11px 12px 12px; border-bottom: 1px solid var(--line); margin-bottom: 6px; }
.tb-profile-id b {
  display: block;
  font-size: 14px; font-weight: 700; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tb-profile-id span {
  display: block; margin-top: 3px;
  font-size: var(--t-eyebrow); font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3);
}

.tb-profile-item {
  all: unset;
  box-sizing: border-box;
  display: block; width: 100%;
  padding: 9px 12px;
  border-radius: var(--radius-xs);
  font-size: 14px; font-weight: 600; color: var(--ink-2);
  cursor: pointer;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.tb-profile-item:hover { background: var(--surface-hover); color: var(--ink); }
.tb-profile-item:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }

@media (prefers-reduced-motion: reduce) {
  .gate-form input,
  .gate-form textarea,
  .gate-form button[type='submit'],
  .linkish { transition: none; }
}

/* ==================================================== analytics surfaces */
/* Everything below serves the dashboard and the analitika view. Same tokens,
   same light-first rule: not one literal colour, because the panel is light by
   default and only goes dark when data-theme says so, and a hardcoded value
   ships grey blocks onto a light page. */

/* The sample size, welded to the number it was computed from. Quiet on purpose
   — it is a qualifier, not a second figure competing with the first. */
.n {
  font-family: var(--font-b); font-variant-numeric: tabular-nums;
  font-size: 10.5px;
  font-weight: 500;
  color: var(--ink-3);
  letter-spacing: 0;
  white-space: nowrap;
}
.chip .n { color: inherit; opacity: .75; }

/* A change against the previous equal-length period. `flat` covers both "no
   change" and "nothing to compare with"; the second one says so on hover. */
.delta { font-family: var(--sans); font-size: 12px; font-weight: 600; white-space: nowrap; letter-spacing: 0; }
.delta.up { color: var(--green); }
.delta.down { color: var(--red-ink); }
.delta.flat { color: var(--ink-3); font-weight: 500; }
.kpis.pulse .kpi dd { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }

/* ------------------------------------------------------------- what to fix */
.attention { list-style: none; margin: 0; padding: 0; }
.att {
  display: grid; grid-template-columns: 26px minmax(0, 1fr); gap: 14px;
  padding: 15px 18px; border-bottom: 1px solid var(--line);
}
.att:last-child { border-bottom: 0; }
.att h3 { font-size: 14.5px; display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.att p { margin: 5px 0 0; font-size: 13.5px; line-height: 1.55; color: var(--ink-2); }
.att .att-mark { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; }
.att .att-mark svg { width: 15px; height: 15px; }
.att.high .att-mark { background: var(--red-soft); color: var(--red-ink); }
.att.medium .att-mark { background: var(--amber-soft); color: var(--amber); }
/* The finding is a sentence, so what it links to is a link, not a whole row
   pretending to be one: a focusable <li> announces as a list item and gives a
   keyboard user nothing to go on. */
.att-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin-top: 8px; font-size: var(--t-small); color: var(--ink-3); }
.att-foot:empty { display: none; }
.att-foot .linky { font-size: var(--t-small); color: var(--brand-ink); font-weight: 600; }

/* --------------------------------------------------------------- charts */
.chart { margin: 0; }
.chart svg { width: 100%; height: auto; display: block; }
.chart .axis { stroke: var(--line-strong); stroke-width: 1; }
.chart .tick { font-size: 11px; font-family: var(--font-b); font-variant-numeric: tabular-nums; fill: var(--ink-3); }
/* Total volume behind, answered in front of it: the gap between the two IS the
   unanswered calls, which is the reading a stacked bar would hide. */
.chart .bar-all { fill: var(--line); }
.chart .bar-ans { fill: var(--brand); fill-opacity: .55; }
.chart .bar-ab { fill: var(--red); fill-opacity: .85; }
.chart .bar-n { fill: var(--ink-3); fill-opacity: .28; }
.chart .score-line { fill: none; stroke: var(--ink); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart .score-dot { fill: var(--ink); }
.chart .legend {
  display: flex; flex-wrap: wrap; gap: 8px 20px; margin-top: 10px;
  font-size: var(--t-small); color: var(--ink-3);
}
.chart .legend span { display: inline-flex; align-items: center; gap: 7px; }
.chart .legend .key.sq { width: 11px; height: 11px; border-radius: 3px; }
.chart .legend .key.sq.all { background: var(--line); }
.chart .legend .key.sq.ans { background: var(--brand); opacity: .55; }
.chart .legend .key.sq.ab { background: var(--red); }
.chart .legend .key.sq.n { background: var(--ink-3); opacity: .28; }
.chart .legend .key.line { width: 18px; height: 0; border-top: 2px solid var(--ink); }

/* ------------------------------------------------------------ bar lists */
.blist { list-style: none; margin: 0; padding: 0; display: grid; gap: 11px; }
.blist li { display: grid; grid-template-columns: minmax(96px, 0.9fr) minmax(60px, 1.4fr) auto; gap: 14px; align-items: center; }
.blist .blabel { font-size: 13.5px; color: var(--ink-2); }
.blist .blabel small { display: block; font-size: 11.5px; color: var(--ink-3); }
.blist .btrack { height: 8px; border-radius: 4px; background: var(--line); overflow: hidden; }
.blist .btrack i { display: block; height: 100%; border-radius: 4px; background: var(--brand); }
.blist .btrack i.good { background: var(--green); }
.blist .btrack i.warn { background: var(--amber); }
.blist .btrack i.bad { background: var(--red); }
.blist .btrack i.mute { background: var(--ink-3); opacity: .5; }
.blist .bval { font-family: var(--font-b); font-variant-numeric: tabular-nums; font-size: 13.5px; text-align: right; }
.blist .bval small { color: var(--ink-3); font-size: 11.5px; }

/* A pass rate never appears without the count under it: 4 judgements and 400
   are the same picture otherwise, and only one of them is a finding. */
.passbar { display: inline-flex; align-items: center; gap: 9px; min-width: 150px; }
.passbar .bar { width: 74px; flex: none; }
.passbar b { font-family: var(--font-b); font-size: 13px; font-variant-numeric: tabular-nums; }
.passbar b.good { color: var(--green); }
.passbar b.warn { color: var(--amber); }
.passbar b.bad { color: var(--red-ink); }

/* --------------------------------------------------------------- heatmap */
/* 24 columns cannot fit a phone, so this scrolls inside .wrap rather than
   making the page scroll sideways. */
/* Natural width, not stretched: `min-width: 100%` handed all the slack to the
   weekday column and pushed the labels a screen away from their own row. */
table.heat { border-collapse: separate; border-spacing: 2px; width: auto; }
table.heat thead th {
  position: static; background: none; border: 0; padding: 0 0 4px;
  text-align: center; font-family: var(--font-b); font-variant-numeric: tabular-nums; font-size: 9.5px; letter-spacing: 0;
}
table.heat th.hd {
  padding: 0 8px 0 0; border: 0; text-align: right; font-size: 11px;
  text-transform: none; letter-spacing: 0; color: var(--ink-3); background: none; white-space: nowrap;
}
table.heat td.hc {
  width: 27px; min-width: 27px; height: 24px; padding: 0; border: 0;
  border-radius: 4px; text-align: center;
  font-family: var(--font-b); font-size: 10.5px; font-variant-numeric: tabular-nums;
  color: var(--ink-2); background: var(--surface-hover);
}
/* Five steps, not a continuous ramp: an eye reads steps and guesses at alpha. */
.heat td.l0 { color: var(--ink-3); opacity: .55; }
.heat td.l1 { background: color-mix(in srgb, var(--brand) 12%, var(--surface)); }
.heat td.l2 { background: color-mix(in srgb, var(--brand) 26%, var(--surface)); }
.heat td.l3 { background: color-mix(in srgb, var(--brand) 44%, var(--surface)); }
.heat td.l4 { background: color-mix(in srgb, var(--brand) 66%, var(--surface)); color: var(--ink); }
.heat td.l5 { background: color-mix(in srgb, var(--brand) 88%, var(--surface)); color: var(--ink); font-weight: 600; }
/* An hour where a fifth of the calls were abandoned. Marked, not recoloured:
   the fill is volume and it has to stay readable as volume. */
.heat td.leaky { box-shadow: inset 0 -3px 0 var(--red); }
.heat-body { padding-bottom: 0; }

/* --------------------------------------------------------- analitika bits */
.stack { display: grid; gap: 18px; }
.lead-line { margin: 16px 0 18px; font-size: 15px; color: var(--ink-2); }
.lead-line b { color: var(--ink); }

.ranked { list-style: none; counter-reset: rank; margin: 0; padding: 0; }
.ranked li {
  counter-increment: rank; position: relative;
  padding: 14px 18px 14px 46px; border-bottom: 1px solid var(--line);
}
.ranked li:last-child { border-bottom: 0; }
.ranked li::before {
  content: counter(rank); position: absolute; left: 18px; top: 14px;
  font-family: var(--font-b); font-variant-numeric: tabular-nums; font-size: 12px; color: var(--ink-3);
}
.ranked li b { display: block; font-size: 14px; font-weight: 600; margin-bottom: 8px; line-height: 1.4; }
.ranked li .sub { display: block; margin-top: 6px; font-size: var(--t-small); color: var(--ink-3); }

/* An operator's row opens onto the two lists that explain their rank. */
tr.sub[hidden] { display: none; }
tr.sub > td { background: var(--surface-hover); padding: 0; }
tr.expander .chev { color: var(--ink-3); font-size: 11px; }
tr.expander[aria-expanded="true"] .chev { color: var(--brand-ink); }
tr.expander[aria-expanded="true"] { background: var(--surface-hover); }
.opdetail { display: grid; grid-template-columns: 1fr 1fr; gap: 0; }
.opdetail > div { padding: 16px 20px; }
.opdetail > div + div { border-left: 1px solid var(--line); }
.opdetail h4 { margin: 0 0 10px; font-size: var(--t-eyebrow); text-transform: uppercase; letter-spacing: .1em; }
.opdetail h4.good { color: var(--green); }
.opdetail h4.bad { color: var(--red-ink); }
.opdetail ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.opdetail li { display: flex; justify-content: space-between; align-items: baseline; gap: 14px; font-size: 13px; }
.opdetail li span { color: var(--ink-2); }
.opdetail li b { font-family: var(--font-b); font-variant-numeric: tabular-nums; }
.opdetail p.dim { margin: 0; font-size: 13px; }

/* A name inside a clickable row still has to be its own destination. */
.linky {
  all: unset; cursor: pointer; font-weight: 600;
  border-bottom: 1px solid transparent;
}
.linky:hover { color: var(--brand-ink); border-bottom-color: var(--brand); }
.linky:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 3px; }

.reason .body { display: grid; gap: 8px; }
.quote-static {
  margin: 0; padding: 9px 13px; border-left: 2px solid var(--line-strong);
  background: var(--surface-hover); border-radius: 0 6px 6px 0;
  font-size: 13.5px; line-height: 1.55; color: var(--ink-2);
}

/* The money surface below its floor: the sentence IS the surface. No axes, no
   empty frame — a chart outline around two deals reads as a chart that failed
   to load rather than as a refusal to draw one. */
.card.gap { border-style: dashed; background: none; }
.gap-body { padding: 30px 28px; max-width: 66ch; }
.gap-body .label {
  display: block; font-size: var(--t-eyebrow); text-transform: uppercase;
  letter-spacing: .13em; color: var(--ink-3); font-weight: 600; margin-bottom: 10px;
}
.gap-body p { margin: 0; font-size: var(--t-lede); line-height: 1.4; color: var(--ink-2); font-weight: 500; }
.gap-body .facts { margin-bottom: 0; }

td.good { color: var(--green); }
td.warn { color: var(--amber); }
td.bad { color: var(--red-ink); }

@media (max-width: 1080px) {
  .opdetail { grid-template-columns: 1fr; }
  .opdetail > div + div { border-left: 0; border-top: 1px solid var(--line); }
}
@media (max-width: 700px) {
  .blist li { grid-template-columns: minmax(70px, 1fr) minmax(40px, 1fr) auto; gap: 10px; }
  .att { grid-template-columns: 1fr; gap: 10px; }
  .gap-body { padding: 22px 18px; }
}
/* ------------------------------------------------- rail, narrow viewports */
/* Appended at the end of the file on purpose. The existing max-width:1080px
   block turns the rail into a horizontal strip, and feat/analytics edits that
   same block — so these corrections go after it rather than inside it, where
   they would collide on every rebase. Cascade order does the rest.

   A row-direction rail needs the brand rule on its trailing edge and no
   divider above the member row: a border-top drawn across a horizontal strip
   reads as an underline under the whole nav. */
@media (max-width: 1080px) {
  /* The shell is a two-row grid at this width and auto rows stretch to fill
     its min-height:100vh, so the rail rendered as a ~344px band of empty
     surface with one row of buttons floating in the middle of it. Predates the
     reskin — it only became obvious once the rail had a background and a
     border of its own to show the empty space off. */
  .shell { align-content: start; }

  .rail .brand {
    height: auto; flex: none;
    padding: 12px 16px;
    border-bottom: 0;
    border-right: 1px solid var(--line);
  }
  /* The rail owns the horizontal scroll here, so the nav must not open a
     second scroll container inside it. */
  .nav { flex: none; padding: 8px 10px; overflow: visible; }

  /* Collapsing is a desktop affordance: the rail is already one row here, and
     a 68px override would fight the horizontal layout rather than help it.
     kit.css hides its own collapse control at its breakpoint for the same
     reason. The attribute is left on <html> so the preference survives a
     resize back to desktop. */
  .rail-collapse { display: none; }
  :root[data-rail='collapsed'] { --rail: 266px; }
  :root[data-rail='collapsed'] .rail .brand { padding: 12px 16px; justify-content: flex-start; }
  :root[data-rail='collapsed'] .rail .brand .name,
  :root[data-rail='collapsed'] .nav button .lbl,
  :root[data-rail='collapsed'] .nav .count { display: revert; }
  :root[data-rail='collapsed'] .nav button { justify-content: flex-start; padding: 0 12px; }
  :root[data-rail='collapsed'] .rail-ai { justify-content: flex-start; padding: 0 12px; height: 40px; }
  :root[data-rail='collapsed'] .rail-ai .lbl,
  :root[data-rail='collapsed'] .rail-ai-go { display: revert; }

  /* The rail is one horizontal row here, so «pinned to the foot» becomes
     «last, behind a rule»: the border moves to the leading edge and the item
     keeps its own width rather than stretching to the bar. It stays the only
     bordered thing in the row, which is what the treatment is for. */
  .rail-foot {
    padding: 8px 10px;
    border-top: 0;
    border-left: 1px solid var(--line);
    margin-left: auto;
  }
  .rail-ai { width: auto; height: 40px; }

  /* The pane stops being its own 100vh scroll container: with the rail above it
     rather than beside it, two stacked 100vh boxes put the page title off the
     bottom of the screen. The document scrolls instead, which is what it did
     before the topbar existed. */
  .pane { height: auto; overflow: visible; }
  .tb { position: sticky; top: 0; padding: 0 16px; }
  main { overflow-y: visible; }
}

/* ------------------------------------------------- «Ogohlantirishlar» */
/* Appended at the end of the file, after the narrow-viewport corrections
   above, so this block can only ever be overridden by a later one — several
   people edit this file at once and a rule dropped into the middle of it
   collides on every rebase.

   Tokens only, no literal colour: the panel's dark theme is `data-theme` on
   <html> and every value below is redefined in that one block, so both themes
   come out of the same rules. */

.alert-bar {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 12px; margin-bottom: 16px;
}
/* The count rides inside its own tab rather than beside the group: a tab
   labelled «Yangi» with no number is a tab you have to open to find out
   whether it is worth opening. */
.alert-bar .seg button { gap: 7px; }
.seg-n {
  font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums;
  color: var(--ink-3); background: var(--surface); border-radius: var(--pill);
  padding: 1px 6px; min-width: 20px; text-align: center;
}
.seg button[aria-pressed="true"] .seg-n { background: var(--brand-soft); color: var(--brand-ink); }

.alert-type { display: inline-flex; align-items: center; }
.alert-type select {
  font-family: var(--font-b); font-size: var(--t-small); font-weight: 600;
  color: var(--ink-2); background: var(--surface);
  border: 1px solid var(--line-2); border-radius: 7px;
  padding: 7px 11px; cursor: pointer;
  transition: border-color 140ms var(--ease), color 140ms var(--ease);
}
.alert-type select:hover { border-color: var(--line-strong); color: var(--ink); }
.alert-type select:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }

.alert-vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

.alert-stale {
  margin: 0 0 14px; padding: 10px 14px;
  font-size: var(--t-small); color: var(--amber);
  background: var(--amber-soft); border-radius: var(--radius-xs);
}

/* Two columns, the shape this list is already read in. It collapses to one
   below the width where a card's sentence starts wrapping every third word. */
.alert-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px; align-items: start;
}

.alert {
  position: relative;
  display: flex; flex-direction: column; gap: 9px;
  padding: 16px 18px 14px 21px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  transition: box-shadow 160ms var(--ease), border-color 160ms var(--ease);
}
.alert:hover { box-shadow: var(--shadow-sm); border-color: var(--line-2); }
/* Severity as a spine down the left edge. It is the second signal, never the
   only one — the chip beside the type says «shoshilinch» or «e'tiborga» in
   words, because a colour alone is not a status. */
.alert::before {
  content: ''; position: absolute; left: 0; top: 12px; bottom: 12px;
  width: 3px; border-radius: var(--pill);
}
.alert.high::before { background: var(--red); }
.alert.medium::before { background: var(--amber); }
/* An alert already dealt with keeps its place in its own tab but stops
   competing for attention in «Barchasi». */
.alert:not(.unread) { background: var(--surface-2); }
.alert:not(.unread) h3 { color: var(--ink-2); }
.alert:not(.unread)::before { opacity: .4; }

.alert-top { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; }
.alert-top-end { display: flex; align-items: center; gap: 9px; margin-left: auto; }
.alert-age {
  font-size: var(--t-small); color: var(--ink-3); white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.alert h3 { font-size: 15px; line-height: 1.35; }
.alert-detail { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--ink-2); }

/* The next step, given its own surface. This is the whole reason the page
   exists: a finding with no action attached is furniture, so the action is not
   allowed to read as the third sentence of a paragraph. */
.alert-do {
  margin: 2px 0 0; padding: 10px 12px;
  font-size: 13px; line-height: 1.5; color: var(--ink);
  background: var(--brand-soft); border-radius: var(--radius-xs);
}
.alert-do-lbl {
  display: block; font-size: var(--t-eyebrow); font-weight: 700;
  text-transform: uppercase; letter-spacing: .07em;
  color: var(--brand-ink); margin-bottom: 3px;
}

.alert-foot {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 10px; margin-top: auto; padding-top: 4px;
}
.alert-foot .who-name { font-size: 13px; }
.alert-foot .linky { font-size: var(--t-small); color: var(--brand-ink); font-weight: 600; }
.alert-scope { font-size: var(--t-small); color: var(--ink-3); }

.alert-acts {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding-top: 11px; border-top: 1px solid var(--line);
}
.alert-btn {
  font-family: var(--font-b); font-size: var(--t-small); font-weight: 600;
  color: var(--ink-2); background: var(--surface);
  border: 1px solid var(--line-2); border-radius: 7px;
  padding: 7px 12px; cursor: pointer;
  transition: background 140ms var(--ease), color 140ms var(--ease), border-color 140ms var(--ease), transform 90ms var(--ease);
}
.alert-btn:hover { background: var(--surface-hover); color: var(--ink); border-color: var(--line-strong); }
/* The press is felt, not just seen: these two buttons are the only thing on
   the page that changes anything, and both re-render the list underneath. */
.alert-btn:active { transform: translateY(1px); }
.alert-btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.alert-btn:disabled { opacity: .5; cursor: default; transform: none; }
/* The first action on an unread card is the expected one, so it carries the
   brand tint and the other stays quiet. */
.alert.unread .alert-btn[data-alert-act="read"] {
  color: var(--brand-ink); background: var(--brand-soft); border-color: transparent;
}
.alert.unread .alert-btn[data-alert-act="read"]:hover { background: var(--brand-soft-2); }

.alert-note {
  margin: 18px 0 0; font-size: var(--t-small); line-height: 1.6;
  color: var(--ink-3); max-width: 76ch;
}

@media (max-width: 1080px) {
  .alert-grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 560px) {
  .alert-bar { align-items: stretch; }
  /* Four labelled tabs each carrying a count measure ~380px, which is wider
     than a phone. They wrap into two rows rather than pushing the page into a
     horizontal scroll — measured at 375px, where the group overflowed by 17px
     before this rule existed. */
  .alert-bar .seg { flex-wrap: wrap; }
  .alert-bar .seg button { flex: 1 1 auto; }
  .alert-type, .alert-type select { width: 100%; }
  .alert-top-end { margin-left: 0; width: 100%; justify-content: space-between; }
}
/* ================================================== dashboard, hero-first */
/* Appended as one block rather than woven into the sections above, so a
   re-sync of the kit.css copy at the top of this file never has to walk
   through it. Tokens only — not one literal colour, because the panel is light
   by default and only goes dark when data-theme says so; a hardcoded value
   ships a grey block onto one of the two. Every tint below is a `-soft` token
   that both themes define, so there is nothing here for the dark block to
   override. */

/* The dashboard's own vertical rhythm. The blocks are not equal weight — the
   verdict is the page — so the gap is one value and the emphasis comes from
   size, not from spacing that grows to signal importance. */
.dash { display: grid; gap: 18px; }

/* ------------------------------------------------------------------ hero */
/* Left half says what happened, right half answers the four standing
   questions. The split is not 50/50: the sentence is the reason the card
   exists and the tiles are reference, so the reading order is enforced by
   width as well as by position. */
.hero {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  align-items: stretch;
}
.hero-say { padding: 24px 26px 26px; min-width: 0; display: flex; flex-direction: column; }

.hero-badges { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 18px; }

/* The filled pill. It is the only filled element on the page above the fold,
   which is what makes the card read as a header rather than a fourth panel. */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px 5px 9px;
  border-radius: var(--pill);
  background: var(--brand); color: var(--on-brand);
  font-size: var(--t-eyebrow); font-weight: 700;
  text-transform: uppercase; letter-spacing: .09em;
}
.pill svg { width: 13px; height: 13px; flex: none; }

/* The verdict itself. Space Grotesk at lede size and a tight measure: it has
   to survive being read at a glance from a metre away, which is how a manager
   reads a dashboard between two calls. */
.hero-line {
  margin: 0;
  font-family: var(--font-d);
  font-weight: 600;
  font-size: clamp(21px, 1.5vw + 12px, 31px);
  line-height: 1.28;
  letter-spacing: -0.025em;
  max-width: 30ch;
  text-wrap: balance;
}

.hero-support {
  display: flex; flex-wrap: wrap; align-items: center;
  margin: 16px 0 0;
  font-size: 13.5px; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.hero-support span + span::before {
  content: '·';
  color: var(--ink-4);
  margin: 0 9px;
}

/* Pushed to the bottom of the column so the sentence keeps the optical centre
   however many drivers cleared their floors. */
.hero-why { margin-top: auto; padding-top: 22px; }
.hero-why .eyebrow {
  display: block; margin-bottom: 9px;
  font-size: var(--t-eyebrow); font-weight: 700;
  text-transform: uppercase; letter-spacing: .11em;
  color: var(--ink-3);
}
.wchips { display: flex; flex-wrap: wrap; gap: 8px; }

/* One driver. The tint is the verdict's own reasoning made visible: green
   pushed the sentence up, red pushed it down, and a neutral chip was weighed
   and found not to move. */
.wchip {
  display: inline-flex; align-items: baseline; gap: 8px;
  padding: 7px 12px;
  border: 1px solid var(--line);
  border-radius: var(--pill);
  background: var(--surface);
  font-size: var(--t-small);
  color: var(--ink-2);
}
.wchip b { font-weight: 600; color: var(--ink-2); }
.wchip .wval {
  font-family: var(--font-d); font-weight: 600;
  font-size: 14px; letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.wchip.good { border-color: transparent; background: var(--green-soft); }
.wchip.good b, .wchip.good .wval { color: var(--green); }
.wchip.bad { border-color: transparent; background: var(--red-soft); }
.wchip.bad b, .wchip.bad .wval { color: var(--red-ink); }
.wchip .n { border: 0; padding: 0; background: none; }

/* ------------------------------------------------------------ hero tiles */
.hero-tiles {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--line);
  border-left: 1px solid var(--line);
}
.htile { background: var(--surface); padding: 18px 20px; display: flex; gap: 13px; min-width: 0; }

/* The daily digest's strip: the same tiles laid five across inside a card of
   their own. The hairline dividers come from the shared gap trick, and the
   card's own overflow:hidden clips the corner tiles — no extra rounding. */
.daily-tiles { grid-template-columns: repeat(5, 1fr); border-left: 0; }
@media (max-width: 1280px) { .daily-tiles { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 760px) { .daily-tiles { grid-template-columns: repeat(2, 1fr); } }
.htile .tbody { min-width: 0; display: flex; flex-direction: column; }

/* The tinted square. Same radius family as the cards, one step down, so the
   icons read as part of the surface rather than as stickers on it. */
.tico {
  width: 34px; height: 34px; flex: none;
  border-radius: var(--radius-xs);
  display: grid; place-items: center;
}
.tico svg { width: 17px; height: 17px; display: block; }
.tico.brand { background: var(--brand-soft); color: var(--brand-ink); }
.tico.violet { background: var(--violet-soft); color: var(--violet); }
.tico.blue { background: var(--blue-soft); color: var(--blue); }
.tico.amber { background: var(--amber-soft); color: var(--amber); }
.tico.red { background: var(--red-soft); color: var(--red-ink); }
.tico.green { background: var(--green-soft); color: var(--green); }

.tlabel {
  display: flex; align-items: center; gap: 6px;
  font-size: var(--t-eyebrow); font-weight: 700;
  text-transform: uppercase; letter-spacing: .09em;
  color: var(--ink-3);
}
.tvalue {
  margin-top: 7px;
  font-family: var(--font-d); font-weight: 600;
  font-size: 26px; line-height: 1.1; letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums;
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
}
.tvalue small { font-family: var(--font-b); font-weight: 500; font-size: 13px; color: var(--ink-3); }
.tsub { margin-top: 7px; font-size: 12.5px; color: var(--ink-3); }

/* The affordance that says a figure has a rule behind it. Focusable, because
   a tooltip only a mouse can reach is a tooltip half the readers never see. */
.info {
  width: 14px; height: 14px; flex: none;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--surface-hover); color: var(--ink-3);
  font-family: var(--font-b); font-size: 9.5px; font-weight: 700;
  text-transform: none; letter-spacing: 0;
  cursor: help;
}
.info:hover { background: var(--brand-soft); color: var(--brand-ink); }
.info:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* --------------------------------------------------------- quality strip */
.qcard .qstrip {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
}
.qtile { background: var(--surface); padding: 18px 20px 20px; display: flex; flex-direction: column; min-width: 0; }
.qtile .tico { margin-bottom: 14px; }
.qvalue {
  font-family: var(--font-d); font-weight: 600;
  font-size: 25px; line-height: 1.1; letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums;
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
}
.qvalue small { font-family: var(--font-b); font-weight: 500; font-size: 13px; color: var(--ink-3); }
.qlabel {
  display: flex; align-items: center; gap: 6px;
  margin-top: 9px;
  font-size: 13px; font-weight: 600; color: var(--ink-2);
}

/* ------------------------------------------------- comparison line chart */
/* Three series, one scale. The dashed line is the previous window and is drawn
   in ink-3 rather than in a fifth hue: it is the same measurement, not another
   one, and a second colour would invite the eye to read it as a second thing. */
.chart .grid-line { stroke: var(--line); stroke-width: 1; stroke-dasharray: 3 4; }
.chart .line-calls { fill: none; stroke: var(--brand); stroke-width: 2.2; stroke-linejoin: round; stroke-linecap: round; }
.chart .line-ans { fill: none; stroke: var(--blue); stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; }
.chart .line-prev {
  fill: none; stroke: var(--ink-3); stroke-width: 1.6;
  stroke-dasharray: 5 4; stroke-linejoin: round; stroke-linecap: round;
  opacity: .8;
}
.chart .dot-calls { fill: var(--brand); }
/* The band is a full-plot-height pointer target so the tooltip is easy to
   hit, which means its hover fill paints over the LINE, not under a bar.
   A solid surface tone there reads as a giant misdrawn column (it was
   screenshotted as a bug); the highlight must stay a breath of a tint. */
.chart .legend .key.line.calls { border-top-color: var(--brand); }
.chart .legend .key.line.ans { border-top-color: var(--blue); }
.chart .legend .key.line.prev { border-top: 2px dashed var(--ink-3); }

/* ------------------------------------------------------------ narrow */
/* The hero splits before the tiles do: a 30ch sentence beside a 2x2 grid stops
   working around 1100px, and stacking the two keeps both readable long before
   the tiles themselves have to become one column. */
@media (max-width: 1180px) {
  .hero { grid-template-columns: minmax(0, 1fr); }
  .hero-tiles { border-left: 0; border-top: 1px solid var(--line); }
  .qcard .qstrip { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .hero-say { padding: 20px 18px; }
  .hero-tiles { grid-template-columns: minmax(0, 1fr); }
  .qcard .qstrip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hero-line { max-width: none; }
}
@media (max-width: 460px) {
  .qcard .qstrip { grid-template-columns: minmax(0, 1fr); }
}

/* ============================================================ lead detail */
/* «Lid tafsilotlari» (/leads/:leadId), rendered by lead-detail.js. The facts,
   card and chip classes above are reused as-is; what is new here is the lead
   header, the «Biznes xulosa» card, the operational-signals grid and the CRM
   chronology timeline. Tokens only, so both themes follow the palette without a
   second rule. */

/* The header: breadcrumb, the contact as the title, the id and the verdict
   badge beside it, then the facts row. Lighter than the dashboard lede — the
   Biznes xulosa card below is where the eye is meant to land. */
.lead-head { margin-bottom: 20px; }
.lead-head .crumb { margin-bottom: 12px; }
.lead-title { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 12px; }
.lead-title h1 {
  font-family: var(--font-d); font-weight: 600; font-size: clamp(22px, 1.2rem + 1.2vw, 30px);
  letter-spacing: -.02em; color: var(--ink); margin: 0;
}

/* «Biznes xulosa» — the card a manager reads first. Two columns: the story and
   figures on the left, one next best step on the right. A left accent bar
   carries the verdict tone, so won / lost / open reads by hue before a word.
   Stacks under the aside on narrow screens. */
.bx-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(220px, 300px);
  gap: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 4px solid var(--ink-4);
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin-bottom: 26px;
}
.bx-good   { border-left-color: var(--green); }
.bx-bad    { border-left-color: var(--red); }
.bx-warn   { border-left-color: var(--amber); }
.bx-accent { border-left-color: var(--brand); }
.bx-mute   { border-left-color: var(--ink-4); }

.bx-main { padding: 20px 22px; }
.bx-head { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.bx-head h2 {
  font-family: var(--font-d); font-weight: 600; font-size: clamp(17px, 1rem + .5vw, 21px);
  letter-spacing: -.01em; color: var(--ink); margin: 0; line-height: 1.25;
}
.bx-story { margin: 0 0 16px; font-size: var(--t-body); color: var(--ink-2); line-height: 1.6; }
.bx-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.bx-chip {
  display: inline-flex; flex-direction: column; gap: 2px;
  padding: 7px 12px; background: var(--surface-2);
  border: 1px solid var(--line); border-radius: var(--radius-xs);
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-3);
}
.bx-chip b {
  font-family: var(--font-d); font-weight: 600; font-size: 14px;
  text-transform: none; letter-spacing: -.01em; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.bx-chip.good b { color: var(--green); }

/* The next best step, in its own tinted rail so it reads as an instruction, not
   more prose. A hairline separates it from the story on wide screens; on narrow
   ones it sits below with a top border instead. */
.bx-step {
  padding: 20px 22px;
  background: var(--surface-2);
  border-left: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 8px;
}
.bx-step-label {
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em;
  color: var(--brand-ink);
}
.bx-step p { margin: 0; font-size: var(--t-body); color: var(--ink); line-height: 1.55; }

@media (max-width: 720px) {
  .bx-card { grid-template-columns: minmax(0, 1fr); }
  .bx-step { border-left: 0; border-top: 1px solid var(--line); }
}

/* The in-product lead link that sits in a call's facts row, beside the external
   amoCRM link. A <button>, so it routes through the SPA rather than reloading;
   the brand ink and outline say it is a link, the missing glyph says it stays
   in the product. */
.fact.internal {
  cursor: pointer;
  font-family: var(--font-b);
  color: var(--brand-ink);
  border-color: var(--brand-soft-2);
  background: var(--surface);
}
.fact.internal b { color: inherit; }
.fact.internal:hover { background: var(--brand-soft); border-color: var(--brand); }
.fact.internal:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Four operational signals, one row. Hairline-gapped tiles the way the shell's
   other grids join, the figure in the display face at magnitude, the caption
   quiet under it. A tile whose count we could not fetch reads «—», never 0. */
.lead-signals {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  margin: 0;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.lead-signals > div { background: var(--surface); padding: 16px 18px; }
.lead-signals > div.unknown { background: var(--surface-2); }
.lead-signals dt {
  font-size: 11px; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .04em; margin-bottom: 8px;
}
.lead-signals dd { margin: 0; }
.lead-signals dd b,
.lead-signals dd .dim {
  font-family: var(--font-d); font-weight: 600; font-size: 28px;
  font-variant-numeric: tabular-nums; letter-spacing: -.02em; color: var(--ink);
}
.lead-signals dd .dim { color: var(--ink-4); }
.lead-signals p { margin: 6px 0 0; font-size: 11.5px; color: var(--ink-3); }

/* «Lid tafsilotlari» beside the CRM chronology — the competitor's two-column
   row under the signals. The panel is a narrow fixed rail; the chronology takes
   the rest. Stacks on a narrow screen. */
.lead-cols {
  display: grid;
  grid-template-columns: minmax(0, 340px) minmax(0, 1fr);
  gap: 20px;
  align-items: start;
  margin-top: 22px;
}
/* The left column is now a stack of analysis cards (details, reasons, actions,
   weaknesses), so it fills beside the chronology instead of sitting empty. */
.lead-side { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.la-sec { padding: 14px 16px; }
.la-head { display: flex; align-items: center; gap: 8px; margin-bottom: 11px; }
.la-head h3 {
  margin: 0; font-family: var(--font-d); font-weight: 600; font-size: 14px; color: var(--ink);
}
.la-n {
  font-size: 11px; color: var(--ink-3); background: var(--surface-2);
  border-radius: var(--pill); padding: 1px 8px; font-variant-numeric: tabular-nums;
}
.la-reasons { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 8px; }
.la-reasons li { font-size: 13px; line-height: 1.5; color: var(--ink-2); }
.la-reasons li.la-primary {
  color: var(--ink); background: var(--amber-soft); border: 1px solid var(--amber-soft);
  border-radius: var(--radius-xs); padding: 9px 11px;
}
.la-actions { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 8px; }
.la-actions li { font-size: 13px; line-height: 1.5; color: var(--ink-2); }
.la-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.la-evidence { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 11px; }
.la-evidence li { border-left: 2px solid var(--line-strong); padding-left: 11px; }
.la-evidence q {
  quotes: '«' '»'; font-size: 13px; line-height: 1.5; color: var(--ink-2); font-style: italic;
}
@media (max-width: 860px) {
  .lead-side { gap: 14px; }
}
.lead-cols .section-head { margin-top: 0; }
.ld-panel { padding: 4px 0; }
.ld-panel-head { padding: 14px 18px 6px; }
.ld-panel-head h3 {
  margin: 0; font-family: var(--font-d); font-weight: 600; font-size: 14px; color: var(--ink);
}
.ld-rows { margin: 0; }
.ld-rows > div {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 10px 18px; border-top: 1px solid var(--line);
}
.ld-rows dt { font-size: var(--t-small); color: var(--ink-3); flex: none; }
.ld-rows dd {
  margin: 0; text-align: right; color: var(--ink); font-size: 13px;
  font-variant-numeric: tabular-nums; min-width: 0;
}
.ld-crm {
  display: inline-flex; align-items: center; gap: 5px;
  margin: 12px 18px 14px; font-size: var(--t-small); font-weight: 600;
  color: var(--brand-ink);
}
.ld-crm:hover { text-decoration: underline; }
@media (max-width: 860px) {
  .lead-cols { grid-template-columns: minmax(0, 1fr); }
}

/* The chronology. A single rail down the left with a dot per event, each event
   a small card. The dot and a left accent carry the kind's colour, so a manager
   reads call / stage move / comment by hue before reading the label. */
.timeline { list-style: none; margin: 0; padding: 0; position: relative; }
/* A day divider between the events of different days, the way the competitor
   breaks its chronology. Centred over the rail, a quiet pill. */
.tl-day {
  position: relative; z-index: 1; display: flex; justify-content: center;
  margin: 4px 0 14px; padding: 0;
}
.tl-day:first-child { margin-top: 0; }
.tl-day span {
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--pill); padding: 3px 12px;
  font-size: var(--t-small); color: var(--ink-3); font-variant-numeric: tabular-nums;
}
.timeline::before {
  content: ''; position: absolute; left: 5px; top: 8px; bottom: 8px;
  width: 2px; background: var(--line);
}
.tl-item { position: relative; padding: 0 0 7px 28px; }
.tl-item:last-child { padding-bottom: 0; }
.tl-dot {
  position: absolute; left: 0; top: 8px;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--surface); border: 2.5px solid var(--ink-3); box-sizing: border-box;
}
.tl-card {
  background: var(--surface); border: 1px solid var(--line);
  border-left: 3px solid var(--ink-3); border-radius: var(--radius-xs);
  padding: 8px 12px;
}
.tl-top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.tl-kind { font-family: var(--font-d); font-weight: 600; font-size: 12.5px; color: var(--ink); }
.tl-ts { font-size: var(--t-small); color: var(--ink-3); white-space: nowrap; }
.tl-text { margin: 3px 0 0; font-size: 12.5px; color: var(--ink-2); line-height: 1.45; }
.tl-foot { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 12px; margin-top: 5px; }
.tl-author { font-size: var(--t-small); color: var(--ink-3); font-weight: 600; }

/* Kind colours, mapped to the status palette so they flip with the theme. */
.tl-call   .tl-dot { border-color: var(--brand); }
.tl-call   .tl-card { border-left-color: var(--brand); }
.tl-comment .tl-dot { border-color: var(--blue); }
.tl-comment .tl-card { border-left-color: var(--blue); }
.tl-stage  .tl-dot { border-color: var(--violet); }
.tl-stage  .tl-card { border-left-color: var(--violet); }
.tl-task   .tl-dot { border-color: var(--amber); }
.tl-task   .tl-card { border-left-color: var(--amber); }
.tl-sms    .tl-dot { border-color: var(--green); }
.tl-sms    .tl-card { border-left-color: var(--green); }
.tl-system .tl-dot { border-color: var(--ink-4); }
.tl-system .tl-card { border-left-color: var(--ink-4); }

@media (max-width: 760px) {
  .lead-signals { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 460px) {
  .lead-signals { grid-template-columns: minmax(0, 1fr); }
}
/* ============================================================================
   CRM view — «CRM va AI qamrovi» + amoCRM topshiriqlar
   (crm-coverage.js). Additive block; tokens only, both themes via --vars.
   ========================================================================== */
.crm-view { display: grid; gap: 22px; }
/* The coverage strip is a .kpis dl; its own margin-bottom would double the
   grid gap, so it is zeroed and the grid owns the rhythm. */
.crm-view .kpis.crm-cover { margin-bottom: 0; }
.crm-note { margin: 0; }

/* Topshiriqlar: a headline count and the overdue link sitting on one line
   above the per-manager table. */
.crm-tasks-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; padding: 16px 17px;
  border-bottom: 1px solid var(--line);
}
.crm-task-fig { display: flex; align-items: baseline; gap: 9px; min-width: 0; }
.crm-task-n {
  font-family: var(--font-d); font-weight: 600; font-size: 34px;
  line-height: 1; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.crm-task-lbl { font-size: 13px; color: var(--ink-3); }

/* The overdue count is a link into amoCRM where it is actually cleared: a red
   number you cannot act on is furniture. As a link it drops the underline and
   lifts slightly on hover so it reads as a destination, not a static badge. */
a.crm-overdue { text-decoration: none; transition: transform .12s var(--ease), box-shadow .12s var(--ease); }
a.crm-overdue:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); }
a.crm-overdue:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.crm-overdue b { font-weight: 700; }
/* ============================================================ reactivation */
/* «Lid xulosalari» — the lost/stalled-lead reactivation worklist. Built to the
   same shape as the alerts grid, because the manager reads both the same way:
   a column of cards, each a decision with a next step attached. Tokens only, so
   both themes come for free. */

/* «Lid xulosalari» — a table of lead analyses, the competitor's shape. A filter
   row, a result count, and one row per lead; the whole row is a link into the
   detail. */
.rx-bar {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 12px; margin-bottom: 16px;
}
.rx-bar .seg button { gap: 7px; }
.rx-count {
  margin-left: auto; font-size: var(--t-small); color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

/* The manager filter: a native select in a bordered pill, the icon a hint. */
.rx-select {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 0 10px; height: 32px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 7px; color: var(--ink-2);
}
.rx-select:focus-within { border-color: var(--brand); }
.rx-select-ic { display: inline-flex; color: var(--ink-3); }
.rx-select-ic svg { width: 15px; height: 15px; }
.rx-select select {
  border: 0; background: transparent; color: var(--ink);
  font: inherit; font-size: var(--t-small); padding: 0; cursor: pointer;
  max-width: 180px;
}
.rx-select select:focus { outline: none; }

/* The table scrolls inside the card, so the header stays put and the infinite
   scroll has a bounded container to fire against — the shape the call list
   uses. Its own height because this page carries a filter bar above the table
   and a note below it, where the call list carries only the filter bar. */
.rx-tablewrap { padding: 0; overflow: hidden; }
.rx-tablewrap .wrap-scroll { max-height: calc(100vh - 268px); }
@media (max-width: 900px) {
  .rx-tablewrap .wrap-scroll { max-height: calc(100vh - 300px); }
}
/* The sticky header needs its own ground: the base `thead th` paints
   `--surface-hover`, and rows would otherwise slide visibly under it. */
.rx-table thead th { position: sticky; top: 0; z-index: 2; background: var(--surface-hover); }
/* FIXED layout, and the widths are declared by the colgroup below. Under auto
   layout the browser weighs each column's widest cell against every other, so
   one fourteen-word grader sentence and one long «Hozircha erta — ~30 kundan
   so'ng» between them threw the whole table out: the reason column was crushed
   to a word a line (a 350px row), «Qayta aloqa» was pushed past the right edge,
   and the card grew a horizontal scrollbar. Six columns whose content is known
   in advance do not need measuring — they need deciding. The min-width is what
   they are decided AT: below it the card scrolls sideways rather than letting
   the one flexible column collapse to nothing. */
.rx-table {
  width: 100%; min-width: 900px;
  table-layout: fixed; border-collapse: collapse; font-size: var(--t-body);
}
.rx-c-when { width: 88px; }
.rx-c-who { width: 232px; }
.rx-c-outcome { width: 168px; }
/* The one column that takes the slack — the sentence is the only cell here
   whose length is genuinely unknown. */
.rx-c-why { width: auto; }
.rx-c-stage { width: 150px; }
.rx-c-recontact { width: 190px; }
.rx-c-chev { width: 34px; }
/* A fixed-layout cell does not clip on its own, so a long name ran under the
   next column's chip instead of ellipsising: `.who` is an inline-flex box sized
   by its content, and `.who-name` can only trim what it is given room to trim.
   «Шахноза Рўзийева (База )» is a real row. */
.rx-row .who { max-width: 100%; }
.rx-table thead th {
  text-align: left; padding: 11px 16px;
  font-size: var(--t-eyebrow); font-weight: 600; text-transform: uppercase;
  letter-spacing: .05em; color: var(--ink-3);
  border-bottom: 1px solid var(--line); white-space: nowrap;
}
.rx-table th.num, .rx-table td.num { text-align: right; }
.rx-table tbody td {
  padding: 12px 16px; border-bottom: 1px solid var(--line); vertical-align: middle;
  /* A fixed-layout cell does not clip on its own. */
  overflow: hidden;
}
.rx-table tbody tr:last-child td { border-bottom: 0; }

.rx-row { cursor: pointer; transition: background 120ms var(--ease); }
.rx-row:hover { background: var(--surface-hover); }
.rx-row:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.rx-row .who-name { font-size: var(--t-body); }

.rx-when { white-space: nowrap; }
.rx-time { display: block; color: var(--ink); font-weight: 500; font-variant-numeric: tabular-nums; }
.rx-date { display: block; font-size: var(--t-small); margin-top: 2px; }
/* Two lines and then an ellipsis, with the whole sentence in the tooltip. A
   list is read by running DOWN it: every row must start at a predictable
   height or the eye loses the column it was following. */
.rx-why { color: var(--ink-2); }
.rx-clamp {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; line-height: 1.45;
}
/* The pipeline stage is the CLIENT's own string, often already in capitals, and
   as plain body text beside two real chips it read as the loudest thing in the
   row. A neutral pill says «label» without claiming a verdict, and it
   ellipsises rather than wraps: a stage is recognised, not read. */
.rx-stagechip {
  display: inline-block; max-width: 100%;
  padding: 3px 9px; border-radius: var(--pill);
  background: var(--surface-hover); color: var(--ink-2);
  font-size: var(--t-small); font-weight: 500; line-height: 1.5;
  letter-spacing: 0; text-transform: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  vertical-align: middle;
}
/* The chip stays on one line; the timing under it may take two. It used to be
   `nowrap` on the whole cell, which is what made this column demand ~230px of
   a table that did not have it to give. */
.rx-recontact .chip { white-space: nowrap; }
.rx-timing {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: var(--t-small); line-height: 1.4; margin-top: 4px;
}
.rx-score b {
  font-family: var(--font-d); font-weight: 600; font-size: 16px;
  font-variant-numeric: tabular-nums;
}
.rx-score .rx-strong { color: var(--green); }
.rx-score .rx-mid { color: var(--amber); }
.rx-score .rx-weak { color: var(--red-ink); }
.rx-chev { width: 24px; text-align: right; color: var(--ink-4); }
.rx-row:hover .rx-chev { color: var(--brand); }

.rx-note { margin: 18px 0 0; font-size: var(--t-small); line-height: 1.6; color: var(--ink-3); }

/* Narrow: the grader's sentence is the first thing to go — it is the widest
   column and the only one that is context rather than identity. The COL is
   collapsed alongside the cells; hiding the cells alone would leave a
   fixed-layout table holding an empty column open, and hiding the td without
   its th (which is what this rule used to do) slid every header one column to
   the left of the data under it. */
@media (max-width: 900px) {
  .rx-c-why { width: 0; }
  .rx-th-why, .rx-why { display: none; }
  .rx-table { min-width: 640px; }
}


/* ============================== charts: trend redesign + donut =============
   Agent B (public/charts.js) markup. Tokens only: the dark theme is
   `data-theme` on <html> re-pointing the same vars, so no dark block needed.
   .key.line.prev (dashed) already exists in the pulse-compare block above. */
.delta .arr { font-style: normal; font-size: 8px; line-height: 1; margin-right: 3px; position: relative; top: -1px; }

.chart .trend-line { fill: none; stroke: var(--brand); stroke-width: 2.2; stroke-linejoin: round; stroke-linecap: round; }
.chart .trend-prev { fill: none; stroke: var(--ink-3); stroke-width: 1.6; stroke-dasharray: 5 5; stroke-linejoin: round; stroke-linecap: round; }
.chart .trend-dot { fill: var(--brand); stroke: var(--surface); stroke-width: 1.5; }
.chart .trend-area { stroke: none; }
.chart .trend-grad-a { stop-color: var(--brand); stop-opacity: .18; }
.chart .trend-grad-b { stop-color: var(--brand); stop-opacity: 0; }
.chart .vol-bar { fill: var(--ink-3); fill-opacity: .3; }
.chart .vol-thin { fill: var(--surface); stroke: var(--ink-3); stroke-width: 1.4; }
.chart .legend .key.line.cur { border-top-color: var(--brand); }
.chart .legend .key.sq.vol { background: var(--ink-3); opacity: .3; }

.donut { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }
.donut svg { width: 156px; height: 156px; flex: none; }
.donut .donut-track { fill: none; stroke: var(--line); stroke-width: 4.4; }
.donut .donut-seg { fill: none; stroke-width: 4.4; transform: rotate(-90deg); transform-origin: 50% 50%; }
.donut .donut-seg.good { stroke: var(--green); }
.donut .donut-seg.warn { stroke: var(--amber); }
.donut .donut-seg.bad { stroke: var(--red); }
.donut .donut-seg.mute { stroke: var(--ink-4); }
.donut .donut-seg.accent { stroke: var(--brand); }
.donut .donut-total { font-family: var(--font-d); font-weight: 600; font-size: 8px; fill: var(--ink); }
.donut .donut-cap { font-family: var(--font-b); font-size: 3.4px; fill: var(--ink-3); }
.donut-legend { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; flex: 1; min-width: 180px; align-content: center; }
.donut-legend li { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.donut-legend .sw { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.donut-legend .sw.good { background: var(--green); }
.donut-legend .sw.warn { background: var(--amber); }
.donut-legend .sw.bad { background: var(--red); }
.donut-legend .sw.mute { background: var(--ink-4); }
.donut-legend .sw.accent { background: var(--brand); }
.donut-legend .dlabel { flex: 1; color: var(--ink-2); }
.donut-legend small { color: var(--ink-3); font-variant-numeric: tabular-nums; }
/* ---- chart tooltip -------------------------------------------------------
   The panel's own hover label, replacing the browser's native `<title>` box.
   Two properties matter and neither was available before: it opens on the
   first pointer event instead of after the engine's half-second delay, and it
   can carry a colour key, so a day on a three-line chart is three labelled rows
   rather than one comma-spliced sentence.

   Positioned with a transform from the top-left corner: it follows the pointer
   across a chart, and moving it by `left`/`top` re-flows the document on every
   mouse event. pointer-events:none so it can never sit between the pointer and
   the band it is describing, which is how a tooltip flickers itself to death. */
.charttip {
  position: fixed; left: 0; top: 0; z-index: 60; pointer-events: none;
  max-width: 288px; padding: 9px 11px;
  border: 1px solid var(--line-2); border-radius: var(--radius-xs);
  background: var(--surface); box-shadow: var(--shadow-lg);
  font-family: var(--font-b); font-size: 12.5px; line-height: 1.4; color: var(--ink-2);
}
.charttip[hidden] { display: none; }
.charttip > b {
  display: block; font-family: var(--font-d); font-size: 13px; font-weight: 600;
  color: var(--ink); margin-bottom: 5px;
}
/* A single-line tip is one sentence and nothing else — the margin under the
   heading would be a gap under a box with nothing in it. */
.charttip > b:only-child { margin-bottom: 0; font-family: var(--font-b); font-size: 12.5px; font-weight: 500; color: var(--ink-2); }
.charttip .r { display: flex; align-items: center; gap: 7px; margin-top: 3px; }
.charttip .r:first-of-type { margin-top: 0; }
.charttip .sw { width: 9px; height: 9px; border-radius: 2px; flex: none; background: var(--ink-4); }
.charttip .k { color: var(--ink-3); }
/* The number is pushed to the right edge so three rows read as a small table:
   the eye compares figures down a column, not across a sentence. */
.charttip .v { margin-left: auto; padding-left: 12px; color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
/* The definition variant. Each row is one flowing line — «lid — hozir shu
   bosqichda turganlar» — because a definition has no right-hand column to
   line up under: the eye reads it across, not down. Inline label and value so
   a long one wraps as prose rather than as a narrow ragged block, and no
   tabular numerals, since nothing here is a number. */
.charttip.defs { max-width: 324px; }
.charttip.defs .r { display: block; margin-top: 5px; }
/* The heading already carries the gap under itself. */
.charttip.defs .r:first-of-type { margin-top: 0; }
.charttip.defs .k { display: inline; color: var(--ink); font-weight: 600; }
.charttip.defs .k::after { content: ' — '; color: var(--ink-3); font-weight: 400; }
.charttip.defs .v {
  display: inline; margin-left: 0; padding-left: 0;
  color: var(--ink-2); font-weight: 400; font-variant-numeric: normal;
}

.charttip small {
  display: block; margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--line);
  font-size: 11.5px; color: var(--ink-3);
}
/* Swatches name the series they belong to, and take their colour from the same
   token the line does — a legend that disagrees with its chart is worse than
   no legend. */
.charttip .sw.calls, .charttip .sw.cur, .charttip .sw.accent { background: var(--brand); }
.charttip .sw.ans { background: var(--blue); }
.charttip .sw.prev { background: var(--ink-3); }
.charttip .sw.vol { background: var(--ink-3); opacity: .4; }
.charttip .sw.good { background: var(--green); }
.charttip .sw.warn { background: var(--amber); }
.charttip .sw.bad { background: var(--red); }
.charttip .sw.mute { background: var(--ink-4); }

/* The crosshair and the markers live inside the hover band and are revealed by
   CSS, not by script: a reader sweeping a 30-day line crosses a band every few
   pixels, and a highlight that waits for a listener to run visibly trails the
   pointer. Both are pointer-transparent, or the marker under the cursor would
   steal the hover from the band that owns the label. */
.chart .band .crosshair,
.chart .band .band-dot { opacity: 0; pointer-events: none; }
.chart .band:hover .crosshair,
.chart .band:hover .band-dot { opacity: 1; }
.chart .crosshair { stroke: var(--ink-3); stroke-width: 1; stroke-dasharray: 3 3; }
.chart .band-dot { stroke: var(--surface); stroke-width: 2; }
.chart .band-dot.calls, .chart .band-dot.cur { fill: var(--brand); }
.chart .band-dot.ans { fill: var(--blue); }
.chart .band-dot.prev { fill: var(--ink-3); }

/* The band itself no longer needs to tint: the crosshair says where the pointer
   is, and a grey wash over a fifth of the plot was heavier than the reading it
   supported. It stays as a whisper so the hit area is still discoverable. */
.chart .hoverband { fill: transparent; }
.chart .band:hover .hoverband { fill: var(--ink-3); fill-opacity: .05; }

/* An arc under the pointer thickens rather than lightens: the ring is the only
   thing on the donut and a colour change there reads as a different value. */
.donut .donut-seg { transition: stroke-width .12s var(--ease); }
/* :has, so the ring only dims when an ARC is under the pointer. Keyed on the
   svg alone it dimmed every slice the moment the pointer crossed the hole in
   the middle, which is most of the donut's area and none of its data. */
.donut svg:has(.donut-seg:hover) .donut-seg { stroke-opacity: .4; }
.donut .donut-seg:hover { stroke-opacity: 1; stroke-width: 5.6; }

.hc { cursor: default; }
.heat .hc:hover { outline: 2px solid var(--brand); outline-offset: -2px; }

/* Anything else carrying a label — a count in a legend, an «i», a criterion cut
   short — says so with the same cursor the native tooltip used to imply. */
.n[data-tip], .delta[data-tip], .crit-sub[data-tip], .crit-q[data-tip],
.wk-badge[data-tip], .info[data-tip], .set-input .lock { cursor: help; }


/* ============================ Analitika redesign: views (agent C) ==== */
/* Umumiy tab (verdict hero, six-tile KPI band, ranking footer), Sifat
   coaching cards and criteria bar rows, the centred quality refusal.
   Tokens only: dark mode is the same tokens flipping under [data-theme]. */

/* The verdict hero on Umumiy is the dashboard hero without its tile
   column: one column, so the sentence keeps the full width. */
.ov-hero { grid-template-columns: minmax(0, 1fr); }

/* Six standing figures in one band. Each dd carries its own delta chip, so
   the cell is flex to keep number and arrow on one baseline. The base rule
   is appended after the 1080px collapse in the file, so the collapse is
   restated below rather than inherited. */
.kpis.ov-kpis { grid-template-columns: repeat(6, 1fr); }
.kpis.ov-kpis .kpi:first-child dd { font-size: 26px; }
.kpis.ov-kpis .kpi dd,
.kpis.q-kpis .kpi dd { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.kpis.ov-kpis .kpi dd small { font-family: var(--font-b); font-weight: 500; font-size: 13px; color: var(--ink-3); }
.kpis.q-kpis .kpi dd.good { color: var(--green); }
.kpis.q-kpis .kpi dd.bad { color: var(--red-ink); }
.kpis.q-kpis .kpi dd.dim { color: var(--ink-3); }
/* The weakest/strongest cells hold a question, not a magnitude: two lines,
   ellipsis, full text on the title attribute. A grid track does not shrink
   below its content's min-width unless told to, so a long criterion on one
   unbreakable line stretched its column and pushed «Eng kuchli mezon» off
   the right edge (Darmon Servis, 15 Oct 2026): the cells may shrink, and the
   question wraps instead of widening the band. */
@media (min-width: 1081px) {
  .kpis.q-kpis { grid-template-columns: minmax(0, 1.5fr) repeat(3, minmax(0, 1fr)); }
}
.kpis.q-kpis .kpi { min-width: 0; }
.kpi .sub.crit-sub {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden; overflow-wrap: anywhere;
}

.rank-foot { margin: 0; padding: 4px 17px 14px; }

/* Coaching cards: what is happening on the calls against what the rubric
   wants to hear, one card per weakest criterion. */
/* The card bones «Mashg'ulotni shulardan boshlang» used to own. Sifat draws a
   ranked list now, but Jamoa's coaching queue (.opcoach) and the loading
   skeleton were built ON these, so they stay shared rather than being folded
   into .opcoach — the queue's own comment says it borrows them. */
.coach-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; margin-bottom: 22px; align-items: stretch; }
.coach-card { display: flex; flex-direction: column; gap: 12px; padding: 15px 17px; }
.coach-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.coach-top h3 { margin: 0; font-size: 14.5px; line-height: 1.4; font-weight: 600; color: var(--ink); }

/* ---- «Suhbatning qaysi bosqichi yo'qotmoqda» ----------------------------
   The group rates, at the TOP of Sifat rather than at its foot. Bars share one
   scale (the best group is full width) so the eye compares lengths, not
   numbers; the number stays on the row because a bar is a shape, not a value. */
.qsum-line { margin: 0 0 14px; font-size: 15px; line-height: 1.55; color: var(--ink-2); }
.qsum-line b { color: var(--ink); font-weight: 600; }
.qsum-bars { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.qsum-bars li { display: grid; grid-template-columns: minmax(120px, 200px) 1fr auto; gap: 14px; align-items: center; }
.qsum-name { font-size: 13.5px; color: var(--ink-2); }
.qsum-track { height: 8px; border-radius: var(--pill); background: var(--line); overflow: hidden; }
.qsum-track i { display: block; height: 100%; border-radius: var(--pill); background: var(--ink-4); }
.qsum-track i.good { background: var(--green); }
.qsum-track i.warn { background: var(--amber); }
.qsum-track i.bad { background: var(--red); }
.qsum-val { font-family: var(--font-d); font-weight: 600; font-size: 15px; font-variant-numeric: tabular-nums; min-width: 2.5ch; text-align: right; }
@media (max-width: 620px) {
  .qsum-bars li { grid-template-columns: 1fr auto; }
  .qsum-track { grid-column: 1 / -1; }
}

/* ---- the ranked problem list -------------------------------------------
   Replaces a five-card grid. A card each gave every problem the same weight
   and only five fitted; a numbered list carries the ranking in its own shape,
   puts the call COUNT beside the rate, and lets the rest sit behind a summary
   instead of being cut off. */
.problems { list-style: none; margin: 0; padding: 0; counter-reset: prob; }
.prob { display: grid; grid-template-columns: 30px 1fr; gap: 16px; padding: 16px 17px; border-top: 1px solid var(--line); }
.prob:first-child { border-top: 0; }
.prob-n {
  font-family: var(--font-d); font-weight: 600; font-size: 15px; line-height: 1.5;
  color: var(--ink-4); font-variant-numeric: tabular-nums;
}
.prob-main { display: grid; gap: 8px; min-width: 0; }
.prob-head { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; }
.prob-head b { font-size: 15px; font-weight: 600; line-height: 1.4; }
.prob-rate { flex: none; font-family: var(--font-d); font-weight: 600; font-size: 19px; font-variant-numeric: tabular-nums; }
.prob-rate.good { color: var(--green); }
.prob-rate.warn { color: var(--amber); }
.prob-rate.bad { color: var(--red-ink); }
/* The count a coach acts on. It used to be footer-sized under the rate; it is
   the number that decides which hour of coaching is worth spending. */
.prob-vol { font-size: 13px; color: var(--ink-3); }
.prob-vol b { font-family: var(--font-b); font-variant-numeric: tabular-nums; font-weight: 700; color: var(--ink-2); }

/* «Hozir» against «Kerak», side by side. Two columns because they are a pair
   to be read across, not a list to be read down. */
.prob-anchors { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 2px; }
@media (max-width: 720px) { .prob-anchors { grid-template-columns: 1fr; } }
.anch { border-radius: var(--radius-xs); padding: 9px 12px; }
.anch .anch-k { display: block; font-size: var(--t-eyebrow); font-weight: 700; letter-spacing: .07em; text-transform: uppercase; margin-bottom: 3px; }
.anch p { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--ink-2); }
.anch.bad { background: var(--red-soft); }
.anch.bad .anch-k { color: var(--red-ink); }
.anch.good { background: var(--green-soft); }
.anch.good .anch-k { color: var(--green); }

.prob-more { border-top: 1px solid var(--line); }
.prob-more > summary { cursor: pointer; padding: 13px 17px; font-size: 13.5px; font-weight: 600; color: var(--brand-ink); }
.prob-more > summary:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.prob-more[open] > summary { border-bottom: 1px solid var(--line); }
.prob-more .prob:first-child { border-top: 0; }

.coach-empty { margin-bottom: 22px; }

/* Criteria as bar rows: question, pass bar, then the raw answer counts
   kept visible on the right. Below-floor rows keep the thin treatment. */
.crit-rows { list-style: none; margin: 0; padding: 0; }
.crit-rows .crit { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(220px, 1fr) auto; gap: 8px 18px; align-items: center; padding: 11px 0; border-top: 1px solid var(--line); }
.crit-rows .crit:first-child { border-top: 0; padding-top: 2px; }
.crit-rows .crit:last-child { padding-bottom: 2px; }
.crit-rows .crit.thin .crit-q b { color: var(--ink-3); font-weight: 500; }
.crit-q { min-width: 0; }
.crit-q b { font-weight: 600; }
.crit-counts { display: flex; align-items: center; gap: 12px; justify-content: flex-end; white-space: nowrap; font-size: 12.5px; font-variant-numeric: tabular-nums; color: var(--ink-2); }
.wk-badge { display: inline-flex; align-items: center; border-radius: var(--pill); padding: 2px 9px; font-size: 11.5px; font-weight: 700; background: var(--amber-soft); color: var(--amber); }

/* The full-panel refusal on Sifat: .empty already centres its text, the
   card frames it instead of leaving a bare strip on the page ground. */
.q-refusal .empty { max-width: 520px; margin: 0 auto; }

@media (max-width: 1080px) {
  .kpis.ov-kpis { grid-template-columns: repeat(2, 1fr); }
  .crit-rows .crit { grid-template-columns: 1fr; gap: 8px; }
  .crit-counts { justify-content: flex-start; }
}
@media (max-width: 700px) {
  .kpis.ov-kpis { grid-template-columns: 1fr; }
}

/* ================= analitika 2-bosqich: trafik KPI + callbacks + jamoa navbati */

/* Trafik KPI band: figure and delta share a baseline, the ov-kpis convention,
   and the transfer share rides as a small beside its count. */
.kpis.tr-kpis .kpi dd { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.kpis.tr-kpis .kpi dd small { font-family: var(--font-b); font-weight: 500; font-size: 13px; color: var(--ink-3); }

/* Callbacks card: the UNRESOLVED count is the headline because it is the pile
   still costing money; resolved work gets the two-tone share bar under it. */
.cb-head { display: flex; align-items: center; gap: 14px; margin: 0 0 12px; }
.cb-num { font-family: var(--font-d); font-weight: 600; font-size: 36px; line-height: 1; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.cb-num.bad { color: var(--red-ink); }
.cb-num.good { color: var(--green); }
.cb-headtext { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cb-headtext b { font-size: 13.5px; color: var(--ink); }
.cb-headtext span { font-size: 12.5px; color: var(--ink-3); }
.cb-share { display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--ink-2); }
.cb-share b { font-variant-numeric: tabular-nums; }
.cb-bar { flex: 1 1 60px; min-width: 60px; height: 6px; border-radius: 3px; background: var(--red-soft); overflow: hidden; }
.cb-bar i { display: block; height: 100%; background: var(--green); border-radius: 3px; }
.cb-median { margin: 6px 0 0; font-size: 12.5px; color: var(--ink-3); }
.cb-label { display: block; margin: 14px 0 4px; font-size: var(--t-eyebrow); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); }
.cb-list { list-style: none; margin: 0; padding: 0; }
.cb-list li { display: flex; align-items: baseline; gap: 10px; padding: 6px 0; border-top: 1px solid var(--line); font-size: 13px; }
.cb-list li:first-child { border-top: 0; }
.cb-tel { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cb-att { color: var(--red-ink); font-size: 12.5px; }
.cb-when { margin-left: auto; font-size: 12px; white-space: nowrap; }
.cb-unknown { margin: 10px 0 0; font-size: 12.5px; }

/* Jamoa coaching queue: coach-card bones, operator-shaped filling. .opcoach
   rather than reusing sifat's block classes so the two grids can drift apart
   without colliding. */
.opcoach-top { display: flex; align-items: center; gap: 10px; min-width: 0; }
.opcoach-top .chip { margin-left: auto; flex: none; }
.opcoach-id { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.opcoach-id .linky { font-weight: 600; font-size: 14px; text-align: left; align-self: flex-start; }
.opcoach-id .dim { font-size: 12px; }
.opcoach-gap { margin: 0; font-size: 12.5px; color: var(--ink-3); }
.opcoach-gap .vs { font-size: 13px; font-weight: 600; }
.opcoach-weak { border-radius: var(--radius-xs); padding: 10px 12px; background: var(--red-soft); }
.opcoach-weak .coach-k { display: block; font-size: var(--t-eyebrow); font-weight: 700; letter-spacing: .07em; text-transform: uppercase; margin-bottom: 4px; color: var(--red-ink); }
.opcoach-weak p { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--ink-2); }
.opcoach-weak .opcoach-rate { margin-top: 6px; font-size: 12.5px; }
.opcoach .coach-foot .linky { color: var(--brand-ink); font-weight: 600; font-size: var(--t-small); }
.opcoach-none { margin: 0 0 22px; font-size: 13px; }

/* =================================================== tahlil o‘rinlari (plan) */
/* Appended after the base sheet on purpose: the .wrap-scroll retune at the
   bottom must outweigh the 232px/268px offsets declared above it, and a later
   rule of equal specificity wins the cascade. */

/* The plan block left behind in .page-head once the title is hoisted into the
   topbar: counter chip, one explanatory line, and the slot the server's 409
   sentence appears in. */
.plan-head { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; min-width: 0; }
.plan-head .chip { font-size: 12px; padding: 3px 10px; }
.plan-sub { margin: 0; font-size: 12px; color: var(--ink-3); }
.plan-note { margin: 0; font-size: 12px; font-weight: 600; color: var(--red-ink); }
.plan-note[hidden] { display: none; }

/* The «Tahlil» switch column. A plain th — there is nothing to sort — kept
   narrow so the seven data columns lose almost nothing to it. */
.th-switch { width: 52px; }
td.cell-switch { width: 52px; }

/* role=switch as track and knob. Only background and transform move, and
   disabled IS the in-flight state: the answer comes from the server, so the
   control goes quiet for the round trip instead of guessing. */
.seat-switch {
  all: unset; box-sizing: border-box; cursor: pointer;
  position: relative; display: inline-block; vertical-align: middle;
  width: 32px; height: 19px; border-radius: 999px; flex: none;
  background: var(--line-strong);
  transition: background .15s var(--ease);
}
.seat-switch::after {
  content: ''; position: absolute; top: 2.5px; left: 2.5px;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--surface); box-shadow: 0 1px 2px rgba(0,0,0,.28);
  transition: transform .15s var(--ease);
}
.seat-switch[aria-checked="true"] { background: var(--brand); }
.seat-switch[aria-checked="true"]::after { transform: translateX(13px); }
.seat-switch:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.seat-switch[disabled] { opacity: .55; cursor: default; }

/* An excluded seat dims its NAME and nothing else: the numbers are real
   history and must not read as deleted. */
tr.plan-off .who-name { color: var(--ink-3); }
tr.plan-off .avatar { opacity: .65; }

/* ---------------------------------------------------- .wrap-scroll retune -- */
/* The 232px/268px offsets above predate the topbar redesign: the h1 and its
   caption (~68px including .page-head's 20px margin) now hoist into the topbar
   and the emptied .page-head is removed, so those offsets left a dead band
   under the card. Measured from the current layout, top to bottom: topbar 72
   + 1px rule, main padding-top 26, card borders 2, the one-line .note under
   the table 38 (10+10 padding, ~17px line, 1px rule), main padding-bottom 60
   = 199, rounded to 200. dvh so mobile browser chrome cannot hide the card
   bottom; internal scroll stays — the sticky thead needs it. This later rule
   also overrides the 268px inside the old 900px media block: same
   specificity, later in the file. */
.wrap-scroll { max-height: calc(100dvh - 200px); }

/* Under a cap the plan block keeps .page-head alive above the card: chip ~24,
   sub-line ~17, gaps, and the head's 20px margin ≈ +64. */
.wrap-scroll.with-plan { max-height: calc(100dvh - 264px); }

/* No arithmetic: the calls view is a flex column and the card takes exactly
   what is left. Three fixed offsets in a row (272, 244, 200) each either left
   a dead band or made MAIN scroll a few px alongside the inner list — two
   nested scrollbars that ping-ponged on a swipe and jumped when load-more
   appended. Flex cannot be off by pixels. A browser without :has falls back
   to the generic 200px cap above and merely scrolls main a little. */
main:has(.calls-table) {
  display: flex; flex-direction: column;
  overflow-y: hidden;
  padding-bottom: 18px;
}
main:has(.calls-table) > * { flex: none; }
main:has(.calls-table) > .card:has(.calls-table) {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
}
main:has(.calls-table) .wrap-scroll:has(.calls-table) {
  flex: 1; min-height: 0; max-height: none;
}

@media (max-width: 900px) {
  /* The calls filter bar wraps to a second row (+44); the plan sub-line wraps
     once (+18). The bare variant is re-stated too: the unmediaed 200px rule
     above outweighs the old mobile tuning by source order, and the narrow
     topbar still takes its extra 36px on this width. */
  .wrap-scroll { max-height: calc(100dvh - 236px); }
  .wrap-scroll.with-plan { max-height: calc(100dvh - 282px); }
}

/* ================================================================= toast */
/* The transient answer to a click, fixed where the eye already is. Neutral
   ink-on-surface inversion works in both themes; `bad` earns a red edge, not
   a red slab — the sentence is the warning, the color only points at it. */
.toast {
  position: fixed; left: 50%; bottom: 26px; z-index: 90;
  max-width: min(560px, calc(100vw - 32px));
  padding: 11px 16px; border-radius: var(--radius-xs);
  background: var(--ink); color: var(--bg);
  font-size: 13.5px; line-height: 1.45; box-shadow: var(--shadow);
  opacity: 0; transform: translate(-50%, 8px); pointer-events: none;
  transition: opacity .18s ease, transform .18s ease;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
.toast.bad { border-left: 3px solid var(--red); }

/* ---- Operator funksiyasi: chip and the Jamoa filter ------------------- */
/* The function chip is an identifier, not a verdict: small, mute, lowercase,
   and absent entirely when the function is unknown. Extends .chip.mute. */
.fn-chip {
  font-size: 10.5px;
  padding: 1px 7px;
  margin-left: 6px;
  text-transform: lowercase;
  vertical-align: middle;
}

/* Hammasi / Sotuv / Qabul / Baza over the Jamoa tab. Same pressed grammar as
   the period buttons (aria-pressed), so the page keeps one filter language. */
.fn-chips { display: inline-flex; gap: 6px; margin: 14px 0 2px; flex-wrap: wrap; }
.fn-chips button {
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-3);
  border-radius: 999px;
  padding: 4px 12px;
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
}
.fn-chips button:hover { color: var(--ink); background: var(--surface-hover); }
.fn-chips button[aria-pressed="true"] {
  background: var(--brand-soft-2);
  border-color: var(--brand);
  color: var(--brand-deep);
  font-weight: 600;
}
.fn-chips button:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
/* The jamoa skeleton reuses .fn-chips as a bar row; inline-flex + gap serve both. */
/* Group and function chips stacked: one row each, the label naming the row
   only when both are drawn. */
.roster-filter { display: flex; flex-direction: column; gap: 6px; margin: 14px 0 6px; }
.roster-filter .fn-chips { margin: 0; align-items: center; }
.fn-chips-label { font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-4); min-width: 72px; }


/* ---------------------------------------------------------------- parts
   Who else was on the call. A numbered chain rather than cards: these are
   ordered in time and the handoff between two people is the whole point, so
   the rows read down the page like a relay and never like a grid of equals. */
.parts { list-style: none; margin: 0; padding: 0; }
.part {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
/* The baton is now an ELEMENT and not a ::before, because it carries a word.
   «uzatdi» between two rows is the answer to the question this block exists
   for — who handed the call to whom — and a bare 2px connector left the
   reader to infer a direction that the data actually states. */
.part-arrow {
  display: flex; align-items: center; gap: 8px;
  padding: 2px 0 2px 26px;
  font-size: 11.5px; letter-spacing: .02em; text-transform: lowercase;
  color: var(--muted);
}
.part-arrow::before {
  content: ''; flex: none;
  width: 2px; height: 14px; background: var(--line);
  margin-left: -1px;
}
.part-arrow span { margin-left: 2px; }
.part-arrow span::before { content: '\2193'; margin-right: 4px; }
.part-n {
  flex: none;
  width: 22px; height: 22px; border-radius: 999px;
  display: grid; place-items: center;
  font-size: 11.5px; font-weight: 700;
  color: var(--brand); background: var(--brand-soft);
  font-variant-numeric: tabular-nums;
}
.part-who { text-decoration: none; color: inherit; min-width: 0; }
.part-who:hover b { color: var(--brand); }
.part .dim { margin-left: auto; font-variant-numeric: tabular-nums; }
.part .who { display: flex; align-items: center; gap: 8px; min-width: 0; }
.part .who .mono { font-size: 11.5px; }
/* A leg the ATS never recorded. Dimmed rather than hidden: it is the finding,
   and a row that quietly vanished would make a 14-minute call look like a
   90-second one and look complete doing it. */
.part-unrecorded { border-style: dashed; background: transparent; }
.part-unrecorded .who b { color: var(--muted); }
/* One play button per leg, sized to the row rather than to the page: the
   recording at the top of the page is the conversation, these are the other
   halves of it. */
.part-play {
  flex: none;
  width: 28px; height: 28px; border-radius: 999px;
  display: grid; place-items: center;
  border: 1px solid var(--line); background: var(--surface);
  color: var(--text); cursor: pointer;
}
.part-play:hover { border-color: var(--brand); color: var(--brand); }
.part-play svg { width: 11px; height: 11px; fill: currentColor; }

/* ---------------------------------------------------------------- MCP ----
   Sozlamalar → «MCP — AI ulanish». The section is mostly PROSE and copyable
   blocks rather than the definition lists the rest of Sozlamalar is made of:
   what a manager does here is read three paragraphs, press one button, and
   paste the result into a program on their own machine — which is a document
   with controls in it, not a settings form. */

.set-lead {
  margin: 0 0 18px;
  font-size: 13.5px; line-height: 1.6; color: var(--ink-2);
}
.set-lead b { color: var(--ink); }

/* What it may read, and the two things it may not. Three cards rather than a
   paragraph, because «it cannot hear the recordings» is the question every
   manager asks second and nobody finds in the middle of a sentence. */
.mcp-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 12px;
  margin-bottom: 22px;
}
.mcp-fact {
  padding: 13px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  border-left: 3px solid var(--line-2);
}
.mcp-fact.ok { border-left-color: var(--green); }
.mcp-fact.no { border-left-color: var(--line-2); }
.mcp-fact b { display: block; font-size: 13px; margin-bottom: 5px; }
.mcp-fact span { display: block; font-size: 12.5px; line-height: 1.55; color: var(--ink-3); }

.mcp-keyblock { margin-bottom: 22px; }
.mcp-keyblock > p { margin: 4px 0 12px; }

/* The key and the control that destroys it, in ONE box.
   The box carries the border the <pre> used to; the <pre> goes bare inside it,
   so the two read as one object rather than a value with a button loose beside
   it. Only the <pre> is a copy target, so the button cannot fire a copy. */
.mcp-key-box {
  display: flex; align-items: center; gap: 10px;
  padding: 5px 6px 5px 0;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  transition: border-color .14s var(--ease), background .14s var(--ease);
}
.mcp-key-box:has(.mcp-code.is-copied) { border-color: var(--brand); background: var(--brand-soft); }
.mcp-key-box .mcp-code { flex: 1; min-width: 0; }
/* Red on hover only. The reader is not here to revoke, so it stays quiet until
   reached for — and it sits next to the value it destroys, which is exactly
   where a mis-click is expensive. */
.mcp-revoke { flex: none; white-space: nowrap; }
.mcp-revoke:hover:not(:disabled) {
  color: var(--red-ink); border-color: var(--red); background: var(--red-soft);
}
@media (max-width: 620px) {
  .mcp-key-box { flex-direction: column; align-items: stretch; padding: 6px; }
}

/* The source «Hammasini nusxalash» reads. Off-screen rather than display:none:
   the clipboard fallback selects a range, and a range in an unrendered element
   selects nothing. */
.mcp-doc-src {
  position: absolute; left: -9999px; top: 0;
  width: 1px; height: 1px; overflow: hidden;
  white-space: pre;
}

.mcp-copy + .mcp-copy { margin-top: 12px; }
.mcp-copy-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin-bottom: 6px;
}
.mcp-copy-lbl { font-size: 12.5px; font-weight: 600; color: var(--ink-2); }
.mcp-copy-lbl small { display: block; margin-top: 2px; font-weight: 400; font-size: 12px; color: var(--ink-3); }
[data-copy-from].is-done { color: var(--brand-deep); border-color: var(--brand); }

/* A code block wraps rather than scrolls: a key is one long unbroken token and
   a manager who cannot SEE all of it does not trust that they copied all of
   it. `anywhere` and not `break-all`, so the JSON's own words stay whole. */
.mcp-code {
  margin: 0;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface-2);
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.65;
  color: var(--ink);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  -webkit-user-select: all; user-select: all;
  /* The block is itself a copy control, so it has to look like one — a value
     you can click with nothing saying so is a value nobody clicks. */
  cursor: pointer;
  transition: border-color .14s var(--ease), background .14s var(--ease);
}
.mcp-code:hover { border-color: var(--line-strong); }
.mcp-code:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
/* The confirmation, since the block cannot change its own text to say
   «copied» — that text is the thing that was just copied. */
.mcp-code.is-copied { border-color: var(--brand); background: var(--brand-soft); }

/* Inside the key box the frame and the fill belong to the BOX. Declared after
   the two rules above so it wins on order rather than on a specificity race:
   without it the copied state paints a lit box inside a lit box. */
.mcp-code.bare,
.mcp-code.bare:hover,
.mcp-code.bare.is-copied {
  border-width: 0; border-color: transparent; background: none;
}

.mcp-steps { display: grid; gap: 20px; margin-top: 14px; }
.mcp-step > b { display: block; font-size: 13.5px; }
.mcp-step > p { margin: 4px 0 9px; font-size: var(--t-small); line-height: 1.55; color: var(--ink-3); }
.mcp-step .note.bare { padding-top: 9px; }
/* The recommended route, tinted so it is read before the three manual ones
   under it — those exist for when this does not apply, not as equals. */
.mcp-step.is-lead {
  padding: 13px 15px;
  border: 1px solid var(--brand-soft-2);
  border-left: 3px solid var(--brand);
  border-radius: var(--radius-sm);
  background: var(--brand-soft);
}
.mcp-step.is-lead > b { color: var(--brand-deep); }
.mcp-step.is-lead > p { margin-bottom: 0; color: var(--ink-2); }
/* Scoped to the paragraph's own inline bolds. A bare `.is-lead b` would carry
   the same specificity as the heading rule above and, being later, would win —
   the exact clash that broke «Kalit faqat shu yerda» across three lines. */
.mcp-step.is-lead > p b { color: var(--ink); }

/* The connect block, which is now the whole feature for a modern client: one
   URL and a sign-in. Tinted so it outranks the fallbacks below it — the static
   key is what you use when this does not apply, not an equal alternative. */
.mcp-connect {
  padding: 15px 16px;
  border: 1px solid var(--brand-soft-2);
  border-left: 3px solid var(--brand);
  border-radius: var(--radius-sm);
  background: var(--brand-soft);
  margin-bottom: 22px;
}
.mcp-connect h3 { color: var(--brand-deep); }
.mcp-connect > p { color: var(--ink-2); }
.mcp-connect > p b { color: var(--ink); }
.mcp-connect .mcp-code { background: var(--surface); border-color: var(--brand); }
/* The static key is the fallback now, so its heading carries the chip saying
   so and the block sits quieter than the one above it. */
.mcp-keyblock h3 .chip { margin-left: 8px; vertical-align: middle; }
/* Consecutive blocks in the MCP pane need air between them: each ends in a
   note and the next starts with an h3, so without this the fallback heading
   reads as another line of the paragraph above it. */
.set-pane-body > .set-block + .set-block { margin-top: 24px; }

/* ------------------------------------------------------ «Sotuv hisoboti»

   The client's own daily sheet, one card per team. Eight columns in a
   half-width card is tight, so the type and the padding step down together —
   but the name keeps the panel's `.who` disc-and-link, because the version
   that drew a bare <button> per row rendered ninety OS chips and they, not the
   numbers, were what the eye landed on.

   Amounts never wrap: a summa broken across two lines stops being one number.
   The table scrolls inside its own `.wrap` on a narrow screen instead. */
/* `.sales-board` is BOTH boards — Analitika → Pul draws one from the call
   window, «Sotuv hisoboti» draws this one from the CRM ledger — so the
   density lives on the shared class and only what is peculiar to the ledger
   board hangs off `.sales-table`. */
.sales-board table { font-size: 13px; }
.sales-board thead th { padding: 8px; }
.sales-board tbody td, .sales-board tfoot td { padding: 9px 8px; }
.sales-board th:first-child, .sales-board td:first-child { padding-left: 16px; }
.sales-board th:last-child, .sales-board td:last-child { padding-right: 16px; }
.sales-board td.num, .sales-board th.num { white-space: nowrap; }
.sales-board small { display: block; font-size: 10px; font-weight: 400; line-height: 1.35; white-space: nowrap; margin-top: 2px; }
.sales-board .who { gap: 8px; }
.sales-board .avatar { width: 24px; height: 24px; font-size: 9.5px; flex: none; }
/* The name gets whatever the numbers do not: eight columns of tabular figures
   are fixed-width by content, so without this the widest amount decides how
   many lines a person's name takes. */
.sales-table th:first-child, .sales-table td:first-child { width: 40%; min-width: 168px; }
.sales-board small[data-tip] { cursor: help; }
.sales-board .linky { text-align: left; }
/* A header carrying `data-tip` is a thing to point at, so it says so. */
.sales-board thead th[data-tip] { cursor: help; }

/* The group's own sum, and quieter than the rows above it: it is a total of
   what is drawn, not a benchmark to compare a seller against. */
.sales-board tfoot td { background: var(--surface-hover); border-top: 1px solid var(--line-2); border-bottom: 0; font-weight: 600; color: var(--ink); }

/* The column key, decoded once above the boards. L / K / Z/Z / UP are the
   client's abbreviations and unreadable to anyone else; the same wording is
   the header tooltip, for when the legend has scrolled off. */
.sales-legend { display: flex; flex-wrap: wrap; gap: 7px; margin: 14px 0 0; padding: 0; }
.sales-legend > div { display: flex; align-items: baseline; gap: 7px; padding: 5px 12px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--pill); }
.sales-legend dt { font: 700 11px/1.4 var(--font-b); letter-spacing: .05em; text-transform: uppercase; color: var(--ink-2); white-space: nowrap; }
.sales-legend dd { margin: 0; font-size: 11.5px; color: var(--ink-3); }

/* The cache saying it is still filling. A banner and not the centred `.empty`
   it used to be: the numbers below it ARE shown, so the line qualifies them
   rather than standing in for them, and a floating grey paragraph in the
   middle of the page read as a failure instead of as progress. */
.sales-status {
  display: flex; align-items: flex-start; gap: 10px; margin: 14px 0 0;
  padding: 11px 14px; border-radius: var(--radius-xs); font-size: 12.5px;
  color: var(--ink-2); background: var(--amber-soft);
  border: 1px solid color-mix(in oklab, var(--amber) 30%, transparent);
}
.sales-status b { font-variant-numeric: tabular-nums; }
.sales-status .dot { width: 8px; height: 8px; margin-top: 5px; flex: none; border-radius: 50%; background: var(--amber); animation: salesPulse 1.6s var(--ease) infinite; }
.sales-status.err { background: var(--red-soft); border-color: color-mix(in oklab, var(--red) 30%, transparent); }
.sales-status.err .dot { background: var(--red); animation: none; }
@keyframes salesPulse { 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) { .sales-status .dot { animation: none; } }

/* Title, then what the figures are as of, then the one control. `space-between`
   would strand the timestamp in the middle of the row. */
.sales-head { justify-content: flex-start; }
.sales-head .hint { margin-right: auto; }
.sales-head .btn { align-self: center; }
@media (max-width: 720px) {
  /* Three things on one line become three narrow columns. The title takes the
     row, the timestamp and the control share the next one. */
  .sales-head { flex-wrap: wrap; }
  .sales-head h2 { width: 100%; }
}

/* The worklist's lede sits inside the card, above its table, so it needs the
   card's own padding rather than `.note`'s tinted strip. */
.sales-work .note.bare-in { background: none; border: 0; padding: 12px 17px 0; }
.sales-work .wrap { margin-top: 12px; }
.sales-work .empty { padding: 28px 20px; }
.sales-work .linky.quiet { font-size: 11.5px; font-weight: 600; color: var(--brand-ink); white-space: nowrap; }

/* Spacing scoped to this page's own siblings — `.seg` is the period control
   everywhere else and must not pick up a margin from here. */
.sales-legend ~ .seg { margin-top: 16px; }
.sales-legend ~ .sales-board-groups, .sales-legend ~ .card, .sales-legend ~ .sales-detail { margin-top: 16px; }

/* --------------------------------------------------- lead drill-down */
/* An openable figure on the employee card: the WHOLE CELL is the door.
   The number used to be a button wearing a dotted underline, which read as a
   tooltip rather than as a link — a manager has no reason to suspect digits
   are clickable, and a two-character hit target is one you have to aim at.
   The cell lifts on hover, shows its chevron, and is a pointer end to end. */
.can-open {
  cursor: pointer; position: relative;
  transition: background .14s var(--ease), box-shadow .14s var(--ease),
              transform .14s var(--ease);
}
.can-open:hover {
  background: var(--surface-hover);
  box-shadow: var(--shadow-sm);
  /* A lift small enough not to move the grid under the pointer, large enough
     to answer «is this a button» before the click. */
  transform: translateY(-1px);
  z-index: 1;
}
.can-open:focus-visible {
  outline: 2px solid var(--brand); outline-offset: -2px; z-index: 2;
}
/* The chevron at rest, so an openable cell is legible in a screenshot and to
   a reader who never hovers. */
.cell-open {
  position: absolute; top: 12px; right: 12px;
  width: 14px; height: 14px; color: var(--ink-4);
  opacity: .5; transition: opacity .14s var(--ease), color .14s var(--ease);
  pointer-events: none;
}
.cell-open svg { width: 100%; height: 100%; display: block; }
.can-open:hover .cell-open { opacity: 1; color: var(--brand); }
/* A TABLE CELL is a door too, and it is not a card.
   `.can-open` lifts and casts a shadow, which on a `<td>` drags one cell out
   of its row and breaks the rules either side of it — a board of ninety rows
   flickering a 1px step under the pointer. The cell keeps the pointer, the
   hover fill and the focus ring, and drops the lift.

   And it is marked AT REST: the figure carries a faint underline, because a
   manager has no reason to suspect a number is clickable and a board whose
   doors only appear on hover has none in a screenshot. */
td.can-open { transform: none; box-shadow: none; }
td.can-open:hover { background: var(--surface-hover); box-shadow: none; }
.sales-table td.can-open { text-decoration: underline dotted var(--ink-4); text-underline-offset: 4px; }
.sales-table td.can-open:hover { text-decoration-color: var(--brand); }
/* Room for the chevron: without it a long label runs under the mark. */
.stats-open dt, .tdy-cell.can-open .tdy-label { padding-right: 18px; }
/* Same room on the dashboard's own tiles: the chevron sits top-right and a
   long label («O‘rtacha suhbat sifati», «Navbatda uzildi») runs under it. */
.qtile.can-open .qlabel, .htile.can-open .tlabel { padding-right: 18px; }
/* Nine figures want a wider cell than the six-figure cards do, and a CAP:
   the 20% floor holds the grid to five columns, so on a wide screen the strip
   breaks 5 and 4 rather than 7 and 2, «Bir dona o'rtacha narxi» stops
   wrapping, and the short row is one cell shy instead of five. */
.stats-open { grid-template-columns: repeat(auto-fit, minmax(max(200px, 20%), 1fr)); }

/* --------------------------------------------------------- lead modal */
/* The rows behind a figure, in a dialog over the page.
   An inline drawer pushed every figure the reader was comparing down the
   screen, and two hundred rows buried the card that opened it. A modal leaves
   the card where it was and has one way out, always in the same place. */
.modal { position: fixed; inset: 0; z-index: 120; display: flex;
  align-items: flex-start; justify-content: center; }
.modal-backdrop {
  position: absolute; inset: 0;
  background: color-mix(in srgb, var(--ink) 42%, transparent);
  backdrop-filter: blur(2px);
}
.modal-panel {
  position: relative; margin: 6vh 0 4vh; width: min(1040px, 94vw);
  max-height: 88vh; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  overflow: hidden; animation: cmdkIn .14s var(--ease);
}
/* Only the BODY scrolls: the title and the count stay on screen through two
   hundred rows, because they are what says which list this is. */
.modal-head {
  display: flex; align-items: flex-start; gap: 16px;
  padding: 18px 20px 14px; border-bottom: 1px solid var(--line); flex: none;
}
.modal-title { min-width: 0; flex: 1; }
.modal-title h3 { margin: 0; font-size: 17px; }
.modal-sub {
  margin: 6px 0 0; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: var(--t-small); color: var(--ink-3);
}
.modal-x {
  flex: none; width: 32px; height: 32px; display: grid; place-items: center;
  border: 1px solid var(--line); border-radius: var(--radius-xs);
  background: var(--surface); color: var(--ink-3); cursor: pointer;
}
.modal-x svg { width: 15px; height: 15px; display: block; }
.modal-x:hover { background: var(--surface-hover); color: var(--ink); }
.modal-x:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.modal-body { overflow-y: auto; padding: 4px 20px 18px; }
.modal-body .wrap { margin: 0 -20px; }
.modal-body .note { margin-top: 14px; }
/* A row goes somewhere, and says so before it is clicked. */
.modal-body tbody tr { cursor: pointer; }
.modal-body tbody tr:hover { background: var(--surface-hover); }
.modal-body tbody tr:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.modal-body .sub {
  display: block; margin-top: 4px; font-size: var(--t-small); color: var(--ink-3);
}
/* The «why» column wraps: a grader's sentence is a sentence, and truncating it
   to one line hides the half that says what to do next. */
.modal-body td.why {
  max-width: 340px; white-space: normal; font-size: var(--t-small); color: var(--ink-2);
}
/* A line DERIVED from the CDR, not written by the grader. Muted and italic so
   a dial count is never read as an analysis of a conversation that never
   happened — the same distinction `basis` carries on the wire. */
.modal-body td.why .why-cdr { color: var(--ink-3); font-style: italic; }
/* ------------------------------------------------ a figure, explained */
/* A dashboard tile's dialog opens on the figure ITSELF, restated large, then
   the counts it came from, then the rule in words, then the calls. The order
   is the reading order of the question: «what is this number», «what is it
   made of», «when is it allowed to appear», «show me». */
.mfig {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  padding: 16px 0 4px;
}
.mfig-value {
  font-family: var(--font-d); font-weight: 600; font-size: 34px;
  line-height: 1; letter-spacing: -.02em; font-variant-numeric: tabular-nums;
}
.mfig-value small { font-family: var(--font-b); font-weight: 500; font-size: 14px; color: var(--ink-3); }
.mfig-sub { font-size: var(--t-small); color: var(--ink-3); }
.mfacts { margin-top: 14px; }
/* The rule behind the figure, in words. A `.note` here would be folded away
   by notes.js into an «i» — the whole reason this dialog was opened. */
.mfig-why {
  margin: 16px 0 0; font-size: var(--t-small); line-height: 1.6; color: var(--ink-2);
  max-width: 74ch;
}
.mfig-h {
  margin: 22px 0 10px; font-size: 12px; text-transform: uppercase;
  letter-spacing: .06em; color: var(--ink-3); font-family: var(--font-b);
  font-weight: 600;
}

/* The page behind a dialog must not scroll under it. */
body.modal-open { overflow: hidden; }

@media (max-width: 700px) {
  .modal-panel { margin: 0; width: 100vw; max-height: 100vh; height: 100vh;
    border: 0; border-radius: 0; }
}

/* ============================ the folded note («i») ==================== */
/* notes.js moves each card's explanatory paragraphs behind one «i» beside its
   heading. The button is a glyph on a 24px target — small enough to sit in a
   heading without becoming a second title, big enough to hit with a thumb —
   and it says it is a thing to point at with the same `help` cursor every
   other label in the panel uses. */
button.noteinfo {
  appearance: none; display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0; margin-left: 7px; vertical-align: middle;
  border: 0; border-radius: 50%; background: none; color: var(--ink-4);
  cursor: help; flex: none; transition: color .12s, background .12s;
}
button.noteinfo svg { width: 15px; height: 15px; display: block; }
button.noteinfo:hover, button.noteinfo[aria-expanded="true"] {
  color: var(--brand); background: var(--surface-hover);
}
button.noteinfo:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
/* A card header is `space-between` with `align-items: baseline`, so dropped in
   beside the title the «i» would float into the middle of the bar and hang off
   the text's baseline rather than its centre. The auto margin gives it the free
   space, which keeps it glued to the heading it belongs to and leaves whatever
   the header carries on the right — a timestamp, a refresh button — where it
   was. */
.card > header > button.noteinfo { margin-right: auto; align-self: center; }

/* Appended to <body> and placed with a transform for the same two reasons the
   chart tooltip is: a box anchored inside a card is clipped by the `.wrap`
   scroller its table lives in, and moving it by left/top re-flows the document.
   Unlike the chart tooltip it KEEPS its pointer events — this is a paragraph
   the reader is meant to be able to travel into, select and copy. */
.noteinfo-pop {
  /* Above the modal (120), because a note inside a dialog is one of the
     places these paragraphs live and a box drawn behind the dialog is a box
     nobody can read. */
  position: fixed; left: 0; top: 0; z-index: 130;
  max-width: min(420px, calc(100vw - 16px)); padding: 12px 14px;
  border: 1px solid var(--line-2); border-radius: var(--radius-sm);
  background: var(--surface); box-shadow: var(--shadow-lg);
  font-family: var(--font-b); font-size: 12.5px; line-height: 1.55; color: var(--ink-2);
}
.noteinfo-pop[hidden] { display: none; }
/* Two notes from one card are two paragraphs, not one run-on wall. */
.noteinfo-pop > p { margin: 0; padding: 0; background: none; border: 0; }
.noteinfo-pop > p + p {
  margin-top: 9px; padding-top: 9px; border-top: 1px solid var(--line);
}
.noteinfo-pop b { color: var(--ink); }
.noteinfo-pop a { color: var(--brand); }

/* ===================================================== responsive shell ==
   Appended last on purpose, like the narrow-viewport rail block above: the
   cascade is the merge strategy in a file several people edit at once.

   Three regimes. Desktop (>1080px) keeps the vertical rail. A tablet
   (761–1080px) keeps the horizontal strip the earlier block builds, but drops
   the labels so eleven items fit the width instead of scrolling off it — the
   icons already carry `title`, and the collapsed desktop rail set the
   precedent that the icon IS the label there. A phone (≤760px) gets the rail
   as an off-canvas drawer behind the topbar's menu button: a horizontal strip
   of eleven items on a 390px screen hides most of the nav behind a sideways
   scroll nobody discovers. 760 and not 768 because 760 is the breakpoint the
   topbar's own search group already collapses at — the shell should change
   shape once per width, not twice three pixels apart. */

@media (max-width: 1080px) and (min-width: 761px) {
  /* Labels off, icons and counts on. Restated under the collapsed-pref
     attribute too, because the strip block above reverts these to visible
     under it and would outrank the bare selector on specificity. */
  .nav button .lbl, .rail-ai .lbl, .rail-ai-go,
  :root[data-rail='collapsed'] .nav button .lbl,
  :root[data-rail='collapsed'] .rail-ai .lbl,
  :root[data-rail='collapsed'] .rail-ai-go { display: none; }
  .nav button, :root[data-rail='collapsed'] .nav button { padding: 0 11px; }
  .rail-ai, :root[data-rail='collapsed'] .rail-ai { padding: 0 12px; }
}

@media (max-width: 760px) {
  /* The strip block above made the shell two rows; on a phone the rail leaves
     the flow entirely, so the pane is the page again. */
  .shell { grid-template-columns: 1fr; }

  .rail {
    position: fixed; top: 0; left: 0; bottom: 0;
    height: 100dvh; width: min(300px, 85vw);
    flex-direction: column; align-items: stretch;
    overflow-x: hidden;
    border-right: 1px solid var(--line);
    transform: translateX(-105%);
    transition: transform .22s var(--ease);
    z-index: 60;
  }
  :root[data-nav='open'] .rail { transform: none; box-shadow: var(--shadow-lg); }
  /* A page cannot scroll behind a modal drawer without the drawer losing the
     scroll gesture that closes nothing and moves the ground instead. */
  :root[data-nav='open'] body { overflow: hidden; }

  /* The vertical anatomy back, undoing the strip treatment: the brand rule
     returns to its bottom edge, the nav to a column that owns the scroll, the
     assistant to a full-width row pinned behind a top rule. */
  .rail .brand, :root[data-rail='collapsed'] .rail .brand {
    height: var(--brandbar); flex: none; padding: 0 20px;
    border-right: 0; border-bottom: 1px solid var(--line);
  }
  .nav { flex: 1 1 auto; flex-direction: column; overflow-y: auto; padding: 16px 14px; }
  .rail-foot { margin-left: 0; border-left: 0; border-top: 1px solid var(--line); padding: 10px 14px 14px; }
  .rail-ai, :root[data-rail='collapsed'] .rail-ai { width: 100%; height: 46px; }

  .rail-backdrop {
    display: block; position: fixed; inset: 0; z-index: 55;
    background: color-mix(in srgb, var(--ink) 42%, transparent);
    opacity: 0; pointer-events: none;
    transition: opacity .22s var(--ease);
  }
  :root[data-nav='open'] .rail-backdrop { opacity: 1; pointer-events: auto; }

  .tb-menu { display: inline-flex; }
  .tb { gap: 12px; }
  /* One line, ellipsed: at 360px «Ogohlantirishlar» wrapped under itself and
     grew the topbar past its 72px. */
  .tb-title h1 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* The group is two icons here and can give up nothing more; without a floor
     a long page title crushed it into overlapping slivers. The title is the
     column that truncates. */
  .tb-searchgroup { flex: none; }
  /* «Boshqa» drops under the segments rather than pushing them off the edge. */
  .period { flex-wrap: wrap; }
  /* Six columns need room to be columns: without a floor the «Mezon» text
     squeezed to one word per line and every row grew ten lines tall. The
     .wrap around it already owns the sideways scroll. */
  .criteria-table { min-width: 640px; }
  /* iOS Safari zooms the page onto any focused control whose font is under
     16px, and does not zoom back out — the login card arrived cropped and
     off-centre after the first tap. 16px on the control, not
     maximum-scale=1 on the viewport: the meta kills pinch-zoom for Android
     readers, this keeps it. !important because per-component sizes
     (.alert-type select and kin) outrank an element selector and the rule
     must win everywhere or the zoom is only mostly gone. */
  input, select, textarea { font-size: 16px !important; }
  main { padding: 18px 14px 56px; }

  /* The desktop paddings cost the login card 120 of a phone's 390 pixels and
     left 270 for the form — narrower than the Google iframe wants to be.
     Tighter frame, same card. */
  .gate { padding: 14px; }
  .gate-card { padding: 28px 20px; }

  /* One element leaking past the edge hands the WHOLE page a sideways pan on
     iOS, and the login form was the first to be read off-centre because of
     one. Every wide block here already scrolls inside its own .wrap; a page
     that still leaks is a bug, and this keeps a bug from becoming a broken
     phone while it waits to be found. */
  body { overflow-x: hidden; }
}

/* A big monitor gets more ground, not a cap — the no-max-width decision at
   `main` stands; the content is tables, tiles and charts, and they use the
   room. All the shell owes a 27-inch screen is margins that do not read as
   a laptop's. */
@media (min-width: 1680px) {
  main { padding: 32px 44px 72px; }
  .tb { padding: 0 44px; }
}

@media (prefers-reduced-motion: reduce) {
  .rail, .rail-backdrop { transition: none; }
}

/* ================================================================ reja */
/* «Rejalar» and «Mening kunim». The bar is the kit's `.bar`; the tones are the
   chip tones, so «bajarildi» is the same green everywhere on the page. A
   fifth tone, `is-track`, is the brand-adjacent blue for «yo‘lda» — in
   progress is neither a warning nor a result. */
.reja-bar { display: flex; align-items: center; gap: 8px; min-width: 120px; }
.reja-bar .bar { flex: 1; }
.reja-pct { font-variant-numeric: tabular-nums; font-size: 12px; min-width: 3em; }
.bar > i.is-good,  .reja-pct.is-good  { background: var(--green); color: var(--green); }
.bar > i.is-warn,  .reja-pct.is-warn  { background: var(--amber); color: var(--amber); }
.bar > i.is-bad,   .reja-pct.is-bad   { background: var(--red);   color: var(--red-ink); }
.bar > i.is-mute,  .reja-pct.is-mute  { background: var(--ink-3); color: var(--ink-3); }
.bar > i.is-track, .reja-pct.is-track { background: var(--blue);  color: var(--blue); }
.reja-pct { background: none !important; }
/* The two tables are cards like every other table in the product. `.card`
   already paints `--surface`, the border and the radius; the padding is
   dropped so the rows run edge to edge under the header. The board is a grid
   with its own gap, so the old bottom margin here would now double it. */
.reja-tablecard { padding: 0; }

/* --- the board ------------------------------------------------------- */
.reja-board { display: grid; gap: 16px; padding-bottom: 96px; }
/* A grid item does not shrink below its content unless told to; without
   this the table's `.wrap` never scrolls and a phone gets a wide page. */
.reja-board > * { min-width: 0; }

/* The head: one big number, its bar, and the standings counted beside it. */
.reja-sum { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 28px; padding: 20px 24px; border: 1px solid var(--line); border-radius: 16px; background: var(--surface); box-shadow: var(--shadow-xs); position: relative; overflow: hidden; }
.reja-sum::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 4px; background: var(--brand); }
.reja-sum.is-off::before, .reja-sum.is-empty::before { background: var(--line-strong); }
.reja-sum-main { flex: 1 1 320px; min-width: 0; }
.reja-sum-num { font-family: var(--font-d); font-weight: 600; font-size: clamp(36px, 5vw, 52px); line-height: 1; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.reja-sum-of { font-size: 0.5em; color: var(--ink-3); font-weight: 500; }
.reja-sum-lbl { margin-top: 6px; color: var(--ink-2); font-size: 13px; }
.reja-sum-bar { height: 8px; margin-top: 14px; max-width: 520px; }
.reja-sum .note.bare { margin: 8px 0 0; }
.reja-sum-counts { display: flex; flex-wrap: wrap; gap: 6px 14px; }
.reja-count { display: inline-flex; align-items: baseline; gap: 6px; font-size: 13px; color: var(--ink-2); }
.reja-count b { font-family: var(--font-d); font-size: 20px; font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1; }
.reja-count.is-good b { color: var(--green); }
.reja-count.is-track b { color: var(--blue); }
.reja-count.is-bad b { color: var(--red-ink); }
.reja-count.is-mute b { color: var(--ink-3); }
.reja-sum-start { margin-left: auto; }
@media (max-width: 640px) { .reja-sum-start { margin-left: 0; width: 100%; } }

/* The assistant strip: an input that reads as one, quick picks under it,
   the reply as a bubble. Brand-tinted so it is visibly the assistant's. */
.reja-ask { padding: 12px 14px; border: 1px solid var(--brand-line); border-radius: 14px; background: linear-gradient(180deg, var(--brand-soft) 0%, var(--surface) 100%); }
.reja-ask-form { display: flex; align-items: center; gap: 10px; }
.reja-ask-ic { display: grid; place-items: center; width: 30px; height: 30px; border-radius: 9px; background: var(--brand); color: var(--on-brand); flex: none; }
.reja-ask-ic svg { width: 16px; height: 16px; }
.reja-ask-input { flex: 1; min-width: 0; height: 40px; padding: 0 14px; border: 1px solid var(--line-2); border-radius: 10px; background: var(--surface); font: inherit; font-size: 14px; color: var(--ink); }
.reja-ask-input::placeholder { color: var(--ink-3); }
.reja-ask-input:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft-2); }
.reja-ask-form .btn { flex: none; }
.reja-quicks { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 10px; }
.reja-quicks-lbl { font-size: 12px; color: var(--ink-3); margin-right: 4px; }
.reja-quick { display: inline-flex; align-items: center; gap: 6px; padding: 5px 11px; border: 1px solid var(--line-2); border-radius: 999px; background: var(--surface); color: var(--ink-2); font: inherit; font-size: 12.5px; cursor: pointer; }
.reja-quick b { color: var(--ink); font-variant-numeric: tabular-nums; }
.reja-quick:hover { border-color: var(--brand); color: var(--brand-ink); }
.reja-quick:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.reja-ask-reply { display: flex; align-items: flex-start; gap: 10px; margin-top: 12px; }
.reja-ask-bot { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 8px; background: var(--surface); border: 1px solid var(--brand-line); color: var(--brand-ink); font-size: 13px; flex: none; }
.reja-ask-bubble { flex: 1; min-width: 0; padding: 10px 14px; border: 1px solid var(--line); border-radius: 12px; border-top-left-radius: 4px; background: var(--surface); font-size: 13.5px; line-height: 1.5; }
.reja-ask-bubble .rt-p { margin: 0 0 6px; }
.reja-ask-bubble .rt-p:last-child { margin-bottom: 0; }
.reja-ask-bubble .rt-list { margin: 4px 0 6px 18px; }
.reja-ask-applied { margin: 8px 0 0; padding-top: 8px; border-top: 1px dashed var(--line-2); color: var(--brand-ink); font-weight: 600; }
.reja-ask-applied .dim { font-weight: 400; }
.reja-ask-reply.is-failed .reja-ask-bubble { border-color: var(--red-soft); background: var(--red-soft); color: var(--red-ink); }
.reja-ask-reply.is-busy .ydm-typing { padding: 6px 4px; }
.reja-ask-x { all: unset; cursor: pointer; width: 26px; height: 26px; display: grid; place-items: center; border-radius: 8px; color: var(--ink-3); font-size: 18px; line-height: 1; }
.reja-ask-x:hover { background: var(--surface-hover); color: var(--ink); }
.reja-ask-x:focus-visible { outline: 2px solid var(--brand); }

/* Rows. Standing colours the left edge; actions appear on hover, and stay
   visible on a touch screen where there is no hover. */
.reja-table .reja-cb { width: 28px; padding-right: 0; }
.reja-table .reja-cb input { width: 16px; height: 16px; accent-color: var(--brand); cursor: pointer; }
.reja-table th.num, .reja-table td.num { text-align: right; }
/* The standing colour is the first cell's edge only: a transparent edge on
   EVERY cell showed the table through it on hover, as gaps between cells. */
.reja-row td:first-child { border-left: 3px solid transparent; }
.reja-row td:first-child { padding-left: 10px; }
.reja-row.is-behind td:first-child { border-left-color: var(--red); }
.reja-row.is-onTrack td:first-child { border-left-color: var(--blue); }
.reja-row.is-met td:first-child { border-left-color: var(--green); }
.reja-row.is-none td, .reja-row.is-notToday td { color: var(--ink-3); }
.reja-row.is-none .who b, .reja-row.is-notToday .who b { color: var(--ink-2); }
.reja-section td { padding: 18px 12px 6px; border-bottom: 0; background: transparent; }
.reja-section:first-child td { padding-top: 6px; }
.reja-section-in { display: flex; align-items: center; gap: 8px; font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-2); }
.reja-section-in b { font-weight: 600; color: var(--ink); }
.reja-section-in input { width: 15px; height: 15px; margin: 0 2px 0 0; accent-color: var(--brand); cursor: pointer; }
.reja-section-n { padding: 1px 7px; border-radius: 999px; background: var(--surface-hover); color: var(--ink-2); font-size: 11px; letter-spacing: 0; }
.reja-section-sum { margin-left: auto; text-transform: none; letter-spacing: 0; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.reja-section-sum b { color: var(--ink); }
.reja-row:hover td { background: var(--surface-hover); }
.reja-who { display: inline-grid; line-height: 1.25; min-width: 0; }
.reja-who .mono { font-size: 11.5px; }
.reja-plan { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; border-radius: 999px; border: 1px solid var(--line-2); background: var(--surface); color: var(--ink-2); font: inherit; font-size: 12.5px; white-space: nowrap; }
.reja-plan b { color: var(--ink); font-variant-numeric: tabular-nums; }
.reja-plan-unit { color: var(--ink-3); }
.reja-plan.is-skip { border-style: dashed; }
.reja-plan-skip { color: var(--ink-3); font-style: italic; }
.reja-plan.is-none { border-color: transparent; background: none; color: var(--ink-3); padding-left: 0; }
button.reja-plan { cursor: pointer; }
button.reja-plan:hover { border-color: var(--brand); color: var(--brand-ink); }
button.reja-plan:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
/* Auto layout handed the name column every spare pixel, which left a hand's
   width of nothing between «Bugun» and «Qoldi». These are hints, not a fixed
   layout: the Guruh and the actions columns are both conditional, so the
   remaining space still has somewhere to go. */
.reja-who-td { width: 30%; }
.reja-plan-td { width: 140px; }
.reja-table td.num { width: 72px; }
.reja-prog-td { min-width: 190px; width: 22%; }
.reja-bar.is-quiet { color: var(--ink-3); }
.reja-bar-nums { font-variant-numeric: tabular-nums; white-space: nowrap; }
.reja-bar-nums + .bar { margin-top: 5px; }
.reja-prog-td .reja-bar { display: block; }
.reja-act { text-align: right; white-space: nowrap; width: 1%; }
/* Quiet until the row is under the cursor, never hidden: a control the ROP
   cannot see is one he does not know exists. */
.reja-act .btn { opacity: .6; transition: opacity .12s; }
.reja-row:hover .reja-act .btn, .reja-row:focus-within .reja-act .btn { opacity: 1; }
.reja-confirm { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--ink-2); }
.reja-confirm .btn { opacity: 1; }
.reja-confirm-yes { background: var(--red); color: #fff; border-color: var(--red); }
.reja-confirm-yes:hover { background: var(--red-ink); }

/* The selection toolbar: a raised bar pinned to the bottom while the table
   scrolls, in the DOM from the first paint so a tick can show it. */
.reja-tb { position: sticky; bottom: 14px; z-index: 6; margin-top: 4px; padding: 12px 16px; border: 1px solid var(--line-2); border-radius: 14px; background: var(--surface); box-shadow: var(--shadow-lg); }
.reja-tb[hidden] { display: none; }
.reja-tb-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; }
.reja-tb-sel { display: inline-flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.reja-tb-count { font-weight: 600; }
.reja-tb-count b { display: inline-block; min-width: 1.4em; padding: 1px 7px; border-radius: 999px; background: var(--brand); color: var(--on-brand); text-align: center; font-variant-numeric: tabular-nums; }
.reja-tb-all { display: inline-flex; align-items: center; gap: 6px; color: var(--ink-2); font-size: 13px; }
.reja-tb-all input { accent-color: var(--brand); }
.reja-tb-tag[hidden] { display: none; }
.reja-tb-num { display: inline-flex; align-items: center; gap: 8px; }
.reja-tb-num input { width: 5.5em; height: 36px; text-align: center; font-weight: 600; font-size: 16px; border-radius: 8px; }
.reja-tb-days { display: inline-flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.reja-daychip { all: unset; box-sizing: border-box; min-width: 34px; height: 30px; padding: 0 8px; display: inline-grid; place-items: center; border: 1px solid var(--line-2); border-radius: 8px; background: var(--surface); color: var(--ink-3); font-size: 12.5px; font-weight: 600; cursor: pointer; }
.reja-daychip:hover { border-color: var(--brand); color: var(--brand-ink); }
.reja-daychip.is-on { background: var(--brand); border-color: var(--brand); color: var(--on-brand); }
.reja-daychip:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.reja-presets { display: inline-flex; gap: 2px; margin-left: 6px; }
.reja-preset { all: unset; cursor: pointer; padding: 4px 8px; border-radius: 6px; font-size: 12px; color: var(--ink-3); text-decoration: underline dotted; text-underline-offset: 3px; }
.reja-preset:hover { color: var(--brand-ink); background: var(--brand-soft); }
.reja-preset:focus-visible { outline: 2px solid var(--brand); }
.reja-tb-act { display: inline-flex; gap: 8px; margin-left: auto; }
.reja-tb-help { margin: 10px 0 0; font-size: 12px; color: var(--ink-3); }
.reja-tb .set-err { margin: 8px 0 0; }
@media (max-width: 720px) {
  .reja-tb { bottom: 8px; padding: 10px 12px; }
  .reja-tb-act { margin-left: 0; width: 100%; }
  .reja-tb-act .btn { flex: 1; }
}


.reja-mine { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(280px, 1fr); gap: 18px; align-items: start; }
@media (max-width: 900px) { .reja-mine { grid-template-columns: 1fr; } }
.reja-hero { padding: 28px 28px 24px; border-radius: 16px; border: 1px solid var(--line); background: var(--surface); position: relative; overflow: hidden; }
.reja-hero::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 4px; background: var(--ink-3); }
.reja-hero.is-good::before { background: var(--green); }
.reja-hero.is-warn::before { background: var(--amber); }
.reja-hero.is-bad::before  { background: var(--red); }
.reja-hero-num { font-family: var(--font-display, inherit); font-weight: 600; font-size: clamp(44px, 7vw, 72px); line-height: 1; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.reja-hero-of { font-size: 0.45em; color: var(--ink-3); font-weight: 500; }
.reja-hero-lbl { margin-top: 8px; color: var(--ink-2); }
.reja-hero-bar { height: 8px; margin: 18px 0 10px; }
.reja-hero-sub { color: var(--ink-2); }
.reja-other-orders { margin: 4px 0 6px; padding-left: 18px; font-size: 14px; color: var(--ink-2); }
.reja-other-orders li { margin: 2px 0; }
.reja-side { display: grid; gap: 14px; }
.reja-card { padding: 16px 18px; }
.reja-card-lbl { font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-3); margin-bottom: 6px; }
.reja-card-val { font-size: 22px; font-weight: 600; }
.reja-strip { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; margin-top: 8px; }
.reja-cell { border-radius: 8px; padding: 8px 4px; text-align: center; background: var(--surface-hover); border-top: 3px solid var(--ink-3); }
.reja-cell.is-good { border-top-color: var(--green); background: var(--green-soft); }
.reja-cell.is-warn { border-top-color: var(--amber); background: var(--amber-soft); }
.reja-cell.is-bad  { border-top-color: var(--red);   background: var(--red-soft); }
.reja-cell-day { display: block; font-size: 11px; color: var(--ink-3); }
.reja-cell-val { display: block; font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; margin-top: 2px; }

/* The assistant's proposal card. */
.reja-proposal { margin: 8px 0; padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px; background: var(--surface); }
.reja-proposal-head { font-weight: 600; margin-bottom: 6px; }
.reja-proposal ul { margin: 6px 0 10px 18px; color: var(--ink-2); }
.reja-proposal .dim { color: var(--ink-3); }

/* «Mening kunim», second pass: a home page, not a placeholder. */
.reja-main { display: grid; gap: 14px; min-width: 0; }
.reja-hero.is-plain::before { background: var(--brand); }
/* FOUR tiles, and the explaining sentence under each figure is what decides
   the shape. Six columns with the money tile spanning two left each count
   about 100px of text, so «bugun qilingan barcha urinishlar» set one word per
   line and the row read as a broken page (19 Sep 2026). Two columns is what
   four tiles want: every label and every sentence fits on one line, and there
   is no empty cell — which a money tile spanning two of three columns would
   leave now that «Gaplashildi» is gone. */
.reja-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
/* Money is the one that pays: brand ink, and first in the reading order. */
.reja-stat.is-money { background: var(--green-soft); border-color: transparent; }
/* The money tile's sub («siz javob bergan 69 tadan · maqsad 30%») takes its
   own line rather than running on from the label as one sentence. */
.reja-stat.is-money .reja-stat-lbl > span:first-child { display: block; }
.reja-stat.is-money .reja-stat-lbl .dim { display: block; margin-top: 3px; }
.reja-stat.is-money .reja-stat-val { color: var(--green); }
.reja-stat.is-money .reja-stat-unit { color: var(--green); opacity: .8; }
@media (max-width: 460px) { .reja-stats { grid-template-columns: minmax(0, 1fr); } }
.reja-stat { padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px; background: var(--surface); }
.reja-stat-val { font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1.1; }
.reja-stat-unit { font-size: 13px; font-weight: 500; color: var(--ink-3); }
/* `flex-start`, not `center`: a label that wraps to two lines would otherwise
   drag the «i» mark down to the middle of them, away from the word it marks. */
.reja-stat-lbl { margin-top: 4px; font-size: 12px; color: var(--ink-2); display: flex; align-items: flex-start; justify-content: space-between; gap: 6px; }
/* The sentence under every figure, and the mark that says the rows are a tap
   away. Both are the same fix: the tile ALREADY opened a dialog explaining
   its population, and the only affordance was a hover lift — nothing on a
   phone, nothing at rest — so five bare numbers were all the reader ever got.
   The sentence answers «what is this» without a tap; the mark says a tap
   gives the calls behind it. */
.reja-stat-what { margin: 6px 0 0; font-size: 11px; line-height: 1.35; color: var(--ink-3); }
.reja-hero .reja-stat-what { font-size: 12px; margin-top: 8px; }
.reja-stat-i { flex: none; width: 14px; height: 14px; border-radius: 50%; border: 1px solid var(--line-2);
  color: var(--ink-3); font-size: 9px; font-weight: 700; line-height: 12px; text-align: center; font-style: italic; }
.reja-stat[data-reja-tile]:hover .reja-stat-i { border-color: var(--brand); color: var(--brand); }
.reja-stat.is-money[data-reja-tile]:hover .reja-stat-i { border-color: var(--green); color: var(--green); }

/* Every figure on «Mening kunim» opens the rows it was counted from, so every
   figure has to LOOK like it does. A quiet lift on hover and a real focus ring
   — the tile is a `role="button"`, not a <button>, because a real one would
   bring the browser's own type, alignment and padding to a three-line block
   and fight every rule above. */
.reja-stat[data-reja-tile],
.reja-hero[data-reja-tile] { cursor: pointer; transition: border-color .14s var(--ease), box-shadow .14s var(--ease); }
.reja-stat[data-reja-tile]:hover { border-color: var(--brand); box-shadow: var(--shadow-xs); }
.reja-stat.is-money[data-reja-tile]:hover { border-color: var(--green); }
.reja-hero[data-reja-tile]:hover { box-shadow: var(--shadow-sm); }
.reja-stat[data-reja-tile]:focus-visible,
.reja-hero[data-reja-tile]:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* The one dialog with no rows behind it: two facts, side by side, over the
   sentence that says where they came from. */
.reja-facts { display: flex; flex-wrap: wrap; gap: 10px 32px; margin: 0 0 4px; }
.reja-facts dt { font-size: var(--t-small); color: var(--ink-3); }
.reja-facts dd { margin: 3px 0 0; font-family: var(--font-d); font-size: 24px; font-weight: 600; font-variant-numeric: tabular-nums; }
.reja-facts dd .dim { font-family: var(--font-b); font-size: 14px; font-weight: 500; }
.reja-calls td, .reja-calls th { white-space: nowrap; }
.reja-calls tbody tr { cursor: pointer; }
.reja-calls tbody tr:hover td { background: var(--surface-hover); }
/* «Mening kunim» lead dialogs (6 Oct 2026): kval by funnel, worked leads. */
.reja-funnels { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 8px; margin-bottom: 14px; }
.reja-funnel { border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; background: var(--surface); }
.reja-funnel-n { font-family: 'Space Grotesk', sans-serif; font-size: 22px; font-weight: 600; line-height: 1.1; }
.reja-funnel-name { font-size: 12px; color: var(--ink-2); margin-top: 2px; }
.reja-dirseg { margin-bottom: 12px; }
.reja-dirseg b { font-weight: 600; margin-left: 4px; }
.reja-fcell { display: flex; flex-direction: column; line-height: 1.25; white-space: normal; min-width: 120px; }
.reja-fcell .dim { font-size: 11px; }
.reja-hop { display: flex; align-items: center; gap: 8px; }
.reja-hop-arrow { color: var(--ink-2); }
.reja-worked td.num, .reja-worked th.num { text-align: right; }
.reja-calls tr[hidden] { display: none; }
.reja-sales tr.is-katta td { background: var(--green-soft); }
.reja-sales tr.is-katta:hover td { background: var(--green-soft); filter: brightness(0.97); }
.reja-chek-fact.is-katta dd { color: var(--green); }
.reja-strip { align-items: end; }
/* A bar in the week carries the day's whole result on hover, so it says it is
   something to point at. */
.reja-cell[data-tip] { cursor: help; }
.reja-cell { display: grid; gap: 4px; justify-items: center; padding: 6px 2px 4px; border-top: 0; background: none; border-radius: 0; }
.reja-cell-bar { display: block; width: 100%; max-width: 26px; height: 44px; display: flex; align-items: flex-end; }
.reja-cell-bar i { display: block; width: 100%; border-radius: 4px 4px 2px 2px; background: var(--ink-3); opacity: .55; }
.reja-cell.is-plain .reja-cell-bar i { background: var(--brand); opacity: .75; }
.reja-cell.is-good .reja-cell-bar i { background: var(--green); opacity: 1; }
.reja-cell.is-warn .reja-cell-bar i { background: var(--amber); opacity: 1; }
.reja-cell.is-bad  .reja-cell-bar i { background: var(--red); opacity: .9; }
.reja-cell.is-mute .reja-cell-bar i { background: var(--ink-3); opacity: .35; }
.reja-cell-val { font-size: 12px; font-weight: 600; margin: 0; }
.reja-cell-day { font-size: 11px; color: var(--ink-3); }
.reja-side .btn { width: 100%; }

/* «Rejani yop, muzlatgichni och» — the fridge. Locked prizes are drawn in
   ink at low opacity behind a lock; an open one is in colour and, the first
   time this browser sees it open today, pops. Compositor-only motion. */
/* «Sotuvga o'tkazish» — the qabul seat's own goal card, where a seller's page
   carries the fridge. The bar is the ordinary `.bar` with one addition: the
   client's floor drawn ON it, because a percentage with no line beside it does
   not say whether the operator is close. */
.reja-handoff-num { font-family: var(--font-d); font-weight: 600; font-size: 30px;
  line-height: 1.1; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  font-variant-numeric: tabular-nums; margin: 2px 0 10px; }
.reja-handoff-bar { position: relative; overflow: visible; }
.reja-handoff-goal { position: absolute; top: -3px; bottom: -3px; width: 2px;
  background: var(--ink-2); border-radius: 1px; transform: translateX(-1px); }
.reja-handoff .btn { margin-top: 12px; }

.reja-fridge { position: relative; overflow: hidden; }
.reja-fridge-lead { margin: 2px 0 12px; color: var(--ink-2); }
.reja-shelf { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 10px; padding-top: 6px; border-top: 3px solid var(--line-2); }
.reja-prize { display: grid; gap: 4px; justify-items: center; text-align: center; padding: 8px 4px 6px; border-radius: 12px; }
.reja-prize-art { position: relative; width: 64px; height: 64px; display: grid; place-items: center; border-radius: 12px; background: var(--surface-hover); overflow: hidden; }
.reja-prize-art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.reja-prize-glyph { width: 40px; height: 40px; color: var(--ink-2); display: grid; place-items: center; }
.reja-prize-glyph svg { width: 100%; height: 100%; }
.reja-prize-art img + .reja-prize-glyph { display: none; }
.reja-prize-lock { position: absolute; right: 4px; bottom: 4px; font-size: 13px; line-height: 1; filter: drop-shadow(0 1px 1px rgba(0,0,0,.25)); }
.reja-prize:not(.is-open) .reja-prize-art { filter: grayscale(1); opacity: .55; }
.reja-prize:not(.is-open) .reja-prize-lbl { color: var(--ink-3); }
.reja-prize.is-open .reja-prize-art { box-shadow: 0 0 0 2px var(--green), 0 6px 18px -8px var(--green); }
.reja-prize-lbl { font-size: 12px; font-weight: 600; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.reja-prize-thr { font-size: 11px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.reja-prize.is-fresh .reja-prize-art { animation: rejaPop 700ms cubic-bezier(.2,1.4,.4,1) both; }
@keyframes rejaPop { 0% { transform: scale(.6) rotate(-8deg); opacity: 0; } 60% { transform: scale(1.15) rotate(3deg); opacity: 1; } 100% { transform: none; } }
.reja-confetti { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
.reja-confetti i { position: absolute; top: -8px; width: 7px; height: 11px; border-radius: 2px; opacity: 0; animation: rejaFall 1.9s ease-in both; }
@keyframes rejaFall { 0% { transform: translate3d(0,0,0) rotate(0); opacity: 1; } 100% { transform: translate3d(var(--dx), 420px, 0) rotate(var(--rot)); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .reja-prize.is-fresh .reja-prize-art { animation: none; } .reja-confetti { display: none; } }

/* The call-list kind tabs: «Hammasi | Telefon qo'ng'iroqlari | Zoom
   uchrashuvlari», drawn only for a tenant whose panel holds more than one kind
   of conversation. It is the kit's `.seg` control with room above the filter
   bar — no new visual language, because it is the same act as picking a
   period. */
.kind-tabs { margin: 0 0 10px; }

/* A page head that carries TWO controls — the call-kind strip beside the
   period — keeps them on one row and lets them wrap together on a narrow
   screen rather than pushing the title around. */
.head-controls { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.head-controls .kind-tabs { margin: 0; }

/* A row of labelled filter controls (the baza «Vazifalar» date filter). It
   was the «O'rindoshlik» form on /operators until that card was taken off
   the page on 29 Sep 2026; the name stayed with the shape.
   One row of labelled controls, wrapping to a column on a phone. The card
   around it is the page's ordinary `.card`; only the form needs a shape,
   because a `<select>` and two dates stacked full-width read as a settings
   page rather than as one sentence a manager is completing. */
.cover-form { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; padding: 16px 20px 4px; }
.cover-form label { display: flex; flex-direction: column; gap: 4px; font-size: 11px; font-weight: 600; color: var(--ink-3); text-transform: uppercase; letter-spacing: .04em; }
.cover-form select, .cover-form input[type="date"] { font: inherit; font-size: 13px; color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 7px 9px; min-width: 150px; }
.cover-form .btn { margin-bottom: 1px; }
.cover-form + .plan-note { padding: 0 20px; }
@media (max-width: 640px) { .cover-form { flex-direction: column; align-items: stretch; } .cover-form select, .cover-form input[type="date"] { width: 100%; } }

/* «Vazifalar» on a baza card: the five amoCRM columns are the filter, so the
   picked one has to read as picked. */
.baza-tasks .stats > div.on { box-shadow: inset 0 -2px 0 var(--brand); }
.baza-tasks .bad-ink { color: var(--red); }
/* Always five — they ARE amoCRM's five columns. The shared `.stats-open`
   floor (20% a cell) plus the borders rounded past the row, so the strip
   broke 4 + 1 and left a blank block under «Bugun». */
.baza-tasks .stats-open { grid-template-columns: repeat(5, minmax(0, 1fr)); }
@media (max-width: 760px) { .baza-tasks .stats-open { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); } }

/* ------------------------------------------------ qabul funnel cards
   «Lidlar bosqichi» as cards (client's sketch, 6 Oct 2026): the group top
   right, one card per funnel with two figures — leads worked and kval. */
.qf-section > header { align-items: center; }
.qf-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; justify-content: flex-end; }
.qf-group { font-size: var(--t-small); color: var(--ink-2); }
.qf-group-lbl { text-transform: uppercase; letter-spacing: .07em; font-size: var(--t-eyebrow); color: var(--ink-3); }
.qf-group b { color: var(--ink); font-weight: 600; }
.qf-pick select { font: inherit; font-size: var(--t-small); color: var(--ink); background: var(--surface); border: 1px solid var(--line); border-radius: 9px; padding: 6px 30px 6px 10px; max-width: 260px; cursor: pointer; }
.qf-pick select:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.qf-body { padding: 14px 17px 4px; }
.qf-summary { display: flex; gap: 18px; align-items: baseline; flex-wrap: wrap; margin-bottom: 12px; font-size: var(--t-small); color: var(--ink-2); }
.qf-summary b { font-family: 'Space Grotesk', sans-serif; font-size: 18px; color: var(--ink); font-weight: 600; margin-right: 2px; }
.qf-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px; }
.qf-grid.is-extra { margin-top: 10px; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
.qf-grid.is-stages { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }
.qf-card { position: relative; border: 1px solid var(--line); border-radius: var(--radius-xs); background: var(--surface); padding: 12px 14px; display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.qf-card.is-own { border-color: var(--brand-line); background: var(--brand-soft); }
.qf-card.is-small { padding: 10px 12px; gap: 8px; }
.qf-card.can-open { cursor: pointer; transition: border-color .12s, box-shadow .12s; }
.qf-card.can-open:hover { border-color: var(--brand-line); box-shadow: 0 1px 6px rgba(0,0,0,.05); }
.qf-card.can-open:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.qf-card-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; }
.qf-card-name { font-weight: 600; font-size: 13px; line-height: 1.3; color: var(--ink); overflow-wrap: anywhere; }
.qf-figs { display: flex; gap: 20px; }
.qf-fig { display: flex; flex-direction: column; }
.qf-num { font-family: 'Space Grotesk', sans-serif; font-size: 26px; font-weight: 600; line-height: 1.05; color: var(--ink); font-variant-numeric: tabular-nums; }
.qf-card.is-small .qf-num { font-size: 20px; }
.qf-fig.is-kval .qf-num { color: var(--brand-ink); }
.qf-fig.is-zero .qf-num { color: var(--ink-3); }
.qf-lbl { font-size: 11px; color: var(--ink-3); text-transform: uppercase; letter-spacing: .06em; margin-top: 2px; }
.qf-foot { font-size: 12px; color: var(--ink-2); display: flex; align-items: center; gap: 4px; }
.qf-foot .cell-open { margin-left: auto; position: static; }
.qf-sub { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; font-size: var(--t-small); }
@media (max-width: 560px) { .qf-head { justify-content: flex-start; } .qf-grid { grid-template-columns: minmax(0, 1fr); } }

/* Numbered pages (client, 6 Oct 2026: «not infinity scroll, with page number»). */
.pager-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 17px 14px; flex-wrap: wrap; font-size: var(--t-small); }
.pager { display: inline-flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.pager-n { min-width: 32px; height: 32px; padding: 0 8px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); color: var(--ink); font: inherit; font-variant-numeric: tabular-nums; cursor: pointer; }
.pager-n:hover:not(:disabled) { border-color: var(--brand-line); }
.pager-n.on { background: var(--brand); border-color: var(--brand); color: var(--on-brand); font-weight: 600; }
.pager-n:disabled { opacity: .4; cursor: default; }
.pager-n:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.pager-gap { color: var(--ink-3); padding: 0 2px; }
.pager-row.is-loading .pager { opacity: .55; pointer-events: none; }
.pager-row:empty { display: none; }

/* «Voronkalar bo'yicha», redesigned 6 Oct 2026: total and share, one stacked
   bar for the stage split, then stage rows with a dot, the count and a %. */
.sf-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px; }
.sf-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 14px 16px 12px; display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.sf-card > header { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
.sf-card > header h3 { margin: 0; font-size: 13.5px; font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; }
.sf-total { text-align: right; display: flex; flex-direction: column; align-items: flex-end; white-space: nowrap; }
.sf-total b { font-family: 'Space Grotesk', sans-serif; font-size: 22px; font-weight: 600; line-height: 1.05; font-variant-numeric: tabular-nums; }
.sf-total > span { font-size: 11.5px; color: var(--ink-3); }
.sf-bar { display: flex; gap: 2px; height: 10px; border-radius: 5px; overflow: hidden; background: var(--line); }
.sf-bar i { display: block; min-width: 3px; }
.sf-card ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.sf-card li { display: grid; grid-template-columns: 10px minmax(0, 1fr) auto 46px; align-items: center; column-gap: 8px; font-size: 12.5px; }
.sf-dot { width: 8px; height: 8px; border-radius: 50%; }
.sf-name { color: var(--ink-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sf-n { font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }
.sf-pct { color: var(--ink-3); font-variant-numeric: tabular-nums; text-align: right; font-size: 11.5px; }
/* The roster's «Lidlar» hover card: a baza seat's funnel cards over the
   table. Fixed to the viewport, placed by JS beside the figure. */
.lead-hover { cursor: help; text-decoration: underline dotted var(--ink-4); text-underline-offset: 4px; }
.lead-hover:hover, .lead-hover:focus-visible { color: var(--brand); text-decoration-color: var(--brand); outline: none; }
.lead-pop { position: fixed; z-index: 130; width: min(960px, calc(100vw - 24px)); max-height: calc(100vh - 24px); overflow: auto;
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius-sm); box-shadow: var(--shadow-lg, 0 12px 32px rgba(0,0,0,.18));
  padding: 14px; display: none; pointer-events: none; }
.lead-pop.on { display: block; }
.lead-pop-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; margin-bottom: 10px; }
.lead-pop-head b { font-family: 'Space Grotesk', sans-serif; font-size: 15px; font-weight: 600; }
.wb-grid { padding: 14px 17px 0; align-items: start; grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); }
.wb-card ul { gap: 0; }
.wb-card li { grid-template-columns: 10px minmax(0, 1fr) 48px 84px 70px; padding: 6px 0; border-top: 1px solid var(--line); }
.wb-card li > b, .wb-card li > span:nth-child(n+4) { text-align: right; font-variant-numeric: tabular-nums; }
.wb-card li > span:nth-child(n+4) { color: var(--ink-3); }
.wb-card li .can-open { border-radius: 4px; padding: 1px 4px; margin: -1px -4px; transform: none; box-shadow: none; }
.wb-card li .can-open:hover { background: var(--brand-soft, var(--surface-hover)); color: var(--brand); }
.wb-card li.wb-head { border-top: 0; padding: 0 0 4px; font-size: 10.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--ink-4); }
.wb-card li.wb-head > span { color: var(--ink-4); }
.wb-card li.wb-head > span:nth-child(n+3) { text-align: right; }
.wb-card .sf-name { white-space: normal; overflow: visible; overflow-wrap: anywhere; line-height: 1.3; }
.wb-card li.wb-total { font-weight: 600; }
.wb-card li.wb-total > span:nth-child(2) { color: var(--ink-2); }
.wb-card li.wb-note { border-top: 0; padding-top: 2px; font-size: 11.5px; color: var(--ink-3); }
.wb-card li.wb-note > span:nth-child(2) { grid-column: 2 / -1; }
@media (max-width: 760px) { .wb-grid { grid-template-columns: 1fr; } .wb-card li { grid-template-columns: 10px minmax(0, 1fr) 40px 72px 60px; } }
.section-head .seg { margin-left: auto; }

/* The baza card's section navbar (6 Oct 2026). The call page's tabs, with
   room above so they read as the page's own navigation under the headline. */
.otabs { margin: 18px 0 18px; overflow-x: auto; scrollbar-width: none; }
.otabs::-webkit-scrollbar { display: none; }
.otabs button { white-space: nowrap; }
.otab-panel[hidden] { display: none; }
.baza-tasks td:last-child { white-space: nowrap; }

/* «Mening kunim» tiles: an odd last tile takes the full row (a qabul seat has
   three since the PBX tile went, 6 Oct 2026). */
.reja-stats > .reja-stat:last-child:nth-child(odd) { grid-column: 1 / -1; }

/* The worked-leads and kval dialogs carry six columns, the last two a funnel
   AND a stage on each side of an arrow; at 1040px the destination was cut off
   (client, 6 Oct 2026: «we need expanding width»). Wider on a desktop only —
   the phone rule above already takes the whole screen. */
@media (min-width: 701px) {
  .modal-panel:has(.reja-worked),
  .modal-panel:has(.reja-kval) { width: min(1480px, 96vw); }
}
.reja-worked .reja-hop .reja-fcell,
.reja-kval .reja-fcell { min-width: 170px; }

/* «Mezon bo‘yicha hisob» on Operatorlar: a criterion picker over a per-seat
   tally. The select carries the whole question, so it is allowed the width. */
.crit-head { display: flex; flex-direction: column; gap: 8px; padding-bottom: 6px; }
.crit-total { margin: 0; font-size: 13px; color: var(--ink-2); }
.crit-card .good-ink { color: var(--brand-ink); }
.crit-card .bad-ink { color: var(--red-ink); }
.who.nowrap { white-space: nowrap; }

/* The popover picker (criterion on Operatorlar, operator on Sifat). A
   <details>, so it opens and closes with no script and from the keyboard;
   analytics.js only closes it on an outside click or Escape. */
.pick { position: relative; max-width: 100%; }
.pick > summary {
  list-style: none; cursor: pointer;
  display: grid; grid-template-columns: 1fr auto; column-gap: 12px; row-gap: 2px;
  padding: 9px 14px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface); max-width: 760px;
}
.pick > summary::-webkit-details-marker { display: none; }
.pick > summary:hover { background: var(--surface-hover); }
.pick > summary:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.pick[open] > summary { border-color: var(--brand); }
.pick-k { grid-column: 1; font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-4); }
.pick-v { grid-column: 1; font-size: 14px; color: var(--ink); font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.pick-caret { grid-column: 2; grid-row: 1 / span 2; align-self: center; color: var(--ink-3); font-size: 15px; transition: transform .12s; }
.pick[open] .pick-caret { transform: rotate(180deg); }
.pick-pop {
  position: absolute; z-index: 30; top: calc(100% + 6px); left: 0;
  width: min(760px, 92vw); max-height: min(460px, 60vh); overflow: auto;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg); padding: 6px;
}
.pick-legend { margin: 4px 8px 6px; font-size: 11.5px; color: var(--ink-3); }
.pick-gname { margin: 10px 8px 4px; font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-4); }
.pick-opt {
  display: flex; align-items: center; justify-content: space-between; gap: 14px; width: 100%;
  text-align: left; font: inherit; font-size: 13px; color: var(--ink-2);
  background: none; border: 0; border-radius: 6px; padding: 8px 10px; cursor: pointer;
}
.pick-opt:hover, .pick-opt:focus-visible { background: var(--surface-hover); color: var(--ink); outline: none; }
.pick-opt[aria-selected="true"] { background: var(--brand-soft-2); color: var(--brand-deep); font-weight: 600; }
.pick-stats { flex: none; font-variant-numeric: tabular-nums; font-size: 12px; font-weight: 600; }
/* On Sifat the operator picker sits in the chip row, so it wears the chip's
   shape and height — one line, «Operator: Hammasi ▾» — rather than the
   two-line box the criterion picker needs for a long question. */
.pick-op > summary {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px 4px 12px; border-radius: 999px; max-width: 280px;
  font-size: 12.5px;
}
.pick-op .pick-k {
  font-size: 12.5px; font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--ink-3);
}
.pick-op .pick-k::after { content: ':'; }
.pick-op .pick-v {
  font-size: 12.5px; font-weight: 600; display: block; white-space: nowrap;
  -webkit-line-clamp: unset;
}
.pick-op .pick-caret { font-size: 11px; }
.pick-op.is-set > summary { background: var(--brand-soft-2); border-color: var(--brand); }
.pick-op.is-set .pick-v { color: var(--brand-deep); }
.pick-op .pick-pop { width: min(320px, 92vw); }
.pick-op .pick-opt .dim { font-size: 11.5px; font-weight: 400; }
/* The chip row and the picker are two filters: a hairline between them says
   so without a second row, and the row keeps clear of the cards below. */
.sifat-filter { display: flex; align-items: center; gap: 10px 14px; flex-wrap: wrap; margin: 16px 0 18px; }
.sifat-filter .fn-chips { margin: 0; }
.sifat-filter .fn-chips + .pick-op { padding-left: 14px; border-left: 1px solid var(--line); }
.sifat-filter + .hint { margin: -8px 0 16px; }

/* A figure that opens the calls behind it. Underlined on hover only: a table
   of dotted numbers reads as a table of links and stops reading as numbers. */
button.drill {
  font: inherit; font-variant-numeric: tabular-nums; color: var(--ink);
  background: none; border: 0; padding: 2px 8px; margin: -2px -8px; border-radius: 6px; cursor: pointer;
}
button.drill.strong { font-weight: 700; }
button.drill.dim { color: var(--ink-3); }
button.drill.good { color: var(--brand-ink); font-weight: 600; }
button.drill.bad { color: var(--red-ink); font-weight: 600; }
button.drill:hover { background: var(--surface-hover); text-decoration: underline; text-underline-offset: 3px; }
button.drill:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }

/* The dialog behind a figure: the quote is the point of the list. */
.crit-calls td { vertical-align: top; }
.crit-calls .nowrap { white-space: nowrap; }
.crit-quote { color: var(--ink-2); font-size: 13px; line-height: 1.45; min-width: 280px; }
.crit-quote .crit-q { display: block; margin-top: 4px; color: var(--ink-3); font-style: italic; quotes: "«" "»"; }
/* `.card` clips its children for the rounded corners; the picker's popover
   must hang below the card, so this one card lets it out. The header and the
   table keep their own backgrounds, so nothing shows past the corners. */
.card.crit-card { overflow: visible; }
.reja-intake-price { margin-top: 4px; font-size: 12px; white-space: nowrap; }
.reja-checks { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 10px; }
.reja-check { border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px; }
.reja-check.is-big { background: var(--brand-soft); border-color: transparent; }
.reja-check-n { font-weight: 600; font-size: 26px; line-height: 1.1; font-variant-numeric: tabular-nums; }
.reja-check-lbl { font-size: 13px; margin-top: 2px; }
.reja-check-rule { font-size: 11px; color: var(--ink-3); margin-top: 2px; }
.reja-checks-card { cursor: pointer; transition: border-color .14s var(--ease), box-shadow .14s var(--ease); }
.reja-checks-card:hover { border-color: var(--brand); box-shadow: var(--shadow-xs); }
.reja-checks-card:hover .reja-stat-i { border-color: var(--brand); color: var(--brand); }
.reja-checks-card .reja-card-lbl { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.reja-check[data-reja-tile] { cursor: pointer; transition: border-color .14s var(--ease); }
.reja-check[data-reja-tile]:hover { border-color: var(--brand); }
.reja-checks-card:focus-visible,
.reja-check[data-reja-tile]:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.reja-own { margin-top: 18px; }
.reja-own-head { margin-bottom: 8px; }
.reja-blk-head { margin: 0 0 10px; }
.reja-blk-head h2 { font-size: var(--t-h2); }
.reja-blk-head .hint { margin: 4px 0 0; font-size: 11.5px; color: var(--ink-3); }
/* Feedback sits under BOTH columns: it is the longest block on the page, and
   inside the left column it left the right one empty for a screen. */
.reja-feedback-wide { margin-top: 26px; }
.reja-own-total { margin: 0 0 10px; font-size: 14px; color: var(--ink-2); }
.reja-own-total b { font-size: 22px; font-weight: 600; color: var(--ink); margin-right: 4px; }
.reja-dumka { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0; padding: 0; cursor: pointer; transition: border-color .14s var(--ease), box-shadow .14s var(--ease); }
.reja-dumka:hover { border-color: var(--brand); box-shadow: var(--shadow-xs); }
.reja-dumka:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.reja-dumka-cell { padding: 14px 16px; border-left: 1px solid var(--line); }
.reja-dumka-cell:first-child { border-left: 0; }
.reja-dumka-n { font-size: 24px; font-weight: 600; line-height: 1.15; font-variant-numeric: tabular-nums; }
.reja-dumka-lbl { font-size: 13px; margin-top: 4px; }
.reja-dumka-sub { font-size: 11px; color: var(--ink-3); margin-top: 2px; }
@media (max-width: 640px) { .reja-dumka { grid-template-columns: 1fr 1fr; } .reja-dumka-cell:nth-child(3) { border-left: 0; } .reja-dumka-cell:nth-child(n+3) { border-top: 1px solid var(--line); } }
.reja-hero-alert { background: var(--red-soft); border-color: var(--red); }
.reja-alert-line { margin: 10px 0 4px; padding: 10px 12px; border-radius: 10px; background: var(--surface); border: 1px solid var(--red); color: var(--red-ink); font-size: 13px; line-height: 1.45; }
.reja-lost-row { display: flex; justify-content: space-between; gap: 12px; padding: 10px 0; border-top: 1px solid var(--line); }
.reja-lost-row:first-of-type { border-top: 0; }
.reja-lost-lbl { font-size: 13px; }
.reja-lost-sub { font-size: 11px; color: var(--ink-3); margin-top: 2px; }
.reja-lost-val { font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
.fb-strip { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin-bottom: 12px; }
.fb-stat { padding: 13px 17px; display: flex; flex-direction: column; gap: 4px; border-left: 1px solid var(--line); min-width: 0; }
.fb-stat:first-child { border-left: 0; }
.pt-strip { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); border: 1px solid var(--line); border-radius: 12px; margin-bottom: 18px; }
.pt-strip .fb-stat { padding: 12px 15px; }
.pt-sub { font-size: 12px; line-height: 1.35; }
.pt-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px 32px; margin-bottom: 18px; }
.pt-h { font-size: 13px; font-weight: 700; margin: 0 0 10px; color: var(--ink-2); }
.pt-zone { display: block; font-size: 11px; }
.pt-tablehead { padding-bottom: 0; }
.pt-todo td { padding-top: 0; font-size: 12.5px; line-height: 1.45; color: var(--ink-2); border-top: 0; }
.pt-audit-ops tr:has(+ .pt-todo) td { border-bottom: 0; padding-bottom: 4px; }
.pt-recs-wrap summary { cursor: pointer; padding: 2px 0; }
.pt-recs-wrap[open] summary { margin-bottom: 12px; }
.pt-recs { margin: 0 0 16px; padding-left: 20px; display: grid; gap: 12px; }
.pt-recs li { font-size: 13px; line-height: 1.45; display: grid; gap: 3px; }
.pt-rec-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pt-grid { margin-bottom: 4px; }
@media (max-width: 760px) {
  .pt-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pt-strip .fb-stat:nth-child(3) { border-left: 0; }
  .pt-strip .fb-stat:nth-child(n + 3) { border-top: 1px solid var(--line); }
  .pt-grid { grid-template-columns: minmax(0, 1fr); }
}
.fb-orders { margin: -4px 0 12px; }
.fb-orders b { color: var(--ink); font-weight: 600; }
.fb-stat.can-open { cursor: pointer; position: relative; transition: background .14s var(--ease); }
.fb-stat.can-open:hover { background: var(--brand-soft); }
.fb-stat.can-open:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.fb-stat.can-open::after { content: '↗'; position: absolute; top: 12px; right: 14px; font-size: 13px; color: var(--ink-3); }
.fb-stat.can-open:hover::after { color: var(--brand-ink); }
.fb-calls .fb-c-when { white-space: nowrap; font-variant-numeric: tabular-nums; }
.fb-calls .fb-c-reason { margin-top: 4px; font-size: 12px; color: var(--ink-2); }
.fb-calls td.fb-c-text, .fb-calls td:nth-child(3) { white-space: normal; }
.fb-calls .fb-c-text { min-width: 260px; font-size: 13px; line-height: 1.45; }
.fb-reasons { list-style: none; margin: 0; padding: 0; }
.fb-reasons > li { border-top: 1px solid var(--line); font-size: 13px; }
.fb-reasons > li:first-child { border-top: 0; }
.fb-r-row { display: grid; grid-template-columns: minmax(0, 1fr) auto 14px; gap: 4px 10px; padding: 9px 0; }
.fb-reasons > li:first-child .fb-r-row { padding-top: 2px; }
.fb-reasons li.fb-zero .fb-r-label, .fb-reasons li.fb-zero .fb-r-mine { color: var(--ink-3); }
.fb-reasons details > summary { list-style: none; cursor: pointer; border-radius: 6px; }
.fb-reasons details > summary::-webkit-details-marker { display: none; }
.fb-reasons details > summary:hover .fb-r-label { color: var(--brand-ink); }
.fb-reasons details > summary:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.fb-r-chev { width: 7px; height: 7px; border-right: 1.6px solid var(--ink-3); border-bottom: 1.6px solid var(--ink-3); transform: rotate(45deg); grid-column: 3; grid-row: 1; align-self: center; justify-self: center; transition: transform .15s var(--ease); }
.fb-reasons details[open] .fb-r-chev { transform: rotate(-135deg); }
.fb-r-calls { list-style: none; margin: 0 0 10px; padding: 0; border-left: 2px solid var(--line); }
.fb-r-calls li { padding: 8px 0 8px 12px; }
.fb-r-calls li + li { border-top: 1px dashed var(--line); }
.fb-r-call-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; font-size: 12px; }
.fb-r-who { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fb-r-open { flex: none; font-size: 12px; color: var(--brand-ink); text-decoration: none; font-weight: 600; }
.fb-r-open:hover { text-decoration: underline; }
.fb-r-calls p { margin: 4px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink); }
.fb-r-mine { white-space: nowrap; font-variant-numeric: tabular-nums; }
.fb-r-team { grid-column: 1 / -1; display: flex; align-items: center; gap: 8px; font-size: 12px; white-space: nowrap; }
.fb-r-team .dim { min-width: 68px; text-align: right; font-variant-numeric: tabular-nums; }
.fb-bar { flex: 1; height: 6px; border-radius: 3px; background: var(--line); overflow: hidden; }
.fb-bar i { display: block; height: 100%; background: var(--ink-3); border-radius: 3px; opacity: .55; }
.fb-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 12px; color: var(--ink-3); margin: 0 0 6px; }
.fb-legend span { display: inline-flex; align-items: center; gap: 6px; }
.fb-legend .fb-m { position: static; transform: none; }
.fb-tone { list-style: none; margin: 0; padding: 0; }
.fb-tone li { padding: 9px 0; border-top: 1px solid var(--line); }
.fb-tone li:first-child { border-top: 0; }
.fb-t-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; font-size: 13px; }
.fb-t-head b { font-family: var(--font-d); font-size: 16px; font-variant-numeric: tabular-nums; }
.fb-track { position: relative; height: 6px; margin: 8px 6px 6px; border-radius: 3px; background: var(--line); }
.fb-m { position: absolute; top: 50%; transform: translate(-50%, -50%); display: inline-block; width: 12px; height: 12px; border-radius: 50%; box-sizing: border-box; }
.fb-m.mine { background: var(--brand); border: 2px solid var(--surface); box-shadow: 0 0 0 1px var(--brand); z-index: 2; }
.fb-m.team { background: var(--surface); border: 2px solid var(--ink-3); z-index: 1; }
.fb-m.sold { width: 3px; height: 16px; border-radius: 1px; background: var(--green); z-index: 3; }
.fb-t-foot { font-size: 12px; }
.fb-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-bottom: 12px; }
/* The block sits in a main column whose width depends on the rail beside
   it, not on the screen, so it answers to its OWN width. */
.fb-wrap { container-type: inline-size; }
@container (max-width: 640px) { .fb-grid { grid-template-columns: minmax(0, 1fr); } }
@container (max-width: 460px) { .fb-stat { padding: 11px 12px; } .fb-stat .tdy-value { font-size: 19px; } .fb-stat .tdy-label { letter-spacing: .06em; } }
.fb-card { padding: 14px 16px; }
.fb-card h3 { margin: 0 0 8px; font-size: 14px; }
.fb-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.fb-table th { text-align: left; font-size: 11px; font-weight: 600; color: var(--ink-3); text-transform: uppercase; letter-spacing: .04em; padding: 4px 6px; }
.fb-table td { padding: 6px; border-top: 1px solid var(--line); vertical-align: top; }
.fb-table .num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.fb-table tr.fb-weak td { background: var(--red-soft); }
.fb-seg tr.fb-seg-head th { padding: 12px 6px 4px; font-size: 12px; color: var(--ink-2); text-transform: none; letter-spacing: 0; border-top: 0; }
.fb-seg td:first-child { padding-left: 14px; }
.fb-seg .fb-seg-team { display: inline-flex; align-items: center; gap: 8px; }
.fb-seg .fb-seg-team .fb-bar { flex: none; width: 72px; }
.fb-seg .fb-seg-few { font-size: 12px; }
.fb-quotes { margin: 0; padding-left: 18px; font-size: 13px; line-height: 1.5; color: var(--ink-2); }
.fb-quotes li { margin: 4px 0; }
.fb-fit { margin: 0; display: flex; gap: 6px; flex-wrap: wrap; }
.fb-call p { margin: 6px 0; }
.fb-rec { padding-top: 8px; border-top: 1px solid var(--line); }
.fb-card + .fb-card, .fb-grid + .fb-card { margin-top: 12px; }
.fb-grid > .fb-card { margin-top: 0; }
.fb-call { padding: 14px 16px; }
/* «Yo'qotilgan»: the loss side of «Bugungi sotuv» — the same soft tint, in red. */
.reja-lost { background: var(--red-soft); border-color: transparent; }
.reja-lost .reja-lost-row { border-top-color: color-mix(in srgb, var(--red) 18%, transparent); }
.reja-lost .reja-lost-val { color: var(--red-ink); }

/* The missed-call strip on /calls (Darmon Servis, `qayta_aloqa`): each card
   narrows the list to the calls it counted, so it reads as pressable. */
/* One compact row: the list under it fills whatever height is LEFT (see
   main:has(.calls-table)), so every pixel this strip takes comes out of the
   list. Label on top, the figure with its detail beside it on one line; the
   full detail is the card's hover. */
.kpis.missed-strip { margin: 8px 0; }
.kpis.missed-strip .kpi {
  padding: 8px 14px; display: grid; grid-template-columns: auto minmax(0, 1fr);
  column-gap: 10px; align-items: center;
}
.kpis.missed-strip .kpi dt { grid-column: 1 / -1; margin-bottom: 2px; }
.kpis.missed-strip .kpi dd { font-size: 22px; line-height: 1; }
.kpis.missed-strip .kpi .sub { margin: 0; font-size: 12px; line-height: 1.3; }
/* «Bemor kutdi» is one long sentence with nothing to press: one line, the
   rest on hover. The other cards' details are buttons and stay whole. */
.kpis.missed-strip .kpi:last-child .sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* «Keyingi qadam»: the chip and its arrow on one line, who and when under it. */
.missed-next { min-width: 170px; }
.missed-next .mn-top { display: flex; align-items: center; white-space: nowrap; }
.missed-next .mn-top .linky { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.missed-next .mn-sub { margin-top: 3px; font-size: 12px; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 200px; }
.missed-strip .missed-kpi { cursor: pointer; }
.missed-strip .missed-kpi:hover { background: var(--surface-2, var(--surface)); }
.missed-strip .missed-kpi[aria-pressed="true"] { box-shadow: inset 0 -3px 0 var(--brand); }
.missed-strip .sub .linky[aria-pressed="true"] { font-weight: 700; text-decoration: underline; }

/* Operator card evidence (`mezon_dalil`): the example call under a criterion,
   and the strengths / gaps pair above the table. */
.crit-example { display: block; margin-top: 4px; font-size: 12.5px; color: var(--ink-3); }
.crit-example.bad { color: var(--red-ink); }
.crit-example.good { color: var(--green); }
.crit-example q { color: var(--ink-2); font-style: italic; }
.crit-example .linky { font-size: 12.5px; }
.strengths-gaps { margin-bottom: 18px; }
.sg-list { margin: 0; padding-left: 18px; display: grid; gap: 10px; }
.sg-list li b { font-weight: 600; }

/* «Seans» on the call page (`seans`): one conversation across calls. */
.session-card { margin-bottom: 14px; }
.session-card .hint { display: block; margin: 4px 0 10px; }
.session-parts { display: flex; flex-wrap: wrap; gap: 8px; }

/* «Qo‘ng‘iroq tarkibi» on the call page (`xizmat_tahlili`). */
.services-strip { margin-bottom: 14px; }
.services-strip b { display: block; margin-bottom: 8px; }

/* ============================================================ «Musobaqa»
   The operators' game (public/game.js), laid out like Upsale's «Xodimlar»:
   the podium sits INSIDE an ordinary card on faint rays, the steps are
   outlined surfaces and only the winner's is filled — in the brand green,
   because a festive page is still Reveo's page. Gold, silver and bronze are
   the one place other colours appear, and they mean a place, not a brand. */
.gm-top { margin-bottom: 16px; }
.gm-top > header { align-items: center; flex-wrap: wrap; }
.gm-top > header .hint { margin-left: auto; }
.gm-teams { margin-left: 8px; }
.gm-stage { position: relative; overflow: hidden; padding: 26px 18px 0; }
.gm-rays {
  position: absolute; inset: -60% -10% -10%; pointer-events: none;
  background: repeating-conic-gradient(from 0deg at 50% 45%, var(--ink) 0deg 6deg, transparent 6deg 20deg);
  opacity: .035;
  -webkit-mask-image: radial-gradient(closest-side, #000 30%, transparent);
          mask-image: radial-gradient(closest-side, #000 30%, transparent);
}
.gm-podium {
  position: relative; display: grid; grid-template-columns: repeat(3, minmax(0, 220px));
  justify-content: center; align-items: end; gap: 10px;
}
.gm-step { display: flex; flex-direction: column; align-items: center; min-width: 0; }
.gm-who { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 0 4px 14px; min-width: 0; max-width: 100%; }
.gm-name { font-weight: 600; font-size: 14.5px; color: var(--ink); text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.gm-stage .avatar.gm-av { width: 54px; height: 54px; font-size: 18px; }
.gm-p1 .avatar.gm-av { width: 74px; height: 74px; font-size: 24px; box-shadow: 0 0 0 3px var(--surface), 0 0 0 6px #E9B10C; }
.gm-bar {
  width: 100%; border: 1px solid var(--line); border-bottom: 0; background: var(--surface-2);
  border-radius: 10px 10px 0 0; display: flex; flex-direction: column; align-items: center;
  padding: 18px 10px 0; text-align: center;
  transform-origin: bottom; animation: gm-rise .6s cubic-bezier(.2,.8,.2,1) both;
}
.gm-p1 .gm-bar { height: 210px; background: var(--brand-soft); border-color: var(--brand-line); animation-delay: .25s; }
.gm-p2 .gm-bar { height: 175px; animation-delay: .1s; }
.gm-p3 .gm-bar { height: 150px; animation-delay: .4s; }
.gm-step.empty .gm-bar { justify-content: center; padding-top: 0; }
.gm-free { font-size: var(--t-small); color: var(--ink-4); }
.gm-pts { font-family: var(--font-d); font-size: 26px; font-weight: 600; letter-spacing: -0.02em; margin-top: 10px; font-variant-numeric: tabular-nums; color: var(--ink); }
.gm-p1 .gm-pts { font-size: 32px; color: var(--brand-deep); }
.gm-sub { font-size: 12.5px; color: var(--ink-3); margin-top: 3px; }
@keyframes gm-rise { from { transform: scaleY(0); } to { transform: scaleY(1); } }
:root[data-theme='dark'] .gm-p1 .gm-pts { color: var(--brand); }

/* The medal: a pentagon with the place on it, gold / silver / bronze. */
.gm-medal {
  --gm-m: #E9A800; --gm-m-hi: #FFD54A;
  display: inline-grid; place-items: center; width: 26px; height: 26px; flex: none;
  background: linear-gradient(160deg, var(--gm-m-hi), var(--gm-m));
  clip-path: polygon(50% 0, 100% 38%, 82% 100%, 18% 100%, 0 38%);
  color: #fff; font-weight: 800; font-size: 12.5px; line-height: 1;
}
.gm-medal b { transform: translateY(2px); text-shadow: 0 1px 1px rgba(0,0,0,.25); }
.gm-medal.lg { width: 50px; height: 48px; font-size: 22px; }
.gm-medal.sm { width: 20px; height: 20px; font-size: 10.5px; }
.gm-m2 { --gm-m: #8E97A6; --gm-m-hi: #C8CED8; }
.gm-m3 { --gm-m: #D9531E; --gm-m-hi: #F48A4B; }

/* The four floor figures: the panel's own strip, with an icon chip each. */
.gm-strip { grid-template-columns: repeat(4, minmax(0, 1fr)); margin-bottom: 16px; }
.gm-kpi { padding: 16px 18px; gap: 7px; }
.gm-kpi-head { display: flex; align-items: center; gap: 10px; }
.gm-kpi-ic { width: 30px; height: 30px; border-radius: 8px; display: grid; place-items: center; flex: none; }
.gm-kpi-ic svg { width: 17px; height: 17px; }
.gm-kpi-ic.brand { background: var(--brand-soft); color: var(--brand-ink); }
.gm-kpi-ic.blue { background: var(--blue-soft); color: var(--blue); }
.gm-kpi-ic.violet { background: #EFEAFD; color: #7653D8; }
.gm-kpi-ic.amber { background: var(--amber-soft); color: var(--amber); }
.gm-kpi-ic.red { background: var(--red-soft); color: var(--red); }
:root[data-theme='dark'] .gm-kpi-ic.violet { background: rgba(118, 83, 216, .18); color: #B4A0F2; }
.gm-kpi .tdy-value { font-size: 26px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gm-kpi .tdy-value small { font-size: 15px; color: var(--ink-3); font-weight: 500; }

.gm-search { margin-bottom: 16px; position: relative; }
.gm-search-ic { position: absolute; left: 13px; top: 50%; width: 17px; height: 17px; transform: translateY(-50%); color: var(--ink-3); pointer-events: none; }
.gm-search input {
  width: 100%; box-sizing: border-box; padding: 10px 14px 10px 38px; border: 1px solid var(--line-2);
  border-radius: var(--radius-sm); background: var(--surface); color: var(--ink); font: inherit; font-size: 14px;
}
.gm-search input:focus { outline: 2px solid var(--brand); outline-offset: -1px; }
/* The suggestions: five rows tall, scrolling opens five more. */
.gm-suggest {
  position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 30;
  max-height: calc(5 * 54px + 8px); overflow-y: auto; overscroll-behavior: contain;
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--radius-sm);
  box-shadow: 0 12px 32px rgba(0,0,0,.14); padding: 4px;
}
.gm-sg {
  all: unset; box-sizing: border-box; display: flex; align-items: center; gap: 11px;
  width: 100%; height: 54px; padding: 0 12px; border-radius: 7px; cursor: pointer;
}
.gm-sg:hover, .gm-sg.active { background: var(--surface-hover); }
.gm-sg.active { box-shadow: inset 2px 0 0 var(--brand); }
.gm-sg-nm { display: flex; flex-direction: column; line-height: 1.25; font-weight: 600; min-width: 0; flex: 1; }
.gm-sg-nm > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gm-sg-nm small, .gm-sg-rk small { font-weight: 400; font-size: 12px; color: var(--ink-3); }
.gm-sg-nm mark { background: none; color: var(--brand-ink); font-weight: 800; }
:root[data-theme='dark'] .gm-sg-nm mark { color: var(--brand); }
.gm-sg-rk { display: flex; flex-direction: column; align-items: flex-end; font-weight: 600; font-size: 13px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.gm-sg-more, .gm-sg-none { padding: 10px 12px; font-size: 12.5px; color: var(--ink-3); text-align: center; }

.gm-tbl th, .gm-tbl td { padding: 11px 14px; text-align: left; border-bottom: 1px solid var(--line); vertical-align: middle; }
.gm-tbl th { font-size: var(--t-eyebrow); color: var(--ink-3); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; white-space: nowrap; }
.gm-tbl .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.gm-tbl .gm-rank { width: 36px; font-weight: 600; color: var(--ink-3); }
.gm-tbl .who { display: flex; align-items: center; gap: 10px; }
.gm-nm { display: flex; flex-direction: column; line-height: 1.25; font-weight: 600; }
.gm-nm small { font-weight: 400; font-size: 12.5px; color: var(--ink-3); }
.gm-ptscol { min-width: 190px; white-space: nowrap; }
.gm-ptscol b { font-variant-numeric: tabular-nums; margin-left: 10px; }
.gm-meter { display: inline-block; vertical-align: middle; width: 110px; height: 6px; border-radius: 99px; background: var(--line); overflow: hidden; }
.gm-meter span { display: block; height: 100%; background: var(--brand); border-radius: inherit; }
.gm-score { font-weight: 600; }
.gm-score.good { color: var(--green); }
.gm-up { color: var(--green); font-weight: 600; }
.gm-down { color: var(--red-ink); font-weight: 600; }
.gm-tbl tr.gm-mine td { background: var(--brand-soft); }
.gm-tbl tr.gm-gap td { text-align: center; color: var(--ink-3); padding: 6px; }
.gm-mcs { white-space: nowrap; }
.gm-mc { display: inline-flex; align-items: center; gap: 4px; margin-right: 10px; font-variant-numeric: tabular-nums; font-weight: 600; }
.gm-mc.zero { opacity: .35; }
.gm-you { font-size: 11px; font-weight: 700; color: var(--brand-ink); background: var(--brand-soft-2); border-radius: 999px; padding: 1px 7px; }

.gm-rules { padding: 12px 17px; margin-top: 16px; }
.gm-rules summary { cursor: pointer; font-weight: 600; color: var(--ink-2); }
.gm-rules ul { margin: 10px 0 2px; padding-left: 18px; color: var(--ink-2); line-height: 1.7; font-size: 13.5px; }
.gm-empty { padding: 38px 20px; text-align: center; margin-top: 16px; }
.gm-empty-ic { font-size: 40px; }

@media (max-width: 900px) { .gm-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) {
  .gm-podium { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 5px; }
  .gm-p1 .gm-bar { height: 180px; } .gm-p2 .gm-bar { height: 150px; } .gm-p3 .gm-bar { height: 130px; }
  .gm-pts { font-size: 19px; } .gm-p1 .gm-pts { font-size: 23px; }
  .gm-sub { font-size: 11px; }
  .gm-medal.lg { width: 38px; height: 36px; font-size: 17px; }
  .gm-top > header .hint { margin-left: 0; }
}
@media (prefers-reduced-motion: reduce) { .gm-bar { animation: none; } }

/* ── «Ish kuni» (work-day.js, extra `ish_kuni`) ─────────────────────────────
   One seat's days on one clock: the workspace's «Журнал смен» drawn from the
   calls. Conversation bars in brand green, a missed inbound client as a red
   tick, a dial nobody picked up as a grey one, the working day as a hatched
   frame and long silences as a dashed band. */
.wd-card { padding-bottom: 6px; }
/* The hover card hangs below the strip; on the last row it must not be cut
   off by the card's own edge. */
.card.wd-card { overflow: visible; }
.wd-card > .wd-legend, .wd-card > .wd-head, .wd-card > .wd-row, .wd-card > .note { margin-left: 18px; margin-right: 18px; }
.wd-card > .wd-legend { margin-top: 12px; }
.wd-legend {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 6px;
  font-size: 12px; color: var(--ink-2); margin: 2px 0 6px;
}
.wd-legend .sw { display: inline-block; width: 18px; height: 11px; border-radius: 3px; flex: none; }
.wd-legend .sw + span { margin-right: 10px; }
.wd-legend .sw.talk { background: var(--brand); }
.wd-legend .sw.missed { width: 3px; background: var(--red); border-radius: 1px; }
.wd-legend .sw.noanswer { width: 3px; height: 7px; background: var(--ink-4); border-radius: 1px; }
.wd-legend .sw.pin { width: 9px; height: 9px; border-radius: 50%; background: var(--green); }
.wd-legend .sw.frame {
  background: repeating-linear-gradient(135deg, var(--line-strong) 0 1.5px, transparent 1.5px 6px);
  box-shadow: inset 0 0 0 1px var(--line-2);
}
.wd-legend .sw.gap { height: 0; border-top: 2px dashed var(--amber); border-radius: 0; }

.wd-head, .wd-row {
  display: grid; grid-template-columns: minmax(130px, 170px) minmax(0, 1fr) 130px; gap: 18px;
}
.wd-head { padding: 10px 0 2px; }
.wd-axis { position: relative; height: 16px; }
.wd-axis-tick {
  position: absolute; top: 0; transform: translateX(-50%); font-size: 11px; font-weight: 600;
  color: var(--ink-3); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.wd-row { padding: 12px 0 14px; border-top: 1px solid var(--line); align-items: start; }
.wd-head + .wd-row { border-top: none; }
.wd-row.quiet .wd-track { opacity: 0.55; }
.wd-who b { display: block; font-size: 14px; color: var(--ink); }
.wd-today {
  display: inline-block; margin-left: 4px; padding: 0 6px; border-radius: 6px; vertical-align: 1px;
  background: var(--brand-soft); color: var(--brand-ink); font-size: 11px; font-weight: 700; line-height: 17px;
}
.wd-meta { display: block; margin-top: 3px; font-size: 12px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.wd-body { min-width: 0; }

.wd-plot { position: relative; padding-top: 12px; }
.wd-plot.can-open { cursor: pointer; }
.wd-pins { position: absolute; left: 0; right: 0; top: 0; height: 12px; }
.wd-pin {
  position: absolute; top: 1px; width: 9px; height: 9px; margin-left: -4.5px; border-radius: 50%;
  background: var(--amber); box-shadow: 0 0 0 1.5px var(--surface);
}
.wd-pin.good { background: var(--green); }
.wd-pin.bad { background: var(--red); }
.wd-track {
  position: relative; height: 28px; border-radius: 7px; background: var(--surface-2);
  overflow: hidden; box-shadow: inset 0 0 0 1px var(--line);
}
.wd-grid { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--line); }
.wd-frame {
  position: absolute; top: 3px; bottom: 3px; border-radius: 5px;
  background: repeating-linear-gradient(135deg, var(--line-2) 0 1.5px, transparent 1.5px 6px);
  box-shadow: inset 0 0 0 1px var(--line-2);
}
/* A break is an absence, so it is drawn as one: a dashed line across the
   middle of the track, not a filled block that outweighs the calls. */
.wd-gap {
  position: absolute; top: 50%; height: 0; margin-top: -1px;
  border-top: 2px dashed var(--amber);
}
.wd-talk {
  position: absolute; top: 4px; bottom: 4px; min-width: 2px; border-radius: 3px;
  background: var(--brand);
}
.wd-tick { position: absolute; width: 2px; margin-left: -1px; border-radius: 1px; }
.wd-tick.missed { top: 3px; bottom: 3px; background: var(--red); }
.wd-tick.noanswer { top: 9px; bottom: 9px; background: var(--ink-4); }
.wd-now { position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px; background: var(--ink); opacity: 0.45; }

.wd-tip {
  position: absolute; top: calc(100% + 8px); z-index: 6; pointer-events: none;
  padding: 11px 13px 10px; border-radius: 12px; text-align: left;
  background: var(--surface); color: var(--ink); border: 1px solid var(--line-2);
  box-shadow: 0 12px 32px rgba(16, 24, 32, 0.16), 0 2px 6px rgba(16, 24, 32, 0.06);
}
.wd-tip[hidden] { display: none; }
.wd-tip::before {
  content: ''; position: absolute; top: -6px; left: var(--arrow, 50%); width: 10px; height: 10px;
  margin-left: -5px; transform: rotate(45deg); background: var(--surface);
  border-left: 1px solid var(--line-2); border-top: 1px solid var(--line-2);
}
.wd-tip-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.wd-tip-dir {
  display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase; color: var(--ink-3);
}
.wd-tip-dir.in svg { color: var(--brand); }
.wd-tip-dir.out svg { color: var(--ink-2); }
.wd-tip-pill {
  display: inline-flex; align-items: center; gap: 4px; height: 22px; padding: 0 8px; border-radius: 999px;
  font-size: 11.5px; font-weight: 600; white-space: nowrap;
}
.wd-tip-pill b { font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums; }
.wd-tip-pill.good { background: var(--green-soft); color: var(--brand-deep); }
.wd-tip-pill.warn { background: var(--amber-soft); color: #9A5B00; }
.wd-tip-pill.bad { background: var(--red-soft); color: var(--red-ink, var(--red)); }
.wd-tip-pill.mute { background: var(--surface-hover); color: var(--ink-2); }
.wd-tip-time {
  display: flex; align-items: baseline; gap: 6px; margin-top: 7px;
  font-family: 'Space Grotesk', sans-serif; font-size: 18px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.wd-tip-time .arr { color: var(--ink-4); font-weight: 500; }
.wd-tip-time .len {
  margin-left: auto; font-family: inherit; font-size: 12.5px; font-weight: 600; color: var(--ink-2);
}
.wd-tip-peer { margin-top: 2px; font-size: 12.5px; color: var(--ink-2); font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wd-tip-sum {
  margin: 8px 0 0; padding-top: 8px; border-top: 1px solid var(--line); font-size: 12.5px; line-height: 1.45;
  color: var(--ink); white-space: normal; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.wd-tip-open { margin-top: 8px; font-size: 11px; font-weight: 600; color: var(--brand-ink); }
:root[data-theme="dark"] .wd-tip-pill.warn { color: var(--amber); }

.wd-list { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 9px; }
.wd-sess {
  display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; border-radius: 999px;
  border: 1px solid var(--line-2); background: var(--surface); font-size: 12.5px; font-weight: 700;
  color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.wd-ev { display: inline-flex; align-items: center; gap: 4px; }
.wd-ev sup { font-size: 9px; color: var(--ink-2); }
.wd-ev .tri { width: 0; height: 0; border-left: 6px solid var(--brand); border-top: 4px solid transparent; border-bottom: 4px solid transparent; }
.wd-ev .sq { width: 7px; height: 7px; border-radius: 1.5px; background: var(--ink-2); }
.wd-dash { color: var(--ink-3); font-weight: 500; }
.wd-len { color: var(--ink-2); font-weight: 600; padding-left: 8px; border-left: 1px solid var(--line); }
.wd-break {
  display: inline-flex; align-items: center; height: 24px; padding: 0 8px; border-radius: 999px;
  background: var(--amber-soft); color: var(--ink-2); font-size: 11.5px; font-weight: 600;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

.wd-sum { margin: 0; display: flex; flex-direction: column; gap: 8px; padding-top: 10px; }
.wd-sum dt { font-size: 11px; font-weight: 600; color: var(--ink-2); }
.wd-sum dd { margin: 1px 0 0; font-size: 15px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.wd-sum dd.talk { color: var(--brand-ink); }
.wd-sum dd small { font-size: 12px; font-weight: 600; color: var(--ink-2); }
.wd-sum dd small.miss { color: var(--red-ink, var(--red)); }

@media (max-width: 760px) {
  .wd-head, .wd-row { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .wd-head > div:first-child, .wd-head > div:last-child { display: none; }
  .wd-sum { flex-direction: row; gap: 18px; padding-top: 0; }
}
