/* ===========================================================================
   canvas (#/home). Prefix: .cn-

   TWO halves, in this order:
     1. THE STAGE. The orb (the landing widget's green/blue blob orb, ported
        from suppo.ge v2.css and driven by real call audio) at the centre, the
        eight channel nodes on a ring, the SVG connector curves, the activity
        pulses travelling node → orb, the status capsule with the call control,
        and the side panel that opens on a node.
     2. THE SHIFT REPORT under it: the three figures, the phone lane, the
        attention queue, the last 7 days, the quota and today's schedule.

   The dark .sh-mast band is gone from this screen; the stage carries the orb
   and the identity. Shared components (.card .btn .pill .toggle .bar .hint
   .skel .chn .gel .num .up .empty) come from shell.css and are never
   redefined here. Nothing under 12px, no font-weight above 700, no green text
   that is not --ok, no emoji.
   =========================================================================== */

/* the stage takes the whole viewport width below the topbar, wider than the
   normal content column, so the #view > * max-width is lifted for this screen
   and given back to the report alone */
#view > .cn-root { max-width: none; }

.cn-root { position: relative; display: flex; flex-direction: column; }
.cn-report {
  width: 100%; max-width: var(--content-max); margin-inline: auto;
  display: flex; flex-direction: column; gap: var(--sp-sec);
  padding-bottom: var(--sp-sec);
}

.cn-stage {
  position: relative;
  height: calc(100dvh - var(--topbar-h) - 118px);
  min-height: 460px;
  overflow: hidden;
}
.cn-lines { position: absolute; inset: 0; pointer-events: none; }
.cn-ring { position: absolute; inset: 0; }

.cn-orbwrap {
  position: absolute; left: 50%; top: 42%;
  transform: translate(-50%, -50%);
  width: min(22vw, 260px); aspect-ratio: 1 / 1;
  z-index: 5;
}
/* ONE ORB (2026-09-13): .cn-orbwrap is the SLOT guide.js fills with its orb
   node (.gd, the same .cn-orb sphere below); the guide's bubble lands in
   .cn-guideslot at the top of the status block, centred under the orb */
.cn-guideslot { width: 100%; display: flex; flex-direction: column; align-items: center; }
.cn-guideslot:empty { display: none; }
.cn-halo {
  position: absolute; inset: -18%; border-radius: 50%;
  background: radial-gradient(circle, rgba(47,191,108,.22), rgba(82,198,255,.14) 45%, transparent 72%);
  filter: blur(6px); pointer-events: none;
}

/* --- the orb, ported verbatim from suppo.ge v2.css (.orb) -------------------
   The face of the call: a soft gradient sphere in the aurora family that
   breathes with the voice (--amp, fed by canvas.js from real playback RMS).
   Drawn with soft-stop radial gradients and translate3d drift ONLY, no
   filter:blur, so it costs nothing on a phone. The grain is one static
   SVG-noise tile. Sized by .cn-orbwrap instead of the widget's fixed 168px. */
