/* YLB design system: one hand-written stylesheet (§5.1, §9.3).
   1. Tokens   2. Base   3. Layout   4. Components   5. Field   6. Utilities   7. Computers
   8. Style guide
   Rules: use tokens, never raw values, in components; no inline styles (CSP §8.4);
   status is text + icon + colour, never colour alone; touch targets ≥ 44px; WCAG 2.2 AA.
   Reference: docs/design-system.md. Live catalogue: /styleguide (development). */

/* ===== 1. Tokens ===================================================== */
:root {
  color-scheme: light;

  /* Palette (raw). Components use the semantic tokens below, never these directly. */
  --blue-50: #eef5fc; --blue-100: #d6e7f7; --blue-600: #1f5f99; --blue-700: #184c7b; --blue-800: #123a5e;
  --gray-0: #ffffff; --gray-50: #f6f7f9; --gray-100: #eceef2; --gray-200: #dde1e7; --gray-300: #c3c9d2;
  --gray-500: #6b7380; --gray-600: #545b67; --gray-700: #3d434d; --gray-900: #1b1f25;
  --amber-400: #f2b01e;

  /* Surfaces and text */
  --color-bg: var(--gray-50);
  --color-surface: var(--gray-0);
  --color-surface-sunken: var(--gray-100);
  --color-surface-raised: var(--gray-0);
  --color-border: var(--gray-200);
  --color-border-strong: var(--gray-300);
  --color-text: var(--gray-900);
  --color-text-muted: var(--gray-600);        /* 7.0:1 on surface */
  --color-text-inverse: var(--gray-0);
  --color-overlay: rgb(15 20 26 / 0.55);

  /* Brand and interaction */
  --color-primary: var(--blue-600);            /* 6.9:1 with white text */
  --color-primary-hover: var(--blue-700);
  --color-primary-active: var(--blue-800);
  --color-primary-soft: var(--blue-50);
  --color-primary-contrast: var(--gray-0);
  --color-link: var(--blue-600);
  --color-focus: var(--blue-600);
  --color-focus-halo: var(--amber-400);        /* visible on photos and dark bars */
  --color-accent: var(--amber-400);            /* brand stripe only; never text */

  /* Tones: every status chip, alert and toast picks one. fg on bg ≥ 4.5:1. */
  --tone-neutral-fg: #3d434d; --tone-neutral-bg: #eceef2; --tone-neutral-border: #c3c9d2;
  --tone-info-fg: #123f73;    --tone-info-bg: #dcebfb;    --tone-info-border: #9cc3ec;
  --tone-success-fg: #145128; --tone-success-bg: #dcf3e2; --tone-success-border: #93d1a6;
  --tone-warning-fg: #6b3d00; --tone-warning-bg: #fdf0cf; --tone-warning-border: #ebc66d;
  --tone-danger-fg: #8a1c1c;  --tone-danger-bg: #fde2e0;  --tone-danger-border: #efa29c;
  --tone-local-fg: #4a2a8c;   --tone-local-bg: #ece6fb;   --tone-local-border: #bcaaf0; /* on this phone, not sent */
  --color-danger: #b42318;     /* solid danger button: 5.9:1 with white */
  --color-danger-hover: #912018;

  /* Typography: system stack, no web fonts (budget §9.4). */
  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;
  --text-xs: 0.75rem;   /* 12 */
  --text-sm: 0.875rem;  /* 14 */
  --text-md: 1rem;      /* 16: body; inputs never smaller (prevents iOS zoom) */
  --text-lg: 1.125rem;  /* 18 */
  --text-xl: 1.375rem;  /* 22 */
  --text-2xl: 1.75rem;  /* 28 */
  --leading-tight: 1.25;
  --leading-normal: 1.5;
  --weight-regular: 400; --weight-medium: 500; --weight-semibold: 600; --weight-bold: 700;

  /* Space: 4px base */
  --space-1: 0.25rem; --space-2: 0.5rem; --space-3: 0.75rem; --space-4: 1rem; --space-5: 1.25rem;
  --space-6: 1.5rem; --space-8: 2rem; --space-10: 2.5rem; --space-12: 3rem; --space-16: 4rem;

  /* Shape, depth, motion, layering */
  --radius-sm: 4px; --radius-md: 8px; --radius-lg: 12px; --radius-full: 999px;
  --border-width: 1px;
  --shadow-1: 0 1px 2px rgb(16 24 40 / 0.06), 0 1px 3px rgb(16 24 40 / 0.08);
  --shadow-2: 0 4px 8px -2px rgb(16 24 40 / 0.10), 0 2px 4px -2px rgb(16 24 40 / 0.06);
  --shadow-3: 0 12px 24px -6px rgb(16 24 40 / 0.18);
  --duration-fast: 120ms; --duration-normal: 200ms; --ease: cubic-bezier(0.2, 0, 0, 1);
  --z-header: 10; --z-dropdown: 20; --z-dialog: 30; --z-toast: 40; --z-progress: 50;

  /* Sizing */
  --touch-target: 44px;   /* minimum for anything tappable (§9.3) */
  --tap-large: 56px;      /* field status taps: gloves, sun, one hand */
  --icon-sm: 16px; --icon-md: 20px; --icon-lg: 24px;
  --container: 72rem; --container-narrow: 40rem;
  --sidebar-width: 14rem; --rail-width: 3.5rem; --form-width: 48rem;  /* computers (section 7) */
  --header-height: 56px;
  --progress-height: 3px;   /* the loading bar: over the brand stripe at the top */
  --progress-delay: 200ms;  /* shorter than this, a click feels instant and the bar never shows */
  --gantt-row: 32px; --gantt-header: 40px;  /* ui.timeline's rows: platform/web/timeline.py ROW and HEADER (tested) */
}
/* Breakpoints (CSS variables cannot be used in media queries; keep these in sync):
   sm 40em (640px) · md 48em (768px) · lg 64em (1024px). */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --color-bg: #0f1419; --color-surface: #161c23; --color-surface-sunken: #11161c; --color-surface-raised: #1d252e;
    --color-border: #2a333d; --color-border-strong: #3a4552;
    --color-text: #e7ecf1; --color-text-muted: #a3aebb; --color-text-inverse: #0f1419;
    --color-overlay: rgb(0 0 0 / 0.65);
    --color-primary: #6aa8e6; --color-primary-hover: #8bbcee; --color-primary-active: #a9cdf2;
    --color-primary-soft: #16283b; --color-primary-contrast: #0b1724; --color-link: #8bbcee;
    --color-focus: #8bbcee;
    --tone-neutral-fg: #d3d9e0; --tone-neutral-bg: #232b34; --tone-neutral-border: #3a4552;
    --tone-info-fg: #b9d7f6;    --tone-info-bg: #142a42;    --tone-info-border: #2c5480;
    --tone-success-fg: #a8e3b8; --tone-success-bg: #12301d; --tone-success-border: #2a6a3e;
    --tone-warning-fg: #f6d68a; --tone-warning-bg: #352808; --tone-warning-border: #7a5a12;
    --tone-danger-fg: #f6b4ae;  --tone-danger-bg: #3a1514;  --tone-danger-border: #8a3530;
    --tone-local-fg: #d2c5f7;   --tone-local-bg: #261d42;   --tone-local-border: #5b479b;
    /* Solid danger button and badge, white text: 5.4:1 and 6.7:1 (#e5544a was 4.3:1, under AA: DR-054). */
    --color-danger: #c0392b; --color-danger-hover: #a8321f;
    --shadow-1: 0 1px 2px rgb(0 0 0 / 0.4); --shadow-2: 0 4px 10px rgb(0 0 0 / 0.45); --shadow-3: 0 12px 28px rgb(0 0 0 / 0.55);
  }
}
:root[data-theme="dark"] { color-scheme: dark; }

