/* GuerrillaRMS shell and shared components: the classic flat layout in the GuerrillaRMS identity
   (DESIGN.md). Colours come only from tokens.css. CSS glyphs are masks of single files in
   /assets/icons/ drawn in currentColor. */

*, *::before, *::after { box-sizing: border-box; }

html { font-size: var(--font-size-base); -webkit-text-size-adjust: 100%; scroll-padding-top: calc(var(--topbar-height) + 8px); }
body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--color-page-bg);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: var(--font-size-base);
  line-height: var(--line-height-base);
}

a { color: var(--color-link); text-decoration: none; }
a:hover { color: var(--color-link-hover); text-decoration: underline; }
:focus-visible { outline: var(--focus-width) solid var(--color-focus); outline-offset: var(--focus-offset); }
::selection { background: var(--color-accent-tint); }

h1, h2, h3, h4 { margin: 0; line-height: var(--leading-tight); font-weight: 600; }
p { margin: 0 0 .75em; }
p:last-child { margin-bottom: 0; }
img { max-width: 100%; }

.skip-link { position: absolute; left: -9999px; top: 0; background: var(--color-surface); padding: var(--space-2) var(--space-3); border-radius: var(--radius-control); z-index: 300; }
.skip-link:focus { left: 8px; top: 8px; }

.inline-form { display: inline; margin: 0; }
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.text-muted { color: var(--color-text-muted); }
.fa-fw { width: 1.28571429em; }

/* Line icons: icon() in app/lib/icons.php, grmsUi.icon() in app.js. Symbols carry no stroke width,
   so the size classes set it (2 on the 24 grid, 1.75 from 20px up). */
.icon {
  display: inline-block;
  flex: none;
  width: 1em;
  height: 1em;
  vertical-align: -0.125em;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  overflow: visible;
}
.icon-16 { width: 16px; height: 16px; }
.icon-18 { width: 18px; height: 18px; }
.icon-20 { width: 20px; height: 20px; stroke-width: 1.75; }
.icon-24 { width: 24px; height: 24px; stroke-width: 1.75; }

/* Codes a scanner, a printer or a person reads back: one character at a time (the mono's calt holds
   code ligatures). */
code, kbd, samp, .mono, .scan-field input { font-family: var(--font-mono); font-variant-ligatures: none; }
/* The mono reads large, so a code is set a step down from its text, snapped to a whole pixel so it
   lands on the scale (16 -> 14, 14 -> 13, 13 -> 12) and never under the floor; a page title keeps its size. */
code, kbd, samp { font-size: 0.93em; font-size: max(var(--text-xs), round(down, 0.93em, 1px)); font-weight: 500; }
.mono { font-size: 0.93em; font-size: max(var(--text-dense), round(down, 0.93em, 1px)); }
.page-title .mono { font-size: inherit; }

/* Mask glyphs: the shared part; each rule names its file with mask-image. The :has() selectors are a
   list of their own, so an engine without :has() still draws the others. */
.flash::before, .error-summary::before, .sidebar-panel > h3[role="button"]::after, .sort-link::after,
.warn-icon:empty::before, .btn-chevron:empty::before, .drag-handle.fa::before, .drag-handle > .fa::before,
.theme-menu > li > button[aria-checked="true"]::after, .scan-status::before {
  background-color: currentColor;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}
.action-list li > a:not(:has(> .fa, > .icon))::before, .action-list li > .inline-form > button:not(:has(> .fa, > .icon))::before,
.list-meta [data-dropdown]:not(:has(.fa, .icon))::after, .btn[data-dropdown]:not(:has(.fa-caret-down))::after,
.btn-link[data-dropdown]:not(:has(.fa, .icon))::after, .theme-tile:has(> input:checked) > .theme-tile-name::before {
  background-color: currentColor;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

@media (prefers-reduced-motion: reduce) {
  *, ::before, ::after { transition-duration: 0ms !important; animation-duration: 0ms !important; }
}

/* ------------------------------------------------------------ top bar (one 56px ink bar) */

.topbar {
  position: sticky;
  top: 0;
  z-index: 200;
  display: flex;
  align-items: stretch;
  height: var(--topbar-height);
  padding: 0 10px 0 var(--gutter);
  background: var(--color-topbar-bg);
  background-image: var(--theme-topbar-image, none);
  color: var(--color-topbar-muted);
}
.topbar :focus-visible { outline-color: var(--color-topbar-text); outline-offset: -2px; }
.brand { align-self: center; color: var(--color-topbar-muted); font-size: 17px; font-weight: 600; }
.brand:hover { color: var(--color-topbar-text); text-decoration: none; }
.nav-toggle { display: none; }

/* ------------------------------------------------------------ main nav */

.main-nav { display: flex; }
.nav-list { list-style: none; margin: 0; padding: 0; display: flex; gap: 0; }
.nav-item { position: relative; height: var(--topbar-height); }
.nav-dashboard { --nav-color: var(--module-dashboard); }
.nav-people { --nav-color: var(--module-people); }
.nav-opportunities { --nav-color: var(--module-opportunities); }
.nav-resources { --nav-color: var(--module-resources); }
.nav-tracking { --nav-color: var(--module-tracking); }
.nav-activities { --nav-color: var(--module-activities); }
.nav-reports { --nav-color: var(--module-reports); }
/* Module colour is a 6px dot before the label and, on the active item, a 3px underline at the bar's
   bottom edge; never a module-colour fill. The active item also takes the bar's hover tone: on the
   coloured bars (Rainbow, Luna, Vaporwave) every label is near-white and a module hue can match the bar. */
.nav-link {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: var(--topbar-height);
  padding: 0 var(--space-3);
  font: inherit;
  font-size: var(--text-base);
  font-weight: 500;
  line-height: 20px;
  white-space: nowrap;
  color: var(--color-nav-text);
  background: none;
  border: 0;
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.nav-link::before { content: ""; flex: none; width: 6px; height: 6px; background: var(--nav-color, currentColor); border-radius: var(--radius-round); }
a.nav-link:hover, button.nav-link:hover, .nav-item.is-open > .nav-link { color: var(--color-topbar-text); background: var(--color-nav-hover-bg); text-decoration: none; }
.nav-item.is-active > .nav-link { color: var(--color-nav-active-text); font-weight: 600; background: var(--color-nav-active-bg); box-shadow: inset 0 -3px 0 var(--nav-color); }
.nav-item > .dropdown-menu { top: var(--topbar-height); z-index: 2; }

/* ------------------------------------------------------------ user block (right of the bar) */

.user-menu { position: relative; margin-left: auto; display: flex; align-items: stretch; }
.user-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  height: var(--topbar-height);
  padding: 0;
  font: inherit;
  color: var(--color-topbar-muted);
  background: none;
  border: 0;
  cursor: pointer;
}
.user-name {
  align-self: flex-start;
  max-width: 220px;
  margin-top: 9px;
  overflow: hidden;
  font-size: var(--text-base);
  font-weight: 500;
  line-height: 20px;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--color-topbar-text);
}
.avatar {
  display: inline-flex;
  flex: none;
  align-self: center;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  overflow: hidden;
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1;
  color: var(--color-avatar-text);
  background: var(--color-avatar-bg);
  border-radius: var(--radius-round);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-topbar-text) 25%, transparent);
}
.user-store {
  position: absolute;
  top: 30px;
  right: 44px;
  max-width: 220px;
  overflow: hidden;
  font-size: var(--text-xs);
  line-height: 16px;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--color-store-link);
}
span.user-store { color: var(--color-store-link); }
a.user-store:hover { color: var(--color-topbar-text); }
a.user-store:focus-visible { outline-offset: 0; }
.user-store .fa, .user-store .icon { margin-right: var(--space-1); color: var(--color-store-icon); }
.user-store .icon { width: 12px; height: 12px; vertical-align: -1px; }
.user-menu > .dropdown-menu { top: var(--topbar-height); left: auto; right: 0; min-width: 220px; }
/* On a desktop the store line shares the name's grid cell, so a store line longer than the name widens
   the block instead of running under the theme button. */
@media screen and (min-width: 981px) {
  .user-menu { display: grid; }
  /* The toggle spans the cell, so the bar's inset focus ring goes round a store line longer than the
     name; 8px each side, taken back by the margin, keeps the ring off the text and the avatar. */
  .user-menu > .user-toggle { grid-area: 1 / 1; justify-self: stretch; justify-content: flex-end; margin: 0 calc(-1 * var(--space-2)); padding: 0 var(--space-2); }
  .user-menu > .user-store { position: relative; top: auto; right: auto; z-index: 1; grid-area: 1 / 1; justify-self: end; align-self: start; margin: 30px 44px 0 0; }
}
.dropdown-menu > li.user-card > a { padding: var(--space-2) var(--space-3); line-height: 1.35; white-space: normal; }
.user-card strong { display: block; font-size: var(--text-base); font-weight: 600; color: var(--color-text); }
.user-card span { font-size: var(--text-xs); color: var(--color-text-muted); }

/* ------------------------------------------------------------ dropdowns */

.dropdown { position: relative; }
.dropdown-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 150;
  min-width: 180px;
  margin: 0;
  padding: var(--space-1);
  list-style: none;
  text-align: left;
  background: var(--color-menu-bg);
  border: 1px solid var(--color-menu-border);
  border-radius: var(--radius-menu);
  box-shadow: var(--shadow-overlay);
}
.dropdown-menu-right { left: auto; right: 0; }
@keyframes grms-menu-in { from { opacity: 0; transform: translateY(-2px); } }
.dropdown.is-open > .dropdown-menu { display: block; }
.dropdown.is-open > .dropdown-menu:not(.is-sheet) { animation: grms-menu-in var(--dur-1) var(--ease-out); }
.dropdown-menu > li > a,
.dropdown-menu > li > button,
.dropdown-menu > li > .inline-form > button {
  display: block;
  width: 100%;
  min-height: 36px;
  padding: var(--space-2) var(--space-3);
  font: inherit;
  font-size: var(--text-base);
  line-height: 20px;
  text-align: left;
  white-space: nowrap;
  color: var(--color-text);
  background: none;
  border: 0;
  border-radius: var(--radius-control);
  cursor: pointer;
}
.dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus-visible,
.dropdown-menu > li > button:hover, .dropdown-menu > li > button:focus-visible,
.dropdown-menu > li > .inline-form > button:hover,
.dropdown-menu > li.is-active > a {
  color: var(--color-menu-hover-text);
  background: var(--color-menu-hover-bg);
  text-decoration: none;
  outline: none;
}
.dropdown-menu .fa { width: 18px; margin-right: 8px; text-align: center; }
.dropdown-menu .icon { margin-right: var(--space-2); vertical-align: -3px; }
.dropdown-menu > li.divider { height: 1px; margin: var(--space-1) 0; background: var(--color-menu-border); }
/* A double rule: two lines with a gap, for a group that stands further apart (the RFID entries). */
.dropdown-menu > li.divider.is-double { height: 3px; background: none; border-top: 1px solid var(--color-menu-border); border-bottom: 1px solid var(--color-menu-border); }
.dropdown-menu > li.is-disabled > a, .dropdown-menu > li.is-disabled > button { color: var(--color-text-faint); pointer-events: none; }
/* A featured entry (the Job Planner) rests on a soft primary tint in a heavier weight, so it stands
   out of the list without reading as the hovered or active item (no edge bar: Carl, 2026-10-06). */
.dropdown-menu > li.nav-featured > a { font-weight: 600; background: var(--color-nav-featured-bg); }
.dropdown-menu > li.nav-featured > a:hover, .dropdown-menu > li.nav-featured > a:focus-visible { background: var(--color-menu-hover-bg); }

/* ------------------------------------------------------------ flash bars (full width, under the bar) */

.flashes { display: flex; flex-direction: column; }
.flash {
  position: relative;
  min-height: 40px;
  padding: var(--space-2) var(--gutter) var(--space-2) calc(var(--gutter) + 24px);
  font-weight: 500;
  line-height: 24px;
  color: var(--color-info-ink);
  background: var(--color-info-bg);
  border-bottom: 1px solid var(--color-info-border);
}
.flash::before {
  content: "";
  position: absolute;
  left: var(--gutter);
  top: 12px;
  width: 16px;
  height: 16px;
  -webkit-mask-image: url(../icons/info.svg);
  mask-image: url(../icons/info.svg);
}
.flash-success { color: var(--color-success-ink); background: var(--color-success-bg); border-bottom-color: var(--color-success-border); }
.flash-success::before { -webkit-mask-image: url(../icons/circle-check.svg); mask-image: url(../icons/circle-check.svg); }
.flash-error { color: var(--color-error-ink); background: var(--color-error-bg); border-bottom-color: var(--color-error-border); }
.flash-error::before { -webkit-mask-image: url(../icons/shield-alert.svg); mask-image: url(../icons/shield-alert.svg); }

/* ------------------------------------------------------------ banner (System Setup > Appearance) */

.app-banner {
  padding: var(--space-1) var(--gutter);
  font-size: var(--text-sm);
  line-height: 20px;
  color: var(--color-warn-ink);
  background: var(--color-warn-bg);
  border-bottom: 1px solid var(--color-warn-border);
}

/* ------------------------------------------------------------ page frame */

.page { flex: 0 0 auto; width: 100%; padding: 20px var(--gutter) 40px; background: var(--color-surface); }
.site-footer { margin-top: auto; padding: var(--space-2) var(--gutter); font-size: var(--text-xs); line-height: 20px; color: var(--color-footer-text); background: var(--color-page-bg); }
.site-footer .version {
  display: inline-block;
  margin-left: var(--space-1);
  padding: 0 6px;
  line-height: 18px;
  border: 1px solid color-mix(in srgb, currentColor 35%, transparent);
  border-radius: var(--radius-chip);
}
.site-footer a.version { color: inherit; }

.crumbs ol { list-style: none; margin: 0 0 6px; padding: 0; display: flex; flex-wrap: wrap; font-size: var(--text-sm); color: var(--color-text-muted); }
.crumbs a { color: var(--color-text-muted); }
.crumbs a:hover { color: var(--color-link-hover); }
.crumbs li + li::before { content: "/"; margin: 0 6px; color: var(--color-text-faint); }

.page-header { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; margin-bottom: 20px; }
.page-heading { display: flex; flex: 1 1 320px; flex-wrap: wrap; align-items: center; gap: 4px 16px; min-width: 0; }
/* The title's 36px line keeps the classic header height, so nothing under it moves. */
.page-title { font-size: var(--text-2xl); font-weight: 600; line-height: 36px; letter-spacing: var(--tracking-tight); color: var(--color-text); text-shadow: var(--theme-title-glow, none); }
.page-subtitle, .page-heading .page-meta { flex-basis: 100%; }
.page-subtitle { font-size: var(--text-base); color: var(--color-text-muted); }
.page-subtitle .fa, .page-subtitle .icon { margin-right: 6px; }
.page-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.page-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-left: auto; }
/* The 36px icon buttons sit in the classic 44px header row, so the page under them does not move. */
.page-actions:has(> .icon-btn, > .inline-form > .icon-btn) { min-height: 44px; }
.count-pill {
  display: inline-block;
  padding: 2px var(--space-2);
  font-size: var(--text-sm);
  font-weight: 500;
  line-height: 20px;
  vertical-align: middle;
  color: var(--color-text-muted);
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-chip);
}

