html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
html, body { overflow-x: hidden; }

/* PSBMS HUB — base styles
   Mirrors the visual language of the original single-file app:
   navy sidebar, white content area, sticky table headers, etc.

   Theming: all colours run through CSS variables. Light is the default
   (:root); dark mode is applied by setting <html data-theme="dark"> (done by
   the early theme script in shell.php / login.php). The navy sidebar and the
   brand navy stay the same in both modes; --heading is used for navy-coloured
   TEXT so it lightens on dark backgrounds. */

:root {
  color-scheme: light;
  --navy:        #1e3a5f;
  --navy-dark:   #15273f;
  --navy-light:  #2a4d7a;
  --accent:      #f59e0b;
  --bg:          #f4f6f8;
  --card:        #ffffff;
  --surface-2:   #f8fafc;   /* subtle secondary surfaces (empty cells, toolbars) */
  --text:        #1f2937;
  --text-muted:  #6b7280;
  --heading:     #1e3a5f;   /* navy-coloured text (headings, titles) */
  --border:      #e5e7eb;
  --row-hover:   #f0f4f8;
  --today-bg:    #fff7ed;   /* "today" highlight in calendars */
  /* Soft tint panels (flip to muted dark equivalents in dark mode). */
  --tint-red:    #fef2f2;
  --tint-amber:  #fef9f4;
  --tint-green:  #eef6ee;
  --tint-blue:   #eef4fb;
  --tint-indigo: #e0e7ff;
  --tint-peach:  #fbe7d6;
  --tint-slate:  #f1f5f9;
  --success:     #059669;
  --danger:      #dc2626;
  --warning:     #d97706;
  /* VC-248 — consolidated design tokens (Visual Consistency plan).
     Fonts: one sans + one mono app-wide. Status hues: exactly one bg + one
     text colour per semantic, themed for light AND dark. Type scale and radii
     replace the scattered literals. */
  --font-sans:   -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-mono:   ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --info:        #2563eb;
  --purple:      #7c3aed;
  --text-subtle: rgba(31,41,55,0.72);
  --ok-bg:#dcfce7;   --ok-fg:#166534;
  --err-bg:#fee2e2;  --err-fg:#991b1b;
  --warn-bg:#fef3c7; --warn-fg:#92400e;
  --info-bg:#dbeafe; --info-fg:#1e40af;
  --purple-bg:#ede9fe; --purple-fg:#5b21b6;
  --mut-bg:#e2e8f0;  --mut-fg:#475569;
  /* Sidebar text (navy band is identical in both themes). */
  --nav-text:     rgba(255,255,255,0.85);
  --nav-text-dim: rgba(255,255,255,0.72);
  /* Type scale (matches the app's real usage: tables/base 14, small 12/13). */
  --fs-xs:11px; --fs-sm:12px; --fs-base:13px; --fs-md:14px;
  --fs-lg:16px; --fs-xl:20px; --fs-2xl:24px;
  --fw-regular:400; --fw-medium:600; --fw-bold:700;
  /* Radii: sm = inputs/buttons, md = cards/panels, lg = large surfaces, pill = badges/chips. */
  --radius-sm:4px; --radius-md:8px; --radius-lg:12px; --radius-pill:999px;
  --shadow-sm:   0 1px 2px rgba(0,0,0,0.05);
  --shadow:      0 1px 4px rgba(0,0,0,0.08);
}

/* ============ Dark theme ============ */
html[data-theme="dark"] {
  color-scheme: dark;
  --bg:          #0f141c;
  --card:        #1a212e;
  --surface-2:   #222b3a;
  --text:        #e5e7eb;
  --text-muted:  #9aa6b6;
  --heading:     #d6e4f7;
  --border:      #2d3748;
  --row-hover:   #253044;
  --today-bg:    rgba(245,158,11,0.16);
  --tint-red:    #3a1f1f;
  --tint-amber:  #33291a;
  --tint-green:  #163024;
  --tint-blue:   #1c2a40;
  --tint-indigo: #262649;
  --tint-peach:  #3a2a1e;
  --tint-slate:  #222c3c;
  /* VC-248 dark values — text-role hues brighten; bg-role hues darken. */
  --purple:      #8169d8;
  --text-subtle: rgba(229,231,235,0.75);
  --ok-bg:#163024;   --ok-fg:#6ee7b7;
  --err-bg:#3a1f1f;  --err-fg:#fca5a5;
  --warn-bg:#33291a; --warn-fg:#fcd34d;
  --info-bg:#1c2a40; --info-fg:#93c5fd;
  --purple-bg:#262649; --purple-fg:#c4b5fd;
  --mut-bg:#222c3c;  --mut-fg:#9aa6b6;
  --shadow-sm:   0 1px 2px rgba(0,0,0,0.40);
  --shadow:      0 2px 6px rgba(0,0,0,0.50);
}
/* Elements that use light pastel literals get dark-mode equivalents. */
/* R283: dark-theme toast overrides removed — .toast now uses the semantic
   --ok/--err/--info token pairs, which flip with the theme automatically. */