/* ===== 2. Base ======================================================= */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
  margin: 0; min-height: 100vh; background: var(--color-bg); color: var(--color-text);
  font: var(--weight-regular) var(--text-md)/var(--leading-normal) var(--font-sans);
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4 { margin: 0 0 var(--space-3); line-height: var(--leading-tight); font-weight: var(--weight-semibold); }
h1 { font-size: var(--text-2xl); } h2 { font-size: var(--text-xl); } h3 { font-size: var(--text-lg); } h4 { font-size: var(--text-md); }
p { margin: 0 0 var(--space-4); }
a { color: var(--color-link); text-underline-offset: 2px; }
a:hover { text-decoration-thickness: 2px; }
img, svg, video { max-width: 100%; height: auto; }
code, kbd { font-family: var(--font-mono); font-size: 0.9em; }
hr { border: 0; border-top: var(--border-width) solid var(--color-border); margin: var(--space-6) 0; }
:focus-visible { outline: 3px solid var(--color-focus); outline-offset: 2px; border-radius: var(--radius-sm); }
::selection { background: var(--color-primary-soft); }
[hidden] { display: none !important; }
[id] { scroll-margin-top: calc(var(--header-height) + var(--space-4)); } /* anchors clear the sticky header */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
}

.icon {
  width: var(--icon-md); height: var(--icon-md); flex: none; vertical-align: middle;
  fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  pointer-events: none;  /* the pointer is on the link or button around it: a hover over an icon-only link
                            counts as one (fetching ahead, DR-051), and a click's target is never the icon */
}
.icon--sm { width: var(--icon-sm); height: var(--icon-sm); }
.icon--lg { width: var(--icon-lg); height: var(--icon-lg); }

.visually-hidden {  /* every property wins: a component's own width or padding must never make it visible */
  position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important;
  margin: -1px !important; overflow: hidden !important; clip: rect(0 0 0 0) !important;
  white-space: nowrap !important; border: 0 !important;
}
.skip-link { position: absolute; left: var(--space-2); top: -100px; z-index: var(--z-toast);
  padding: var(--space-2) var(--space-4); background: var(--color-surface); border-radius: var(--radius-md); }
.skip-link:focus { top: var(--space-2); }

/* ===== 3. Layout ===================================================== */
.app-header {
  position: sticky; top: 0; z-index: var(--z-header);
  background: var(--color-surface); border-bottom: var(--border-width) solid var(--color-border);
  box-shadow: inset 0 3px 0 var(--color-accent);
}
.app-header__inner {
  display: flex; align-items: center; gap: var(--space-3);
  max-width: var(--container); margin: 0 auto; padding: 0 var(--space-4); min-height: var(--header-height);
}
.brand { display: inline-flex; align-items: center; gap: var(--space-2); color: var(--color-text);
  font-weight: var(--weight-bold); text-decoration: none; min-height: var(--touch-target); }
.brand__mark { display: grid; place-items: center; width: 32px; height: 32px; border-radius: var(--radius-md);
  background: var(--color-primary); color: var(--color-primary-contrast); font-size: var(--text-sm); }
.app-header__actions { margin-left: auto; display: flex; align-items: center; gap: var(--space-1); }

.nav { display: none; }
.btn[data-nav-toggle] { display: none; }  /* the Menu button expands the computer's rail (section 7) */
.nav__list { display: flex; gap: var(--space-1); margin: 0; padding: 0; list-style: none; }
.nav__link {
  display: inline-flex; align-items: center; gap: var(--space-2); min-height: var(--touch-target);
  padding: 0 var(--space-3); border-radius: var(--radius-md); color: var(--color-text-muted);
  font-weight: var(--weight-medium); text-decoration: none;
}
.nav__link:hover { background: var(--color-surface-sunken); color: var(--color-text); }
.nav__link[aria-current="page"] { color: var(--color-primary); background: var(--color-primary-soft); }
.nav__link.is-pending { color: var(--color-primary); background: var(--color-primary-soft); }  /* clicked: current at once */
.sidebar:has(.is-pending) .nav__link[aria-current="page"]:not(.is-pending),
.tabbar:has(.is-pending) .nav__link[aria-current="page"]:not(.is-pending) { color: var(--color-text-muted); background: none; }
/* Phones: bottom tab bar with the first items; desktop: inline in the header. */
.tabbar {
  position: fixed; inset: auto 0 0 0; z-index: var(--z-header); display: flex;
  background: var(--color-surface); border-top: var(--border-width) solid var(--color-border);
  padding-bottom: env(safe-area-inset-bottom);
}
.tabbar .nav__list { width: 100%; gap: 0; }
.tabbar .nav__item { flex: 1; display: flex; }
.tabbar .nav__link { flex: 1; flex-direction: column; gap: 2px; justify-content: center; padding: var(--space-1);
  font-size: var(--text-xs); border-radius: 0; min-height: var(--tap-large); }
.has-tabbar .app-main { padding-bottom: calc(var(--tap-large) + var(--space-6)); }
@media (min-width: 64em) {
  .nav { display: block; }
  .tabbar { display: none; }
  .has-tabbar .app-main { padding-bottom: var(--space-8); }
}

.app-main { max-width: var(--container); margin: 0 auto; padding: var(--space-4) var(--space-4) var(--space-8); }
.app-main--narrow { max-width: var(--container-narrow); }
@media (min-width: 48em) { .app-main { padding: var(--space-6) var(--space-6) var(--space-10); } }

.page-header { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: var(--space-3); margin-bottom: var(--space-5); }
.page-header__title { margin: 0; }
.page-header__meta { color: var(--color-text-muted); font-size: var(--text-sm); margin: var(--space-1) 0 0; }
.page-header__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }

.breadcrumbs { font-size: var(--text-sm); margin-bottom: var(--space-2); }
.breadcrumbs ol { display: flex; flex-wrap: wrap; gap: var(--space-1); margin: 0; padding: 0; list-style: none; }
.breadcrumbs li + li::before { content: "/"; margin-right: var(--space-1); color: var(--color-text-muted); }
.breadcrumbs a { color: var(--color-text-muted); }

.stack { display: flex; flex-direction: column; gap: var(--space-4); }
.stack--sm { gap: var(--space-2); } .stack--lg { gap: var(--space-8); }
.cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.cluster--between { justify-content: space-between; }
.grid { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fill, minmax(min(100%, 16rem), 1fr)); }
.grid--wide { grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); }  /* parts share the row */
.grid--aside { grid-template-columns: minmax(0, 1fr); }  /* a main part and a narrower one beside it on computers */
@media (min-width: 64em) { .grid--aside { grid-template-columns: minmax(0, 2fr) minmax(20rem, 1fr); } }
.section { margin-bottom: var(--space-8); }
.section__title { font-size: var(--text-lg); margin-bottom: var(--space-3); }
.home-menu { margin-top: var(--space-8); }  /* the office's home page: the menu's cards below the tabs */

/* ===== 4. Components ================================================= */

/* --- Card / widget --- */
.card { background: var(--color-surface); border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-1); }
.card__header { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  padding: var(--space-4) var(--space-4) 0; }
.card__title { margin: 0; font-size: var(--text-md); }
.card__body { padding: var(--space-4); }
.card__footer { padding: var(--space-3) var(--space-4); border-top: var(--border-width) solid var(--color-border);
  font-size: var(--text-sm); }
a.card { display: block; color: inherit; text-decoration: none; transition: border-color var(--duration-fast) var(--ease); }
a.card:hover { border-color: var(--color-border-strong); }

.stat { display: flex; flex-direction: column; gap: var(--space-1); }
.stat__value { font-size: var(--text-2xl); font-weight: var(--weight-bold); line-height: 1; font-variant-numeric: tabular-nums; }
.stat__label { color: var(--color-text-muted); font-size: var(--text-sm); }
.stat__note { font-size: var(--text-sm); font-weight: var(--weight-medium); }
.stat--warning .stat__note { color: var(--tone-warning-fg); }
.stat--danger .stat__note { color: var(--tone-danger-fg); }
.stat--warning .stat__value { color: var(--tone-warning-fg); }
.stat--danger .stat__value { color: var(--tone-danger-fg); }