.page-body { min-width: 0; }
.page-content { min-width: 0; }
.page-content > * + * { margin-top: 20px; }
.section-title, .page-content > h2 { font-size: var(--text-xl); font-weight: 600; letter-spacing: var(--tracking-tight); }

/* Detail pages: 2/3 white main column + full-height 1/3 grey sidebar, flush to the bar and the right edge. */
.page-body.with-sidebar {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  margin: -20px calc(-1 * var(--gutter)) -40px;
}
.page-body.with-sidebar > .page-content { padding: 20px var(--gutter) 40px; }
.page-sidebar { min-width: 0; padding: 20px 30px 40px; background: var(--color-surface-alt); border-left: 1px solid var(--color-border); }
.page:has(> .page-body.with-sidebar),
.page:has(> .page-body > .page-content > .page-body.with-sidebar) { display: flex; flex-direction: column; flex: 1 0 auto; }
.page > .page-body.with-sidebar,
.page > .page-body:has(> .page-content > .page-body.with-sidebar) { flex: 1 0 auto; }
.page > .page-body:has(> .page-content > .page-body.with-sidebar),
.page > .page-body:has(> .page-content > .page-body.with-sidebar) > .page-content { display: flex; flex-direction: column; }
.page > .page-body:has(> .page-content > .page-body.with-sidebar) > .page-content,
.page-content > .page-body.with-sidebar { flex: 1 0 auto; }
.page-content > .page-body.with-sidebar:not(:first-child),
* + .page-body > .page-content > .page-body.with-sidebar:first-child { margin-top: 0; }

/* ------------------------------------------------------------ sections and panels */

.panel { background: var(--color-surface); }
.panel-header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 12px; }
.panel-header h2 { font-size: var(--text-xl); font-weight: 600; letter-spacing: var(--tracking-tight); }
.panel-body { min-width: 0; }
.table-scroll { position: relative; max-width: 100%; overflow-x: auto; }
/* Row menus open outside the scroll box on wide screens, where tables rarely need to scroll. */
@media (min-width: 981px) {
  .table-scroll:has(.dropdown.is-open) { overflow: visible; }
}

.table-footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 4px 16px;
  min-height: 30px;
  padding: 6px var(--space-4);
  font-size: var(--text-sm);
  line-height: 18px;
  background: var(--color-surface-alt);
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
}
.table-footer > :only-child, .table-footer > .is-right { margin-left: auto; }
.table-scroll + .table-footer, .data-table + .table-footer, .items-table + .table-footer { margin-top: 0; }

/* Sidebar sections: small tracked label headings over a hairline; line icons in a 28px indent. */
.sidebar-panel + .sidebar-panel { margin-top: var(--space-4); }
.sidebar-panel > h3 {
  position: relative;
  margin-bottom: var(--space-2);
  padding-right: 24px;
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 32px;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-label);
  border-bottom: 1px solid var(--color-border);
}
.sidebar-panel > h3[role="button"] { cursor: pointer; }
.sidebar-panel > h3[role="button"]::after {
  content: "";
  position: absolute;
  right: 0;
  top: 50%;
  width: 14px;
  height: 14px;
  margin-top: -7px;
  color: var(--color-text-muted);
  -webkit-mask-image: url(../icons/chevron-up.svg);
  mask-image: url(../icons/chevron-up.svg);
}
.sidebar-panel.is-collapsed > h3[role="button"]::after { -webkit-mask-image: url(../icons/chevron-down.svg); mask-image: url(../icons/chevron-down.svg); }
.sidebar-panel.is-collapsed > :not(h3) { display: none; }
.sidebar-panel > :not(h3):not(.action-list):not(.stat-tiles) { padding: var(--space-1) 0 var(--space-1) 28px; }

.action-list { list-style: none; margin: 0; padding: 0; }
.action-list li > a, .action-list li > .inline-form > button, .action-list li > button {
  position: relative;
  display: block;
  width: 100%;
  padding: 6px 0 6px 28px;
  font: inherit;
  font-size: var(--text-base);
  line-height: 20px;
  text-align: left;
  color: var(--color-text);
  background: none;
  border: 0;
  cursor: pointer;
}
.action-list li > a:hover, .action-list li > .inline-form > button:hover { color: var(--color-link); text-decoration: none; }
.action-list .fa, .action-list .icon {
  position: absolute;
  left: 0;
  top: 8px;
  width: 16px;
  height: 16px;
  font-size: 16px;
  line-height: 1;
  text-align: center;
  color: var(--color-text-muted);
}
.action-list li > a:not(:has(> .fa, > .icon))::before, .action-list li > .inline-form > button:not(:has(> .fa, > .icon))::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  width: 16px;
  height: 16px;
  color: var(--color-text-muted);
  -webkit-mask-image: url(../icons/chevron-right.svg);
  mask-image: url(../icons/chevron-right.svg);
}
.action-list .is-danger, .action-list .is-danger .fa, .action-list .is-danger .icon { color: var(--color-danger); }
.action-list li > button:disabled, .action-list li > button:disabled:hover { color: var(--color-text-muted); text-decoration: none; cursor: not-allowed; }
.action-list li > button:disabled .fa, .action-list li > button:disabled .icon { color: var(--color-text-faint); }
.action-list .divider { border-top: 1px solid var(--color-border); margin: 6px 0; }

/* ------------------------------------------------------------ tabs (the function strip: underline tabs) */

.tabs { display: flex; flex-wrap: wrap; gap: 2px; border-bottom: 1px solid var(--color-border); }
.tab { padding: var(--space-2) var(--space-4); font-weight: 500; line-height: 20px; color: var(--color-label); background: transparent; transition: color var(--dur-1) var(--ease-out); }
.tab:hover { color: var(--color-text); text-decoration: none; }
.tab.is-active { color: var(--color-text); font-weight: 600; box-shadow: inset 0 -2px 0 var(--color-primary-strong); }

/* ------------------------------------------------------------ detail pairs */

.detail-grid { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--space-1) var(--space-5); margin: 0; }
.detail-grid dt { font-weight: 500; color: var(--color-label); }
.detail-grid dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
/* In the sidebar the classic shows plain "Label: value" lines. */
.page-sidebar .detail-grid { display: block; font-size: var(--text-base); line-height: 28px; }
.page-sidebar .detail-grid dt { display: inline; font-weight: 500; color: var(--color-label); }
.page-sidebar .detail-grid dt::after { content: ": "; }
.page-sidebar .detail-grid dd { display: inline; }
.page-sidebar .detail-grid dd::after { content: "\A"; white-space: pre; }

/* One line that says what is missing and the one next action, inside the table frame. */
.empty-state { padding: var(--space-5) var(--space-4); text-align: center; color: var(--color-text-muted); border-bottom: 1px solid var(--color-border); }
.empty-state > .icon { display: block; margin: 0 auto var(--space-2); }
.empty-state > .empty-action { margin-top: var(--space-2); }

/* ------------------------------------------------------------ list pages */

.list-toolbar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px 16px; }
.list-toolbar > .toolbar-actions, .list-toolbar > :last-child:not(:first-child):not(.list-search):not(.filter-tabs) { margin-left: auto; }
.toolbar-actions { display: flex; flex-wrap: wrap; gap: 4px; }
.list-search { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 4px 12px; }
.list-search > label { flex-basis: 100%; font-size: var(--text-xs); font-weight: 600; line-height: 16px; color: var(--color-label); }
.list-search input[type="search"], .list-search input[type="text"] { width: 490px; max-width: 100%; height: 36px; }
.list-search select { height: 36px; }
.list-search button, .list-search .btn { min-width: 42px; height: 36px; padding: 7px var(--space-3); line-height: 20px; color: var(--color-on-primary); background: var(--color-primary-strong); border-color: transparent; }
.list-search button:hover, .list-search .btn:hover { color: var(--color-on-primary); background: var(--color-primary-strong-hover); }
.list-search .btn-link, .list-search a.btn-link { min-width: 0; color: var(--color-link); background: none; }

/* A joined segmented group: the active segment is tinted, ink 600 with a primary border. */
.filter-tabs { display: flex; flex-wrap: wrap; }
.filter-tab { padding: 7px var(--space-3); font-weight: 500; line-height: 20px; color: var(--color-label); background: var(--color-surface); border: 1px solid var(--color-input-border); }
.filter-tab:first-child { border-radius: var(--radius-control) 0 0 var(--radius-control); }
.filter-tab:last-child { border-radius: 0 var(--radius-control) var(--radius-control) 0; }
.filter-tab:only-child { border-radius: var(--radius-control); }
.filter-tab + .filter-tab { border-left: 0; }
.filter-tab:hover { color: var(--color-text); background: var(--color-row-hover); text-decoration: none; }
.filter-tab.is-active { position: relative; color: var(--color-text); font-weight: 600; background: var(--color-accent-tint); border-color: var(--color-primary-strong); }
.filter-tab + .filter-tab.is-active { box-shadow: -1px 0 0 var(--color-primary-strong); }

.list-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 24px; font-size: var(--text-base); color: var(--color-text); }
.list-meta > .dropdown { display: inline-block; }
.list-meta [data-dropdown] {
  padding: 0;
  font: inherit;
  color: var(--color-text);
  background: none;
  border: 0;
  cursor: pointer;
}
.list-meta .list-icons { display: flex; gap: 14px; margin-left: auto; font-size: 18px; }
.list-icons a, .list-icons button { color: var(--color-text); background: none; border: 0; padding: 0; cursor: pointer; font: inherit; }
.list-icons a:hover, .list-icons button:hover, .list-icons .is-active { color: var(--color-link); text-decoration: none; }
.list-meta [data-dropdown]:not(:has(.fa, .icon))::after,
.btn[data-dropdown]:not(:has(.fa-caret-down))::after, .btn-link[data-dropdown]:not(:has(.fa, .icon))::after {
  display: inline-block;
  width: 12px;
  height: 12px;
  margin-left: 6px;
  vertical-align: -1px;
  content: "";
  -webkit-mask-image: url(../icons/chevron-down.svg);
  mask-image: url(../icons/chevron-down.svg);
}

/* ------------------------------------------------------------ tables */

.data-table, .items-table { width: 100%; border-collapse: collapse; background: var(--color-surface); font-size: 14px; }
.data-table th, .data-table td, .items-table th, .items-table td { padding: var(--space-2) var(--space-3); text-align: left; vertical-align: middle; border-bottom: 1px solid var(--color-border); }
.data-table thead th, .items-table thead th {
  padding-top: var(--space-2);
  padding-bottom: var(--space-2);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 16px;
  letter-spacing: var(--tracking-th);
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--color-th-text);
  background: var(--color-th-bg);
  border-bottom: 1px solid var(--color-th-border);
}
.data-table th:first-child, .data-table td:first-child, .items-table th:first-child, .items-table td:first-child { padding-left: var(--space-4); }
.data-table tbody th { font-weight: 400; color: var(--color-label); }
@media (hover: hover) {
  .data-table tbody tr:hover > td { background: var(--color-row-hover); }
}
.data-table tr.is-selected > td, .items-table tr.is-selected > td { background: var(--color-row-selected); }
.data-table td.num, .data-table th.num, .items-table td.num, .items-table th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.data-table tr[data-href] { cursor: pointer; }
.data-table tr.is-muted > td, .items-table tr.is-muted > td { color: var(--color-text-muted); }
.data-table td.actions, .items-table td.actions, td.row-menu { width: 1%; text-align: right; white-space: nowrap; }
.data-table tfoot td { background: var(--color-surface-alt); }
.cell-sub { display: block; font-size: var(--text-sm); color: var(--color-text-muted); }
.cell-sub .icon { margin-right: 2px; }
.cell-link { font-size: var(--text-md); font-weight: 600; }
.thumb { display: block; width: 40px; height: 40px; object-fit: contain; }

/* Sort links read in the header colour with a chevron that shows on hover and focus and stays on the
   sorted column. On a desktop a header cell holding only its sort link is the link, edge to edge. */
.sort-link { color: inherit; }
.sort-link:hover { color: var(--color-text); text-decoration: none; }
.sort-link::after { content: ""; display: inline-block; flex: none; width: 12px; height: 12px; margin-left: var(--space-1); vertical-align: -1px; opacity: 0; -webkit-mask-image: url(../icons/chevron-down.svg); mask-image: url(../icons/chevron-down.svg); transition: opacity var(--dur-1) var(--ease-out); }
.sort-link:hover::after, .sort-link:focus-visible::after, .sort-link.sort-asc::after, .sort-link.sort-desc::after { opacity: 1; }
.sort-link.sort-asc::after { transform: rotate(180deg); }
.sort-link.sort-asc, .sort-link.sort-desc { color: var(--color-text); }
th > a.sort-link:only-child { display: flex; align-items: center; gap: var(--space-1); min-height: 32px; margin: -8px -12px; padding: 8px 12px; }
th > a.sort-link:only-child::after { margin-left: 0; }
th:first-child > a.sort-link:only-child { margin-left: -16px; padding-left: 16px; }
th.num > a.sort-link:only-child { justify-content: flex-end; }

/* Opportunity rows: each .state-* sets --row-state; the 3px bar, the four pips and the hover tint read it. */
.data-table tr[class*="state-"] > td:first-child { box-shadow: inset var(--bar-width) 0 0 var(--row-state); }
td.state-cell {
  width: 100px;
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-3);
  font-size: var(--text-xs);
  font-weight: 500;
  line-height: 16px;
  text-align: center;
  color: var(--color-label);
}
/* Four 6px square pips on the one empty element: 1-4 filled in the state colour. */
.state-icon {
  --seg-off: var(--color-state-seg-off);
  display: block;
  width: 30px;
  height: 6px;
  margin: 0;
  background:
    linear-gradient(var(--seg1, var(--seg-off)), var(--seg1, var(--seg-off))) 0 0 / 6px 6px no-repeat,
    linear-gradient(var(--seg2, var(--seg-off)), var(--seg2, var(--seg-off))) 8px 0 / 6px 6px no-repeat,
    linear-gradient(var(--seg3, var(--seg-off)), var(--seg3, var(--seg-off))) 16px 0 / 6px 6px no-repeat,
    linear-gradient(var(--seg4, var(--seg-off)), var(--seg4, var(--seg-off))) 24px 0 / 6px 6px no-repeat;
}
span.state-icon { display: inline-block; vertical-align: middle; }
td.state-cell > .state-icon { display: block; margin: 0 auto 6px; }
.state-enquiry { --row-state: var(--state-enquiry); --seg1: var(--row-state); }
.state-draft { --row-state: var(--state-draft); --seg1: var(--row-state); --seg2: var(--row-state); }
.state-quotation { --row-state: var(--state-quotation); --seg1: var(--row-state); --seg2: var(--row-state); --seg3: var(--row-state); }
.state-order { --row-state: var(--state-order); --seg1: var(--row-state); --seg2: var(--row-state); --seg3: var(--row-state); --seg4: var(--row-state); }
@media (hover: hover) {
  .data-table tr[class*="state-"]:hover > td.state-cell { background: color-mix(in srgb, var(--row-state) 12%, var(--color-surface)); }
}

