/* ==========================================================================
   HARDTRAC — admin.css  (v3 — light, mobile-first, corrected)

   Back-office layer for the Seller Admin panel and Administrator Console.
   Loads after app.css and inherits its tokens, buttons, fields, modals,
   toasts, chat bubbles and skeletons. This file adds only what the back
   office needs on top: the shell, data density, and charts.

   v3 changes on top of v2
   -----------------------
   · The topbar action strip scrolls sideways on a phone instead of wrapping
     under the title or pushing it off screen.
   · Genuinely wide tables get a horizontal scroll at desktop widths instead
     of wrapping cell content into unreadable slivers.
   · On the phone card layout, the first cell of each row (usually the order
     or product id) reads as the card title.
   · Sidebar and login shell use dynamic viewport units, so nothing hides
     behind the mobile URL bar.
   · z-index values come from the app.css scale, so the edit modal always
     sits above the sidebar and its scrim.
   ========================================================================== */

:root{
  --side-w:226px;
  --top-h:52px;
  /* chart series — used by charts.js and the legend swatches */
  --chart-1:#5b4bf5;
  --chart-2:#0a8055;
  --chart-3:#f0a413;
  --chart-4:#2563eb;
  --chart-5:#db2777;
  --chart-6:#0891b2;
}

/* ==========================================================================
   1. SHELL  (phone first)
   ========================================================================== */
.app{display:flex;min-height:100vh;min-height:100dvh;background:var(--bg-2)}

.sidebar{
  position:fixed;left:0;top:0;z-index:930;
  width:var(--side-w);height:100vh;height:100dvh;flex-shrink:0;
  background:#fff;border-right:1px solid var(--line);
  padding:calc(14px + var(--safe-t)) 12px 14px;
  display:flex;flex-direction:column;
  transform:translateX(-100%);
  transition:transform var(--t-slow) var(--ease);
  box-shadow:var(--shadow-lg);
  will-change:transform;
  overflow-y:auto;
}
.sidebar.open{transform:translateX(0)}

.side-logo img{height:24px;margin:2px 6px}
.side-tag{
  font-size:9.5px;color:var(--ink-3);
  padding:5px 8px 12px;font-weight:800;
  letter-spacing:.1em;text-transform:uppercase;
}

/* The menu itself never scrolls with the page — see section 8. This keeps
   the list readable when it is long enough to need its own scroll. */
.sidebar nav{display:flex;flex-direction:column;gap:1px;overflow-y:auto;min-height:0}
.sidebar nav::-webkit-scrollbar{width:6px}
.sidebar nav::-webkit-scrollbar-thumb{background:var(--line-2);border-radius:3px}

/* An accent rail on the active row instead of a filled block — it marks the
   position without turning a ten-item menu into ten coloured slabs. */
.nav-item{
  position:relative;
  display:flex;align-items:center;gap:11px;
  min-height:40px;padding:8px 10px;border-radius:var(--radius-sm);
  color:var(--ink-2);font-size:13px;font-weight:500;
  cursor:pointer;margin-bottom:1px;
  transition:background var(--t-fast) var(--ease),color var(--t-fast) var(--ease);
}
.nav-item::before{
  content:"";position:absolute;left:-10px;top:8px;bottom:8px;width:3px;
  border-radius:0 3px 3px 0;background:transparent;
  transition:background var(--t-fast) var(--ease);
}
.nav-item:hover,.nav-item:active{background:var(--bg-2);color:var(--ink)}
.nav-item.on{background:var(--brand-soft);color:var(--brand-ink);font-weight:700}
.nav-item.on::before{background:var(--brand)}
.nav-item.on svg{color:var(--brand)}
.nav-item svg{width:17px;height:17px;flex-shrink:0;opacity:.9}
.nav-item.has-new{color:var(--ink)}
.nav-badge{
  margin-left:auto;
  min-width:19px;height:19px;line-height:19px;padding:0 5px;
  border-radius:999px;background:var(--danger);color:#fff;
  font-size:10.5px;font-weight:800;text-align:center;
}

.side-foot{
  margin-top:auto;padding:10px 8px calc(4px + var(--safe-b));
  border-top:1px solid var(--line);
  font-size:12.5px;color:var(--ink-2);flex-shrink:0;
}
.side-foot b{color:var(--ink);font-weight:700}