/* --- Buttons --- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: var(--touch-target); padding: 0 var(--space-4); border: var(--border-width) solid transparent;
  border-radius: var(--radius-md); font: inherit; font-weight: var(--weight-semibold); line-height: 1;
  text-decoration: none; cursor: pointer; white-space: nowrap; user-select: none;
  transition: background-color var(--duration-fast) var(--ease), border-color var(--duration-fast) var(--ease);
}
.btn--primary { background: var(--color-primary); color: var(--color-primary-contrast); }
.btn--primary:hover { background: var(--color-primary-hover); }
.btn--primary:active { background: var(--color-primary-active); }
.btn--secondary { background: var(--color-surface); color: var(--color-text); border-color: var(--color-border-strong); }
.btn--secondary:hover { background: var(--color-surface-sunken); }
.btn--ghost { background: transparent; color: var(--color-link); }
.btn--ghost:hover { background: var(--color-primary-soft); }
.btn--danger { background: var(--color-danger); color: #fff; }
.btn--danger:hover { background: var(--color-danger-hover); }
.btn--sm { min-height: 36px; padding: 0 var(--space-3); font-size: var(--text-sm); }
.btn--lg { min-height: var(--tap-large); padding: 0 var(--space-6); font-size: var(--text-lg); }
.btn--block { display: flex; width: 100%; }
.btn--icon { padding: 0; width: var(--touch-target); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; }
/* .btn--sm stays a 44px target on touch screens */
@media (pointer: coarse) { .btn--sm { min-height: var(--touch-target); } }
.btn .spinner { display: none; }
.btn.htmx-request .spinner, .btn[aria-busy="true"] .spinner { display: inline-block; }
.btn:active:not([disabled]):not([aria-disabled="true"]) { transform: translateY(1px); }  /* the press is felt at once */
/* A plain form's button while its page is on its way (app.js, DR-051): the spinner takes the icon's place, so
   the button keeps its size; a button without an icon just shows the busy cursor (the loading bar says the rest). */
.btn.is-busy { cursor: progress; }
.btn.is-busy:has(.spinner ~ .icon) .spinner { display: inline-block; width: var(--icon-md); height: var(--icon-md); }
.btn.is-busy .spinner ~ .icon { display: none; }

/* --- Forms --- */
.form { display: flex; flex-direction: column; gap: var(--space-5); }
.field { display: flex; flex-direction: column; gap: var(--space-1); }
.field__label { font-weight: var(--weight-semibold); }
.field__required { color: var(--tone-danger-fg); margin-left: 2px; }
.field__optional { color: var(--color-text-muted); font-weight: var(--weight-regular); font-size: var(--text-sm); }
.field__hint { color: var(--color-text-muted); font-size: var(--text-sm); margin: 0; }
.field__error { display: flex; align-items: flex-start; gap: var(--space-1); color: var(--tone-danger-fg);
  font-size: var(--text-sm); font-weight: var(--weight-medium); margin: 0; }
.input, .select, .textarea {
  width: 100%; min-height: var(--touch-target); padding: var(--space-2) var(--space-3);
  background: var(--color-surface); color: var(--color-text); font: inherit; font-size: var(--text-md);
  border: var(--border-width) solid var(--color-border-strong); border-radius: var(--radius-md);
}
.textarea { min-height: 6rem; resize: vertical; }
.select { appearance: none; padding-right: var(--space-8);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 18px center, right 13px center; background-size: 5px 5px; background-repeat: no-repeat; }
.input:hover, .select:hover, .textarea:hover { border-color: var(--color-text-muted); }
.input:focus-visible, .select:focus-visible, .textarea:focus-visible { outline: 3px solid var(--color-focus); outline-offset: 0; border-color: var(--color-focus); }
.input[aria-invalid="true"], .select[aria-invalid="true"], .textarea[aria-invalid="true"] { border-color: var(--tone-danger-fg); border-width: 2px; }
/* A long text box's limit (DR-055): said under it, counted down near it, and marked once over it (app.js). */
.field__count { margin: 0; color: var(--color-text-muted); font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.field__count--over { color: var(--tone-danger-fg); font-weight: var(--weight-semibold); }
.textarea.is-over { border-color: var(--tone-danger-fg); border-width: 2px; }
.input:disabled, .select:disabled, .textarea:disabled { background: var(--color-surface-sunken); color: var(--color-text-muted); }
.input--money { font-variant-numeric: tabular-nums; text-align: right; }
.choice { display: flex; align-items: flex-start; gap: var(--space-3); min-height: var(--touch-target); padding: var(--space-2) 0; cursor: pointer; }
.choice .field__hint { display: block; }
.choice input { width: 22px; height: 22px; margin: 1px 0 0; flex: none; accent-color: var(--color-primary); }
.pre-line { white-space: pre-line; }
.choices { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 13rem), 1fr)); column-gap: var(--space-4); }
fieldset.field { border: 0; padding: 0; margin: 0; }
fieldset.field legend { padding: 0; margin-bottom: var(--space-1); }
/* A form's section (fieldset.stack with a legend): the legend is its title over a rule, not a boxed frame. */
fieldset.stack { border: 0; padding: 0; margin: 0; min-width: 0; }
fieldset.stack > legend { width: 100%; padding: 0 0 var(--space-2); margin-bottom: var(--space-1);
  border-bottom: var(--border-width) solid var(--color-border); font-weight: var(--weight-semibold); }
.form__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); padding-top: var(--space-2); }
/* reveal_checkbox: the block shows while the box is ticked (or, --unchecked, while it isn't). Without :has the
   rule is dropped and the block stays visible, which still works. */
.reveal__body { padding-left: calc(22px + var(--space-3)); }
/* line_item: a form's repeated row (a quote's line); its top fields share a row, stacked on a phone. */
.line-item { display: grid; gap: var(--space-3); padding: var(--space-3); border: var(--border-width) solid var(--color-border); border-radius: var(--radius-md); }
.line-item__top { display: grid; gap: var(--space-3); align-items: end; grid-template-columns: minmax(0, 2fr) minmax(8rem, 1fr) auto; }
.line-item__top--stage { grid-template-columns: minmax(0, 1fr) minmax(9rem, auto) auto; }  /* a stage: name, kind, buttons */
@media (max-width: 40em) { .line-item__top { grid-template-columns: 1fr; } }
.reveal:not(.reveal--unchecked):has(> .choice .reveal__toggle:not(:checked)) > .reveal__body,
.reveal--unchecked:has(> .choice .reveal__toggle:checked) > .reveal__body { display: none; }
.error-summary { border-left: 4px solid var(--tone-danger-fg); }

/* --- Status chip --- */
.chip {
  display: inline-flex; align-items: center; gap: var(--space-1); padding: 2px var(--space-2) 2px 6px;
  border: var(--border-width) solid var(--tone-neutral-border); border-radius: var(--radius-full);
  background: var(--tone-neutral-bg); color: var(--tone-neutral-fg);
  font-size: var(--text-sm); font-weight: var(--weight-semibold); line-height: 1.4; white-space: nowrap;
}
.chip .icon { width: var(--icon-sm); height: var(--icon-sm); }
.tone-info    { --t-fg: var(--tone-info-fg);    --t-bg: var(--tone-info-bg);    --t-border: var(--tone-info-border); }
.tone-success { --t-fg: var(--tone-success-fg); --t-bg: var(--tone-success-bg); --t-border: var(--tone-success-border); }
.tone-warning { --t-fg: var(--tone-warning-fg); --t-bg: var(--tone-warning-bg); --t-border: var(--tone-warning-border); }
.tone-danger  { --t-fg: var(--tone-danger-fg);  --t-bg: var(--tone-danger-bg);  --t-border: var(--tone-danger-border); }
.tone-local   { --t-fg: var(--tone-local-fg);   --t-bg: var(--tone-local-bg);   --t-border: var(--tone-local-border); }
.tone-neutral { --t-fg: var(--tone-neutral-fg); --t-bg: var(--tone-neutral-bg); --t-border: var(--tone-neutral-border); }
.chip[class*="tone-"], .alert[class*="tone-"], .toast[class*="tone-"] { color: var(--t-fg); background: var(--t-bg); border-color: var(--t-border); }
.tone-local.chip { border-style: dashed; } /* "not sent yet" reads differently even without colour */
/* --- Field pages (§10) --- */
.field-update { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  margin-bottom: var(--space-4); padding: var(--space-3) var(--space-4); border-radius: var(--radius-md);
  background: var(--tone-info-bg); color: var(--tone-info-fg); border: var(--border-width) solid var(--tone-info-border); }
