/* ══════════════════════════════════════════════════════════════════════════════
   vb-kpi.css — THE single shared KPI/summary card component for all of ViyaBook.
   ----------------------------------------------------------------------------
   Master reference: the Dashboard KPI cards (.vbd-card in assets/css/dashboard.css).
   Every visual value below (radius, padding, icon size, gradients, shadows) is
   taken directly from that spec, not approximated - so a card built with these
   classes is visually identical to Dashboard, not just "close."

   Usage (see any page migrating onto this system):
     <div class="vb-kpi-grid">
       <div class="vb-kpi-card vb-kpi-blue">
         <div class="vb-kpi-top">
           <span class="vb-kpi-label">Revenue</span>
           <span class="vb-kpi-icon"><i class="ti ti-currency-dollar"></i></span>
         </div>
         <div class="vb-kpi-value">
           <span class="vb-kpi-currency">MVR</span>
           <span class="vb-kpi-number">12,530.52</span>
         </div>
         <div class="vb-kpi-footer">Collected &amp; due</div>
       </div>
     </div>

   IMPORTANT - styles/design-system.css ALSO ships an older `.vb-kpi-card`
   definition (its own "GLOBAL KPI CARD COMPONENT", with a couple of properties
   forced via a shared `!important` "unified card surface" rule) and it loads
   before OR after this file depending on the page. Every visual property here
   therefore carries `!important` too, and the one property design-system.css
   forces on its own (border-radius) is overridden with a 3-class-specificity
   selector so it wins regardless of link order. Do not hand-edit per-page KPI
   CSS after migrating - fix it here so every page stays in sync automatically.
   ══════════════════════════════════════════════════════════════════════════════ */

.vb-kpi-grid {
  display: grid !important;
  grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
  gap: 16px !important;
  width: 100% !important;
  min-width: 0 !important;
  align-items: stretch !important;
  /* Card ORDER within the row stays identical to English too - the Dashboard
     "master reference" layout (Revenue, Outstanding, Expenses, Profit, left to
     right) shouldn't reverse just because the page is in Dhivehi. */
  direction: ltr !important;
}
.vb-kpi-grid > * { min-width: 0 !important; }

.vb-kpi-card {
  position: relative !important;
  display: flex !important;
  flex-direction: column !important;
  justify-content: space-between !important;
  width: 100% !important;
  min-width: 0 !important;
  min-height: 180px !important;
  padding: 24px !important;
  box-sizing: border-box !important;
  overflow: hidden !important;
  background: #fff !important;
  border: 1px solid #dbe4ef !important;
  box-shadow: 0 1px 2px rgba(13,27,47,.05), 0 6px 18px -6px rgba(13,27,47,.10) !important;
  transition: transform .18s ease, box-shadow .18s ease;
  /* Card layout (icon position, label/value/footer order) stays IDENTICAL in
     Dhivehi as in English - only the text itself differs. Without this, the
     inherited direction:rtl from html[lang="dv"] would flip the flexbox order
     and move the icon from top-right to top-left, making Dhivehi cards look
     structurally different from English instead of just showing different text. */
  direction: ltr !important;
}
/* design-system.css's "unified card surface" rule forces border-radius via
   !important at 2-class specificity; this selector repeats the target class
   to reach 3-class specificity so 20px always wins, whichever file loads last. */
.vb-kpi-grid .vb-kpi-card.vb-kpi-card { border-radius: 20px !important; }
.vb-kpi-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 2px 4px rgba(13,27,47,.04), 0 16px 40px -12px rgba(13,27,47,.16) !important;
}