.data-table tr.date-band > td, .items-table tr.date-band > td {
  padding-top: var(--space-1);
  padding-bottom: var(--space-1);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 22px;
  color: var(--color-label);
  background: var(--color-surface-alt);
}
.data-table tr.date-band:hover > td { background: var(--color-surface-alt); }

/* Shortage: the whole row turns pink and a warning triangle follows the quantity. */
.data-table tr.is-shortage > td, .items-table tr.is-shortage > td,
.data-table tr.is-shortage:hover > td, .items-table tr.is-shortage:hover > td { background: var(--color-shortage-bg); }
.warn-icon { display: inline-block; margin-left: 4px; vertical-align: -2px; color: var(--color-text); }
.warn-icon:empty::before { content: ""; display: block; width: 14px; height: 14px; -webkit-mask-image: url(../icons/triangle-alert.svg); mask-image: url(../icons/triangle-alert.svg); }

/* Row menu: a 32px ghost chevron button, quiet until hover. */
.btn-chevron {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  font: inherit;
  font-size: 16px;
  line-height: 1;
  vertical-align: middle;
  color: var(--color-text-muted);
  background: none;
  border: 0;
  border-radius: var(--radius-control);
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.btn-chevron:hover, .dropdown.is-open > .btn-chevron { color: var(--color-text); background: var(--color-surface-sunken); }
.btn-chevron:empty::before { content: ""; width: 16px; height: 16px; -webkit-mask-image: url(../icons/chevron-down.svg); mask-image: url(../icons/chevron-down.svg); }

/* ------------------------------------------------------------ items tree */

.items-table td { padding-top: 8px; padding-bottom: 8px; }
/* The items tree is the densest table: its cells keep the classic 10px sides and its headers no
   tracking, so the name column keeps the width it had and names stay on one line. */
.items-table th, .items-table td { padding-right: 10px; padding-left: 10px; }
.items-table thead th { letter-spacing: 0; }
.items-table tr.item-group > td { padding-top: 7px; padding-bottom: 7px; font-size: var(--text-md); font-weight: 600; line-height: 22px; }
.items-table tr.item-group > td.num, .items-table tr.item-group > td .badge { font-size: 14px; font-weight: 400; }
.items-table tr.item-group > td .badge { font-size: 12px; }
.items-table td.item-gutter { width: 50px; }
.items-table td.item-name { width: 40%; }
.items-table tr.is-shortage > td.item-gutter { background: none; }
.items-table tr:not(.item-group) > td.item-gutter { border-bottom-color: transparent; }
.items-table .depth-0 { --item-indent: 10px; }
.items-table .depth-1 { --item-indent: 40px; }
.items-table .depth-2 { --item-indent: 70px; }
.items-table .depth-3 { --item-indent: 100px; }
.items-table .depth-4 { --item-indent: 130px; }
.items-table td[class*="depth-"], .items-table tr[class*="depth-"] > td.item-name { padding-left: var(--item-indent); }
/* A leading drag handle hangs in the indent so wrapped names line up under the first line. */
.items-table td.item-name:has(> .drag-handle:first-child) { padding-left: calc(var(--item-indent, 10px) + 30px); }
.items-table td.item-name > .drag-handle:first-child { margin-left: -30px; }
.item-name .text-marker { float: right; margin-left: 8px; }
.item-desc { display: block; font-style: italic; color: var(--color-text); }
.drag-handle { display: inline-block; width: 18px; margin-right: 12px; font-size: 16px; color: var(--color-text-muted); }
/* The handle's glyph is a grip line icon, whichever markup draws it. */
.drag-handle.fa::before, .drag-handle > .fa::before { content: ""; display: inline-block; width: 16px; height: 16px; vertical-align: -3px; -webkit-mask-image: url(../icons/grip-vertical.svg); mask-image: url(../icons/grip-vertical.svg); }
.item-toggle { display: inline-block; width: 12px; margin-right: 12px; padding: 0; font: inherit; font-weight: 400; color: var(--color-text); background: none; border: 0; cursor: pointer; }
.items-table tfoot.totals td { font-size: var(--text-base); background: none; border-bottom: 0; }
.items-table tfoot.totals td.num { font-weight: 700; box-shadow: inset 0 1px 0 var(--color-text); }
.text-marker {
  display: inline-block;
  width: 18px;
  height: 18px;
  font-size: var(--text-xs);
  line-height: 16px;
  text-align: center;
  vertical-align: middle;
  color: var(--color-label);
  border: 1px solid var(--color-text-muted);
}

/* ------------------------------------------------------------ summary tiles and sidebar stats */

/* Tiles share a row equally but never get narrower than their text; a row that cannot hold them wraps. */
.summary-tiles { display: flex; flex-wrap: wrap; gap: 4px; }
.summary-tile {
  display: flex;
  flex: 1 1 0;
  flex-direction: column;
  justify-content: center;
  min-width: max-content;
  min-height: 50px;
  padding: 2px var(--space-3);
  color: var(--color-text);
  background: color-mix(in srgb, var(--color-tile) 8%, var(--color-surface));
  border: 1px solid color-mix(in srgb, var(--color-tile) 35%, var(--color-surface));
  border-radius: var(--radius-panel);
  transition: background-color var(--dur-1) var(--ease-out);
}
.summary-tile:hover { color: var(--color-text); background: color-mix(in srgb, var(--color-tile) 14%, var(--color-surface)); text-decoration: none; }
.summary-tile strong { font-size: var(--text-lg); font-weight: 600; line-height: 24px; }
.summary-tile span { font-size: var(--text-sm); line-height: 20px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--color-label); }
.summary-tile span .fa, .summary-tile span .icon { margin-right: 6px; color: var(--color-tile); }

.stat-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin: 4px 0 6px; }
.stat-tiles.cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.stat-tile { min-width: 0; padding: 8px 12px; border-left: 1px solid var(--color-border); }
.stat-tiles > .stat-tile:nth-child(n+4) { border-top: 1px solid var(--color-border); }
.stat-tiles.cols-4 > .stat-tile:nth-child(n+5) { border-top: 1px solid var(--color-border); }
.stat-tiles.cols-4 > .stat-tile:nth-child(4) { border-top: 0; }
.stat-tile strong { display: block; overflow: hidden; font-size: var(--text-md); font-weight: 600; line-height: 26px; white-space: nowrap; text-overflow: ellipsis; color: var(--color-text); }
.stat-tile span { display: block; font-size: var(--text-xs); line-height: 16px; overflow-wrap: break-word; color: var(--color-text-muted); }
/* Sidebar money tiles: the figure scales with its tile, so a seven-figure sum shows whole, never cut off. */
.page-sidebar .stat-tiles:not(.cols-4) > .stat-tile { container-type: inline-size; }
.page-sidebar .stat-tiles:not(.cols-4) > .stat-tile strong { font-size: clamp(12px, 14cqi, 16px); }
@media (min-width: 981px) and (max-width: 1279px) {
  .page-sidebar .stat-tiles:not(.cols-4) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .page-sidebar .stat-tiles:not(.cols-4) > .stat-tile:nth-child(n+3) { border-top: 1px solid var(--color-border); }
}
.stat-tile.is-warn { background: color-mix(in srgb, var(--avail-warn) 14%, var(--color-surface)); border-left-color: var(--avail-warn); }
.stat-tile.is-short { background: color-mix(in srgb, var(--avail-short) 14%, var(--color-surface)); border-left-color: var(--avail-short); }
.stat-tile.is-warn strong, .stat-tile.is-warn span, .stat-tile.is-short strong, .stat-tile.is-short span { color: var(--color-text); }

/* ------------------------------------------------------------ header icon buttons */

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  font: inherit;
  font-size: 18px;
  color: var(--color-icon-btn);
  background: var(--color-surface);
  border: 1px solid var(--color-icon-btn-ring);
  border-radius: var(--radius-control);
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.icon-btn .icon { width: 18px; height: 18px; }
.icon-btn:hover { color: var(--color-text); background: var(--color-row-hover); border-color: var(--color-text-muted); text-decoration: none; }
.icon-btn.is-danger:hover, .icon-btn.btn-danger:hover { color: var(--color-danger); border-color: var(--color-danger); }
.page-actions .icon-btn + .icon-btn, .page-actions .inline-form + .icon-btn, .page-actions .icon-btn + .inline-form { margin-left: 0; }

/* ------------------------------------------------------------ forms */

.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 30px; }
.form-grid.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.form-grid.cols-1 { grid-template-columns: minmax(0, 1fr); }
.form-grid > .span-all { grid-column: 1 / -1; }
.form-row { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; min-width: 0; }
.form-grid .form-row { margin-bottom: 0; }
.form-row > label, .form-label { display: flex; align-items: center; gap: 4px; font-size: var(--text-sm); font-weight: 600; line-height: 18px; color: var(--color-label); }
.required { order: -1; color: inherit; }
.form-row > label > input[type="checkbox"], .form-row > label > input[type="radio"] { margin: 0 4px 0 0; }
.field-hint { margin-top: 2px; font-size: var(--text-sm); color: var(--color-text-muted); }
.field-error { font-size: var(--text-sm); color: var(--color-error-ink); }
.form-row.has-error input, .form-row.has-error select, .form-row.has-error textarea { border-color: var(--color-danger); }
.form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 20px; }
.form-row > .toggle-yesno, .form-row > .btn, .form-row > .filter-tabs { align-self: flex-start; }

input[type="text"], input[type="email"], input[type="password"], input[type="search"], input[type="number"],
input[type="date"], input[type="datetime-local"], input[type="time"], input[type="tel"], input[type="url"], select, textarea {
  max-width: 100%;
  height: var(--control-height);
  padding: 0 var(--space-3);
  font: inherit;
  font-size: var(--text-base);
  line-height: 20px;
  color: var(--color-text-input);
  background: var(--color-input-bg);
  border: 1px solid var(--color-input-border);
  border-radius: var(--radius-control);
  box-shadow: none;
  transition: border-color var(--dur-1) var(--ease-out);
}
select { padding: 0 var(--space-2); }
textarea { height: auto; min-height: 100px; padding: var(--space-2) var(--space-3); resize: vertical; }
/* Masked fields (app.js wraps every password input): the eye at the right edge shows or hides what is typed. */
.pw-field { position: relative; display: block; }
.pw-field > input { width: 100%; padding-right: 44px; }
.input-group > .pw-field { flex: 1 1 auto; min-width: 0; width: 1%; }
.pw-toggle {
  position: absolute;
  top: 0;
  right: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 100%;
  padding: 0;
  color: var(--color-text-muted);
  background: none;
  border: 0;
  border-radius: var(--radius-control);
  cursor: pointer;
}
.pw-toggle:hover { color: var(--color-text); }
.pw-toggle:focus-visible { outline: var(--focus-width) solid var(--color-focus); outline-offset: -3px; }
.pw-toggle .pw-eye-off, .pw-toggle[aria-pressed="true"] .pw-eye { display: none; }
.pw-toggle[aria-pressed="true"] .pw-eye-off { display: block; }
:is(input[type="text"], input[type="email"], input[type="password"], input[type="search"], input[type="number"],
input[type="date"], input[type="datetime-local"], input[type="time"], input[type="tel"], input[type="url"], select, textarea):hover:not(:disabled) { border-color: var(--color-text-muted); }
input:focus, select:focus, textarea:focus { border-color: var(--color-focus); outline: var(--focus-width) solid var(--color-focus); outline-offset: 1px; box-shadow: none; }
input[type="checkbox"], input[type="radio"] { width: 16px; height: 16px; accent-color: var(--color-primary-strong); }
input[type="checkbox"]:focus, input[type="radio"]:focus { outline: 0; }
input[type="checkbox"]:focus-visible, input[type="radio"]:focus-visible { outline: var(--focus-width) solid var(--color-focus); outline-offset: var(--focus-offset); }
/* A search field's clear control: the line x in the field's own text colour, not the engine's blue cross. */
input[type="search"]::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
  width: 16px;
  height: 16px;
  margin: 0 0 0 var(--space-1);
  background-color: currentColor;
  -webkit-mask: url(../icons/x.svg) center / contain no-repeat;
  mask: url(../icons/x.svg) center / contain no-repeat;
  cursor: pointer;
}
input[type="search"]:placeholder-shown::-webkit-search-cancel-button { display: none; }
input[type="file"] { max-width: 100%; font: inherit; font-size: var(--text-sm); }
input[type="file"]::file-selector-button {
  height: var(--control-height-sm);
  margin-right: var(--space-2);
  padding: 0 var(--space-3);
  font: inherit;
  font-weight: 600;
  color: var(--color-btn-text);
  background: var(--color-btn-bg);
  border: 1px solid var(--color-btn-border);
  border-radius: var(--radius-control);
  cursor: pointer;
}
input[type="file"]::file-selector-button:hover { background: var(--color-row-hover); }
input[type="color"] { height: var(--control-height); padding: 2px; background: var(--color-input-bg); border: 1px solid var(--color-input-border); border-radius: var(--radius-control); cursor: pointer; }
input[disabled], select[disabled], textarea[disabled], input[readonly] { background: var(--color-addon-bg); }
::placeholder { color: var(--color-text-muted); opacity: 1; }