.field-expired { margin: 0 0 var(--space-4); padding: var(--space-3) var(--space-4); border-radius: var(--radius-md);
  background: var(--tone-warning-bg); color: var(--tone-warning-fg); border: var(--border-width) solid var(--tone-warning-border); }
.drawing { display: grid; gap: var(--space-4); }
.drawing__page { margin: 0; }
.drawing__page img { display: block; width: 100%; height: auto; background: var(--color-surface); border: var(--border-width) solid var(--color-border); border-radius: var(--radius-md); touch-action: pan-x pan-y pinch-zoom; }

.choice__input { width: 22px; height: 22px; margin: 2px 0 0; flex: none; accent-color: var(--color-primary); }

/* --- Comments (§6.6) --- */
.comment-list { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-3); }
.comment { padding: var(--space-3) var(--space-4); background: var(--color-surface); border: var(--border-width) solid var(--color-border); border-radius: var(--radius-md); }
.comment__meta { margin: 0 0 var(--space-1); font-size: var(--text-sm); color: var(--color-text-muted); }
.comment__meta strong { color: var(--color-text); }
.comment__body { margin: 0; white-space: pre-line; overflow-wrap: anywhere; }
.comment__body--removed { color: var(--color-text-muted); font-style: italic; }
.comment form { margin-top: var(--space-2); }
.bell { position: relative; }
.bell__count { position: absolute; top: 2px; right: 2px; line-height: 1; }
.bell__count:empty { display: none; }
.badge { display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: var(--radius-full); background: var(--color-danger); color: #fff;
  font-size: var(--text-xs); font-weight: var(--weight-bold); font-variant-numeric: tabular-nums; }

/* --- Alerts (inline messages) --- */
.alert { display: flex; gap: var(--space-3); align-items: flex-start; padding: var(--space-3) var(--space-4);
  border: var(--border-width) solid; border-radius: var(--radius-md); }
.alert > .icon { margin-top: 2px; }
.alert__title { font-weight: var(--weight-semibold); margin: 0 0 var(--space-1); }
.alert__body > :last-child { margin-bottom: 0; }
#page-messages:empty { display: none; }
#page-messages { margin-bottom: var(--space-4); }

/* --- Tables that become cards on phones --- */
.table-wrap { background: var(--color-surface); border: var(--border-width) solid var(--color-border); border-radius: var(--radius-lg); overflow-x: auto; }  /* a table wider than its place scrolls inside its box, never cut off */
.table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.table caption { text-align: left; padding: var(--space-3) var(--space-4); font-weight: var(--weight-semibold); }
.table th, .table td { padding: var(--space-3) var(--space-4); text-align: left; vertical-align: top; }
.table thead th { background: var(--color-surface-sunken); color: var(--color-text-muted); font-weight: var(--weight-semibold);
  font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.04em; }
.table tbody tr + tr td { border-top: var(--border-width) solid var(--color-border); }
.table tbody tr:hover { background: var(--color-surface-sunken); }
.table .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }  /* a long description never squeezes the amount */
.table a { font-weight: var(--weight-semibold); }
@media (max-width: 47.99em) {
  .table--cards thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .table--cards, .table--cards caption, .table--cards tbody, .table--cards tr, .table--cards td { display: block; width: 100%; }
  .table--cards tbody tr { padding: var(--space-3) var(--space-4); }
  .table--cards tbody tr + tr { border-top: var(--border-width) solid var(--color-border); }
  .table--cards tbody tr + tr td { border-top: 0; }
  .table--cards td { display: flex; justify-content: space-between; gap: var(--space-4); padding: var(--space-1) 0; text-align: right; }
  .table--cards td::before { content: attr(data-label); color: var(--color-text-muted); font-weight: var(--weight-medium); text-align: left; }
  .table--cards td[data-primary] { display: block; text-align: left; font-size: var(--text-md); padding-bottom: var(--space-2); }
  .table--cards td[data-primary]::before { content: none; }
}

/* --- Month calendar (plans, §13.5) --- */
.calendar-wrap { overflow-x: auto; background: var(--color-surface); border: var(--border-width) solid var(--color-border); border-radius: var(--radius-lg); }
.calendar { width: 100%; min-width: 42rem; border-collapse: collapse; table-layout: fixed; font-size: var(--text-sm); }
.calendar caption { text-align: left; padding: var(--space-3) var(--space-4); font-weight: var(--weight-semibold); }
.calendar thead th { background: var(--color-surface-sunken); color: var(--color-text-muted); font-size: var(--text-xs);
  font-weight: var(--weight-semibold); text-transform: uppercase; text-align: left; padding: var(--space-2); }
.calendar__day { vertical-align: top; height: 6.5rem; padding: var(--space-1) var(--space-2);
  border-top: var(--border-width) solid var(--color-border); border-left: var(--border-width) solid var(--color-border); }
.calendar__day:first-child { border-left: 0; }
.calendar__day--muted { color: var(--color-text-muted); background: var(--color-surface-sunken); }
.calendar__day--closed { background: repeating-linear-gradient(135deg, var(--color-surface-sunken) 0 6px, var(--color-surface) 6px 12px); }
.calendar__date { display: inline-block; min-width: 1.5rem; font-weight: var(--weight-semibold); }
.calendar__day--today .calendar__date { color: var(--color-primary-contrast); background: var(--color-primary); border-radius: var(--radius-full); text-align: center; }
.calendar__note { display: block; font-size: var(--text-xs); color: var(--color-text-muted); }
.calendar__entries { list-style: none; margin: var(--space-1) 0 0; padding: 0; display: grid; gap: 2px; }
.calendar__entry { font-size: var(--text-xs); padding: 1px var(--space-1); border-radius: var(--radius-sm); color: var(--t-fg);
  background: var(--t-bg); border: 1px solid var(--t-border); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.calendar__entry a { color: inherit; }

/* --- Before/after changes (activity log) --- */
.changes { margin-top: var(--space-2); border: var(--border-width) solid var(--color-border); border-radius: var(--radius-md); }
.changes th[scope="row"] { font-weight: var(--weight-medium); color: var(--color-text-muted); white-space: nowrap; }
.changes__before { color: var(--tone-danger-fg); text-decoration: line-through; text-decoration-thickness: 1px; }
.changes__after { color: var(--tone-success-fg); font-weight: var(--weight-medium); }
.changes td, .changes th { word-break: break-word; }
details.disclosure > summary { cursor: pointer; color: var(--color-link); font-size: var(--text-sm); min-height: var(--touch-target);
  display: inline-flex; align-items: center; }
.filters { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fill, minmax(min(100%, 11rem), 1fr)); align-items: end;
  padding: var(--space-4); background: var(--color-surface); border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-lg); margin-bottom: var(--space-4); }
.filters .field__label { font-size: var(--text-sm); }

/* --- Description list (record details) --- */
.details { display: grid; grid-template-columns: minmax(8rem, max-content) 1fr; gap: var(--space-2) var(--space-4); margin: 0; }
.details dt { color: var(--color-text-muted); font-size: var(--text-sm); }
.details dd { margin: 0; }
.details dt, .details dd { min-width: 0; overflow-wrap: anywhere; }  /* a long email address wraps */