.main{flex:1;min-width:0}
.topbar{
  height:calc(var(--top-h) + var(--safe-t));
  border-bottom:1px solid var(--line);
  display:flex;align-items:center;padding:0 12px;gap:10px;
  position:sticky;top:0;background:#fff;z-index:20;
  padding-top:var(--safe-t);flex-shrink:0;
}
.topbar h1{font-size:16px;font-weight:800;letter-spacing:-.026em;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* the action strip scrolls sideways rather than crushing the page title */
#topActions{display:flex;align-items:center;gap:8px;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
#topActions::-webkit-scrollbar{display:none}
#topActions>*{flex:0 0 auto}
.content{padding:12px 10px 44px}
.content::-webkit-scrollbar{width:10px}
.content::-webkit-scrollbar-thumb{background:var(--line-2);border-radius:5px;border:3px solid var(--bg-2)}
.content::-webkit-scrollbar-track{background:transparent}

/* hamburger + scrim injected by boost.js */
.mob-menu-btn{
  display:inline-flex;align-items:center;justify-content:center;
  width:44px;height:44px;flex-shrink:0;
  border-radius:var(--radius-sm);
  border:1px solid var(--line-2);background:#fff;color:var(--ink-2);
}
.mob-menu-btn svg{width:20px;height:20px}
.side-scrim{
  position:fixed;inset:0;z-index:920;
  background:rgba(17,19,42,.4);
  opacity:0;pointer-events:none;
  transition:opacity var(--t) var(--ease);
}
.side-scrim.show{opacity:1;pointer-events:auto}

/* ==========================================================================
   2. LAYOUT HELPERS
   ========================================================================== */
.grid-2,.grid-3{display:grid;grid-template-columns:1fr;gap:12px}
.toolbar{display:flex;gap:8px;flex-wrap:wrap;align-items:center}

/* ==========================================================================
   3. KPI STRIP
   ========================================================================== */
.kpis{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;margin-bottom:12px}
.kpi{
  position:relative;overflow:hidden;
  background:#fff;border:1px solid var(--line);
  border-radius:var(--radius-lg);padding:10px 12px;
  transition:border-color var(--t-fast) var(--ease),box-shadow var(--t-fast) var(--ease);
}
.kpi:hover{border-color:var(--line-2);box-shadow:var(--shadow-sm)}
/* a hairline marker, not a coloured block */
.kpi::before{content:"";position:absolute;left:0;top:0;bottom:0;width:2px;background:var(--brand)}
.kpi .label{
  font-size:9.5px;color:var(--ink-3);margin-bottom:5px;
  font-weight:800;text-transform:uppercase;letter-spacing:.07em;
}
.kpi .val{
  font-family:var(--display);font-size:19px;font-weight:800;
  letter-spacing:-.035em;line-height:1.15;
  font-variant-numeric:tabular-nums;
}
.kpi .sub{font-size:11px;margin-top:3px;color:var(--ink-3)}
.up{color:var(--green);font-weight:700}
.down{color:var(--danger);font-weight:700}

/* ==========================================================================
   4. SURFACES
   ========================================================================== */
.card{background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg)}
.panel{background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);overflow:hidden}
.panel{box-shadow:var(--shadow-sm)}
.panel-head{
  padding:10px 13px;border-bottom:1px solid var(--line);
  display:flex;align-items:center;justify-content:space-between;
  gap:10px;flex-wrap:wrap;
}
.panel-head h3{font-size:13.5px;font-weight:800;letter-spacing:-.02em}

.insight-panel{
  margin-bottom:14px;
  background:#fff;border:1px solid var(--brand-line);
  border-radius:var(--radius-lg);
  border-left:3px solid var(--brand);
}
.insight-list{list-style:none;margin:0;padding:4px 13px 11px;display:grid;gap:7px}
.insight-list li{position:relative;padding-left:19px;font-size:12.5px;line-height:1.55;color:var(--ink-2)}
.insight-list li::before{
  content:"";position:absolute;left:4px;top:8px;
  width:6px;height:6px;border-radius:50%;background:var(--brand);
}
.insight-list li:nth-child(2n)::before{background:var(--chart-4)}
.insight-list li:nth-child(3n)::before{background:var(--chart-3)}

/* ==========================================================================
   5. TABLES
   On a phone each row restacks as a card. boost.js copies the <th> text onto
   every <td> as data-col, and the label is drawn from that — so no markup
   change is needed in admin.js or console.js.
   ========================================================================== */