.cn-orb {
  --amp: 0; --gain: .1;
  position: relative; display: block; width: 100%; aspect-ratio: 1 / 1;
  border-radius: 999px; overflow: hidden;
  background: linear-gradient(125deg, #7ED6A4 8%, #9CD9FF 92%);
  transform: scale(calc(1 + var(--amp) * var(--gain))) translateZ(0);
  transition: transform 110ms linear, opacity 140ms cubic-bezier(.2, 0, 0, 1);
}
.cn-orb__b { position: absolute; inset: -28%; border-radius: 999px; will-change: transform; transition: scale 110ms linear; }
.cn-orb__b1 { background: radial-gradient(closest-side at 36% 56%, #2FBF6C 0%, #2FBF6C 26%, rgba(47,191,108,0) 68%); animation: cn-orbDrift1 11s cubic-bezier(.2, 0, 0, 1) infinite alternate; }
.cn-orb__b2 { background: radial-gradient(closest-side at 74% 44%, #52C6FF 0%, rgba(82,198,255,0) 62%); animation: cn-orbDrift2 9s cubic-bezier(.2, 0, 0, 1) infinite alternate; animation-delay: -3s; }
.cn-orb__b3 { background: radial-gradient(closest-side at 70% 84%, #2E6BE6 0%, rgba(46,107,230,0) 58%); animation: cn-orbDrift3 13s cubic-bezier(.2, 0, 0, 1) infinite alternate; animation-delay: -7s; }
.cn-orb__b4 { background: radial-gradient(closest-side at 78% 28%, #EFFFF6 0%, rgba(239,255,246,0) 52%); animation: cn-orbDrift2 8s cubic-bezier(.2, 0, 0, 1) infinite alternate; animation-delay: -5s; }
.cn-orb__grain {
  position: absolute; inset: 0; pointer-events: none; mix-blend-mode: soft-light; opacity: .6;
  background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E");
  background-size: 140px;
}
@keyframes cn-orbDrift1 { from { transform: translate3d(-7%, 4%, 0); } to { transform: translate3d(9%, -6%, 0); } }
@keyframes cn-orbDrift2 { from { transform: translate3d(6%, -5%, 0); } to { transform: translate3d(-8%, 7%, 0); } }
@keyframes cn-orbDrift3 { from { transform: translate3d(4%, 7%, 0); } to { transform: translate3d(-6%, -8%, 0); } }
/* Idle: the line is not open yet, quiet, desaturated, slow. */
.cn-orb--idle { filter: saturate(.45); opacity: .68; }
.cn-orb--idle .cn-orb__b { animation-duration: 18s, 18s, 18s; }
/* Connecting: a soft ring reaches out while the handshake runs. */
.cn-orb--connecting::after {
  content: ""; position: absolute; inset: 0; border-radius: 999px;
  border: 2px solid rgba(255,255,255,.75); animation: cn-orbRing 1.5s cubic-bezier(.2, 0, 0, 1) infinite;
}
@keyframes cn-orbRing { 0% { opacity: .8; transform: scale(.82); } 75%, 100% { opacity: 0; transform: scale(1.04); } }
/* Thinking: the weather speeds up while it decides what to say. */
.cn-orb--thinking .cn-orb__b1 { animation-duration: 3.2s; }
.cn-orb--thinking .cn-orb__b2 { animation-duration: 2.6s; }
.cn-orb--thinking .cn-orb__b3 { animation-duration: 3.8s; }
.cn-orb--thinking .cn-orb__b4 { animation-duration: 2.9s; }
/* Speaking: --amp is the REAL speaker output level (playback analyser). The
   whole sphere swells and glows with it, and canvas.js moves the blobs inline
   every frame. Keyframes MUST be off here or they override the inline transforms. */
.cn-orb--speaking {
  --gain: .14;
  filter: saturate(calc(1.08 + var(--amp) * .35)) brightness(calc(1 + var(--amp) * .1));
}
.cn-orb--speaking .cn-orb__b { animation: none; transition: none; }
@media (prefers-reduced-motion: reduce) {
  .cn-orb, .cn-orb__b, .cn-orb--connecting::after { animation: none !important; transition: none; }
  .cn-orb { transform: none; }
}

/* ── nodes ─────────────────────────────────────────────────────────────── */
.cn-node {
  position: absolute; z-index: 6; transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  background: none; border: none; padding: 0; cursor: pointer;
  font: inherit; color: inherit; text-align: center;
}
.cn-node__badge {
  width: 58px; height: 58px; border-radius: 50%; display: grid; place-items: center;
  background: var(--card); border: 1.5px solid var(--line-2); box-shadow: var(--e2);
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
  position: relative;
}
.cn-node:hover .cn-node__badge { transform: translateY(-2px) scale(1.05); box-shadow: var(--e3); }
.cn-node:focus-visible { outline: none; }
.cn-node:focus-visible .cn-node__badge { box-shadow: var(--focus); }
.cn-node__badge svg { width: 26px; height: 26px; color: var(--muted-2); transition: color .16s ease; }
.cn-node__label { font-size: var(--fs-micro); font-weight: 700; color: var(--muted); white-space: nowrap; }

.cn-node--live .cn-node__badge {
  border-color: var(--node-c, var(--live));
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--node-c, var(--live)) 14%, transparent), var(--e2);
}
.cn-node--live .cn-node__badge svg { color: var(--node-c, var(--live)); }
.cn-node--live .cn-node__label { color: var(--ink); }

.cn-node--connecting .cn-node__badge { border-color: var(--warn-line); box-shadow: 0 0 0 4px var(--warn-soft), var(--e2); }
.cn-node--connecting .cn-node__badge svg { color: var(--warn-bold); }
.cn-node--connecting .cn-node__label { color: var(--warn); }

.cn-node--error .cn-node__badge { border-color: var(--danger-line); box-shadow: 0 0 0 4px var(--danger-soft), var(--e2); }
.cn-node--error .cn-node__badge svg { color: var(--danger); }
.cn-node--error .cn-node__label { color: var(--danger); }

.cn-node--paused .cn-node__badge { border-color: var(--line-2); background: var(--tint-1); }
.cn-node--paused .cn-node__badge svg { color: var(--muted-2); }

.cn-node--add .cn-node__badge { border-style: dashed; background: var(--tint-1); box-shadow: none; }
.cn-node--sel .cn-node__badge { outline: 2px solid var(--ink); outline-offset: 3px; }

.cn-node__dot {
  position: absolute; top: -2px; right: -2px; width: 12px; height: 12px; border-radius: 50%;
  background: var(--warn-bold); border: 2px solid var(--card); display: none;
}
.cn-node--connecting .cn-node__dot, .cn-node--error .cn-node__dot { display: block; }
.cn-node--error .cn-node__dot { background: var(--danger); }

.cn-pulse { position: absolute; width: 7px; height: 7px; border-radius: 50%; pointer-events: none; z-index: 4; }

/* ── status strip ───────────────────────────────────────────────────────── */
.cn-status {
  position: absolute; left: 50%; bottom: 18px; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-8);
  text-align: center; z-index: 6; max-width: min(92%, 560px);
}
.cn-status__name { font-size: var(--fs-lg); font-weight: var(--fw-strong); letter-spacing: -.01em; }
.cn-status__line {
  display: flex; align-items: center; gap: var(--sp-10);
  font-size: var(--fs-sm); color: var(--muted);
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-full);
  padding: 7px var(--sp-16); box-shadow: var(--e2); min-height: 34px;
  max-width: 100%;
}
.cn-status__text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); font-weight: 600; }
.cn-chip {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  font-size: var(--fs-micro); font-weight: 700; color: var(--muted-2); letter-spacing: .04em;
}
.cn-chip i { width: 6px; height: 6px; border-radius: 50%; background: var(--tint-4); }
.cn-chip--on i { background: var(--live); }
.cn-chip--err i { background: var(--danger); }

/* ── side panel ─────────────────────────────────────────────────────────── */
.cn-scrim {
  position: fixed; inset: 0; background: rgba(10, 10, 11, .28);
  opacity: 0; pointer-events: none; transition: opacity .2s; z-index: 55;
}
.cn-scrim--on { opacity: 1; pointer-events: auto; }

.cn-panel {
  position: fixed; top: 0; right: 0; width: 400px; max-width: 100vw; height: 100dvh;
  background: var(--card); border-left: 1px solid var(--line); box-shadow: var(--e4);
  z-index: 60; display: flex; flex-direction: column;
  transform: translateX(105%); transition: transform .26s cubic-bezier(.2, .8, .2, 1);
  visibility: hidden;
}
.cn-panel--on { transform: none; visibility: visible; }
.cn-panel__head { display: flex; align-items: center; gap: var(--sp-12); padding: var(--sp-20); border-bottom: 1px solid var(--line); }
.cn-panel__icon { width: 42px; height: 42px; border-radius: 50%; display: grid; place-items: center; background: var(--tint-2); flex: none; }
.cn-panel__icon svg { width: 22px; height: 22px; }
.cn-panel__title { font-weight: var(--fw-strong); font-size: var(--fs-lg); }
.cn-panel__close {
  margin-left: auto; width: 32px; height: 32px; border-radius: 50%; flex: none;
  border: 1px solid var(--line); background: none; cursor: pointer; color: var(--muted);
  display: grid; place-items: center;
}
.cn-panel__close svg { width: 16px; height: 16px; }
.cn-panel__close:hover { background: var(--tint-2); }
.cn-panel__body { padding: var(--sp-20); overflow-y: auto; display: flex; flex-direction: column; gap: var(--sp-20); }

/* .cn-lab itself is defined once, with the report's section labels below;
   inside the panel it carries the spacing it always had. */
.cn-panel__body .cn-lab { margin-bottom: var(--sp-8); }
.cn-note { color: var(--muted); font-size: var(--fs-sm); margin: 0 0 var(--sp-16); }
/* saved but not working: Meta's own reason is DATA, it wraps inside the panel */
.cn-err { margin: 0 0 var(--sp-12); overflow-wrap: anywhere; line-height: var(--lh-body); }
/* the saved-credentials row comes from screens/channels.js (it owns the row
   and its .ch-saved styles), this wrapper only owns the spacing */
.cn-savedrow { margin: 0 0 var(--sp-12); }
.cn-caps { display: flex; flex-wrap: wrap; gap: 6px; }
.cn-cap {
  display: inline-flex; align-items: center; font-size: var(--fs-micro); font-weight: 700;
  color: var(--ink-2); background: var(--tint-2); border: 1px solid var(--line);
  border-radius: var(--r-full); padding: 4px var(--sp-10);
}
.cn-counts { display: flex; gap: var(--sp-24); }
.cn-count b { display: block; font-size: var(--fs-2xl); font-weight: var(--fw-strong); letter-spacing: -.02em; }
.cn-count span { font-size: var(--fs-micro); color: var(--muted-2); font-weight: 700; }

.cn-togrow { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-12); }
.cn-togrow__label { font-weight: 600; font-size: var(--fs-sm); }
.cn-togrow__hint { font-size: var(--fs-fine); color: var(--muted-2); margin-top: 1px; }

.cn-feed { display: flex; flex-direction: column; }
.cn-feed__item { display: flex; gap: var(--sp-10); padding: var(--sp-10) 0; border-bottom: 1px solid var(--line); font-size: var(--fs-sm); }
.cn-feed__item:last-child { border-bottom: none; }
.cn-feed__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--live); margin-top: 6px; flex: none; }
.cn-feed__time { font-size: var(--fs-micro); color: var(--muted-2); margin-top: 2px; }
.cn-empty { color: var(--muted-2); font-size: var(--fs-sm); }
.cn-acts { display: flex; flex-direction: column; gap: var(--sp-10); margin-top: auto; }
.cn-acts .btn { width: 100%; }

