/* VertiServices — the UI kit (sprint ui-kit-foundation, K0, 8 Oct 2026)

   ONE shared CSS language for every page: one component per family, reading
   one set of tokens, so that one CSS change reflects on every page (operator,
   8 Oct 2026). Linked by every product page right AFTER style.css, with the
   same ?v= token; precached beside it in sw.js. Never @import'ed (rule E1).

   K0 (this sprint) defines TOKENS ONLY and points nothing visible at them:
   no product page changes by a pixel because this file exists (proven with
   scripts/visual-diff.mjs). style.css keeps every rule it has. The family
   sweeps move the components in here, one family per sprint:

     K1 buttons  ->  K2 filter chips + segmented choice  ->  K3 badges
     ->  page buckets (estimates, portal, installation-followup, projects,
         map, then 3-6 pages a sprint)  ->  tables LAST, in their own sprint(s)

   Operator decisions already taken for those sweeps (8 Oct 2026, mockup
   "UI Kit — Ortak Dil"): (a) the primary button is FLAT NAVY, the gradient
   stays on the page header band only (applied in K1); (b) a filter chip is ONE
   pill shape whose height comes from --chip-h, 32 px on a desk and 44 px on a
   phone, and the segmented single choice has the same height in an r10
   container (applied in K2); (c) the customer-facing pages (sign.html,
   privacy.html) load this file too, with the letterhead pixel-identical.

   THE RATCHET. scripts/check-kit-ratchet.mjs counts, per product page, the
   page-local CSS that styles a kit family (buttons, chips, tabs, badges,
   fields, modals/sheets, cards, empty/loading/toast, the page header) - in
   its <style>, in style="" attributes, and in CSS its modules inject - and
   FAILS when a count rises or a new page is not at zero. A rule that must
   stay local says so in its own body: kit-exempt, a colon and the reason, in
   a CSS comment. Table rules are counted in a family of their own and only
   reported until the table sprint. docs/design-system.md, "UI kit".

   TOKENS. Every value below is today's value of the thing it names: the
   heights and radii are the ones the approved mockup drew, the tones are
   today's badge and alert colours (style.css .badge-*, .alert.*), so a sweep
   that points a component at a token moves no colour by accident. */

:root {
  /* Control heights. --ctl-h is a button / input / house dropdown; -sm is the
     compact one (a table row action, a table filter chip); --chip-h is a
     filter chip and a segmented choice; --tab-h a tab. */
  --ctl-h: 34px;
  --ctl-h-sm: 28px;
  /* sprint kit-pilot-items (operator, 19 Oct 2026): -xs is the 24 px button
     (.btn-xs); --input-h the filter / toolbar / in-row input (.kit-input) -
     a FORM input (.kit-form, .kit-input-form) is --ctl-h, a button's height. */
  --ctl-h-xs: 24px;
  --input-h: 30px;
  --chip-h: 32px;
  --tab-h: 36px;

  /* Radii: a control, a pill (chip, badge), a segmented container. */
  --radius-ctl: 8px;
  --radius-pill: 999px;
  --radius-seg: 10px;

  /* The keyboard focus ring, in the navy's channels (--verti-navy-rgb). */
  --focus-ring: 0 0 0 3px rgba(var(--verti-navy-rgb), .28);

  /* Badge tones - a status maps to a TONE, never to a colour of its own.
       ok       .badge-status-on
       warn     .alert.warning (table.data tr.row-warn's background)
       danger   .alert.error   (table.data tr.row-danger's background)
       info     .badge-technician / -type-elevator / -work-maintenance
       neutral  .badge-viewer / -type-other / -work-meeting
       brand    the navy on its 50 tint */
  --tone-ok-bg: #D9F1E4;
  --tone-ok-fg: #1E6C49;
  --tone-warn-bg: #FBF2DA;
  --tone-warn-fg: #6E5318;
  --tone-danger-bg: #FBE9E9;
  --tone-danger-fg: #8C2A2A;
  --tone-info-bg: #DCEAF7;
  --tone-info-fg: #214E7E;
  --tone-neutral-bg: #E8ECF2;
  --tone-neutral-fg: #495568;
  --tone-brand-bg: var(--verti-navy-50);
  --tone-brand-fg: var(--verti-navy);

  /* A registered brand shape (rule Z1 reads any --brand-gradient* declaration
     as the register, check-page-conformance.mjs): the three-stop 90 degree
     navy -> purple -> orange, the strip under sign.html's brand bar. It is
     NOT --brand-gradient (that one holds the navy to 20 %), and the signing
     page must look exactly as it did, so its hand-written copy became this
     name rather than the house gradient. Written from the colour tokens. */
  --brand-gradient-3stop: linear-gradient(90deg, var(--verti-navy) 0%, var(--tke-purple) 55%, var(--tke-orange) 100%);

  /* The four role badges keep today's colours as tokens of their own
     (style.css .badge-admin / -manager / -technician / -viewer). */
  --role-admin-bg: #FCE3D9;
  --role-admin-fg: #9C3712;
  --role-manager-bg: #E7E0F2;
  --role-manager-fg: #4F2D6F;
  --role-tech-bg: #DCEAF7;
  --role-tech-fg: #214E7E;
  --role-viewer-bg: #E8ECF2;
  --role-viewer-fg: #495568;
}

/* The phone. Below 700 px is the fleet's phone everywhere a component already
   switches: the house dropdown opens its sheet (house-select.js PHONE_BELOW),
   the house sheet rises from the bottom edge instead of centring (style.css,
   .mobile-sheet at min-width 700px). A touch target is 44 px there. */
@media (max-width: 699.98px) {
  :root {
    --ctl-h: 44px;
    --chip-h: 44px;
    --tab-h: 44px;
  }
}
/* A phone page (body.mobile-body - the mobile-shell pages) is a phone at any
   width: its controls keep the 44 px tap target even when the page is opened
   on a desk (sprint ui-kit-buttons, K1). */
.mobile-body { --ctl-h: 44px; }

/* ===========================================================================
   BUTTONS (K1, sprint ui-kit-buttons, 8 Oct 2026; mockup "UI Kit - Ortak
   Dil", Buttons family). ONE button, defined here and nowhere else: a page
   writes the class name, never its own copy (the ratchet holds the button
   family at its floor - scripts/check-kit-ratchet.mjs, FAIL).

     .btn                 primary - FLAT NAVY (operator decision a); hover
                          --verti-navy-700. The brand gradient stays on the
                          page header band only (house rule B9).
     .btn-ghost           white, a rim, navy text - the secondary action
     .btn-danger          red fill - a destructive confirm
     .btn-ghost.btn-danger  red text on white - an undo, a cancel, a remove
     .btn-accent          TKE orange - the page's one "new" action
     .btn-ok / .btn-go    green (finish, approve) / amber (start, do it now) -
                          the field states the shared row button carried
                          (style.css .fr-btn.ok / .go, hotfix billable-jobs-ui)
     .btn-sm              --ctl-h-sm (28 px) - a compact toolbar / row action
     .btn-icon            square, icon only (keep the aria-label)
     .btn-block           full width
   States: :hover, :focus-visible (the --focus-ring), :active, :disabled,
   [aria-busy="true"] (working: full strength, progress cursor), offline
   (shell.js's [data-requires-online] guard), [hidden].

   Height comes from --ctl-h: 34 px on a desk, 44 px on a phone (below 700 px
   and on every body.mobile-body page). min-height, not height, so a button in
   a stretching row still stretches as it always did, and on a phone a long
   label (the az one) WRAPS inside the button instead of overflowing its row.

   Older names that remain ALIASES of the kit button (markup keeps them; the
   look is the kit's): .btn.ghost / .small / .danger / .icon (the Sprint 183
   puantaj pages), and the shared row buttons that lived in style.css -
   .fr-btn (unit task, billable jobs), .pf-btn (the photo slots), .ft-btn (the
   field tools under a textarea), .pcc-btn (the project contacts card),
   .btn-ai-fix (the AI text fix) and the house sheet header's Save / Cancel
   (.mobile-sheet-act .sv / .cn). Print hides the header's buttons as before
   (style.css @media print).

   THE [hidden] TRAP, canonical statement (Sprint 718; see also .row,
   .mobile-h1-action, .msh-ttabs in style.css and .offline-chip in shell.js).
   The `hidden` attribute contributes exactly one thing: the USER-AGENT rule
   `[hidden] { display: none }`. Origin is resolved BEFORE specificity, so the
   author-origin `display: inline-flex` below beats it outright and a
   `<button class="btn" hidden>` stays fully visible. Every permission-gated
   create button in this app is written that way, which is how view-only users
   were being shown ecNew / sqNew / esNew / esImport. Hence every display rule
   here has its [hidden] twin.
   =========================================================================== */
.btn,
.fr-btn, .pf-btn, .ft-btn, .pcc-btn, .btn-ai-fix {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: var(--ctl-h);
  padding: 0 14px;
  border: 1px solid transparent;
  border-radius: var(--radius-ctl);
  background: var(--verti-navy);
  color: var(--surface);
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 650;
  line-height: 1.25;
  letter-spacing: normal;
  text-transform: none;
  text-decoration: none;
  text-align: center;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .15s, border-color .15s, box-shadow .15s, transform .05s;
}
.btn[hidden], .fr-btn[hidden], .pf-btn[hidden], .ft-btn[hidden], .pcc-btn[hidden], .btn-ai-fix[hidden] { display: none; }
/* An <a class="btn"> is a button, not a link: no underline on hover either
   (style.css a:hover is (0,1,1)). */
