/* ==========================================================================
   Bento dashboard — app/views/crm_dashboard/_bento.html.erb
   --------------------------------------------------------------------------
   Everything here is prefixed .icb- and used by one template. Nothing else in
   the app can pick these up by accident, which is the point: the classic
   board has to keep rendering exactly as it did when DASHBOARD_CLASSIC=true
   sends it back (see DashboardDesign).

   Colours resolve through the --t-* tokens with their literal as the var()
   fallback, the same contract as the rest of public/*.css: the tokens are
   only defined under [data-theme="dark"], so light renders the fallback
   byte for byte and dark arrives for free.

   Raw-served from public/, so no sprockets and no precompile step. It is
   loaded from the layout alongside ic-theme.css and splynx-ui.css.
   ========================================================================== */

/* ---------- page furniture ------------------------------------------------ */
.icb-live { display: inline-flex; align-items: center; gap: 7px; }

.icb-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--t-success-text, #27ae60);
  box-shadow: 0 0 0 0 rgba(63, 190, 118, 0.55);
  animation: icb-pulse 2.6s infinite;
}
@keyframes icb-pulse {
  70%  { box-shadow: 0 0 0 7px rgba(63, 190, 118, 0); }
  100% { box-shadow: 0 0 0 0 rgba(63, 190, 118, 0); }
}
/* A blinking dot is decoration, and for some people it is worse than that. */
@media (prefers-reduced-motion: reduce) {
  .icb-dot { animation: none; }
}