/* --- Project header and tabs --- */
/* Phones: the number over the name, the status chip at the right, the meta below (section 7 puts it on one line). */
.project-header { margin-bottom: var(--space-4); }
.project-header__top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2); }
.project-header__number { display: block; font-family: var(--font-mono); font-size: var(--text-sm); color: var(--color-text-muted); }
.project-header__name { margin: 0; }
.project-header__meta { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); margin-top: var(--space-4);
  color: var(--color-text-muted); font-size: var(--text-sm); }
.project-header__meta span { display: inline-flex; align-items: center; gap: var(--space-1); }
.tabs { display: flex; gap: var(--space-1); overflow-x: auto; margin: 0 calc(-1 * var(--space-4)) var(--space-5);
  padding: 0 var(--space-4); border-bottom: var(--border-width) solid var(--color-border); scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tabs__link { display: inline-flex; align-items: center; min-height: var(--touch-target); padding: 0 var(--space-3);
  color: var(--color-text-muted); font-weight: var(--weight-medium); text-decoration: none; white-space: nowrap;
  border-bottom: 3px solid transparent; margin-bottom: -1px; }
.tabs__link:hover { color: var(--color-text); }
.tabs__link[aria-current="page"] { color: var(--color-primary); border-bottom-color: var(--color-primary); }
/* A tab just clicked looks current at once, before its page arrives (app.js adds .is-pending, DR-051). */
.tabs__link.is-pending { color: var(--color-primary); border-bottom-color: var(--color-primary); }
.tabs:has(.is-pending) .tabs__link[aria-current="page"]:not(.is-pending) { color: var(--color-text-muted); border-bottom-color: transparent; }
/* A strip wider than the screen shows that it scrolls (phones, DR-055): the end with tabs out of sight fades
   out (app.js sets data-more to "start", "end" or both, and brings the current tab into view). */
.tabs[data-more="end"] { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 3rem), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 3rem), transparent); }
.tabs[data-more="start"] { -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 3rem), transparent); mask-image: linear-gradient(to left, #000 calc(100% - 3rem), transparent); }
.tabs[data-more="start end"] { -webkit-mask-image: linear-gradient(to right, transparent, #000 3rem, #000 calc(100% - 3rem), transparent); mask-image: linear-gradient(to right, transparent, #000 3rem, #000 calc(100% - 3rem), transparent); }

/* --- Timeline: ui.timeline, a Gantt chart (DR-052) --- */
/* The names on the left are HTML (the text and the links), the chart beside them one SVG drawn by the server
   (platform/web/timeline.py), scrolling sideways. Both use --gantt-row, so each name sits beside its bar; the
   chart's colours are these classes, so it follows the theme. Status is also in each name's text and the tooltip. */
.gantt { display: grid; grid-template-columns: minmax(7.5rem, 16rem) minmax(0, 1fr); margin-bottom: var(--space-3);
  background: var(--color-surface); border: var(--border-width) solid var(--color-border); border-radius: var(--radius-lg); overflow: hidden; }
@media (max-width: 39.99em) { .gantt { grid-template-columns: minmax(6rem, 8.5rem) minmax(0, 1fr); } }
.gantt__labels { min-width: 0; margin: 0; padding: 0; list-style: none; border-right: var(--border-width) solid var(--color-border); }
.gantt__head, .gantt__label { display: flex; align-items: center; min-width: 0; height: var(--gantt-row); padding: 0 var(--space-3); font-size: var(--text-sm); }
.gantt__head { height: var(--gantt-header); background: var(--color-surface-sunken); color: var(--color-text-muted);
  font-size: var(--text-xs); font-weight: var(--weight-semibold); text-transform: uppercase; letter-spacing: 0.04em; }
.gantt__label:nth-child(odd) { background: var(--color-surface-sunken); }
.gantt__label > :first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* On a phone a name wraps onto a second line inside its row (DR-055), so it still sits beside its bar. After the
   rules above: same specificity, so the later rule wins. */
@media (max-width: 39.99em) {
  .gantt__label { font-size: var(--text-xs); line-height: 1.2; }
  .gantt__label > :first-child { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
    white-space: normal; overflow-wrap: anywhere; }
}
.gantt__label--critical { box-shadow: inset 3px 0 0 var(--tone-danger-fg); }
.gantt__chart { min-width: 0; overflow-x: auto; overscroll-behavior-x: contain; }
.gantt__chart:focus-visible { outline-offset: -3px; }
.gantt__svg { display: block; max-width: none; }  /* its own size: the rows must stay beside their names */
.gantt__svg text { font-family: var(--font-sans); font-size: 11px; fill: var(--color-text-muted); }
.gantt__svg a { cursor: pointer; }
.gantt__header { fill: var(--color-surface-sunken); }
.gantt__month { font-weight: var(--weight-semibold); fill: var(--color-text); }
.gantt__row { fill: transparent; } .gantt__row--alt { fill: var(--color-surface-sunken); }
.gantt__line { stroke: var(--color-border); } .gantt__line--month { stroke: var(--color-border-strong); }
.gantt__hatch { fill: var(--color-border-strong); }
.gantt__bar { fill: var(--color-primary-soft); stroke: var(--color-primary); }
.gantt__svg a:hover .gantt__bar { stroke-width: 2; }
.gantt__done { fill: var(--color-primary); pointer-events: none; }
.gantt__bar--completed { fill: var(--tone-success-border); stroke: var(--tone-success-fg); }
.gantt__bar--fixed { fill: var(--tone-warning-bg); stroke: var(--tone-warning-fg); }
.gantt__bar--critical { fill: var(--tone-danger-bg); stroke: var(--tone-danger-fg); stroke-width: 1.5; }
.gantt__bar--fixed.gantt__bar--critical { fill: var(--tone-warning-bg); }  /* still a booking, outlined as critical */
.gantt__done--critical { fill: var(--tone-danger-fg); }
.gantt__bar--conflict { stroke: var(--tone-danger-fg); stroke-width: 2; stroke-dasharray: 3 2; }
.gantt__bar--milestone { fill: var(--color-text); stroke: none; }
.gantt__bar--milestone.gantt__bar--critical { fill: var(--tone-danger-fg); }
.gantt__baseline { fill: var(--color-text-muted); opacity: 0.55; }
.gantt__arrow { fill: none; stroke: var(--color-border-strong); stroke-width: 1.25; }
.gantt__arrow--critical { stroke: var(--tone-danger-fg); }
.gantt__arrowhead { fill: var(--color-border-strong); } .gantt__arrowhead--critical { fill: var(--tone-danger-fg); }
.gantt__today { stroke: var(--color-primary); stroke-width: 2; }
.gantt__svg .gantt__today-label { fill: var(--color-primary); font-weight: var(--weight-semibold); }
.gantt-legend { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); margin: 0 0 var(--space-2); padding: 0;
  list-style: none; font-size: var(--text-sm); color: var(--color-text-muted); }
.gantt-legend li { display: inline-flex; align-items: center; gap: var(--space-2); }
.gantt-swatch { width: 18px; height: 10px; border: var(--border-width) solid var(--color-primary); border-radius: 2px; background: var(--color-primary-soft); }
.gantt-swatch--progress { background: var(--color-primary); }
.gantt-swatch--completed { background: var(--tone-success-border); border-color: var(--tone-success-fg); }
.gantt-swatch--fixed { background: var(--tone-warning-bg); border-color: var(--tone-warning-fg); }
.gantt-swatch--critical { background: var(--tone-danger-bg); border-color: var(--tone-danger-fg); }
.gantt-swatch--milestone { width: 10px; height: 10px; border: 0; background: var(--color-text); transform: rotate(45deg); }
.gantt-swatch--baseline { height: 3px; border: 0; background: var(--color-text-muted); opacity: 0.55; }
.gantt-swatch--closed { border-color: var(--color-border); background: repeating-linear-gradient(135deg, var(--color-border-strong) 0 2px, transparent 2px 5px); }
.gantt-swatch--today { width: 2px; height: 14px; border: 0; background: var(--color-primary); }
/* What saving a change would do (the phase page's Preview, DR-052). */
.preview-moves { margin: 0; padding-left: var(--space-5); }
.preview-moves li + li { margin-top: var(--space-1); }

/* --- Empty, loading, error states --- */
.empty { text-align: center; padding: var(--space-10) var(--space-4); color: var(--color-text-muted); }
.empty > .icon { width: 40px; height: 40px; margin-bottom: var(--space-3); stroke-width: 1.5; }
.empty__title { color: var(--color-text); font-size: var(--text-lg); margin-bottom: var(--space-2); }
.empty .btn { margin-top: var(--space-2); }
.spinner { width: 18px; height: 18px; border-radius: 50%; border: 2px solid currentColor; border-right-color: transparent;
  animation: spin 0.7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.loading { display: flex; align-items: center; justify-content: center; gap: var(--space-2); padding: var(--space-6); color: var(--color-text-muted); }
/* The loading bar (DR-051): a thin line over the brand stripe at the top. Hidden for a click answered within
   --progress-delay; after that it runs towards the end, slowing as it goes, until the page or the answer arrives,
   then fills and fades (.progress--done, from where it got to: --progress-at, set by app.js). A transform and an
   opacity only, so it keeps moving while the page is busy; with reduced motion it simply appears and goes. */
.progress { position: fixed; z-index: var(--z-progress); top: 0; left: 0; width: 100%; height: var(--progress-height);
  background: var(--color-primary); transform-origin: 0 50%; transform: scaleX(0); opacity: 0; pointer-events: none;
  --progress-at: 0.5; }
.progress--running { animation: progress-run 10s cubic-bezier(0.1, 0.8, 0.2, 1) var(--progress-delay) forwards; }
.progress--done { animation: progress-done 420ms var(--ease) forwards; }
@keyframes progress-run { from { opacity: 1; transform: scaleX(0.08); } to { opacity: 1; transform: scaleX(0.94); } }
@keyframes progress-done { 0% { opacity: 1; transform: scaleX(var(--progress-at)); }
  55% { opacity: 1; transform: scaleX(1); } 100% { opacity: 0; transform: scaleX(1); } }
.htmx-indicator { opacity: 0; transition: opacity var(--duration-normal) var(--ease); }
.htmx-request .htmx-indicator, .htmx-request.htmx-indicator { opacity: 1; }
.skeleton { background: linear-gradient(90deg, var(--color-surface-sunken), var(--color-border), var(--color-surface-sunken));
  background-size: 200% 100%; animation: shimmer 1.4s ease infinite; border-radius: var(--radius-sm); min-height: 1em; }
@keyframes shimmer { to { background-position: -200% 0; } }

/* --- Toasts --- */
.toasts { position: fixed; z-index: var(--z-toast); left: var(--space-4); right: var(--space-4);
  bottom: calc(var(--tap-large) + var(--space-4) + env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: var(--space-2); pointer-events: none; }
@media (min-width: 48em) { .toasts { left: auto; bottom: var(--space-6); width: 24rem; } }
/* Never over the field pages' "Send now" (the pending bar sits just above the tab bar). */
body:has(.pending-bar:not([hidden])) .toasts { bottom: calc(2 * var(--tap-large) + var(--space-4) + env(safe-area-inset-bottom)); }
.toast { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4);
  border: var(--border-width) solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface-raised);
  box-shadow: var(--shadow-3); pointer-events: auto; animation: toast-in var(--duration-normal) var(--ease); }
.toast__message { flex: 1; font-weight: var(--weight-medium); }
@keyframes toast-in { from { transform: translateY(8px); opacity: 0; } }

/* --- Dialog (native <dialog>) --- */
.dialog { width: min(32rem, calc(100% - 2 * var(--space-4))); padding: 0; border: 0; border-radius: var(--radius-lg);
  background: var(--color-surface); color: var(--color-text); box-shadow: var(--shadow-3); }
.dialog::backdrop { background: var(--color-overlay); }
.dialog__body { padding: var(--space-6) var(--space-6) var(--space-4); }
.dialog__title { font-size: var(--text-lg); }
.dialog__actions { display: flex; flex-wrap: wrap-reverse; justify-content: flex-end; gap: var(--space-2);
  padding: var(--space-4) var(--space-6) var(--space-6); }
@media (max-width: 39.99em) { .dialog__actions .btn { flex: 1; } }

/* --- Menu (details/summary) --- */
.menu { position: relative; }
.menu > summary { list-style: none; } .menu > summary::-webkit-details-marker { display: none; }
.menu__panel { position: absolute; right: 0; top: calc(100% + var(--space-1)); z-index: var(--z-dropdown); min-width: 12rem;
  padding: var(--space-1); background: var(--color-surface-raised); border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-2); }
.menu__item { display: flex; align-items: center; gap: var(--space-2); width: 100%; min-height: var(--touch-target);
  padding: 0 var(--space-3); border: 0; background: none; color: var(--color-text); font: inherit; text-align: left;
  text-decoration: none; border-radius: var(--radius-sm); cursor: pointer; }
.menu__item:hover { background: var(--color-surface-sunken); }
.menu__item--danger { color: var(--tone-danger-fg); }

/* --- Files and photos --- */
.file-picker { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: 8rem; padding: var(--space-5); text-align: center; border: 2px dashed var(--color-border-strong);
  border-radius: var(--radius-lg); background: var(--color-surface); color: var(--color-text-muted); cursor: pointer; }
.file-picker:hover, .file-picker:focus-within { border-color: var(--color-primary); color: var(--color-text); }
.file-picker:focus-within { outline: 3px solid var(--color-focus); outline-offset: 2px; }
.file-picker input[type="file"] { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.file-picker__label { color: var(--color-link); font-weight: var(--weight-semibold); }
.photo-grid { display: grid; gap: var(--space-2); grid-template-columns: repeat(auto-fill, minmax(min(46%, 9rem), 1fr));
  margin: 0; padding: 0; list-style: none; }
.photo { position: relative; aspect-ratio: 1; overflow: hidden; border-radius: var(--radius-md); background: var(--color-surface-sunken); }
.photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo__placeholder { display: grid; place-items: center; width: 100%; height: 100%; color: var(--color-text-muted); }
.photo__placeholder .icon { width: 32px; height: 32px; stroke-width: 1.5; }
.photo .chip { position: absolute; left: var(--space-1); bottom: var(--space-1); max-width: calc(100% - var(--space-2));
  overflow: hidden; text-overflow: ellipsis; box-shadow: var(--shadow-1); }
.photo a { display: block; height: 100%; }
.file-thumb { width: 64px; height: 64px; object-fit: cover; border-radius: var(--radius-sm); flex: none; background: var(--color-surface-sunken); }
.file-row { display: flex; align-items: center; gap: var(--space-3); min-height: var(--touch-target); }
.file-row__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--weight-medium); }
.file-row__meta { color: var(--color-text-muted); font-size: var(--text-sm); }