/* ── narrow: the ring stacks, orb on top, nodes in a grid under it ─────── */
@media (max-width: 820px) {
  .cn-stage { height: calc(100dvh - var(--topbar-h) - 150px); min-height: 420px; }
  .cn-orbwrap { width: 32vw; top: 34%; }
  .cn-node__badge { width: 50px; height: 50px; }
  .cn-node__badge svg { width: 22px; height: 22px; }
  .cn-node__label { max-width: 96px; overflow: hidden; text-overflow: ellipsis; }
  .cn-status { bottom: 8px; }
  .cn-panel { width: 100%; }
}
.cn-stage--stack {
  height: auto; min-height: 0; overflow: visible;
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-24);
  padding: var(--sp-16) 0 var(--sp-8);
}
.cn-stage--stack .cn-lines { display: none; }
.cn-stage--stack .cn-orbwrap { order: 1; }
.cn-stage--stack .cn-ring { order: 2; }
.cn-stage--stack .cn-status { order: 3; }
.cn-stage--stack .cn-orbwrap {
  position: relative; left: auto; top: auto; transform: none !important;
  width: 180px; margin: var(--sp-8) auto var(--sp-8);
}
/* stacked: the bubble slot moves right under the orb (canvas.js re-parents it) */
.cn-stage--stack .cn-guideslot { order: 1; padding: 0 var(--sp-8); }
.cn-stage--stack .cn-ring {
  position: static; width: 100%;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-16) var(--sp-8);
}
.cn-stage--stack .cn-node { position: static; transform: none; }
.cn-stage--stack .cn-node__label { max-width: 100%; white-space: normal; overflow: visible; line-height: 1.25; }
.cn-stage--stack .cn-status { position: static; transform: none; max-width: 100%; width: 100%; }
.cn-node__badge--ping { animation: cn-ping .9s ease-out; }
@keyframes cn-ping {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--node-c, var(--live)) 45%, transparent), var(--e2); }
  100% { box-shadow: 0 0 0 14px transparent, var(--e2); }
}
@media (prefers-reduced-motion: reduce) {
  .cn-panel { transition: none; }
  .cn-node__badge { transition: none; }
  .cn-p--draw { animation: none; }
  .cn-halo--pulse { animation: none; }
}