/* Top accent line - same gradients as Dashboard's per-column colours. */
.vb-kpi-card::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px !important;
  opacity: .9;
  pointer-events: none;
}
.vb-kpi-blue::before   { background: linear-gradient(90deg, #2C7BC9, #185FA5) !important; }
.vb-kpi-red::before    { background: linear-gradient(90deg, #FF8A6E, #FF6A4D) !important; }
.vb-kpi-dark::before   { background: linear-gradient(90deg, #33507C, #0C1E3E) !important; }
.vb-kpi-green::before  { background: linear-gradient(90deg, #34C98A, #0FAE6E) !important; }
.vb-kpi-orange::before { background: linear-gradient(90deg, #F5A742, #E8890C) !important; }

.vb-kpi-top {
  display: flex !important;
  align-items: flex-start !important;
  justify-content: space-between !important;
  gap: 10px !important;
  width: 100% !important;
}

.vb-kpi-label {
  min-width: 0 !important;
  margin: 0 !important;
  color: #64748B !important;
  font-size: 13px !important;
  font-weight: 700 !important;
  line-height: 1.2 !important;
  letter-spacing: .08em !important;
  text-transform: uppercase !important;
  white-space: nowrap !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  text-align: left !important;
}

.vb-kpi-icon {
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  flex: 0 0 44px !important;
  width: 44px !important;
  height: 44px !important;
  border-radius: 13px !important;
  color: #fff !important;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.28) !important;
}
.vb-kpi-icon i, .vb-kpi-icon svg {
  width: 20px !important;
  height: 20px !important;
  font-size: 20px !important;
  stroke-width: 1.8;
}
/* Icon backgrounds - identical gradients to Dashboard's .vbd-ci.ci-*. */
.vb-kpi-blue   .vb-kpi-icon { background: linear-gradient(145deg, #2C7BC9, #14538F) !important; box-shadow: 0 6px 14px -6px rgba(24,95,165,.7), inset 0 1px 0 rgba(255,255,255,.28) !important; }
.vb-kpi-red    .vb-kpi-icon { background: linear-gradient(145deg, #FF8A6E, #F2542F) !important; box-shadow: 0 6px 14px -6px rgba(255,106,77,.7), inset 0 1px 0 rgba(255,255,255,.30) !important; }
.vb-kpi-dark   .vb-kpi-icon { background: linear-gradient(145deg, #2B4368, #0C1E3E) !important; box-shadow: 0 6px 14px -6px rgba(12,30,62,.6), inset 0 1px 0 rgba(255,255,255,.16) !important; }
.vb-kpi-green  .vb-kpi-icon { background: linear-gradient(145deg, #34C98A, #0B9A60) !important; box-shadow: 0 6px 14px -6px rgba(15,174,110,.65), inset 0 1px 0 rgba(255,255,255,.28) !important; }
/* Orange is not one of Dashboard's own 4 KPI colours (Dashboard only ever needs
   4), but other pages need a 5th distinct colour - built in the exact same
   visual language (145deg gradient, same shadow treatment) so it never looks
   foreign next to the other four. */
.vb-kpi-orange .vb-kpi-icon { background: linear-gradient(145deg, #F5A742, #C97200) !important; box-shadow: 0 6px 14px -6px rgba(232,137,12,.65), inset 0 1px 0 rgba(255,255,255,.28) !important; }

/* Main number takes the card's accent colour (matches the Dashboard master
   reference - Revenue blue, Outstanding red, Expenses dark, Profit green).
   Targets BOTH markup patterns in use across the app: pages that split the
   value into <span class="vb-kpi-currency">+<span class="vb-kpi-number">,
   and pages that just set textContent on a single .vb-kpi-value div. */
.vb-kpi-blue   .vb-kpi-number, .vb-kpi-blue   > .vb-kpi-value { color: #185FA5 !important; }
.vb-kpi-red    .vb-kpi-number, .vb-kpi-red    > .vb-kpi-value { color: #F2542F !important; }
.vb-kpi-dark   .vb-kpi-number, .vb-kpi-dark   > .vb-kpi-value { color: #0C1E3E !important; }
.vb-kpi-green  .vb-kpi-number, .vb-kpi-green  > .vb-kpi-value { color: #0FAE6E !important; }
.vb-kpi-orange .vb-kpi-number, .vb-kpi-orange > .vb-kpi-value { color: #C97200 !important; }

.vb-kpi-value {
  display: flex !important;
  align-items: baseline !important;
  gap: 6px !important;
  width: 100% !important;
  min-width: 0 !important;
  margin-top: 16px !important;
  white-space: nowrap !important;
  overflow: hidden !important;
  text-align: left !important;
  /* Matches .vb-kpi-number below - pages that set text directly on
     .vb-kpi-value (no separate .vb-kpi-currency/.vb-kpi-number spans) must
     still land on the same 42px Dashboard spec instead of falling through to
     design-system.css's older 20px .vb-kpi-value rule. Has no effect on pages
     that DO use the split markup, since a child span's own explicit
     font-size always wins over its parent's. */
  font-size: 32px !important;
  font-weight: 800 !important;
  letter-spacing: 0 !important;
  line-height: 1.05 !important;
  font-variant-numeric: tabular-nums !important;
  font-family: Inter, system-ui, sans-serif !important;
  direction: ltr !important;
  unicode-bidi: isolate !important;
}
.vb-kpi-currency {
  flex: 0 0 auto !important;
  color: #94A3B8 !important;
  font-size: 14px !important;
  font-weight: 700 !important;
}
.vb-kpi-number {
  min-width: 0 !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  color: #0C1E3E !important;
  font-size: 32px !important;
  font-weight: 800 !important;
  letter-spacing: 0 !important;
  line-height: 1.05 !important;
  font-variant-numeric: tabular-nums !important;
  /* Figures must never be bidi-reordered or picked up by a Dhivehi font, even
     inside an RTL-direction card - same protection this codebase already uses
     elsewhere (e.g. trips.html's .ltr-num) for numbers sitting inside RTL text. */
  direction: ltr !important;
  unicode-bidi: isolate !important;
  font-family: Inter, system-ui, sans-serif !important;
}
.vb-kpi-value.neg .vb-kpi-number, .vb-kpi-card .vb-kpi-value.neg { color: #F2542F !important; }

.vb-kpi-footer {
  margin-top: 16px !important;
  color: #64748B !important;
  font-size: 15px !important;
  font-weight: 500 !important;
  line-height: 1.25 !important;
  white-space: nowrap !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  text-align: left !important;
}

/* ── Dark mode — same surface/border/text treatment everywhere, no per-page variants. */
html.viya-dv .vb-kpi-card { background: #101a32 !important; border-color: #22324f !important; box-shadow: 0 1px 2px rgba(0,0,0,.2), 0 6px 18px -6px rgba(0,0,0,.35) !important; }
html.viya-dv .vb-kpi-number { color: #f1f6ff !important; }
html.viya-dv .vb-kpi-value { color: #f1f6ff !important; }
html.viya-dv .vb-kpi-blue   .vb-kpi-number, html.viya-dv .vb-kpi-blue   > .vb-kpi-value { color: #4A9EEA !important; }
html.viya-dv .vb-kpi-red    .vb-kpi-number, html.viya-dv .vb-kpi-red    > .vb-kpi-value { color: #FF7A5C !important; }
html.viya-dv .vb-kpi-dark   .vb-kpi-number, html.viya-dv .vb-kpi-dark   > .vb-kpi-value { color: #f1f6ff !important; }
html.viya-dv .vb-kpi-green  .vb-kpi-number, html.viya-dv .vb-kpi-green  > .vb-kpi-value { color: #34D399 !important; }
html.viya-dv .vb-kpi-orange .vb-kpi-number, html.viya-dv .vb-kpi-orange > .vb-kpi-value { color: #F5A742 !important; }
html.viya-dv .vb-kpi-label { color: #93a4c0 !important; }
html.viya-dv .vb-kpi-footer { color: #9fb1cb !important; }

/* ── TABLET 768–1024px: 4 cards stay in ONE row, everything scales down smoothly
   with the viewport instead of wrapping to 2 rows or clipping. Main number is a
   fixed 38px per the KPI spec; only the surrounding chrome uses clamp() so it
   eases toward the desktop values as the viewport approaches 1024px. ───────── */
@media (min-width: 768px) and (max-width: 1024px) {
  .vb-kpi-grid { grid-template-columns: repeat(4, minmax(0, 1fr)) !important; gap: clamp(10px, 1.4vw, 16px) !important; }
  .vb-kpi-card { min-height: clamp(128px, 15vw, 180px) !important; padding: clamp(14px, 1.8vw, 24px) !important; }
  .vb-kpi-grid .vb-kpi-card.vb-kpi-card { border-radius: clamp(16px, 2vw, 20px) !important; }
  .vb-kpi-label { font-size: clamp(11px, 1.2vw, 13px) !important; }
  .vb-kpi-value { margin-top: clamp(11px, 1.6vw, 16px) !important; font-size: 28px !important; }
  .vb-kpi-number { font-size: 28px !important; }
  .vb-kpi-currency { font-size: clamp(11px, 1.1vw, 14px) !important; }
  .vb-kpi-footer { font-size: clamp(12px, 1.3vw, 15px) !important; margin-top: clamp(11px, 1.6vw, 16px) !important; }
  .vb-kpi-icon { flex-basis: clamp(38px, 4.5vw, 44px) !important; width: clamp(38px, 4.5vw, 44px) !important; height: clamp(38px, 4.5vw, 44px) !important; border-radius: clamp(11px, 1.4vw, 13px) !important; }
  .vb-kpi-icon i, .vb-kpi-icon svg { width: clamp(18px, 2.1vw, 20px) !important; height: clamp(18px, 2.1vw, 20px) !important; font-size: clamp(18px, 2.1vw, 20px) !important; }
}

/* ── MOBILE 320–767px: 2 cards per row, compact, same proportions/type scale as
   desktop, never overlapping or scrolling.

   REVERTED 2026-08-27. I briefly changed this to repeat(4) chasing a one-row
   look on Projects. That was wrong on two counts: it had no effect (Projects
   still rendered 2x2, so something else governs that page), and it contradicts a
   measured decision documented in mobile-fixes.css — a 4-card row on a 390px
   phone gives ~82px cards, and on reports.html that left "MVR 0.00" needing
   117px inside 56px. Rows of four or fewer are meant to fall through to THIS
   2-up default; only rows of five or more become the scroll strip.
   Pages that show one row do so through their own CSS, not this rule. */
@media (max-width: 767px) {
  .vb-kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; gap: 10px !important; }
  .vb-kpi-card { min-height: 118px !important; padding: 12px !important; }
  .vb-kpi-grid .vb-kpi-card.vb-kpi-card { border-radius: 16px !important; }
  .vb-kpi-label { font-size: 11px !important; letter-spacing: .06em !important; }
  .vb-kpi-value { margin-top: 14px !important; font-size: 24px !important; }
  .vb-kpi-number { font-size: 24px !important; }
  .vb-kpi-currency { font-size: 11px !important; }
  .vb-kpi-footer { font-size: 12px !important; margin-top: 14px !important; }
  .vb-kpi-icon { flex-basis: 38px !important; width: 38px !important; height: 38px !important; border-radius: 11px !important; }
  .vb-kpi-icon i, .vb-kpi-icon svg { width: 18px !important; height: 18px !important; font-size: 18px !important; }
}

/* ── Short landscape (phone in landscape, especially with the address bar
   still visible, has very little vertical room) - a narrow, supplementary
   refinement on top of the width-based rules above, not a replacement for
   them. Only kicks in when height is genuinely tight. ── */
@media (orientation: landscape) and (max-height: 500px) {
  .vb-kpi-card { min-height: 96px !important; padding: 10px !important; }
  .vb-kpi-value { margin-top: 8px !important; }
  .vb-kpi-footer { margin-top: 4px !important; }
}

@media (max-width: 359px) {
  .vb-kpi-card { min-height: 108px !important; padding: 10px !important; }
  .vb-kpi-value, .vb-kpi-number { font-size: 21px !important; }
}

/* Three-state KPI figures — see assets/js/viya-load-state.js.
   A failed read renders an em-dash, never a number. */
.viya-fig-pending { color: var(--faint, #98a4b3); letter-spacing: 2px; font-weight: 700; }
.viya-fig-failed  { color: var(--muted, #6b7a8d); font-weight: 700; cursor: help; }

/* ══════════════════════════════════════════════════════════════════════════════
   KPI FIGURES SIZE TO THEIR CARD, NOT TO THE VIEWPORT
   ────────────────────────────────────────────────────────────────────────────
   THE DEFECT. Every font-size above is chosen per VIEWPORT breakpoint — 32px
   desktop, 28px tablet, 24px phone. But the width a figure actually gets depends
   on how many cards the PAGE puts in that row, which the breakpoint knows nothing
   about. Sales renders five KPIs in one row, so at 768px each card is ~145px and
   the value gets 104px of it — while the tablet rule still hands it 28px type.
   "MVR 0.00" needs 137px. Measured: scrollWidth 137 inside clientWidth 104.
   Real data is far worse: "MVR 125,480.75" at 28px needs ~250px.

   That is why this kept coming back. Fixing it per page meant another !important
   layer per page, and the brief for this release explicitly rules that out.

   THE FIX. Make the card a containment context and size the figure in container
   units, so a figure always fits the card it is actually in — 5-up, 4-up or 2-up,
   any page, any breakpoint, with no page-specific rule at all.

   clamp() keeps it bounded: never below 13px (unreadable) and never above the
   per-breakpoint maximum the design already uses, so a normal 4-up desktop row
   looks exactly as it does today. Only cramped cards shrink, and they shrink
   instead of clipping.

   PROGRESSIVE ENHANCEMENT. The fixed font-size declarations above are left
   untouched and come first. A browser without container-query units ignores the
   cqi values below and keeps today's behaviour — no regression, just no
   improvement. Chromium 105+ and Safari 16+ support it, which covers the
   Capacitor WebView and every browser this app targets.

   SPECIFICITY. Must beat `html body .vb-kpi-value` (0,1,2) in mobile-fixes.css
   and the `:is(...)` rules (0,1,0) in design-system.css, both !important.
   `html body[class] .vb-kpi-card .vb-kpi-value` scores (0,2,2) and wins outright. */
.vb-kpi-card { container-type: inline-size; }

html body[class] .vb-kpi-card .vb-kpi-value,
html body[class] .vb-kpi-card .vb-kpi-number {
  font-size: clamp(11px, 8cqi, 32px) !important;
  white-space: nowrap !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;   /* if it still cannot fit, SAY so */
  min-width: 0 !important;
}
@media (min-width: 768px) and (max-width: 1024px) {
  html body[class] .vb-kpi-card .vb-kpi-value,
  html body[class] .vb-kpi-card .vb-kpi-number { font-size: clamp(11px, 8cqi, 28px) !important; }
}
@media (max-width: 767px) {
  html body[class] .vb-kpi-card .vb-kpi-value,
  html body[class] .vb-kpi-card .vb-kpi-number { font-size: clamp(11px, 8cqi, 24px) !important; }
}
/* The small currency prefix and the label track the figure so the card stays
   proportioned rather than a big label above a shrunken number. */
html body[class] .vb-kpi-card .vb-kpi-currency { font-size: clamp(8px, 7cqi, 14px) !important; }
html body[class] .vb-kpi-card .vb-kpi-label {
  font-size: clamp(8px, 6.5cqi, 13px) !important;
  white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important;
}


/* ══════════════════════════════════════════════════════════════════════════════
   PHONE KPI LAYOUT — one row, owned by the PAGES
   ────────────────────────────────────────────────────────────────────────────
   Restored to a single row at the owner's request 2026-08-26. An earlier pass had
   split phone KPI rows into two columns to stop large amounts clipping; that is
   reverted and every page is back to one row, as it was before.

   No shared grid rule is declared here on purpose. Each page already forces its
   own single row at <=767px with selectors like
   `html body.page-trips.trips-page .dashboard-shell .main-content > .metrics`,
   which score (0,5,3). A shared rule cannot outrank that without another
   !important escalation, and a rule that never wins is dead CSS — so the page
   rules are left to own the layout and this file does not fight them.

   What this file DOES still contribute is the container-query sizing below: each
   figure is sized from its own card rather than from the viewport, so a narrow
   one-row card shrinks its number down to the 11px floor instead of being cut at
   full size. That is what makes one row workable at 320-430px.

   Known trade-off, accepted deliberately: at the smallest widths a very large
   amount (MVR 12,500,000.00) can still exceed even the floored type in a ~69px
   card. One row is the owner's preference; two columns was the only layout that
   removed that last case. */

/* Labels clip on their own once a card is narrow. Size them to the card too, and
   let a genuinely long label wrap to a second line rather than lose characters -
   a KPI label is short enough that two lines is cheaper than an ellipsis. */
html body[class] .vb-kpi-card .vb-kpi-label {
  font-size: clamp(9px, 5.5cqi, 13px) !important;
  white-space: normal !important;
  overflow-wrap: anywhere !important;
  text-overflow: clip !important;
}

/* ══════════════════════════════════════════════════════════════════════════════
   PHONE: FOUR KPI CARDS IN ONE ROW — final, authoritative
   ────────────────────────────────────────────────────────────────────────────
   The owner has asked for one row three times. Every previous attempt failed
   because SEVEN stylesheets independently force 2-up at <=767px for these
   selectors, all with !important and equal (0,1,0) specificity, so the winner is
   whichever happens to load last:

     viyabook.css         .summary-grid,.kpi-grid,.stats-grid,...  repeat(2)
     viyabook-mobile.css  .summary-grid,.stats-grid,.metrics,...   repeat(2)
     responsive-fix.css   .dashboard-shell .summary-grid,...       repeat(2)
     design-system.css    :is(.vb-kpi-grid,.vbd-cards,...)         repeat(2)
     design-system.css    .summary-grid,.stats-grid,.kpi-grid,...  repeat(2)
     tablet.css           .summary-grid,...,.metrics,...           repeat(2)
     page CSS             .metrics                                 1fr / 1fr 1fr

   Editing any one of them changed nothing, which is why this kept coming back.
   This rule is last in this file and carries enough specificity to settle it for
   every KPI row class the app uses, including .metrics on Projects.

   The measured objection to 4-up on a phone (~82px cards cutting money figures)
   is answered by assets/js/viya-kpi-autofit.js, which shrinks each figure to fit
   its own card and wraps labels rather than truncating. That did not exist when
   the 2-up default was chosen. */
@media (max-width: 767px) {
  html body[class] .vb-kpi-grid,
  html body[class] .vbd-cards,
  html body[class] .metrics,
  html body[class] .summary-grid,
  html body[class] .stats-grid,
  html body[class] .kpi-grid,
  html body[class] .stat-cards,
  html body[class] .summary-cards {
    display: grid !important;
    grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
    grid-auto-flow: row !important;
    gap: 8px !important;
    overflow-x: visible !important;
  }
  html body[class] .vb-kpi-grid > *,
  html body[class] .vbd-cards > *,
  html body[class] .metrics > * { min-width: 0 !important; }
}
