/* ==========================================================================
   MASAR — 9-pages.css
   Shared page-level atoms. Anything used by more than one page group lives
   here; a single page's own layout lives in its 9-pages-<group>.css.

   If something in here starts being used by four or more pages, it has
   earned a place in the component kit — move it to 3-components.css or
   4-data.css and give it a factory in js5/ui/kit.js.
   ========================================================================== */

/* ---- a filter bar above a table or list ------------------------------- */
.p-filters{
  display:flex;align-items:center;gap:var(--s-2);flex-wrap:wrap;
  padding:10px var(--card-pad-lg);
  border-bottom:1px solid var(--line-subtle);
}
.p-filters__sep{width:1px;height:20px;background:var(--line);flex:0 0 auto}

/* ---- a definition pair, used in every detail panel -------------------- */
.p-kvs{display:grid;grid-template-columns:auto 1fr;gap:7px 16px;min-width:0}
.p-kvs dt{font:var(--ty-caption);color:var(--text-3);white-space:nowrap}
.p-kvs dd{margin:0;font:var(--ty-body-sm);color:var(--text);min-width:0;
          overflow-wrap:anywhere;unicode-bidi:plaintext}
.p-kvs--wide{grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}
.p-kvs--wide dt{grid-column:auto}

/* ---- a titled block inside a drawer or a detail panel ----------------- */
.p-block{display:flex;flex-direction:column;gap:9px;padding-block:var(--s-4);
         border-top:1px solid var(--line-subtle)}
.p-block:first-child{border-top:0;padding-top:0}
.p-block__t{font:var(--ty-label);color:var(--text-2);
            display:flex;align-items:center;gap:7px}
.p-block__t .m-rule{width:22px}

/* ---- a row of actions ------------------------------------------------- */
.p-actions{display:flex;align-items:center;gap:var(--s-2);flex-wrap:wrap}

/* ---- a cell that holds a bar plus its figure -------------------------- */
.p-cellbar{display:flex;align-items:center;gap:9px;min-width:104px}
.p-cellbar .m-bar{flex:1 1 auto;min-width:44px}
.p-cellbar b{font:var(--ty-label-sm);color:var(--text);
             font-variant-numeric:tabular-nums;flex:0 0 auto}

/* ---- a small count tile, for a summary strip that is not a KPI -------- */
.p-counts{display:grid;grid-template-columns:repeat(auto-fit,minmax(124px,1fr));gap:var(--s-3)}
.p-count{
  display:flex;flex-direction:column;gap:2px;padding:11px 13px;
  background:var(--surface-sunken);border-radius:var(--r-md);min-width:0;
}
.p-count b{font:var(--ty-metric-sm);font-size:17px;color:var(--text)}
.p-count span{font:var(--ty-caption);color:var(--text-2)}
.p-count--ok b{color:var(--ok)} .p-count--warn b{color:var(--warn)}
.p-count--crit b{color:var(--critical)} .p-count--info b{color:var(--info)}

/* ---- a link rendered inside a table cell ------------------------------ */
.m-link-btn{color:var(--accent);font-weight:550;text-align:start}
.m-link-btn:hover{text-decoration:underline}

/* ---- provenance marks, used wherever a figure could be mistaken for an
        official municipal statistic ------------------------------------- */
.p-prov{display:inline-flex;align-items:center;gap:5px;font:var(--ty-caption)}
.p-prov a{color:var(--text-2);text-decoration:underline;text-underline-offset:2px}
.p-note{
  font:var(--ty-caption);color:var(--text-3);line-height:1.6;
  padding:9px 12px;background:var(--surface-sunken);border-radius:var(--r-sm);
}
.p-note code{background:var(--surface);padding:1px 5px;border-radius:4px;
             border:1px solid var(--line);font-size:.92em}

/* ---- a fenced block for a payload or a generated note ----------------- */
.p-code{
  margin:0;padding:12px 14px;border-radius:var(--r-md);
  background:var(--surface-sunken);border:1px solid var(--line);
  font:400 12px/1.65 var(--font-mono);color:var(--text);
  white-space:pre-wrap;overflow:auto;max-height:340px;direction:ltr;text-align:start;
}

/* ---- a visually hidden label, where a control's name must exist for a
        screen reader but would be noise on screen ---------------------- */
.m-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
      overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ---- a granted / withheld mark in a permission matrix ----------------- */
.p-ok-ic{display:inline-flex;color:var(--ok)}
.p-ok-ic--no{color:var(--text-3);opacity:.45}

/* ---- a colour swatch in a registry table ------------------------------ */
.p-swatch{display:inline-block;width:12px;height:12px;border-radius:3px;
          flex:0 0 auto;border:1px solid rgba(0,0,0,.12)}

/* ---- a range input, for a playback scrubber --------------------------- */
.m-range{
  -webkit-appearance:none;appearance:none;width:100%;height:4px;
  border-radius:var(--r-full);background:var(--line);outline:none;direction:ltr;
}
.m-range::-webkit-slider-thumb{
  -webkit-appearance:none;width:14px;height:14px;border-radius:var(--r-full);
  background:var(--accent);cursor:pointer;box-shadow:var(--sh-xs);
}
.m-range::-moz-range-thumb{
  width:14px;height:14px;border:0;border-radius:var(--r-full);
  background:var(--accent);cursor:pointer;
}
.m-range:focus-visible{box-shadow:var(--focus-ring)}