/* --- Pagination --- */
.pagination { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-top: var(--space-4); }
.pagination__info { color: var(--color-text-muted); font-size: var(--text-sm); }
.load-more { display: flex; justify-content: center; margin-top: var(--space-4); }

/* --- Inbox / activity list --- */
.list { margin: 0; padding: 0; list-style: none; background: var(--color-surface); border: var(--border-width) solid var(--color-border); border-radius: var(--radius-lg); }
/* A row's text keeps at least 12rem: on a narrow screen its chips and buttons move to the next line instead of
   squeezing it, and a long name, address or checksum breaks rather than pushing the page sideways. */
.list__item { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: flex-start; padding: var(--space-3) var(--space-4); }
.list__item + .list__item { border-top: var(--border-width) solid var(--color-border); }
.list__main { flex: 1 1 12rem; min-width: 0; }
.list__title { font-weight: var(--weight-semibold); margin: 0; overflow-wrap: anywhere; }
.list__meta { color: var(--color-text-muted); font-size: var(--text-sm); margin: 0; overflow-wrap: anywhere; }
a.list__item { color: inherit; text-decoration: none; } a.list__item:hover { background: var(--color-surface-sunken); }

/* --- Sign-in and account pages --- */
.auth { display: flex; flex-direction: column; gap: var(--space-4); max-width: 26rem; margin: var(--space-6) auto 0; }
@media (min-width: 48em) { .auth { margin-top: var(--space-12); } }
.auth__card .card__body { padding: var(--space-6); }
.auth__alt { padding: 0 var(--space-2); color: var(--color-text-muted); font-size: var(--text-sm); }
.input--code { font-family: var(--font-mono); font-size: var(--text-xl); letter-spacing: 0.3em; text-align: center; }
.menu__meta { margin: 0; padding: var(--space-2) var(--space-3) var(--space-3); border-bottom: var(--border-width) solid var(--color-border);
  margin-bottom: var(--space-1); font-weight: var(--weight-semibold); line-height: var(--leading-tight); }