.btn:hover { text-decoration: none; }
.btn:where(:not(:disabled)):hover,
.fr-btn.pri:where(:not(:disabled)):hover, .pf-btn.solid:where(:not(:disabled)):hover,
.ft-btn.btn-ai-fix:where(:not(:disabled)):hover, .btn-ai-fix:where(:not(:disabled)):hover { background: var(--verti-navy-700); border-color: transparent; }
.btn:focus-visible,
.fr-btn:focus-visible, .pf-btn:focus-visible, .ft-btn:focus-visible, .pcc-btn:focus-visible, .btn-ai-fix:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.btn:where(:not(:disabled)):active,
.fr-btn:where(:not(:disabled)):active, .pf-btn:where(:not(:disabled)):active, .ft-btn:where(:not(:disabled)):active,
.pcc-btn:where(:not(:disabled)):active, .btn-ai-fix:where(:not(:disabled)):active { transform: translateY(1px); }
.btn:disabled,
.fr-btn:disabled, .pf-btn:disabled, .ft-btn:disabled, .pcc-btn:disabled, .btn-ai-fix:disabled { opacity: .5; cursor: not-allowed; }
/* hotfix items-sync-buttons: a button that is WORKING (aria-busy) is disabled
   against a second click but must not look dead - full strength, a spinning
   icon and a "Syncing..." label say "wait, it is running". */
.btn[aria-busy="true"]:disabled,
.fr-btn[aria-busy="true"]:disabled, .ft-btn[aria-busy="true"]:disabled,
.btn-ai-fix[aria-busy="true"]:disabled { opacity: 1; cursor: progress; }
/* Offline: shell.js's guard disables a [data-requires-online] control and adds
   its plug; on a button the look is the kit's disabled one. */
.btn[data-requires-online][data-offline-disabled] { opacity: .5; cursor: not-allowed; }