/* ── the call control under the status line (2026-09-04): one small talk
      button, replaced by a red hang-up button while the line is open, and one
      sentence when a call could not start ── */
/* the progress caption and the call control share one row, so the block
   stays as tall as before and the ring's bottom nodes keep their place */
.cn-status__row { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: var(--sp-8) var(--sp-16); max-width: 100%; }
.cn-call { display: inline-flex; align-items: center; }
.cn-call__go, .cn-call__hang { display: inline-flex; align-items: center; gap: 7px; }
.cn-call__go svg, .cn-call__hang svg { width: 15px; height: 15px; fill: currentColor; flex: none; }
.cn-call__hang { background: var(--danger); border-color: var(--danger); color: var(--danger-ink); }
.cn-call__hang:hover { background: var(--danger-hover); border-color: var(--danger-hover); color: var(--danger-ink); }
.cn-call__note { margin: 0; font-size: var(--fs-hint); color: var(--danger); text-align: center; max-width: 100%; line-height: var(--lh-body); }

/* ── one action per node (2026-09-04): progress line, retry, the reward loop ── */
/* "N / 8 არხი ცოცხალია" under the status line */
.cn-status__prog { font-size: var(--fs-micro); font-weight: 700; color: var(--muted-2); letter-spacing: .04em; }
.cn-status__prog--all { color: var(--ok); }   /* --live is 2.01:1: surface only, never text */
/* the load-failure retry sits inside the status capsule */
.cn-retry { flex: none; }
/* a curve that draws itself in once the node goes live (pathLength="1" on the path) */
.cn-p--draw { stroke-dashoffset: 0; animation: cn-draw 1.1s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes cn-draw {
  0% { stroke-dashoffset: 1; opacity: .4; }
  70% { opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: .9; }
}
/* the orb's halo swells once, the class is dropped on animationend */
.cn-halo--pulse { animation: cn-halo-pulse 1.2s ease-out 1; }
@keyframes cn-halo-pulse {
  0% { transform: scale(1); opacity: 1; }
  45% { transform: scale(1.28); opacity: 1; filter: blur(4px); }
  100% { transform: scale(1); opacity: 1; filter: blur(6px); }
}

/* ── phase 2: the node panel's "აქტივობა | პოსტები | კომენტარები" tabs ──── */
.cn-tabs { align-self: flex-start; max-width: 100%; overflow-x: auto; flex-wrap: nowrap; }
.cn-tabs::-webkit-scrollbar { display: none; }
.cn-tabs > button { white-space: nowrap; }
.cn-pane { display: flex; flex-direction: column; gap: var(--sp-12); min-width: 0; }
.cn-pane .ps-list { gap: var(--sp-10); }
.cn-pane .ps-item__acts .btn,
.cn-pane .ps-cm__acts .btn { flex: 1 1 auto; }
.cn-pane__new, .cn-pane__all { align-self: stretch; }

/* Viber sells its bots: the price disclaimer sits above the connect button */
.cn-paid { margin: 0 0 var(--sp-16); padding: var(--sp-12) var(--sp-14); border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--card-2); }
.cn-paid p { margin: 0; font-size: var(--fs-hint); font-weight: 500; color: var(--muted); line-height: var(--lh-body); }
.cn-paid p + p { margin-top: var(--sp-6); color: var(--muted-2); }
.cn-paid__a { display: inline-block; margin-top: var(--sp-10); font-size: var(--fs-hint); font-weight: 700; color: var(--ink); }