.input-group { display: flex; align-items: stretch; min-width: 0; }
.input-group > input, .input-group > select { flex: 1 1 auto; min-width: 0; width: 1%; }
.input-addon {
  display: flex;
  flex: none;
  align-items: center;
  padding: 0 var(--space-3);
  font-size: var(--text-base);
  white-space: nowrap;
  color: var(--color-text-input);
  background: var(--color-addon-bg);
  border: 1px solid var(--color-input-border);
}
.input-group > .input-addon:first-child { border-right: 0; border-radius: var(--radius-control) 0 0 var(--radius-control); }
.input-group > .input-addon:last-child { border-left: 0; border-radius: 0 var(--radius-control) var(--radius-control) 0; }
.input-group > :not(:first-child), .input-group > .autocomplete:not(:first-child) > input { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.input-group > :not(:last-child), .input-group > .autocomplete:not(:last-child) > input { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.input-group > .btn { flex: none; height: var(--control-height); }
.input-group > .autocomplete { flex: 1 1 auto; min-width: 0; }

/* The classic centred form panel with line icons in a left gutter and hairline section rules. */
.form-panel { max-width: var(--form-panel-width); margin: 0 auto; padding: 20px 30px 30px; background: var(--color-surface-alt); border: 1px solid var(--color-border); border-radius: var(--radius-panel); }
.form-panel .page-title, .form-title { font-size: var(--text-2xl); font-weight: 600; line-height: 36px; letter-spacing: var(--tracking-tight); color: var(--color-label); }
.form-subtitle { margin-top: 6px; font-size: var(--text-xl); font-weight: 600; color: var(--color-label); }
.form-panel .form-actions { justify-content: flex-end; padding-top: 20px; border-top: 1px solid var(--color-border); }
.form-section { display: grid; grid-template-columns: 130px minmax(0, 1fr); margin: 0; padding: 20px 0; border: 0; border-top: 1px solid var(--color-border); }
.form-section:first-of-type { border-top: 0; padding-top: 10px; }
.form-section > .form-section-icon { grid-column: 1; align-self: start; justify-self: center; margin-top: var(--space-5); font-size: 24px; line-height: 1; text-align: center; color: var(--color-text-muted); }
svg.form-section-icon { width: 24px; height: 24px; }
.form-section > :not(.form-section-icon) { grid-column: 2; }
.form-section > legend { float: left; padding: 0; margin-bottom: 8px; font-size: var(--text-md); font-weight: 600; color: var(--color-label); }
.page:has(> .page-body > .page-content > .form-panel:first-child) { padding-top: 0; }
.page:has(> .page-body > .page-content > .form-panel:first-child) > .page-header {
  max-width: var(--form-panel-width);
  margin: 0 auto;
  padding: 20px 30px 0;
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border);
  border-top: 0;
  border-bottom: 0;
}
.page:has(> .page-body > .page-content > .form-panel:first-child) > .page-header .page-title { color: var(--color-label); }
.page > .page-header + .page-body > .page-content > .form-panel:first-child { border-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; }
/* Breadcrumbs above a joined form panel line up with the panel (the page's top padding is dropped there). */
.page:has(> .page-body > .page-content > .form-panel:first-child) > .crumbs { max-width: var(--form-panel-width); margin: 0 auto; padding: 14px 0 6px; }

/* Yes/No segmented toggle (never a switch): paper halves in a frame, Yes chosen in create green, No in red. */
.toggle-yesno { position: relative; display: inline-flex; }
.toggle-yesno > input { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; pointer-events: none; }
.toggle-yesno > label {
  min-width: 52px;
  height: var(--control-height);
  padding: 0 var(--space-3);
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: calc(var(--control-height) - 2px);
  text-align: center;
  color: var(--color-label);
  background: var(--color-btn-bg);
  border: 1px solid var(--color-border-strong);
  cursor: pointer;
  user-select: none;
  transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.toggle-yesno > label:first-of-type { border-radius: var(--radius-control) 0 0 var(--radius-control); }
.toggle-yesno > label:last-of-type { border-left: 0; border-radius: 0 var(--radius-control) var(--radius-control) 0; }
.toggle-yesno > label:hover { color: var(--color-text); background: var(--color-row-hover); }
.toggle-yesno > input:checked + label { color: var(--color-on-button); background: var(--color-create-strong); border-color: var(--color-create-strong); }
.toggle-yesno > input:checked + label:last-of-type { color: var(--color-on-danger); background: var(--color-danger); border-color: var(--color-danger); }
.toggle-yesno > input:focus-visible + label { position: relative; z-index: 1; outline: 2px solid var(--color-focus); outline-offset: 1px; }
.toggle-yesno > input:disabled + label { opacity: .65; cursor: not-allowed; }

/* ------------------------------------------------------------ buttons */

/* The default .btn is the secondary face (paper, a rule, ink text); filled variants use the deep
   fills with their pair text tokens. */
.btn {
  display: inline-block;
  height: var(--control-height);
  padding: calc((var(--control-height) - 22px) / 2) var(--space-4);
  font: inherit;
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 20px;
  text-align: center;
  white-space: nowrap;
  vertical-align: middle;
  color: var(--color-btn-text);
  background: var(--color-btn-bg);
  border: 1px solid var(--color-btn-border);
  border-radius: var(--radius-control);
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.btn:hover { color: var(--color-btn-text); background: var(--color-row-hover); text-decoration: none; }
.btn .fa, .btn .icon { margin-right: var(--space-2); }
.btn .icon { vertical-align: -3px; }
.btn-icon .fa, .btn-icon .icon { margin-right: 0; }
.btn-primary { color: var(--color-on-primary); background: var(--color-primary-strong); border-color: transparent; }
.btn-primary:hover { color: var(--color-on-primary); background: var(--color-primary-strong-hover); }
.btn-create { color: var(--color-on-button); background: var(--color-create-strong); border-color: transparent; }
.btn-create:hover { color: var(--color-on-button); background: var(--color-create-strong-hover); }
.btn-danger, .btn.is-danger { color: var(--color-on-danger); background: var(--color-danger); border-color: transparent; }
.btn-danger:hover, .btn.is-danger:hover { color: var(--color-on-danger); background: var(--color-danger-hover); }
.btn-warning { color: var(--color-on-button); background: var(--color-warning-strong); border-color: transparent; }
.btn-warning:hover { color: var(--color-on-button); background: var(--color-warning-strong-hover); }
.btn-small { height: var(--control-height-sm); padding: calc((var(--control-height-sm) - 20px) / 2) var(--space-3); font-size: var(--text-sm); line-height: 18px; }
.btn-icon { min-width: 42px; padding-left: 10px; padding-right: 10px; }
.btn-link { height: auto; padding: 0; font: inherit; color: var(--color-link); background: none; border: 0; border-radius: 0; cursor: pointer; }
.btn-link:hover { color: var(--color-link-hover); text-decoration: underline; background: none; }
.btn[disabled], .btn.is-disabled, .btn:disabled { opacity: .65; cursor: not-allowed; pointer-events: none; }
.btn-group { display: inline-flex; flex-wrap: wrap; gap: var(--space-1); }
.btn .count-bubble {
  display: inline-block;
  min-width: 18px;
  height: 18px;
  margin-left: 6px;
  padding: 0 5px;
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 18px;
  text-align: center;
  vertical-align: 1px;
  color: inherit;
  background: var(--color-count-bubble-bg);
  border-radius: var(--radius-chip);
}

/* ------------------------------------------------------------ badges, chips, availability */

/* A status is a dot plus a word: an 8px dot in --badge with a darker inner ring, then the word in ink.
   Each .badge-* class only sets --badge; the category group below draws tinted tags instead. */
.badge {
  --badge: var(--status-inactive);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 20px;
  padding: 0;
  font-size: var(--text-sm);
  font-weight: 500;
  line-height: 20px;
  white-space: nowrap;
  vertical-align: middle;
  color: var(--color-text);
  background: none;
}
.badge::before {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  background: var(--badge);
  border-radius: var(--radius-round);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--badge) 70%, var(--color-text));
}
/* The status word carries the meaning; an older glyph inside a status badge is not drawn. */
.badge[class*="badge-status-"] > :is(.fa, .icon) { display: none; }
/* Fixed keys: purchase-order draft and order, invoice statuses, open and closed discussions;
   active only for the style guide's detail demo (styleguide/pages/index.php), until it uses badge_code(). */
.badge-draft { --badge: var(--state-draft); }
.badge-order { --badge: var(--state-order); }
.badge-open { --badge: var(--status-open); }
.badge-active { --badge: var(--status-active); }
.badge-paid { --badge: var(--status-invoiced); }
.badge-issued { --badge: var(--status-provisional); }
.badge-partially-paid { --badge: var(--status-open); }
.badge-overdue { --badge: var(--color-danger); }
.badge-completed, .badge-voided, .badge-inactive { --badge: var(--status-inactive); }
.badge-deal-price { --badge: var(--item-deal-price); }
.badge-rental { --badge: var(--type-rental); }
.badge-sale { --badge: var(--type-sale); }
.badge-service { --badge: var(--type-service); }
.badge-optional { --badge: var(--incl-optional); }
.badge-default { --badge: var(--incl-default); }
.badge-mandatory { --badge: var(--incl-mandatory); }
.badge-active-record, .badge-signed-in { --badge: var(--color-create); }
.badge-locked, .badge-failed { --badge: var(--color-danger); }
.badge-role { --badge: var(--status-inactive); }
.badge-role-admin { --badge: var(--module-admin); }
.badge-role-staff { --badge: var(--color-primary); }
.badge-role-warehouse { --badge: var(--module-rfid); }
.badge-role-office { --badge: var(--module-opportunities); }
.badge-manual { --badge: var(--color-primary); }
.badge-inferred { --badge: var(--color-warning); }
/* badge_code(): opportunity states and statuses and item statuses, keyed by code, so a renamed
   word keeps its colour. Never derive a badge class from a display name. */
.badge-state-0 { --badge: var(--state-enquiry); }
.badge-state-1 { --badge: var(--state-draft); }
.badge-state-2 { --badge: var(--state-quotation); }
.badge-state-3 { --badge: var(--state-order); }
.badge-status-0 { --badge: var(--status-open); }
.badge-status-1 { --badge: var(--status-provisional); }
.badge-status-5 { --badge: var(--status-reserved); }
.badge-status-20 { --badge: var(--status-active); }
.badge-status-40, .badge-status-50, .badge-status-60, .badge-status-70, .badge-status-80 { --badge: var(--status-inactive); }
.badge-item-status-0, .badge-item-status-1 { --badge: var(--item-open); }
.badge-item-status-5 { --badge: var(--item-reserved); }
.badge-item-status-10 { --badge: var(--item-allocated); }
.badge-item-status-15 { --badge: var(--item-prepared); }
.badge-item-status-20 { --badge: var(--item-booked-out); }
.badge-item-status-25 { --badge: var(--item-part-checked-in); }
.badge-item-status-30 { --badge: var(--item-checked-in); }
.badge-item-status-40 { --badge: var(--item-completed); }
.badge-item-status-50, .badge-item-status-60, .badge-item-status-70, .badge-item-status-80 { --badge: var(--status-inactive); }

/* Categories are tinted tags: ink on a 14% tint of the hue with a 50% rule. */
.badge-rental, .badge-sale, .badge-service, .badge-optional, .badge-default, .badge-mandatory,
.badge-role, .badge-manual, .badge-inferred,
.badge-deal-price, .badge-active-record, .badge-signed-in, .badge-locked, .badge-failed {
  padding: 0 6px;
  font-size: var(--text-xs);
  font-weight: 600;
  background: color-mix(in srgb, var(--badge) 14%, var(--color-surface));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--badge) 50%, var(--color-surface));
  border-radius: var(--radius-badge);
}
:is(.badge-rental, .badge-sale, .badge-service, .badge-optional, .badge-default, .badge-mandatory,
.badge-role, .badge-manual, .badge-inferred,
.badge-deal-price, .badge-active-record, .badge-signed-in, .badge-locked, .badge-failed)::before { content: none; }

.tag-chip {
  display: inline-block;
  padding: 1px 6px;
  font-size: var(--text-xs);
  font-weight: 500;
  line-height: 16px;
  color: var(--color-label);
  background: var(--color-surface-alt);
  border: 1px solid var(--color-tag-border);
  border-radius: var(--radius-chip);
}
.section-count {
  --badge: var(--color-section-count);
  display: inline-block;
  height: 20px;
  padding: 0 6px;
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 20px;
  vertical-align: middle;
  color: var(--color-text);
  background: color-mix(in srgb, var(--badge) 14%, var(--color-surface));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--badge) 50%, var(--color-surface));
  border-radius: var(--radius-badge);
}

/* Availability keeps its solid data fills (the number carries the meaning); the text on each is
   the chip ink or inverse text, whichever passes on that hue. */
.avail {
  display: inline-block;
  min-width: 28px;
  padding: 2px 6px;
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 16px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  color: var(--color-chip-ink);
  background: var(--avail-ok);
  border-radius: var(--radius-chip);
}
.avail-ok { color: var(--color-chip-ink); background: var(--avail-ok); }
.avail-warn { color: var(--color-text-inverse); background: var(--avail-warn-strong); }
.avail-short { color: var(--color-text-inverse); background: var(--avail-short); }

/* ------------------------------------------------------------ pager (small and flat) */

.pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; font-size: 14px; }
.pager-count { color: var(--color-text-muted); }
.pager-pages { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 2px; }
.pager-pages a, .pager-pages span { display: inline-block; min-width: 32px; padding: 6px var(--space-2); line-height: 20px; text-align: center; border-radius: var(--radius-control); }
.pager-pages a:hover { color: var(--color-text); background: var(--color-row-hover); text-decoration: none; }
.pager-pages .is-current { color: var(--color-on-primary); font-weight: 600; background: var(--color-primary-strong); }
.pager-pages .is-disabled { color: var(--color-text-muted); cursor: default; }
.pager-pages .gap { color: var(--color-text-muted); }

/* ------------------------------------------------------------ modals (dialog.modal) */

dialog.modal {
  width: 600px;
  max-width: calc(100vw - 32px);
  max-height: calc(100vh - 32px);
  padding: 0;
  color: var(--color-text);
  background: var(--color-surface);
  border: 0;
  border-radius: var(--radius-menu);
  box-shadow: var(--shadow-overlay);
}
dialog.modal::backdrop { background: var(--color-backdrop); }
.modal-header { display: flex; align-items: center; gap: 10px; min-height: 52px; padding: 8px 12px 8px 20px; color: var(--color-text); background: var(--color-surface); border-bottom: 1px solid var(--color-border); }
.modal-header h2 { flex: 1; font-size: var(--text-lg); font-weight: 600; }
.modal-close {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  font-size: 22px;
  line-height: 1;
  color: var(--color-text-muted);
  background: none;
  border: 0;
  border-radius: var(--radius-control);
  cursor: pointer;
}
.modal-close:hover { color: var(--color-text); background: var(--color-row-hover); }
.modal-body { padding: 20px 30px; }
.modal-footer { display: flex; justify-content: flex-end; gap: 12px; padding: 16px 30px; border-top: 1px solid var(--color-border); }

/* ------------------------------------------------------------ inline notice (tinted box) */

.notice { padding: 10px var(--space-4); color: var(--color-error-ink); background: var(--color-error-bg); border: 1px solid var(--color-error-border); border-radius: var(--radius-control); }
.notice-info { color: var(--color-info-ink); background: var(--color-info-bg); border-color: var(--color-info-border); }
.notice-warn { color: var(--color-warn-ink); background: var(--color-warn-bg); border-color: var(--color-warn-border); }

/* Error summary: the error box at the top of a form panel after a failed save, one link per field
   error (the field itself carries .has-error and a .field-error line). */