/* ---- a map band inside an ordinary (non-flush) page ------------------- */
.p-mapband{position:relative;height:clamp(320px,44vh,560px);min-height:280px;
           border-radius:var(--r-lg);overflow:hidden}
.p-mapband .m-map-host{border-radius:inherit}

/* ---- density, driven from Settings ------------------------------------ */
html[data-density="compact"]{--row-h:34px;--row-h-lg:40px;--card-pad:13px;--card-pad-lg:16px}
html[data-density="relaxed"]{--row-h:46px;--row-h-lg:54px;--card-pad:18px;--card-pad-lg:24px}

/* ---- print: a report body must survive without the chrome ------------- */
@media print{
  .p-filters,.p-actions{display:none !important}
  .p-mapband{display:none !important}
  .p-code{max-height:none;border:1px solid #ccc}
}

/* ==========================================================================
   Integration pass — defects found by rendering every page at 1600×1000.
   Each rule below exists because a real screen broke without it.
   ========================================================================== */

/* A card head whose tools are a chip row was forcing the title to wrap one
   word per line. Let the head wrap instead, and keep the title first. */
.m-card__head{flex-wrap:wrap;row-gap:8px}
.m-card__title{flex:1 1 200px;min-width:0}
.m-card__title h3{overflow-wrap:anywhere}
.m-card__tools{flex-wrap:wrap;row-gap:6px}
.m-card__tools--scroll{
  flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;max-width:100%;
}
.m-card__tools--scroll::-webkit-scrollbar{display:none}

/* Eight KPIs on an auto-fit grid came out 6 + 2 and the second row read as
   an orphan. Four across is the honest shape for eight. */
.m-kpis--4{grid-template-columns:repeat(4,minmax(0,1fr))}
.m-kpis--3{grid-template-columns:repeat(3,minmax(0,1fr))}
@media (max-width:1180px){ .m-kpis--4{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media (max-width:640px){ .m-kpis--4,.m-kpis--3{grid-template-columns:repeat(2,minmax(0,1fr))} }
/* A KPI note must never push the tile wider than its column. */
.m-kpi__x{min-width:0}
.m-kpi__d{flex-wrap:nowrap}
.m-kpi__d span{min-width:0}

/* A chip in a narrow filter rail truncates its label and keeps its count —
   the count is the part that makes the chip worth reading. */
.p-rail .m-chip,.m-chip--fit{max-width:100%}
.p-rail .m-chip > span:not([class]),
.m-chip--fit > span:not([class]){overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.p-rail .m-chip{justify-content:flex-start;width:100%}

/* Dense tables must not grow past their column. Long free text truncates to
   one line with the full value on the title attribute; an address gets two. */
.m-table td{max-width:0}
.m-table td.wrap{white-space:normal}
.m-table .cell-1{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.m-table .cell-2{
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;white-space:normal;line-height:1.4;
}
.m-table .shrink{max-width:none}
.m-ent__x{min-width:0}

/* A process strip inside a narrow detail panel scrolls rather than clipping,
   and says so with a fade at the trailing edge. */
.m-process{
  -webkit-mask-image:linear-gradient(to right,#000 0,#000 calc(100% - 20px),transparent 100%);
          mask-image:linear-gradient(to right,#000 0,#000 calc(100% - 20px),transparent 100%);
}
html[dir="rtl"] .m-process{
  -webkit-mask-image:linear-gradient(to left,#000 0,#000 calc(100% - 20px),transparent 100%);
          mask-image:linear-gradient(to left,#000 0,#000 calc(100% - 20px),transparent 100%);
}
.m-process--wrap{flex-wrap:wrap;mask-image:none;-webkit-mask-image:none}
.m-process--wrap .m-process__s{flex:1 1 150px}

/* The three-rail workspace needs more room than 1600px leaves once the
   navigation is open. Drop the left rail one breakpoint earlier. */
@media (max-width:1560px){
  .m-grid--3rail{grid-template-columns:200px minmax(0,1fr) 320px}
}
@media (max-width:1400px){
  .m-grid--3rail{grid-template-columns:minmax(0,1fr) 330px}
  .m-grid--3rail > .p-rail{display:none}
  .m-grid--3rail.is-rail-open{grid-template-columns:220px minmax(0,1fr)}
  .m-grid--3rail.is-rail-open > .p-rail{display:block}
  .m-grid--3rail.is-rail-open > .p-detail{display:none}
}

/* A HUD panel must never eat more than a third of the map it sits on. */
.m-hud{max-width:min(320px,34%)}
/* — except the key, which is not a panel. It is a strip along the bottom
   edge, and a third of the map is exactly what it took when it was held to
   that width: six state counts and two symbol notes wrapped onto three
   lines and covered a municipality. Given the room it has, it is one line. */
.m-hud.m-legend-strip{max-width:calc(100% - 78px)}
.m-hud--bl,.m-hud--br{max-height:min(46%,320px)}

/* Six figures across, one row. The auto-fit grid was producing 6 + 2 and the
   second row pushed the map below the fold. */
.m-kpis--6{grid-template-columns:repeat(6,minmax(0,1fr))}
@media (max-width:1200px){ .m-kpis--6{grid-template-columns:repeat(3,minmax(0,1fr))} }
@media (max-width:760px){  .m-kpis--6{grid-template-columns:repeat(2,minmax(0,1fr))} }