html[data-theme="dark"] .cal-chip-t     { background: #0b3d2e; color: #6ee7b7; }
html[data-theme="dark"] .cal-chip-m     { background: #1e3252; color: #93c5fd; }
html[data-theme="dark"] .rt-btn:hover   { background: #2a3446; }

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body { font-family: var(--font-sans); font-size: var(--fs-md); color: var(--text); background: var(--bg); }
/* VC-248 P0: form controls inherit the app font instead of the UA default
   (the source of the harvested bare-Arial / 13.3333px nodes). */
input, select, textarea, button { font-family: var(--font-sans); font-size: inherit; }
code, pre, kbd, .mono { font-family: var(--font-mono); }
/* VC-248 P4: heading levels bound to fixed styles (component-scoped rules
   below may still specialise; red/semantic colours are never structural). */
h1 { font-size: var(--fs-2xl); font-weight: var(--fw-bold); color: var(--heading); }
h2 { font-size: var(--fs-xl); font-weight: var(--fw-bold); color: var(--heading); }
h3 { font-size: var(--fs-lg); font-weight: var(--fw-medium); color: var(--heading); }
h4 { font-size: var(--fs-base); font-weight: var(--fw-medium); color: var(--heading); }
a { color: var(--navy-light); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ============ Login page ============ */
.login-body { display: grid; place-items: center; min-height: 100vh; background: linear-gradient(135deg, var(--navy) 0%, var(--navy-dark) 100%); }
.login-card { background: var(--card); padding: 36px 32px; border-radius: var(--radius-lg); min-width: 340px; max-width: 380px; box-shadow: 0 10px 40px rgba(0,0,0,0.2); }
.login-brand { text-align: center; margin-bottom: 24px; }
.login-logo { font-size: 28px; font-weight: 800; /* brand lockup — intentional, not part of the type scale */ color: var(--heading); letter-spacing: 2px; }
.login-tag  { font-size: 13px; color: var(--text-muted); margin-top: 4px; }
.field { display: block; margin-bottom: 14px; }
.field span { display: block; font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 4px; }
.field input { width: 100%; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-md); font-size: 14px; }
.field input:focus { outline: none; border-color: var(--navy-light); box-shadow: 0 0 0 3px rgba(42,77,122,0.15); }
.btn-primary { width: 100%; background: var(--navy); color: white; border: 0; padding: 11px; border-radius: var(--radius-sm); font-size: var(--fs-md); font-weight: var(--fw-medium); cursor: pointer; }
.btn-primary:hover { background: var(--navy-light); }
.error { color: var(--danger); font-size: 13px; margin-top: 10px; }
.login-foot { text-align: center; margin-top: 20px; font-size: 12px; color: var(--text-muted); }

/* Sign-in card + the cross-sell link stack together as one centred group, so
   adding the link below never disturbs the card's centring on the login grid. */
.login-stack { display: flex; flex-direction: column; align-items: center; }

/* R270 (Piotr): the Engineering Software cross-sell block was removed from
   the login page (markup gone from login.php; its styles removed here).
   .login-stack stays — the sign-in card wrapper still uses it. */

/* ============ App shell ============ */
/* overflow:hidden on the grid + min-width:0 on the scrolling main column
   keeps the sidebar at exactly 100vh on every page — without this, a wide
   table or oversized card can push the grid track taller than the viewport
   and stretch the sidebar to match. */
.app-body { display: grid; grid-template-columns: 220px 1fr; height: 100vh; overflow: hidden; }
.sidebar { background: var(--navy); color: white; display: flex; flex-direction: column; height: 100vh; }
.sidebar-brand { padding: 18px 18px 14px; border-bottom: 1px solid var(--navy-light); }
.brand-mark { font-size: 22px; font-weight: 800; /* brand lockup — intentional, not part of the type scale */ letter-spacing: 1.5px; }
.brand-sub { font-size: 11px; opacity: 0.7; margin-top: 4px; }
.brand-logo { display: block; width: 100%; max-width: 170px; height: auto; }
.nav { flex: 1; padding: 8px 6px; overflow-y: auto; }
.nav-item { display: block; padding: 5px 12px; color: var(--nav-text); border-radius: var(--radius-sm); cursor: pointer; font-size: 13px; margin-bottom: 1px; line-height: 1.35; }
.nav-item:hover { background: var(--navy-light); color: white; text-decoration: none; }
.nav-item.active { background: var(--navy-light); color: white; font-weight: 600; }
/* Collapsible nav groups (R-NAVGROUPS). Headers are buttons so they're
   keyboard-reachable; items inside a group indent slightly so the hierarchy
   reads at a glance. */
/* Group headers read as PARENT categories: a shaded full-width band with an
   amber accent bar + chevron, clearly heavier than the page links nested
   under them. */
.nav-group-head { display: flex; align-items: center; gap: 6px; width: 100%; background: rgba(255,255,255,0.08); border: 0; border-left: 3px solid var(--accent); text-align: left; padding: 6px 8px 6px 7px; margin-top: 10px; color: var(--nav-text); font-size: var(--fs-xs); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 1px; cursor: pointer; border-radius: var(--radius-sm); }
.nav-group-head:hover { background: rgba(255,255,255,0.14); color: #fff; }
.nav-group-chev { font-size: 9px; width: 10px; display: inline-block; color: var(--accent); }
.nav-group-body .nav-item { padding-left: 22px; }
.sidebar-foot { padding: 12px; border-top: 1px solid var(--navy-light); }
.user-chip { padding: 6px 0 10px; }
.user-name { font-weight: 600; font-size: 13px; }
.user-role { font-size: 11px; opacity: 0.7; }
.btn-ghost { width: 100%; background: transparent; color: white; border: 1px solid rgba(255,255,255,0.3); padding: 7px; border-radius: var(--radius-sm); cursor: pointer; font-size: var(--fs-base); }
.btn-ghost:hover { background: var(--navy-light); }

/* Theme switch (Auto / Light / Dark) — lives in the navy sidebar footer. */
.theme-switch { display: flex; gap: 3px; margin: 0 0 10px; background: rgba(255,255,255,0.08); border-radius: var(--radius-md); padding: 3px; }
.theme-opt { flex: 1; background: transparent; border: 0; color: var(--nav-text-dim); font-size: var(--fs-sm); padding: 5px 2px; border-radius: var(--radius-sm); cursor: pointer; line-height: 1.1; }
.theme-opt:hover { color: #fff; }
.theme-opt.active { background: var(--navy-light); color: #fff; font-weight: 600; }

/* R283 (UX audit): coarse-pointer touch targets — sidebar links, group heads
   and theme controls get 44px-tall hit areas on touch devices and mobile
   widths. Desktop mouse density is unchanged. */
@media (hover: none), (max-width: 768px) {
  .nav-item { min-height: 44px; display: flex; align-items: center; padding-top: 8px; padding-bottom: 8px; }
  .nav-group-head { min-height: 44px; }
  .theme-opt { min-height: 40px; }
}

/* R283 (UX audit): respect the OS "reduce motion" preference — remove
   transitions/animations and smooth scrolling app-wide for users who ask
   their system for less movement. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Landing-page picker (sidebar foot) — the native dropdown list pops up on a
   light OS panel while the options inherit the sidebar's white text, making
   them unreadable in both themes. Force a dark scheme + explicit option
   colours so the list is navy-on-white-text everywhere (the sidebar is navy
   in BOTH light and dark modes). */
#landing-select { color-scheme: dark; }
#landing-select option { background: var(--navy); color: #fff; }

/* Nav toggle (hamburger) + backdrop.
   Desktop (≥1000px): the toggle collapses / restores the sidebar (.nav-collapsed).
   Below 1000px: it opens the off-canvas drawer (.nav-open); the
   max-width:999px block below adjusts size. The backdrop is mobile-only. */
.nav-toggle {
  display: flex; align-items: center; justify-content: center;
  position: fixed; top: 8px; left: 8px; z-index: 1100;
  width: 40px; height: 40px; padding: 0;
  background: var(--navy); color: #fff; border: none; border-radius: var(--radius-md);
  font-size: 21px; line-height: 1; cursor: pointer;
  box-shadow: 0 1px 5px rgba(0,0,0,0.3);
}
.nav-toggle:hover { background: var(--navy-light); }
.nav-backdrop { display: none; }

/* Desktop sidebar collapse. The grid column animates to 0 and the sidebar
   content is clipped; the fixed toggle stays put so the panel can be
   restored. Scoped to desktop so it never fights the mobile drawer rules. */
@media (min-width: 1000px) {
  .app-body { transition: grid-template-columns 0.2s ease; }
  .app-body.nav-collapsed { grid-template-columns: 0 1fr; }
  .app-body.nav-collapsed .sidebar { overflow: hidden; }
  /* Drop the toggle clear of the logo so it doesn't cover the brand. */
  .sidebar-brand { padding-top: 50px; }
  /* When collapsed, keep the page heading clear of the fixed toggle. */
  .app-body.nav-collapsed .page-toolbar { padding-left: 56px; }
}

/* min-width:0 stops a wide child (long table, wide card) from pushing the
   grid column out — without it grid items default to min-content which
   blows wide content past the column. */
.main-col { display: flex; flex-direction: column; min-width: 0; min-height: 0; overflow: hidden; }
.main { overflow-y: auto; overflow-x: auto; padding: 0; min-width: 0; flex: 1; }

/* Persistent banner strip (e.g. backup reminder) above the SPA mount. */
.app-banner-strip { display: flex; align-items: center; gap: 10px; padding: 8px 14px;
  background: var(--tint-amber); color: var(--text); border-bottom: 1px solid var(--border); font-size: 13px; }
.app-banner-strip a { font-weight: 700; color: var(--heading); text-decoration: underline; }
.app-banner-dismiss { margin-left: auto; border: 0; background: transparent; cursor: pointer;
  color: var(--text-muted); font-size: 16px; line-height: 1; padding: 6px 10px; min-width: 32px; }
.app-banner-dismiss:hover { color: var(--text); }

/* ============ Page chrome ============ */
.page-toolbar { position: sticky; top: 0; z-index: 6; background: var(--card); padding: 14px 24px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 12px; box-shadow: var(--shadow-sm); }
.page-title { font-size: 20px; font-weight: 700; color: var(--heading); margin: 0; }
.toolbar-spacer { flex: 1; }
.page-body { padding: 18px 24px; }

/* ============ Tables ============ */
.table-wrap { background: var(--card); border-radius: var(--radius-md); box-shadow: var(--shadow); }
table.list { width: 100%; border-collapse: collapse; font-size: 14px; }
.list thead th { position: sticky; top: 52px; z-index: 5; background: var(--navy); color: white; text-align: left; padding: 10px 12px; font-weight: 600; font-size: 13px; }
.list tbody td { padding: 10px 12px; border-bottom: 1px solid var(--border); }
.fm-list tbody td { vertical-align: top; }
.fm-file-view:hover { text-decoration: underline; }
.list tbody tr.clickable { cursor: pointer; }
.list tbody tr.clickable:hover { background: var(--row-hover); }

/* R251 (Piotr): row hairlines + cursor highlight everywhere data is read in
   rows — the same experience as the Invoices list. `.data-table` previously
   had NO styling at all (bare rows on Bookkeeping Transactions / Templates /
   Quarterly VAT, and on Ledger + Audit which share the class); `.list`
   highlighted only rows explicitly marked clickable (so Reconcile/Payables
   had lines but no hover). Mobile card collapses are unaffected — they reset
   td borders/padding with !important. */
.data-table { width: 100%; border-collapse: collapse; font-size: var(--fs-md); }
.data-table th { text-align: left; padding: 8px 10px; font-weight: var(--fw-medium); color: var(--heading); border-bottom: 2px solid var(--border); }
.data-table td { padding: 8px 10px; border-bottom: 1px solid var(--border); }
.data-table tbody tr:hover,
.list tbody tr:hover { background: var(--row-hover); }
.num { text-align: right; font-variant-numeric: tabular-nums; }
/* Numeric column headers — bump specificity so `.num` beats the generic
   `.list thead th { text-align:left }` rule above. Without these selectors,
   headers like Total / Value / Labour / Materials / Mileage / Margin sit
   left-aligned while their values below right-align, looking broken. */
.list thead th.num,
thead th.num,
table th.num { text-align: right; }
/* Sortable list headers (R-SORT) — cursor invites the click; the ▲▼
   indicator span is injected by the app.js delegated handler. */
table.list[data-sortable] thead th { cursor: pointer; user-select: none; }
table.list[data-sortable] thead th:hover { background: var(--navy-light); }
.sort-ind { font-size: 10px; opacity: 0.9; }

/* ============ Toast / messages ============ */
/* Above every overlay (detail views 1500, sheets 1600, modals 1700) so save
   feedback is never buried. */
.toast { position: fixed; right: 20px; bottom: 20px; padding: 12px 16px; border-radius: var(--radius-md); box-shadow: var(--shadow); z-index: 2000; font-size: 14px; }
/* R283 (UX audit): toasts moved onto the VC-248 semantic AA pairs — the
   legacy #d1fae5/#059669-style combinations failed normal-text contrast
   (~3.3:1). Token pairs flip with the theme automatically. */
.toast.success { background: var(--ok-bg);   color: var(--ok-fg); }
.toast.error   { background: var(--err-bg);  color: var(--err-fg); }
.toast.info    { background: var(--info-bg); color: var(--info-fg); }

/* ============ Buttons ============ */
.btn { background: var(--navy); color: white; border: 0; padding: 8px 14px; border-radius: var(--radius-sm); font-size: var(--fs-md); font-weight: var(--fw-medium); cursor: pointer; }
.btn:hover { background: var(--navy-light); }
.btn.secondary { background: var(--card); color: var(--heading); border: 1px solid var(--border); }
.btn.secondary:hover { background: var(--row-hover); }
.btn.danger { background: var(--danger); }
.btn.danger:hover { background: #b91c1c; }

/* ============ Forms ============ */
.form-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }
.form-grid .full { grid-column: 1 / -1; }
.form-grid label { display: block; }
.form-grid label > span { display: block; font-size: 12px; font-weight: 600; color: var(--text-muted); margin-bottom: 4px; text-transform: uppercase; letter-spacing: 0.3px; }
.form-grid label.cbx { display: flex; align-items: center; gap: 8px; }
.form-grid label.cbx > span { display: inline; font-size: 14px; font-weight: 400; color: var(--text); margin: 0; text-transform: none; letter-spacing: normal; }
.form-grid label.cbx > input[type="checkbox"] { flex: 0 0 auto; width: 16px; height: 16px; margin: 0; }
.form-grid input, .form-grid select, .form-grid textarea { width: 100%; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: 14px; font-family: inherit; }
.form-grid textarea { min-height: 80px; resize: vertical; }

/* ============ Modal ============ */
/* 1700: above the mobile DetailView (1500) and BottomSheet (1600) so flows
   launched from them — e.g. the chase-email compose — layer correctly. */
.modal-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 1700; display: grid; place-items: center; padding: 20px; overflow-y: auto; }
.modal-card { background: var(--card); border-radius: var(--radius-lg); max-width: 640px; width: 100%; max-height: calc(100vh - 40px); overflow-y: auto; box-shadow: 0 20px 60px rgba(0,0,0,0.3); }
.modal-head { display: flex; align-items: center; padding: 16px 22px; border-bottom: 1px solid var(--border); }
.modal-head h2 { margin: 0; font-size: 18px; color: var(--heading); flex: 1; }
.modal-close { background: none; border: 0; font-size: 28px; line-height: 1; color: var(--text-muted); cursor: pointer; padding: 0 6px; }
.modal-close:hover { color: var(--text); }
.modal-card form { padding: 22px; }
.modal-actions { display: flex; gap: 10px; align-items: center; padding-top: 18px; margin-top: 18px; border-top: 1px solid var(--border); }

/* Nested rows inside modal forms (sites/contacts/line items) */
.nested-row input, .nested-row select, .nested-row textarea { padding: 6px 8px; border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: 13px; font-family: inherit; width: 100%; }
.nested-row .del-row { padding: 5px 10px; min-width: 32px; }

/* ============ Planner ============ */
.planner-wrap { background: var(--card); border-radius: var(--radius-md); box-shadow: var(--shadow); overflow: hidden; }
.planner-grid { width: 100%; border-collapse: collapse; table-layout: fixed; }
/* PLAN-UX P0 fallback (2026-07-09): if the desktop grid ever renders below the
   1000px tier (the JS agenda normally takes over there — this covers the
   resize-without-redraw edge), keep chips readable via contained horizontal
   scroll with a sticky person column instead of crushing 7 columns into 400px. */
@media (max-width: 999px) {
  .planner-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .planner-grid { min-width: 940px; }
  .planner-grid th:first-child, .planner-grid td:first-child {
    position: sticky; left: 0; z-index: 2; background: var(--card);
  }
}
.planner-grid th, .planner-grid td { border: 1px solid var(--border); }

.planner-corner-cell { width: 140px; background: var(--navy); }
.planner-day-head { background: var(--navy); color: white; padding: 8px; text-align: center; font-weight: 600; }
.planner-day-head .day-name { font-size: 13px; text-transform: uppercase; letter-spacing: 0.5px; }
.planner-day-head .day-date { font-size: 11px; opacity: 0.85; margin-top: 2px; }
.planner-day-head.today { background: var(--accent); color: var(--navy-dark); }
.planner-day-head.today .day-name { color: var(--navy-dark); }

.planner-name-cell { width: 140px; background: var(--bg); padding: 12px 10px; text-align: left; vertical-align: middle; font-weight: 600; color: var(--heading); border-right: 2px solid var(--navy) !important; }
.planner-name-cell .eng-name { font-size: 14px; }

.planner-cell { height: 90px; vertical-align: top; padding: 4px; cursor: pointer; font-size: 12px; line-height: 1.35; transition: outline 0.1s; overflow: hidden; background: var(--card); }
.planner-cell .cell-content { display: flex; flex-direction: column; gap: 3px; height: 100%; }
.planner-cell:hover { outline: 2px solid var(--navy); outline-offset: -2px; }
.planner-cell.empty { background: var(--surface-2); }
.planner-cell.empty:hover { background: var(--row-hover); }
.planner-cell .wo-link { font-weight: 700; text-decoration: underline; color: inherit; }
.planner-cell .wo-link:hover { opacity: 0.7; }
.planner-entry { padding: 4px 6px; border-radius: var(--radius-sm); word-break: break-word; line-height: 1.25; font-size: 11px; flex: 1 1 auto; }

/* Category chips in the cell-edit modal */
.cat-chips { display: flex; flex-wrap: wrap; gap: 6px; }
/* PLAN-UX P2 (2026-07-09): nowrap stops a chip's label breaking mid-word at
   narrow widths, which read as a "clipped" chip in the audit. */
.cat-chip { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: var(--radius-pill); font-size: 13px; font-weight: 600; cursor: pointer; user-select: none; white-space: nowrap; }
.cat-chip input { margin: 0; cursor: pointer; }
.cat-chip:hover { opacity: 0.85; }
.cat-chip input:checked + span::after { content: ' ✓'; }

/* ============ Dashboard ============ */
.kpi-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; margin-bottom: 16px; }
.kpi-card { background: var(--card); padding: 14px 16px; border-radius: var(--radius-md); box-shadow: var(--shadow-sm); border-left: 4px solid var(--navy); }
.kpi-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted); }
.kpi-value { font-size: 24px; font-weight: 700; color: var(--heading); margin-top: 4px; }
.kpi-sub   { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
/* R257 (Piotr): KPI cards light up under the cursor — the same row-hover cue
   as tables. Dashboard cards deep-link on click, so hover signals behaviour;
   the Reports KPI strip shares the component and gets the same feel. */
.kpi-card { transition: background 0.12s ease, box-shadow 0.12s ease; }
.kpi-card:hover { background: var(--row-hover); box-shadow: var(--shadow); }
a.kpi-card:hover { text-decoration: none; }

.dash-grid { display: grid; grid-template-columns: 2fr 1fr; gap: 14px; }
/* Grid children default to min-width:auto, so a card can never shrink below
   its content — the Chart.js canvas therefore pinned the revenue card (and
   the whole row) at its grown width while every other panel narrowed.
   min-width:0 lets the card shrink; Chart.js (responsive:true) then resizes
   the canvas to follow. */
.dash-grid > .dash-card { min-width: 0; }
.dash-card { background: var(--card); padding: 16px 18px; border-radius: var(--radius-md); box-shadow: var(--shadow); }
.dash-card h3 { margin: 0 0 12px; font-size: 14px; color: var(--heading); text-transform: uppercase; letter-spacing: 0.5px; }
/* DASH-UX R2 Task 1 (2026-07-09): below ~1300px viewport the 1fr side card
   (Top debtors / Top clients) drops under ~320px once the sidebar + padding
   are taken out, which clipped the Overdue + "chase ›" column. Collapse to a
   single column much earlier — cards stack full-width and nothing clips. */
@media (max-width: 1300px) { .dash-grid { grid-template-columns: 1fr; } }

/* ============ Settings ============ */
.settings-card { background: var(--card); padding: 18px 22px; border-radius: var(--radius-md); box-shadow: var(--shadow); margin-bottom: 14px; }
.settings-card h2 { margin: 0 0 14px; font-size: 16px; color: var(--heading); }

/* ============ My Time — calendar grid + day modal ============ */
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--radius-md); overflow: hidden; }
.cal-head { background: var(--navy); color: white; padding: 6px 8px; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; text-align: center; }
.cal-cell { background: var(--card); min-height: 90px; padding: 6px 8px; cursor: pointer; display: flex; flex-direction: column; transition: background 0.1s; }
.cal-cell:hover { background: var(--row-hover); }
.cal-cell-other { background: var(--surface-2); color: var(--text-muted); opacity: 0.55; }
.cal-cell-today { background: var(--today-bg); border: 2px solid var(--accent); padding: 4px 6px; }
.cal-date { font-size: 12px; font-weight: 600; color: var(--heading); margin-bottom: 4px; }
.cal-cell-today .cal-date { color: var(--accent); }
.cal-chip { display: block; font-size: 11px; padding: 2px 6px; border-radius: var(--radius-sm); margin-bottom: 2px; line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-chip-t { background: #dcfce7; color: #166534; }   /* hours = green */
.cal-chip-m { background: #dbeafe; color: #1e40af; }   /* mileage = blue */

.day-entry { display: flex; gap: 10px; align-items: center; padding: 8px 10px; background: var(--bg); border-radius: var(--radius-md); margin-bottom: 6px; }
.day-entry-icon { font-size: 18px; }
.day-entry-main { flex: 1; font-size: 13px; }
.day-entry.dragging { opacity: 0.45; outline: 2px dashed var(--navy); }
.day-entry-handle:active { cursor: grabbing; }
.day-add { background: var(--surface-2); border: 1px dashed var(--border); border-radius: var(--radius-md); padding: 12px; }

/* ============ Responsive tiers (Build Plan Phase 2) ============ */
/* Desktop ≥1000px is untouched. Below 1000px the "mobile patterns" apply
   (off-canvas drawer, wrapped toolbars, full-screen editors) for BOTH the
   tablet tier (700–999px) and the phone tier (<700px). The legacy phone
   density rules (single-column forms, hidden table columns, compact
   calendar) keep their proven 768px line — flagged in the phase report. */

/* ---- Mobile patterns: tablet + phone (<1000px) ---- */
@media (max-width: 999px) {
  .app-body { grid-template-columns: 1fr; height: 100dvh; }

  .nav-toggle {
    display: flex; align-items: center; justify-content: center;
    position: fixed; top: 8px; left: 8px; z-index: 1100;
    width: 44px; height: 44px; padding: 0;
    background: var(--navy); color: #fff; border: none; border-radius: var(--radius-md);
    font-size: 22px; line-height: 1; cursor: pointer;
    box-shadow: 0 1px 5px rgba(0,0,0,0.3);
  }

  .sidebar {
    position: fixed; top: 0; left: 0;
    /* R303: 100dvh (dynamic viewport) so the drawer footer + Log out sit above
       the mobile browser's bottom toolbar; 100vh fallback for old engines. */
    width: 250px; max-width: 84vw; height: 100vh; height: 100dvh; z-index: 1090;
    transform: translateX(-100%);
    transition: transform 0.25s ease;
    box-shadow: 2px 0 12px rgba(0,0,0,0.25);
  }
  .app-body.nav-open .sidebar { transform: translateX(0); }

  .nav-backdrop {
    display: block; position: fixed; inset: 0; z-index: 1080;
    background: rgba(0,0,0,0.45);
    opacity: 0; pointer-events: none; transition: opacity 0.25s ease;
  }
  .app-body.nav-open .nav-backdrop { opacity: 1; pointer-events: auto; }

  /* Wrapped toolbar, clear of the fixed hamburger. */
  .page-toolbar { flex-wrap: wrap; gap: 8px; padding: 10px 12px 10px 60px; }
  .page-toolbar .page-title { width: 100%; margin: 0; }
  .toolbar-spacer { display: none; }
  .page-toolbar .btn, .page-toolbar select { font-size: 13px; padding: 8px 12px; }

  .table-wrap { overflow-x: auto; }
  /* The wrapped mobile toolbar is taller than the desktop 52px sticky offset,
     which left a blank band above the header and hid the first row. Don't stick
     the table header below 1000px. */
  .list thead th { position: static; top: auto; }

  /* Full-screen, comfortable editors (plan: DetailView, not centre modal) */
  .modal-backdrop { padding: 0; }
  .modal-card { max-width: 100%; width: 100%; min-height: 100vh; max-height: 100vh; border-radius: 0; }
  .modal-card form { padding: 16px; }
  .modal-actions { position: sticky; bottom: 0; background: var(--card); }

  /* 16px inputs stop iOS/iPadOS auto-zoom on focus; ≥44px touch targets */
  .form-grid input, .form-grid select, .form-grid textarea { font-size: 16px; padding: 10px 12px; }
  .btn { padding: 10px 16px; min-height: 44px; }

  /* Works Report editor (custom overlay, not .modal-card) — full-screen with
     a wrapping action bar so engineers can finish a report on-site. */
  #wr-editor-overlay { padding: 0 !important; align-items: flex-start !important; -webkit-overflow-scrolling: touch; }
  #wr-editor-overlay > div { width: 100% !important; max-width: 100% !important; min-height: 100vh; border-radius: 0 !important; overflow: visible !important; }
  #wr-editor-overlay form { padding: 14px !important; }
  #wr-editor-overlay .modal-actions { flex-wrap: wrap; }

  /* Full-screen modal/overlay headers start at the top of the screen, under the
     fixed hamburger — indent their titles so the button doesn't obstruct them. */
  .modal-card .modal-head { padding-left: 60px; }
  #wr-editor-overlay .modal-head { padding-left: 60px !important; }
}

/* ---- Phone density (legacy 768px line — see tier note above) ---- */
@media (max-width: 768px) {
  /* Files page: too many columns for a phone — hide Uploaded-by + Date so
     Name, Size and the action buttons fit without sideways scrolling. */
  .fm-list th:nth-child(4), .fm-list td:nth-child(4),
  .fm-list th:nth-child(5), .fm-list td:nth-child(5) { display: none; }
  .fm-list td:nth-child(2) { word-break: break-word; overflow-wrap: anywhere; }
  .fm-list td:last-child { white-space: normal !important; }
  .kpi-row { grid-template-columns: 1fr 1fr; gap: 8px; }

  /* Calendar is desktop-shaped; JS switches to the list view on phones, but if
     it is shown, keep the cells compact rather than unusable. */
  .cal-cell { min-height: 54px; padding: 3px 4px; }
  .cal-date { font-size: 11px; }
  .cal-chip { font-size: 10px; }

  /* Single-column forms on phones */
  .form-grid { grid-template-columns: 1fr; gap: 12px; }
  .day-add select[size] { font-size: 15px; }
}

/* Rich-text editor (richtext.js) */
.rt-wrap { border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; background: var(--card); }
.rt-toolbar { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; padding: 5px 7px; background: var(--surface-2); border-bottom: 1px solid var(--border); }
.rt-btn { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-sm); min-width: 26px; height: 24px; font-size: 12px; cursor: pointer; color: var(--heading); padding: 0 6px; line-height: 1; }
.rt-btn:hover { background: var(--row-hover); }
/* NOTES-UX P1 (09/07): visible active state for Bold/Italic/Underline. */
.rt-btn.rt-on { background: var(--heading); color: var(--card); border-color: var(--heading); }
/* NOTES-UX P1: comfortable toolbar targets on coarse pointers / phones. */
@media (hover: none), (max-width: 768px) {
  .rt-toolbar { gap: 6px; }
  .rt-btn { min-width: 40px; height: 40px; font-size: 14px; }
  .rt-sw { width: 32px; height: 32px; }
}
/* QUO-UX P2+P4 (09/07): modal footer buttons and the quote-builder ⋮⋮ drag
   handles get real touch targets on coarse pointers / phones. */
@media (hover: none), (max-width: 768px) {
  .modal-actions .btn { min-height: 44px; }
  .row-handle { font-size: 18px !important; padding: 10px 8px; }
}
.rt-sep { width: 1px; height: 18px; background: var(--border); margin: 0 3px; }
.rt-swatches { display: inline-flex; gap: 3px; }
.rt-sw { width: 18px; height: 18px; border: 1px solid rgba(0,0,0,0.2); border-radius: var(--radius-sm); cursor: pointer; padding: 0; }
.rt-editor { min-height: 90px; max-height: 320px; overflow: auto; padding: 9px 10px; font-size: 13px; line-height: 1.5; outline: none; color: var(--text); }
.rt-editor:focus { box-shadow: inset 0 0 0 2px rgba(30,58,95,0.15); }
.rt-editor ul, .rt-editor ol { margin: 4px 0; padding-left: 22px; }
.rt-editor p { margin: 0 0 6px; }
/* R276: page-break marker (toolbar ⤓ Page break button inserts an <hr>) —
   dashed divider with a centred label so it reads as "new PDF page here". */
.rt-editor hr {
  border: none; border-top: 2px dashed var(--border);
  margin: 14px 0; position: relative; overflow: visible;
}
.rt-editor hr::after {
  content: 'Page break';
  position: absolute; top: -9px; left: 50%; transform: translateX(-50%);
  background: var(--card); padding: 0 8px;
  font-size: 11px; color: var(--text-muted); white-space: nowrap;
}
/* R277: "Default text colour" swatch. #4a596d is the PDF ink colour, so
   text set with it prints exactly like unstyled text; on screen we force it
   to the theme text colour (!important beats the inline colour) so it reads
   as plain text in both light and dark themes. rgb(74, 89, 109) covers the
   browser's normalised inline-style form.
   R278 (Piotr): selectors made GLOBAL (were .rt-editor-scoped) — Notes and
   Tasks display the saved rich HTML outside an editor, where the literal
   #4a596d was showing (too dark on the dark theme). No app UI uses #4a596d
   as an inline text colour, so the global override is safe. */
.rt-sw-def::after { content: 'A'; color: #fff; font-size: 11px; font-weight: 700; line-height: 1; display: block; }
font[color="#4a596d" i],
span[style*="#4a596d" i],
span[style*="rgb(74, 89, 109)"] { color: var(--text) !important; }

/* ---- In-app file preview (Files page + share portal) ---- */
/* Intentionally dark in both themes — a neutral backdrop for viewing files. */
.fviewer-overlay {
  position: fixed; inset: 0; z-index: 4000;
  background: #1c1c1f; display: flex; flex-direction: column;
}
.fviewer-bar {
  flex: 0 0 auto; display: flex; align-items: center; gap: 12px;
  padding: calc(10px + env(safe-area-inset-top, 0px)) 14px 10px;
  background: #11161d; color: #fff; box-shadow: 0 2px 8px rgba(0,0,0,0.4);
}
.fviewer-close {
  background: rgba(255,255,255,0.14); color: #fff; border: none;
  border-radius: var(--radius-md); padding: 9px 16px; font-size: 15px; font-weight: 600;
  cursor: pointer; line-height: 1; white-space: nowrap;
}
.fviewer-close:hover { background: rgba(255,255,255,0.26); }
.fviewer-name {
  flex: 1 1 auto; font-size: 14px; opacity: 0.9;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.fviewer-dl {
  flex: 0 0 auto; color: #fff; text-decoration: none;
  background: rgba(255,255,255,0.14); border-radius: var(--radius-md);
  padding: 9px 14px; font-size: 14px; white-space: nowrap;
}
.fviewer-dl:hover { background: rgba(255,255,255,0.26); }
.fviewer-body {
  flex: 1 1 auto; overflow: auto; -webkit-overflow-scrolling: touch;
  display: block;
}
.fviewer-img { max-width: 100%; height: auto; margin: 0 auto; display: block; }
.fviewer-open {
  flex: 0 0 auto; color: #fff; background: rgba(255,255,255,0.14); border: none;
  border-radius: var(--radius-md); padding: 9px 14px; font-size: 14px; font-weight: 600;
  white-space: nowrap; cursor: pointer; line-height: 1;
}
.fviewer-open:hover { background: rgba(255,255,255,0.26); }
.fviewer-frame { width: 100%; height: 100%; border: none; background: #fff; }
@media (max-width: 720px) {
  .fviewer-dl { padding: 9px 12px; }
  .fviewer-name { font-size: 13px; }
}

/* ===========================================================================
   MOBILE COMPONENT LIBRARY (Build Plan Phase 2) — class prefix .m-
   Used by the sub-1000px screens; all colours via the theme variables so
   light + dark both work. Tap targets >=44px. Focus always visible.
   =========================================================================== */

.m-lock-scroll { overflow: hidden; }

/* Shared focus visibility for every library control */
.m-chip:focus-visible, .m-card:focus-visible, .m-tab:focus-visible,
.m-select-btn:focus-visible, .m-select-opt:focus-visible, .m-select-filter:focus-visible,
.m-num button:focus-visible, .m-actionbar-more:focus-visible, .m-menu-item:focus-visible,
.m-topbar-back:focus-visible, .m-detail-back:focus-visible, .m-summary-card:focus-visible {
  outline: 3px solid var(--accent); outline-offset: 1px;
}

/* ---- TopBar ---- */
.m-topbar { position: sticky; top: 0; z-index: 40; background: var(--card);
  border-bottom: 1px solid var(--border); box-shadow: var(--shadow-sm); }
.m-topbar-row { display: flex; align-items: center; gap: 10px; padding: 8px 12px; min-height: 52px; }
.m-topbar-row2 { display: flex; align-items: center; gap: 8px; padding: 0 12px 10px; flex-wrap: wrap; }
.m-topbar-back { display: flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px; font-size: 26px; color: var(--heading);
  text-decoration: none; border-radius: var(--radius-md); }
.m-topbar-back:hover { background: var(--row-hover); text-decoration: none; }
.m-topbar-spacer { min-width: 44px; }   /* keeps the title clear of the fixed hamburger */
.m-topbar-title { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 8px;
  font-size: 16px; color: var(--heading); overflow: hidden; }
.m-topbar-title strong { white-space: nowrap; }
.m-topbar-title span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---- Status pill (text + colour, never colour-only) ---- */
.m-pill { background: var(--pill, var(--text-muted)); color: #fff; padding: 2px 10px;
  border-radius: var(--radius-pill); font-size: var(--fs-xs); font-weight: var(--fw-medium); white-space: nowrap; }

/* VC-248 P2 — the ONE Badge component. Six semantic variants, single
   size/weight/radius, tinted bg + dark text pairs that pass WCAG AA in both
   themes (token pairs flip with the theme). Applies to .m-pill too when a
   variant class is given, so mobile cards share the exact same look. */
.badge { display: inline-block; padding: 2px 10px; border-radius: var(--radius-pill);
  font-size: var(--fs-xs); font-weight: var(--fw-medium); line-height: 1.6; white-space: nowrap; }
.badge.b-success, .m-pill.b-success { background: var(--ok-bg);     color: var(--ok-fg); }
.badge.b-danger,  .m-pill.b-danger  { background: var(--err-bg);    color: var(--err-fg); }
.badge.b-warning, .m-pill.b-warning { background: var(--warn-bg);   color: var(--warn-fg); }
.badge.b-info,    .m-pill.b-info    { background: var(--info-bg);   color: var(--info-fg); }
.badge.b-purple,  .m-pill.b-purple  { background: var(--purple-bg); color: var(--purple-fg); }
.badge.b-neutral, .m-pill.b-neutral { background: var(--mut-bg);    color: var(--mut-fg); }
/* Filled navy = "active / current" per the uniform-highlight house rule. */
.badge.b-accent,  .m-pill.b-accent  { background: var(--navy); color: #fff; }

/* ---- SummaryStrip ---- */
.m-summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px; padding: 12px; }
@media (max-width: 699px) { .m-summary { grid-template-columns: 1fr; } }
.m-summary-card { display: block; background: var(--card); border: 1px solid var(--border);
  border-left: 4px solid var(--navy); border-radius: var(--radius-md); padding: 10px 14px;
  text-decoration: none; color: inherit; min-height: 44px; }
.m-summary-card:hover { text-decoration: none; }
a.m-summary-card:hover { background: var(--row-hover); }
.m-summary-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted); }
.m-summary-value { font-size: 22px; font-weight: 700; color: var(--heading); }
.m-summary-sub { font-size: 12px; color: var(--text-muted); }
.m-summary-warn   { border-left-color: var(--warning); }
.m-summary-danger { border-left-color: var(--danger); }
.m-summary-danger .m-summary-value { color: var(--danger); }
.m-summary-ok     { border-left-color: var(--success); }

/* ---- FilterChips (the one deliberate horizontal scroller) ---- */
/* INV-UX P1 (09/07): contained scroll — max-width stops the strip poking past
   the viewport; the ::after spacer gives the last chip breathing room; the
   right-edge mask fade signals "more chips this way" (it lands on the spacer,
   not the chip, once fully scrolled). */
.m-chips { display: flex; gap: 8px; padding: 8px 12px; overflow-x: auto;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
  max-width: 100%; box-sizing: border-box;
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 20px), transparent);
  mask-image: linear-gradient(90deg, #000 calc(100% - 20px), transparent); }
.m-chips::after { content: ''; flex: 0 0 20px; }
.m-chips::-webkit-scrollbar { display: none; }
.m-chip { flex: 0 0 auto; min-height: 44px; padding: 8px 16px; border-radius: var(--radius-pill);
  border: 1px solid var(--border); background: var(--card); color: var(--text);
  font-size: 14px; cursor: pointer; white-space: nowrap; }
.m-chip.active { background: var(--navy); border-color: var(--navy); color: #fff; font-weight: 600; }
.m-chip-count { display: inline-block; margin-left: 4px; padding: 1px 8px; border-radius: var(--radius-lg);
  background: rgba(127,127,127,0.18); font-size: 12px; }
.m-chip.active .m-chip-count { background: rgba(255,255,255,0.25); }

/* ---- ListCard ---- */
.m-cardlist { display: flex; flex-direction: column; gap: 8px; padding: 0 12px 12px; }
.m-card { display: flex; align-items: stretch; gap: 0; width: 100%; text-align: left;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: 0; cursor: pointer; color: var(--text); font: inherit; min-height: 60px;
  overflow: hidden; }
.m-card:hover { background: var(--row-hover); }
.m-card-cat { flex: 0 0 6px; }
.m-card-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; padding: 10px 14px; }
.m-card-top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.m-card-primary { flex: 1; min-width: 0; font-size: 15px; font-weight: 600; color: var(--heading);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.m-card-value { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 15px;
  color: var(--heading); white-space: nowrap; margin-left: auto; }
.m-card-value.m-danger { color: var(--danger); }
.m-card-secondary { font-size: 13px; color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---- DetailView ---- */
.m-detail { position: fixed; inset: 0; z-index: 1500; background: var(--bg);
  display: flex; flex-direction: column; }
.m-detail-top { flex: 0 0 auto; display: flex; align-items: center; gap: 8px;
  background: var(--card); border-bottom: 1px solid var(--border);
  padding: calc(6px + env(safe-area-inset-top, 0px)) 10px 6px; min-height: 52px; }
.m-detail-back { min-width: 44px; min-height: 44px; border: 0; background: transparent;
  font-size: 26px; color: var(--heading); cursor: pointer; border-radius: var(--radius-md); }
.m-detail-back:hover { background: var(--row-hover); }
.m-detail-title { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px;
  font-size: 16px; font-weight: 600; color: var(--heading); overflow: hidden; }
.m-detail-body { flex: 1; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch;
  padding-bottom: 90px; /* clearance for the sticky action bar */ }

.m-section { margin: 12px; background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-lg); overflow: hidden; }
.m-section-label { margin: 0; padding: 10px 14px 8px; font-size: 12px; font-weight: 700;
  color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.6px;
  border-bottom: 1px solid var(--border); background: var(--surface-2); }
.m-section-body { padding: 12px 14px; }

/* Read-first key/value rows used in Details sections */
.m-kv { display: flex; gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--border); font-size: 14px; }
.m-kv:last-child { border-bottom: 0; }
.m-kv-k { flex: 0 0 38%; color: var(--text-muted); }
.m-kv-v { flex: 1; min-width: 0; color: var(--text); overflow-wrap: anywhere; }

/* ---- SearchableSelect ---- */
.m-select { position: relative; display: grid; gap: 4px; }
.m-select-btn { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 44px;
  padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--card); color: var(--text); font-size: 16px; cursor: pointer; text-align: left; }
.m-select-btn[disabled] { opacity: 0.6; cursor: default; }
.m-select-current { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.m-select-empty { color: var(--text-muted); }
.m-select-arrow { color: var(--text-muted); }
.m-select-pop { position: absolute; top: 100%; left: 0; right: 0; z-index: 60;
  margin-top: 4px; background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-md); box-shadow: 0 8px 30px rgba(0,0,0,0.25); overflow: hidden; }
.m-select-filter { width: 100%; box-sizing: border-box; padding: 10px 12px; border: 0;
  border-bottom: 1px solid var(--border); background: var(--card); color: var(--text);
  font-size: 16px; outline: none; min-height: 44px; }
.m-select-list { max-height: 240px; overflow-y: auto; }
.m-select-opt { display: block; width: 100%; text-align: left; padding: 11px 14px;
  border: 0; background: transparent; color: var(--text); font-size: 15px;
  cursor: pointer; min-height: 44px; }
.m-select-opt:hover, .m-select-opt.hi { background: var(--row-hover); }
.m-select-opt[aria-selected="true"] { font-weight: 700; color: var(--heading); }
.m-select-none { padding: 12px 14px; color: var(--text-muted); font-size: 13px; }

/* ---- BottomSheet ---- */
.m-sheet-backdrop { position: fixed; inset: 0; z-index: 1600; background: rgba(0,0,0,0);
  transition: background 0.18s ease; display: flex; align-items: flex-end; }
.m-sheet-backdrop.open { background: rgba(0,0,0,0.45); }
.m-sheet { width: 100%; max-height: 92vh; background: var(--card);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0; display: flex; flex-direction: column;
  transform: translateY(100%); transition: transform 0.18s ease; touch-action: none; }
.m-sheet-backdrop.open .m-sheet { transform: translateY(0); }
.m-sheet-grab { display: flex; justify-content: center; padding: 8px 0 2px; cursor: grab; }
.m-sheet-grab span { width: 42px; height: 4px; border-radius: var(--radius-sm); background: var(--border); }
.m-sheet-head { padding: 6px 16px 10px; font-size: 16px; font-weight: 700; color: var(--heading);
  border-bottom: 1px solid var(--border); }
.m-sheet-body { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 14px 16px; touch-action: pan-y; }
.m-sheet-foot { flex: 0 0 auto; display: flex; gap: 10px; justify-content: flex-end;
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--border); background: var(--card); }
.m-sheet-foot .btn { min-height: 44px; }

/* ---- StickyActionBar ---- */
.m-actionbar { position: sticky; bottom: 0; z-index: 45; display: flex; align-items: center;
  gap: 10px; padding: 10px 14px calc(10px + env(safe-area-inset-bottom, 0px));
  background: var(--card); border-top: 1px solid var(--border); }
.m-detail .m-actionbar { position: absolute; bottom: 0; left: 0; right: 0; }
.m-actionbar-spacer { flex: 1; }
.m-actionbar-primary { min-height: 44px; }
.m-actionbar-more { min-width: 44px; min-height: 44px; border: 1px solid var(--border);
  border-radius: var(--radius-md); background: var(--card); color: var(--heading); font-size: 20px;
  cursor: pointer; line-height: 1; }
.m-actionbar-menu { position: absolute; bottom: calc(100% + 6px); left: 10px; z-index: 70;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: 0 8px 30px rgba(0,0,0,0.3); min-width: 200px; overflow: hidden; padding: 4px; }
.m-menu-item { display: block; width: 100%; text-align: left; padding: 12px 14px;
  border: 0; background: transparent; color: var(--text); font-size: 15px;
  border-radius: var(--radius-md); cursor: pointer; min-height: 44px; }
.m-menu-item:hover { background: var(--row-hover); }
.m-menu-item.m-danger { color: var(--danger); }

/* ---- TabStrip ---- */
.m-tabs { display: flex; gap: 2px; overflow-x: auto; scrollbar-width: none;
  background: var(--card); border-bottom: 1px solid var(--border); padding: 0 8px; }
.m-tabs::-webkit-scrollbar { display: none; }
.m-tab { flex: 0 0 auto; min-height: 44px; padding: 10px 14px; border: 0;
  border-bottom: 3px solid transparent; background: transparent; color: var(--text-muted);
  font-size: 14px; font-weight: 600; cursor: pointer; white-space: nowrap; }
.m-tab.active { color: var(--heading); border-bottom-color: var(--accent); }
.m-tab-count { display: inline-block; margin-left: 3px; padding: 0 7px; border-radius: var(--radius-md);
  background: rgba(127,127,127,0.18); font-size: 11px; }

/* ---- Form fields ---- */
.m-field { display: grid; gap: 4px; margin-bottom: 12px; }
.m-label { font-size: 13px; font-weight: 600; color: var(--text); }
.m-req { color: var(--danger); }
.m-hint { font-size: 12px; color: var(--text-muted); }
.m-field input:not([type=hidden]), .m-field select, .m-field textarea {
  font-size: 16px; padding: 10px 12px; border: 1px solid var(--border);
  border-radius: var(--radius-md); background: var(--card); color: var(--text); min-height: 44px; box-sizing: border-box; }

.m-num { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.m-num input { width: 90px; text-align: center; font-size: 16px; min-height: 44px;
  padding: 8px; border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--card); color: var(--text); }
.m-num-dec, .m-num-inc { min-width: 44px; min-height: 44px; border: 1px solid var(--border);
  border-radius: var(--radius-md); background: var(--surface-2); color: var(--heading);
  font-size: 20px; font-weight: 700; cursor: pointer; line-height: 1; }
.m-num-suffix { color: var(--text-muted); font-size: 14px; }
.m-num-quick { display: inline-flex; gap: 6px; margin-left: 4px; }
.m-num-q { min-width: 44px; min-height: 44px; border: 1px solid var(--border);
  border-radius: var(--radius-md); background: var(--card); color: var(--text); font-size: 15px; cursor: pointer; }
.m-num-q:hover { background: var(--row-hover); }

/* Floating add button (used by Phase 3 Planner) */
.m-fab { position: fixed; right: 16px; bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  z-index: 50; width: 56px; height: 56px; border-radius: 50%; border: 0;
  background: var(--navy); color: #fff; font-size: 28px; line-height: 1; cursor: pointer;
  box-shadow: 0 4px 14px rgba(0,0,0,0.35); }
.m-fab:hover { background: var(--navy-light); }
.m-fab:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

/* Sticky day sub-headers (Phase 3 agenda) */
.m-dayhead { position: sticky; top: 0; z-index: 30; display: flex; align-items: baseline; gap: 8px;
  padding: 8px 14px; background: var(--bg); border-bottom: 1px solid var(--border);
  font-size: 13px; font-weight: 700; color: var(--heading); }
.m-dayhead.today { color: var(--accent); }
.m-dayhead-count { margin-left: auto; font-weight: 400; color: var(--text-muted); font-size: 12px; }

/* ---- Phase 6: per-column filters + results count (desktop tables) ---- */
.table-results-count { font-size: 12px; color: var(--text-muted); padding: 6px 2px 4px; }
.colfilter-row td { padding: 3px 6px 6px; background: var(--surface-2); border-bottom: 1px solid var(--border); }
.colfilter { width: 100%; box-sizing: border-box; padding: 4px 8px; font-size: 12px;
  border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--card); color: var(--text); }
.colfilter::placeholder { color: var(--text-muted); }

/* ---- Phase 6: accessibility - visible keyboard focus everywhere ---- */
/* :focus-visible only (mouse clicks stay clean); state-level change, no
   layout impact at any width. The .m-* components carry their own rule. */
button:focus-visible, a:focus-visible, input:focus-visible, select:focus-visible,
textarea:focus-visible, [tabindex]:focus-visible, [contenteditable]:focus-visible {
  outline: 3px solid var(--accent); outline-offset: 1px;
}