/* ghost - the secondary action */
.btn.btn-ghost, .btn.ghost,
.fr-btn, .pf-btn, .ft-btn, .pcc-btn {
  background: var(--surface);
  color: var(--verti-navy);
  border-color: var(--border);
}
.btn.btn-ghost:where(:not(:disabled)):hover, .btn.ghost:where(:not(:disabled)):hover,
.fr-btn:where(:not(:disabled)):hover, .pf-btn:where(:not(:disabled)):hover,
.ft-btn:where(:not(:disabled)):hover, .pcc-btn:where(:not(:disabled)):hover {
  background: var(--verti-navy-50);
  border-color: var(--verti-navy);
}
/* the primary of an aliased family */
.fr-btn.pri, .pf-btn.solid, .ft-btn.btn-ai-fix {
  background: var(--verti-navy);
  color: var(--surface);
  border-color: transparent;
}
/* danger - a red fill */
.btn.btn-danger, .btn.danger { background: var(--danger); color: var(--surface); }
.btn.btn-danger:where(:not(:disabled)):hover, .btn.danger:where(:not(:disabled)):hover { background: #B83C3C; }
/* danger ghost - red text on white: an undo, a cancel, a remove */
.btn.btn-ghost.btn-danger, .btn.danger.ghost, .fr-btn.bad {
  background: var(--surface);
  color: var(--danger);
  border-color: var(--border);
}
.btn.btn-ghost.btn-danger:where(:not(:disabled)):hover, .btn.danger.ghost:where(:not(:disabled)):hover,
.fr-btn.bad:where(:not(:disabled)):hover { background: var(--tone-danger-bg); border-color: var(--danger); }
/* accent - TKE orange */
.btn.btn-accent { background: var(--tke-orange); color: var(--surface); }
.btn.btn-accent:where(:not(:disabled)):hover { background: #C9491E; }
/* ok - green: finish, approve, complete */
.btn.btn-ok, .fr-btn.ok { background: #15803D; color: var(--surface); border-color: transparent; }
.btn.btn-ok:where(:not(:disabled)):hover, .fr-btn.ok:where(:not(:disabled)):hover { background: #116632; border-color: transparent; }
/* go - amber: start, do it now (#B45309 is 5.02:1 under white). A row button
   that is a TOGGLE (the Before-photo exit on the Billable Jobs phone) shows
   its pressed state in the same amber. */
.btn.btn-go, .fr-btn.go, .fr-btn[aria-pressed="true"] { background: #B45309; color: var(--surface); border-color: transparent; }
.btn.btn-go:where(:not(:disabled)):hover, .fr-btn.go:where(:not(:disabled)):hover,
.fr-btn[aria-pressed="true"]:where(:not(:disabled)):hover { background: #92400E; border-color: transparent; }

/* sizes */
.btn.btn-sm, .btn.small,
.ft-btn, .pcc-btn, .btn-ai-fix {
  min-height: var(--ctl-h-sm);
  padding: 0 10px;
  gap: 5px;
  font-size: 12.5px;
}
.btn.btn-icon, .btn.icon {
  width: var(--ctl-h);
  height: var(--ctl-h);
  min-width: var(--ctl-h);
  padding: 0;
}
.btn.btn-sm.btn-icon, .btn.small.icon {
  width: var(--ctl-h-sm);
  height: var(--ctl-h-sm);
  min-width: var(--ctl-h-sm);
}
/* .btn-xs (sprint kit-pilot-items, operator 19 Oct 2026, decision 4): the
   24 px size - a bulk bar's actions, a row's icon button, a value chooser
   inside a row. A SIZE, so it also sizes a button that keeps a colour of its
   own (the navy bulk bar's white buttons): height, padding, gap and font come
   from here, the colours from the button's family. Like -sm it is 44 px on a
   phone (--ctl-h-xs below). Written on the element (button.btn-xs) so it
   outranks a page's single-class look rule that also sizes the button. */
button.btn-xs, a.btn-xs, .btn.btn-xs {
  height: auto;
  min-height: var(--ctl-h-xs);
  padding: 0 8px;
  gap: 4px;
  font-size: 11.5px;
}
.btn.btn-xs.btn-icon {
  width: var(--ctl-h-xs);
  height: var(--ctl-h-xs);
  min-width: var(--ctl-h-xs);
  padding: 0;
}
.btn.btn-block { width: 100%; }
/* .btn-icon WITHOUT .btn is the older standalone square of Raw Records' row
   actions - a TABLE's, kept exactly as it was (32 px, white, a rim) until the
   table sprint makes those rows .btn.btn-ghost.btn-sm.btn-icon. */
.btn-icon:not(.btn) {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border: 1px solid var(--border);
  border-radius: var(--radius-ctl);
  background: var(--surface);
  cursor: pointer;
  font-size: 16px;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
  color: var(--text);
}
.btn-icon:not(.btn):hover { background: var(--verti-navy-50); border-color: var(--verti-navy); }
.btn-icon:not(.btn).btn-icon-danger { color: var(--danger); }
.btn-icon:not(.btn).btn-icon-danger:hover { background: var(--tone-danger-bg); border-color: var(--danger); }
.btn-icon:not(.btn):disabled { opacity: 0.5; cursor: not-allowed; }
/* A button that shows an upload's progress (api.js uploadWithProgress: the
   Import buttons of projects, units, faults and service records) carries a
   .btn-progress-fill bar behind its .btn-label; while it runs it is disabled
   but not dimmed. */
.btn:has(> .btn-progress-fill) { position: relative; overflow: hidden; }
.btn:has(> .btn-progress-fill):disabled { opacity: 1; cursor: progress; }
.btn > .btn-progress-fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: 0%;
  background: rgba(34, 197, 94, .30);
  transition: width .25s ease-out;
  pointer-events: none; z-index: 0;
}
.btn > .btn-label { position: relative; z-index: 1; }
/* The AI text fix sits INLINE beside a field's label: its 28 px box is pulled
   into the label's line (negative block margins) so the label row keeps its
   height - the button changed, the form did not. */
.btn-ai-fix { margin: -4px 0 -4px 8px; vertical-align: middle; }
.ft-btn.btn-ai-fix { margin: 0; }

/* The house sheet header's Save + Cancel pair (style.css .mobile-sheet-act):
   Save LEFT of Cancel, in the header, on the brand band - kit height, the
   white Save and the glass Cancel (the approved mockup's sheet header). */
.mobile-sheet-act button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 34px;
  padding: 0 13px;
  border: 0;
  border-radius: var(--radius-ctl);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 800;
  line-height: 1.25;
  white-space: nowrap;
  cursor: pointer;
}
.mobile-sheet-act button[hidden] { display: none; }
.mobile-sheet-act .sv { background: var(--surface); color: var(--verti-navy); }
.mobile-sheet-act .cn { background: rgba(255, 255, 255, .2); color: var(--surface); }
.mobile-sheet-act button:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(255, 255, 255, .45); }
.mobile-sheet-act button:disabled { opacity: .5; cursor: not-allowed; }

/* The phone: a long label wraps inside its button (two lines fit in 44 px)
   and a button never grows past its row. */
@media (max-width: 699.98px) {
  .btn,
  .fr-btn, .pf-btn, .ft-btn, .pcc-btn {
    max-width: 100%;
    white-space: normal;
    overflow-wrap: break-word;
  }
}
/* ---- K2 chips + segmented ---- */
/* ===========================================================================
   FILTER CHIPS + THE SEGMENTED CHOICE (K2, sprint ui-kit-chips, 8 Oct 2026;
   mockup "UI Kit - Ortak Dil", Filter chips family, operator decision b).
   ONE filter chip and ONE segmented single choice, defined here and nowhere
   else: a page writes the class name, never its own copy (the ratchet holds
   the chip family at its floor - scripts/check-kit-ratchet.mjs, FAIL).

     .mobile-chips        the chip row: wraps, 6 px gap (and the 12 px under
                          it the row always had)
     .mobile-chips.chips-scroll  a row that SCROLLS sideways instead of
                          wrapping (a phone strip that already scrolled)
     .mobile-chip         ONE PILL (--radius-pill), height --chip-h: 32 px on a
                          desk, 44 px on a phone (below 700 px and on every
                          body.mobile-body page) - the tap target
     .mobile-chip .chip-n a count inside the pill (tabular figures)
     .mobile-chip .chip-cv  the chevron of a FACET chip - a chip that opens a
                          multi-pick list (multiPick({ trigger }))
     .mobile-chip + .chip-x  the round clear after a SET facet chip (below)
     .seg-choice          the segmented single choice, full width (a phone
                          sheet, a form): equal shares, a long label wraps
                          inside its own segment
     .seg-choice.inline   the desk form: content width
   The name is .mobile-chip, not a new .chip: the existing house chip was
   written by 5 product pages (mobile-finance, mobile-photo, projects,
   unit-photos, app-ui - through mobile-units.js and unit-detail-modal.js),
   while the two pages that own a local `.chip` (attendance's status chip,
   tasks' dismissible scope tag) use it for a badge and a tag, not a filter.

   STATE. Selected is the ARIA attribute - aria-pressed on a multi toggle,
   aria-checked on a single choice - read the same way on every page; .active
   and .on (the classes the older page scripts toggle) are its aliases, so a
   page's click handler stays as it was. Navy fill when selected (the house
   rule: a FILTER is VERTI NAVY when pressed; the gradient is the buttons').
   States: :hover (navy rim and ink), :focus-visible (--focus-ring), selected,
   :disabled (the kit's disabled look; no data-requires-online is added),
   [hidden]. The table's filter-row chip (.dt-chip, inside a th) is a TABLE
   element and keeps its look until the table sprint (style.css).
   =========================================================================== */
.mobile-body { --chip-h: 44px; }

/* THE COMPACT BUTTON ON A PHONE (K2, the Sef's addition to the brief, 8 Oct
   2026; house tap-target rule mobile.2). --ctl-h-sm (.btn-sm, .btn-sm.btn-icon)
   is 28 px on a desk and 44 px wherever --ctl-h is: below 700 px and on every
   body.mobile-body page. K1 left four page rules holding a compact button at a
   touch height (elevator-catalog's phone sheet, mobile-report's Retry,
   mobile-photo's Approve / Reject; portal's answer bar is a desk floor of
   regular buttons and stays) - the token holds them now. */
@media (max-width: 699.98px) {
  :root { --ctl-h-sm: 44px; --ctl-h-xs: 44px; --input-h: 44px; }
}
.mobile-body { --ctl-h-sm: 44px; --ctl-h-xs: 44px; --input-h: 44px; }
.mobile-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0 0 12px; }
.mobile-chips[hidden] { display: none; }
.mobile-chips.chips-scroll {
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.mobile-chips.chips-scroll::-webkit-scrollbar { display: none; }
.mobile-chips.chips-scroll > .mobile-chip { flex: none; }
.mobile-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  box-sizing: border-box;
  min-height: var(--chip-h);
  margin: 0;
  padding: 0 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: #374151;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.25;
  font-variant-numeric: tabular-nums;
  letter-spacing: normal;
  text-transform: none;
  text-decoration: none;
  text-align: center;
  white-space: nowrap;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color .15s, border-color .15s, color .15s, box-shadow .15s;
}
.mobile-chip[hidden] { display: none; }
/* hover is for a chip that is NOT selected: a pressed chip stays navy under the
   pointer, whatever order a page or the kit page's forced states put the rules in */
.mobile-chip:where(:not(:disabled):not([aria-pressed="true"]):not([aria-checked="true"]):not(.active):not(.on)):hover { border-color: var(--verti-navy); color: var(--verti-navy); text-decoration: none; }
.mobile-chip:hover { text-decoration: none; }
.mobile-chip:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.mobile-chip:is([aria-pressed="true"], [aria-checked="true"], .active, .on) {
  background: var(--verti-navy);
  border-color: var(--verti-navy);
  color: var(--surface);
}
.mobile-chip:disabled, .mobile-chip[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
/* A label that can outgrow its row (a facet value, a site name) sits in a
   .chip-l and is cut with an ellipsis - only on a chip that carries the whole
   label in its title (the implied state "ellipsis only with a title"). */
.mobile-chip { max-width: 100%; }
.mobile-chip .chip-l { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* a count inside the pill or the segment: orange figures, white when selected */
:is(.mobile-chip, .seg-choice > button) .chip-n { font-weight: 800; color: var(--tke-orange); font-variant-numeric: tabular-nums; }
.mobile-chip:is([aria-pressed="true"], [aria-checked="true"], .active, .on) .chip-n,
.seg-choice > button:is([aria-checked="true"], [aria-pressed="true"], .on, .active) .chip-n { color: var(--surface); }

/* THE FACET CHIP (sprint part-taxonomy, 10 Oct 2026; the part picker's filter
   row, operator decision A). The same pill, at the same --chip-h, opening a
   multi-pick list: unset it reads its name and a chevron ("Part Type" + the
   .chip-cv), set it is selected (.on) and reads "Part Type: Contactor +1", and
   the round clear right after it (.chip-x) empties the facet in one tap. The
   clear is its OWN button (aria-label common.clear) - a button never sits
   inside a button - laid over the chip's right end: a --chip-h square (32 on
   a desk, 44 on a phone - the tap target), the chip keeping that much padding
   so no text sits under it. It is drawn only after a set chip, in a
   .chips-scroll row, where it can never wrap away from its chip. */
.mobile-chip .chip-cv { font-size: 10px; opacity: .7; }
.mobile-chip:has(+ .chip-x) { padding-right: calc(var(--chip-h) + 2px); }
.mobile-chips > .chip-x {
  flex: none;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  box-sizing: border-box;
  width: var(--chip-h);
  min-height: var(--chip-h);
  margin: 0 0 0 calc(-6px - var(--chip-h));
  padding: 0 9px 0 0;
  border: 0;
  border-radius: 0 var(--radius-pill) var(--radius-pill) 0;
  background: transparent;
  color: var(--surface);
  font-family: inherit;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.mobile-chips > .chip-x[hidden] { display: none; }
.mobile-chips > .chip-x > span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .22);
  transition: background-color .15s, box-shadow .15s;
}
.mobile-chips > .chip-x:hover > span { background: rgba(255, 255, 255, .4); }
.mobile-chips > .chip-x:focus-visible { outline: none; }
.mobile-chips > .chip-x:focus-visible > span { box-shadow: var(--focus-ring); }

/* The segmented choice - ONE row of 2-5 options (operator: "ikili, uclu,
   dortlu"), the chosen one navy. Equal shares, and the automatic minimum of a
   flex item keeps the longest word whole: a long label wraps inside its own
   segment while the short ones give way. The font steps down by option count
   so five fit a Samsung A56 (360 px). NO default where the choice is the
   user's: an unanswered row wears .need until it is answered (house-sheet.js
   sheetMissing). The container is the r10 box (--radius-seg).
   HEIGHT (--seg-opt-h, the option's own height): on a desk the WHOLE control
   is --chip-h tall, as a chip beside it is (the option is --chip-h less the
   box's two 1 px rims: 30 + 2 = 32); on a phone (below 700 px and on every
   body.mobile-body page) each OPTION is the 44 px tap target itself, so the
   box is 46 - the house tap-target rule counts the thing you press. */
.seg-choice {
  --seg-opt-h: calc(var(--chip-h) - 2px);
  display: flex;
  width: 100%;
  box-sizing: border-box;
  margin: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-seg);
  overflow: hidden;
  background: var(--surface);
}
.mobile-body .seg-choice { --seg-opt-h: var(--chip-h); }
.seg-choice[hidden] { display: none; }
.seg-choice > button {
  flex: 1 1 0;
  min-height: var(--seg-opt-h);
  margin: 0;
  padding: 6px 6px;
  border: 0;
  border-right: 1px solid var(--border);
  border-radius: 0;
  background: var(--surface);
  color: var(--verti-navy);
  font: inherit;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  white-space: normal;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color .15s, color .15s, box-shadow .15s;
}
.seg-choice > button[hidden] { display: none; }
.seg-choice > button:last-child { border-right: 0; }
.seg-choice > button:where(:not(:disabled):not([aria-pressed="true"]):not([aria-checked="true"]):not(.active):not(.on)):hover { background: var(--verti-navy-50); }
.seg-choice > button:is([aria-checked="true"], [aria-pressed="true"], .on, .active) { background: var(--verti-navy); color: var(--surface); }
.seg-choice > button:focus-visible { outline: none; box-shadow: inset var(--focus-ring); }
.seg-choice > button:disabled { color: #A6AFBE; cursor: not-allowed; }
/* a choice that is shown but locked (estimates' read-only header) */
.seg-choice > button:is([aria-checked="true"], [aria-pressed="true"], .on, .active):disabled { background: #6B7588; color: var(--surface); }
.seg-choice:not(.inline):has(> button:nth-child(4)) > button { font-size: 11.5px; padding: 6px 4px; }
.seg-choice:not(.inline):has(> button:nth-child(5)) > button { font-size: 10.5px; padding: 6px 3px; }
.seg-choice.need { border: 1.4px dashed #B45309; }
/* The DESK form (sprint w7-desk-shell, the operator's W7 M2 A, 6 Oct 2026):
   content width, the same --chip-h and r10 box. Under a coarse pointer (a
   tablet at desk width) the options keep the 44 px tap target. */
.seg-choice.inline { display: inline-flex; width: auto; max-width: 100%; vertical-align: middle; }
.seg-choice.inline > button {
  flex: 0 0 auto;
  padding: 0 13px;
  white-space: nowrap;
}
@media (pointer: coarse) {
  .seg-choice.inline > button { min-height: 44px; }
}

/* The phone: a long label (the az one) wraps inside its pill or segment
   instead of pushing the page sideways, and a chip never grows past its row. */
@media (max-width: 699.98px) {
  .seg-choice { --seg-opt-h: var(--chip-h); }
  .mobile-chip { max-width: 100%; white-space: normal; overflow-wrap: break-word; }
  .mobile-chips.chips-scroll > .mobile-chip { max-width: none; white-space: nowrap; }
  .seg-choice.inline > button { flex: 1 1 auto; white-space: normal; }
  /* a choice wider than its row scrolls sideways inside its own box rather
     than cutting its last options off (faults' six sources at 360 px) */
  .seg-choice.inline { overflow-x: auto; scrollbar-width: none; }
  .seg-choice.inline::-webkit-scrollbar { display: none; }
}

/* ---- K3 badges + cards ---- */
/* ===========================================================================
   BADGES (K3, sprint ui-kit-badges-cards, 9 Oct 2026; mockup "UI Kit - Ortak
   Dil", Badges family). ONE badge, defined here and nowhere else: a status, a
   category, a role or a flag is `.badge` plus a TONE - never a colour of its
   own (the ratchet holds the badge family at its floor).

     .badge               the pill - and the NEUTRAL tone, so a status the
                          page's map does not know is grey, never blank
     .badge-ok            done, paid, active, live         (--tone-ok-*)
     .badge-warn          waiting, due, partly, stale      (--tone-warn-*)
     .badge-danger        open fault, overdue, failed, off (--tone-danger-*)
     .badge-info          in progress, submitted, a type   (--tone-info-*)
     .badge-neutral       closed, none, other, skipped     (--tone-neutral-*)
     .badge-brand         ours, installation, the company  (--tone-brand-*)
     .badge-admin / -manager / -technician / -viewer
                          the four ROLE badges keep their own colours (--role-*)
     .badge-solid         an alarm: the tone's ink as the fill, white text
     .badge-sm            compact - beside a title, in a dense phone card or table row
     .badge-case          mixed case - a name or a sentence, not a status word
     .badge-fit           inside a fixed cell: ellipsis (write the full word
                          in the title attribute)
     .badge-ring          an inset ring in the ink - a kind set apart within
                          its tone (an R0 contract beside an R, Sprint 748)
     .badge > .dot        a 6 px dot in the ink colour before the word

   WHICH TONE is the page's decision, per ENTITY, drawn from the colour that
   entity's status had before K3 (a fault's Open is red - danger; a
   correction's Open was grey - neutral): the maps live where the markup is
   written. docs/design-system.md, "K3".

   The box is the badge of before K3 (style.css .badge): 3 / 8 px, 11 px bold
   uppercase, so a table row that holds one keeps its height. It never wraps
   (an az status word stays one pill); a cell too narrow for it uses
   .badge-fit.
   =========================================================================== */
.badge {
  display: inline-block;
  padding: 3px 8px;
  border-radius: var(--radius-pill);
  background: var(--tone-neutral-bg);
  color: var(--tone-neutral-fg);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  white-space: nowrap;
}
.badge[hidden] { display: none; }
.badge-ok      { background: var(--tone-ok-bg);      color: var(--tone-ok-fg); }
.badge-warn    { background: var(--tone-warn-bg);    color: var(--tone-warn-fg); }
.badge-danger  { background: var(--tone-danger-bg);  color: var(--tone-danger-fg); }
.badge-info    { background: var(--tone-info-bg);    color: var(--tone-info-fg); }
.badge-neutral { background: var(--tone-neutral-bg); color: var(--tone-neutral-fg); }
.badge-brand   { background: var(--tone-brand-bg);   color: var(--tone-brand-fg); }
.badge-admin      { background: var(--role-admin-bg);   color: var(--role-admin-fg); }
.badge-manager    { background: var(--role-manager-bg); color: var(--role-manager-fg); }
.badge-technician { background: var(--role-tech-bg);    color: var(--role-tech-fg); }
.badge-viewer     { background: var(--role-viewer-bg);  color: var(--role-viewer-fg); }
/* solid: the tone's ink as the fill (every --tone-*-fg holds white text) */
.badge.badge-solid                { background: var(--tone-neutral-fg); color: var(--surface); }
.badge.badge-solid.badge-ok       { background: var(--tone-ok-fg); }
.badge.badge-solid.badge-warn     { background: var(--tone-warn-fg); }
.badge.badge-solid.badge-danger   { background: var(--tone-danger-fg); }
.badge.badge-solid.badge-info     { background: var(--tone-info-fg); }
.badge.badge-solid.badge-brand    { background: var(--tone-brand-fg); }
.badge.badge-sm   { padding: 2px 6px; font-size: 10px; letter-spacing: 0.2px; }
.badge.badge-case { text-transform: none; letter-spacing: 0; }
.badge.badge-fit  { max-width: 100%; overflow: hidden; text-overflow: ellipsis; vertical-align: middle; }
.badge.badge-ring { box-shadow: inset 0 0 0 1px currentColor; }
/* a badge whose title explains it (a tooltip) says so under the pointer */
.badge[title] { cursor: help; }
.badge > .dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 5px;
  border-radius: 50%;
  background: currentColor;
  vertical-align: 1px;
}

/* ===========================================================================
   CARDS + KPI TILES (K3; mockup "UI Kit - Ortak Dil", Cards / KPI family).

     .card                the surface: white, a rim, --radius, --shadow-sm
     .card-pad            its padding, --card-pad (18 px desk, 14 px phone)
     .stat-grid           the KPI row: auto-fit columns of 180 px or more
     .stat-card           the KPI tile - .stat-value, .stat-label, .stat-sub;
                          a 4 px strip on top (the brand gradient)
       .t-ok / .t-warn / .t-danger / .t-info / .t-neutral
                          the strip in a TONE - the same meaning as the badge
       .accent / .purple / .green
                          the strip in the brand's orange / purple / green
       .hero              the brand gradient fill, white text
       .t-fill            with a tone: the tone TINTS the whole tile and its
                          figure (sprint item-history: D No recorded source
                          in warn, E No stock movement quiet grey)
       .stat-aside        a tile kept APART from its row's sum (Untracked:
                          not counted) - a dashed rim, no strip, a quiet figure
       .stat-sm           compact - a banner of 6 to 8 tiles, a phone pair
       .stat-click        a tile that filters the page: hover lifts it, a
                          pressed one (.on / aria-pressed="true") is ringed
       .stat-flat         no strip at all (a tab whose tiles are a quiet
                          breakdown - projects' customer tiles, Sprint 200)
     A tile may be a <div>, a <button> or an <a>: the kit resets the last two.
   A page lays the tiles out (its own grid of N columns stays, declared
   kit-exempt as layout); it never restyles the tile.
   =========================================================================== */
:root { --card-pad: 18px; }
@media (max-width: 699.98px) { :root { --card-pad: 14px; } }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.card-pad { padding: var(--card-pad); }

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr));
  gap: 14px;
  margin-bottom: 20px;
}
.stat-grid[hidden] { display: none; }
.stat-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 18px 16px;
  box-shadow: var(--shadow-sm);
  position: relative;
  overflow: hidden;
}
.stat-card[hidden] { display: none; }
/* a tile written as a <button> (it filters the page) or an <a> (it opens a
   page) reads like the others; so does a card written as a <button> */