/* ── one-button Meta: the connect control comes from screens/channels.js
      (.ch-fbw, it owns those styles), the panel only sizes and spaces it ── */
.cn-panel__body > .ch-fbw { margin-top: var(--sp-4); }
.cn-panel__body > .ch-fbw .btn { width: 100%; }
/* „ძველი კავშირი" on a live node, the same capsule the card shows */
.cn-panel__body .ch-card__legacy { margin: calc(-1 * var(--sp-8)) 0 0; }

/* ── products and features on a node (2026-09-05) ──────────────────────────
   The page node carries the Posting and Ads switches, a chat node and the
   phone node show the product they run under. One item per line: name, state,
   price, the quota meter, what it includes. No new colours: the state reads
   from the shared .pill, the meter from the shared .bar. */
.cn-ent{display:flex;flex-direction:column;gap:var(--sp-12)}
.cn-panel__body .cn-ent__lab{margin-bottom:0}
.cn-ent__item{
  border:1px solid var(--line);border-radius:var(--r-card);
  padding:var(--sp-14) var(--sp-16);background:var(--card);
  display:flex;flex-direction:column;gap:var(--sp-8);
}
.cn-ent__item[data-st="off"]{background:var(--card-2)}
.cn-ent__head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-12)}
.cn-ent__id{display:flex;align-items:center;gap:var(--sp-8);min-width:0}
.cn-ent__name{font-weight:700;font-size:var(--fs-base)}
.cn-ent__ctl{flex:none}
.cn-ent__price{font-size:var(--fs-sm);color:var(--muted);margin-top:calc(var(--sp-8) * -1)}
.cn-ent__note{margin:0;font-size:var(--fs-fine);color:var(--muted)}
.cn-ent__note--warn{color:var(--warn)}
.cn-ent__meter{display:flex;flex-direction:column;gap:var(--sp-6)}
.cn-ent__used{font-size:var(--fs-micro);color:var(--muted-2)}
.cn-ent__what .cn-lab{margin-bottom:var(--sp-6)}
.cn-ent__feats{list-style:none;margin:0;padding:0;display:grid;gap:var(--sp-6)}
.cn-ent__feats li{
  position:relative;padding-left:var(--sp-16);
  font-size:var(--fs-fine);color:var(--muted);line-height:var(--lh-body);
}
.cn-ent__feats li::before{
  content:"";position:absolute;left:0;top:.55em;
  width:6px;height:6px;border-radius:var(--r-circle);background:var(--tint-4);
}
.cn-ent__item[data-st="on"] .cn-ent__feats li::before,
.cn-ent__item[data-st="trial"] .cn-ent__feats li::before{background:var(--live)}
.cn-ent__more{align-self:flex-start}