.menu__meta span { display: block; font-weight: var(--weight-regular); color: var(--color-text-muted); font-size: var(--text-sm); }
.menu > summary.btn--ghost { color: var(--color-text); }

/* ===== 5. Field (phone screens, §10) ================================= */
.connection { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm); font-weight: var(--weight-medium); }
.connection--offline { background: var(--tone-local-bg); color: var(--tone-local-fg); }
.saved-at { display: inline-flex; align-items: center; gap: var(--space-1); color: var(--color-text-muted); font-size: var(--text-sm); }
.task-card { padding: var(--space-4); }
.task-card__title { font-size: var(--text-lg); margin-bottom: var(--space-1); }
.task-card__meta { color: var(--color-text-muted); font-size: var(--text-sm); margin-bottom: var(--space-3); }
.status-taps { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-2); margin: 0; padding: 0; border: 0; }
@media (min-width: 40em) { .status-taps { grid-template-columns: repeat(4, 1fr); } }
.status-tap { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-1);
  min-height: var(--tap-large); padding: var(--space-2); border: 2px solid var(--color-border-strong); border-radius: var(--radius-md);
  background: var(--color-surface); color: var(--color-text); font: inherit; font-weight: var(--weight-semibold); cursor: pointer; }
.status-tap:hover { border-color: var(--color-text-muted); }
.status-tap[aria-pressed="true"] { color: var(--t-fg); background: var(--t-bg); border-color: var(--t-fg); }
/* A tick marks the chosen status, so the selection never depends on colour alone. */
.status-tap[aria-pressed="true"]::after { content: "✓"; position: absolute; top: 4px; right: 8px; font-size: var(--text-sm); }
.pending-bar { position: sticky; bottom: calc(var(--tap-large) + env(safe-area-inset-bottom)); display: flex; align-items: center;
  justify-content: space-between; gap: var(--space-2); padding: var(--space-2) var(--space-4);
  background: var(--tone-local-bg); color: var(--tone-local-fg); border-top: 1px dashed var(--tone-local-border); }

/* ===== 6. Utilities ================================================== */
.text-muted { color: var(--color-text-muted); }
.text-sm { font-size: var(--text-sm); }
.text-right { text-align: right; }
.num { font-variant-numeric: tabular-nums; }
.mono { font-family: var(--font-mono); }
.m-0 { margin: 0; } .mt-4 { margin-top: var(--space-4); } .mb-4 { margin-bottom: var(--space-4); }
.w-full { width: 100%; }

/* ===== 7. Computers ================================================== */
/* lg (64em) and wider: the menu is a rail of icons at the left, each link named by its title and by text only
   screen readers get; the header's Menu button expands it to the full sidebar, in sections, over the page
   (data-nav-toggle in app.js) until a click elsewhere, Escape or Menu again. The page uses the rest of the
   screen. With a mouse (pointer: fine) spacing is compact too; touch screens keep the 44px targets. Phones and
   tablets never see this section, so the field pages stay as they are. */
.sidebar__section + .sidebar__section { margin-top: var(--space-4); }
.sidebar__title { margin: 0 0 var(--space-1); padding: 0 var(--space-3); color: var(--color-text-muted);
  font-size: var(--text-xs); font-weight: var(--weight-semibold); text-transform: uppercase; letter-spacing: 0.04em; }