button.stat-card { font: inherit; color: inherit; text-align: left; }
a.stat-card, a.stat-card:hover { color: inherit; text-decoration: none; }
button.card { font: inherit; color: inherit; text-align: left; cursor: pointer; }
/* Sprint 199: KPI cards carry a two-brand gradient strip across the top. */
.stat-card::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 4px;
  background: var(--brand-gradient);
}
.stat-card.accent::before    { background: var(--tke-orange); }
.stat-card.purple::before    { background: var(--tke-purple); }
.stat-card.green::before     { background: var(--success); }
.stat-card.t-ok::before      { background: var(--success); }
.stat-card.t-warn::before    { background: var(--warning); }
.stat-card.t-danger::before  { background: var(--danger); }
.stat-card.t-info::before    { background: var(--tone-info-fg); }
.stat-card.t-neutral::before { background: var(--muted); }
.stat-card.stat-flat::before { display: none; }
/* sprint item-history: the tone tints the tile (.t-fill), a tile set apart (.stat-aside) */
.stat-card.t-fill.t-ok      { background: var(--tone-ok-bg); }
.stat-card.t-fill.t-warn    { background: var(--tone-warn-bg); }
.stat-card.t-fill.t-danger  { background: var(--tone-danger-bg); }
.stat-card.t-fill.t-info    { background: var(--tone-info-bg); }
.stat-card.t-fill.t-neutral { background: #F6F8FB; }
.stat-card.t-fill.t-ok .stat-value      { color: var(--tone-ok-fg); }
.stat-card.t-fill.t-warn .stat-value    { color: var(--tone-warn-fg); }
.stat-card.t-fill.t-danger .stat-value  { color: var(--tone-danger-fg); }
.stat-card.t-fill.t-info .stat-value    { color: var(--tone-info-fg); }
.stat-card.t-fill.t-neutral .stat-value { color: var(--tone-neutral-fg); }
.stat-card.stat-aside { background: #FAFBFC; border: 1.5px dashed #A9B4C8; box-shadow: none; }
.stat-card.stat-aside::before { display: none; }
.stat-card.stat-aside .stat-value { color: var(--tone-neutral-fg); }
.stat-card.stat-sm.stat-aside .stat-value { font-size: 16px; }
/* Sprint 199 - the gradient "hero" KPI (full brand gradient, white text). */
.stat-card.hero { background: var(--brand-gradient); border-color: transparent; }
.stat-card.hero::before { display: none; }
.stat-card.hero .stat-value,
.stat-card.hero .stat-label,
.stat-card.hero .stat-sub { color: var(--surface); }
.stat-card .stat-value {
  font-size: 30px; font-weight: 800; color: var(--text);
  line-height: 1.1; margin-bottom: 4px;
}
.stat-card .stat-label {
  font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px;
  color: var(--muted); font-weight: 600;
}
.stat-card .stat-sub {
  font-size: 12px; color: var(--muted); margin-top: 6px;
}
/* the unit after a figure (AZN, / cap) - smaller and muted */
.stat-card .stat-value small { font-size: 12px; font-weight: 700; color: var(--muted); margin-left: 3px; }
/* compact */
.stat-card.stat-sm { padding: 10px 12px 9px; }
.stat-card.stat-sm .stat-value { font-size: 20px; margin-bottom: 2px; }
/* a whole-pixel line: 10.5px x the inherited 1.5 is a 15.75px line, and a quarter-pixel tile
   row puts everything under it on a quarter pixel - a sticky table column then rasters a
   quarter pixel off (a finance table under these tiles must not move a pixel) */
.stat-card.stat-sm .stat-label { font-size: 10.5px; letter-spacing: 0.3px; line-height: 16px; }
.stat-card.stat-sm .stat-sub { font-size: 10.5px; margin-top: 2px; line-height: 16px; }
/* KPI-06 the inline tile (hotfix finance-month-lock, operator 25 Oct 2026): the
   compact tile with its label on the figure's own line, to its right - one line
   per tile. A tile too narrow for both lets the label drop under the figure,
   never cuts it. kpiCardHtml({ inline: true }) writes .stat-sm.stat-inline. */
.stat-card.stat-inline { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 8px; }
.stat-card.stat-inline .stat-value { margin-bottom: 0; white-space: nowrap; }
.stat-card.stat-inline .stat-sub { flex-basis: 100%; }
/* the ? keeps its 22 px clear of the LAST item only: on one line the figure's
   own 22 px would sit between the figure and its label */
.stat-card.stat-inline:has(> .htip.stat-tip) > .stat-value { padding-right: 0; }
/* a tile that filters the page (a <button> or [role=button]) */
.stat-card.stat-click { cursor: pointer; transition: box-shadow .15s, transform .12s; }
.stat-card.stat-click:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); }
.stat-card.stat-click:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.stat-card.stat-click.on,
.stat-card.stat-click[aria-pressed="true"] { box-shadow: inset 0 0 0 2px var(--verti-navy); }
.stat-card.stat-click.on:focus-visible,
.stat-card.stat-click[aria-pressed="true"]:focus-visible { box-shadow: inset 0 0 0 2px var(--verti-navy), var(--focus-ring); }
@media (prefers-reduced-motion: reduce) {
  .stat-card.stat-click, .stat-card.stat-click:hover { transition: none; transform: none; }
}