/* the trust ladder card on a page node's panel (screens/trust.css owns the
   card itself; this is only the slot it sits in) */
.cn-trust{margin:0 0 var(--sp-14)}
.cn-trust .tr-card{padding:var(--sp-12)}


/* ═══ 2. THE SHIFT REPORT ═════════════════════════════════════════════════ */

/* ── the three figures the masthead used to carry ─────────────────────────
   .sh-fig is not reused: its caption colour (--on-rail-2) only has its
   contrast on the dark band, and the band is gone from this screen. */
.cn-figs {
  display: flex; flex-wrap: wrap; gap: var(--sp-24) var(--sp-40);
  padding-bottom: var(--sp-16); border-bottom: 1px solid var(--line);
}
.cn-fig { display: flex; flex-direction: column; gap: var(--sp-4); min-width: 0; }
.cn-fig__n {
  font-size: var(--fs-3xl); font-weight: var(--fw-strong); line-height: 1;
  letter-spacing: -.02em;
}
.cn-fig__c { font-size: var(--fs-micro); font-weight: 600; color: var(--muted-2); }   /* 4.83:1 */
/* the same figure over seven days, so a true zero today never stands alone.
   Hidden when it is itself zero: two zeros are worse than one. */
.cn-fig__wk { font-size: var(--fs-micro); color: var(--muted-2); opacity: .82; }
.cn-fig__wk:empty { display: none; }
@media (max-width: 760px) {
  .cn-figs { gap: var(--sp-20) var(--sp-24); }
  .cn-fig__n { font-size: var(--fs-2xl); }
}