.icb-pills { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 16px; }
.icb-pills a {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 14px; border-radius: 999px;
  background: var(--t-surface, #fff);
  border: 1px solid var(--t-line, #e2e8f0);
  color: var(--t-ink-2, #334155);
  font-size: 12.5px; font-weight: 600;
}
.icb-pills a i { color: var(--t-tint-purple-ink, #7b3fa8); }
.icb-pills a:hover {
  border-color: var(--t-brand, #5b2c86);
  color: var(--t-brand-text, #5b2c86);
  text-decoration: none;
}

/* ---------- the V2.0 switch ------------------------------------------------
   Deliberately the same control as .ic-theme-toggle in the header: same pill,
   same is-on treatment. It is the same kind of decision, and a second visual
   language for it would just be a second thing to learn.

   Anchors, not buttons -- no JavaScript, survives a bookmark, and the
   controller turns the ?design= into a cookie. Lives here rather than in
   ic-theme.css because it belongs to the dashboard, but it renders on BOTH
   boards, which is why this stylesheet loads for every page.
   -------------------------------------------------------------------------- */
.icb-vtoggle {
  margin-left: auto;
  display: inline-flex;
  border: 1px solid var(--t-line, #d8dee8);
  border-radius: 999px;
  overflow: hidden;
  background: var(--t-surface, #fff);
  flex: 0 0 auto;
}
.icb-vtoggle a {
  padding: 6px 14px;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--t-muted, #5b6b7c);
  white-space: nowrap;
}
.icb-vtoggle a + a { border-left: 1px solid var(--t-line, #d8dee8); }
.icb-vtoggle a:hover {
  background: var(--t-surface-2, #f7f9fc);
  color: var(--t-ink, #1b2433);
  text-decoration: none;
}
.icb-vtoggle a.is-on {
  background: var(--t-brand, #5b2c86);
  color: #fff;
}
.icb-vtoggle a:focus-visible {
  outline: 2px solid var(--t-accent, #2f80ed);
  outline-offset: -2px;
}
@media print { .icb-vtoggle { display: none; } }

/* ---------- the grid ------------------------------------------------------- */
.icb-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
}
.icb-w2 { grid-column: span 2; }
.icb-h2 { grid-row: span 2; }

@media (max-width: 1280px) {
  .icb-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .icb-grid { grid-template-columns: minmax(0, 1fr); }
  .icb-w2, .icb-h2 { grid-column: span 1; grid-row: span 1; }
}

/* A box is a div in some places and an <a> in others, so it has to carry the
   link reset itself rather than relying on being one or the other. */
.icb-box {
  position: relative;
  overflow: hidden;
  /* A column, so the hero's bottom strip can be pushed to the card's floor by
     margin-top:auto and the chart can take the slack above it. Without this
     the h2 hero was a tall card with its footer stranded in the middle. */
  display: flex;
  flex-direction: column;
  padding: 16px 18px;
  border-radius: 16px;
  border: 1px solid var(--t-line, #e2e8f0);
  background: var(--t-surface, #fff);
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.06), 0 1px 3px rgba(16, 24, 40, 0.10);
  color: var(--t-ink, #2c3340);
}
a.icb-box:hover { text-decoration: none; color: var(--t-ink, #2c3340); }
a.icb-box:hover, .icb-box:hover {
  border-color: var(--t-line, #cbd5e1);
  box-shadow: 0 6px 22px rgba(16, 24, 40, 0.10);
}
:root[data-theme="dark"] .icb-box {
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}
:root[data-theme="dark"] .icb-box:hover {
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.45);
}

/* The wash in the corner. Purely decorative, and the only thing that carries
   the per-card accent besides the icon. */
.icb-glow {
  position: absolute; top: -96px; right: -58px;
  width: 210px; height: 210px; border-radius: 50%;
  filter: blur(58px); opacity: 0.22; pointer-events: none;
}
.icb-accent-green  .icb-glow { background: var(--t-success-text, #27ae60); }
.icb-accent-amber  .icb-glow { background: var(--t-tint-amber-ink, #e67e22); }
.icb-accent-red    .icb-glow { background: var(--t-danger-text, #c0392b); }
.icb-accent-blue   .icb-glow { background: var(--t-accent-text, #2f80ed); }
.icb-accent-purple .icb-glow { background: var(--t-tint-purple-ink, #8e44ad); }

.icb-accent-green  .icb-label i:first-child { color: var(--t-success-text, #27ae60); }
.icb-accent-amber  .icb-label i:first-child { color: var(--t-tint-amber-ink, #e67e22); }
.icb-accent-red    .icb-label i:first-child { color: var(--t-danger-text, #c0392b); }
.icb-accent-blue   .icb-label i:first-child { color: var(--t-accent-text, #2f80ed); }
.icb-accent-purple .icb-label i:first-child { color: var(--t-tint-purple-ink, #8e44ad); }

/* ---------- inside a box --------------------------------------------------- */
.icb-label {
  position: relative; z-index: 1;
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; font-weight: 700; letter-spacing: 0.3px;
  color: var(--t-muted, #6b7789);
  text-transform: uppercase;
}
.icb-more {
  margin-left: auto;
  font-size: 11.5px; font-weight: 600; text-transform: none; letter-spacing: 0;
  color: var(--t-link, #1d6fa5);
}

.icb-value {
  position: relative; z-index: 1;
  display: block;
  margin: 8px 0 0;
  font-size: 38px; line-height: 1.08; font-weight: 700;
  letter-spacing: -1.2px;
  font-variant-numeric: tabular-nums;
  color: var(--t-ink, #2c3340);
}
a.icb-value:hover { text-decoration: none; }
.icb-value-sm { font-size: 30px; letter-spacing: -0.8px; }

.icb-ink-green { color: var(--t-success-text, #27ae60); }
.icb-ink-amber { color: var(--t-tint-amber-ink, #e67e22); }
.icb-ink-blue  { color: var(--t-accent-text, #2f80ed); }
.icb-ink-red   { color: var(--t-danger-text, #c0392b); }
a.icb-ink-green:hover { color: var(--t-success-text, #27ae60); }
a.icb-ink-blue:hover  { color: var(--t-accent-text, #2f80ed); }

.icb-meta {
  position: relative; z-index: 1;
  margin-top: 3px;
  font-size: 12.5px;
  color: var(--t-muted, #6b7789);
}
.icb-meta b { color: var(--t-ink-2, #334155); }
.icb-centre { text-align: center; }
.icb-stale { color: var(--t-faint, #8895a7); }

.icb-chip {
  display: inline-flex; align-items: center;
  padding: 2px 9px; border-radius: 999px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.2px;
  text-transform: none;
  background: var(--t-tint-slate, #f3f7fb);
  color: var(--t-tint-slate-ink, #5b6472);
}
.icb-chip-count {
  background: var(--t-tint-red, #fdeeee);
  color: var(--t-tint-red-ink, #b42318);
}

.icb-empty {
  margin-top: 12px;
  font-size: 13px;
  color: var(--t-muted, #6b7789);
}
.icb-empty i { color: var(--t-success-text, #27ae60); margin-right: 6px; }

.icb-footnote {
  margin-top: 10px;
  font-size: 11.5px;
  color: var(--t-faint, #8895a7);
}
/* Every other anchor on the board is styled by the block it sits in; this one
   was not, and fell through to the browser default -- which on a dark card is
   an unreadable maroon. Caught by rendering the real template. */
.icb-footnote a { color: var(--t-link, #1d6fa5); font-weight: 600; }

/* ---------- the 24-hour line ------------------------------------------------ */
/* preserveAspectRatio="none" on the viewBox means this stretches to whatever
   height the flex row leaves it, which is how the hero fills its two rows.
   The stroke stays 2.4px through it -- see vector-effect below. */
.icb-chart { display: block; width: 100%; flex: 1 1 auto; min-height: 120px; margin-top: 14px; }
.icb-chart-grid line { stroke: currentColor; stroke-width: 1; opacity: 0.12; }
.icb-chart-line {
  fill: none;
  stroke: var(--t-success-text, #27ae60);
  stroke-width: 2.4;
  stroke-linejoin: round;
  stroke-linecap: round;
  /* preserveAspectRatio="none" stretches the x axis, which would stretch the
     stroke with it and leave a line that is thick at one end. */
  vector-effect: non-scaling-stroke;
}
.icb-chart-area { fill: var(--t-success-text, #27ae60); opacity: 0.14; stroke: none; }
.icb-chart-head { fill: var(--t-success-text, #27ae60); }

.icb-axis {
  display: flex; justify-content: space-between; gap: 10px;
  margin-top: 4px;
  font-size: 11px;
  color: var(--t-faint, #8895a7);
}
.icb-axis-scale { text-align: center; }

.icb-chart-empty {
  margin: 18px 0;
  padding: 18px 14px;
  border: 1px dashed var(--t-line, #e2e8f0);
  border-radius: 10px;
  text-align: center;
  font-size: 12.5px;
  color: var(--t-faint, #8895a7);
}
.icb-chart-empty i { display: block; font-size: 18px; margin-bottom: 6px; opacity: 0.7; }

/* The hero's bottom strip. Sits flush with the card edge, so it needs the
   card's own padding cancelled out. */
.icb-foot {
  position: relative; z-index: 1;
  display: flex; align-items: center; gap: 8px;
  margin: 14px -18px -16px;
  padding: 11px 18px;
  border-top: 1px solid var(--t-line-soft, #eef2f6);
  background: var(--t-surface-2, #f6f8fb);
  font-size: 12.5px;
  color: var(--t-ink-2, #334155);
}
a.icb-foot:hover { text-decoration: none; color: var(--t-ink-2, #334155); }
.icb-foot i:first-child { color: var(--t-faint, #8895a7); }
.icb-foot-warn i:first-child { color: var(--t-tint-amber-ink, #e67e22); }
.icb-foot-warn b { color: var(--t-tint-amber-ink, #e67e22); }
.icb-foot-go { margin-left: auto; font-weight: 600; color: var(--t-link, #1d6fa5); white-space: nowrap; }

/* ---------- gauge ----------------------------------------------------------- */
.icb-gauge { display: block; width: 100%; max-width: 230px; height: auto; margin: 6px auto 0; }
.icb-gauge-track { fill: none; stroke: currentColor; opacity: 0.13; stroke-width: 16; stroke-linecap: round; }
.icb-gauge-fill  { fill: none; stroke-width: 16; stroke-linecap: round; }
.icb-accent-green .icb-gauge-fill { stroke: var(--t-success-text, #27ae60); }
.icb-accent-amber .icb-gauge-fill { stroke: var(--t-tint-amber-ink, #e67e22); }
.icb-accent-red   .icb-gauge-fill { stroke: var(--t-danger-text, #c0392b); }
.icb-gauge-value {
  fill: var(--t-ink, #2c3340);
  font-size: 30px; font-weight: 700;
  font-family: inherit;
}
.icb-gauge-cap { fill: var(--t-muted, #6b7789); font-size: 11px; font-family: inherit; }

/* ---------- donut ------------------------------------------------------------ */
.icb-donut { display: block; width: 130px; height: 130px; margin: 10px auto 0; }
.icb-donut-track { fill: none; stroke: currentColor; opacity: 0.10; stroke-width: 15; }
.icb-donut-seg { fill: none; stroke-width: 15; }
.icb-donut-value { fill: var(--t-ink, #2c3340); font-size: 27px; font-weight: 700; font-family: inherit; }
.icb-donut-cap { fill: var(--t-muted, #6b7789); font-size: 10px; font-family: inherit; }

/* Ticket statuses keep the colours the ticket list already gives them, so a
   colour means the same thing on both screens. waiting_agent is the one
   exception: splynx-ui paints it and waiting_customer the same purple, which
   two neighbouring arcs of one ring cannot be, so it takes the lighter of the
   two brand purples. */
.icb-seg-new                 { stroke: var(--t-accent-text, #2f80ed); }
.icb-seg-work-in-progress    { stroke: var(--t-tint-amber-ink, #e67e22); }
.icb-seg-waiting-customer    { stroke: var(--t-tint-purple-ink, #8e44ad); }
.icb-seg-waiting-agent       { stroke: var(--t-brand-2, #9b59b6); }
.icb-seg-process-cancellation{ stroke: var(--t-faint, #8895a7); }
.icb-seg-resolved            { stroke: var(--t-success-text, #27ae60); }

/* ---------- stacked bars + legends -------------------------------------------- */
.icb-stack {
  position: relative; z-index: 1;
  display: flex;
  height: 11px;
  margin-top: 14px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--t-surface-3, #eef1f6);
}
.icb-stack > i { display: block; height: 100%; }

.icb-legend {
  position: relative; z-index: 1;
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  margin-top: 12px;
  font-size: 12px;
  color: var(--t-muted, #6b7789);
}
.icb-legend a, .icb-legend span { display: inline-flex; align-items: center; color: var(--t-muted, #6b7789); }
.icb-legend a:hover { color: var(--t-ink, #2c3340); text-decoration: none; }
.icb-legend b { margin-left: 5px; color: var(--t-ink-2, #334155); font-variant-numeric: tabular-nums; }

.icb-swatch {
  width: 9px; height: 9px; border-radius: 3px;
  margin-right: 6px; flex: 0 0 9px;
}
/* The donut classes set stroke, which a swatch <i> cannot use. */
.icb-swatch.icb-seg-new                  { background: var(--t-accent-text, #2f80ed); }
.icb-swatch.icb-seg-work-in-progress     { background: var(--t-tint-amber-ink, #e67e22); }
.icb-swatch.icb-seg-waiting-customer     { background: var(--t-tint-purple-ink, #8e44ad); }
.icb-swatch.icb-seg-waiting-agent        { background: var(--t-brand-2, #9b59b6); }
.icb-swatch.icb-seg-process-cancellation { background: var(--t-faint, #8895a7); }
.icb-swatch.icb-seg-resolved             { background: var(--t-success-text, #27ae60); }

.icb-fill-green  { background: var(--t-success-text, #27ae60); }
.icb-fill-blue   { background: var(--t-accent-text, #2f80ed); }
.icb-fill-purple { background: var(--t-tint-purple-ink, #8e44ad); }
.icb-fill-red    { background: var(--t-danger-text, #c0392b); }

.icb-quote-new       { background: var(--t-tint-amber-ink, #e67e22); }
.icb-quote-sent      { background: var(--t-accent-text, #2f80ed); }
.icb-quote-on-review { background: var(--t-tint-blue-ink, #1d6fa5); }
.icb-quote-accepted  { background: var(--t-success-text, #27ae60); }
.icb-quote-denied    { background: var(--t-danger-text, #c0392b); }

/* ---------- lead funnel ---------------------------------------------------------- */
.icb-funnel { position: relative; z-index: 1; display: grid; gap: 5px; margin-top: 14px; }
.icb-step {
  display: grid;
  grid-template-columns: minmax(120px, 210px) minmax(0, 1fr) 36px;
  align-items: center; gap: 12px;
  font-size: 12.5px;
  color: var(--t-ink-2, #334155);
}
.icb-step:hover { text-decoration: none; color: var(--t-ink, #2c3340); }
.icb-step-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.icb-step-bar {
  height: 20px; border-radius: 5px;
  background: var(--t-surface-3, #eef1f6);
  overflow: hidden;
}
.icb-step-bar i {
  display: block; height: 100%; border-radius: 5px;
  background: linear-gradient(90deg, var(--t-brand, #5b2c86), var(--t-tint-purple-ink, #8e44ad));
}
.icb-step-n { text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; }
/* An empty stage still has to be on the page -- a funnel that hides its gaps
   is a funnel that cannot show you where leads are stalling. */
.icb-step-empty, .icb-step-empty .icb-step-n { color: var(--t-faint, #8895a7); }

/* ---------- needs attention -------------------------------------------------------- */
.icb-attn { position: relative; z-index: 1; list-style: none; margin: 10px 0 0; padding: 0; }
.icb-attn li {
  display: flex; align-items: center; gap: 11px;
  padding: 8px 0;
  border-top: 1px solid var(--t-line-soft, #eef2f6);
  font-size: 13px;
}
.icb-attn li:first-child { border-top: 0; padding-top: 2px; }
.icb-attn-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 8px; }
.icb-attn-bad   { background: var(--t-danger-text, #c0392b); }
.icb-attn-warn  { background: var(--t-tint-amber-ink, #e67e22); }
.icb-attn-info  { background: var(--t-accent-text, #2f80ed); }
.icb-attn-muted { background: var(--t-faint, #8895a7); }
.icb-attn-text { min-width: 0; flex: 1; }
.icb-attn-text b { display: block; font-weight: 600; color: var(--t-ink, #2c3340); }
.icb-attn-text span { font-size: 11.5px; color: var(--t-muted, #6b7789); }
.icb-attn-go {
  margin-left: auto; white-space: nowrap;
  font-size: 12px; font-weight: 600;
  padding: 4px 11px; border-radius: 7px;
  border: 1px solid var(--t-line, #e2e8f0);
  background: var(--t-surface-2, #f6f8fb);
  color: var(--t-ink-2, #334155);
}
.icb-attn-go:hover {
  border-color: var(--t-brand, #5b2c86);
  color: var(--t-brand-text, #5b2c86);
  text-decoration: none;
}

/* ---------- activity ----------------------------------------------------------------- */
.icb-activity { list-style: none; margin: 10px 0 0; padding: 0; }
.icb-activity li {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 8px 0;
  border-top: 1px solid var(--t-line-soft, #eef2f6);
  font-size: 13px;
}
.icb-activity li:first-child { border-top: 0; padding-top: 2px; }
.icb-activity li > div { min-width: 0; }
.icb-activity a { color: var(--t-ink, #2c3340); font-weight: 600; }
.icb-activity a:hover { color: var(--t-link, #1d6fa5); }
.icb-sub { display: block; font-size: 11px; color: var(--t-faint, #8895a7); }

/* Invoices and anything going to a printer stay on paper. The washes and the
   dark card fills are screen-only. */
@media print {
  .icb-glow, .icb-pills { display: none; }
  .icb-box { box-shadow: none; break-inside: avoid; }
}