.error-summary { position: relative; margin: 0 0 16px; padding: 8px var(--space-4) 10px 40px; color: var(--color-error-ink); background: var(--color-error-bg); border: 1px solid var(--color-error-border); border-radius: var(--radius-control); }
.error-summary::before { content: ""; position: absolute; left: var(--space-4); top: 10px; width: 16px; height: 16px; -webkit-mask-image: url(../icons/shield-alert.svg); mask-image: url(../icons/shield-alert.svg); }
.error-summary h2 { margin: 0 0 2px; font-size: var(--text-base); font-weight: 600; line-height: 20px; color: inherit; }
.error-summary ul { margin: 0; padding-left: 18px; }
.error-summary li { line-height: 20px; }
.error-summary a, .error-summary a:hover { color: inherit; text-decoration: underline; }
.error-summary:focus, .error-summary:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.form-panel > .error-summary:first-child, .form-panel > form > .error-summary:first-of-type { margin-top: 4px; }

/* ------------------------------------------------------------ dashboard */

/* The page's h1 is visually hidden above the panel, so the panel takes no sibling gap. */
.dash-panel { margin: 0; padding: 16px 30px 26px; color: var(--color-dash-text); background: var(--color-dash-panel); background-image: var(--theme-dash-image, none); border: 1px solid var(--color-border); border-radius: var(--radius-panel); }
.dash-panel h2 { margin-bottom: 24px; font-size: var(--text-xl); font-weight: 600; letter-spacing: var(--tracking-tight); }
.dash-counters { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)) minmax(0, 2fr); gap: 20px 40px; }
.dash-counter { display: flex; flex-direction: column; min-width: 0; }
.dash-counter a, .dash-counter a:hover { color: inherit; text-decoration: none; }
.dash-counter > a:first-child { display: flex; flex: 1 0 auto; flex-direction: column; }
.dash-counter a:hover span, .dash-counter a:hover small { text-decoration: underline; }
.dash-counter strong { display: block; font-size: var(--text-display-2); font-weight: 600; line-height: 1.2; letter-spacing: var(--tracking-display); overflow-wrap: anywhere; }
.dash-counter span { display: block; margin-top: auto; font-size: var(--text-xs); font-weight: 600; letter-spacing: var(--tracking-label); text-transform: uppercase; }
.dash-counter small { display: block; margin-top: 4px; font-size: var(--text-xs); font-weight: 500; letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-dash-muted); }
.dash-counter.is-value { grid-column: 5; }
.dash-bar { height: 6px; margin-top: 8px; overflow: hidden; background: var(--color-dash-track); border-radius: var(--radius-chip); }
.dash-bar > i { display: block; height: 100%; background: var(--color-dash-fill); }
.dash-bar.is-enquiry > i { background: var(--state-enquiry); }
.dash-bar.is-quotation > i { background: var(--state-quotation); }
.dash-bar.is-order > i { background: var(--state-order); }
/* Tiles are tinted surfaces of their colour; text on a tint is ink or label colour only. */
.dash-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px; }
.dash-tile {
  display: flex;
  flex-direction: column;
  min-height: 190px;
  padding: 14px var(--space-4);
  text-align: left;
  color: var(--color-text);
  background: color-mix(in srgb, var(--tile-bg, var(--tile-blue)) 10%, var(--color-surface));
  border: 1px solid color-mix(in srgb, var(--tile-bg, var(--tile-blue)) 35%, var(--color-surface));
  border-radius: var(--radius-panel);
  transition: background-color var(--dur-1) var(--ease-out);
}
a.dash-tile:hover { color: var(--color-text); text-decoration: none; background: color-mix(in srgb, var(--tile-bg, var(--tile-blue)) 14%, var(--color-surface)); }
.dash-tiles > .dash-tile :is(h2, h3) { margin: 0; font-size: var(--text-xs); font-weight: 600; line-height: 16px; letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-label); }
.dash-tile strong { margin: auto 0; font-size: var(--text-display-3); font-weight: 600; line-height: 1; letter-spacing: var(--tracking-display); color: var(--color-text); }
.dash-tile small { font-size: var(--text-sm); color: var(--color-label); }
.tile-green { --tile-bg: var(--tile-green); }
.tile-orange { --tile-bg: var(--tile-orange); }
.tile-blue { --tile-bg: var(--tile-blue); }
.tile-red { --tile-bg: var(--tile-red); }
.tile-purple { --tile-bg: var(--module-dashboard); }

/* ------------------------------------------------------------ autocomplete */

.autocomplete { position: relative; }
.form-row .autocomplete > input, .input-group .autocomplete > input { width: 100%; }
.autocomplete-list {
  position: absolute;
  z-index: 160;
  left: 0;
  right: 0;
  top: 100%;
  max-height: 300px;
  overflow-y: auto;
  margin: 0;
  padding: var(--space-1);
  list-style: none;
  background: var(--color-menu-bg);
  border: 1px solid var(--color-menu-border);
  border-radius: var(--radius-menu);
  box-shadow: var(--shadow-overlay);
}
.autocomplete-list li { min-height: 36px; padding: var(--space-2) var(--space-3); border-radius: var(--radius-control); cursor: pointer; }
.autocomplete-list li.is-active, .autocomplete-list li:hover { color: var(--color-text); background: var(--color-accent-tint); }
/* The keyboard row also has a rule, so it shows where the tint cannot be drawn. */
.autocomplete-list li.is-active { outline: 1px solid var(--color-primary-strong); outline-offset: -1px; }
.autocomplete-list .sub { display: block; font-size: var(--text-xs); color: var(--color-text-muted); }
.autocomplete-list li.is-active .sub, .autocomplete-list li:hover .sub { color: var(--color-label); }

/* ------------------------------------------------------------ scan field (barcodes, QR codes, tag EPCs)

   div.scan-field > svg.icon (scan-line) + input + p.scan-status[aria-live=polite]. .is-ok and .is-fail
   tint the field and put a word and an icon in the status line (never colour alone); .is-flash holds
   the tint for --dur-flash (grmsUi.scanStatus sets both); .is-busy says it is looking. */
.scan-field { position: relative; display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.scan-field > .icon { position: absolute; top: 14px; left: var(--space-3); width: 20px; height: 20px; stroke-width: 1.75; color: var(--color-text-muted); pointer-events: none; }
div.scan-field > input {
  width: 100%;
  height: 48px;
  padding-left: 44px;
  font-family: var(--font-mono);
  font-size: var(--text-md);
  font-weight: 500;
  letter-spacing: 0.02em;
  transition: background-color var(--dur-flash) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.scan-status { display: flex; align-items: center; gap: 6px; min-height: 20px; margin: 0; font-size: var(--text-sm); line-height: 20px; color: var(--color-text-muted); }
.scan-field.is-busy .scan-status { color: var(--color-label); }
.scan-field.is-ok > input { border-color: var(--color-scan-ok); }
.scan-field.is-fail > input { border-color: var(--color-scan-fail); }
.scan-field.is-ok.is-flash > input { background: var(--color-scan-ok-bg); transition-duration: 0ms; }
.scan-field.is-fail.is-flash > input { background: var(--color-scan-fail-bg); transition-duration: 0ms; }
.scan-field.is-ok .scan-status, .scan-field.is-fail .scan-status { color: var(--color-text); font-weight: 500; }
.scan-field.is-ok .scan-status::before, .scan-field.is-fail .scan-status::before { content: ""; flex: none; width: 16px; height: 16px; }
.scan-field.is-ok .scan-status::before { -webkit-mask-image: url(../icons/check.svg); mask-image: url(../icons/check.svg); }
.scan-field.is-fail .scan-status::before { -webkit-mask-image: url(../icons/triangle-alert.svg); mask-image: url(../icons/triangle-alert.svg); }

/* ------------------------------------------------------------ login and errors */

.is-bare .page { background: transparent; }
.login-box { max-width: 400px; margin: 40px auto 0; padding: 24px 30px 30px; background: var(--color-surface-alt); border: 1px solid var(--color-border); border-radius: var(--radius-panel); }
.login-box .panel-header { margin-bottom: 16px; }
.login-box .panel-header h2 { font-size: var(--text-xl); color: var(--color-label); }
.login-form input[type="email"], .login-form input[type="password"] { width: 100%; }
.login-form .form-actions { margin-top: 8px; }
.login-form .form-actions .btn { width: 100%; }
.error-panel { max-width: 640px; }
.error-detail { margin: 12px 0 0; padding: 10px; overflow-x: auto; font-family: var(--font-mono); font-size: var(--text-xs); font-variant-ligatures: none; background: var(--color-surface-alt); border: 1px solid var(--color-border); border-radius: var(--radius-control); white-space: pre-wrap; }

/* ------------------------------------------------------------ themes: top-bar switch, secret menu, User Settings tiles */

.theme-switch { display: flex; flex: none; align-items: center; margin-right: 12px; }
.theme-switch + .user-menu { margin-left: 0; }
.theme-form { display: flex; margin: 0; }
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  font: inherit;
  font-size: 18px;
  line-height: 1;
  color: var(--color-topbar-muted);
  background: none;
  border: 0;
  border-radius: var(--radius-control);
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.theme-toggle .icon { width: 18px; height: 18px; }
.theme-toggle:hover, .theme-switch.is-open .theme-toggle { color: var(--color-topbar-text); background: var(--color-nav-hover-bg); }
.theme-menu { min-width: 240px; }
.dropdown-menu > li.theme-menu-title { padding: var(--space-2) var(--space-3) var(--space-1); font-size: var(--text-xs); font-weight: 600; line-height: 16px; text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--color-text-muted); }
/* The secret rows show only when the list was opened with a modifier key (app.js sets .is-secret). */
.theme-switch:not(.is-secret) .theme-menu-secret { display: none; }
.dropdown-menu > li.theme-menu-title.theme-menu-secret { margin-top: 6px; border-top: 1px solid var(--color-border); }
.theme-menu > li > button[aria-checked="true"] { font-weight: 600; }
.theme-menu > li > button[aria-checked="true"]::after { content: ""; float: right; width: 16px; height: 16px; margin: 2px 0 0 12px; -webkit-mask-image: url(../icons/check.svg); mask-image: url(../icons/check.svg); }
/* The look switch, the menu's first row (ui_look_switch_html()): its label and a slider. Off, the slider
   is drawn in the row's text colour, so it reads on the hover tint of every theme; on, it fills with
   create green and the knob moves right. */
.theme-look { margin-bottom: var(--space-1); padding-bottom: var(--space-1); border-bottom: 1px solid var(--color-menu-border); }
.theme-look-form { margin: 0; }
.theme-look-switch {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  width: 100%;
  min-height: 44px;
  padding: var(--space-2) var(--space-3);
  font: inherit;
  font-size: var(--text-base);
  line-height: 20px;
  text-align: left;
  white-space: nowrap;
  color: var(--color-text);
  background: none;
  border: 0;
  border-radius: var(--radius-control);
  cursor: pointer;
}
.theme-look-switch:hover, .theme-look-switch:focus-visible { color: var(--color-menu-hover-text); background: var(--color-menu-hover-bg); outline: none; }
.theme-look-switch[aria-busy="true"] { cursor: progress; }
.theme-look-slider {
  position: relative;
  flex: none;
  width: 36px;
  height: 20px;
  border: 2px solid currentColor;
  border-radius: var(--radius-round);
  transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.theme-look-slider::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 10px;
  height: 10px;
  background: currentColor;
  border-radius: var(--radius-round);
  transition: transform var(--dur-1) var(--ease-out);
}
.theme-look-switch[aria-checked="true"] .theme-look-slider { background: var(--color-create-strong); border-color: var(--color-create-strong); }
.theme-look-switch[aria-checked="true"] .theme-look-slider::after { background: var(--color-on-button); transform: translateX(16px); }
@media (prefers-reduced-motion: reduce) {
  .theme-look-slider, .theme-look-slider::after { transition: none; }
}
.theme-swatch {
  display: inline-block;
  flex: none;
  width: 18px;
  height: 18px;
  margin-right: 10px;
  vertical-align: -4px;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-chip);
}