/* ── the phone lane, the upsell, never the headline ─────────────────────── */
.cn-phone {
  display: flex; align-items: center; gap: var(--sp-24) var(--sp-32); flex-wrap: wrap;
  margin-top: calc(var(--sp-sec) * -1 + var(--sp-16));   /* it belongs to the figures above it */
  padding: var(--sp-12) var(--sp-16);
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-lg);
}
.cn-phone__id { display: flex; align-items: center; gap: var(--sp-10); flex: none; }
.cn-phone__mk { display: flex; flex: none; }
.cn-phone__lab { font-size: var(--fs-btn); font-weight: var(--fw-strong); }
.cn-phone__ms { display: flex; gap: var(--sp-32); flex-wrap: wrap; margin-left: auto; }
.cn-phone__m { display: flex; align-items: baseline; gap: var(--sp-8); }
.cn-phone__m b { font-size: var(--fs-lg); font-weight: var(--fw-strong); letter-spacing: -.01em; }
.cn-phone__m span { font-size: var(--fs-micro); font-weight: 600; color: var(--muted-2); }   /* 4.83:1 */

/* ── a section: a 12px cased label over a hairline, and nothing else ───────
   Hierarchy from size, case and rule. No card wrapper, no second heading. */
.cn-sec { display: flex; flex-direction: column; }
.cn-sec__head {
  display: flex; align-items: center; gap: var(--sp-10);
  padding-bottom: var(--sp-10); margin-bottom: var(--sp-6);
  border-bottom: 1px solid var(--line);
}
.cn-lab {
  font-size: var(--fs-micro); font-weight: var(--fw-strong);
  color: var(--muted-2); letter-spacing: .06em;   /* .up adds the case feature */
}
h2.cn-lab { line-height: 1.3; }
.cn-sec__act {
  margin-left: auto; flex: none;
  font-size: var(--fs-btn); font-weight: 600; color: var(--muted);
  transition: color var(--t);
}
.cn-sec__act:hover { color: var(--ink); }
.cn-sec__act:focus-visible { outline: none; box-shadow: var(--focus); border-radius: var(--r-sm); }

/* the count beside NEEDS YOU. --attn is the one colour that means "a person
   is blocked", the same grade the nav badge wears. White on it: 5.74:1. */
.cn-qn {
  min-width: 19px; height: 19px; padding: 0 6px; border-radius: var(--r-full);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--attn); color: var(--attn-ink);
  font-size: var(--fs-micro); font-weight: var(--fw-strong); line-height: 1;
}

/* ── the attention queue ─────────────────────────────────────────────────── */
.cn-q__list { display: flex; flex-direction: column; }
.cn-q {
  display: grid; grid-template-columns: 22px minmax(0, 1fr) auto;
  align-items: center; gap: var(--sp-12);
  min-height: 56px; padding: var(--sp-10) var(--sp-12);
  border-bottom: 1px solid var(--line); border-radius: var(--r-md);
  transition: background var(--t);
}
.cn-q:last-child { border-bottom: 0; }
.cn-q:hover { background: var(--card-2); }
.cn-q:focus-visible { outline: none; box-shadow: var(--focus); }
.cn-q__mk { display: flex; }
.cn-q__tx { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.cn-q__tx b { font-size: var(--fs-row); font-weight: 600; }
.cn-q__tx span {
  font-size: var(--fs-fine); color: var(--muted);   /* 6.7:1 */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cn-q__t { flex: none; font-size: var(--fs-micro); font-weight: 600; color: var(--muted-2); }

/* the empty state is ONE line, never a zero and never an illustration */
.cn-q__none {
  display: flex; align-items: center; min-height: 48px;
  margin: 0; padding: 0 var(--sp-12);
  font-size: var(--fs-base); font-weight: 500; color: var(--muted);
}
/* the skeleton, while three network calls land */
.cn-q--skel { pointer-events: none; }
.cn-q__sk1 { width: 22px; height: 22px; border-radius: var(--r-sm); }
.cn-q__sk2 { height: 11px; border-radius: var(--r-sm); }
.cn-q__sk3 { width: 42px; height: 11px; border-radius: var(--r-sm); }
.cn-q--skel:nth-child(2) .cn-q__sk2 { width: 74%; }
.cn-q--skel:nth-child(3) .cn-q__sk2 { width: 56%; }

/* ── the two columns under the queue ─────────────────────────────────────── */
.cn-cols {
  display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: var(--sp-grid) var(--sp-sec); align-items: start;
}
.cn-col { display: flex; flex-direction: column; gap: var(--sp-grid); min-width: 0; }

/* ── the last 7 days ─────────────────────────────────────────────────────── */
.cn-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-grid); }
.cn-tile {
  display: flex; flex-direction: column; gap: var(--sp-4);
  padding: var(--sp-14) var(--sp-16) var(--sp-10);
  min-width: 0;
}
/* one step under the report's own figures: those are the headline, these
   are the shape of the week behind it */