.sidebar__section .nav__list { flex-direction: column; gap: 2px; }
.sidebar__section .nav__link { display: flex; }
@media (min-width: 64em) {
  .app-header__inner { max-width: none; }
  /* The Menu button sits over the rail's icons: the same distance from the edge as they are. */
  .app-header__inner:has(> [data-nav-toggle]) { padding-left: calc((var(--rail-width) - var(--touch-target)) / 2); }
  .btn[data-nav-toggle] { display: inline-flex; }
  .app-body { display: flex; align-items: flex-start; }
  .sidebar { position: sticky; top: var(--header-height); flex: none; width: var(--rail-width);
    height: calc(100vh - var(--header-height)); overflow: hidden auto; padding: var(--space-2) var(--space-1);
    background: var(--color-surface); border-right: var(--border-width) solid var(--color-border); }
  /* The rail: icons centred, labels and section titles kept for screen readers, a line between sections. */
  .sidebar:not(.sidebar--open) .nav__link { width: var(--touch-target); margin: 0 auto; padding: 0; justify-content: center; }
  .sidebar:not(.sidebar--open) .nav__link > span, .sidebar:not(.sidebar--open) .sidebar__title {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .sidebar:not(.sidebar--open) .sidebar__section + .sidebar__section { margin-top: var(--space-2); padding-top: var(--space-2);
    border-top: var(--border-width) solid var(--color-border); }
  /* Expanded: the full width over the page, which keeps the rail's room and never moves (the negative margin
     takes the extra width out of the row). */
  .sidebar--open { width: var(--sidebar-width); margin-right: calc(var(--rail-width) - var(--sidebar-width));
    z-index: var(--z-dropdown); box-shadow: var(--shadow-3); }
  .app-main { flex: 1; min-width: 0; max-width: none; margin: 0; }
  .app-main--narrow { max-width: var(--container-narrow); margin: 0 auto; }
  .form { max-width: var(--form-width); }
  .card:has(> .card__body > .form:only-child) { max-width: calc(var(--form-width) + 2 * var(--space-4)); }
  /* Tabs stay in reach while a long tab scrolls: one row, sideways when it must, stuck under the header
     (below it in the stack, above the page). */
  .tabs { position: sticky; top: var(--header-height); z-index: calc(var(--z-header) - 1);
    margin: 0 calc(-1 * var(--space-6)) var(--space-5); padding: 0 var(--space-6); background: var(--color-surface); scrollbar-width: thin; }
  .home-menu { display: none; }  /* the sidebar is the menu; phones reach the cards through "More" */
}
/* Compact (DR-050): a computer with a mouse gets the dense scale: 14px body text on a 1.45 line, 13px small
   text, 32px controls (WCAG 2.2 asks for 24), 44px header, 6/10px corners, 18px icons; borders do the
   separating (a line under a card's header, no card shadow) so the padding can shrink; forms run at 12px
   between fields with 13px labels and 12px hints. Everything here is a token or a padding: no component
   changes shape, and a touch screen of any size keeps the 44px scale above. */
@media (min-width: 64em) and (pointer: fine) {
  :root {
    --touch-target: 32px; --header-height: 44px;
    --text-sm: 0.8125rem; --text-md: 0.875rem; --text-lg: 1rem; --text-xl: 1.125rem; --text-2xl: 1.375rem;
    --leading-normal: 1.45; --radius-md: 6px; --radius-lg: 10px; --icon-md: 18px; --icon-lg: 22px;
  }
  h1, h2, h3, h4 { margin-bottom: var(--space-2); }
  p { margin-bottom: var(--space-3); }
  hr { margin: var(--space-4) 0; }
  .app-header__inner { gap: var(--space-2); }
  .brand__mark { width: 28px; height: 28px; }
  .app-main { padding: var(--space-4) var(--space-5) var(--space-8); }
  .page-header { gap: var(--space-2); margin-bottom: var(--space-3); }
  .breadcrumbs { margin-bottom: var(--space-1); }
  .tabs { margin: 0 calc(-1 * var(--space-5)) var(--space-3); padding: 0 var(--space-5); }
  /* The project header on one line: number, name, status; then the meta as one line. */
  .project-header { margin-bottom: var(--space-2); }
  .project-header__top { justify-content: flex-start; align-items: baseline; gap: var(--space-1) var(--space-3); }
  .project-header__title { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-3); min-width: 0; }
  .project-header__number { display: inline; }
  .project-header__name { font-size: var(--text-xl); }
  .project-header__meta { margin-top: var(--space-1); }
  .section { margin-bottom: var(--space-4); }
  .section__title { margin-bottom: var(--space-2); }
  .stack:not(.stack--sm):not(.stack--lg) { gap: var(--space-3); }
  .stack--lg { gap: var(--space-6); }
  .grid { gap: var(--space-3); }
  /* Cards: flat, the header on its own line above a rule, 12px inside. */
  .card { box-shadow: none; }
  .card__header { padding: var(--space-2) var(--space-3); border-bottom: var(--border-width) solid var(--color-border); }
  .card__body { padding: var(--space-3); }
  .card__footer { padding: var(--space-2) var(--space-3); }
  /* Buttons and controls: 32px tall, less padding; icon buttons keep their square. */
  .btn:not(.btn--icon) { padding: 0 var(--space-3); }
  .btn--sm { min-height: 28px; padding: 0 var(--space-2); }
  .btn--lg { min-height: 40px; padding: 0 var(--space-5); font-size: var(--text-md); }
  /* Forms: 12px between fields, 13px labels, 12px hints and errors, 4/8px inside the inputs. */
  .form { gap: var(--space-3); }
  .field__label { font-size: var(--text-sm); }
  fieldset.stack > legend { font-size: var(--text-md); }  /* a section's title stays at body size */
  .field__optional, .field__hint, .field__error, .field__count { font-size: var(--text-xs); }
  .input, .select, .textarea { padding: var(--space-1) var(--space-2); }
  .select { padding-right: var(--space-6); background-position: right 14px center, right 9px center; }
  .textarea { min-height: 4.5rem; }
  .choice { min-height: 0; gap: var(--space-2); padding: var(--space-1) 0; }
  .choice input, .choice__input { width: 18px; height: 18px; }
  .reveal__body { padding-left: calc(18px + var(--space-2)); }
  .choices { column-gap: var(--space-3); }
  .form__actions { padding-top: var(--space-1); }
  .line-item { gap: var(--space-2); padding: var(--space-2) var(--space-3); }
  .line-item__top { gap: var(--space-2); }
  .filters { gap: var(--space-2); padding: var(--space-2) var(--space-3); margin-bottom: var(--space-3); }
  /* Tables, lists, details, chips. */
  .table caption { padding: var(--space-2) var(--space-3); }
  .table th, .table td { padding: var(--space-2) var(--space-3); }
  .details { gap: var(--space-1) var(--space-3); }
  .list__item { padding: var(--space-2) var(--space-3); }
  .comment { padding: var(--space-2) var(--space-3); }
  .chip { padding: 1px var(--space-2) 1px 5px; font-size: var(--text-xs); }
  .tabs__link { padding: 0 var(--space-2); }
  .alert { padding: var(--space-2) var(--space-3); }
  #page-messages { margin-bottom: var(--space-3); }
  .empty { padding: var(--space-8) var(--space-4); }
  .empty > .icon { width: 32px; height: 32px; }
  .dialog__body { padding: var(--space-5) var(--space-5) var(--space-3); }
  .dialog__actions { padding: var(--space-3) var(--space-5) var(--space-5); }
  .pagination, .load-more { margin-top: var(--space-3); }
}

/* ===== 8. Style guide (development page only) ======================== */
.sg-nav { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-6); }
.sg-swatches { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); }
.sg-swatch { border: var(--border-width) solid var(--color-border); border-radius: var(--radius-md); overflow: hidden; background: var(--color-surface); font-size: var(--text-xs); }
.sg-swatch__color { height: 3.5rem; border-bottom: var(--border-width) solid var(--color-border); }
.sg-swatch__name { padding: var(--space-2); font-family: var(--font-mono); word-break: break-all; }
.sg-swatch--bg .sg-swatch__color { background: var(--color-bg); }
.sg-swatch--surface .sg-swatch__color { background: var(--color-surface); }
.sg-swatch--sunken .sg-swatch__color { background: var(--color-surface-sunken); }
.sg-swatch--border .sg-swatch__color { background: var(--color-border-strong); }
.sg-swatch--text .sg-swatch__color { background: var(--color-text); }
.sg-swatch--muted .sg-swatch__color { background: var(--color-text-muted); }
.sg-swatch--primary .sg-swatch__color { background: var(--color-primary); }
.sg-swatch--primary-soft .sg-swatch__color { background: var(--color-primary-soft); }
.sg-swatch--accent .sg-swatch__color { background: var(--color-accent); }
.sg-swatch--danger .sg-swatch__color { background: var(--color-danger); }
.sg-type > * { margin-bottom: var(--space-2); }
.sg-type .t-xs { font-size: var(--text-xs); } .sg-type .t-sm { font-size: var(--text-sm); } .sg-type .t-md { font-size: var(--text-md); }
.sg-type .t-lg { font-size: var(--text-lg); } .sg-type .t-xl { font-size: var(--text-xl); } .sg-type .t-2xl { font-size: var(--text-2xl); }
.sg-space { display: flex; align-items: center; gap: var(--space-3); font-family: var(--font-mono); font-size: var(--text-xs); }
.sg-space__bar { height: 12px; background: var(--color-primary); border-radius: 2px; }
.sg-space--1 .sg-space__bar { width: var(--space-1); } .sg-space--2 .sg-space__bar { width: var(--space-2); }
.sg-space--3 .sg-space__bar { width: var(--space-3); } .sg-space--4 .sg-space__bar { width: var(--space-4); }
.sg-space--6 .sg-space__bar { width: var(--space-6); } .sg-space--8 .sg-space__bar { width: var(--space-8); }
.sg-space--12 .sg-space__bar { width: var(--space-12); } .sg-space--16 .sg-space__bar { width: var(--space-16); }
.sg-icons { display: grid; gap: var(--space-2); grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr)); }
.sg-icon { display: flex; flex-direction: column; align-items: center; gap: var(--space-1); padding: var(--space-3);
  border: var(--border-width) solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); font-size: var(--text-xs); font-family: var(--font-mono); }
.sg-demo { padding: var(--space-4); background: var(--color-surface); border: var(--border-width) dashed var(--color-border-strong); border-radius: var(--radius-lg); }
.sg-demo--flush { padding: 0; overflow: hidden; }
/* A small shell for the rail and its Menu button: the sidebar stays inside the box instead of sticking to the window. */
.sg-shell__header { display: flex; align-items: center; gap: var(--space-3); min-height: var(--header-height);
  padding: 0 var(--space-4) 0 calc((var(--rail-width) - var(--touch-target)) / 2); border-bottom: var(--border-width) solid var(--color-border); }
.sg-shell__body { display: flex; height: 44rem; background: var(--color-bg); }
.sg-shell .sidebar { position: relative; top: auto; height: auto; }
.sg-shell__main { flex: 1; min-width: 0; padding: var(--space-4); }
@media (max-width: 63.99em) { .sg-shell { display: none; } }  /* phones have the tab bar, not the rail */