/* ===========================================================================
   THE PAGE TABS (TAB-01, sprint page-tabs-kit, operator 19 Oct 2026: "Uygulamadaki
   tum tablari ortak ve ayni yapalim" - option A of the samples, the folder tab
   with the brand-gradient underline). ONE tab strip for every page whose tabs
   move between SECTIONS of the page; a strip that picks a VALUE (a filter, a
   view mode, a form mode) is the segmented choice (.seg-choice) or a chip,
   never this. The values are .pb-tab's (style.css, Sprint 399 - install-tabs),
   moved here unchanged, so a page that wore .pb-tabs renders pixel for pixel
   what it did.
     .kit-tabs        the strip (role="tablist"): a flex row on a 1 px rule
     .kit-tab         one tab (role="tab"); a <button>, or an element with
                      aria-disabled="true" for a tab that is not open yet
     the selected tab aria-selected="true" - kit-tabs.js keeps it equal to
                      the page's own state class (.active / .on), so a page
                      toggling its class needs no other change
     .kit-tabs--touch the phone size (44 px, --tab-h) on any width: a phone
                      page; below 700 px (the kit's phone, --tab-h) every
                      strip takes it and becomes ONE row that scrolls sideways
                      with no visible scrollbar
   A page keeps its own class beside the kit's (.pb-tab, .it-tab, .ml-tab ...)
   as a HOOK only - its tests and its JS read it - and never a look rule on it
   (scripts/check-kit-ratchet.mjs, the tab floor). Layout stays the page's:
   where the strip sticks, its margin in a toolbar row.
   =========================================================================== */
.kit-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin: 0 0 16px; flex-wrap: wrap; }
.kit-tabs[hidden] { display: none; }
.kit-tab { padding: 8px 16px 10px; font-weight: 700; font-size: 13px; color: var(--muted); cursor: pointer;
           border-radius: 8px 8px 0 0; position: relative; background: transparent; border: 0; }
.kit-tab[hidden] { display: none; }
.kit-tab:is(.active, .on, [aria-selected="true"]) { color: var(--verti-navy); background: var(--surface); border: 1px solid var(--border); border-bottom-color: var(--surface); }
.kit-tab:is(.active, .on, [aria-selected="true"])::after { content: ""; position: absolute; left: 12px; right: 12px; bottom: 5px; height: 3px;
           border-radius: 2px; background: var(--brand-gradient); }
.kit-tab:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.kit-tab[aria-disabled="true"] { opacity: .55; cursor: default; }
/* a count inside a tab: the tab's own figure, never a badge of its own colour */
.kit-tab .kit-tab-n { margin-left: 6px; font-weight: 800; color: var(--verti-navy); font-variant-numeric: tabular-nums; }
/* the phone size, and the one row that scrolls (a strip that would wrap to two
   rows on a 360 px phone becomes a scroller; the right-edge fade says "there is
   more" only while the row can still scroll right) */
@property --kt-fade { syntax: '<length>'; inherits: false; initial-value: 0px; }
@keyframes kit-tabs-fade { 0%, 92% { --kt-fade: 32px; } 100% { --kt-fade: 0px; } }
.kit-tabs--touch > .kit-tab, .mobile-body .kit-tabs > .kit-tab { min-height: 44px; display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; }
.kit-tabs--touch > .kit-tab[hidden], .mobile-body .kit-tabs > .kit-tab[hidden] { display: none; }
@media (max-width: 699.98px) {
  .kit-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - var(--kt-fade)), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - var(--kt-fade)), transparent);
  }
  .kit-tabs::-webkit-scrollbar { display: none; }
  .kit-tabs > .kit-tab { flex: 0 0 auto; white-space: nowrap; min-height: var(--tab-h); display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; }
  .kit-tabs > .kit-tab[hidden] { display: none; }
  @supports (animation-timeline: scroll()) {
    .kit-tabs { animation: kit-tabs-fade linear both; animation-timeline: scroll(self inline); }
  }
}
@media print {
  .kit-tabs { display: none !important; }
}

/* ===========================================================================
   THE SWITCH (hotfix mobile-kit-2, operator 9 Oct 2026: the Out of Service
   switch is the kit switch, never a hand-built copy). ONE on / off switch for
   a yes / no that is a STATE (Out of Service, Fixed on the spot, Back in
   service). Moved here unchanged from style.css (Sprint 450's wide switch,
   Sprint 532's small one).

     .fr-tgl              the switch, 72 x 32 - a row of its own (the report
                          form's Out of Service row, style.css .fr-oos)
     .fr-tgl.sm           compact, 44 x 24 - inline in a row of text (a unit
                          group header, the fixed-on-the-spot row, the phone
                          fault form's and close sheet's rows)
     .fr-tgl.tgl-ok       ON is green - a switch whose yes is the GOOD answer
                          (Back in service); the default ON is red, the unit
                          is down
   STATE. ON is the ARIA attribute - role="switch" aria-checked="true" - and
   .on its alias (the older page scripts toggle the class), read the same way
   on every page. States: :focus-visible (--focus-ring), :disabled (half
   strength; the fixed-on-the-spot row keeps its own cursor), [hidden].
   =========================================================================== */