.cn-tile__n { font-size: var(--fs-2xl); font-weight: var(--fw-strong); line-height: 1; letter-spacing: -.02em; }
.cn-tile__c {
  font-size: var(--fs-micro); font-weight: 600; color: var(--muted-2);
  line-height: 1.35; min-height: calc(1.35em * 2);
}
/* the sparkline is a meaning-carrying graphical object, so it needs 3:1 and
   --live (2.01:1) is illegal here. --ok is 5.4:1 on the card. */
.cn-spark { width: 100%; height: 26px; margin-top: var(--sp-8); color: var(--ok); }
/* nothing happened in seven days: the tile keeps the sparkline's height so the
   row stays level, and draws no line at all rather than a flat green rule */
.cn-tile--flat { padding-bottom: calc(var(--sp-10) + 26px + var(--sp-8)); }

/* ── quota, on the surface and readable ──────────────────────────────────── */
.cn-quota { display: flex; flex-direction: column; }
.cn-quota__top { display: flex; align-items: center; gap: var(--sp-10); }
.cn-quota__n {
  font-size: var(--fs-2xl); font-weight: var(--fw-strong); letter-spacing: -.02em;
  margin: var(--sp-8) 0 var(--sp-12);
}
.cn-quota__foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-12); margin-top: var(--sp-10);
}
.cn-quota__up {
  display: inline-flex; align-items: center; gap: 3px; flex: none;
  font-size: var(--fs-btn); font-weight: 600; color: var(--ink);
}
.cn-quota__up:hover { color: var(--muted); }
.cn-quota__up:focus-visible { outline: none; box-shadow: var(--focus); border-radius: var(--r-sm); }
.cn-quota__up .sh-ic { width: 14px; height: 14px; }

/* ── today's schedule ────────────────────────────────────────────────────── */
.cn-ev__list { display: flex; flex-direction: column; }
.cn-ev {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: var(--sp-12);
  min-height: 50px; padding: var(--sp-8) var(--sp-4);
  border-bottom: 1px solid var(--line);
}
.cn-ev:last-child { border-bottom: 0; }
.cn-ev__t { font-size: var(--fs-sm); font-weight: var(--fw-strong); flex: none; }
.cn-ev__b { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.cn-ev__b b { font-size: var(--fs-sm); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cn-ev__b span { font-size: var(--fs-micro); color: var(--muted-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cn-ev__p { flex: none; font-size: var(--fs-sm); font-weight: 600; color: var(--muted); }
/* the two that sit on top of each other, named for the first time */
.cn-ev--clash .cn-ev__t { color: var(--warn); }          /* 5.1:1 on white */
.cn-clash { margin: 0 0 var(--sp-10); }
.cn-none { margin: 0; padding: var(--sp-12) var(--sp-4); font-size: var(--fs-sm); color: var(--muted); }

/* ── narrow ──────────────────────────────────────────────────────────────── */
@media (max-width: 1000px) {
  .cn-cols { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 640px) {
  .cn-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-8); }
  .cn-tile { padding: var(--sp-12); }
  .cn-tile__n { font-size: var(--fs-2xl); }
  .cn-phone { margin-top: calc(var(--sp-sec) * -1 + var(--sp-12)); }
  .cn-phone__ms { margin-left: 0; gap: var(--sp-20); width: 100%; }
  .cn-q { grid-template-columns: 22px minmax(0, 1fr); }
  .cn-q__t { grid-column: 2; }
}
@media (prefers-reduced-motion: reduce) {
  .cn-q { transition: none; }
}