.theme-tiles { display: flex; flex-wrap: wrap; gap: 12px; }
.theme-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 150px;
  padding: 8px;
  color: var(--color-text);
  background: var(--color-surface);
  border: 2px solid var(--color-border-strong);
  border-radius: var(--radius-panel);
  cursor: pointer;
}
.theme-tile:hover { border-color: var(--color-text-muted); }
.theme-tile > input { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; pointer-events: none; }
.theme-tile > .theme-swatch { width: 100%; height: 64px; margin: 0; }
.theme-tile-name { font-size: 14px; text-align: center; }
.theme-tile:has(> input:checked) { border-color: var(--color-primary-strong); box-shadow: 0 0 0 1px var(--color-primary-strong); }
.theme-tile:has(> input:checked) > .theme-tile-name { font-weight: 600; }
.theme-tile:has(> input:checked) > .theme-tile-name::before { content: ""; display: inline-block; width: 14px; height: 14px; margin-right: 6px; vertical-align: -2px; color: var(--color-primary-strong); -webkit-mask-image: url(../icons/check.svg); mask-image: url(../icons/check.svg); }
.theme-tile:has(> input:focus-visible) { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.theme-secret-note { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin: 14px 0 0; }
.theme-secret-note > .theme-swatch { margin: 0; }
@media (max-width: 600px) {
  .theme-switch { margin-right: 4px; }
  .theme-toggle { width: 32px; }
  .user-toggle .user-name { max-width: 104px; }
}
.theme-secret-note + .field-hint, .theme-tiles + .field-hint { margin-top: 12px; }

/* A person's photo in place of the letter: the header tile keeps a 2px frame of its colour. */
.avatar.has-photo { padding: 2px; }
.avatar > img, .rec-tile > img { display: block; width: 100%; height: 100%; object-fit: cover; }
.avatar > img { border-radius: var(--radius-round); }
.rec-tile.has-photo { overflow: hidden; background: var(--color-surface-sunken); }
.dropdown-menu > li.user-card > a:hover strong, .dropdown-menu > li.user-card > a:hover span,
.dropdown-menu > li.user-card > a:focus-visible strong, .dropdown-menu > li.user-card > a:focus-visible span { color: inherit; }

/* Rainbow: the top bar's colours flow by and the module dots turn through the hues. */
@keyframes theme-rainbow-flow { to { background-position: -200% 0; } }
@keyframes theme-rainbow-hue { to { filter: hue-rotate(360deg); } }
:root[data-theme="rainbow"] .topbar { background-size: 200% 100%; animation: theme-rainbow-flow 12s linear infinite; }
:root[data-theme="rainbow"] .nav-link::before { animation: theme-rainbow-hue 12s linear infinite; }
@media (prefers-reduced-motion: reduce) {
  :root[data-theme="rainbow"] .topbar, :root[data-theme="rainbow"] .nav-link::before { animation: none; }
}

/* Retro 3.1 and Platinum: raised buttons and window frames. */
:root[data-theme="retro"] .btn, :root[data-theme="platinum"] .btn,
:root[data-theme="retro"] .filter-tab, :root[data-theme="retro"] .toggle-yesno > label {
  box-shadow: inset -1px -1px var(--bevel-dark), inset 1px 1px var(--bevel-light), inset -2px -2px var(--bevel-shade);
}
:root[data-theme="retro"] .btn:active, :root[data-theme="platinum"] .btn:active {
  box-shadow: inset 1px 1px var(--bevel-dark), inset -1px -1px var(--bevel-light);
}
:root[data-theme="retro"] .form-panel, :root[data-theme="retro"] .login-box, :root[data-theme="retro"] .dropdown-menu,
:root[data-theme="platinum"] .form-panel, :root[data-theme="platinum"] .login-box {
  box-shadow: inset 1px 1px var(--bevel-light), inset -1px -1px var(--bevel-shade);
}
:root[data-theme="platinum"] .page-sidebar, :root[data-theme="platinum"] .form-panel,
:root[data-theme="platinum"] .login-box { background-image: var(--theme-pinstripe); }

/* Retro 3.1 and Luna Blue: the login window and dialogs get a title bar. */
:root[data-theme="retro"] .login-box > .panel-header, :root[data-theme="luna"] .login-box > .panel-header {
  margin: -24px -30px 16px;
  padding: 8px 14px;
  background: var(--color-topbar-bg);
  background-image: var(--theme-topbar-image, none);
  border-radius: var(--radius-panel) var(--radius-panel) 0 0;
}
:root[data-theme="retro"] .login-box > .panel-header h2, :root[data-theme="luna"] .login-box > .panel-header h2 { font-size: var(--text-lg); color: var(--color-topbar-text); }
:root[data-theme="retro"] .modal-header, :root[data-theme="luna"] .modal-header {
  color: var(--color-topbar-text);
  background: var(--color-topbar-bg);
  background-image: var(--theme-topbar-image, none);
  border-bottom: 0;
}
:root[data-theme="retro"] .modal-close, :root[data-theme="luna"] .modal-close { color: var(--color-topbar-text); }
:root[data-theme="retro"] .modal-close:hover, :root[data-theme="luna"] .modal-close:hover { background: var(--color-nav-hover-bg); }
@media (max-width: 600px) {
  :root[data-theme="retro"] .login-box > .panel-header, :root[data-theme="luna"] .login-box > .panel-header { margin: -20px -16px 16px; }
}

/* Themes with a bold desktop colour: text never sits on it, so the calendar's weekend and off-hours
   shading uses the weekend tone and a signed-out page title takes the footer's ink. */
:root:is([data-theme="retro"], [data-theme="hotdog"], [data-theme="luna"], [data-theme="platinum"], [data-theme="vaporwave"], [data-theme="pocket"]) :is(.cal-heat, .cal-week, .cal-day) {
  --color-page-bg: var(--color-weekend);
}
:root:is([data-theme="retro"], [data-theme="hotdog"], [data-theme="luna"], [data-theme="platinum"], [data-theme="vaporwave"], [data-theme="pocket"]) .is-bare .page-title {
  color: var(--color-footer-text);
}

/* Luna Blue: glossy buttons. */
:root[data-theme="luna"] .btn, :root[data-theme="luna"] .summary-tile { background-image: var(--theme-btn-sheen); }

/* Game Pocket: links share the ink colour, so plain content links are underlined. */
:root[data-theme="pocket"] .page :is(p, dd, td, li) > a:not([class]) { text-decoration: underline; }

/* ------------------------------------------------------------ ordered choices (app.js ORDERED_PREFS) */

.setup-multi.is-ordered { display: grid; grid-template-columns: minmax(0, 1fr); gap: 3px; max-width: 460px; }
.ordered-choice { display: flex; align-items: center; gap: 4px; padding: 3px 4px 3px 8px; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-control); }
.ordered-choice > .setup-check { flex: 1 1 auto; min-width: 0; }
.ordered-move { display: inline-flex; flex: none; align-items: center; justify-content: center; width: 30px; height: 28px; padding: 0; font: inherit; color: var(--color-icon-btn); background: none; border: 1px solid var(--color-border); border-radius: var(--radius-control); cursor: pointer; }
.ordered-move:hover { color: var(--color-text); background: var(--color-row-hover); }
.ordered-choice:first-of-type > .ordered-move[data-move="up"],
.ordered-choice:last-of-type > .ordered-move[data-move="down"] { visibility: hidden; }

/* ------------------------------------------------------------ System Setup > Terminology */

.term-table { width: 100%; border-collapse: collapse; }
.term-table th, .term-table td { padding: 6px 10px; text-align: left; vertical-align: top; border-bottom: 1px solid var(--color-border); }
.term-table thead th { font-size: 13px; font-weight: 600; color: var(--color-label); }
.term-table tbody th { width: 30%; padding-top: 12px; font-weight: 400; }
.term-table td { width: 35%; }
.term-table td.is-modified { box-shadow: inset 3px 0 0 var(--color-warning); }
.term-table td.is-flash { background: var(--color-info-bg); transition: background-color .3s; }
.term-plural { color: var(--color-text-muted); }
.term-input { display: flex; align-items: center; gap: 6px; }
.term-input > input { flex: 1 1 auto; min-width: 0; }
.term-cell > .setup-modified-note { display: block; margin-top: 3px; white-space: normal; }
.term-cell.term-none { padding-top: 12px; }
.term-later { margin-top: 16px; }

/* ------------------------------------------------------------ System Setup > Appearance preview */

.appearance-preview-panel { max-width: var(--form-panel-width); margin: 0 auto 20px; }
.appearance-preview { overflow: hidden; background: var(--color-surface-alt); border: 1px solid var(--color-border-strong); border-radius: var(--radius-panel); }
.appearance-preview-bar { display: flex; align-items: stretch; gap: 0; min-height: 44px; padding: 0 12px; background: var(--preview-topbar); }
.appearance-preview-name { align-self: center; margin-right: 12px; overflow: hidden; font-size: var(--text-md); font-weight: 600; white-space: nowrap; text-overflow: ellipsis; color: var(--color-topbar-text); }
.appearance-preview-nav { display: flex; align-items: center; gap: var(--space-2); padding: 0 var(--space-3); font-size: var(--text-sm); font-weight: 500; white-space: nowrap; color: var(--color-nav-text); }
.appearance-preview-nav::before { content: ""; flex: none; width: 6px; height: 6px; background: var(--nav-color, var(--module-dashboard)); border-radius: var(--radius-round); }
.appearance-preview-nav.is-active { --nav-color: var(--module-opportunities); color: var(--color-nav-active-text); font-weight: 600; background: var(--color-nav-active-bg); box-shadow: inset 0 -3px 0 var(--module-opportunities); }
.appearance-preview-body { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 24px; padding: 16px; }
.appearance-preview-btn { display: inline-block; padding: 6px var(--space-4); font-weight: 600; color: var(--color-on-primary); background: var(--preview-primary); border-radius: var(--radius-control); }
.appearance-preview-tile { display: inline-flex; flex-direction: column; min-width: 130px; padding: 8px 12px; color: var(--color-text-inverse); background: var(--preview-primary); border-radius: var(--radius-panel); }
.appearance-preview-tile strong { font-size: 22px; line-height: 1.1; }
.appearance-preview-ratios { display: grid; grid-template-columns: auto auto; gap: 2px 10px; margin: 0; font-size: 13px; }
.appearance-preview-ratios dt { color: var(--color-label); }
.appearance-preview-ratios dd { margin: 0; font-weight: 600; }
.appearance-preview-ratios dd.is-low { color: var(--color-danger); }
.appearance-preview-note { margin: 8px 0 0; }

/* ------------------------------------------------------------ narrower screens */

/* The 1100px squeeze: tighter nav items and a 100px cap on the name and store line. */
@media (max-width: 1100px) {
  .nav-link { padding: 0 10px; }
  .user-name, .user-store { max-width: 100px; }
  .dash-counters { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .dash-counter.is-value { grid-column: 1 / -1; }
}
/* Eight menus since Asset Tracking: from 981 to 1100 px the menus sit closer and the user's name gives its room
   to the bar with the store under it (the avatar stays and the open menu names the person; the store is on User
   Settings and in the phone drawer), so the user menu never runs off the edge. */
@media screen and (min-width: 981px) and (max-width: 1100px) {
  .nav-link { padding: 0 6px; }
  .user-toggle > .user-name, .user-menu > .user-store { display: none; }
}

@media (max-width: 980px) {
  .topbar { padding-left: 0; }
  .is-bare .topbar { padding-left: var(--gutter); }
  .nav-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 var(--gutter);
    font: inherit;
    font-size: 15px;
    font-weight: 500;
    color: var(--color-topbar-text);
    background: none;
    border: 0;
    cursor: pointer;
    transition: background-color var(--dur-1) var(--ease-out);
  }
  .nav-toggle > .icon, .nav-toggle > .fa { order: -1; }
  .nav-toggle[class*="nav-"]::before { content: ""; flex: none; width: 6px; height: 6px; background: var(--nav-color); border-radius: var(--radius-round); }
  .nav-toggle[aria-expanded="true"] { background: var(--color-nav-hover-bg); }
  .main-nav {
    display: none;
    position: absolute;
    top: var(--topbar-height);
    left: 0;
    right: 0;
    max-height: calc(100vh - var(--topbar-height));
    overflow-y: auto;
    background: var(--color-nav-bg);
    box-shadow: 0 6px 12px var(--color-shadow);
  }
  .main-nav.is-open { display: block; }
  .nav-list { flex-direction: column; gap: 0; padding-bottom: 8px; }
  .nav-item { height: auto; }
  .nav-link, .nav-item.is-active > .nav-link { width: 100%; height: auto; padding: 10px 16px; text-align: left; box-shadow: none; }
  .nav-item:not(.dropdown) > .nav-link { font-size: 15px; color: var(--color-topbar-text); }
  .nav-item.dropdown > .nav-link { padding-bottom: 4px; font-size: var(--text-xs); font-weight: 600; text-transform: uppercase; letter-spacing: var(--tracking-label); cursor: default; }
  .nav-item.is-open > .nav-link { color: var(--color-nav-text); background: none; }
  .nav-item.is-active > .nav-link, .nav-item.is-active.is-open > .nav-link { color: var(--color-nav-active-text); font-weight: 600; background: var(--color-nav-hover-bg); }
  .nav-item > .dropdown-menu { display: block; position: static; min-width: 0; padding: 0 0 6px; background: none; border: 0; border-radius: 0; box-shadow: none; animation: none; }
  .nav-item > .dropdown-menu > li > a { padding: 8px 16px 8px 28px; font-size: 15px; color: var(--color-topbar-text); border-radius: 0; }
  .nav-item > .dropdown-menu > li > a:hover, .nav-item > .dropdown-menu > li > a:focus-visible { color: var(--color-topbar-text); background: var(--color-nav-hover-bg); }
  .nav-item > .dropdown-menu > li.divider { margin: 4px 16px 4px 28px; background: var(--color-nav-hover-bg); }
  .nav-item > .dropdown-menu > li.divider.is-double { border-color: var(--color-nav-hover-bg); }
  /* In the drawer the featured entry sits on the bar itself, so its tint is the bar's hover tone. */
  .nav-item > .dropdown-menu > li.nav-featured > a { background: var(--color-nav-hover-bg); }
  .page-body.with-sidebar { grid-template-columns: minmax(0, 1fr); }
  .page-body.with-sidebar > .page-content { padding-bottom: 30px; }
}

@media (max-width: 760px) {
  .table-scroll > .items-table { min-width: 720px; }
  .dash-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .form-grid, .form-grid.cols-3 { grid-template-columns: minmax(0, 1fr); }
  .form-section { grid-template-columns: minmax(0, 1fr); }
  .form-section > .form-section-icon { display: none; }
  .form-section > :not(.form-section-icon) { grid-column: 1; }
  .stat-tiles.cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat-tiles.cols-4 > .stat-tile:nth-child(n+3) { border-top: 1px solid var(--color-border); }
}

@media (max-width: 600px) {
  :root { --gutter: 16px; }
  .page-title, .form-panel .page-title, .form-title { font-size: 22px; line-height: 29px; }
  .section-title, .page-content > h2, .panel-header h2 { font-size: var(--text-lg); }
  .page-header { margin-bottom: 14px; }
  .page-actions { margin-left: 0; }
  .list-search { flex-wrap: nowrap; width: 100%; }
  .list-search > label { display: none; }
  .list-search input[type="search"], .list-search input[type="text"] { flex: 1 1 auto; width: auto; min-width: 0; }
  .list-toolbar > .toolbar-actions { margin-left: 0; }
  .form-panel, .page:has(> .page-body > .page-content > .form-panel:first-child) > .page-header { padding-left: 16px; padding-right: 16px; }
  .page:has(> .page-body > .page-content > .form-panel:first-child) { padding-left: 0; padding-right: 0; }
  .page:has(> .page-body > .page-content > .form-panel:first-child) > .crumbs { padding-left: 16px; padding-right: 16px; }
  .page-sidebar { padding: 20px var(--gutter) 30px; }
  .sidebar-panel > :not(h3):not(.action-list):not(.stat-tiles) { padding-left: 0; }
  .page-sidebar .stat-tiles:not(.cols-4) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .page-sidebar .stat-tiles:not(.cols-4) > .stat-tile:nth-child(n+3) { border-top: 1px solid var(--color-border); }
  .user-name { max-width: 150px; }
  .user-store { max-width: 150px; }
  .summary-tile { flex-basis: calc(50% - 2px); }
  .dash-panel { padding: 14px 16px 20px; }
  .dash-panel h2 { margin-bottom: 16px; font-size: var(--text-lg); }
  .dash-counters { gap: 16px; }
  .dash-counter strong { font-size: var(--text-display-1); }
  .dash-tile { min-height: 150px; }
  .login-box { margin-top: 16px; padding: 20px 16px; }
  .term-table thead { display: none; }
  .term-table, .term-table tbody, .term-table tr, .term-table th, .term-table td { display: block; width: 100%; }
  .term-table tr { padding: 6px 0; border-bottom: 1px solid var(--color-border); }
  .term-table tbody th, .term-table td { padding: 3px 0; border: 0; }
  .term-table td.is-modified { padding-left: 9px; }
}

/* ------------------------------------------------------------ compact, phone and touch (docs/ARCHITECTURE.md 5.4)

   Every rule below is screen-only and sits inside one of these queries, used exactly as written
   (app.js grmsUi.mq holds the same strings), so a mouse desktop at 981px and above and every
   printout render exactly as before:
     compact  screen and (max-width: 980px)
     phone    screen and (max-width: 760px)
     touch    screen and (max-width: 760px), screen and (pointer: coarse)
   The only unscoped rules are for elements that never exist or never show on a mouse desktop
   (.quickbar, .is-sheet, .sheet-backdrop, .toast-region) and the phone and maps link look. */