.fr-tgl {
  position: relative;
  flex: 0 0 auto;
  width: 72px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: #DDE3EE;
  cursor: pointer;
  transition: background .15s;
  -webkit-tap-highlight-color: transparent;
}
.fr-tgl[hidden] { display: none; }
.fr-tgl::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .3);
  transition: left .15s;
}
.fr-tgl:is(.on, [aria-checked="true"]) { background: #DC2626; }
.fr-tgl:is(.on, [aria-checked="true"])::after { left: 43px; }
.fr-tgl.sm { width: 44px; height: 24px; }
.fr-tgl.sm::after { width: 18px; height: 18px; }
.fr-tgl.sm:is(.on, [aria-checked="true"])::after { left: 23px; }
.fr-tgl.tgl-ok:is(.on, [aria-checked="true"]) { background: #15803D; }
.fr-tgl:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.fr-tgl:disabled { opacity: .5; cursor: not-allowed; }
@media (prefers-reduced-motion: reduce) {
  .fr-tgl, .fr-tgl::after { transition: none; }
}

/* ===========================================================================
   THE EMPTY STATE (hotfix mobile-kit-2, operator 9 Oct 2026: ONE empty-state
   element for every phone list - .mf-empty, .fr-empty, .mpl-empty, .mc-empty,
   .td-empty and the rest were each page's own copy). What a list shows when
   it has no row to show: an icon that says which case it is, ONE line, at most
   one action. Drawn by mobile-shell.js emptyState(), never by hand.

     .empty-state            the block, in the list's place: a dashed frame on
                             white, centred - .empty-ic (a Font Awesome icon in
                             a round navy tint), .empty-tx (the line),
                             .empty-act (optional: one kit button)
     .empty-state.empty-sm   compact, inside a card or a section that has a
                             frame already: no frame, left-aligned, the icon
                             small before the line
     .empty-state.empty-err  could not load: the icon in the danger tone
   The icon names the case (emptyState's kind): fa-inbox nothing there,
   fa-hourglass-half loading, fa-triangle-exclamation could not load, fa-lock
   a desk-only step, fa-circle-info a hint, fa-circle-check all done. The
   desk's plain .empty (EMP-01) is a panel's line and stays as it is.
   =========================================================================== */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  box-sizing: border-box;
  width: 100%;
  margin: 0;
  padding: 16px 14px;
  border: 1px dashed var(--border);
  border-radius: 12px;
  background: var(--surface);
  color: var(--muted);
  font-size: 13px;
  line-height: 1.4;
  text-align: center;
}
.empty-state[hidden] { display: none; }
.empty-state > .empty-ic {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--verti-navy-50);
  color: var(--verti-navy);
  font-size: 16px;
}
.empty-state.empty-err > .empty-ic { background: var(--tone-danger-bg); color: var(--tone-danger-fg); }
.empty-state > .empty-tx { max-width: 34em; overflow-wrap: anywhere; }
.empty-state > .empty-act { display: flex; justify-content: center; margin-top: 2px; }
.empty-state.empty-sm {
  flex-direction: row;
  align-items: baseline;
  gap: 6px;
  padding: 6px 2px;
  border: 0;
  border-radius: 0;
  background: none;
  font-size: 11.5px;
  text-align: left;
}
.empty-state.empty-sm > .empty-ic {
  display: inline-block;
  width: auto;
  height: auto;
  background: none;
  color: inherit;
  font-size: 11px;
}
.empty-state.empty-sm.empty-err > .empty-ic { background: none; color: var(--tone-danger-fg); }

/* ===========================================================================
   THE MULTI-SELECT + THE HELP TIP (sprint part-taxonomy, 10 Oct 2026; the
   approved mockup's "Tooltip önizlemesi"). assets/js/multi-pick.js draws
   both - multiPick(), helpTipHtml(), chipsHtml() - and a page never builds a
   copy. The house dropdown (house-select.js) refuses `multiple`: a native
   <select multiple> is the retired look.

     .mpk                 the wrapper multiPick() draws into its host
     .mpk-btn             the face: the chosen values as chips, a chevron;
                          --ctl-h tall (34 desk / 44 phone), 44 in a .field
                          form beside the house inputs; .mpk-sm is the compact
                          face (--ctl-h-sm) for a dense table row
     .mpk-ph              the face's text when nothing is chosen (Unknown)
     .mpk-cell            ONE row of fixed-height kit badges (.badge-brand)
                          that NEVER WIDENS what it sits in (inline-size
                          containment; --mpk-fit-w is the width it asks a table
                          column for): what does not fit collapses into ONE
                          "+N" badge (.mpk-more, fitChips()) - one line on a
                          desk, two lines on a phone
     .mpk-pop             the desk list, in the house dropdown's popover
                          material (style.css .hsel-pop / .hsel-veil)
     .mpk-sheet           the phone list: the house bottom sheet, Done in its
                          head, thumb-sized rows on a white card
     .mpk-opt             a row (role=option): .mpk-box (the checkbox mark),
                          .mpk-nm (the name), the ? at the right end
     .htip                the ? - an 18 px ring; the press area is 28 px on a
                          desk and 44 px on a phone (its ::after)
     .htip-pop            THE tooltip of the document (#htipPop, one node for
                          every ? - never one per row): a navy bubble beside
                          the ?, 12.5 px text, at most 290 px wide
   States: the face's :hover / :focus-visible / [aria-expanded="true"] /
   :disabled; a row's :hover / :focus-visible / [aria-selected="true"]; the
   ?'s :hover / :focus-visible / open (aria-describedby names #htipPop);
   [hidden] on every one of them.
   =========================================================================== */
.mpk { position: relative; display: block; min-width: 0; }
.mpk[hidden] { display: none; }
.mpk-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  min-width: 0;
  min-height: var(--ctl-h);
  box-sizing: border-box;
  margin: 0;
  padding: 3px 9px 3px 5px;
  border: 1px solid var(--border);
  border-radius: var(--radius-ctl);
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  font-size: 13px;
  line-height: 1.25;
  text-align: left;
  cursor: pointer;
  transition: border-color .15s, box-shadow .15s;
}
.mpk-btn[hidden] { display: none; }
.mpk-btn:where(:not(:disabled)):hover { border-color: var(--verti-navy); }
.mpk-btn:focus-visible, .mpk-btn[aria-expanded="true"] {
  outline: none;
  border-color: var(--verti-navy);
  box-shadow: var(--focus-ring);
}
.mpk-btn:disabled { opacity: .6; cursor: not-allowed; background: #F3F4F6; }
.mpk-btn > .mpk-cell { flex: 1 1 auto; }
.mpk-btn .badge { cursor: inherit; }
.mpk-ph {
  flex: 1 1 auto;
  min-width: 0;
  padding-left: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--muted);
}
.mpk-cv {
  flex: none;
  width: 11px;
  height: 11px;
  margin-left: auto;
  opacity: .7;
  transition: transform var(--dur-pill) var(--ease-spring);
}
.mpk-btn[aria-expanded="true"] .mpk-cv { transform: rotate(180deg); }
.mpk-sm > .mpk-btn { min-height: var(--ctl-h-sm); padding-block: 2px; }
/* a .field form (the units and project modals): the house dropdown's 44 px row */
.field .mpk-btn { min-height: 44px; border-radius: var(--radius-sm); }

/* The chip cell. Fixed-height badges, so a row of 500 cells never reflows;
   inline-size containment, so the cell's chips never widen its table column
   (it asks for --mpk-fit-w and fills what it is given). */
.mpk-cell {
  --mpk-chip-h: 22px;
  --mpk-more-w: 34px;
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 4px;
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  contain: inline-size;
  contain-intrinsic-inline-size: var(--mpk-fit-w, 120px);
  vertical-align: middle;
}
.mpk-cell[hidden] { display: none; }
.mpk-cell > .badge {
  flex: none;
  box-sizing: border-box;
  height: var(--mpk-chip-h);
  line-height: calc(var(--mpk-chip-h) - 6px);
}
.mpk-cell > .badge.mpk-shrink { flex: 0 1 auto; min-width: 0; }
.mpk-cell > .mpk-more { width: var(--mpk-more-w); padding-left: 0; padding-right: 0; text-align: center; }
/* the phone: two lines of chips at most, then +N */
@media (max-width: 699.98px) {
  .mpk-cell { flex-wrap: wrap; max-height: calc(var(--mpk-chip-h) * 2 + 4px); }
}
.mobile-body .mpk-cell { flex-wrap: wrap; max-height: calc(var(--mpk-chip-h) * 2 + 4px); }