table.tbl{width:100%;border-collapse:collapse;font-size:12.5px;font-variant-numeric:tabular-nums}
table.tbl thead{display:none}
table.tbl tbody tr{
  display:block;
  background:#fff;border:1px solid var(--line);
  border-radius:var(--radius);
  padding:3px 11px;margin-bottom:7px;
}
table.tbl td{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:6px 0;border-bottom:1px solid var(--line);
  text-align:right;
}
table.tbl tr td:last-child{border-bottom:none}
/* the first cell is almost always the id — read it as the card title */
table.tbl td:first-child{font-weight:700}
table.tbl td::before{
  content:attr(data-col);
  flex:0 0 auto;
  font-size:10.5px;font-weight:700;color:var(--ink-3);
  text-transform:uppercase;letter-spacing:.05em;text-align:left;
}
/* a cell with no label (a thumbnail, an action button) spans the full row */
table.tbl td[data-col=""]::before{display:none}

.tbl-thumb{
  width:40px;height:40px;border-radius:var(--radius-sm);
  overflow:hidden;border:1px solid var(--line);background:#fff;
  display:grid;place-items:center;font-weight:800;font-size:11px;color:var(--ink-3);
}
.tbl-thumb .thumb-img{width:100%;height:100%;object-fit:contain;display:block;background:#fff}
.tbl-thumb .thumb-glyph{width:100%;height:100%;display:grid;place-items:center;font-weight:800;font-size:11px}

/* ==========================================================================
   6. STATUS PILLS
   ========================================================================== */
.pill,.badge,.status{
  display:inline-block;padding:3px 10px;border-radius:999px;
  font-size:11.5px;font-weight:700;white-space:nowrap;
}
.pill-green{background:var(--green-bg);color:var(--green)}
.pill-amber{background:var(--warn-bg);color:var(--warn)}
.pill-blue{background:#e8f0fc;color:#1a52ad}
.pill-red{background:var(--danger-bg);color:var(--danger)}
.pill-gray{background:var(--bg-3);color:var(--ink-2)}

/* ==========================================================================
   7. CONTROLS
   ========================================================================== */
.seg,.subtabs{
  display:inline-flex;background:var(--bg-2);
  border:1px solid var(--line);border-radius:var(--radius);
  padding:3px;gap:3px;flex-wrap:wrap;
}
.subtabs{margin-bottom:14px}
.seg button,.subtabs button{
  min-height:40px;padding:8px 14px;border-radius:var(--radius-xs);
  font-size:13px;color:var(--ink-2);font-weight:600;
  transition:background var(--t-fast) var(--ease),color var(--t-fast) var(--ease);
}
.seg button.on,.subtabs button.on{background:#fff;color:var(--brand-ink);font-weight:700;box-shadow:var(--shadow-sm)}

.search{
  display:flex;align-items:center;gap:8px;
  background:#fff;border:1px solid var(--line-2);
  border-radius:var(--radius-sm);padding:0 12px;min-height:44px;
  transition:border-color var(--t-fast) var(--ease),box-shadow var(--t-fast) var(--ease);
}
.search:focus-within{border-color:var(--brand);box-shadow:var(--ring)}
.search input{border:none;outline:none;flex:1;font-size:16px;background:transparent;min-width:0}

.tagbox{
  display:flex;flex-wrap:wrap;gap:6px;
  padding:8px 10px;border:1px solid var(--line-2);
  border-radius:var(--radius-sm);background:#fff;
  min-height:46px;align-content:flex-start;
}
.tagbox:focus-within{border-color:var(--brand);box-shadow:var(--ring)}
.tagbox input{border:none;outline:none;flex:1;min-width:90px;font-size:16px;background:transparent}
.tagchip{
  display:inline-flex;align-items:center;gap:6px;
  background:var(--brand-soft);color:var(--brand-ink);
  border-radius:999px;padding:4px 10px;font-size:12px;font-weight:700;
}
.tagchip b{cursor:pointer;opacity:.6}
.tagchip b:hover{opacity:1}

#editBody textarea{
  width:100%;min-height:88px;padding:11px 12px;
  border:1px solid var(--line-2);border-radius:var(--radius-sm);
  resize:vertical;font-size:16px;background:#fff;line-height:1.55;
}
#editBody textarea:focus{outline:none;border-color:var(--brand);box-shadow:var(--ring)}
#editBody .field{margin-bottom:12px}

/* ==========================================================================
   8. CHARTS
   ========================================================================== */
.chart-grid-2{display:grid;grid-template-columns:1fr;gap:12px;margin-bottom:14px}
.chart-card .panel-head{margin-bottom:0}
.chart-wrap{position:relative;padding:10px 12px 4px;min-height:180px}
/* Chart.js sizes to its parent; without an explicit box a canvas in a grid
   cell can collapse to zero height on first paint and never recover. */
.chart-wrap canvas{max-width:100%;display:block}
.chart-card{display:flex;flex-direction:column}
.chart-card .chart-wrap{flex:1 1 auto}
.donut-wrap{display:grid;place-items:center;padding:14px 14px 4px}
.chart-legend{display:flex;flex-wrap:wrap;gap:6px 8px;padding:2px 12px 12px;justify-content:center}
/* Each legend entry is a chip rather than loose text — at a glance you can
   see how many series a chart carries without reading it. */
.chart-legend .lg-item{
  display:flex;align-items:center;gap:6px;
  font-size:11.5px;color:var(--ink-2);font-weight:600;
  background:var(--bg-2);border:1px solid var(--line);
  border-radius:999px;padding:3px 9px 3px 7px;
}
.chart-legend .lg-dot{width:8px;height:8px;border-radius:999px;flex-shrink:0}
.chart-legend .lg-val{color:var(--ink);font-weight:800;font-variant-numeric:tabular-nums}

.bar-row{display:flex;align-items:center;gap:10px;margin-bottom:9px}
.bar-row:last-child{margin-bottom:2px}
.bar-label{width:100px;font-size:12.5px;color:var(--ink-2);flex-shrink:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bar-track{flex:1;height:7px;background:var(--bg-3);border-radius:999px;overflow:hidden;min-width:40px}
.bar-fill{
  height:100%;border-radius:999px;
  background:linear-gradient(90deg,var(--brand-2),var(--brand));
  transition:width var(--t-slow) var(--ease);
}
/* The bars grow from zero on first paint rather than snapping in — the only
   animation on the dashboard, and it reads as the data arriving. */
@media (prefers-reduced-motion:no-preference){
  .bar-fill{animation:barGrow .5s var(--ease) both}
}
@keyframes barGrow{from{transform:scaleX(0);transform-origin:left}to{transform:none}}
.bar-val{width:82px;text-align:right;font-size:12.5px;font-weight:700;flex-shrink:0;font-variant-numeric:tabular-nums}

.spark{display:flex;align-items:flex-end;gap:3px;height:78px}
.spark .b{
  flex:1;min-height:2px;border-radius:3px 3px 0 0;
  background:linear-gradient(180deg,var(--brand),var(--brand-2));
  opacity:.85;transition:opacity var(--t-fast) var(--ease);
}
.spark:hover .b{opacity:.5}
.spark .b:hover{opacity:1}

.legend{display:flex;flex-direction:column;gap:7px}
.legend .row span:first-child{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--ink-2)}
.dot{width:10px;height:10px;border-radius:3px;flex-shrink:0}

/* ==========================================================================
   9. GIFT CARD BATCH OUTPUT
   ========================================================================== */
.gc-fresh{
  margin-top:14px;padding:13px 15px;border-radius:var(--radius-lg);
  background:var(--brand-soft);border:1px dashed var(--brand-line);
}
.gc-codes{display:flex;flex-wrap:wrap;gap:6px;max-height:180px;overflow-y:auto}
.gc-code{
  font-family:var(--mono);font-size:12px;font-weight:700;letter-spacing:.04em;
  color:var(--brand-ink);background:#fff;
  border:1px solid var(--brand-line);border-radius:var(--radius-xs);
  padding:6px 10px;
}

/* ==========================================================================
   10. LOGIN
   ========================================================================== */
.login-shell{
  min-height:100vh;min-height:100dvh;display:grid;place-items:center;padding:20px;
  background:linear-gradient(180deg,#f6f4ff 0%,var(--bg-2) 45%);
}
.login-card{
  width:min(380px,100%);background:#fff;
  border:1px solid var(--line);border-radius:var(--radius-xl);
  padding:26px 22px calc(26px + var(--safe-b));
  box-shadow:var(--shadow);
}
.login-card img{height:30px;margin-bottom:4px}

/* ==========================================================================
   11. TABLET AND UP
   ========================================================================== */
@media (min-width:560px){
  .kpis{grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:11px}
  .kpi .val{font-size:21px}
  .bar-label{width:132px}
  .bar-val{width:92px}
}

@media (min-width:900px){
  /* ---- FROZEN SHELL ---------------------------------------------------
     The menu and the page title do not move. Only the content column
     scrolls, inside its own box — so the navigation is always one click
     away no matter how far down a long table you are. */
  body:has(.app){overflow:hidden}
  .app{height:100vh;height:100dvh;overflow:hidden}

  .sidebar{
    position:fixed;left:0;top:0;
    height:100vh;height:100dvh;
    transform:none;box-shadow:none;border-right:1px solid var(--line);
    padding:16px 12px;overflow:hidden;
  }
  .main{
    margin-left:var(--side-w);
    height:100vh;height:100dvh;
    display:flex;flex-direction:column;min-width:0;overflow:hidden;
  }
  .content{
    flex:1 1 auto;min-height:0;
    overflow-y:auto;overflow-x:hidden;
    overscroll-behavior:contain;
    scroll-behavior:smooth;
  }
  .mob-menu-btn,.side-scrim{display:none!important}

  .topbar{padding:0 20px;gap:12px}
  .topbar h1{font-size:17px}
  .content{padding:16px 20px 48px}

  .grid-2{grid-template-columns:1fr 1fr;gap:14px}
  .grid-3{grid-template-columns:repeat(3,1fr);gap:14px}
  .chart-grid-2{grid-template-columns:1.4fr 1fr;gap:14px;margin-bottom:14px}
  .chart-wrap{padding:14px 16px 6px}
  .chart-legend{gap:8px 16px;padding:4px 16px 16px}

  .kpi{padding:12px 14px}
  .kpi .val{font-size:22px}

  /* tables return to real rows; genuinely wide ones scroll sideways in the
     panel instead of wrapping cells into slivers */
  .panel:has(> table.tbl){overflow-x:auto}
  .panel > table.tbl{min-width:640px}
  table.tbl{font-size:12px}
  table.tbl thead{display:table-header-group}
  table.tbl tbody tr{
    display:table-row;background:transparent;border:none;
    border-radius:0;padding:0;margin:0;
    transition:background var(--t-fast) var(--ease);
  }
  table.tbl tbody tr:hover td{background:var(--bg-2)}
  table.tbl th{
    text-align:left;padding:7px 12px;
    color:var(--ink-3);font-weight:800;font-size:10px;
    text-transform:uppercase;letter-spacing:.06em;
    border-bottom:1px solid var(--line);
    white-space:nowrap;background:var(--bg-2);
    position:sticky;top:0;z-index:1;
  }
  table.tbl td{
    display:table-cell;text-align:left;
    padding:7px 12px;border-bottom:1px solid var(--line);
    vertical-align:middle;
  }
  table.tbl td::before{display:none}
  table.tbl tr:last-child td{border-bottom:none}

  .seg button,.subtabs button{min-height:32px;padding:6px 13px;font-size:12.5px}
  .search{min-height:36px;padding:0 11px}
  .search input{font-size:13px}
  .tagbox{min-height:40px}
  .tagbox input,#editBody textarea{font-size:13px}
  .nav-item{min-height:34px;padding:6px 10px;font-size:12.5px}
  .mob-menu-btn{width:40px;height:40px}
}

@media (prefers-reduced-motion:reduce){
  .sidebar,.bar-fill,.side-scrim{transition:none!important}
  .content{scroll-behavior:auto}
}

/* ==========================================================================
   8. FROZEN SHELL — phone
   Below 900px the menu is a drawer, so the page keeps the browser's own
   scroll: an internal scroller there would fight the collapsing URL bar and
   cost more viewport than it saves. The title bar stays pinned either way.
   ========================================================================== */
@media (max-width:899px){
  .app{min-height:100vh;min-height:100dvh}
  .main{display:flex;flex-direction:column;min-width:0}
}

/* ==========================================================================
   9. WIDE SCREENS
   Past ~1600px a full-bleed dashboard turns every row into a long sparse
   line. The content column stops widening and centres instead; the KPI strip
   uses the extra room for a fourth and fifth card rather than fatter ones.
   ========================================================================== */
@media (min-width:1500px){
  .content{padding-left:32px;padding-right:32px}
  .content > *{max-width:1560px;margin-left:auto;margin-right:auto}
  .kpis{grid-template-columns:repeat(4,1fr)}
}

/* ==========================================================================
   10. DASHBOARD POLISH
   Small things that make a set of panels read as one dashboard rather than
   a pile of boxes.
   ========================================================================== */

/* The KPI accent takes the colour of what it reports, so a glance across the
   strip tells you which numbers are money, which are volume, which are risk.
   Nothing to change in admin.js — it is positional. */
.kpis .kpi:nth-child(2)::before{background:var(--chart-4)}
.kpis .kpi:nth-child(3)::before{background:var(--chart-2)}
.kpis .kpi:nth-child(4)::before{background:var(--chart-3)}
.kpis .kpi:nth-child(5)::before{background:var(--chart-6)}

/* The direction of a KPI is the part people scan for, so it gets a marker
   rather than only a colour — colour alone fails for the ~8% of men with a
   red/green deficiency, and fails entirely in a printed screenshot. */
.kpi .sub.up::before,.kpi .sub.down::before{
  font-size:9px;margin-right:4px;vertical-align:1px;
}
.kpi .sub.up::before{content:"\25B2"}
.kpi .sub.down::before{content:"\25BC"}

/* Panels lift very slightly under the pointer — enough to confirm which one
   you are reading on a dense screen, not enough to be a distraction. */
.panel,.card,.insight-panel{transition:box-shadow var(--t-fast) var(--ease),border-color var(--t-fast) var(--ease)}
@media (hover:hover){
  .panel:hover,.card:hover{box-shadow:var(--shadow);border-color:var(--line-2)}
}

/* Tables inside a panel: a quiet zebra at rest, a clear row under the
   pointer. Reading a wide row across a 1600px screen is the single most
   error-prone thing anyone does in this panel. */
@media (min-width:900px){
  table.tbl tbody tr:nth-child(even) td{background:rgba(20,22,40,.014)}
  table.tbl tbody tr:hover td{background:var(--brand-soft)}
  /* money and counts right-align themselves when the header says so */
  table.tbl td[data-col*="Total" i],
  table.tbl td[data-col*="Amount" i],
  table.tbl td[data-col*="Price" i],
  table.tbl td[data-col*="Qty" i],
  table.tbl td[data-col*="Stock" i]{text-align:right}
}

/* Loading state for a panel whose data has not arrived — replaces a blank
   white box with something that has the shape of the answer. */
.panel .skel{margin:12px 14px}

/* ==========================================================================
   11. CHART CARD DENSITY
   The dashboards now carry eight charts each. These keep a wall of panels
   readable rather than merely present.
   ========================================================================== */
.chart-card .panel-head{gap:8px}
/* the caption beside a chart title explains the encoding — quieter than the
   title, but it has to survive a narrow column */
.chart-card .panel-head .faint{white-space:nowrap;font-weight:600}
@media (max-width:559px){ .chart-card .panel-head .faint{display:none} }

/* A doughnut with its total in the middle needs less height than one with a
   caption underneath, and its legend sits tighter to it. */
.donut-wrap + .chart-legend{padding-top:0}

/* Charts sit on a very faint tint so the plot area reads as a surface and
   the panel's white header separates from it. */
.chart-card .chart-wrap{background:linear-gradient(180deg,rgba(20,22,40,.012),transparent 70%)}

/* Three-across chart rows collapse gracefully: the grid is auto-fitting
   (grid.css), so this only has to keep the boxes from going too short. */
.grid-3 .chart-wrap,.chart-grid-2 .chart-wrap{min-height:150px}


/* ==========================================================================
   POPUPS — compact pass. Every admin dialog is a form, and the forms had
   grown taller than the screen: this trims the chrome, tightens the field
   rhythm and keeps the sheet inside the viewport so the save button is
   always reachable without hunting.
   ========================================================================== */
.modal{max-height:94vh;max-height:94dvh}
.modal-head{padding:14px 52px 2px 16px}
.modal-head h3{font-size:16.5px}
.modal-head p{font-size:12px;margin-top:3px}
.modal-body{padding:12px 16px calc(16px + var(--safe-b))}
.modal-body .field{margin-bottom:10px}
.modal-body .field label{margin-bottom:4px}
.modal-body h4{margin-top:2px}
.modal-body .btn-block{margin-top:2px}
@media (max-width:640px){
  .modal-body{padding:10px 13px calc(14px + var(--safe-b))}
  .modal-head{padding:13px 48px 2px 13px}
}