@media not screen, screen and (min-width: 981px) { .only-compact { display: none !important; } }
@media not screen, screen and (min-width: 761px) { .only-phone { display: none !important; } }
@media screen and (max-width: 980px) { .hide-compact { display: none !important; } }
@media screen and (max-width: 760px) { .hide-phone { display: none !important; } }

/* Numbers and addresses that were plain text keep the look of the text around them on a desktop,
   hover and focus included (the focus ring stays). */
a.phone-link, a.phone-link:hover, a.phone-link:focus,
a.maps-link, a.maps-link:hover, a.maps-link:focus { color: inherit; text-decoration: none; }

/* The quick bar (layout_start 'quick'); hidden unless the compact query matches. */
.quickbar { display: none; }

/* In-place sheets (grmsUi.sheet): the element stays where it is in the DOM, so its forms and
   delegated handlers keep working; display is forced so a hidden menu or panel shows. */
@keyframes grms-sheet-up { from { transform: translateY(100%); } }
@keyframes grms-sheet-down { from { transform: translateY(-16px); opacity: 0; } }
@media screen {
  html.has-sheet { overflow: hidden; }
  .sheet-backdrop { position: fixed; inset: 0; z-index: var(--z-sheet-backdrop); background: var(--color-sheet-backdrop); }
  /* The top-docked drawer lives inside the top bar's stacking context, so its backdrop sits under the bar. */
  .sheet-backdrop.is-dock-top { z-index: calc(var(--z-quickbar) + 1); }
  .is-sheet {
    display: block !important;
    position: fixed !important;
    top: auto !important;
    right: 0 !important;
    bottom: 0 !important;
    left: 0 !important;
    z-index: var(--z-sheet) !important;
    width: auto !important;
    min-width: 0 !important;
    max-width: none !important;
    max-height: var(--sheet-max-height) !important;
    max-height: min(85dvh, calc(var(--vvh, 100dvh) - 8px)) !important;
    margin: 0 !important;
    overflow-x: hidden !important;
    overflow-y: auto !important;
    overscroll-behavior: contain;
  }
  .is-sheet:not(.is-sheet-top) {
    padding: 0 var(--gutter) calc(12px + env(safe-area-inset-bottom, 0px)) !important;
    color: var(--color-text);
    background: var(--color-sheet-bg);
    border: 0;
    border-top: 1px solid var(--color-border-strong);
    border-radius: var(--radius-menu) var(--radius-menu) 0 0;
    box-shadow: 0 -6px 16px var(--color-shadow);
    animation: grms-sheet-up var(--dur-2) var(--ease-out);
  }
  /* Docked under the top bar (the menu drawer), in its own colours. */
  .is-sheet.is-sheet-top {
    top: var(--topbar-height) !important;
    bottom: auto !important;
    max-height: calc(100vh - var(--topbar-height)) !important;
    max-height: calc(var(--vvh, 100dvh) - var(--topbar-height)) !important;
    animation: grms-sheet-down var(--dur-3) var(--ease-out);
  }
  .is-sheet > .sheet-head {
    position: sticky !important;
    top: 0;
    z-index: 2;
    display: flex !important;
    align-items: center;
    gap: 8px;
    min-height: 48px;
    margin: 0 calc(-1 * var(--gutter)) 6px !important;
    padding: 2px 2px 2px var(--gutter) !important;
    list-style: none;
    background: var(--color-sheet-bg);
    border-bottom: 1px solid var(--color-border);
  }
  .is-sheet-top > .sheet-head { display: none !important; }
  .sheet-title { flex: 1 1 auto; min-width: 0; overflow: hidden; font-size: var(--text-md); font-weight: 600; line-height: 22px; white-space: nowrap; text-overflow: ellipsis; color: var(--color-label); }
  .sheet-close {
    flex: none;
    width: var(--touch-target);
    height: var(--touch-target);
    margin-left: auto;
    padding: 0;
    font: inherit;
    font-size: 28px;
    line-height: 1;
    color: var(--color-label);
    background: none;
    border: 0;
    cursor: pointer;
    touch-action: manipulation;
  }
  .sheet-close:active { background: var(--color-active-bg); }
  .sheet-close:focus-visible { outline-offset: -3px; }
  /* The sheet's title is taken from its own first heading, which the head then replaces. */
  .is-sheet > .sheet-head + h2, .is-sheet > .sheet-head + h3 { display: none !important; }
}
@media (prefers-reduced-motion: reduce) {
  .is-sheet { animation: none !important; }
}

/* Toasts (grmsUi.toast): above the quick bar, the safe area and any open sheet. */
.toast-region {
  position: fixed;
  right: 16px;
  bottom: calc(var(--quickbar-offset, 0px) + 16px);
  z-index: 300;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  max-width: min(440px, calc(100vw - 32px));
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: var(--touch-target);
  padding: 6px 6px 6px 16px;
  font-size: var(--text-base);
  font-weight: 500;
  line-height: 20px;
  color: var(--color-dark-ink);
  background: var(--color-dark-bg);
  border-radius: var(--radius-menu);
  box-shadow: var(--shadow-overlay);
  pointer-events: auto;
}
.toast.is-error { color: var(--color-text-inverse); background: var(--color-flash-error); }
@media screen and (max-width: 760px) {
  .toast-region { left: 8px; right: 8px; align-items: stretch; max-width: none; }
}
.toast-text { flex: 1 1 auto; min-width: 0; padding: 6px 10px 6px 0; overflow-wrap: anywhere; }
.toast-undo {
  flex: none;
  min-width: var(--touch-target);
  min-height: var(--touch-target);
  padding: 0 12px;
  font: inherit;
  font-weight: 600;
  color: inherit;
  text-decoration: underline;
  background: none;
  border: 0;
  cursor: pointer;
}

@media screen and (max-width: 980px) {
  body.has-quickbar {
    --quickbar-offset: calc(var(--quickbar-height) + env(safe-area-inset-bottom, 0px));
    padding-bottom: var(--quickbar-offset);
  }
  html.is-typing body.has-quickbar { --quickbar-offset: 0px; }
  .quickbar {
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: var(--z-quickbar);
    display: flex;
    gap: 1px;
    height: calc(var(--quickbar-height) + env(safe-area-inset-bottom, 0px));
    padding: 0 0 env(safe-area-inset-bottom, 0px);
    background: var(--color-quickbar-bg);
    border-top: 1px solid var(--color-quickbar-border);
    box-shadow: 0 -2px 8px var(--color-shadow);
  }
  html.is-typing .quickbar { display: none; }
  .quickbar > .quickbar-btn, .quickbar-form { flex: 1 1 0; min-width: 0; }
  .quickbar-form { display: flex; margin: 0; }
  .quickbar-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
    width: 100%;
    min-width: 0;
    height: var(--quickbar-height);
    padding: 4px 2px;
    font: inherit;
    font-size: var(--text-xs);
    font-weight: 500;
    line-height: 16px;
    text-align: center;
    color: var(--color-quickbar-text);
    background: none;
    border: 0;
    cursor: pointer;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
  }
  .quickbar-btn > span { display: block; max-width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
  .quickbar-btn > .fa { font-size: 20px; line-height: 22px; }
  .quickbar-btn > .icon { width: 20px; height: 20px; stroke-width: 1.75; }
  .quickbar-btn:hover { color: var(--color-quickbar-text); text-decoration: none; }
  .quickbar-btn:active, .quickbar-btn[aria-expanded="true"] { background: var(--color-active-bg); }
  .quickbar-btn:focus-visible { outline-offset: -3px; }
  .quickbar-btn.is-primary, .quickbar-btn.is-primary:hover { color: var(--color-on-primary); background: var(--color-primary-strong); }
  .quickbar-btn.is-primary:active { background: var(--color-primary-strong-hover); }
  .quickbar-btn.is-danger { color: var(--color-danger); }
}

@media screen and (max-width: 980px), screen and (pointer: coarse) {
  /* Phone numbers, addresses and emails: link colour and a 44px hit area without moving the text. */
  a.phone-link, a.maps-link, a.email-link { display: inline-block; padding: 12px 0; margin: -12px 0; touch-action: manipulation; }
  a.phone-link, a.phone-link:hover, a.phone-link:focus, a.maps-link, a.maps-link:hover, a.maps-link:focus { color: var(--color-link); }
}

/* Stacked cards: a table.data-table.card-table (or items-table.card-table) at phone width.
   td.card-title and td.card-aside share the first line, td.card-inline cells share one meta line
   (" · " between them), td.card-line and unclassed cells take a line each, td.card-hide goes. */
@media screen and (max-width: 760px) {
  .table-scroll > table.card-table { min-width: 0; }
  table.card-table, table.card-table > thead, table.card-table > tbody, table.card-table > tfoot, table.card-table > caption { display: block; width: 100%; }
  table.card-table > thead:not(:has(.sort-link)) { display: none; }
  /* A wrapped bar keeps its rows, and its last row and the first card, 8px apart. */
  table.card-table > thead > tr {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 18px;
    padding: 0 12px 6px 15px;
    background: var(--color-th-bg);
    border-top: 1px solid var(--color-border);
    border-bottom: 1px solid var(--color-th-border);
    box-shadow: inset var(--bar-width) 0 0 var(--color-th-bar);
  }
  table.card-table > thead > tr > th { display: none; }
  table.card-table > thead > tr > th:has(.sort-link) { display: block; padding: 0; background: none; border: 0; box-shadow: none; }
  table.card-table > thead .sort-link { display: inline-flex; align-items: center; min-height: var(--touch-target); touch-action: manipulation; }
  table.card-table > tbody > tr {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 3px 10px;
    min-height: var(--touch-target);
    padding: 10px 12px 10px 15px;
    border-bottom: 1px solid var(--color-border);
  }
  /* Ends the first line after the title and aside. */
  table.card-table > tbody > tr::after { content: ""; order: 3; flex: 0 0 100%; height: 0; }
  table.card-table > tbody > tr > :is(td, th) {
    display: block;
    order: 5;
    flex: 1 1 100%;
    width: auto;
    min-width: 0;
    padding: 0;
    text-align: left;
    white-space: normal;
    overflow-wrap: anywhere;
    background: none;
    border: 0;
    box-shadow: none;
  }
  table.card-table > tbody > tr:hover > :is(td, th) { background: none; }
  table.card-table > tbody > tr > :is(td, th):empty, table.card-table > tbody > tr > .card-hide { display: none; }
  table.card-table > tbody > tr > td.num:not(.card-aside) { text-align: left; }
  table.card-table > tbody > tr > .card-title { order: 1; flex: 1 1 0%; font-size: 16px; line-height: 22px; }
  table.card-table > tbody > tr > .card-aside { order: 2; flex: 0 1 auto; max-width: 60%; margin-left: auto; text-align: right; }
  table.card-table > tbody > tr > .card-inline { order: 4; flex: 0 1 auto; color: var(--color-label); }
  table.card-table > tbody > tr > .card-line { order: 5; flex: 1 1 100%; }
  table.card-table > tbody > tr > [data-label]::before { content: attr(data-label) ": "; color: var(--color-text-muted); }
  table.card-table > tbody > tr > .card-inline:not(:empty) ~ .card-inline::before { content: "\00B7\00A0\00A0"; color: var(--color-text-muted); }
  table.card-table > tbody > tr > .card-inline:not(:empty) ~ .card-inline[data-label]::before { content: "\00B7\00A0\00A0" attr(data-label) ": "; }
  /* A meta line that wraps (app.js): its first cell's separator is clipped off and the line moved
     left over it. Offsets and clipping move no layout, so the wrap stays where it was measured. */
  table.card-table > tbody > tr > .card-inline.card-shift { position: relative; left: calc(-1 * var(--card-sep, 0px)); }
  table.card-table > tbody > tr > .card-inline.card-lead { clip-path: inset(-100vmax -100vmax -100vmax calc(var(--card-sep, 0px) - 3px)); }
  table.card-table > tbody > tr.is-muted > :is(td, th) { color: var(--color-text-muted); }
  table.card-table > tbody > tr[class*="state-"] { box-shadow: inset var(--bar-width) 0 0 var(--row-state); }
  table.card-table > tbody > tr[class*="state-"] > :is(td, th):first-child { box-shadow: none; }
  table.card-table > tbody > tr.is-shortage { background: var(--color-shortage-bg); }
  /* The label and meta greys fall under 4.5:1 on the shortage pink. */
  table.card-table > tbody > tr.is-shortage > .card-inline,
  table.card-table > tbody > tr.is-shortage > [data-label]::before,
  table.card-table > tbody > tr.is-shortage > .card-inline ~ .card-inline::before { color: var(--color-text); }
  table.card-table > tbody > tr[data-href] { touch-action: manipulation; }
  table.card-table > tbody > tr[data-href]:active { background: var(--color-active-bg); }
  table.card-table > tbody > tr.date-band { display: block; min-height: 0; padding: 0; }
  table.card-table > tbody > tr.date-band::after { content: none; }
  table.card-table > tbody > tr.date-band > td {
    padding: 4px 12px 4px 15px;
    line-height: 22px;
    color: var(--color-label);
    background: var(--color-surface-alt);
    box-shadow: inset var(--bar-width) 0 0 var(--color-date-band-bar);
  }
  table.card-table > tfoot > tr { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 4px 12px; padding: 8px 12px 8px 15px; }
  table.card-table > tfoot > tr > :is(td, th) { display: block; padding: 0; background: none; border: 0; box-shadow: none; }
  table.card-table > tfoot > tr > :is(td, th):empty { display: none; }
}
@media screen and (max-width: 760px) and (hover: hover) {
  table.card-table > tbody > tr[data-href]:not(.is-shortage):hover { background: var(--color-row-hover); }
}

/* 100vh reaches under one engine's toolbar; the phone rule below replaces this with 92dvh. */
@media screen and (max-width: 980px) {
  dialog.modal:not(.picker-modal) { max-height: calc(100dvh - 32px); }
}