/* The list: desk popover (the .hsel-pop material) and the phone sheet. */
.mpk-pop { padding: 6px; }
.mpk-pop > .mpk-q { margin-bottom: 6px; }
.mpk-opts {
  position: relative;
  display: grid;
  gap: 1px;
  max-height: 280px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.mpk-opts[hidden] { display: none; }
.mpk-opt {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 32px;
  box-sizing: border-box;
  padding: 4px 6px 4px 9px;
  border-radius: 8px;
  color: var(--text);
  font-size: 13px;
  line-height: 1.3;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 130ms var(--ease-enter);
}
.mpk-opt[hidden] { display: none; }
.mpk-opt:hover { background: var(--verti-navy-50); }
.mpk-opt:focus-visible {
  outline: none;
  background: var(--verti-navy-50);
  box-shadow: inset 0 0 0 2px rgba(var(--verti-navy-rgb), .35);
}
.mpk-opt[aria-selected="true"] { color: var(--verti-navy); font-weight: 650; }
.mpk-box {
  display: grid;
  place-items: center;
  flex: none;
  width: 16px;
  height: 16px;
  box-sizing: border-box;
  border: 1.5px solid var(--muted);
  border-radius: 4px;
  background: var(--surface);
  color: var(--surface);
  transition: background-color 130ms var(--ease-enter), border-color 130ms var(--ease-enter);
}
.mpk-box[hidden] { display: none; }
.mpk-box svg { width: 10px; height: 10px; visibility: hidden; }
.mpk-opt[aria-selected="true"] .mpk-box { background: var(--verti-navy); border-color: var(--verti-navy); }
.mpk-opt[aria-selected="true"] .mpk-box svg { visibility: visible; }
.mpk-nm { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.mpk-sheet .mpk-qf { margin: 0; }
.mpk-sheet .mpk-opts {
  max-height: 60vh;
  padding: 4px;
  border: 1px solid #DDE3EE;
  border-radius: 12px;
  background: var(--surface);
}
.mpk-sheet .mpk-opt { min-height: 48px; padding: 8px 10px 8px 12px; font-size: 15px; gap: 10px; }
.mpk-sheet .mpk-box { width: 20px; height: 20px; border-radius: 5px; }
.mpk-sheet .mpk-box svg { width: 12px; height: 12px; }

/* The ? and the one tooltip. */
.htip {
  position: relative;
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 18px;
  height: 18px;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  border: 1.5px solid var(--muted);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--muted);
  font-family: inherit;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  vertical-align: middle;
  cursor: help;
  -webkit-tap-highlight-color: transparent;
  transition: color .15s, border-color .15s, box-shadow .15s;
}
.htip[hidden] { display: none; }
/* the press area: 28 px on a desk, the 44 px tap target on a phone */
.htip::after { content: ""; position: absolute; inset: -5px; }
.htip:hover, .htip[aria-describedby~="htipPop"] { color: var(--tke-orange); border-color: var(--tke-orange); }
.htip:focus-visible { outline: none; color: var(--tke-orange); border-color: var(--tke-orange); box-shadow: var(--focus-ring); }
.htip:disabled { opacity: .5; cursor: not-allowed; }
@media (max-width: 699.98px) {
  .htip::after { inset: -13px; }
}
.mobile-body .htip::after { inset: -13px; }
.htip-pop {
  position: fixed;
  z-index: 10048;   /* over the house dropdown's popover and sheet (10045), under the message box (10050) */
  left: 0;
  top: 0;
  box-sizing: border-box;
  width: max-content;
  max-width: min(290px, calc(100vw - 24px));
  padding: 9px 11px;
  border-radius: var(--radius-ctl);
  background: var(--verti-navy);
  color: var(--surface);
  font-size: 12.5px;
  font-weight: 400;
  line-height: 1.45;
  text-align: left;
  white-space: normal;
  overflow-wrap: break-word;
  box-shadow: 0 6px 20px rgba(var(--verti-navy-rgb), .28);
}
.htip-pop[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) {
  .mpk-btn, .mpk-cv, .mpk-opt, .mpk-box, .htip { transition: none; }
}
@media print {
  .htip, .htip-pop { display: none; }
}

/* ===========================================================================
   PROGRESS (sprint ledger-sync-now, 14 Oct 2026; App UI catalogue PRG-01 and
   PRG-02). The operator's standing order: every Sync button of the app shows
   ONE shared panel - assets/js/sync-progress.js syncProgress() draws it and
   injects no CSS; these rules are the whole look.
   PRG-01 .kit-prog > .kit-prog-fill: one bar, 8 px, on the neutral tone; the fill is
   the brand gradient while it runs and takes its end tone when it stops -
   .t-ok done, .t-warn paused, .t-danger failed, .t-neutral stopped - where it
   stood. Its width eases; reduced motion jumps.
   PRG-02 .syncp: the panel inline under a page header (never a sheet: the
   page stays usable) - its head (the title, the "Zoho calls today" counter),
   the steps (a dot, the name, the state as a .badge-sm, the bar and its count
   line, a detail line) and the state line (.syncp-s + a tone, Retry beside
   it). It fits a 360 px phone: the grid's middle column gives, every line
   wraps.
   =========================================================================== */
.kit-prog {
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--tone-neutral-bg);
  overflow: hidden;
}
.kit-prog > .kit-prog-fill {
  width: 0;
  height: 100%;
  border-radius: inherit;
  background: var(--brand-gradient);
  transition: width .35s ease-out, background-color .2s;
}
.kit-prog > .kit-prog-fill.t-ok { background: var(--success); }
.kit-prog > .kit-prog-fill.t-warn { background: var(--warning); }
.kit-prog > .kit-prog-fill.t-danger { background: var(--danger); }
.kit-prog > .kit-prog-fill.t-neutral { background: var(--muted); }

.syncp {
  margin: 0 0 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.syncp-h {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  color: var(--verti-navy);
  font-size: 13px;
  font-weight: 600;
}
.syncp-meta {
  margin-left: auto;
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
}
.syncp-meta[hidden] { display: none; }
.syncp-steps { margin: 0; padding: 0; list-style: none; }
.syncp-step {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr) auto;
  gap: 4px 8px;
  align-items: start;
  padding: 8px 10px;
}
.syncp-step[hidden] { display: none; }
/* a rule between the DRAWN steps (a reopened page draws its saved step alone) */
.syncp-step:not([hidden]) ~ .syncp-step:not([hidden]) { border-top: 1px solid var(--border); }
.syncp-dot {
  display: grid;
  place-items: center;
  box-sizing: border-box;
  width: 16px;
  height: 16px;
  margin-top: 1px;
  border-radius: var(--radius-pill);
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
}
.syncp-step[data-state="wait"] .syncp-dot { border: 2px solid var(--border); }
.syncp-step[data-state="run"] .syncp-dot { border: 2px solid var(--tone-info-fg); border-right-color: transparent; }
.syncp-step[data-state="ok"] .syncp-dot { background: var(--success); color: var(--surface); }
.syncp-step[data-state="warn"] .syncp-dot { background: var(--warning); color: var(--verti-navy); }
.syncp-step[data-state="bad"] .syncp-dot { background: var(--danger); color: var(--surface); }
.syncp-step[data-state="stop"] .syncp-dot { background: var(--muted); color: var(--surface); }
.syncp-name { min-width: 0; color: var(--text); font-size: 13px; font-weight: 600; overflow-wrap: anywhere; }
.syncp-step[data-state="wait"] .syncp-name { color: var(--muted); font-weight: 500; }
.syncp-pill { justify-self: end; }
.syncp-bar { grid-column: 2 / 4; display: grid; gap: 3px; }
.syncp-bar[hidden] { display: none; }
.syncp-barline {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 2px 8px;
  color: var(--text);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.syncp-eta { color: var(--muted); }
.syncp-eta:empty { display: none; }
.syncp-det { grid-column: 2 / 4; color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.syncp-det[hidden] { display: none; }
.syncp-s {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
  padding: 8px 10px;
  border-top: 1px solid var(--border);
  font-size: 12.5px;
}
.syncp-s[hidden] { display: none; }
.syncp-st { flex: 1 1 200px; min-width: 0; }
.syncp-s.t-info { background: var(--tone-info-bg); color: var(--tone-info-fg); }
.syncp-s.t-warn { background: var(--tone-warn-bg); color: var(--tone-warn-fg); }
.syncp-s.t-bad { background: var(--tone-danger-bg); color: var(--tone-danger-fg); }
.syncp-s.t-stop { background: var(--tone-neutral-bg); color: var(--text); }
.syncp-s.t-ok { background: var(--tone-ok-bg); color: var(--tone-ok-fg); }
@media (prefers-reduced-motion: no-preference) {
  .syncp-step[data-state="run"] .syncp-dot { animation: syncp-spin 1s linear infinite; }
}
@keyframes syncp-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .kit-prog > .kit-prog-fill { transition: none; }
}
@media print {
  .syncp { display: none; }
}

/* ===========================================================================
   THE LIST ROW, THE FOLD AND THE INLINE ALERT (sprint items-manage-tab, 24 Oct
   2026; App UI catalogue ROW-01 the row, ROW-02 the fold, ALR-01 the alert). A
   tool page's list of things to do or download - a checklist step, a file -
   is ONE row: a status badge (optional), the label with its meta line under
   it, the action(s) right; under 700 px the action takes the full width under
   the text. A row may end in a "What is this?" expander (.kit-row-help: a
   <details>, keyboard and screen reader for free).
   .kit-fold is a card whose head opens and closes it (a <details> with a
   <summary class="kit-fold-h">): the head is one line - the card's title,
   a badge, a chevron that turns when open.
   .alert.kit-alert is the shared .alert (style.css) laid out as one line
   that can carry a button: bold, flex, wraps on a phone.
   =========================================================================== */
.kit-rows { display: grid; gap: 8px; }
.kit-rows[hidden] { display: none; }
.kit-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  padding: 10px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 13px;
}
.kit-row[hidden] { display: none; }
.kit-row-main { flex: 1 1 220px; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.kit-row-label { font-weight: 700; color: var(--verti-navy); overflow-wrap: anywhere; }
.kit-row-meta { font-size: 12px; color: var(--muted); overflow-wrap: anywhere; }
.kit-row-meta[hidden] { display: none; }
.kit-row-act { display: flex; flex-wrap: wrap; gap: 8px; margin-left: auto; }
.kit-row-act:empty { display: none; }
/* a progress bar inside a row (PRG-01) runs the row's full width under its text */
.kit-row > .kit-prog { flex: 1 1 100%; }
.kit-row-help { flex-basis: 100%; font-size: 12px; color: var(--muted); }
.kit-row-help > summary { cursor: pointer; width: max-content; max-width: 100%; color: var(--verti-navy); font-weight: 700; }
.kit-row-help > summary:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: 4px; }
.kit-row-help > dl { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 2px 10px; margin: 6px 0 0; }
.kit-row-help dt { font-weight: 700; color: var(--text); }
.kit-row-help dd { margin: 0; overflow-wrap: anywhere; }
@media (max-width: 699.98px) {
  .kit-row-act { flex-basis: 100%; margin-left: 0; }
  .kit-row-act > .btn { flex: 1 1 auto; }
}