/* Dialogs become bottom sheets on a phone; the picker has its own full-screen layout. */
@media screen and (max-width: 760px) {
  dialog.modal:not(.picker-modal) {
    width: 100%;
    max-width: 100%;
    max-height: 92vh;
    max-height: 92dvh;
    margin: auto 0 0;
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  dialog.modal:not(.picker-modal) .modal-header { position: sticky; top: 0; z-index: 1; }
  dialog.modal:not(.picker-modal) .modal-footer { position: sticky; bottom: 0; z-index: 1; padding-right: 16px; padding-left: 16px; background: var(--color-surface); }
  dialog.modal:not(.picker-modal) .modal-body { padding-right: 16px; padding-left: 16px; }
  /* -12px meets the header's 12px right padding: the 44px target reaches the sheet's edge and no further. */
  dialog.modal:not(.picker-modal) .modal-close { min-width: var(--touch-target); min-height: var(--touch-target); margin: -10px -12px -10px 0; }
}

@media screen and (max-width: 760px), screen and (pointer: coarse) {
  /* A small icon control keeps its look and gets a 44 x 44 hit area. Not for positioned controls
     or ones that draw their own ::after. */
  .hit-44 { position: relative; }
  .hit-44::after { content: ""; position: absolute; top: 50%; left: 50%; width: max(100%, var(--touch-target)); height: max(100%, var(--touch-target)); transform: translate(-50%, -50%); }
  /* A text link that wraps would centre its hit area on its last line only. */
  a.hit-44 { display: inline-block; }

  /* 16px field text: one engine zooms the page into any focused field set smaller. */
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="image"]):not([type="hidden"]),
  select, textarea { font-size: var(--font-size-input-touch) !important; }
  input[type="text"], input[type="email"], input[type="password"], input[type="search"], input[type="number"],
  input[type="date"], input[type="datetime-local"], input[type="time"], input[type="tel"], input[type="url"], select { height: var(--touch-control-height); }
  .list-search input[type="search"], .list-search input[type="text"], .list-search select,
  .list-search button, .list-search .btn, .input-group > .btn { height: var(--touch-control-height); }
  .list-search .btn-link, .list-search a.btn-link { height: auto; }
  /* The report page's save field sets its own 30px (reports.css), which outranks the rule above. */
  form.rep-save-form input[type="text"] { height: var(--touch-control-height); }

  /* A swipe on an open dialog never scrolls the page under it. */
  dialog.modal { overscroll-behavior: contain; }
  html:has(dialog.modal:modal) { overflow: hidden; }
}

/* The theme list opens inside the screen, anchored under the right end of the top bar. */
@media screen and (max-width: 600px) {
  .theme-menu {
    position: fixed;
    top: var(--topbar-height);
    right: 8px;
    left: auto;
    max-width: calc(100vw - 16px);
    max-height: calc(100vh - var(--topbar-height) - 8px);
    max-height: calc(100dvh - var(--topbar-height) - 8px);
    overflow-y: auto;
  }
}

/* Row menus and list menus open as bottom sheets at compact widths (app.js); the menu stays in its
   row, so scripts that find the row with closest('tr') keep working. */
@media screen {
  .dropdown-menu.is-sheet { padding-right: 0 !important; padding-left: 0 !important; border: 0; }
  .dropdown-menu.is-sheet > .sheet-head { margin: 0 0 4px !important; }
  /* The head's close button is an li > button too: keep it the 44px square the sheet head draws. */
  .dropdown-menu.is-sheet > .sheet-head > .sheet-close {
    display: block;
    width: var(--touch-target);
    height: var(--touch-target);
    min-height: 0;
    padding: 0;
    font-size: 28px;
    line-height: 1;
    text-align: center;
    color: var(--color-label);
    background: none;
  }
  .dropdown-menu.is-sheet > li > a,
  .dropdown-menu.is-sheet > li > button,
  .dropdown-menu.is-sheet > li > .inline-form > button {
    display: flex;
    align-items: center;
    min-height: 48px;
    padding: 12px var(--gutter);
    white-space: normal;
    touch-action: manipulation;
  }
  .dropdown-menu.is-sheet > li > .inline-form { display: block; }
  .dropdown-menu.is-sheet .fa { flex: none; }
  .dropdown-menu.is-sheet > li.divider { margin: 4px 0; }
  .dropdown-menu.is-sheet > li > a:active,
  .dropdown-menu.is-sheet > li > button:active,
  .dropdown-menu.is-sheet > li > .inline-form > button:active { background: var(--color-active-bg); }
}

@media screen and (max-width: 980px) {
  /* The menu drawer (grmsUi.sheet with dock 'top'): 44px rows, section names are labels only. */
  .main-nav { max-height: calc(100dvh - var(--topbar-height)); overscroll-behavior: contain; }
  .nav-item.dropdown > .nav-link { pointer-events: none; }
  .nav-item:not(.dropdown) > .nav-link { padding-top: 12px; padding-bottom: 12px; }
  .nav-item > .dropdown-menu > li > a { padding-top: 11px; padding-bottom: 11px; }
  .nav-item:not(.dropdown) > .nav-link:active, .nav-item > .dropdown-menu > li > a:active { background: var(--color-nav-hover-bg); }
  /* A strip of the backdrop stays in view beside the drawer, so a tap there closes it. */
  .main-nav.is-sheet-top { right: auto !important; width: min(420px, calc(100% - 56px)) !important; }
}

@media screen and (max-width: 980px), screen and (pointer: coarse) {
  /* A tap on the store line opens the user menu under it. */
  .user-store { pointer-events: none; }

  /* Scroll cue (app.js sets the classes only here): an edge shadow on the side with hidden columns. */
  .table-scroll.has-overflow { display: flex; align-items: stretch; }
  .table-scroll.has-overflow > table { flex: none; }
  .table-scroll.has-overflow::before, .table-scroll.has-overflow::after,
  .filter-tabs.has-overflow::before, .filter-tabs.has-overflow::after {
    content: "";
    position: sticky;
    z-index: 3;
    flex: none;
    width: 14px;
    pointer-events: none;
    transition: opacity .15s;
  }
  .table-scroll.has-overflow::before { left: 0; margin-right: -14px; background: linear-gradient(to right, var(--color-scroll-cue), transparent); }
  .table-scroll.has-overflow::after { right: 0; margin-left: -14px; background: linear-gradient(to left, var(--color-scroll-cue), transparent); }
  /* The filter strip's chips fade into the page on the side that scrolls further. */
  .filter-tabs.has-overflow::before { left: 0; width: 40px; margin-right: -40px; background: linear-gradient(to right, var(--color-surface), transparent); }
  .filter-tabs.has-overflow::after { right: 0; width: 40px; margin-left: -40px; background: linear-gradient(to left, var(--color-surface), transparent); }
  .has-overflow.is-at-start::before, .has-overflow.is-at-end::after { opacity: 0; }
  .table-scroll[data-cue]:focus-visible { outline-offset: -2px; }
}

/* Touch sizing (docs/mobile-gap-spec.md 2.6): 44px hit areas. On a touch tablet at desktop width the
   layout stays the desktop one; only these sizes change. */
@media screen and (max-width: 760px), screen and (pointer: coarse) {
  a, button, label, summary, input, select, textarea, [role="button"] { touch-action: manipulation; }

  .btn:not(.btn-link) { height: var(--touch-control-height); padding-top: 11px; padding-bottom: 11px; }
  .btn-small:not(.btn-link) { min-width: var(--touch-target); padding-top: 12px; padding-bottom: 12px; }
  .btn-icon, .list-search .btn-icon { min-width: var(--touch-target); }
  .btn:active, .btn-primary:active, .btn-create:active { filter: brightness(.9); }
  .toggle-yesno > label { height: var(--touch-control-height); line-height: calc(var(--touch-control-height) - 2px); }

  /* A row menu's chevron keeps its size and gets a 44 x 44 hit area. */
  .btn-chevron { position: relative; }
  .btn-chevron::after { content: ""; position: absolute; top: 50%; left: 50%; width: max(100%, var(--touch-target)); height: max(100%, var(--touch-target)); transform: translate(-50%, -50%); }
  /* Its row is at least that tall, so neighbouring rows' hit areas never overlap (a cell's height is
     its row's minimum). Cards reset it in the phone query below. */
  td:has(.btn-chevron) { height: var(--touch-target); }

  /* Neighbouring tabs and toolbar buttons keep 8px apart. The segmented filter tabs and the quick
     bar's buttons are one control each and keep their joins. */
  .tabs, .toolbar-actions { gap: 8px; }

  .filter-tab { display: inline-flex; align-items: center; justify-content: center; min-width: var(--touch-target); min-height: var(--touch-target); }
  /* The desktop header-cell sort link's negative margins stop here; the rules below size it for touch. */
  th > a.sort-link:only-child { display: inline-flex; min-height: var(--touch-target); margin: 0; padding: 0; }
  .data-table > thead > tr > th:has(> .sort-link), .items-table > thead > tr > th:has(> .sort-link) { padding-top: 0; padding-bottom: 0; }
  .data-table > thead .sort-link, .items-table > thead .sort-link { display: inline-flex; align-items: center; min-width: var(--touch-target); min-height: var(--touch-target); }
  th.num > .sort-link { justify-content: flex-end; }
  .dash-counter > a:not(:first-child) { padding: 10px 0; margin: -10px 0; }
  .filter-tab:active { background: var(--color-active-bg); }
  .list-meta [data-dropdown] { min-height: var(--touch-target); }
  .list-icons a, .list-icons button { display: inline-flex; align-items: center; justify-content: center; min-width: var(--touch-target); min-height: var(--touch-target); }
  .pager-pages a, .pager-pages span { display: inline-flex; align-items: center; justify-content: center; min-width: var(--touch-target); min-height: var(--touch-target); }
  .pager-pages a:active { background: var(--color-active-bg); }

  .dropdown-menu > li > a, .dropdown-menu > li > button, .dropdown-menu > li > .inline-form > button { min-height: var(--touch-target); padding-top: 11px; padding-bottom: 11px; }
  .action-list li > a, .action-list li > .inline-form > button, .action-list li > button { padding-top: 12px; padding-bottom: 12px; }
  .action-list .fa, .action-list .icon, .action-list li > a:not(:has(> .fa, > .icon))::before, .action-list li > .inline-form > button:not(:has(> .fa, > .icon))::before { top: 14px; }
  .action-list li > a:active, .action-list li > .inline-form > button:active, .action-list li > button:active { background: var(--color-active-bg); }
  .sidebar-panel > h3[role="button"] { line-height: var(--touch-target); }

  /* Text links in a footer or the breadcrumb: a 44px tall hit area that does not move the line. */
  .table-footer a { display: inline-block; padding: 13px 0; margin: -13px 0; }
  .crumbs a { display: inline-block; padding: 13px 0; margin: -13px 0; }

  .modal-close { min-width: var(--touch-target); min-height: var(--touch-target); }

  input[type="checkbox"], input[type="radio"] { width: 22px; height: 22px; }
  label:has(> input[type="checkbox"]), label:has(> input[type="radio"]) { min-height: var(--touch-target); }

  .theme-switch { margin-right: 12px; }
  /* When the bar runs short the user name gives way, so the search box keeps its magnifier (search.css). */
  .user-menu, .user-toggle { min-width: 0; }
  .theme-toggle { position: relative; }
  .theme-toggle::after { content: ""; position: absolute; top: 50%; left: 50%; width: var(--touch-target); height: var(--touch-target); transform: translate(-50%, -50%); }

  /* Lookups: 44px options; the list stops above the on-screen keyboard (app.js scrolls the field up
     to html's scroll-padding-top, just under the top bar). */
  .autocomplete-list { max-height: max(132px, min(300px, calc(var(--vvh, 100dvh) - var(--topbar-height) - 72px))); overscroll-behavior: contain; }
  .autocomplete-list li { padding-top: 12px; padding-bottom: 12px; }
  .autocomplete-list li:active { color: var(--color-menu-hover-text); background: var(--color-menu-hover-bg); }
}

@media screen and (max-width: 760px) {
  /* The theme toggle's 44px hit area, 6px wider each side than its 32px icon, stays 10px clear of the user button. */
  .theme-switch { margin-right: 16px; }

  /* Filter tabs in a list toolbar: one sideways-scrolling row of chips (app.js brings the active one into view). */
  .list-toolbar .filter-tabs, .list-meta .filter-tabs {
    flex: 1 1 100%;
    flex-wrap: nowrap;
    min-width: 0;
    max-width: 100%;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .list-toolbar .filter-tabs::-webkit-scrollbar, .list-meta .filter-tabs::-webkit-scrollbar { display: none; }
  .list-toolbar .filter-tab, .list-meta .filter-tab { flex: none; white-space: nowrap; }

  /* Pager: Prev, "Page 2 of 19" and Next. */
  .pager-pages { flex: 1 1 100%; flex-wrap: nowrap; align-items: center; justify-content: space-between; gap: 8px; }
  .pager-pages > li { display: none; }
  .pager-pages > li.pager-prev, .pager-pages > li.pager-next, .pager-pages > li.pager-status { display: block; }
  .pager-prev > a, .pager-prev > span, .pager-next > a, .pager-next > span { padding: 0 16px; border: 1px solid var(--color-input-border); }
  .pager-status { color: var(--color-text-muted); white-space: nowrap; }

  /* Summary tiles: value and label on one line, two to a row. A label with no room beside its value
     drops whole to a second line, and the values of a row stay on the same top line. */
  .summary-tile { flex: 1 1 calc(50% - 2px); flex-direction: row; flex-wrap: wrap; align-content: flex-start; align-items: baseline; justify-content: flex-start; gap: 2px 8px; min-width: 0; min-height: var(--touch-target); padding: 11px 10px; }
  .summary-tile strong { flex: none; font-size: 16px; line-height: 20px; }
  .summary-tile span { min-width: 0; font-size: 13px; line-height: 18px; white-space: normal; overflow-wrap: break-word; }
  .summary-tile span .fa, .summary-tile span .icon { display: none; }

  /* Dashboard tiles: the heading keeps two lines and the number follows it, so the numbers in a row
     line up whichever heading or caption wraps (dashboard.css aligns the two-number tile to them). */
  .dash-tiles > .dash-tile :is(h2, h3) { min-height: 32px; }
  .dash-tile strong { margin: 0 0 auto; }

  /* Cards are at least 44px already; a chevron's cell keeps its own height in one. */
  table.card-table > tbody > tr > td:has(.btn-chevron) { height: auto; }

  /* Long forms in the main column keep Save in reach, above the quick bar. The RFID console's short
     cards keep their buttons in place (:where keeps the selector's weight). */
  .page-content .form-actions:where(:not(.rfc-card > .form-actions)) {
    position: sticky;
    bottom: var(--quickbar-offset, 0px);
    z-index: 5;
    padding-top: 10px;
    padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
    background: var(--color-surface);
    box-shadow: 0 -1px 0 var(--color-border);
  }
  .page-content .form-panel .form-actions { padding-top: 10px; background: var(--color-surface-alt); }
  .page-content dialog .form-actions, .page-content .is-sheet .form-actions { bottom: 0; }
}

@media screen and (max-width: 600px) {
  .dash-tiles { gap: 8px; }
  .dash-tile { min-height: 88px; padding: 8px 10px; }
  .dash-tiles .dash-tile h2, .dash-tiles .dash-tile h3 { font-size: var(--text-xs); line-height: 16px; }
  .dash-tile strong { font-size: var(--text-display-2); }
  .dash-tile small { font-size: var(--text-xs); line-height: 15px; }
}