.kit-fold > .kit-fold-h {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  cursor: pointer;
  list-style: none;
}
.kit-fold > .kit-fold-h::-webkit-details-marker { display: none; }
.kit-fold > .kit-fold-h > h5 { margin: 0; }
.kit-fold > .kit-fold-h > .alert { flex: 1 1 220px; margin: 0; }
.kit-fold > .kit-fold-h:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-sm); }
.kit-fold-ic { margin-left: auto; color: var(--muted); transition: transform .15s; }
.kit-fold[open] > .kit-fold-h { margin-bottom: 10px; }
.kit-fold[open] > .kit-fold-h > .kit-fold-ic { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .kit-fold-ic { transition: none; }
}

.alert.kit-alert {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  margin: 12px 0 0;
  font-size: 13px;
  font-weight: 700;
}
.alert.kit-alert[hidden] { display: none; }
/* sprint stockcount-countable: the STATUS BAND - the same alert with an icon, a
   bold title over a plain body line (.kit-alert-text) and the button right; the
   info tone beside .warning. The text takes the line, so on a phone (360 px)
   the button drops under it. */
.alert.kit-alert.info { background: var(--tone-info-bg); color: var(--tone-info-fg);
                        border: 1px solid color-mix(in srgb, var(--tone-info-fg) 25%, transparent); }
.kit-alert-ic { flex: 0 0 auto; font-size: 16px; line-height: 1; }
.kit-alert-text { flex: 1 1 260px; min-width: 0; display: grid; gap: 2px; }
.kit-alert-text > span { font-size: 12.5px; font-weight: 400; overflow-wrap: break-word; }
.kit-alert-text + .btn { flex: 0 0 auto; }

/* ===========================================================================
   PAGE WIDTH (hotfix page-width, 9 Oct 2026). On a 32-inch screen a page
   whose content is narrow - few columns, cards, a form - is centred with its
   header at --page-max; a 13-15 inch laptop never reaches the cap, so nothing
   moves there. A page opts in with <body data-width="page">; a page whose
   table does not fit (wide tables, boards, grids, the map, month-column
   finance reports) simply does not opt in and keeps the full width. Opt-in,
   not a default, so each page moves only when the operator approved it.
   =========================================================================== */
:root { --page-max: 1380px; }
body[data-width="page"] main.content { max-width: var(--page-max); margin-inline: auto; width: 100%; }

/* ===========================================================================
   THE TABLE TOOLBAR'S RIGHT SLOT and THE INPUT (sprint kit-pilot-items,
   operator 19 Oct 2026, mockup claude.ai/artifact/WwwAqqZ7J1MdHsBre3J7af,
   decisions 1 and 2; the
   rule beside them: an element's LOOK is the kit's, identical everywhere, its
   PLACEMENT is the page's - and a placement two pages repeat becomes a named
   kit layout pattern).

     .dt-end              the table toolbar's right-hand slot: the table's own
                          actions, then the Columns button, one row, pinned
                          right - data-table.js toolbarHtml(left, { end })
                          writes it, a page never pins an action beside
                          Columns with rules of its own. Below 640 px it takes
                          the bar's full row, its buttons still on the right.
     .kit-input           a filter / toolbar / in-row input or select:
                          --input-h (30 px desk, 44 phone)
     .kit-input-form      a form input (a modal, a sheet): --ctl-h, the
                          height of the .btn beside it (34 desk, 44 phone)
     .kit-input-num       a figure: right-aligned, tabular digits
     .kit-filter          a container whose bare inputs and selects are
                          .kit-input; .kit-form the same for .kit-input-form
   Padding, radius, border, font and the focus ring are the kit's tokens; a
   WIDTH is the page's layout (a qty is narrow, a search is wide).
   =========================================================================== */
.dt-end { display: flex; align-items: center; gap: 9px; margin-left: auto; }
.dt-end[hidden] { display: none; }
@media (max-width: 639.98px) {
  .dt-end { flex: 1 0 100%; flex-wrap: wrap; justify-content: flex-end; }
}
.kit-input,
.kit-filter :is(input:not([type="checkbox"], [type="radio"], [type="file"], [type="range"], [type="color"]), select),
.kit-form :is(input:not([type="checkbox"], [type="radio"], [type="file"], [type="range"], [type="color"]), select) {
  box-sizing: border-box;
  height: var(--input-h);
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-ctl);
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  font-size: 12.5px;
  line-height: normal;
}
.kit-input.kit-input-form,
.kit-form :is(input:not([type="checkbox"], [type="radio"], [type="file"], [type="range"], [type="color"]), select) {
  height: var(--ctl-h);
  font-size: 13.5px;
}
.kit-input.kit-input-num { padding: 0 8px; text-align: right; font-variant-numeric: tabular-nums; }
.kit-input:hover,
.kit-filter :is(input, select):hover,
.kit-form :is(input, select):hover { border-color: var(--verti-navy); }
.kit-input:focus-visible,
.kit-filter :is(input, select):focus-visible,
.kit-form :is(input, select):focus-visible { outline: none; border-color: var(--verti-navy); box-shadow: var(--focus-ring); }
.kit-input:disabled,
.kit-filter :is(input, select):disabled,
.kit-form :is(input, select):disabled { background: var(--bg); color: var(--muted); cursor: not-allowed; }
.kit-input:disabled:hover { border-color: var(--border); }

/* ===========================================================================
   TITLE CASE ON LABELS (hotfix page-width, operator 9 Oct 2026: "every word of
   a multi-word label starts with a capital"). A PRESENTATION rule, not a copy
   change: the dictionaries keep sentence case (the strings also read as
   sentences in toasts and the manual), and only these label surfaces draw
   every word capitalised - the page title, buttons, the segmented choice,
   chips, tabs, the table title and the Columns button, the house dropdown's
   face. <html lang> is set by shell.js, so Turkish and Azerbaijani "i" become
   "I" with the dot, never a plain "I". Running text, hints, table cells and
   print are untouched.
   =========================================================================== */
.page-header h1, .ph-titlerow h1,
.btn, .fr-btn, .pf-btn, .ft-btn, .pcc-btn, .btn-ai-fix,
.seg-choice > button, .mobile-chip,
.kit-tab, .mobile-atab,
.dt-title, .dt-btn,
.hsel-btn .hsel-lbl { text-transform: capitalize; }
/* the connecting words stay small: i18n.js markSmallWords wraps them (operator, 9 Oct 2026) */
.tc-low { text-transform: lowercase; }
/* a tr/az word's dotted i: uppercase is language-aware, capitalize is not ("İş", never "Iş") */
.tc-up { text-transform: uppercase; }
@media print {
  .page-header h1, .ph-titlerow h1, .btn, .seg-choice > button, .mobile-chip, .kit-tab, .dt-title { text-transform: none; }
}

/* ===========================================================================
   THE KPI HELP TIP (sprint items-insights, operator 24 Oct 2026: "tek bir
   dosyadan ortak yapıda olsun ve değiştirdiğimiz zaman tüm uygulamada
   değişsin"; App UI HLP-01 + KPI-01..05). Every KPI tile carries the kit ?
   through kpi-row.js kpiRow({ items: [{ ..., help: { what, for } }] }) -
   help-tip.js draws it, ONE file; a page never hand-writes a tip and never
   writes the explanation inside the tile (.claude/rules/pages.md).
     .stat-card > .htip.stat-tip   the ? in the tile's top-right corner; the
                                   value and the label keep clear of it
     .htip-pop .htip-sec           a structured tip's two paragraphs, each led
       .htip-lbl                   by its bold label ("What it is" / "What it
                                   is for") - the SAME size as the text, bold
                                   only: no caps, no letter-spacing, no opacity
                                   (operator, mockup round 6)
   The ? keeps the kit's press area (28 px desk, 44 px on a phone), clipped
   by the tile's own edge. A tap pins the tip, a tap outside closes it.
   =========================================================================== */
.stat-card > .htip.stat-tip { position: absolute; top: 10px; right: 10px; z-index: 1; }
.stat-card.stat-sm > .htip.stat-tip { top: 8px; right: 8px; }
.stat-card:has(> .htip.stat-tip) > :is(.stat-value, .stat-label) { padding-right: 22px; }
.stat-card.hero > .htip.stat-tip { color: var(--surface); border-color: var(--surface); }
.htip-pop .htip-sec { margin: 0; }
.htip-pop .htip-sec + .htip-sec { margin-top: 6px; }
.htip-pop .htip-lbl { display: block; font-size: inherit; font-weight: 700; line-height: inherit; letter-spacing: normal; text-transform: none; opacity: 1; }
