/*
 * Saffron & Spruce — NativeTable Deliveries (console redo, 2026-09-27).
 *
 * Loaded AFTER the vendored bootstrap.min.css. Everything here maps the palette
 * onto Bootstrap 5.3's own CSS variables; bootstrap.min.css is never edited.
 *
 * Spruce carries the structure: the rail, primary buttons, pins. Saffron is
 * fill-only: a background, a bar, a dot, a focus ring — never text and never a
 * hairline on white. Every colour is a token in the :root block below; no
 * literal colour lives anywhere else in this file (test/assets/theme_tokens_test.rb).
 */

/* ------------------------------------------------------------------ *
 * Faces (SIL OFL), vendored as woff2 in app/assets/fonts — no font CDN.
 * Bricolage Grotesque: display. Instrument Sans: body. JetBrains Mono: numbers.
 * ------------------------------------------------------------------ */
@font-face {
  font-family: "Bricolage Grotesque";
  src: url("/assets/bricolage-grotesque-latin-78692770.woff2") format("woff2");
  font-weight: 400 700;
  font-stretch: 100%;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Bricolage Grotesque";
  src: url("/assets/bricolage-grotesque-latin-ext-2186fff6.woff2") format("woff2");
  font-weight: 400 700;
  font-stretch: 100%;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Instrument Sans";
  src: url("/assets/instrument-sans-latin-570a9648.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Instrument Sans";
  src: url("/assets/instrument-sans-latin-ext-a083bc1c.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "JetBrains Mono";
  src: url("/assets/jetbrains-mono-latin-7c88d0cc.woff2") format("woff2");
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ------------------------------------------------------------------ *
 * Tokens — the only place a colour is written down.
 * ------------------------------------------------------------------ */
:root {
  /* Grounds and lines. */
  --nt-paper: #F5F7F7;      /* page */
  --nt-shell: #FFFFFF;      /* cards + surfaces */
  --nt-line: #E2E7E8;       /* hairlines */
  --nt-rule: #CFD7D8;       /* a pane's own border, a table's head rule */
  --nt-wash: #EEF2F2;       /* table heads, hovers, quiet fills */
  --nt-carton: #E3E9EA;     /* a segmented control's trough, a plain chip */
  --nt-carton-2: #D8E1E0;   /* an avatar's ground, a count pill */

  /* Ink, all contrast-checked against --nt-shell and --nt-wash. */
  --nt-ink: #13201F;        /* text */
  --nt-ink-2: #3D4A49;      /* quiet — a second line still meant to be read */
  --nt-muted: #596665;      /* secondary text */
  --nt-ink-3: #6B7877;      /* the quietest legible ink */
  --nt-edge: #7A8687;       /* control borders (AA non-text) */

  /* Spruce: the rail, primary buttons, pins. */
  --nt-spruce: #0E3A37;
  --nt-spruce-2: #185450;   /* rail hover, primary hover */
  --nt-spruce-3: #1F5A55;   /* rail count pill */
  --nt-spruce-soft: #8BA7A4; /* a disabled primary */
  --nt-spruce-4: #2A6B65;   /* the signed-in initials' ground */
  --nt-rail-ink: #E6F0EE;
  --nt-rail-muted: #A6C1BD;

  /* Saffron: fill-only. */
  --nt-saffron: #F2A516;
  --nt-saffron-deep: #C98400; /* a border on a saffron fill, a focus outline */
  --nt-saffron-wash: #FFF1CF; /* outgoing chat bubbles — the lightest saffron */
  --nt-saffron-wash-2: #FFF8E8;
  --nt-saffron-wash-3: #FFEAB8;

  /* Links. */
  --nt-link: #0D6B63;
  --nt-link-hover: #094F49;

  /* States. */
  --nt-ok: #1D7641;         /* verified / paid */
  --nt-wash-ok: #E3F4E8;
  --nt-edge-ok: #BFE3CB;
  --nt-bad: #C0342A;        /* mismatch / unpaid */
  --nt-bad-deep: #A12B22;   /* a danger button's hover */
  --nt-wash-bad: #FDEAE8;
  --nt-edge-bad: #F0B9B3;
  --nt-warn: #8A5800;       /* unreadable — not wrong, but you have to look */
  --nt-wash-warn: #FFF3D6;
  --nt-edge-warn: #F2D48A;
  --nt-info: #1D5DB5;
  --nt-wash-info: #E6EEFB;
  --nt-live: #23A05A;       /* the Live dot */

  /* A WhatsApp group, drawn as WhatsApp draws it (wa_group/_feed). */
  --nt-wa-bg: #E7EEEC;      /* the chat's tinted ground */
  --nt-wa-out: #D9FDD3;     /* our own bubbles, pale green */
  --nt-wa-tick: #1D5DB5;    /* ✓✓ read */
  --nt-wa-shadow: 0 1px 1px rgba(10, 32, 30, .13);
  --nt-wa-name-1: #1D5DB5;  /* sender names, picked by a stable hash */
  --nt-wa-name-2: #8A3FA0;
  --nt-wa-name-3: #B0451F;
  --nt-wa-name-4: #1D7641;
  --nt-wa-name-5: #0D6B63;
  --nt-wa-name-6: #9A4A00;
  --nt-wa-name-7: #B0306A;
  --nt-wa-name-8: #4F55A8;

  /* Legacy names (Eggshell & Yolk) keep their meaning, pointed at the new set. */
  --nt-yolk: var(--nt-saffron);
  --nt-yolk-deep: var(--nt-saffron-deep);
  --nt-wash-yolk: var(--nt-saffron-wash);
  --nt-leaf: var(--nt-ok);
  --nt-wash-leaf: var(--nt-wash-ok);
  --nt-brick: var(--nt-bad);
  --nt-wash-brick: var(--nt-wash-bad);

  /* Chart series — a colour-vision-checked set of their own, never the brand
     palette stretched. Used inside a chart and nowhere else. */
  --nt-s1: #2a78d6;         /* community drops */
  --nt-s2: #eb6834;         /* solo */
  --nt-s3: #1baf7a;         /* B2B */
  --nt-s-other: #9AA6A5;    /* everything else */
  --nt-seq-1: #CFE0F5;      /* one ordered ramp, for ageing buckets */
  --nt-seq-2: #8FB8E9;
  --nt-seq-3: #2a78d6;
  --nt-seq-4: #164C8F;

  /* Radii by role: a pane holds content, a control is acted on. */
  --nt-r-pane: 10px;
  --nt-r-ctl: 5px;

  --nt-rail: 200px;
  --nt-shadow: 0 10px 30px -18px rgba(10, 32, 30, .35);
  --nt-scrim: rgba(10, 32, 30, .28);        /* behind the drawer */
  --nt-drawer-shadow: -24px 0 48px -28px rgba(10, 32, 30, .45);
  --nt-palette-shadow: 0 30px 70px -30px rgba(10, 32, 30, .6);

  --nt-font-display: "Bricolage Grotesque", Georgia, serif;
  --nt-font-body: "Instrument Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --nt-font-mono: "JetBrains Mono", ui-monospace, Menlo, monospace;
  --nt-display: var(--nt-font-display);
  --nt-body: var(--nt-font-body);
}

/* ------------------------------------------------------------------ *
 * Bootstrap variable mapping
 * ------------------------------------------------------------------ */
:root,
[data-bs-theme="light"] {
  --bs-body-bg: var(--nt-paper);
  --bs-body-bg-rgb: 245, 247, 247;
  --bs-body-color: var(--nt-ink);
  --bs-body-color-rgb: 19, 32, 31;
  --bs-body-font-family: var(--nt-font-body);
  --bs-body-font-size: 0.9375rem;
  --bs-body-line-height: 1.45;
  --bs-font-monospace: var(--nt-font-mono);

  --bs-emphasis-color: var(--nt-ink);
  --bs-emphasis-color-rgb: 19, 32, 31;
  --bs-heading-color: var(--nt-ink);
  --bs-secondary-color: var(--nt-muted);
  --bs-secondary-color-rgb: 89, 102, 101;
  --bs-tertiary-color: var(--nt-muted);

  --bs-secondary-bg: var(--nt-wash);
  --bs-tertiary-bg: var(--nt-wash);

  --bs-border-color: var(--nt-line);
  --bs-border-color-translucent: var(--nt-line);
  --bs-border-radius: var(--nt-r-ctl);
  --bs-border-radius-sm: 4px;
  --bs-border-radius-lg: var(--nt-r-pane);

  --bs-primary: var(--nt-spruce);
  --bs-primary-rgb: 14, 58, 55;
  --bs-success: var(--nt-ok);
  --bs-success-rgb: 29, 118, 65;
  --bs-danger: var(--nt-bad);
  --bs-danger-rgb: 192, 52, 42;

  --bs-link-color: var(--nt-link);
  --bs-link-color-rgb: 13, 107, 99;
  --bs-link-hover-color: var(--nt-link-hover);
  --bs-link-hover-color-rgb: 9, 79, 73;

  --bs-focus-ring-color: rgba(242, 165, 22, 0.45);
  --bs-focus-ring-width: 0.2rem;
}

body {
  background-color: var(--nt-paper);
  color: var(--nt-ink);
  font-family: var(--nt-font-body);
  -webkit-text-size-adjust: 100%;
}

/* Numbers — money, counts, eggs, times — in the mono face, tabular. */
.nt-num, td.num {
  font-family: var(--nt-font-mono);
  font-variant-numeric: tabular-nums;
}

/* Links are not underlined until hovered (Bootstrap hardcodes the underline). */
a {
  text-decoration: none;
}

a:hover,
a:focus-visible {
  text-decoration: underline;
}

/* ------------------------------------------------------------------ *
 * Type scale — the display face carries the brand, h1–h3 and table heads.
 * Body copy is Instrument Sans.
 * ------------------------------------------------------------------ */
h1, h2, h3, .h1, .h2, .h3 {
  font-family: var(--nt-display);
  color: var(--nt-ink);
  letter-spacing: -0.018em;
  text-wrap: balance;
}

h1, .h1 {
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: -0.024em;
  line-height: 1.25;
  margin-bottom: 1rem;
}

h2, .h2 {
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.3;
  margin-top: 1.75rem;
  margin-bottom: 0.625rem;
}

h3, .h3 {
  font-size: 1rem;
  font-weight: 600;
  margin-bottom: 0.5rem;
}

h4, h5, h6, .h4, .h5, .h6 {
  font-family: var(--nt-body);
  font-size: 0.9375rem;
  font-weight: 600;
}

small, .small {
  font-size: 0.8125rem;
}

.text-body-secondary {
  color: var(--nt-muted) !important;
}

/* ------------------------------------------------------------------ *
 * The shell (D1) — the spruce rail, the top bar, the main pane
 *
 * `.nt-shell` is a two-column grid: the rail (`#nt_rail`, 200px, sticky and
 * exactly the viewport tall, scrolling inside itself) and a column holding
 * the sticky top bar over `main#nt_main`. The rail and the top bar are
 * `data-turbo-permanent`; see shell_controller.js.
 *
 * Inside the rail `#nt_rail_counts` is `display: contents`, so its three
 * children — the nav, the foot and the tab bar — are flex items of the rail.
 * Below 860px the rail wrapper dissolves too, and the foot and the bar become
 * grid items of `.nt-shell`, each placed by hand.
 * ------------------------------------------------------------------ */
.nt-shell {
  display: grid;
  grid-template-columns: var(--nt-rail) minmax(0, 1fr);
  /* `1fr`, not `minmax(0, 1fr)`: the row must be as tall as the page, or the
     sticky rail has nowhere to travel. */
  grid-template-rows: 1fr;
  min-height: 100vh;
}

.nt-rail-col {
  grid-column: 1;
  grid-row: 1;
  align-self: start;
  position: sticky;
  top: 0;
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow-y: auto;
  padding: 16px 12px 14px 22px;
  background-color: var(--nt-spruce);
  color: var(--nt-rail-ink);
}

#nt_rail_counts {
  display: contents;
}

.nt-rail {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.nt-brand {
  font-family: var(--nt-display);
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--nt-ink);
  white-space: nowrap;
}

.nt-brand:hover,
.nt-brand:focus-visible {
  color: var(--nt-ink);
  text-decoration: none;
}

/* The saffron dot after the wordmark, outside the shell (sign-in). */
.nt-brand::after {
  content: "";
  display: inline-block;
  width: 0.36em;
  height: 0.36em;
  margin-left: 0.22em;
  border-radius: 50%;
  background-color: var(--nt-saffron);
}

/* Inside the rail the egg carries the saffron instead. */
.nt-rail .nt-rail-brand {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 22px 2px;
  font-size: 17px;
  letter-spacing: -0.01em;
  color: var(--nt-rail-ink);
}

.nt-rail .nt-rail-brand::after {
  content: none;
}

.nt-rail .nt-rail-brand:hover,
.nt-rail .nt-rail-brand:focus-visible {
  color: var(--nt-rail-ink);
}

.nt-rail-egg path { fill: var(--nt-saffron); }
.nt-rail-egg circle { fill: var(--nt-saffron-wash); }

.nt-rail-link {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  height: 34px;
  padding: 0 10px;
  border-radius: 7px;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--nt-rail-muted);
}

.nt-rail-link .nt-icon {
  flex: none;
}

.nt-rail-link:hover,
.nt-rail-link:focus-visible {
  background-color: var(--nt-spruce-2);
  color: var(--nt-rail-ink);
  text-decoration: none;
}

.nt-rail-link.is-active {
  background-color: var(--nt-spruce-2);
  color: var(--nt-rail-ink);
  font-weight: 600;
}

/* The saffron bar in the gutter beside the entry you are standing on. */
.nt-rail-link.is-active::before {
  content: "";
  position: absolute;
  left: -10px;
  top: 8px;
  width: 3px;
  height: 18px;
  border-radius: 2px;
  background-color: var(--nt-saffron);
}

.nt-rail-divider {
  height: 1px;
  margin: 10px 0;
  background-color: var(--nt-spruce-2);
}

/* The foot: the Setup link, the keys card and who is signed in. A sibling of the nav,
   because below 860px the nav hides and nothing else reaches Sign out or the
   Setup screens. It takes the rail's slack, so the keys and the user sit at
   the bottom of the screen. */
.nt-rail-foot {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 2px;
}

.nt-keys {
  margin-top: auto;
  padding: 10px 11px;
  border: 1px solid var(--nt-spruce-2);
  border-radius: 9px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--nt-rail-muted);
}

.nt-keys-head,
.nt-keys-row {
  display: flex;
  justify-content: space-between;
  gap: 8px;
}

.nt-keys-head {
  font-weight: 600;
  color: var(--nt-rail-ink);
}

.nt-keys kbd {
  padding: 0;
  font-family: var(--nt-font-mono);
  font-size: 12px;
  color: var(--nt-rail-ink);
  background: none;
  box-shadow: none;
}

.nt-rail-who {
  position: relative;
  font-size: 13px;
}

.nt-user-menu > summary {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 2px;
  border-radius: 7px;
  color: var(--nt-rail-ink);
  cursor: pointer;
  list-style: none;
}

.nt-user-menu > summary::-webkit-details-marker { display: none; }

.nt-user-menu > summary:hover {
  background-color: var(--nt-spruce-2);
}

.nt-user-initials {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 14px;
  font-size: 12px;
  font-weight: 700;
  background-color: var(--nt-spruce-4);
}

.nt-user-lines {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.2;
}

.nt-user-name {
  font-weight: 600;
}

.nt-user-role {
  font-size: 11.5px;
  color: var(--nt-rail-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The user's menu opens upward, over the keys card. */
.nt-user-pop {
  position: absolute;
  bottom: calc(100% + 6px);
  left: 0;
  z-index: 30;
  min-width: 140px;
  padding: 6px;
  border: 1px solid var(--nt-line);
  border-radius: 8px;
  background-color: var(--nt-shell);
  box-shadow: var(--nt-shadow);
}

.nt-signout {
  margin: 0;
}

.nt-signout-btn {
  width: 100%;
  padding: 6px 8px;
  border: 0;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 600;
  text-align: left;
  color: var(--nt-ink);
  background: none;
}

.nt-signout-btn:hover {
  background-color: var(--nt-wash);
}

/* ---- the column: the top bar over the page ---- */
.nt-col {
  grid-column: 2;
  grid-row: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.nt-topbar {
  position: sticky;
  top: 0;
  z-index: 25;
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  height: 52px;
  padding: 0 18px;
  border-bottom: 1px solid var(--nt-line);
  background-color: var(--nt-shell);
}

.nt-topbar-name {
  min-width: 0;
  font-size: 13.5px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--nt-ink);
}

.nt-topbar-name:empty,
.nt-topbar-city:empty,
.nt-topbar-date:empty {
  display: none;
}

.nt-city-switch {
  display: flex;
  margin: 0 0 0 6px;
  padding: 2px;
  border: 1px solid var(--nt-line);
  border-radius: 8px;
  background-color: var(--nt-wash);
  overflow-x: auto;
}

.nt-city-btn {
  flex: none;
  height: 26px;
  padding: 0 10px;
  border: 0;
  border-radius: 6px;
  font: 600 12.5px var(--nt-font-body);
  color: var(--nt-ink-2);
  background: transparent;
  cursor: pointer;
  white-space: nowrap;
}

.nt-city-btn:hover {
  color: var(--nt-ink);
}

.nt-city-btn[aria-pressed="true"] {
  color: var(--nt-ink);
  background-color: var(--nt-shell);
  box-shadow: 0 1px 2px rgba(10, 32, 30, .18);
}

.nt-jump {
  flex: 1;
  max-width: 380px;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 32px;
  padding: 0 10px;
  border: 1px solid var(--nt-rule);
  border-radius: 8px;
  font-size: 13px;
  color: var(--nt-muted);
  background-color: var(--nt-paper);
}

.nt-jump:hover {
  color: var(--nt-ink);
  text-decoration: none;
  border-color: var(--nt-edge);
}

.nt-jump-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nt-jump-key {
  margin-left: auto;
  padding: 1px 5px;
  border: 1px solid var(--nt-rule);
  border-radius: 4px;
  font-family: var(--nt-font-mono);
  font-size: 11px;
  color: var(--nt-ink-2);
  background: none;
  box-shadow: none;
}

.nt-topbar-date {
  margin-left: auto;
}

.nt-scrub {
  display: flex;
  align-items: center;
}

.nt-scrub-step,
.nt-scrub-label {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 30px;
  border: 1px solid var(--nt-rule);
  color: var(--nt-ink);
  background-color: var(--nt-shell);
}

.nt-scrub-step {
  width: 28px;
}

.nt-scrub-step:hover,
.nt-scrub-label:hover {
  color: var(--nt-ink);
  background-color: var(--nt-wash);
  text-decoration: none;
}

.nt-scrub-prev { border-radius: 7px 0 0 7px; }
.nt-scrub-next { border-radius: 0 7px 7px 0; }

.nt-scrub-label {
  position: relative;
  gap: 7px;
  margin: 0;
  padding: 0 12px;
  border-left: 0;
  border-right: 0;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}

.nt-mono-date {
  font-variant-numeric: tabular-nums;
}

/* The native picker sits under the label, invisible, so the label opens it. */
.nt-scrub-input {
  position: absolute;
  inset: 0;
  width: 100%;
  opacity: 0;
  pointer-events: none;
}

.nt-live {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--nt-ok);
}

.nt-topbar-date:empty + .nt-live {
  margin-left: auto;
}

.nt-live-dot {
  width: 7px;
  height: 7px;
  border-radius: 4px;
  background-color: var(--nt-live);
  animation: nt-live 2.4s ease-in-out infinite;
}

@keyframes nt-live {
  0%, 100% { opacity: 1; }
  50% { opacity: .35; }
}

@media (prefers-reduced-motion: reduce) {
  .nt-live-dot { animation: none; }
}

.nt-main {
  flex: 1 0 auto;
  min-width: 0;
  /* The one padding number: the tab bar is fixed over the bottom of a phone,
     and this is what keeps the last row out from under it. */
  padding: 22px 28px calc(84px + env(safe-area-inset-bottom));
}

/* `display: none` until the media block: at desktop width it would be a
   fourth flex item in the rail. */
.nt-tabbar {
  display: none;
}

.nt-tabbar-link {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 4px 2px;
  font-size: 11px;
  font-weight: 600;
  color: var(--nt-rail-muted);
}

.nt-tabbar-link:hover {
  color: var(--nt-rail-ink);
  text-decoration: none;
}

.nt-tabbar-link.is-active {
  color: var(--nt-rail-ink);
}

.nt-tabbar-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background-color: transparent;
}

.nt-tabbar-link.is-active .nt-tabbar-dot {
  background-color: var(--nt-saffron);
}

.nt-tabbar-label {
  line-height: 1.2;
}

/* ------------------------------------------------------------------ *
 * The phone: the rail goes, the spruce bar arrives, the foot survives
 * both, and the top bar keeps the page name, the city and the date.
 * ------------------------------------------------------------------ */
@media (max-width: 860px) {
  .nt-shell {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: 1fr auto;
  }

  .nt-rail-col {
    display: contents;
  }

  .nt-rail,
  .nt-keys,
  .nt-jump,
  .nt-live-text {
    display: none;
  }

  .nt-col {
    grid-column: 1;
    grid-row: 1;
  }

  .nt-topbar {
    gap: 8px;
    padding: 0 12px;
  }

  /* At 375 three cities and the scrubber overran the bar (Task 34): the
     switcher scrolls sideways inside the bar, the scrubber keeps its size. */
  .nt-city-switch {
    margin-left: 0;
    min-width: 0;
    flex: 1 1 auto;
    overflow-x: auto;
    scrollbar-width: none;
  }

  /* The page head under the bar already names the page. */
  .nt-topbar-name { display: none; }
  .nt-topbar-city { flex: 1 1 auto; min-width: 0; display: flex; }
  .nt-topbar-date { flex: none; }

  .nt-scrub-label {
    padding: 0 8px;
  }

  .nt-main {
    /* No bottom reserve here: the foot follows the column and carries the
       bar's room itself. */
    padding: 14px 14px 0;
  }

  /* Not hidden with the nav: Sign out and Setup are reachable from nowhere
     else, so the foot drops into the flow under the page, on spruce, and
     reserves the bar's room. */
  .nt-rail-foot {
    grid-column: 1;
    grid-row: 2;
    padding: 12px 14px calc(84px + env(safe-area-inset-bottom));
    background-color: var(--nt-spruce);
    color: var(--nt-rail-ink);
  }

  .nt-user-pop {
    bottom: auto;
    top: calc(100% + 6px);
  }

  .nt-tabbar {
    display: flex;
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 20;
    background-color: var(--nt-spruce);
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
  }
}

/* Dropdown menus */
.dropdown-menu {
  --bs-dropdown-bg: var(--nt-shell);
  --bs-dropdown-border-color: var(--nt-line);
  --bs-dropdown-border-radius: 0.625rem;
  --bs-dropdown-link-color: var(--nt-ink);
  --bs-dropdown-link-hover-color: var(--nt-ink);
  --bs-dropdown-link-hover-bg: var(--nt-wash);
  --bs-dropdown-link-active-color: var(--nt-ink);
  --bs-dropdown-link-active-bg: var(--nt-wash);
  --bs-dropdown-font-size: 0.875rem;
  --bs-dropdown-padding-y: 0.375rem;
  box-shadow: 0 6px 20px rgba(10, 32, 30, 0.08);
}

/* ------------------------------------------------------------------ *
 * The page head (D6): breadcrumbs + back, the title, a primary action,
 * the NT Agent button where the page has a scoped agent, and "⋯".
 * Mockup: build.py `breadcrumbs`, `agent_btn`, `overflow_menu`.
 * ------------------------------------------------------------------ */
.nt-page-head {
  padding: 12px 16px 0;
}

.nt-crumbs {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-size: 12.5px;
  color: var(--nt-muted);
}

.nt-crumbs-back {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: 1px solid var(--nt-rule);
  border-radius: 7px;
  color: var(--nt-ink);
}

.nt-crumbs-back:hover,
.nt-crumbs-back:focus-visible {
  background: var(--nt-wash);
  color: var(--nt-ink);
}

.nt-crumbs-sep {
  color: var(--nt-rule);
}

.nt-crumbs-link {
  color: var(--nt-link);
  font-weight: 600;
  text-decoration: none;
}

.nt-crumbs-link:hover {
  color: var(--nt-link-hover);
  text-decoration: underline;
}

.nt-crumbs-here,
.nt-crumbs-text {
  overflow: hidden;
  color: var(--nt-ink);
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nt-crumbs-text {
  color: var(--nt-muted);
}

.nt-crumbs-hint {
  margin-left: 4px;
  font-family: var(--nt-font-mono);
  font-size: 11px;
  white-space: nowrap;
}

.nt-page-head-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-top: 8px;
}

.nt-page-head-title {
  min-width: 0;
}

.nt-page-head-h1 {
  margin: 0;
  font-family: var(--nt-font-display);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--nt-ink);
}

.nt-page-head-sub {
  margin-top: 3px;
  font-size: 12.5px;
  color: var(--nt-muted);
}

.nt-page-head-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

.nt-head-form {
  display: contents;
}

.nt-head-primary,
.nt-head-agent {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 32px;
  padding: 0 11px;
  border: 1px solid var(--nt-spruce);
  border-radius: 8px;
  font: 600 13px var(--nt-font-body);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}

.nt-head-primary {
  background: var(--nt-spruce);
  color: var(--nt-rail-ink);
}

.nt-head-primary:hover,
.nt-head-primary:focus-visible {
  background: var(--nt-spruce-2);
  color: var(--nt-rail-ink);
}

/* Spruce outline, saffron spark (the plan's "saffron dot"). */
.nt-head-agent {
  background: var(--nt-shell);
  color: var(--nt-spruce);
}

.nt-head-agent .nt-icon {
  fill: var(--nt-saffron);
  stroke: var(--nt-spruce);
}

.nt-head-agent:hover,
.nt-head-agent:focus-visible {
  background: var(--nt-wash);
  color: var(--nt-spruce);
}

.nt-head-agent-key {
  font-family: var(--nt-font-mono);
  font-size: 11px;
  font-weight: 500;
  color: var(--nt-muted);
}

/* ---- the "⋯" menu ---- */
.nt-menu {
  position: relative;
}

.nt-menu-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: 1px solid var(--nt-rule);
  border-radius: 8px;
  background: var(--nt-shell);
  color: var(--nt-ink);
  cursor: pointer;
}

.nt-menu-button:hover,
.nt-menu-button[aria-expanded="true"] {
  background: var(--nt-wash);
}

.nt-menu-list {
  position: absolute;
  top: 38px;
  right: 0;
  z-index: 20;
  width: 244px;
  padding: 5px;
  border: 1px solid var(--nt-line);
  border-radius: 10px;
  background: var(--nt-shell);
  box-shadow: 0 18px 40px -18px rgba(10, 32, 30, .45);
}

.nt-menu-list[hidden] {
  display: none;
}

.nt-menu-form {
  margin: 0;
}

.nt-menu-item {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 7px 9px;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: var(--nt-ink);
  font: inherit;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

.nt-menu-item:hover,
.nt-menu-item:focus-visible {
  background: var(--nt-wash);
  color: var(--nt-ink);
  outline: none;
}

.nt-menu-icon {
  display: flex;
  flex-shrink: 0;
  justify-content: center;
  width: 18px;
  color: var(--nt-ink-2);
}

.nt-menu-text {
  flex: 1;
  min-width: 0;
}

.nt-menu-label {
  display: block;
  font-size: 13px;
  font-weight: 600;
}

.nt-menu-sub,
.nt-menu-hint {
  font-family: var(--nt-font-mono);
  font-size: 11px;
  color: var(--nt-muted);
}

.nt-menu-sub {
  display: block;
}

.nt-menu-danger,
.nt-menu-danger:hover,
.nt-menu-danger:focus-visible,
.nt-menu-danger .nt-menu-icon {
  color: var(--nt-bad);
}

.nt-menu-head {
  padding: 4px 9px 2px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--nt-muted);
}

.nt-menu-sep {
  height: 1px;
  margin: 4px 0;
  background: var(--nt-line);
}

@media (max-width: 860px) {
  .nt-crumbs-hint,
  .nt-head-agent-key {
    display: none;
  }

  .nt-page-head-row {
    flex-wrap: wrap;
  }
}

/* ------------------------------------------------------------------ *
 * Tables — white card surface, hairline dividers, display-face heads.
 * ------------------------------------------------------------------ */
.table {
  --bs-table-bg: var(--nt-shell);
  --bs-table-color: var(--nt-ink);
  --bs-table-border-color: var(--nt-line);
  --bs-table-striped-bg: transparent;
  --bs-table-striped-color: var(--nt-ink);
  --bs-table-hover-bg: var(--nt-wash);
  --bs-table-hover-color: var(--nt-ink);
  background-color: var(--nt-shell);
  border: 1px solid var(--nt-line);
  border-radius: 0.625rem;
  border-collapse: separate;
  border-spacing: 0;
  overflow: hidden;
}

.table > :not(caption) > * > * {
  padding: 0.625rem 0.75rem;
  border-width: 0 0 1px 0;
  border-style: solid;
  border-color: var(--nt-line);
  box-shadow: none;
}

.table > tbody > tr:last-child > * {
  border-bottom-width: 0;
}

.table > thead > tr > th {
  border-bottom-color: var(--nt-rule);
  font-family: var(--nt-display);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--nt-muted);
  background-color: var(--nt-wash);
  white-space: nowrap;
  vertical-align: middle;
}

.table > thead > tr:first-child > th:first-child {
  border-top-left-radius: 0.625rem;
}

.table > thead > tr:first-child > th:last-child {
  border-top-right-radius: 0.625rem;
}

.table > thead > tr > th a {
  color: inherit;
}

/* Secondary lines inside a cell (addresses, hints) step back. */
.table td small {
  color: var(--nt-muted);
}

/* A five-column run sheet cannot compress into a phone. Below the tablet
   breakpoint wide tables scroll inside their own card so the page never does.
   Narrower tables are left alone so they still fill the card.
 *
 * The scroll box alone is not enough: a block-level table still lays its
 * columns out to the width of the box, so the cells crush to one word per
 * line instead of overflowing. Holding the cells on one line is what gives
 * the row its natural width and gives the box something to scroll. The
 * address is the one field long enough to need wrapping, so it opts back in
 * against a cap. */
@media (max-width: 767.98px) {
  .table:has(> thead > tr > th:nth-child(5)) {
    display: block;
    overflow-x: auto;
    white-space: nowrap;
  }

  .table:has(> thead > tr > th:nth-child(5)) td small {
    display: inline-block;
    max-width: 13rem;
    white-space: normal;
    vertical-align: top;
  }
}

/* Sticky heads inside scroll boxes keep the wash, not the paper ground. */
.table-scroll {
  border: 1px solid var(--nt-line);
  border-radius: 0.625rem;
  background-color: var(--nt-shell);
}

.table-scroll .table {
  border: 0;
  border-radius: 0;
  margin-bottom: 0;
}

.table-scroll thead th {
  background-color: var(--nt-wash);
  box-shadow: inset 0 -1px 0 var(--nt-rule);
}

/* ------------------------------------------------------------------ *
 * Status chips — pill, hairline, colour lives in the dot.
 * ------------------------------------------------------------------ */
.nt-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.15rem 0.55rem 0.2rem;
  border: 1px solid var(--nt-line);
  border-radius: 999px;
  background-color: var(--nt-paper);
  color: var(--nt-ink);
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.35;
  white-space: nowrap;
}

.nt-chip::before {
  content: "";
  width: 0.45em;
  height: 0.45em;
  border-radius: 50%;
  background-color: var(--nt-muted);
  flex: none;
}

.nt-chip--paid {
  background-color: var(--nt-wash-leaf);
  border-color: var(--nt-edge-ok);
}

.nt-chip--paid::before {
  background-color: var(--nt-leaf);
}

.nt-chip--unpaid {
  background-color: var(--nt-wash-brick);
  border-color: var(--nt-edge-bad);
}

.nt-chip--unpaid::before {
  background-color: var(--nt-brick);
}

.nt-chip--neutral::before {
  background-color: var(--nt-edge);
}

/* Waiting on a person: a proposal, a day with expenses still to decide. */
.nt-chip--warn {
  background-color: var(--nt-wash-warn);
  border-color: var(--nt-edge-warn);
}

.nt-chip--warn::before {
  background-color: var(--nt-warn);
}

/* A label with no state behind it — a rate card, a segment, a billing mode.
   It reads as a tag on the carton rather than a status, and it is written
   above the toned chips on purpose: `--plain` alongside `--yolk` is "yolk, no
   dot", and a plain rule that came later would repaint the yolk away. */
.nt-chip--plain {
  background-color: var(--nt-carton);
  border-color: var(--nt-rule);
}

/* A rate or a credit that explains a number beside it. */
.nt-chip--yolk {
  background-color: var(--nt-wash-yolk);
  border-color: var(--nt-edge-warn);
}

.nt-chip--yolk::before {
  background-color: var(--nt-yolk-deep);
}

/* A label, not a state — so it drops the dot the way --customer does. */
.nt-chip--plain::before {
  display: none;
}

/* The compact variant rides inside a list row or a thread header. */
.nt-chip--sm {
  padding: 0.05rem 0.45rem 0.1rem;
  font-size: 0.75rem;
}

/* A linked customer is a destination, not a status, so it wears the yolk as an
   outline and drops the dot — the dot stays the mark of a state. */
.nt-chip--customer {
  border-color: var(--nt-yolk);
  background-color: var(--nt-shell);
  color: var(--nt-ink);
}

.nt-chip--customer::before {
  display: none;
}

.nt-chip--customer:hover,
.nt-chip--customer:focus-visible {
  border-color: var(--nt-yolk-deep);
  background-color: var(--nt-wash-yolk);
  color: var(--nt-ink);
  text-decoration: none;
}

/* Bootstrap badges inherit the chip silhouette. */
.badge {
  --bs-badge-border-radius: 999px;
  --bs-badge-padding-x: 0.55rem;
  --bs-badge-padding-y: 0.28em;
  --bs-badge-font-weight: 500;
  font-family: var(--nt-body);
  letter-spacing: 0;
}

/* ------------------------------------------------------------------ *
 * Buttons
 * ------------------------------------------------------------------ */
.btn {
  --bs-btn-font-weight: 500;
  --bs-btn-border-radius: 0.5rem;
  --bs-btn-focus-box-shadow: 0 0 0 0.2rem var(--bs-focus-ring-color);
}

.btn-sm {
  --bs-btn-border-radius: 0.4375rem;
  --bs-btn-font-size: 0.8125rem;
  --bs-btn-padding-x: 0.625rem;
  --bs-btn-padding-y: 0.3125rem;
}

.btn-primary {
  --bs-btn-color: var(--nt-shell);
  --bs-btn-bg: var(--nt-spruce);
  --bs-btn-border-color: var(--nt-spruce);
  --bs-btn-hover-color: var(--nt-shell);
  --bs-btn-hover-bg: var(--nt-spruce-2);
  --bs-btn-hover-border-color: var(--nt-spruce-2);
  --bs-btn-active-color: var(--nt-shell);
  --bs-btn-active-bg: var(--nt-spruce-2);
  --bs-btn-active-border-color: var(--nt-spruce-2);
  --bs-btn-active-shadow: none;
  --bs-btn-disabled-color: var(--nt-shell);
  --bs-btn-disabled-bg: var(--nt-spruce-soft);
  --bs-btn-disabled-border-color: var(--nt-spruce-soft);
  --bs-btn-focus-shadow-rgb: 242, 165, 22;
}

.btn-outline-secondary {
  --bs-btn-color: var(--nt-ink);
  --bs-btn-bg: var(--nt-shell);
  --bs-btn-border-color: var(--nt-edge);
  --bs-btn-hover-color: var(--nt-ink);
  --bs-btn-hover-bg: var(--nt-wash);
  --bs-btn-hover-border-color: var(--nt-edge);
  --bs-btn-active-color: var(--nt-ink);
  --bs-btn-active-bg: var(--nt-wash);
  --bs-btn-active-border-color: var(--nt-edge);
  --bs-btn-active-shadow: none;
  --bs-btn-disabled-color: var(--nt-muted);
  --bs-btn-disabled-bg: var(--nt-shell);
  --bs-btn-disabled-border-color: var(--nt-line);
  --bs-btn-focus-shadow-rgb: 242, 165, 22;
}

.btn-outline-danger,
.btn-danger {
  --bs-btn-focus-shadow-rgb: 192, 52, 42;
}

.btn-danger {
  --bs-btn-bg: var(--nt-brick);
  --bs-btn-border-color: var(--nt-brick);
  --bs-btn-hover-bg: var(--nt-bad-deep);
  --bs-btn-hover-border-color: var(--nt-bad-deep);
  --bs-btn-active-bg: var(--nt-bad-deep);
  --bs-btn-active-border-color: var(--nt-bad-deep);
}

.btn-outline-danger {
  --bs-btn-color: var(--nt-brick);
  --bs-btn-border-color: var(--nt-brick);
  --bs-btn-hover-bg: var(--nt-brick);
  --bs-btn-hover-border-color: var(--nt-brick);
  --bs-btn-active-bg: var(--nt-brick);
  --bs-btn-active-border-color: var(--nt-brick);
}

/* Action cells hold several buttons; keep them tight and on one baseline.
   button_to wraps each control in its own block-level form, which would
   otherwise stack them one per line and stretch every row. */
.table td .btn {
  --bs-btn-padding-x: 0.55rem;
  margin-bottom: 0;
}

/* Uniform trailing margins rather than margins between siblings, so a cell
   too narrow to hold the controls side by side wraps them flush left. */
.table td form.button_to {
  display: inline-block;
  margin: 0 0.25rem 0.25rem 0;
}

.table td form.button_to:last-child {
  margin-bottom: 0;
}

/* A run sheet puts an affirmative control on every row. Filling each one with
   yolk turns the page into a wall of gold and drowns the dot that carries the
   brand, so inside a table the primary action wears the gold as an edge and
   the surface stays paper. The page-level primary (Sign in, New order) keeps
   the filled button, so there is still exactly one loud thing per screen. */
.table td .btn-primary,
.table th .btn-primary {
  --bs-btn-color: var(--nt-ink);
  --bs-btn-bg: var(--nt-shell);
  --bs-btn-border-color: var(--nt-spruce);
  --bs-btn-hover-color: var(--nt-ink);
  --bs-btn-hover-bg: var(--nt-wash);
  --bs-btn-hover-border-color: var(--nt-spruce);
  --bs-btn-active-color: var(--nt-ink);
  --bs-btn-active-bg: var(--nt-carton);
  --bs-btn-active-border-color: var(--nt-spruce);
  --bs-btn-active-shadow: none;
  font-weight: 500;
}

/* ------------------------------------------------------------------ *
 * Forms
 * ------------------------------------------------------------------ */
.form-control,
.form-select {
  background-color: var(--nt-shell);
  border-color: var(--nt-edge);
  border-radius: 0.5rem;
  color: var(--nt-ink);
  font-size: 0.9375rem;
}

.form-control:focus,
.form-select:focus {
  border-color: var(--nt-yolk-deep);
  box-shadow: 0 0 0 0.2rem var(--bs-focus-ring-color);
}

.form-control::placeholder {
  color: var(--nt-muted);
  opacity: 1;
}

.form-label {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--nt-muted);
  margin-bottom: 0.3rem;
}

/* Checkboxes and radios ship a hardcoded blue fill that Bootstrap exposes no
   variable for, so the selector is restated rather than the token remapped. */
.form-check-input {
  border-color: var(--nt-edge);
}

.form-check-input:checked {
  background-color: var(--nt-spruce);
  border-color: var(--nt-spruce);
}

.form-check-input:focus {
  border-color: var(--nt-yolk-deep);
  box-shadow: 0 0 0 0.2rem var(--bs-focus-ring-color);
}

.form-check-label {
  font-size: 0.9375rem;
}

/* Tabs (the city page) read as the top nav does: quiet until current. */
.nav-tabs {
  --bs-nav-tabs-border-color: var(--nt-line);
  --bs-nav-tabs-link-active-color: var(--nt-ink);
  --bs-nav-tabs-link-active-bg: var(--nt-shell);
  --bs-nav-tabs-link-active-border-color: var(--nt-line) var(--nt-line) var(--nt-shell);
  --bs-nav-tabs-link-hover-border-color: var(--nt-line);
  --bs-nav-link-color: var(--nt-muted);
  --bs-nav-link-hover-color: var(--nt-ink);
  --bs-nav-link-font-size: 0.875rem;
  --bs-nav-link-font-weight: 500;
  margin-bottom: 1rem;
}

.nav-tabs .nav-link.active {
  font-weight: 600;
}

/* ------------------------------------------------------------------ *
 * Flash messages
 * ------------------------------------------------------------------ */
.alert {
  --bs-alert-border-color: var(--nt-line);
  --bs-alert-padding-y: 0.625rem;
  --bs-alert-padding-x: 0.875rem;
  border-radius: 0.625rem;
  border-left-width: 3px;
  font-size: 0.9375rem;
}

.alert-success {
  --bs-alert-color: var(--nt-ink);
  --bs-alert-bg: var(--nt-wash-leaf);
  --bs-alert-border-color: var(--nt-edge-ok);
  border-left-color: var(--nt-leaf);
}

.alert-danger {
  --bs-alert-color: var(--nt-ink);
  --bs-alert-bg: var(--nt-wash-brick);
  --bs-alert-border-color: var(--nt-edge-bad);
  border-left-color: var(--nt-brick);
}

/* ------------------------------------------------------------------ *
 * Cards and the sign-in screen
 * ------------------------------------------------------------------ */
.card {
  --bs-card-bg: var(--nt-shell);
  --bs-card-border-color: var(--nt-line);
  --bs-card-border-radius: 0.625rem;
}

/* Unauthenticated shell: one narrow centred column under the brand bar. */
.nt-shell-bare {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-bottom: 4rem; /* optical centring — sit the card above the midline */
}

/* No rail and no bar out here: the wordmark is the whole of the chrome, and
   it centres over the one card. */
.nt-shell-bare .nt-brand {
  display: block;
  text-align: center;
  padding: 1.5rem 0 1.25rem;
  font-size: 1.375rem;
}

.nt-shell-bare > .container {
  max-width: 24rem;
}

.nt-auth-card {
  background-color: var(--nt-shell);
  border: 1px solid var(--nt-line);
  border-radius: 0.75rem;
  padding: 1.5rem 1.375rem;
  box-shadow: 0 1px 2px rgba(10, 32, 30, 0.04);
}

.nt-auth-title {
  font-size: 1.125rem;
  margin-bottom: 1.125rem;
}

.nt-auth-foot {
  margin: 1.125rem 0 0;
  font-size: 0.8125rem;
}

/* ------------------------------------------------------------------ *
 * Filter toolbar — search plus its filters as one control strip.
 * ------------------------------------------------------------------ */
.nt-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem;
  margin-bottom: 0.875rem;
  padding: 0.4375rem;
  background-color: var(--nt-shell);
  border: 1px solid var(--nt-line);
  border-radius: 0.625rem;
}

.nt-toolbar .form-control,
.nt-toolbar .form-select {
  width: auto;
  min-width: 0;
  flex: 0 1 auto;
}

/* The search field is the one control that should eat the leftover width, but
   only up to a readable line — the toolbar stays a compact strip on a laptop
   rather than stretching a search box across the whole page. */
.nt-toolbar .nt-toolbar-search {
  flex: 1 1 11rem;
  max-width: 20rem;
}

.nt-toolbar .btn {
  flex: none;
}

/* ------------------------------------------------------------------ *
 * Initial avatars — one deterministic tint per name, mixed from the
 * palette so no new colour enters the system.
 * ------------------------------------------------------------------ */
.nt-avatar {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background-color: var(--nt-wash); /* fallback where color-mix is unsupported */
  color: var(--nt-ink);
  font-family: var(--nt-display);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1;
  user-select: none;
}

.nt-avatar--sm {
  width: 2rem;
  height: 2rem;
  font-size: 0.875rem;
}

.nt-avatar--0 { background-color: color-mix(in srgb, var(--nt-yolk) 20%, var(--nt-shell)); }
.nt-avatar--1 { background-color: color-mix(in srgb, var(--nt-leaf) 18%, var(--nt-shell)); }
.nt-avatar--2 { background-color: color-mix(in srgb, var(--nt-brick) 15%, var(--nt-shell)); }
.nt-avatar--3 { background-color: color-mix(in srgb, var(--nt-ink) 12%, var(--nt-shell)); }
.nt-avatar--4 { background-color: color-mix(in srgb, var(--nt-yolk-deep) 16%, var(--nt-shell)); }
.nt-avatar--5 { background-color: color-mix(in srgb, var(--nt-muted) 20%, var(--nt-shell)); }

/* ------------------------------------------------------------------ *
 * WhatsApp — the conversation list
 * ------------------------------------------------------------------ */
.nt-chats {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
  background-color: var(--nt-shell);
  border: 1px solid var(--nt-line);
  border-radius: 0.625rem;
  overflow: hidden;
}

.nt-chat {
  position: relative; /* anchors the stretched link to the whole row */
  display: flex;
  align-items: flex-start;
  gap: 0.6875rem;
  padding: 0.625rem 0.875rem;
  border-bottom: 1px solid var(--nt-line);
}

.nt-chat:last-child {
  border-bottom: 0;
}

.nt-chat:hover {
  background-color: var(--nt-wash);
}

/* The stretched link's own outline would ring the name only, so the ring is
   moved onto the row it actually activates. */
.nt-chat:has(.stretched-link:focus-visible) {
  background-color: var(--nt-wash);
  outline: 2px solid var(--nt-yolk-deep);
  outline-offset: -2px;
}

.nt-chat .stretched-link:focus-visible {
  outline: none;
}

.nt-chat-body {
  flex: 1 1 auto;
  min-width: 0; /* lets the ellipsis rules below actually bite */
}

.nt-chat-top {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}

.nt-chat-name {
  min-width: 0;
  overflow: hidden;
  color: var(--nt-ink);
  font-size: 0.9375rem;
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nt-chat-name:hover,
.nt-chat-name:focus-visible {
  color: var(--nt-ink);
  text-decoration: none; /* the row's wash is the affordance */
}

.nt-chat-name.is-recent {
  font-weight: 700;
}

.nt-chat-time {
  flex: none;
  margin-left: auto;
  color: var(--nt-muted);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}

.nt-chat-snippet {
  margin: 0.0625rem 0 0;
  overflow: hidden;
  color: var(--nt-muted);
  font-size: 0.8125rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nt-chat-snippet i {
  font-size: 0.75rem;
}

.nt-chat-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-top: 0.375rem;
}
/* Lift only the chips above the row's stretched-link overlay — lifting the
   whole flex container made everything right of a chip a dead zone. */
.nt-chat-tags .nt-chip {
  position: relative;
  z-index: 2;
}

.nt-chat-empty {
  justify-content: center;
  padding: 2rem 1rem;
  color: var(--nt-muted);
}

.nt-note {
  margin: 0 0 1rem;
  color: var(--nt-muted);
  font-size: 0.8125rem;
}

/* ------------------------------------------------------------------ *
 * WhatsApp — the thread
 * ------------------------------------------------------------------ */
.nt-thread {
  max-width: 760px;
  margin: 0 auto;
}

.nt-thread-head {
  position: sticky;
  top: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 0.625rem;
  margin-bottom: 0.5rem;
  padding: 0.5rem 0.75rem;
  background-color: var(--nt-shell);
  border: 1px solid var(--nt-line);
  border-radius: 0.625rem;
  /* The only shadow in the app: the one place where content slides underneath
     a surface and the eye needs to be told which is on top. */
  box-shadow: 0 8px 12px -12px rgba(10, 32, 30, 0.45);
}

.nt-thread-back {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  margin-left: -0.25rem;
  border-radius: 0.5rem;
  color: var(--nt-muted);
  font-size: 1.125rem;
}

.nt-thread-back:hover {
  background-color: var(--nt-wash);
  color: var(--nt-ink);
  text-decoration: none;
}

.nt-thread-id {
  flex: 1 1 auto;
  min-width: 0;
}

.nt-thread-name {
  margin: 0;
  overflow: hidden;
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.3;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nt-thread-meta {
  margin: 0;
  overflow: hidden;
  color: var(--nt-muted);
  font-size: 0.75rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nt-thread-tags {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 0.3rem;
  max-width: 40%;
}

/* "Load older" sits above the oldest bubble as a quiet pill. */
.nt-older {
  display: flex;
  justify-content: center;
  margin: 0.5rem 0;
}

.nt-older a {
  padding: 0.2rem 0.75rem 0.25rem;
  background-color: var(--nt-shell);
  border: 1px solid var(--nt-line);
  border-radius: 999px;
  color: var(--nt-muted);
  font-size: 0.8125rem;
  font-weight: 500;
}

.nt-older a:hover {
  border-color: var(--nt-edge);
  color: var(--nt-ink);
  text-decoration: none;
}

.nt-msgs {
  display: flex;
  flex-direction: column;
  gap: 0.1875rem;
  /* Breathing room between bubbles and the pane edges. */
  padding: 0 1rem 2rem;
}

.nt-day {
  display: flex;
  justify-content: center;
  margin: 0.875rem 0 0.5rem;
}

.nt-day span {
  padding: 0.1rem 0.625rem 0.15rem;
  background-color: var(--nt-wash);
  border: 1px solid var(--nt-line);
  border-radius: 999px;
  color: var(--nt-muted);
  font-size: 0.75rem;
  font-weight: 500;
}

.nt-msg {
  display: flex;
}

.nt-msg--out {
  justify-content: flex-end;
}

.nt-bubble {
  max-width: min(85%, 32rem);
  min-width: 0;
  padding: 0.375rem 0.5625rem 0.3125rem;
  background-color: var(--nt-shell);
  border: 1px solid var(--nt-line);
  border-radius: 0.75rem;
  font-size: 0.9375rem;
}

/* The squared-off corner points the bubble at its side of the thread. */
.nt-msg--in .nt-bubble {
  border-bottom-left-radius: 0.25rem;
}

.nt-msg--out .nt-bubble {
  background-color: var(--nt-wash-yolk);
  border-color: color-mix(in srgb, var(--nt-yolk-deep) 22%, var(--nt-wash-yolk));
  border-bottom-right-radius: 0.25rem;
}

.nt-bubble-sender {
  margin: 0 0 0.0625rem;
  color: var(--nt-leaf);
  font-size: 0.75rem;
  font-weight: 600;
}

/* Pasted addresses and bare JIDs are longer than a phone is wide, so a word
   with no break in it is allowed to break anywhere rather than overflow. */
.nt-bubble-text {
  margin: 0;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

.nt-bubble-text--quiet {
  color: var(--nt-muted);
  font-size: 0.875rem;
  font-style: italic;
}

.nt-attach {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.1875rem;
  padding: 0.3rem 0.45rem;
  background-color: var(--nt-paper);
  border: 1px solid var(--nt-line);
  border-radius: 0.5rem;
  font-size: 0.8125rem;
}

.nt-attach i {
  flex: none;
  color: var(--nt-link);
  font-size: 0.9375rem;
}

.nt-attach-name {
  min-width: 0;
  overflow: hidden;
  color: var(--nt-ink);
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nt-attach-size {
  flex: none;
  color: var(--nt-muted);
  font-variant-numeric: tabular-nums;
}

.nt-bubble-time {
  display: block;
  margin-top: 0.0625rem;
  color: var(--nt-muted);
  font-size: 0.6875rem;
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.nt-empty {
  margin: 1.5rem 0;
  padding: 2rem 1rem;
  background-color: var(--nt-shell);
  border: 1px solid var(--nt-line);
  border-radius: 0.625rem;
  color: var(--nt-muted);
  text-align: center;
}

/* ------------------------------------------------------------------ *
 * Focus + motion
 * ------------------------------------------------------------------ */
:focus-visible {
  outline: 2px solid var(--nt-yolk-deep);
  outline-offset: 2px;
  border-radius: 0.25rem;
}

.btn:focus-visible,
.form-control:focus-visible,
.form-select:focus-visible {
  outline: 2px solid var(--nt-yolk-deep);
  outline-offset: 1px;
}

/* This is an ops tool: nothing here animates. Honour the setting anyway for
   the transitions Bootstrap ships. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ------------------------------------------------------------------ *
 * Small screens (delivery staff on phones, down to 375px)
 * ------------------------------------------------------------------ */
@media (max-width: 575.98px) {
  .container {
    padding-left: 0.875rem;
    padding-right: 0.875rem;
  }

  h1, .h1 {
    font-size: 1.3125rem;
  }

  .table > :not(caption) > * > * {
    padding: 0.5rem 0.5rem;
  }

  .table td .btn {
    --bs-btn-padding-x: 0.5rem;
  }

  .form-control,
  .form-select {
    font-size: 1rem; /* keeps iOS from zooming the viewport on focus */
  }

  /* Three rows on a phone: the search, then the two filters side by side, then
     a full-width submit. The filter bases are wide enough that "All accounts"
     never truncates to a bare "All", and wide enough together to push the
     button onto its own line. */
  .nt-toolbar .nt-toolbar-search {
    flex: 1 1 100%;
    max-width: none;
  }

  .nt-toolbar .form-select {
    flex: 1 1 9rem;
  }

  .nt-toolbar .btn {
    flex: 1 1 100%;
  }

  .nt-chat {
    gap: 0.5625rem;
    padding: 0.5625rem 0.6875rem;
  }

  .nt-avatar {
    width: 2.25rem;
    height: 2.25rem;
    font-size: 0.9375rem;
  }

  .nt-thread-head {
    gap: 0.5rem;
    padding: 0.5rem 0.625rem;
  }

  /* A long customer name would otherwise squeeze the chat name to nothing. */
  .nt-thread-tags {
    max-width: 8.5rem;
  }

  .nt-bubble {
    max-width: 88%;
  }
}

/* ---------------------------------------------------------------- wa spa
   Two panes, WhatsApp-Web style: the conversation list stays put on the
   left; a row click swaps only the right pane (the "wa_thread" frame). On
   a phone the panes collapse to one: :has() flips list -> thread the
   moment the frame holds a thread, and the header's back arrow returns. */
.nt-wa {
  display: grid;
  grid-template-columns: 360px minmax(0, 1fr);
  background: var(--nt-shell);
  border: 1px solid var(--nt-line);
  border-radius: .75rem;
  overflow: hidden;
  height: calc(100vh - 6.625rem);
  min-height: 26rem;
}
.nt-wa-side {
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-right: 1px solid var(--nt-line);
}
.nt-wa-side .nt-toolbar {
  margin: 0;
  padding: .75rem;
  border-bottom: 1px solid var(--nt-line);
}
.nt-wa-side .nt-chats {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  margin: 0;
  border: 0;
  border-radius: 0;
}
.nt-wa-side .nt-empty,
.nt-wa-side .nt-note { padding: .75rem; margin: 0; }
.nt-wa-thread {
  display: block;
  min-width: 0;
  overflow-y: auto;
  background: var(--nt-paper);
}
.nt-wa-thread .nt-thread { border: 0; border-radius: 0; min-height: 100%; }
.nt-wa-blank {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .3rem;
  color: var(--nt-muted);
}
.nt-wa-blank i { font-size: 2.1rem; opacity: .6; }
.nt-wa-blank-title { margin: 0; font-weight: 600; color: var(--nt-ink); }
.nt-wa-blank-note { margin: 0; font-size: .85rem; }

/* The open thread's row: server-rendered on load, :focus-within carries the
   highlight to the row just clicked during a frame swap. */
.nt-chat.is-active,
.nt-chat:focus-within {
  background: color-mix(in srgb, var(--nt-yolk) 12%, var(--nt-shell));
}

/* Group members panel */
.nt-members { list-style: none; margin: 0 0 .75rem; padding: 0; max-height: 16rem; overflow-y: auto; }
.nt-member {
  display: flex;
  align-items: baseline;
  gap: .5rem;
  padding: .3rem 0;
  border-top: 1px solid var(--nt-line);
  font-size: .9rem;
}
.nt-member-name { font-weight: 500; }
.nt-member-phone { color: var(--nt-muted); font-size: .8rem; }

/* Back arrow is a phone affordance; the list is already beside you on desktop. */
.nt-thread-back { display: none; }

@media (max-width: 767.98px) {
  .nt-wa { grid-template-columns: 1fr; height: calc(100vh - 7rem); }
  .nt-wa-thread { display: none; }
  .nt-wa:has(.nt-thread) .nt-wa-side { display: none; }
  .nt-wa:has(.nt-thread) .nt-wa-thread { display: block; }
  .nt-thread-back { display: inline-flex; align-items: center; }
}

/* Manual pull: a quiet full-width strip under the sidebar toolbar. */
.nt-pull-form { display: block; border-bottom: 1px solid var(--nt-line); }
.nt-pull {
  width: 100%;
  border: 0;
  background: transparent;
  color: var(--nt-link);
  font-size: .8rem;
  font-weight: 600;
  padding: .45rem .75rem;
  text-align: left;
  cursor: pointer;
}
.nt-pull:hover { background: color-mix(in srgb, var(--nt-yolk) 8%, var(--nt-shell)); }
.nt-pull:focus-visible { outline: 2px solid var(--nt-yolk-deep); outline-offset: -2px; }

/* Quoted original inside a reply bubble, WhatsApp style. */
.nt-quote {
  display: block;
  border-left: 3px solid var(--nt-yolk);
  background: color-mix(in srgb, var(--nt-ink) 5%, transparent);
  border-radius: 0.25rem;
  padding: 0.3rem 0.5rem;
  margin-bottom: 0.3rem;
  font-size: 0.8rem;
}
.nt-quote-sender { display: block; font-weight: 600; font-size: 0.75rem; color: var(--nt-link); }
.nt-quote-text { display: block; color: var(--nt-muted); overflow-wrap: anywhere; }
.nt-quote-text--missing { font-style: italic; }

/* Sender runs: a new sender's first bubble gets air above; the rest of the
   run stays tight under the container's small gap. */
.nt-msg--first { margin-top: 0.5rem; }
.nt-day + .nt-msg--first { margin-top: 0; }

/* Inline media in bubbles. */
.nt-media-img { display: block; max-width: 100%; max-height: 22rem; border-radius: 0.5rem; }
.nt-media-video { display: block; max-width: 100%; max-height: 22rem; border-radius: 0.5rem; }
.nt-media-audio { display: block; width: 16rem; max-width: 100%; }

/* Content-search hits under the chat list. */
.nt-chats--hits { border-top: 2px solid var(--nt-line); }

/* Sidebar toolbar: search + a dots menu, one line. The yolk dot on the
   toggle says filters are active — the signature doing real work. */
.nt-toolbar--line { flex-wrap: nowrap; align-items: center; }
.nt-toolbar--line .nt-toolbar-search { flex: 1 1 auto; min-width: 0; }
.nt-filter-toggle {
  position: relative;
  border: 1px solid var(--nt-edge);
  color: var(--nt-muted);
}
.nt-filter-toggle.has-filters::after {
  content: "";
  position: absolute;
  top: 3px;
  right: 3px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--nt-yolk-deep);
}
.nt-filter-menu { padding: 0.75rem; min-width: 14rem; }

/* Groups sit on the warm wash so the list reads at a glance. */
.nt-chat--group { background: var(--nt-wash); }

/* The panes scroll, but quietly. */
.nt-wa-side .nt-chats,
.nt-wa-thread,
.nt-members {
  scrollbar-width: none;
}
.nt-wa-side .nt-chats::-webkit-scrollbar,
.nt-wa-thread::-webkit-scrollbar,
.nt-members::-webkit-scrollbar { display: none; }

/* Chat info: full-pane view behind the header's i button. */
.nt-cinfo-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.9rem;
  height: 1.9rem;
  border-radius: 50%;
  color: var(--nt-muted);
}
.nt-cinfo-btn:hover { background: var(--nt-wash); color: var(--nt-ink); text-decoration: none; }
.nt-cinfo-btn:focus-visible { outline: 2px solid var(--nt-yolk-deep); outline-offset: 2px; }
.nt-info-back { display: inline-flex; align-items: center; color: var(--nt-muted); }
.nt-info-back:hover { color: var(--nt-ink); }
.nt-info { max-width: 34rem; padding: 0 1rem 2rem; }
.nt-info-section { margin-top: 1.25rem; }
.nt-info-title { margin-top: 0; }
.nt-cinfo-list {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.15rem 0.75rem;
  margin: 0;
  font-size: 0.85rem;
}
.nt-cinfo-list dt { color: var(--nt-muted); font-weight: 500; }
.nt-cinfo-list dd { margin: 0; overflow-wrap: anywhere; }

/* Tag chips with inline remove, and the one-line typeahead add forms. */
.nt-tag { display: inline-flex; align-items: center; gap: 0.3rem; }
.nt-tag-x-form { display: inline; }
.nt-tag-x {
  border: 0;
  background: transparent;
  color: var(--nt-muted);
  padding: 0 0.1rem;
  line-height: 1;
  cursor: pointer;
  font-size: 0.9em;
}
.nt-tag-x:hover { color: var(--nt-brick); }
.nt-tag-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-bottom: 0.75rem; }
.nt-tag-forms { display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem; }
.nt-tag-form { display: flex; gap: 0.35rem; align-items: center; }
.nt-tag-form .form-control { width: 12rem; }
/* The role select sits in the same column as the tag typeaheads, so it wears
   their width rather than stretching the pane. */
.nt-role .form-select { width: 12rem; }
.nt-role .nt-tag-chips { margin-bottom: 0.5rem; }
.nt-info-tabs { margin-top: 1.25rem; }
.nt-info-tabs + .tab-content { padding-top: 0.9rem; }

/* --------------------------------------------------------------- two-pane spa
   The generalized shell behind the "wa spa" block above: a list that stays put
   on the left, a detail pane on the right that a row click swaps on its own,
   collapsing to one column on a phone. The nt-wa* classes stay exactly as they
   are — this family is what every other two-pane page (Customers first) is
   built from, and it reuses the row, chip, avatar and header classes the chat
   list already defines rather than restating them. */
.nt-spa {
  display: grid;
  grid-template-columns: 360px minmax(0, 1fr);
  background: var(--nt-shell);
  border: 1px solid var(--nt-line);
  border-radius: .75rem;
  overflow: hidden;
  height: calc(100vh - 6.625rem);
  min-height: 26rem;
}
.nt-spa-side {
  display: flex;
  flex-direction: column;
  /* Both minimums are load-bearing: without them a grid track takes its
     automatic minimum from the widest row, and a long address or a search box
     asking for 100% pushes the column past the viewport. */
  min-height: 0;
  min-width: 0;
  border-right: 1px solid var(--nt-line);
}
.nt-spa-side .nt-toolbar-search { min-width: 0; }
.nt-spa-side .nt-toolbar {
  margin: 0;
  padding: .75rem;
  border-bottom: 1px solid var(--nt-line);
}
.nt-spa-side .nt-chats {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  margin: 0;
  border: 0;
  border-radius: 0;
}
.nt-spa-side .nt-empty,
.nt-spa-side .nt-note { padding: .75rem; margin: 0; }
/* The chat list lifts its chips above the row's stretched link because they are
   links themselves; these are plain labels, so they stay under it and the whole
   row keeps taking the click. */
.nt-spa-side .nt-chat-tags .nt-chip { position: static; }
.nt-spa-pane {
  display: block;
  min-width: 0;
  overflow-y: auto;
  background: var(--nt-paper);
}
.nt-spa-blank {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .3rem;
  color: var(--nt-muted);
}
.nt-spa-blank i { font-size: 2.1rem; opacity: .6; }
.nt-spa-blank-title { margin: 0; font-weight: 600; color: var(--nt-ink); }
.nt-spa-blank-note { margin: 0; font-size: .85rem; }

/* The right-aligned meta slot in a list row — a city here, a time in a chat. */
.nt-row-meta {
  flex: none;
  margin-left: auto;
  color: var(--nt-muted);
  font-size: .75rem;
}

/* One record filling the pane. The header spans it as a sticky bar — a record
   has no bubbles to slide under a floating card — and the body keeps a column
   width the eye can follow on a wide screen. */
.nt-detail { min-height: 100%; }
.nt-detail > .nt-thread-head {
  margin-bottom: 0;
  border-width: 0 0 1px;
  border-radius: 0;
}
.nt-detail-body {
  max-width: 46rem;
  margin: 0 auto;
  padding: 1rem 1rem 2.5rem;
}
.nt-detail-section { margin-top: 1.75rem; }
.nt-detail-section:first-child { margin-top: 0; }
.nt-detail-section > h2:first-child { margin-top: 0; }
.nt-detail-section h3 { margin-top: 1.25rem; }
.nt-detail-section .nt-note { margin-bottom: 0; }
.nt-detail .table-scroll { overflow-x: auto; }
/* A form in the pane is a column of short answers, not a full-width sheet. */
.nt-detail-body .form-control,
.nt-detail-body .form-select { max-width: 24rem; }
/* Row actions are two or three small buttons that must not stack. */
.nt-detail-actions {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .375rem;
}
.nt-detail-actions form { display: inline; }

/* The panes scroll, but quietly — same as the chat list's. */
.nt-spa-side .nt-chats,
.nt-spa-pane { scrollbar-width: none; }
.nt-spa-side .nt-chats::-webkit-scrollbar,
.nt-spa-pane::-webkit-scrollbar { display: none; }

@media (max-width: 767.98px) {
  .nt-spa { grid-template-columns: minmax(0, 1fr); height: calc(100vh - 7rem); }
  .nt-spa-pane { display: none; }
  .nt-spa:has(.nt-detail) .nt-spa-side { display: none; }
  .nt-spa:has(.nt-detail) .nt-spa-pane { display: block; }
  /* The wrapper does the sideways scrolling in this pane, so a wide table
     stays a table instead of turning into its own scroll box — and its cells
     stay on one line rather than collapsing into a column of single words. */
  .nt-detail .table-scroll > .table { display: table; white-space: nowrap; }
  .nt-detail-body { padding: .75rem .75rem 2.5rem; }
}

/* -------------------------------------------------------------------- orders
   Orders sit in the .nt-spa shell above and borrow its rows, chips, avatars
   and header wholesale. Only what a money page needs on top of that is new:
   an amount that reads at a glance, the two lifecycle tones the paid/unpaid
   pair does not cover, and a total that stands apart from its lines. Nothing
   above this line changes. */

/* An amount is the first thing read in an order row, so it leads the snippet
   in the ink colour while the items stay quiet behind it. */
/* Where an order stands on its way out. Yolk while it is still coming, leaf
   once it has landed; skipped and cancelled keep the neutral grey dot. */
.nt-chip--scheduled {
  background-color: var(--nt-wash-yolk);
  border-color: color-mix(in srgb, var(--nt-yolk-deep) 22%, var(--nt-wash-yolk));
}
.nt-chip--scheduled::before { background-color: var(--nt-yolk-deep); }
.nt-chip--delivered {
  background-color: var(--nt-wash-leaf);
  border-color: var(--nt-edge-ok);
}
.nt-chip--delivered::before { background-color: var(--nt-leaf); }

/* The total closes the items table: one rule, label left, money right. */
.nt-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin: .75rem 0 0;
  padding-top: .6rem;
  border-top: 1px solid var(--nt-line);
}
.nt-total-label { color: var(--nt-muted); font-size: .85rem; }
.nt-total-value { font-size: 1.15rem; font-weight: 600; font-variant-numeric: tabular-nums; }

/* A statement's ledger: the balance column is the one the eye runs down, and
   the opening row is context rather than an entry — quiet, but still a row. */
.nt-ledger .nt-ledger-open td { color: var(--nt-muted); font-style: italic; }
.nt-ledger .nt-ledger-balance { font-weight: 600; }

/* A list pinned to one customer says so, and offers the way out — the strip
   sits under the toolbar where the "New order" action does. */
/* A quantity is two digits, not a sentence — it must not inherit the pane's
   24rem field width, and the price columns need the room. */
/* ------------------------------------------------------- two-pane spa, mended
   A QA pass over the rebuilt Customers and Orders panes. Everything here is
   either a shared class the two-pane family was missing (right-aligned money,
   a table that fits a phone, a due row) or the correction of a rule that was
   measurably wrong at 375px. Nothing above this line is edited; the nt-wa*
   family keeps every rule it had, and the two additions that reach it — the
   sidebar's missing minimum and the shell's height on a phone — are the fixes
   that block was always meant to have. */

/* The sidebar's automatic minimum. .nt-spa-side carries both of these and says
   why; .nt-wa-side only ever got the height one, so at 375px a single long URL
   in a snippet held its column open to 4241px inside a 332px shell and the
   overflow: hidden above quietly clipped nine tenths of every row. */
.nt-wa-side { min-width: 0; }

/* The shell is "the viewport minus the chrome above it", which was written as a
   fixed 7rem — but the nav wraps to two lines on a phone and is 127px there, so
   the shell hung past the fold and the page grew a scrollbar behind the list's
   own. Measuring nothing and letting flex do the subtraction is exact at every
   nav height. Above the phone breakpoint the fixed heights stand. */
@media (max-width: 767.98px) {
  /* A definite height, not a minimum: only a fixed one gives the shell below
     something to take a share of, and the shell scrolls inside itself anyway. */
  body:has(.nt-spa, .nt-wa) {
    display: flex;
    flex-direction: column;
    height: 100vh;
  }

  body:has(.nt-spa, .nt-wa) > .nt-shell {
    flex: 1 1 auto;
    min-height: 0;
  }

  /* The bar's room is reserved by the foot below main on a phone, so main
     itself gives the shell every pixel between the two. */
  body:has(.nt-spa, .nt-wa) .nt-main {
    display: flex;
    flex-direction: column;
    min-height: 0;
    padding-bottom: 0.75rem;
  }

  /* Basis zero, so what it takes is the leftover exactly — a flash above it
     shortens the shell instead of pushing its foot past the fold. */
  .nt-spa,
  .nt-wa {
    flex: 1 1 0;
    height: auto;
    min-height: 0;
  }
}

/* The pane header on a phone: two chips capped at 8.5rem were taking the width
   the name needed, clipping "Vishaka S…" into an 86px slot and still wrapping
   onto two lines. Identity first — the chips drop to their own line under it. */
@media (max-width: 575.98px) {
  .nt-detail > .nt-thread-head { flex-wrap: wrap; }

  /* Basis zero so a long meta line ellipsizes on the first line as it always
     has, instead of taking the wrap the chips below are there to take. */
  .nt-detail > .nt-thread-head .nt-thread-id { flex: 1 1 0; }

  .nt-detail > .nt-thread-head .nt-thread-tags {
    order: 3;
    flex-basis: 100%;
    max-width: none;
    justify-content: flex-start;
    margin-top: 0.15rem;
  }
}

/* The filter menu sits inside the toolbar form, so it inherited the toolbar's
   "size to your content" and the selects stepped raggedly at the right edge.
   Inside the menu they are a stacked column, and a column is one width. */
.nt-spa-side .nt-filter-menu .form-control,
.nt-spa-side .nt-filter-menu .form-select { width: 100%; }

/* The cap note is about the list, not about the row it happens to fall under.
   Its own ground and a hairline say so, and separate it from a row the scroll
   has cut in half. */
.nt-spa-side > .nt-note {
  border-top: 1px solid var(--nt-line);
  background-color: var(--nt-wash);
}

/* An empty avatar slot on the new-record panes: without it the title started
   42px to the left of where show and edit put it, and the header jumped
   sideways as you moved between pane states. */
.nt-avatar--blank {
  background-color: var(--nt-wash);
  border: 1px dashed var(--nt-edge);
  color: var(--nt-muted);
  font-size: 0.8125rem;
}

/* Money reads down a column, not across one: every numeric cell is flush right
   with tabular figures, so decimals line up between rows of different
   magnitude, and the total is inset by one cell's padding to land on the same
   edge as the line it totals. */
.nt-num,
th.nt-num { text-align: right; }
.nt-num { font-variant-numeric: tabular-nums; }
.nt-total { padding-right: calc(0.75rem + 1px); }

/* The quantity field keeps a floor as well as its cap: squeezed into the last
   column of a table that now fits a phone, it was clipping its own digits. */
/* A table narrow enough to fit a phone should fit it. The pane holds wide
   tables on one line and scrolls them sideways, which is right for a five
   column history and wrong for the three numbers on an order: there the
   product name wraps and the money stays on screen. */
@media (max-width: 767.98px) {
  .nt-detail .table-scroll > .table.nt-table--fit { white-space: normal; }
  .nt-total { padding-right: calc(0.5rem + 1px); }
}

/* An outstanding order is a small stack, not a table row: the two pay buttons
   are the reason the section exists, and a fourth column put them past the
   right edge of a phone behind a sideways scroll nobody would find. */
.nt-dues {
  list-style: none;
  margin: 0;
  padding: 0;
  background-color: var(--nt-shell);
  border: 1px solid var(--nt-line);
  border-radius: 0.625rem;
  overflow: hidden;
}

.nt-due {
  padding: 0.625rem 0.75rem;
  border-bottom: 1px solid var(--nt-line);
}

.nt-due:last-child { border-bottom: 0; }

.nt-due-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
}

.nt-due-date { font-weight: 500; }

.nt-due-amount {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.nt-due-items {
  margin: 0.125rem 0 0.5rem;
  color: var(--nt-muted);
  font-size: 0.8125rem;
}

/* The ghost the table rule gives a primary button, available by name now that
   the same repeated action lives outside a table: spruce as an edge, white as
   the surface, so a list of them does not become a wall of fills. */
.btn-outline-primary {
  --bs-btn-color: var(--nt-ink);
  --bs-btn-bg: var(--nt-shell);
  --bs-btn-border-color: var(--nt-spruce);
  --bs-btn-hover-color: var(--nt-ink);
  --bs-btn-hover-bg: var(--nt-wash);
  --bs-btn-hover-border-color: var(--nt-spruce);
  --bs-btn-active-color: var(--nt-ink);
  --bs-btn-active-bg: var(--nt-carton);
  --bs-btn-active-border-color: var(--nt-spruce);
  --bs-btn-active-shadow: none;
  --bs-btn-focus-shadow-rgb: 242, 165, 22;
  font-weight: 500;
}

/* A section heading and the sub-heading inside it were 18px and 16px of the
   same weight, so "Add subscription" read at the level of the "Subscriptions"
   that contains it. The sub-heading takes the small caps the table heads wear
   — plainly a label, plainly one rung down. */
.nt-detail-section h3 {
  font-family: var(--nt-body);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--nt-muted);
}

/* Bootstrap ships code in its own pink, which is the one colour in the app that
   belongs to no token. A JID is a value, so it reads as one. */
code {
  padding: 0.05em 0.3em;
  background-color: var(--nt-wash);
  border-radius: 0.3rem;
  color: var(--nt-ink);
  font-size: 0.875em;
}

/* ----------------------------------------------------------------- ticks
   The order list this dressed went with `_orders_chunk` when the pane became
   a ledger; the tick outlived it, on the ledger row and on the run sheet. */
.nt-tick { text-align: center; color: var(--nt-muted); opacity: 0.5; }
.nt-tick.is-on { color: var(--nt-leaf); opacity: 1; }

/* ------------------------------------------------------------------ *
 * Approval queue — evidence beside the proposal.
 * ------------------------------------------------------------------ */

/* Money lines up column-wise wherever it is tabulated. */
.nt-num { font-variant-numeric: tabular-nums; }

/* The screenshot the finding was read off. Square-cropped so a column of them
   reads as a column; the link behind it opens the full image. */
/* Two columns of fact: label quiet on the left, value in ink on the right. */
/* One message, several buyers: the extras sit under the main proposal, each
   with its own fields, rather than folded into the first buyer's order. */
/* The extra buyers a relay-board message named are ticked inside the same
   form as the main proposal, so each takes a full row of it rather than
   queueing up beside the first buyer's fields. */
/* A pair is two findings, so its card is two columns: the delivery on the
   left, the money said to pay for it on the right, and one strip of answers
   under both. On a phone they stack, the order first — that is the order a
   reviewer reads them in, and the money only means anything after it. */
/* Which side of the pair this column is, said once at the top of it. */
/* How far the reading got, above the lists it produced. */

/* ------------------------------------------------------------------ *
 * Today — the day's named sections
 * ------------------------------------------------------------------ */

.nt-day-section { margin-bottom: 2rem; }

/* The day's section headings, and the only place in the app that uses this
   treatment: sentence case at the weight of a heading, not an all-caps label
   above a table. Today reads as a page of named sections, so the names are
   read as names. */
.nt-day-section > h2,
.nt-pulse > h2 {
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--nt-ink);
  margin-bottom: 0.6rem;
}

.nt-day-plan { margin: 0; font-size: 0.875rem; }

/* The pulse's table scrolls inside its pane rather than dragging the page
   sideways on a phone — or, in a third of a page, clipping its own last
   column. It is the only table left on Today; every other section is rows. */
.nt-pulse .table-scroll { overflow-x: auto; }
.nt-pulse .nt-pane .table { margin-bottom: 0; }
.nt-pulse .nt-pane .table-scroll { border-radius: var(--nt-r-pane); }

/* Four columns in a third of a page. The compact treatment is not a phone
   rule here — the pulse lives in the narrowest column of the widest screen,
   and left to size itself the table was wider than its pane at every width:
   the stale chip and the promo link sat off the right edge behind a scrollbar
   nobody thinks to drag.

   So the table is told its width instead of asking its content: fixed layout
   at the pane's full width, the four columns proportioned to what they hold,
   and every cell free to wrap. A long name and a long "27 days ago" take two
   lines rather than a hidden inch of table. */
.nt-pulse .table { font-size: 0.8125rem; table-layout: fixed; width: 100%; }
.nt-pulse th, .nt-pulse td { padding-left: 0.25rem; padding-right: 0.25rem; }
.nt-pulse th, .nt-pulse td, .nt-pulse .table > thead > tr > th {
  white-space: normal;
  overflow-wrap: break-word;
}
/* The count column is sized by its heading, not its number: "Open" is wider
   set in the label's caps than any tally of open orders it will ever hold. */
.nt-pulse .table > thead > tr > th:nth-child(1) { width: 32%; }
.nt-pulse .table > thead > tr > th:nth-child(2) { width: 18%; }
.nt-pulse .table > thead > tr > th:nth-child(3) { width: 16%; }
.nt-pulse .table > thead > tr > th:nth-child(4) { width: 34%; }

/* Below the day's work: every group in the city, quiet ones first. A group
   nobody has heard from in over a week wears the brick dot — the same read as
   an unpaid order, and for the same reason: somebody has to go do something. */
.nt-pulse { margin-bottom: 2rem; }

.nt-pulse-name { font-weight: 500; }

.nt-pulse-count { font-variant-numeric: tabular-nums; }

.nt-pulse-quiet { color: var(--nt-muted); }

/* A quiet group's way out of being quiet, on its own line under the chip that
   says it has gone quiet. Not a column of its own and not held to the right
   edge: the empty-drops sentence points at this link, and a link parked
   behind a horizontal scrollbar is a sentence pointing at nothing. */
.nt-pulse-act { margin-top: 0.15rem; }

/* A link and not a button: four columns in a third of a page, and the
   button's own chrome was twenty pixels this cell does not have. */
.nt-pulse-promo { font-weight: 500; }

.nt-chip--stale {
  background-color: var(--nt-wash-brick);
  border-color: var(--nt-edge-bad);
}

.nt-chip--stale::before { background-color: var(--nt-brick); }

/* ------------------------------------------------------------------ *
 * Today — the header, the tray meter, the drops
 * ------------------------------------------------------------------ */
.nt-top {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.15rem;
}

.nt-top h1 { margin: 0; }

/* A segmented control made of links, because a city is a place in the URL and
   has to survive being shared and reloaded. */
.nt-seg {
  display: inline-flex;
  background-color: var(--nt-carton);
  border: 1px solid var(--nt-rule);
  border-radius: 99px;
  padding: 3px;
}

.nt-seg-link {
  padding: 0.32rem 0.85rem;
  border-radius: 99px;
  font-weight: 600;
  font-size: 0.875rem;
  color: var(--nt-ink-2);
  text-decoration: none;
}

.nt-seg-link:hover { color: var(--nt-ink); }

.nt-seg-link.is-active {
  background-color: var(--nt-shell);
  color: var(--nt-ink);
  box-shadow: 0 1px 0 var(--nt-rule);
}

/* The tray meter. It is a Turbo frame, and a frame is inline until told. */
.nt-meter {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 1.4rem;
  align-items: center;
  background-color: var(--nt-shell);
  border: 1px solid var(--nt-line);
  border-radius: var(--nt-r-pane);
  padding: 1.1rem 1.35rem;
  margin-bottom: 1.15rem;
}

/* Tabular figures without `.nt-num`: that class also flushes its text right,
   which is a rule for a money column and wrong for a headline. */
.nt-meter-big,
.nt-meter-facts { font-variant-numeric: tabular-nums; }

.nt-meter-big {
  font-family: var(--nt-display);
  font-size: 3.375rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
}

.nt-meter-big small {
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--nt-ink-3);
  letter-spacing: 0;
  margin-left: 0.4rem;
}

.nt-meter-facts { color: var(--nt-ink-3); font-size: 0.875rem; margin-top: 0.35rem; }

.nt-trays { display: flex; gap: 4px; flex-wrap: wrap; }

/* Two states and no third: filled is delivered, outlined is still to pack.
   Nothing in the schema knows that an order has been packed. */
.nt-tray {
  display: inline-block;
  border: 1.5px solid var(--nt-yolk);
  border-radius: 3px;
  background-color: transparent;
}

.nt-tray { width: 22px; height: 16px; }

.nt-tray--done {
  background-color: var(--nt-leaf);
  border-color: var(--nt-leaf);
}

/* The foot spans both columns: where the stock leaves from is a setting for
   the day, not a fact about the trays above it. */
.nt-meter-foot {
  grid-column: 1 / -1;
  border-top: 1px solid var(--nt-line);
  padding-top: 0.75rem;
}

.nt-meter-stock { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.nt-meter-stock-label { margin: 0; color: var(--nt-muted); font-size: 0.875rem; }

/* Three columns that become one on a phone, and never a sideways scroll: an
   fr track's implied minimum is its content, so each column is told otherwise. */
.nt-grid3 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 1rem;
  align-items: start;
}

.nt-grid3 > * { min-width: 0; }

/* One pane shape, used by every section this redesign rebuilds. */
.nt-pane {
  background-color: var(--nt-shell);
  border: 1px solid var(--nt-line);
  border-radius: var(--nt-r-pane);
}

.nt-pane-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.65rem;
  flex-wrap: wrap;
  padding: 0.85rem 1.1rem;
  border-bottom: 1px solid var(--nt-line);
}

.nt-pane-head h3 {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin: 0;
  font-size: 1.05rem;
}

.nt-pane-head-aside { display: inline-flex; align-items: center; gap: 0.35rem; flex-wrap: wrap; }
.nt-pane-body { padding: 0.75rem 1.1rem; }

/* One action bar per pane, at its foot, on the wash so it reads as the ledge
   the pane sits on rather than another row. */
.nt-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  flex-wrap: wrap;
  padding: 0.7rem 1.1rem;
  border-top: 1px solid var(--nt-line);
  background-color: var(--nt-wash);
  border-radius: 0 0 var(--nt-r-pane) var(--nt-r-pane);
}

.nt-actions-quiet { color: var(--nt-muted); font-size: 0.875rem; }
.nt-actions-buttons { display: inline-flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.nt-actions form { display: inline; margin: 0; }

.nt-drop,
.nt-round,
.nt-popup,
.nt-unattached { margin-bottom: 0.9rem; }

/* The round. The stop number is display type in its own narrow column, and
   the member row takes the rest — so the numbers stack into a column the eye
   runs down while the rows keep the shape they have everywhere else. */
.nt-stop {
  display: grid;
  grid-template-columns: 1.75rem minmax(0, 1fr);
  align-items: start;
  border-bottom: 1px solid var(--nt-line);
}

.nt-stop:last-of-type { border-bottom: 0; }
.nt-stop > turbo-frame,
.nt-stop > div { display: block; min-width: 0; }
.nt-stop .nt-mrow { border-bottom: 0; padding-left: 0; }

.nt-stop-k {
  padding: 0.6rem 0 0 1.1rem;
  font-family: var(--nt-display);
  font-weight: 700;
  color: var(--nt-muted);
}

.nt-round-from { color: var(--nt-muted); font-size: 0.8125rem; }

/* The area a stop is in, beside the name: on the round it is what orders the
   list, so it earns the ink a drop's shared address would not. */
.nt-mrow-area {
  margin-left: 0.35rem;
  color: var(--nt-muted);
  font-weight: 400;
  font-size: 0.8125rem;
}

/* A stall's four facts, in as many columns as the pane can hold. */
.nt-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: 0.6rem 1.1rem;
}

.nt-facts b {
  display: block;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--nt-muted);
}

/* Money today: four figures, each with what it is and where it came from.
   The track is narrow enough that two fit side by side inside a third of the
   page — four tiles stacked in a column read as a list of unrelated numbers
   rather than one strip. */
.nt-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
  gap: 0.7rem;
}

.nt-tile {
  padding: 0.8rem 0.95rem;
  border: 1px solid var(--nt-line);
  border-radius: var(--nt-r-pane);
  background-color: var(--nt-shell);
}

.nt-tile b { display: block; font-size: 0.8125rem; font-weight: 600; color: var(--nt-muted); }

.nt-tile-value {
  margin-top: 0.1rem;
  font-family: var(--nt-display);
  font-size: 1.5rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* The one figure on the strip somebody has to go do something about. */
.nt-tile-value--bad { color: var(--nt-brick); }

.nt-tile-note { margin-top: 0.1rem; font-size: 0.8125rem; color: var(--nt-ink-3); }

.nt-drop-meta { margin: 0; padding-top: 0.55rem; padding-bottom: 0.55rem; color: var(--nt-ink-3); font-size: 0.8125rem; }
.nt-drop-paid { color: var(--nt-muted); }
.nt-drop-none { margin: 0; color: var(--nt-muted); font-size: 0.875rem; }

/* Every member row is its own Turbo frame — a delivery replaces one row and
   the meter, never the pane — and a frame is inline until it is told. */
.nt-drop turbo-frame { display: block; }
.nt-drop turbo-frame:last-of-type .nt-mrow { border-bottom: 0; }

/* Two columns, three rows: who and what on the left with the amount held to
   the right of them, then the chips, then whatever is still to be done. A
   third column for the chips reads well in a prototype the width of a page and
   collapses the name to one letter per line inside a third of one. */
.nt-mrow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.3rem 0.6rem;
  align-items: baseline;
  padding: 0.6rem 1.1rem;
  border-bottom: 1px solid var(--nt-line);
  font-size: 0.875rem;
}

.nt-mrow-who { grid-column: 1; min-width: 0; }
.nt-mrow-name { font-weight: 600; color: var(--nt-ink); text-decoration: none; }
.nt-mrow-name:hover { color: var(--nt-link-hover); }
.nt-mrow-items { color: var(--nt-ink-3); font-size: 0.8125rem; }
.nt-mrow-leg { margin-top: 0.2rem; }
.nt-mrow-amount { grid-column: 2; justify-self: end; font-weight: 600; white-space: nowrap; }

.nt-mrow-chips {
  grid-column: 1 / -1;
  display: flex;
  gap: 0.3rem;
  flex-wrap: wrap;
}

/* Four buttons do not fit beside a name in a third of a page, so they take the
   row under it — and take none at all when there is nothing left to do. */
.nt-mrow-acts {
  grid-column: 1 / -1;
  display: flex;
  gap: 0.35rem;
  flex-wrap: wrap;
}

.nt-mrow-acts:empty { display: none; }
.nt-mrow-acts form { display: inline; margin: 0; }
.nt-mrow-note { margin: 0; padding: 0 1.1rem 0.6rem; }

/* The sentence a refused decision carries back into its own row. */
.nt-note--bad { color: var(--nt-brick); font-weight: 500; }

@media (max-width: 575.98px) {
  .nt-meter { grid-template-columns: minmax(0, 1fr); gap: 0.9rem; padding: 0.9rem; }
  .nt-meter-big { font-size: 2.75rem; }
  .nt-mrow { padding-left: 0.75rem; padding-right: 0.75rem; }
  .nt-pane-head,
  .nt-pane-body,
  .nt-actions { padding-left: 0.75rem; padding-right: 0.75rem; }
}

/* ── Task 7: the customer ledger ──────────────────────────────────────────
   One column of dates with a balance running down the side, and the head that
   says who the buyer is before you read it. */

/* `.nt-ledger-row` was asserted by the statement's tests and styled by
   nothing: the striped table carried it. Now that the pane renders the same
   row it earns a rule of its own — a quiet top border so a run of dates reads
   as a column rather than a block, and figures that line up. */
.nt-ledger .nt-ledger-row > td { border-top: 1px solid var(--nt-line); }
.nt-ledger .nt-ledger-row .nt-num { font-variant-numeric: tabular-nums; }

/* A date, a rupee figure and a chip are each one thing and read badly broken
   over three lines. The entry is the only cell with anything to give, so it
   is handed the width the others do not need. */
.nt-ledger td:first-child,
.nt-ledger th:first-child { white-space: nowrap; }
.nt-ledger .nt-num { white-space: nowrap; }
.nt-ledger th:nth-child(2) { width: 45%; }

/* Brick only when the customer is under. A balance in their favour is money
   we are holding, not a number anybody has to go and do something about. */
.nt-ledger-balance--bad { color: var(--nt-brick); }

/* The delivered tick / not-yet-delivered chip column: as narrow as its
   content, and never the reason the table scrolls. */
.nt-ledger-mark { width: 1%; white-space: nowrap; }

/* How the three tiles join up, said once under them. */
.nt-ledger-note {
  margin: 0.6rem 0 0.9rem;
  color: var(--nt-muted);
  font-size: 0.8125rem;
}

.nt-ledger-note span { font-variant-numeric: tabular-nums; }

/* Paging runs oldest block first, because a running balance can only be
   computed forwards; the strip says which entries are on screen so the
   direction of the two links is never a guess. */
.nt-ledger-pager {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 0.6rem;
  color: var(--nt-muted);
  font-size: 0.8125rem;
}

.nt-ledger-range { font-variant-numeric: tabular-nums; }
.nt-ledger-steps { display: flex; gap: 0.9rem; }

/* Three tiles across the pane rather than the four-across money strip, and
   they wrap before they squeeze a rupee figure off its own tile. */
.nt-detail-body .nt-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }

@media (max-width: 420px) {
  .nt-detail-body .nt-tiles { grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr)); }
}

/* The pane head with five label chips on it. They cannot ride in the 40% slot
   the two-chip head allowed, so this head wraps and the chips take the row
   under the name — the shape the phone breakpoint already gives every pane
   head, applied at every width because there is more to say here. */
.nt-thread-head--wide { flex-wrap: wrap; }

.nt-thread-head--wide .nt-thread-tags {
  order: 3;
  flex: 1 1 100%;
  max-width: none;
  justify-content: flex-start;
  margin-top: 0.15rem;
}

/* The two things staff come to a customer to do, and the two icon links the
   head already carried, in one group that does not wrap between them. */
.nt-head-actions {
  flex: none;
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

/* `.nt-field` and `.nt-field-hint` are the first two rules of spec §2.7's field
   system, landing here because this is the first screen that owes a label and a
   hint to every control it offers (§5.1, §5.4). Task 12 builds the rest of it —
   `--need`, `--warn` and the markers on the label — over these. */
.nt-field {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  margin-bottom: 0.6rem;
}

.nt-field > .form-label {
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--nt-ink-2);
}

.nt-field-hint {
  margin: 0;
  color: var(--nt-muted);
  font-size: 0.75rem;
}

/* Need and doubt, on the field itself (spec §5.3). `--need` is a value the
   approval will refuse without and the day never read; `--warn` is a value that
   is there but suspect, and its hint says why. The ring is on the control
   rather than the box, so a field's state survives sitting in a grid cell next
   to another one. */
.nt-field--warn > .form-control,
.nt-field--warn > .form-select { border-color: var(--nt-brick); }

/* A tick is a control too: it sits one level deeper, inside `.nt-check`, so the
   child combinator above walks straight past it and "Book it anyway" — the one
   field on the card that answers a duplicate — wore no ring at all. */
.nt-field--warn .nt-check .form-check-input { border-color: var(--nt-brick); }

.nt-field--warn > .nt-field-hint { color: var(--nt-brick); }

/* The marker the label wears so the state is readable without colour. */
/* A tick is a label beside its box, not above it. */
.nt-field--check .nt-check { display: flex; align-items: center; gap: 0.4rem; }
.nt-field--check .nt-check .form-label { font-weight: 600; }
/* ---- Expenses by day (spec §6.3) ----------------------------------------- */

/* A list and the thing it opens. The list is narrow on purpose — a day, its
   stops and one figure — and the pane takes the rest; under the tab bar's
   width they stack, list first, because the list is how the pane is chosen. */
.nt-two {
  display: grid;
  grid-template-columns: minmax(0, 23rem) minmax(0, 1fr);
  gap: 1rem;
  align-items: start;
}

.nt-two > * { min-width: 0; }

@media (max-width: 860px) {
  .nt-two { grid-template-columns: minmax(0, 1fr); }
}

/* Four columns inside a 23rem pane, and on a phone inside the whole 375px of
   it: the day, its stops, what it cost and "N to decide". The base
   `.table-scroll` box sets no overflow, so without this the waiting chip is
   simply cut off at the right-hand edge — the one cell that says there is
   something to do here. It scrolls, as every other table this app puts in a
   scroll box does. */
.nt-two .table-scroll { overflow-x: auto; }

/* Four tiles read as a strip over the two panes rather than as a column beside
   them, so they get the width the pane grid does not. */
.nt-tiles--wide { margin-bottom: 1rem; }

/* Four across a phone is four columns of nothing: `₹1,240` wraps under its own
   label and the note beneath it becomes a column of single words. Two and two. */
@media (max-width: 575.98px) {
  .nt-tiles--wide { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* A date is one word and a figure is one word: neither may wrap the list into
   three lines inside a column this narrow. The stops are what give. */
/* The whole row opens the day: the link is in the date cell and stretched over
   the row, which is what makes the cells to its right clickable too. */
.nt-xday { position: relative; }
/* Bootstrap paints a table row through its cells, so the standing day is
   marked on the cells or it is not marked at all. */
.nt-xday:hover > td { background-color: var(--nt-wash); }
.nt-xday.is-on > td { background-color: var(--nt-wash-yolk); }
/* The day as a tree: one node per stop, its rows indented under a rule so the
   eye can see which spend hangs on which stop without reading a word. */
/* What, how much, and what is left to do about it — the same three columns a
   proposal and a booked spend both answer in. */

/* Where the spend is decided: the whole width under the three columns of the
   row it belongs to, so the questions sit beneath the reading they are about
   rather than beside it in a 90px slot. */
/* What the button will write, on its own line and leading the strip: a
   sentence squeezed between the reject disclosure and the fields is a sentence
   with its last four words cut off. */
/* The form takes the strip's full width and stacks: the fields, then the one
   primary button at the right-hand end of them. */
/* As many field columns as the pane is wide enough for, and never fewer than
   one: the pane is 600-odd pixels at 1280 and a single column at 375. */
/* ------------------------------------------------------------------ *
 * Approvals, the overview (spec §6.4)
 *
 * Four lists and the card they point at. Nothing here decides anything
 * except the card, so the rows are links first: a whole row is the
 * target, and the only ink that competes with the name is the figure it
 * is waiting on.
 * ------------------------------------------------------------------ */

/* This week's decisions over this week's arrivals: the figure on the left,
   the bar and the two lines that qualify it on the right. Below 34rem the
   figure goes above the bar rather than squeezing it to nothing. */
/* One bar, filled left to right. The fill is an element rather than a
   gradient so its width is the number and a screen reader is told the same
   number through the track's own role. */
.nt-bar {
  height: 0.625rem;
  border-radius: 999px;
  background-color: var(--nt-wash);
  border: 1px solid var(--nt-line);
  overflow: hidden;
}

.nt-bar > i {
  display: block;
  height: 100%;
  background-color: var(--nt-leaf);
}

/* Reports' cost-per-egg bar is the one mark in the console whose colour is a
   verdict rather than an identity (spec §6.6): the ₹0.50 and ₹1 lines, in the
   status tokens. All three are written out — a default that happens to mean
   "good" is a good nobody chose — and the pane's note says the exception out
   loud so a reader never reads leaf here as "the community series". */
.nt-bar--leaf > i { background-color: var(--nt-leaf); }
.nt-bar--warn > i { background-color: var(--nt-warn); }
.nt-bar--brick > i { background-color: var(--nt-brick); }

/* The bar column is the one that gives: three columns of figures keep their
   width and the picture takes what is left. */
.nt-econ-bar { width: 34%; }

/* The panes stack inside their column of .nt-grid3. */
/* A list of rows inside a pane: no rule above the first or below the last,
   because the pane's own edge is already there. */
/* Avatar, the two lines that name the row, and the figure with its chip.
   The middle column is the one that gives, so a long name truncates rather
   than pushing the amount off the pane. */
.nt-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 0 0.7rem;
  align-items: center;
  padding: 0.6rem 1.1rem;
  color: var(--nt-ink);
  text-decoration: none;
}

a.nt-row:hover,
a.nt-row:focus-visible { background-color: var(--nt-wash); }

/* The row the card on the right is showing. */
.nt-row.is-on { background-color: var(--nt-wash-yolk); }
/* A feed row is not a link and must not offer the hover of one. */
/* The search above Needs a home: the labelled box, then the button beside it
   at the bottom of the field so the two baselines agree. */
/* The card is the only element on the screen carrying the shadow: it is the
   one thing here that writes anything. */
/* ---- The decision card (spec §5, §6.4) ----------------------------------- */

/* Three zones in one order, always: what it is, what was read, what will be
   booked. The zones are separated by a hairline rather than by boxes — the card
   is one object and a reviewer reads it top to bottom. */
/* The heading of a zone: quiet, small caps, and never competing with the card's
   own title. */
.nt-book  { padding: 0.85rem 1.1rem; }
/* The message itself, in the shape a message has everywhere else in the app. */
.nt-quote {
  margin: 0.6rem 0 0;
  padding: 0.55rem 0.7rem;
  background-color: var(--nt-wash-yolk);
  border-radius: var(--nt-r-ctl);
  font-size: 0.875rem;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
/* Spec §2.7: the field grid. `auto-fit` rather than a fixed column count, so
   the card reads as one column on a phone and two or three in the pane. */
.nt-formgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 0 0.9rem;
}
/* The action bar at the foot of the card, and the only one on it: the reject
   disclosure on the left, the sentence saying what the click writes, the
   primary button on the right. The sentence leads its own line — squeezed
   between a disclosure and two buttons in a third of a page it loses its last
   four words. */
.nt-book .nt-actions {
  margin: 0.4rem -1.1rem -0.85rem;
  border-radius: 0 0 var(--nt-r-pane) var(--nt-r-pane);
}

/* Printed primary-first and read primary-last. The default submit of a form is
   the first one in the document, and on a payment card that has to be "Record
   payment" rather than the FIFO split beside it — so the bar reverses here and
   nowhere else, leaving the DOM to say which button Return presses and the CSS
   to say where each one sits. */
.nt-book .nt-actions-buttons {
  flex-direction: row-reverse;
  /* `flex-start` is the right-hand edge once the row is reversed, and that is
     where a bar three buttons deep has to wrap against: the card is a third of
     a page and the third button drops to a line of its own. */
  justify-content: flex-start;
}
/* Every other buyer one message named, as a row each with its own four fields.
   It scrolls inside its own box: five columns of controls do not fit a third of
   a page, and the card must not widen the screen to hold them. */
/* A label that is read aloud and not seen: the column head carries the visible
   name, and this is the per-row half of it that a screen reader needs. Never an
   `aria-label` (spec §5.1) — an attribute is not a label. */
/* A pair inside the decision card is one column whatever the viewport says: the
   pane is a third of a screen wide and the media query above is about the page,
   not about this box — two columns in 320px wraps a buyer's name one letter to
   a line. */
/* ---- Money (spec §6.5) ---------------------------------------------------
   Two panes: what came in on the left, what to do about one of them on the
   right. The list rows are `.nt-row`, which the overview already ships; only
   the pane's own parts are new. */

/* The re-match rides in the head's controls beside the city segment, so its
   bottom margin — which spaced it under the sweep facts on Approvals — goes. */
/* Who this money is from, under the amount in the pane head. */
/* What a payment paid for. The two figures are tabular so a column of rupees
   reads down rather than across. */
/* A floor under the table and under the column that names the order, so the
   pane scrolls sideways rather than squeezing "1 × Native Table Brown Eggs 12
   Pack" to one word a line inside a 375px phone. `.nt-two .table-scroll` is the
   box that does the scrolling. */
/* The three facts a receipt states, read-only: they are the evidence a buyer
   is being chosen against, not fields to key over. */
.nt-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  gap: 0.5rem 0.9rem;
  margin: 0 0 0.75rem;
}

.nt-facts dt { font-size: 0.75rem; font-weight: 600; color: var(--nt-muted); }
.nt-facts dd { margin: 0; font-weight: 600; font-variant-numeric: tabular-nums; }

/* The decision form spans the pane body and the bar at its foot, so it must
   not introduce a box of its own between them. */
/* The pane's bar reads receipt on the left, primary on the right, and it has to
   go on reading that way when the money came in as cash and there is no receipt
   to link: with one child left, `space-between` would walk the primary over to
   the left, so the right-hand group pins itself rather than being held there by
   an empty span. */
/* ---- Reports: the chart kit (spec §6.6) ---------------------------------- */

/* Two filters on one line above the panes, in the order they narrow: which
   city, then how far back. */
.nt-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 1rem;
}

/* Two panes across a desktop, one across a phone. The charts are drawn to a
   viewBox and take whatever width they are given, so the breakpoint is about
   how many questions fit side by side and never about the SVG. */
.nt-grid2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
  align-items: start;
}

.nt-grid2 > * { min-width: 0; }

@media (max-width: 860px) {
  .nt-grid2 { grid-template-columns: minmax(0, 1fr); }
}

/* Each pane is its own Turbo frame so a Table toggle re-renders one pane and
   leaves the other five where they were — and a frame is inline until told. */
.nt-chart-pane,
.nt-grid2 > turbo-frame { display: block; }

/* A pane wide enough for the question it asks. Six columns of community inside
   half of 1,280px puts the Members column off the pane, and a column nobody can
   see is a column that is not there. */
.nt-grid2 > .nt-pane-wide { grid-column: 1 / -1; }

/* The SVG carries the aspect ratio; the box only says how wide it may be. */
.nt-chart { margin: 0.35rem 0 0; }

.nt-chart-svg {
  display: block;
  width: 100%;
  height: auto;
  /* Every length inside the viewBox is in these units, so this one declaration
     is the type scale of every chart on the screen. */
  font-size: 12px;
  font-family: var(--nt-body);
  font-variant-numeric: tabular-nums;
}

/* Ink, never a series colour: a number painted in the colour of the bar it
   belongs to is a number whose contrast nobody can check. */
.nt-chart-tick { fill: var(--nt-ink-3); }
.nt-chart-label { fill: var(--nt-ink-2); }
.nt-chart-value,
.nt-chart-total { fill: var(--nt-ink-2); font-weight: 600; }

/* Recessive on purpose. The grid is there to be measured against, not read;
   the axis is one line darker because it is the zero everything stands on. */
.nt-chart-grid { stroke: var(--nt-line); stroke-width: 1; }
.nt-chart-axis { stroke: var(--nt-rule); stroke-width: 1; }

/* Every mark is outlined against the pane it sits on. The pale end of the
   sequential ramp is 1.3:1 against `--nt-shell` — a bar you cannot find the
   edge of is a bar you cannot read the length of — and the fold's colour is
   little better. A hairline is the fix that costs no palette change: the fill
   still carries identity, the rule carries the edge. `crispEdges` because one
   viewBox unit is around half a device pixel here, and half a pixel of
   anti-aliased rule is a smudge rather than an edge.

   The child combinator on purpose: the hatch pattern's own background rect
   lives inside `<defs>` and must not be drawn as a mark. */
.nt-chart-svg > rect {
  stroke: var(--nt-rule);
  stroke-width: 1;
  shape-rendering: crispEdges;
}

/* Identity is never colour alone: two series or more and the legend is not
   optional. One series has the pane's own h3 and needs none. */
.nt-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.9rem;
  margin-bottom: 0.35rem;
  font-size: 0.8125rem;
  color: var(--nt-ink-2);
}

.nt-legend-key { display: inline-flex; align-items: center; gap: 0.35rem; }

.nt-legend-key i {
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 3px;
  /* The same hairline the marks wear, for the same reason: a swatch of
     `--nt-seq-1` on the pane is otherwise a swatch of the pane. */
  box-shadow: inset 0 0 0 1px var(--nt-rule);
}

/* What the chart cannot say about itself: which orders it counted, what the
   unit is, and whether the range above applies to it. */
.nt-chart-note { margin: 0.5rem 0 0; font-size: 0.8125rem; color: var(--nt-ink-3); }

/* An axis with no marks under it is a chart claiming to have been drawn. */
.nt-chart-empty { margin: 0.6rem 0; color: var(--nt-muted); }

.nt-chart-pane .table { margin-bottom: 0; }

/* `.nt-num` on the table itself is how a table of money columns buys tabular
   figures in one declaration — but that class also flushes text right, and
   `text-align` inherits, so it flushed the label column with them: a column of
   months and age bands hugging the figures beside it, ragged down its left. The
   row's own header is a word and the heading over it is a word, and words are
   read from the left edge. */
.nt-chart-pane .table.nt-num th[scope="row"],
.nt-chart-pane .table.nt-num thead th:first-child { text-align: left; }
/* The same words are not figures, so they stay in the body face. */
.nt-chart-pane .table.nt-num th[scope="row"],
.nt-chart-pane .table.nt-num thead th { font-family: var(--nt-font-body); }

/* Four pills — All cities and the three — are wider than 375px of phone, and a
   segmented control that overflows takes the whole document with it: the page
   itself starts scrolling sideways. Inside a column that may be zero wide, the
   control fills the row and its links wrap into it instead. */
@media (max-width: 575.98px) {
  .nt-filters { display: grid; grid-template-columns: minmax(0, 1fr); }
  .nt-filters .nt-seg { display: flex; flex-wrap: wrap; }

  /* The viewBox is 520 units wide inside about 310px of phone, so every length
     in the chart is drawn at roughly 0.6 — and a 12-unit tick label lands at
     seven device pixels, which is a shape rather than a number. The type scale
     is one declaration (`.nt-chart-svg`'s own font-size), so one override buys
     the whole chart ten legible pixels back. */
  .nt-chart-svg { font-size: 17px; }
}

/* Six channels of ₹38,000.00 is wider than half a desktop and all of a phone.
   The base `.table-scroll` sets no overflow, so without this the Total column
   is simply cut off — the one column somebody opened the table view for. It
   scrolls, as the ledger's and the day's tables already do. */
.nt-chart-pane .table-scroll { overflow-x: auto; }
.nt-chart-pane tbody th { white-space: nowrap; }

/* And the Total column stays. Scrolling is the affordance nobody sees: at rest
   the table shows Month, Community, Solo — and the column the reader opened the
   table view for is off the right edge with nothing to say it is there. The
   last column is pinned to that edge instead, and its rule is the seam that
   says the middle of the table has slid under it. */
/* `.table` clips its own rounded corners with `overflow: hidden`, and a hidden
   box *is* a scroll container: it becomes the scrollport a sticky cell inside
   it sticks to, and that scrollport never scrolls, so the cell below would pin
   to nothing and ride off the edge exactly as it did before. `clip` clips the
   same corners without being scrollable, and the cell pins to the
   `.table-scroll` around the table, which is the box that actually moves. */
.nt-chart-pane .table { overflow: clip; }

.nt-chart-pane th:last-child,
.nt-chart-pane td:last-child {
  position: sticky;
  right: 0;
  background: var(--nt-shell);
  box-shadow: -1px 0 0 var(--nt-line);
}

/* The sheet page (Task 11): head, action bar, rows left and a side column. */
.nt-sheet-head { padding: 1rem; margin-bottom: .75rem; }
.nt-sheet-counts { display: flex; flex-wrap: wrap; gap: 1.25rem; margin: .5rem 0; }
.nt-sheet-counts dt { font-weight: 400; font-size: .8rem; color: var(--bs-secondary-color); }
.nt-sheet-counts dd { margin: 0; font-weight: 600; }
.nt-sheet-inline-form { display: inline-flex; align-items: center; gap: .5rem; margin: .25rem .75rem .25rem 0; }
.nt-sheet-inline-form .form-label { margin: 0; }
.nt-sheet-inline-form .form-control { width: auto; }
.nt-sheet-grid { display: grid; grid-template-columns: minmax(0, 1fr) 20rem; gap: 1rem; }
.nt-sheet-side:empty { display: none; }
.nt-sheet-grid:has(.nt-sheet-side:empty) { grid-template-columns: minmax(0, 1fr); }
@media (max-width: 860px) { .nt-sheet-grid { grid-template-columns: minmax(0, 1fr); } }
/* The agent panel on the sheet (Task 24): the log, the diff, the form. */
.nt-agent { padding: .75rem; margin-top: 1rem; }
.nt-agent .nt-msg { max-width: none; margin: 0; padding: .5rem .6rem; border-radius: .5rem; background: var(--bs-tertiary-bg); font-size: .85rem; }
.nt-agent-body p { margin: .25rem 0; }
.nt-agent-applied, .nt-agent-cost { margin: .25rem 0 0; font-size: .75rem; color: var(--bs-secondary-color); }
/* Rows typed on the sheet (Task 12). The empty note hides once a row exists. */
.nt-sheet:has(#sheet_rows tr) .nt-sheet-empty { display: none; }
.nt-sheet .nt-sheet-unit { min-width: 6rem; }
.nt-sheet .nt-sheet-qty { width: 4.5rem; margin-left: auto; }
.nt-sheet-row-actions { white-space: nowrap; }
.nt-sheet-row-actions form { display: inline-flex; align-items: center; gap: .35rem; margin: 0 .25rem .25rem 0; vertical-align: middle; }
.nt-sheet-special { display: inline-flex; align-items: center; gap: .35rem; font-size: .8rem; color: var(--bs-secondary-color); }
.nt-sheet-special .form-control { width: 5rem; }
.nt-sheet-row-actions .nt-note { white-space: normal; margin: .25rem 0 0; }

/* ---- The Order Book (Task 13; History's filter bar, SPA Task 19) ------- */
.nt-book { padding: 16px; max-width: 1200px; }
.nt-book-empty { margin: 0; color: var(--nt-muted); font-size: .875rem; }
.nt-book-filters { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 2px 0 10px; }
.nt-book-filter-icon { display: flex; color: var(--nt-ink-2); }
.nt-book-filter {
  display: flex; align-items: center; gap: 6px; height: 30px; padding: 0 8px; margin: 0;
  border: 1px solid var(--nt-rule); border-radius: 7px; background: var(--nt-shell);
  font: 500 12.5px var(--nt-font-body); color: var(--nt-muted); white-space: nowrap;
}
.nt-book-filter:focus-within { border-color: var(--nt-ink); background: var(--nt-wash-yolk); }
.nt-book-filter input, .nt-book-filter select {
  border: none; background: transparent; font: 600 12.5px var(--nt-font-body); color: var(--nt-ink); padding: 0; outline: none;
}
.nt-book-filter-go {
  height: 30px; padding: 0 12px; border: 1px solid var(--nt-rule); border-radius: 7px;
  background: var(--nt-shell); font: 600 12.5px var(--nt-font-body); color: var(--nt-ink); cursor: pointer;
}
.nt-book-filter-go:hover { background: var(--nt-wash); }
.nt-book-summary { margin-left: auto; font-size: 12px; color: var(--nt-muted); }
.nt-book-history { display: block; --nt-book-cols: 112px minmax(0, 1fr) 104px 150px 104px 76px 160px 18px; }
.nt-book-history.nt-book-open--money { --nt-book-cols: 112px minmax(0, 1fr) 104px 150px 104px 76px 220px 160px 18px; }
.nt-book-off { color: var(--nt-muted); }
.nt-book-bar--history { background: var(--nt-carton); }
.nt-book-flag--neutral { color: var(--nt-ink-2); background: var(--nt-carton); }
.nt-book-history .nt-note { margin: 0 0 8px; }

/* ---- The Order Book: tabs and the Open lines (SPA Task 18, D7) ---------- */
.nt-book { max-width: 1440px; }
.nt-book-tabs { display: flex; gap: 22px; border-bottom: 1px solid var(--nt-line); margin: 4px 0 10px; }
.nt-book-tab {
  display: flex; align-items: center; gap: 7px; height: 36px; padding: 0 2px; margin-bottom: -1px;
  font: 600 14px var(--nt-font-body); color: var(--nt-muted); text-decoration: none;
  border-bottom: 2px solid transparent;
}
.nt-book-tab:hover { color: var(--nt-ink); }
.nt-book-tab.is-current { color: var(--nt-ink); border-bottom-color: var(--nt-spruce); }
.nt-book-tab-count {
  font: 600 11.5px var(--nt-font-mono); font-variant-numeric: tabular-nums; border-radius: 9px; padding: 1px 7px;
  background: var(--nt-carton); color: var(--nt-ink-2);
}
.nt-book-tab.is-current .nt-book-tab-count { background: var(--nt-spruce); color: var(--nt-shell); }

.nt-book-open { --nt-book-cols: 112px minmax(0, 1fr) 104px 150px 104px 76px 160px 18px; }
.nt-book-open--money { --nt-book-cols: 112px minmax(0, 1fr) 104px 150px 104px 76px 220px 160px 18px; }
.nt-book-cols, .nt-book-line {
  display: grid; grid-template-columns: var(--nt-book-cols); align-items: center; padding: 0 14px;
}
.nt-book-cols { height: 28px; font-size: 11.5px; font-weight: 600; color: var(--nt-ink-2); }
.nt-book-col--eggs { text-align: right; padding-right: 16px; }
.nt-book-group-head { display: flex; align-items: baseline; gap: 8px; padding: 12px 2px 6px; margin: 0; }
.nt-book-group-label { font-family: var(--nt-font-display); font-size: 14px; font-weight: 700; color: var(--nt-ink); }
.nt-book-group-sub { font: 400 12px var(--nt-font-body); color: var(--nt-muted); }
.nt-book-lines { border: 1px solid var(--nt-rule); border-radius: var(--nt-r-pane); background: var(--nt-shell); overflow: hidden; }
.nt-book-line {
  min-height: 50px; border-bottom: 1px solid var(--nt-line); color: var(--nt-ink); text-decoration: none;
}
.nt-book-line:last-child { border-bottom: none; }
.nt-book-line:hover { background: var(--nt-wash); color: var(--nt-ink); }
.nt-book-line:focus-visible { outline: 2px solid var(--nt-saffron); outline-offset: -2px; }
.nt-book-line.has-proposal { background: var(--nt-saffron-wash); box-shadow: inset 3px 0 0 var(--nt-saffron); }
.nt-book-cell { min-width: 0; }
.nt-book-name { display: block; font-size: 13.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nt-book-date, .nt-book-orders-sub { display: block; font-size: 12px; color: var(--nt-muted); }
.nt-book-orders-sub { font-size: 11.5px; }
.nt-book-num { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-weight: 600; font-size: 13px; }
.nt-book-cell--eggs { text-align: right; padding-right: 16px; }
.nt-book-pill {
  display: inline-flex; align-items: center; font-size: 11.5px; font-weight: 600; border-radius: 10px;
  padding: 1px 8px; white-space: nowrap; border: 1px solid transparent;
}
.nt-book-pill--community, .nt-book-status--delivered { color: var(--nt-info); background: var(--nt-wash-info); }
.nt-book-pill--popup { color: var(--nt-warn); background: var(--nt-wash-warn); }
.nt-book-pill--one-off { color: var(--nt-ink-2); background: var(--nt-shell); border-color: var(--nt-rule); }
.nt-book-status--draft { color: var(--nt-ink-2); background: var(--nt-shell); border: 1px dashed var(--nt-edge); }
.nt-book-status--open, .nt-book-status--settled { color: var(--nt-ok); background: var(--nt-wash-ok); }
.nt-book-status--closed { color: var(--nt-shell); background: var(--nt-ink-2); }
.nt-book-status--cancelled { color: var(--nt-muted); background: var(--nt-wash); }
.nt-book-cell--cutoff { font-size: 12.5px; color: var(--nt-ink-2); }
.nt-book-countdown { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-weight: 600; color: var(--nt-ink); }
.nt-book-countdown.is-soon { color: var(--nt-warn); }
.nt-book-when.is-warn { color: var(--nt-bad); font-weight: 600; }
.nt-book-cell--money { display: flex; flex-direction: column; gap: 4px; padding-right: 18px; }
.nt-book-money-figs {
  display: flex; justify-content: space-between; font-family: var(--nt-font-mono);
  font-variant-numeric: tabular-nums; font-size: 12px;
}
.nt-book-got { color: var(--nt-ok); font-weight: 600; }
.nt-book-due { color: var(--nt-bad); }
.nt-book-allin { color: var(--nt-muted); }
.nt-book-bar { display: flex; height: 6px; border-radius: 3px; overflow: hidden; background: var(--nt-wash-bad); }
.nt-book-bar-fill { display: block; height: 100%; background: var(--nt-ok); }
.nt-book-cell--flags { display: flex; flex-wrap: wrap; gap: 4px; }
.nt-book-flag { display: inline-flex; font-size: 11.5px; font-weight: 600; border-radius: 10px; padding: 1px 8px; white-space: nowrap; }
.nt-book-flag--bad { color: var(--nt-bad); background: var(--nt-wash-bad); }
.nt-book-flag--warn { color: var(--nt-warn); background: var(--nt-wash-warn); }
.nt-book-proposal {
  display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 600; white-space: nowrap;
  color: var(--nt-shell); background: var(--nt-spruce); border-radius: 10px; padding: 1px 8px;
}
.nt-book-proposal-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--nt-saffron); }
.nt-book-noflag { font-size: 11.5px; color: var(--nt-muted); }
.nt-book-cell--go { color: var(--nt-muted); display: flex; }
.nt-book-open-empty { padding: 24px 2px; }

/* A phone: each line is a small card — name and pills on top, figures below. */
/* A desk narrower than the mockup's 1440: the fixed columns shrink so the
   sheet's name keeps room (at 1280 the 1440 widths left it ~20px). */
@media (min-width: 860.02px) and (max-width: 1439.98px) {
  .nt-book-open, .nt-book-history { --nt-book-cols: 96px minmax(150px, 1fr) 92px 118px 88px 60px 124px 18px; }
  .nt-book-open--money, .nt-book-history.nt-book-open--money { --nt-book-cols: 96px minmax(150px, 1fr) 92px 118px 88px 60px 170px 124px 18px; }
}
@media (max-width: 860px) {
  .nt-book-cols { display: none; }
  .nt-book-line, .nt-book-open--money .nt-book-line {
    grid-template-columns: auto auto minmax(0, 1fr) 14px;
    grid-template-areas: "sheet sheet sheet go" "kind status cutoff go" "orders eggs flags go" "money money money go";
    gap: 6px 10px; padding: 10px 12px;
  }
  .nt-book-cell--kind { grid-area: kind; }
  .nt-book-cell--sheet { grid-area: sheet; }
  .nt-book-cell--status { grid-area: status; }
  .nt-book-cell--cutoff { grid-area: cutoff; text-align: right; }
  .nt-book-cell--orders { grid-area: orders; }
  .nt-book-cell--eggs { grid-area: eggs; text-align: left; padding-right: 0; }
  .nt-book-cell--eggs::after { content: " eggs"; font-family: var(--nt-font-body); font-weight: 400; color: var(--nt-muted); }
  .nt-book-cell--money { grid-area: money; padding-right: 0; }
  .nt-book-cell--flags { grid-area: flags; justify-content: flex-end; }
  .nt-book-cell--go { grid-area: go; align-self: center; }
  .nt-book-tabs { gap: 18px; }
}

/* Record payment (Task 17): the sheet's side panel and the customer's page. */
.nt-sheet-side:has(> #sheet_payment:empty:only-child) { display: none; }
.nt-sheet-grid:has(.nt-sheet-side > #sheet_payment:empty:only-child) { grid-template-columns: minmax(0, 1fr); }
.nt-pay-page { max-width: 36rem; padding: 1rem; }
.nt-pay-pane { padding: 1rem; }
.nt-pay-head { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.nt-pay-head h1, .nt-pay-head h2 { font-size: 1.1rem; margin: 0; }
.nt-pay-form { display: grid; gap: .75rem; }
.nt-pay-form fieldset { border: 0; padding: 0; margin: 0; }
.nt-pay-form legend { font-size: .85rem; font-weight: 600; margin-bottom: .25rem; }
.nt-pay-row-head { margin: .25rem 0; font-size: .85rem; color: var(--nt-muted, inherit); }
.nt-pay-line { display: grid; grid-template-columns: auto 1fr auto; gap: .5rem; align-items: center; }
.nt-pay-fields { display: grid; gap: .5rem; }
.nt-pay-radios label { display: block; }
.nt-pay-wa-img { max-width: 100%; max-height: 16rem; border-radius: .25rem; }
.nt-pay-lines summary { list-style: none; cursor: pointer; }
.nt-pay-lines ul { margin: .25rem 0 0; padding-left: 1rem; font-size: .8rem; }

/* ---- The expense register (Task 18) ---------------------------------- */
.nt-xreg-filters { display: flex; flex-wrap: wrap; gap: .5rem; align-items: flex-end; margin-bottom: 1rem; }
.nt-xreg-filters label { display: flex; flex-direction: column; font-size: .8rem; gap: .15rem; }
.nt-xreg td { vertical-align: top; }
.nt-xreg-form td { min-width: 7rem; }
.nt-xreg-cost { border: 0; margin: 0; padding: 0; }
.nt-xreg-total th, .nt-xreg-total td { font-weight: 600; }
.nt-xattach { display: inline-block; margin-right: .35rem; }

/* Task 19: what a sheet earned. */
.nt-sheet-econ { margin-top: 1rem; }
.nt-sheet-econ-list { display: grid; grid-template-columns: 1fr auto; gap: .25rem .75rem; margin: 0 0 .75rem; }
.nt-sheet-econ-list dd { margin: 0; }
.nt-sheet-econ-expenses { padding-left: 1rem; margin-bottom: .75rem; }

/* Task 20: the settlement panel and the verification highlight. */
.nt-sheet-settlement { margin-top: 1rem; }
.nt-sheet-verification li { font-size: .875rem; }
.nt-sheet tr.is-flagged > td { background: var(--nt-wash-warn); }

/* The public sheet (Task 27): a resident's order form, no rail, no JavaScript. */
.nt-public > .container { max-width: 32rem; }
.nt-note--good { color: var(--nt-leaf); font-weight: 500; }
.nt-public-qty { width: 4.5rem; margin-left: auto; }
.nt-public-link { word-break: break-all; }

/* ---- The till (Task 33; Phone-Till.dc.html): one phone screen for a pop-up
   stall. App bar, the sync strip, product tiles with −/+ at 44px, a Cash/UPI
   segment with the camera beside it, then a charge bar held at the bottom. ---- */
.nt-till-body { background: var(--nt-paper); color: var(--nt-ink); font-family: var(--nt-font-body); }
.nt-till { max-width: 480px; margin: 0 auto; padding: 14px 0 0; min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }
.nt-till-head { display: flex; align-items: center; gap: 10px; padding: 4px 16px 12px; }
.nt-till-mark path { fill: var(--nt-saffron); }
.nt-till-mark circle { fill: var(--nt-saffron-wash); }
.nt-till-heading { flex: 1; min-width: 0; }
.nt-till-title { margin: 0; font-family: var(--nt-font-display); font-size: 19px; font-weight: 700; line-height: 1.15; }
.nt-till-sheet { margin: 0; font-size: 12.5px; color: var(--nt-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nt-till-net { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; border-radius: 14px; font-size: 12px; font-weight: 700; }
.nt-till-net.is-online { background: var(--nt-wash-ok); color: var(--nt-ok); }
.nt-till-net.is-offline { background: var(--nt-wash-warn); color: var(--nt-warn); }
.nt-till-picker { display: grid; gap: 4px; padding: 0 16px 10px; }
.nt-till-sync {
  margin: 0 16px; display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 0 14px;
  border: 1px dashed var(--nt-warn); border-radius: 12px; background: var(--nt-wash-warn); color: var(--nt-warn);
  font: 600 14px var(--nt-font-body); text-align: left; cursor: pointer;
}
.nt-till-sync.is-clear { border: 1px solid var(--nt-line); background: var(--nt-shell); color: var(--nt-muted); font-weight: 500; }
.nt-till-pending { font-variant-numeric: tabular-nums; }
.nt-till-retry { margin-left: auto; font-size: 12.5px; text-decoration: underline; }
.nt-till-sync.is-clear .nt-till-retry { display: none; }
.nt-till-message { margin: 10px 16px 0; }
.nt-till-message[hidden] { display: none; }
.nt-till-products { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; padding: 14px 16px 0; }
.nt-till-product { background: var(--nt-shell); border: 1px solid var(--nt-rule); border-radius: 14px; padding: 11px; }
.nt-till-product.is-picked { border: 2px solid var(--nt-saffron); padding: 10px; }
.nt-till-product-top { display: flex; align-items: flex-start; justify-content: space-between; color: var(--nt-warn); }
.nt-till-badge {
  min-width: 30px; height: 30px; padding: 0 6px; border-radius: 15px; display: flex; align-items: center; justify-content: center;
  font: 600 15px var(--nt-font-mono); font-variant-numeric: tabular-nums; background: var(--nt-carton); color: var(--nt-ink-2);
}
.nt-till-product.is-picked .nt-till-badge { background: var(--nt-saffron); color: var(--nt-ink); }
.nt-till-product-name { margin-top: 8px; font-size: 15px; font-weight: 700; }
.nt-till-product-price { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-size: 14px; color: var(--nt-ink-2); }
.nt-till-steps { display: flex; gap: 8px; margin-top: 10px; }
.nt-till-step { flex: 1; height: 44px; display: flex; align-items: center; justify-content: center; border-radius: 10px; cursor: pointer; }
.nt-till-minus { border: 1px solid var(--nt-rule); background: var(--nt-shell); color: var(--nt-ink); }
.nt-till-minus:disabled { color: var(--nt-ink-3); cursor: default; }
.nt-till-plus { border: none; background: var(--nt-ink); color: var(--nt-shell); }
.nt-till-payrow { margin: 14px 16px 0; display: flex; align-items: center; gap: 10px; }
.nt-till-seg { flex: 1; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); background: var(--nt-carton); border-radius: 12px; padding: 3px; }
.nt-till-method { height: 44px; border: none; border-radius: 10px; background: transparent; color: var(--nt-ink-2); font: 700 15px var(--nt-font-body); cursor: pointer; }
.nt-till-method[aria-pressed="true"] { background: var(--nt-shell); color: var(--nt-ink); box-shadow: 0 1px 3px rgba(19, 32, 31, .2); }
.nt-till-camera {
  width: 52px; height: 50px; margin: 0; flex: none; display: flex; align-items: center; justify-content: center; cursor: pointer;
  border: 1.5px solid var(--nt-ink); border-radius: 12px; background: var(--nt-shell); color: var(--nt-ink);
}
.nt-till-camera[hidden] { display: none; }
.nt-till-camera.is-snapped { border: 2px solid var(--nt-ok); background: var(--nt-wash-ok); color: var(--nt-ok); }
.nt-till-photo-input { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.nt-till-camnote { margin: 8px 16px 0; font-size: 12.5px; color: var(--nt-ink-2); }
.nt-till-phone { display: grid; gap: 4px; margin: 14px 16px 0; font-size: 14px; }
.nt-till-totals { display: grid; grid-template-columns: repeat(5, 1fr); gap: 4px; margin: 14px 16px 0; }
.nt-till-stat { background: var(--nt-shell); border: 1px solid var(--nt-line); border-radius: 8px; padding: 6px 4px; text-align: center; }
.nt-till-stat dt { font-size: 11px; font-weight: 500; color: var(--nt-muted); }
.nt-till-stat dd { margin: 0; font-family: var(--nt-font-mono); font-weight: 600; font-variant-numeric: tabular-nums; }
.nt-till-history { margin: 20px 16px 16px; }
.nt-till-history-title { font-size: 14px; font-weight: 600; color: var(--nt-muted); margin: 0 0 6px; }
.nt-till-sales { list-style: none; padding: 0; margin: 0; }
.nt-till-sale { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; padding: 8px 0; border-bottom: 1px solid var(--nt-line); }
.nt-till-sale-time { color: var(--nt-muted); font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; }
.nt-till-sale-what { flex: 1; font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; }
.nt-till-sale-reason { flex-basis: 100%; color: var(--nt-muted); font-size: 14px; }
.nt-till-charge {
  position: sticky; bottom: 0; margin-top: auto; padding: 12px 16px calc(16px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--nt-line); background: var(--nt-shell);
}
.nt-till-charge[hidden] { display: none; }
.nt-till-chargeline { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 10px; }
.nt-till-linetext { font-size: 14px; color: var(--nt-ink-2); font-variant-numeric: tabular-nums; }
.nt-till-total { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-size: 26px; font-weight: 600; }
.nt-till-save {
  width: 100%; height: 60px; border: none; border-radius: 16px; font: 700 18px var(--nt-font-body);
  background: var(--nt-carton); color: var(--nt-ink-2); cursor: default;
}
.nt-till-save.is-ready { background: var(--nt-saffron); color: var(--nt-ink); cursor: pointer; }
.nt-till-save:focus-visible, .nt-till-step:focus-visible, .nt-till-method:focus-visible, .nt-till-sync:focus-visible {
  outline: 3px solid var(--nt-saffron-deep); outline-offset: 2px;
}
.nt-till-toast {
  position: fixed; left: 16px; right: 16px; bottom: 150px; max-width: 448px; margin: 0 auto; z-index: 20;
  background: var(--nt-ink); color: var(--nt-shell); border-radius: 12px; padding: 12px 14px; font-size: 14px;
}
.nt-till-toast[hidden] { display: none; }

/* ---------- The community page (D9, Task 24; Community.dc.html) ----------
   Five tiles, then the trend beside the map, then the groups beside the
   agent notes; one column on a phone. */
.nt-community-page { display: flex; flex-direction: column; gap: 12px; }
.nt-community-overview { display: flex; flex-direction: column; gap: 12px; }
.nt-community-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr)); gap: 10px; }
.nt-community-tile {
  display: block; color: var(--nt-ink); text-decoration: none;
  background: var(--nt-shell); border: 1px solid var(--nt-line); border-radius: 10px; padding: 11px 13px;
}
a.nt-community-tile--link { border-color: var(--nt-ink); }
a.nt-community-tile--link:hover { background: var(--nt-wash); color: var(--nt-ink); }
.nt-community-tile b { display: flex; justify-content: space-between; gap: 6px; font-size: 12px; font-weight: 600; color: var(--nt-muted); }
.nt-community-tile-open { color: var(--nt-link); }
.nt-community-tile-value { margin-top: 4px; font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-size: 22px; font-weight: 600; }
.nt-community-tile-note { margin-top: 2px; font-size: 12px; color: var(--nt-ink-2); font-variant-numeric: tabular-nums; }
.nt-community-pair { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; align-items: stretch; }
.nt-community-pair--trend { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); }
@media (max-width: 860px) {
  .nt-community-pair, .nt-community-pair--trend { grid-template-columns: minmax(0, 1fr); }
}
.nt-community-card { background: var(--nt-shell); border: 1px solid var(--nt-line); border-radius: 10px; padding: 12px 14px; min-width: 0; }
.nt-community-cardhead { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 8px; margin-bottom: 8px; }
.nt-community-h2 { margin: 0; font-family: var(--nt-font-display); font-size: 15px; font-weight: 700; }
.nt-community-cardsub { font-size: 12px; color: var(--nt-muted); font-variant-numeric: tabular-nums; }
.nt-community-bars { display: flex; align-items: flex-end; gap: 8px; height: 160px; margin: 0; padding: 0; list-style: none; border-bottom: 1px solid var(--nt-rule); }
.nt-community-bars li { flex: 1 1 0; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 4px; min-width: 0; }
.nt-community-bar-track { flex: 1 1 auto; width: 100%; max-width: 38px; display: flex; align-items: flex-end; }
.nt-community-bar { display: block; width: 100%; min-height: 2px; border-radius: 4px 4px 0 0; background: var(--nt-rule); }
.nt-community-bars li.is-last .nt-community-bar { background: var(--nt-saffron); }
.nt-community-bar-value { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-size: 11px; color: var(--nt-ink-2); }
.nt-community-bar-label { font-size: 11px; color: var(--nt-muted); white-space: nowrap; }
.nt-community-bars li.is-last .nt-community-bar-label { color: var(--nt-ink); font-weight: 600; }
.nt-community-map { padding: 0; overflow: hidden; min-height: 210px; display: flex; align-items: center; justify-content: center; background: var(--nt-wash); }
.nt-community-map .nt-empty { padding: 1rem; text-align: center; }
/* Leaflet's panes and controls carry z-index 400–1000; a stacking context of
   their own keeps them under the drawer, the menus and the top bar. */
.nt-overview-map-canvas { width: 100%; height: 100%; min-height: 210px; position: relative; z-index: 0; isolation: isolate; }
.nt-community-grouplist { list-style: none; margin: 0 0 8px; padding: 0; }
.nt-community-group { display: flex; align-items: center; gap: 9px; padding: 8px 0; border-bottom: 1px solid var(--nt-line); }
.nt-community-group-icon { width: 28px; height: 28px; flex: none; border-radius: 8px; display: flex; align-items: center; justify-content: center; background: var(--nt-wash-leaf); color: var(--nt-leaf); }
.nt-community-group-text { flex: 1; min-width: 0; }
.nt-community-group-name { font-size: 13px; font-weight: 600; }
.nt-community-group-sub { font-size: 12px; color: var(--nt-muted); }
.nt-community-group-form { margin: 0; }
.nt-community-btn {
  display: inline-flex; align-items: center; gap: 5px; height: 26px; padding: 0 9px;
  border: 1px solid var(--nt-rule); border-radius: 6px; background: var(--nt-shell); color: var(--nt-ink-2);
  font: 500 12px var(--nt-font-body); cursor: pointer; white-space: nowrap;
}
.nt-community-btn:hover { background: var(--nt-wash); color: var(--nt-ink); }
.nt-community-attach { display: flex; gap: 8px; align-items: center; }
.nt-community-notes-form textarea { font-size: 13px; line-height: 1.5; background: var(--nt-paper); resize: vertical; }
.nt-community-notes-foot { display: flex; align-items: center; gap: 8px; margin-top: 6px; font-size: 11.5px; color: var(--nt-muted); }
.nt-community-notes-foot span { flex: 1; }
.nt-community-list table { font-size: 13px; }
.nt-community-list-name a { font-weight: 600; }
.nt-community-list-sub { font-size: 11.5px; color: var(--nt-muted); margin-left: 4px; }
@media (max-width: 860px) {
  .nt-community-list { overflow-x: auto; }
}
/* The community's members (communities#members): a row per person, the
   name and groups, their status, their posts; stacked as a card under 640px. */
.nt-community-cardlink { margin-left: auto; font-size: 12px; font-weight: 600; }
.nt-members-summary { font-size: 13px; color: var(--nt-ink-2); font-variant-numeric: tabular-nums; }
.nt-members-filters { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.nt-members-filter {
  display: inline-flex; align-items: center; gap: 5px; height: 26px; padding: 0 10px;
  border: 1px solid var(--nt-rule); border-radius: 999px; background: var(--nt-shell); color: var(--nt-ink-2);
  font-size: 12px; font-weight: 500; text-decoration: none;
}
.nt-members-filter:hover { background: var(--nt-wash); color: var(--nt-ink); }
.nt-members-filter.is-on { border-color: var(--nt-ink); background: var(--nt-ink); color: var(--nt-shell); }
.nt-members-list { list-style: none; margin: 0; padding: 0; }
.nt-members-row {
  display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 0.9fr) minmax(0, 1.6fr) minmax(0, 0.8fr); gap: 4px 12px;
  align-items: center; padding: 8px 0; border-bottom: 1px solid var(--nt-line); font-size: 13px;
}
.nt-members-name { font-weight: 600; }
.nt-members-sub, .nt-members-note { font-size: 12px; color: var(--nt-muted); }
.nt-members-status { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; }
.nt-members-badge {
  display: inline-block; padding: 1px 8px; border: 1px solid var(--nt-line); border-radius: 999px;
  background: var(--nt-paper); color: var(--nt-ink-2); font-size: 11.5px; font-weight: 600; white-space: nowrap;
}
.nt-members-badge--customer { background: var(--nt-wash-leaf); border-color: var(--nt-edge-ok); color: var(--nt-ink); }
.nt-members-badge--team { background: var(--nt-wash); border-color: var(--nt-rule); color: var(--nt-ink); }
.nt-members-posts { text-align: right; font-size: 12px; color: var(--nt-ink-2); }
.nt-members-habit { font-size: 12.5px; color: var(--nt-ink); font-variant-numeric: tabular-nums; }
.nt-members-due {
  display: inline-block; margin-left: 4px; padding: 0 7px; border-radius: 999px; font-size: 11px; font-weight: 600;
  border: 1px solid var(--nt-rule); background: var(--nt-wash);
}
.nt-members-due--overdue { background: var(--nt-wash-brick); border-color: var(--nt-edge-bad); }
.nt-members-search { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 8px; }
.nt-members-search .form-control { flex: 1 1 14rem; max-width: 22rem; }
.nt-members-search .form-select { flex: 0 1 11rem; width: auto; }
.nt-members-clear { font-size: 12px; }
@media (max-width: 640px) {
  .nt-members-row { grid-template-columns: minmax(0, 1fr); padding: 10px 0; }
  .nt-members-posts { text-align: left; }
  .nt-members-posts .nt-members-sub { display: inline; }
}

/* ---------- The drawer (D2, Task 5) ----------
   One right-hand panel over a dimmed page: 440px (a page may ask for more
   through `data-drawer-width`), full height, full width on a phone. Hidden
   until drawer_controller.js adds `.is-open` after the frame loads. */
.nt-drawer-root { position: fixed; inset: 0; z-index: 60; pointer-events: none; }
.nt-drawer-scrim { position: absolute; inset: 0; background: var(--nt-scrim); opacity: 0; transition: opacity .16s ease; }
.nt-drawer {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(var(--nt-drawer-w, 440px), 100vw);
  display: flex; flex-direction: column;
  background: var(--nt-shell); border-left: 1px solid var(--nt-rule); box-shadow: var(--nt-drawer-shadow);
  transform: translateX(100%); visibility: hidden; transition: transform .18s ease, visibility 0s linear .18s;
}
.nt-drawer-root.is-open { pointer-events: auto; }
.nt-drawer-root.is-open .nt-drawer-scrim { opacity: 1; }
.nt-drawer-root.is-open .nt-drawer { transform: none; visibility: visible; transition: transform .18s ease; }
html.nt-drawer-open { overflow: hidden; }
.nt-drawer-panel { display: flex; flex-direction: column; min-height: 0; height: 100%; }
.nt-drawer-head { display: flex; align-items: flex-start; gap: 10px; padding: 14px 16px 12px; border-bottom: 1px solid var(--nt-line); }
.nt-drawer-badge {
  width: 30px; height: 30px; flex-shrink: 0; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  background: var(--nt-spruce); color: var(--nt-rail-ink);
}
.nt-drawer-badge .nt-icon { fill: var(--nt-saffron); }
.nt-drawer-titles { flex: 1; min-width: 0; }
.nt-drawer-title { margin: 0; font-family: var(--nt-font-display); font-size: 16px; font-weight: 700; line-height: 1.25; color: var(--nt-ink); }
.nt-drawer-sub { margin: 2px 0 0; font-size: 12px; line-height: 1.4; color: var(--nt-muted); }
.nt-drawer-esc {
  margin-top: 5px; padding: 2px 5px; border: 1px solid var(--nt-line); border-radius: 4px;
  background: none; color: var(--nt-muted); font-family: var(--nt-font-mono); font-size: 11px; box-shadow: none;
}
.nt-drawer-close {
  width: 30px; height: 30px; flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--nt-line); border-radius: 7px; background: var(--nt-shell); color: var(--nt-ink); cursor: pointer;
}
.nt-drawer-close:hover { background: var(--nt-wash); }
.nt-drawer-modes {
  display: grid; grid-auto-columns: minmax(0, 1fr); grid-auto-flow: column; gap: 3px;
  margin: 10px 16px; padding: 3px; border-radius: 8px; background: var(--nt-wash);
}
.nt-drawer-mode {
  display: flex; align-items: center; justify-content: center; height: 30px; border-radius: 6px;
  color: var(--nt-ink-2); font-size: 13px; font-weight: 600; text-decoration: none;
}
.nt-drawer-mode[aria-selected="true"] { background: var(--nt-shell); color: var(--nt-ink); box-shadow: 0 1px 2px rgba(10, 32, 30, .12); }
.nt-drawer-mode-key { margin-left: 5px; padding: 0; background: none; color: var(--nt-muted); font-family: var(--nt-font-mono); font-size: 10.5px; box-shadow: none; }
.nt-drawer-body { flex: 1; min-height: 0; overflow-y: auto; padding: 14px 16px; }
.nt-drawer-foot { border-top: 1px solid var(--nt-line); padding: 12px 16px; }
@media (max-width: 860px) {
  .nt-drawer { width: 100vw; border-left: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .nt-drawer, .nt-drawer-scrim, .nt-drawer-root.is-open .nt-drawer { transition: none; }
}

/* The toast slot (`#nt_toast`); Task 28 puts the Undo toast in it. */
.nt-toast-slot { position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%); z-index: 70; }
.nt-toast-slot:empty { display: none; }

/* ---------- The ⌘K palette and the keys card (D1, Task 6) ----------
   Mockup orderbook.py `palette()`: a 660px card 96px from the top over a
   dimmed page, groups of results with a lettered badge, the highlighted one
   on the lightest saffron, a foot with the keys and the count. Both are
   modal <dialog>s, so they sit above the drawer. */
.nt-palette-dialog, .nt-keys-help {
  margin: 0; padding: 0; border: 0; background: transparent; max-width: none; max-height: none;
  width: 100%; height: 100%; overflow: hidden;
}
.nt-palette-dialog::backdrop, .nt-keys-help::backdrop { background: var(--nt-scrim); }
.nt-palette {
  position: absolute; left: 50%; top: 96px; transform: translateX(-50%);
  width: min(660px, calc(100vw - 32px)); max-height: calc(100vh - 140px);
  display: flex; flex-direction: column;
  background: var(--nt-shell); border: 1px solid var(--nt-rule); border-radius: 14px;
  box-shadow: var(--nt-palette-shadow); overflow: hidden;
}
.nt-palette--page { position: static; transform: none; width: auto; max-height: none; margin-top: 12px; box-shadow: none; }
.nt-palette-search { display: flex; align-items: center; gap: 10px; margin: 0; padding: 14px 16px; border-bottom: 1px solid var(--nt-line); color: var(--nt-ink-2); }
.nt-palette-input {
  flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; box-shadow: none;
  font: 500 17px var(--nt-font-body); color: var(--nt-ink);
}
.nt-palette-esc {
  padding: 2px 6px; border: 1px solid var(--nt-rule); border-radius: 5px; background: var(--nt-shell);
  color: var(--nt-ink-2); font-family: var(--nt-font-mono); font-size: 11px; cursor: pointer; box-shadow: none;
}
.nt-palette-results { display: flex; flex-direction: column; min-height: 0; flex: 1; }
.nt-palette-list { padding: 6px 8px 8px; overflow-y: auto; min-height: 0; flex: 1; }
.nt-palette-group-title {
  padding: 8px 8px 4px; font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--nt-muted);
}
.nt-palette-item { display: flex; align-items: center; gap: 11px; padding: 7px 8px; border-radius: 8px; text-decoration: none; color: var(--nt-ink); }
.nt-palette-item[aria-selected="true"] { background: var(--nt-saffron-wash); }
.nt-palette-badge {
  width: 28px; height: 28px; flex-shrink: 0; border-radius: 7px; background: var(--nt-wash);
  display: flex; align-items: center; justify-content: center;
  color: var(--nt-ink-2); font-family: var(--nt-font-mono); font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.nt-palette-lines { flex: 1; min-width: 0; }
.nt-palette-label, .nt-palette-sub { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nt-palette-label { font-size: 13.5px; font-weight: 600; color: var(--nt-ink); }
.nt-palette-sub { font-size: 12px; color: var(--nt-muted); }
.nt-palette-empty { margin: 0; padding: 14px 8px; font-size: 13px; color: var(--nt-muted); }
.nt-palette-foot {
  display: flex; gap: 16px; padding: 9px 16px; border-top: 1px solid var(--nt-line); background: var(--nt-paper);
  font-family: var(--nt-font-mono); font-size: 11.5px; color: var(--nt-ink-2);
}
.nt-palette-count { margin-left: auto; font-variant-numeric: tabular-nums; }
.nt-search-page { max-width: 720px; padding: 18px; }
.nt-search-title { font-family: var(--nt-font-display); font-size: 20px; font-weight: 700; margin: 0 0 12px; }
.nt-search-form { display: flex; gap: 8px; }
.nt-keys-help-card {
  position: absolute; left: 50%; top: 96px; transform: translateX(-50%);
  width: min(440px, calc(100vw - 32px)); max-height: calc(100vh - 140px); overflow-y: auto;
  background: var(--nt-shell); border: 1px solid var(--nt-rule); border-radius: 14px; box-shadow: var(--nt-palette-shadow);
}
.nt-keys-help-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px; border-bottom: 1px solid var(--nt-line); }
.nt-keys-help-head form { margin: 0; }
.nt-keys-help-title { margin: 0; font-family: var(--nt-font-display); font-size: 16px; font-weight: 700; }
.nt-keys-help-list { margin: 0; padding: 8px 16px 14px; }
.nt-keys-help-list > div { display: flex; justify-content: space-between; gap: 12px; padding: 5px 0; font-size: 13px; }
.nt-keys-help-list dt { font-weight: 500; color: var(--nt-ink); }
.nt-keys-help-list dd { margin: 0; }
.nt-keys-help-list kbd {
  padding: 1px 6px; border: 1px solid var(--nt-rule); border-radius: 4px; background: var(--nt-shell);
  color: var(--nt-ink-2); font-family: var(--nt-font-mono); font-size: 11px; box-shadow: none;
}
@media (max-width: 860px) {
  .nt-palette { top: 16px; }
  .nt-palette-foot span:not(.nt-palette-count) { display: none; }
}

/* ---------- The shared NT Agent chat (Task 11; build.py bubble_*, diff_card, draft_card, chat) ---------- */
.nt-agent-chat { display: flex; flex-direction: column; min-height: 0; height: 100%; background: var(--nt-shell); }
.nt-agent-chat-head { display: flex; gap: 10px; align-items: flex-start; padding: 14px 16px 10px; }
.nt-agent-chat-heading { flex: 1; min-width: 0; }
.nt-agent-chat-title { margin: 0; font-family: var(--nt-font-display); font-size: 16px; font-weight: 700; line-height: 1.25; color: var(--nt-ink); }
.nt-agent-chat-sub { margin: 2px 0 0; font-size: 12px; line-height: 1.4; color: var(--nt-muted); }
.nt-agent-chat-reading { margin: 0; padding: 8px 16px; border-top: 1px solid var(--nt-line); border-bottom: 1px solid var(--nt-line);
  background: var(--nt-paper); font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-size: 11.5px; color: var(--nt-ink-2); }
.nt-agent-chat-log { flex: 1; min-height: 0; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 16px; }
.nt-agent-chat-earlier { margin: 0; text-align: center; font-size: 11.5px; color: var(--nt-muted); }
.nt-agent-avatar { width: 24px; height: 24px; border-radius: 7px; background: var(--nt-spruce); color: var(--nt-rail-ink);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.nt-agent-avatar .nt-icon { fill: var(--nt-saffron); stroke: var(--nt-saffron); } /* the saffron spark, a fill */
.nt-agent-avatar--lg { width: 30px; height: 30px; border-radius: 8px; }
.nt-agent-turn { display: flex; gap: 9px; align-items: flex-start; font-size: 13px; line-height: 1.55; color: var(--nt-ink); }
.nt-agent-turn-body { flex: 1; min-width: 0; }
.nt-agent-turn--person { flex-direction: column; align-items: flex-end; gap: 3px; }
.nt-agent-bubble--person { max-width: 320px; background: var(--nt-saffron-wash); color: var(--nt-ink); border-radius: 12px 12px 3px 12px;
  padding: 9px 12px; white-space: pre-line; overflow-wrap: anywhere; }
.nt-agent-meta { font-size: 11px; color: var(--nt-muted); }
.nt-agent-meta time { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; }
.nt-agent-body p { margin: 0 0 .4em; }
.nt-agent-body p:last-child { margin-bottom: 0; }
.nt-agent-body--failed { color: var(--nt-bad); }
.nt-agent-stopped, .nt-agent-worker-down { margin: 4px 0 0; font-size: 11.5px; color: var(--nt-muted); }
.nt-agent-worker-down { color: var(--nt-bad); }
.nt-agent-turn--discarded .nt-agent-diff-text { text-decoration: line-through; opacity: .6; }

/* thinking: three pulsing dots, the stage line and an elapsed ticker */
.nt-agent-thinking-row { display: flex; gap: 9px; align-items: center; }
.nt-agent-dots { display: flex; gap: 4px; align-items: center; background: var(--nt-wash); border-radius: 12px; padding: 10px 12px; }
.nt-agent-dots span { width: 6px; height: 6px; border-radius: 3px; background: var(--nt-ink-2); animation: nt-dot 1.2s ease-in-out infinite; }
.nt-agent-dots span:nth-child(2) { animation-delay: .18s; }
.nt-agent-dots span:nth-child(3) { animation-delay: .36s; }
.nt-agent-stage { font-size: 12px; color: var(--nt-muted); }
.nt-agent-elapsed { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-size: 11px; color: var(--nt-muted); }
.nt-agent-turn--thinking .nt-agent-text:empty { display: none; }
.nt-agent-turn--thinking .nt-agent-text { margin: 6px 0 0; white-space: pre-line; }
@keyframes nt-dot { 0%, 80%, 100% { opacity: .25; transform: translateY(0); } 40% { opacity: 1; transform: translateY(-2px); } }

/* streaming: the text so far and a blinking caret */
.nt-agent-streamed { margin: 0; white-space: pre-line; }
.nt-agent-caret { display: inline-block; width: 7px; height: 15px; margin-left: 2px; vertical-align: -2px; background: var(--nt-ink);
  animation: nt-caret 1s steps(1) infinite; }
@keyframes nt-caret { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
.nt-agent-foot { display: flex; align-items: center; gap: 8px; margin-top: 6px; font-size: 11px; color: var(--nt-muted); }
.nt-agent-stop-form { display: inline; margin: 0; }
.nt-agent-stop { height: 22px; padding: 0 8px; border: 1px solid var(--nt-line); border-radius: 6px; background: var(--nt-shell);
  color: var(--nt-ink-2); font: 600 11px var(--nt-font-body); cursor: pointer; }
.nt-agent-stop kbd { font-family: var(--nt-font-mono); background: none; color: inherit; padding: 0; font-size: 10.5px; }

/* cards: a proposal (diff + Apply/Discard) and a draft (Copy) */
.nt-agent-card { margin-top: 8px; border: 1px solid var(--nt-rule); border-radius: 9px; overflow: hidden; background: var(--nt-shell); }
.nt-agent-card-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 10px;
  border-bottom: 1px solid var(--nt-line); font-size: 12px; font-weight: 600; color: var(--nt-ink); }
.nt-agent-card-kind { font-weight: 500; color: var(--nt-muted); }
.nt-agent-diff { display: flex; flex-direction: column; gap: 1px; font-size: 12.5px; }
.nt-agent-diff-row { display: flex; gap: 8px; padding: 5px 10px; }
.nt-agent-diff-sign { width: 10px; flex-shrink: 0; font-family: var(--nt-font-mono); }
.nt-agent-diff-row--add { background: var(--nt-wash-ok); } .nt-agent-diff-row--add .nt-agent-diff-sign { color: var(--nt-ok); }
.nt-agent-diff-row--change { background: var(--nt-wash-warn); } .nt-agent-diff-row--change .nt-agent-diff-sign { color: var(--nt-warn); }
.nt-agent-diff-row--same { background: var(--nt-wash); } .nt-agent-diff-row--same .nt-agent-diff-sign { color: var(--nt-ok); }
.nt-agent-diff-row--same .nt-agent-diff-text { color: var(--nt-ink-2); }
.nt-agent-diff-row--remove, .nt-agent-diff-row--bad { background: var(--nt-wash-bad); }
.nt-agent-diff-row--remove .nt-agent-diff-sign, .nt-agent-diff-row--bad .nt-agent-diff-sign { color: var(--nt-bad); }
.nt-agent-diff-problem { display: block; font-size: 11.5px; color: var(--nt-bad); }
.nt-agent-cite { color: var(--nt-link); font-weight: 500; text-decoration: underline; white-space: nowrap; }
.nt-agent-card-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 9px 10px; border-top: 1px solid var(--nt-line); }
.nt-agent-card-foot:empty { display: none; }
.nt-agent-card-foot form { margin: 0; }
.nt-agent-card-hint { margin-left: auto; font-size: 11.5px; color: var(--nt-muted); }
.nt-agent-applied { font-size: 11.5px; color: var(--nt-muted); }
.nt-agent-draft-text { padding: 10px 12px; font-size: 12.5px; line-height: 1.55; white-space: pre-line; color: var(--nt-ink); }
.nt-agent-btn { height: 30px; padding: 0 12px; border: 1px solid var(--nt-rule); border-radius: 7px; background: var(--nt-shell);
  color: var(--nt-ink); font: 500 12.5px var(--nt-font-body); cursor: pointer; display: inline-flex; align-items: center; gap: 5px; }
.nt-agent-btn:hover { background: var(--nt-wash); }
.nt-agent-btn--primary { background: var(--nt-spruce); border-color: var(--nt-spruce); color: var(--nt-shell); font-weight: 600; }
.nt-agent-btn--primary:hover { background: var(--nt-spruce-2); }
.nt-agent-btn:disabled { opacity: .5; cursor: not-allowed; }
.nt-agent-copy { height: 26px; padding: 0 9px; font-weight: 600; font-size: 12px; }
.nt-agent-retry { margin: 6px 0 0; }

/* the answer's footer: thumbs and the owner's cost line */
.nt-agent-feedback { display: flex; align-items: center; gap: 6px; margin-top: 6px; }
.nt-agent-thumb-form { display: inline; margin: 0; }
.nt-agent-thumb { width: 26px; height: 24px; border: 1px solid var(--nt-line); border-radius: 6px; background: var(--nt-shell);
  color: var(--nt-ink-2); display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0; }
.nt-agent-thumb.is-on { background: var(--nt-wash-ok); }
.nt-agent-cost { margin-left: 4px; font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-size: 11px; color: var(--nt-muted); }
.nt-agent-trace { font-size: 11px; color: var(--nt-link); margin-left: 4px; }

/* chips and the composer */
.nt-agent-composer { padding: 0 16px 16px; }
.nt-agent-composer-form { margin: 0; }
.nt-agent-chips { display: flex; gap: 6px; padding: 0 0 8px; flex-wrap: wrap; }
/* The composer's extra field (the community's reminder group picker, Task 13). */
.nt-agent-field { display: flex; align-items: center; gap: 8px; padding: 0 0 8px; font-size: 12px; color: var(--nt-ink-3); }
.nt-agent-field .form-select, .nt-agent-field .form-control { width: auto; flex: 1; }
.nt-agent-chip { display: flex; align-items: center; gap: 5px; height: 28px; padding: 0 10px; border: 1px solid var(--nt-rule);
  border-radius: 14px; background: var(--nt-shell); color: var(--nt-ink); font: 500 12px var(--nt-font-body); cursor: pointer; white-space: nowrap; }
.nt-agent-chip:hover { background: var(--nt-wash); }
.nt-agent-chip--primary { background: var(--nt-spruce); border-color: var(--nt-spruce); color: var(--nt-shell); }
.nt-agent-chip--primary:hover { background: var(--nt-spruce-2); }
.nt-agent-box { display: block; border: 1px solid var(--nt-edge); border-radius: 10px; background: var(--nt-shell); padding: 9px 10px 8px; }
.nt-agent-box:focus-within { outline: 2px solid var(--nt-saffron); outline-offset: 1px; }
.nt-agent-box textarea { width: 100%; border: none; outline: none; resize: none; font: 13px var(--nt-font-body); color: var(--nt-ink); background: transparent; }
.nt-agent-box-foot { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--nt-muted); }
.nt-agent-send { margin-left: auto; width: 30px; height: 28px; border: none; border-radius: 7px; background: var(--nt-spruce); color: var(--nt-shell);
  display: flex; align-items: center; justify-content: center; cursor: pointer; }
.nt-agent-send:disabled { background: var(--nt-spruce-soft); cursor: not-allowed; }
@media (prefers-reduced-motion: reduce) {
  .nt-agent-dots span, .nt-agent-caret { animation: none; }
  .nt-agent-dots span { opacity: .6; }
}

/* ------------------------------------------------------------------ *
 * A WhatsApp group, read-only (wa_group/_feed) — the sheet's WhatsApp
 * tab and the drawer's Chats mode. Per build.py chat_feed.
 * ------------------------------------------------------------------ */
.nt-wa-feed { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.nt-wa-head { padding: 10px 14px; background: var(--nt-shell); border-bottom: 1px solid var(--nt-line); }
.nt-wa-head-row { display: flex; align-items: center; gap: 10px; }
.nt-wa-avatar { width: 36px; height: 36px; border-radius: 18px; background: var(--nt-spruce); color: var(--nt-shell);
  display: flex; align-items: center; justify-content: center; font: 700 13px var(--nt-font-body); flex-shrink: 0; }
.nt-wa-title { display: block; font-size: 14px; font-weight: 700; color: var(--nt-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nt-wa-sub { display: block; font-size: 12px; color: var(--nt-muted); }
.nt-wa-filters { display: flex; align-items: center; gap: 6px; padding: 6px 14px; background: var(--nt-shell); border-bottom: 1px solid var(--nt-line); flex-wrap: wrap; }
.nt-wa-pill { display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 10px; border-radius: 12px;
  border: 1px solid var(--nt-rule); background: var(--nt-shell); color: var(--nt-ink-2); font: 600 12px var(--nt-font-body); text-decoration: none; }
.nt-wa-pill:hover { background: var(--nt-wash); color: var(--nt-ink); }
.nt-wa-pill.is-on { border-color: var(--nt-spruce); background: var(--nt-spruce); color: var(--nt-shell); }
.nt-wa-pill-count { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-size: 11px; }
.nt-wa-shown { margin-left: auto; font-size: 11.5px; color: var(--nt-muted); font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; }
.nt-wa-log { flex: 1; min-height: 0; overflow-y: auto; background: var(--nt-wa-bg); padding: 6px 14px 10px; display: flex; flex-direction: column; }
.nt-wa-empty { margin: auto; font-size: 13px; color: var(--nt-muted); text-align: center; }
.nt-wa-day { display: flex; justify-content: center; margin: 10px 0 4px; }
.nt-wa-day span { font-size: 11.5px; font-weight: 600; color: var(--nt-ink-2); background: var(--nt-shell); border-radius: 8px; padding: 3px 10px; box-shadow: var(--nt-wa-shadow); }
.nt-wa-row { display: flex; flex-direction: column; align-items: flex-start; margin-top: 2px; }
.nt-wa-row.is-first { margin-top: 8px; }
.nt-wa-row.is-out { align-items: flex-end; }
.nt-wa-row.is-cited .nt-wa-bubble { box-shadow: 0 0 0 2px var(--nt-saffron); }
.nt-wa-bubble { position: relative; max-width: 78%; padding: 6px 9px 7px; border-radius: 8px; background: var(--nt-shell); box-shadow: var(--nt-wa-shadow); }
.nt-wa-row.is-out .nt-wa-bubble { background: var(--nt-wa-out); }
.nt-wa-row.is-first .nt-wa-bubble { border-radius: 0 8px 8px 8px; }
.nt-wa-row.is-first.is-out .nt-wa-bubble { border-radius: 8px 0 8px 8px; }
.nt-wa-row.is-first .nt-wa-bubble::before { content: ""; position: absolute; top: 0; left: -7px; width: 0; height: 0;
  border-top: 9px solid var(--nt-shell); border-left: 8px solid transparent; }
.nt-wa-row.is-first.is-out .nt-wa-bubble::before { left: auto; right: -7px; border-top-color: var(--nt-wa-out); border-left: none; border-right: 8px solid transparent; }
.nt-wa-name { font-size: 12.5px; font-weight: 700; margin-bottom: 1px; }
.nt-wa-tag { font-weight: 500; color: var(--nt-muted); font-family: var(--nt-font-mono); font-size: 11px; }
.nt-wa-dm { display: inline-block; margin: 0 0 2px; padding: 0 6px; border-radius: 8px; font-size: 10.5px; font-weight: 600; letter-spacing: .02em; color: var(--nt-muted); border: 1px solid currentColor; }
.nt-wa-text { font-size: 13.5px; line-height: 1.4; color: var(--nt-ink); white-space: pre-line; overflow-wrap: anywhere; }
.nt-wa-clock { float: right; display: inline-flex; align-items: center; gap: 3px; margin: 6px 0 -3px 10px; font-size: 11px; color: var(--nt-muted);
  font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; }
.nt-wa-read { color: var(--nt-wa-tick); font-weight: 700; letter-spacing: -3px; margin-right: 3px; }
.nt-wa-marker { display: flex; align-items: center; gap: 6px; margin: 3px 2px 2px; }
.nt-wa-chip { font-size: 11.5px; font-weight: 600; border-radius: 10px; padding: 2px 9px; text-decoration: none; }
.nt-wa-chip--on { color: var(--nt-ok); background: var(--nt-wash-ok); }
.nt-wa-chip--changed { color: var(--nt-info); background: var(--nt-wash-info); }
.nt-wa-chip--missing { color: var(--nt-warn); background: var(--nt-wash-warn); }
.nt-wa-add { display: inline-flex; align-items: center; height: 24px; padding: 0 9px; border: 1px solid var(--nt-rule); border-radius: 6px;
  background: var(--nt-shell); color: var(--nt-ink); font: 600 11.5px var(--nt-font-body); text-decoration: none; }
.nt-wa-foot { padding: 8px 14px; background: var(--nt-shell); border-top: 1px solid var(--nt-line); font-size: 12px; color: var(--nt-muted); text-align: center; }

/* The drawer's Chats mode (Task 16): the feed fills the drawer edge to edge. */
.nt-drawer-body:has(> .nt-wa-feed) { padding: 0; display: flex; flex-direction: column; overflow: hidden; }
.nt-wa-switcher { margin-top: 8px; }
.nt-wa-switcher .form-select { max-width: 100%; }
.nt-wa-buyer { margin: 8px 0 0; font-size: 12px; color: var(--nt-ink-2); }
.nt-wa-quote { margin: 0 0 14px; padding: 8px 12px; border-radius: 8px; background: var(--nt-wa-out); font-size: 13.5px; color: var(--nt-ink); }
.nt-wa-quote footer { margin-top: 4px; font-size: 11px; color: var(--nt-muted); font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; }
.nt-drawer-form .nt-stack { display: flex; flex-direction: column; gap: 10px; }
.nt-drawer-form .form-label { display: flex; flex-direction: column; gap: 4px; margin: 0; font-size: 12.5px; font-weight: 600; color: var(--nt-ink-2); }
.nt-sheet-status-cell { display: inline-flex; align-items: center; gap: 6px; }
.nt-sheet-row-chat { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 6px; color: var(--nt-ink-2); }
.nt-sheet-row-chat:hover { background: var(--nt-wash); color: var(--nt-ink); }

/* The sheet page's head and tabs (Task 20, Sheet.dc.html). */
.nt-page-head-titleline { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.nt-cutoff-chip { display: inline-flex; align-items: center; gap: 7px; height: 32px; padding: 0 11px; border-radius: 8px;
  background: var(--nt-wash-warn); color: var(--nt-warn); font-size: 12.5px; font-weight: 600; white-space: nowrap; }
.nt-cutoff-chip.is-past { background: var(--nt-wash); color: var(--nt-muted); }
.nt-cutoff-chip-time { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; }
.nt-menu-copy { display: contents; }
.nt-menu-copy .nt-menu-item { width: 100%; border: 0; background: transparent; text-align: left; font: inherit; }
.nt-sheet-page > .nt-sheet-head { margin-top: 10px; }
.nt-sheet-tabbar { display: flex; align-items: center; margin-bottom: 12px; border-bottom: 1px solid var(--nt-line); overflow-x: auto; }
.nt-sheet-tabs { display: flex; }
.nt-sheet-tab { height: 34px; display: flex; align-items: center; padding: 0 2px; margin-right: 18px; margin-bottom: -1px;
  font: 600 13px var(--nt-font-body); color: var(--nt-muted); text-decoration: none; white-space: nowrap;
  border-bottom: 2px solid transparent; }
.nt-sheet-tab:hover { color: var(--nt-ink); }
.nt-sheet-tab.is-on { color: var(--nt-ink); border-bottom-color: var(--nt-ink); }
.nt-sheet-tab-count { margin-left: 5px; font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-weight: 500; color: var(--nt-muted); }
.nt-sheet-tabpane { max-width: 44rem; }
.nt-sheet-activity { padding-left: 1rem; color: var(--nt-ink-2); font-size: 13px; }
.nt-sheet-remind-lead { font-size: 13px; color: var(--nt-ink-2); }
@media (max-width: 860px) {
  .nt-cutoff-chip { height: 28px; font-size: 12px; }
  .nt-page-head-actions { flex-wrap: wrap; }
}

/* ---- Task 21: the sheet grid (spreadsheet cells) and its sticky totals bar ---- */
.nt-sheet-keys { margin-left: auto; padding-left: 12px; white-space: nowrap; font-family: var(--nt-font-mono); font-size: 11.5px; color: var(--nt-muted); }
.nt-sheet td.nt-sheet-cell { position: relative; }
.nt-sheet [data-grid-cell] { border-color: transparent; background-color: transparent; font-variant-numeric: tabular-nums; }
.nt-sheet .nt-sheet-qty { font-family: var(--nt-font-mono); text-align: center; }
.nt-sheet .nt-sheet-unit { font-family: var(--nt-font-mono); font-weight: 600; }
.nt-sheet [data-grid-cell]:hover { border-color: var(--nt-line); }
.nt-sheet [data-grid-cell]:focus { border-color: var(--nt-saffron-deep); background-color: var(--nt-saffron-wash-2); box-shadow: none; outline: 2px solid var(--nt-saffron); outline-offset: -1px; }
.nt-sheet td.is-editing [data-grid-cell] { background-color: var(--nt-shell); outline-color: var(--nt-spruce); }
.nt-sheet tr.is-current > td { background-color: var(--nt-saffron-wash-2); }
.nt-sheet tr.is-current > td:first-child { box-shadow: inset 3px 0 0 var(--nt-saffron); }
.nt-sheet td.is-saving::after,
.nt-sheet td.is-saved::after { position: absolute; top: 2px; right: 3px; font-size: 10px; line-height: 1; }
.nt-sheet td.is-saving::after { content: "…"; color: var(--nt-muted); }
.nt-sheet td.is-saved::after { content: "✓"; color: var(--nt-ok); }

.nt-sheet-totals { position: sticky; bottom: 0; z-index: 2; display: flex; align-items: stretch; flex-wrap: wrap;
  margin-top: -1px; border: 1px solid var(--nt-rule); border-radius: 0 0 var(--nt-r-pane) var(--nt-r-pane); background: var(--nt-paper); }
.nt-sheet-totals-cell { padding: 9px 14px; border-right: 1px solid var(--nt-line); }
.nt-sheet-totals-cell:last-child { border-right: 0; }
.nt-sheet-totals-label { font-size: 11px; font-weight: 600; color: var(--nt-muted); }
.nt-sheet-totals-label.is-caps { text-transform: uppercase; letter-spacing: .05em; }
/* Pack headers read "6s 12s 30s" (Sheet.dc.html), not "6S". */
.table.nt-sheet > thead > tr > th[title] { text-transform: none; letter-spacing: 0; }
.nt-sheet-totals-big,
.nt-sheet-totals-num,
.nt-sheet-totals-side { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; }
.nt-sheet-totals-big { font-size: 17px; font-weight: 700; }
.nt-sheet-totals-num { font-size: 15px; font-weight: 600; }
.nt-sheet-totals-side { font-size: 12px; color: var(--nt-muted); white-space: nowrap; }
.nt-sheet-totals-packs { display: flex; gap: 16px; }
.nt-sheet-totals-bar { min-width: 220px; }
.nt-sheet-totals-grow { flex: 1; }
.nt-sheet-totals-meter { display: flex; align-items: center; gap: 8px; margin-top: 3px; }
.nt-sheet-totals-track { flex: 1; min-width: 40px; height: 7px; border-radius: 4px; background: var(--nt-carton); overflow: hidden; display: flex; }
.nt-sheet-totals-track.is-money { background: var(--nt-wash-bad); }
.nt-sheet-totals-fill { display: block; height: 100%; background: var(--nt-spruce); }
.nt-sheet-totals-fill.is-ok { background: var(--nt-ok); }
.nt-sheet-totals .is-ok { color: var(--nt-ok); }
.nt-sheet-totals .is-bad { color: var(--nt-bad); }
.nt-sheet-totals-end { text-align: right; margin-left: auto; }
.nt-sheet-main > .table-scroll { margin-bottom: 0; }
@media (max-width: 860px) {
  .nt-sheet-keys { display: none; }
  .nt-sheet-totals-cell { padding: 7px 10px; }
  .nt-sheet-totals-bar { min-width: 0; flex: 1 1 100%; border-right: 0; border-top: 1px solid var(--nt-line); }
}
@media (prefers-reduced-motion: no-preference) {
  .nt-sheet-totals-fill { transition: width .2s ease; }
}

/* ---- Task 22: the sheet's Payments, WhatsApp and Activity tabs ---- */
.nt-sheet-payments .nt-sheet-settlement { max-width: none; }
.nt-sheet-paylines { margin-top: 1rem; }
.nt-sheet-paylines-table { font-size: 13px; margin-bottom: 0; }
.nt-sheet-paylines-table th { font-size: 11.5px; font-weight: 600; color: var(--nt-muted); text-transform: uppercase; letter-spacing: .04em; }
.nt-sheet-paylines-table .nt-num { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; }
.nt-sheet-wa { max-width: none; }
.nt-sheet-wa #sheet_wa_feed { display: flex; flex-direction: column; height: min(72vh, 760px); border: 1px solid var(--nt-line); border-radius: 10px; overflow: hidden; }
.nt-sheet-wa .nt-wa-bubble { max-width: min(78%, 560px); }
.nt-sheet-activity-sum { font-size: 13px; color: var(--nt-ink-2); }
.nt-sheet-activity-sum .nt-num { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; }
.nt-sheet-activity { list-style: none; padding-left: 0; margin: 0; }
.nt-sheet-activity-item { display: flex; gap: 10px; align-items: baseline; padding: 6px 0; border-bottom: 1px solid var(--nt-line); }
.nt-sheet-activity-item time { flex: 0 0 8.5rem; font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-size: 12px; color: var(--nt-muted); }
.nt-sheet-activity-actor { color: var(--nt-muted); }
@media (max-width: 860px) { .nt-sheet-activity-item time { flex-basis: 7rem; } }

/* ---- Operations (Task 26, Operations.dc.html) ---- */
.nt-ops-page { display: flex; flex-direction: column; gap: 12px; }
.nt-ops-page > .nt-seg { align-self: flex-start; }
.nt-ops-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 26rem); gap: 14px; align-items: start; }
@media (max-width: 1100px) { .nt-ops-grid { grid-template-columns: minmax(0, 1fr); } }
.nt-ops-col { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.nt-ops-heat-wrap { overflow-x: auto; }
.nt-ops-heat { display: flex; flex-direction: column; gap: 4px; min-width: 34rem; font-size: 12px; }
.nt-ops-heat-row { display: grid; grid-template-columns: 8rem repeat(7, minmax(0, 1fr)); gap: 4px; }
.nt-ops-heat-day { text-align: center; font-weight: 600; color: var(--nt-ink-2); padding-bottom: 2px; }
.nt-ops-heat-day.is-today { color: var(--nt-ink); }
.nt-ops-heat-day small { display: block; font-size: 10.5px; font-weight: 500; color: var(--nt-muted); }
.nt-ops-heat-day.is-today small { color: var(--nt-leaf); font-weight: 600; }
.nt-ops-heat-label { display: flex; align-items: center; font-weight: 600; color: var(--nt-ink-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nt-ops-heat-cell {
  height: 40px; border-radius: 6px; display: flex; align-items: center; justify-content: center;
  font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-size: 14px; font-weight: 600; color: var(--nt-ink);
}
.nt-ops-heat-0 { background: var(--nt-wash); color: var(--nt-muted); }
.nt-ops-heat-1 { background: var(--nt-saffron-wash-2); }
.nt-ops-heat-2 { background: var(--nt-saffron-wash); }
.nt-ops-heat-3 { background: var(--nt-saffron-wash-3); }
.nt-ops-heat-4 { background: var(--nt-saffron); }
.nt-ops-heat-foot { border-top: 1px solid var(--nt-rule); padding-top: 6px; }
.nt-ops-heat-foot .nt-ops-heat-label { color: var(--nt-ink); font-weight: 700; }
.nt-ops-heat-total { text-align: center; font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-size: 13px; font-weight: 600; }
.nt-ops-heat-total small { display: block; font-family: var(--nt-font-body); font-size: 11px; font-weight: 500; color: var(--nt-muted); }
.nt-ops-sheets { list-style: none; margin: 10px 0 0; padding: 0; font-size: 12.5px; }
.nt-ops-sheets li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; padding: 6px 0; border-top: 1px solid var(--nt-line); }
.nt-ops-sheet-day { width: 3.5rem; font-weight: 600; color: var(--nt-ink-2); }
.nt-ops-sheet-name { flex: 1 1 12rem; min-width: 0; }
.nt-ops-sheet-figs { color: var(--nt-ink-2); font-variant-numeric: tabular-nums; }
.nt-ops-count { font-family: var(--nt-font-mono); font-size: 12px; color: var(--nt-shell); background: var(--nt-brick); border-radius: 9px; padding: 0 7px; }
.nt-ops-alerts { list-style: none; margin: 0; padding: 0; }
.nt-ops-alerts li { display: flex; align-items: baseline; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--nt-line); font-size: 13px; }
.nt-ops-alerts li:last-child { border-bottom: 0; }
.nt-ops-dot { width: 8px; height: 8px; border-radius: 4px; flex: none; transform: translateY(-1px); }
.nt-ops-dot--bad { background: var(--nt-brick); }
.nt-ops-dot--warn { background: var(--nt-saffron); }
.nt-ops-run { display: block; background: var(--nt-spruce); color: var(--nt-shell); border-radius: 10px; padding: 13px 14px; text-decoration: none; }
.nt-ops-run:hover { color: var(--nt-shell); filter: brightness(1.08); }
.nt-ops-run > span { display: flex; }
.nt-ops-run-top { align-items: center; gap: 8px; font-size: 12px; font-weight: 600; opacity: .85; }
.nt-ops-run-dot { width: 7px; height: 7px; border-radius: 4px; background: var(--nt-saffron); }
.nt-ops-run-open { margin-left: auto; }
.nt-ops-run-big { align-items: baseline; gap: 8px; margin-top: 6px; font-size: 13px; }
.nt-ops-run-big b { font-size: 26px; font-weight: 600; }
.nt-ops-run-bar { height: 8px; border-radius: 4px; overflow: hidden; margin-top: 8px; background: color-mix(in srgb, var(--nt-shell) 18%, transparent); }
.nt-ops-run-bar span { display: block; height: 100%; background: var(--nt-saffron); }
.nt-ops-run-foot { gap: 12px; margin-top: 8px; font-size: 12px; opacity: .85; }
.nt-ops-run-foot > :last-child { margin-left: auto; }
.nt-ops-money { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 12px; margin: 0; }
.nt-ops-money dt { font-size: 12px; font-weight: 500; color: var(--nt-muted); }
.nt-ops-money dd { margin: 0; font-size: 17px; font-weight: 600; }
@media (prefers-reduced-motion: no-preference) { .nt-ops-run-dot { animation: nt-live 2.4s ease-in-out infinite; } }

/* ---- Today: the run board (Task 27) -------------------------------------
   Four columns from RunBoard::COLUMNS; a card per stop. Main.dc.html. */
.nt-board { margin: 12px 0 20px; }
.nt-board-empty { margin: 0 0 8px; }
.nt-board-cols { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.nt-board-col { background: var(--nt-wash); border-radius: 10px; padding: 8px; min-width: 0; }
.nt-board-col-head { display: flex; align-items: center; gap: 7px; padding: 2px 4px 8px;
  font-size: 12.5px; font-weight: 600; }
.nt-board-col-icon { width: 22px; height: 22px; border-radius: 6px; display: flex;
  align-items: center; justify-content: center; }
.nt-board-col--to_pack .nt-board-col-icon { color: var(--nt-warn); background: var(--nt-wash-warn); }
.nt-board-col--out .nt-board-col-icon { color: var(--nt-info); background: var(--nt-wash-info); }
.nt-board-col--delivered .nt-board-col-icon { color: var(--nt-leaf); background: var(--nt-wash-leaf); }
.nt-board-col--problems .nt-board-col-icon { color: var(--nt-brick); background: var(--nt-wash-brick); }
.nt-board-col-label { color: var(--nt-ink); }
.nt-board-col-count { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums;
  font-size: 12px; color: var(--nt-muted); }
.nt-board-col-body { display: flex; flex-direction: column; gap: 6px; }
.nt-board-col-none { margin: 0; padding: 6px 4px; font-size: 12px; color: var(--nt-muted); }
.nt-board-card { background: var(--nt-shell); border: 1px solid var(--nt-rule); border-radius: 8px; }
.nt-board-card:hover { border-color: var(--nt-ink-3); }
.nt-board-card-link { display: block; padding: 9px 10px; color: inherit; text-decoration: none; }
.nt-board-card-top { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
.nt-board-card-label { font-family: var(--nt-font-mono); font-size: 12.5px; font-weight: 600;
  color: var(--nt-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nt-board-card--drop .nt-board-card-label { font-family: var(--nt-font-body); }
.nt-board-card-comm, .nt-board-card-homes { font-size: 11.5px; color: var(--nt-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nt-board-card-drive { margin-left: auto; font-family: var(--nt-font-mono);
  font-variant-numeric: tabular-nums; font-size: 11px; color: var(--nt-muted); white-space: nowrap; }
.nt-board-card-name { display: block; font-size: 13px; color: var(--nt-ink); margin-top: 2px; }
.nt-board-card-foot { display: flex; align-items: center; gap: 6px; margin-top: 6px; flex-wrap: wrap; }
.nt-board-card-packs { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums;
  font-size: 11.5px; color: var(--nt-ink-2); background: var(--nt-wash); border-radius: 4px; padding: 1px 5px; }
.nt-board-card-eggs { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums;
  font-size: 11px; color: var(--nt-muted); }
.nt-board-pay { font-size: 11px; font-weight: 600; border-radius: 9px; padding: 1px 7px; }
.nt-board-pay--ok { color: var(--nt-leaf); background: var(--nt-wash-leaf); }
.nt-board-pay--bad { color: var(--nt-brick); background: var(--nt-wash-brick); }
.nt-board-pay--warn { color: var(--nt-warn); background: var(--nt-wash-warn); }
.nt-board-pay--neutral { color: var(--nt-ink-2); background: var(--nt-wash); }
.nt-board-card-problem { display: block; margin-top: 6px; font-size: 11.5px; color: var(--nt-brick); }
.nt-board-sheets-head { font-family: var(--nt-font-display); font-size: 15px; font-weight: 700; margin: 8px 0; }
@media (max-width: 860px) {
  .nt-board-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 520px) {
  .nt-board-cols { grid-template-columns: minmax(0, 1fr); }
}

/* ---- Today: meter, route strip, stop inspector, Undo toast, packing (Task 28;
   Main.dc.html's meter(), mapstrip(), inspector_body(), toast_html()) ---- */
.nt-meter {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: stretch;
  background: none; border: 0; padding: 0; margin: 0 0 12px;
}
.nt-meter-card {
  flex: 1.4 1 320px; min-width: 0;
  background: var(--nt-shell); border: 1px solid var(--nt-line); border-radius: 10px; padding: 12px 14px;
}
.nt-meter-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.nt-meter-label { font-size: 12px; color: var(--nt-muted); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }
.nt-meter .nt-meter-big {
  font-family: var(--nt-font-mono); font-size: 22px; font-weight: 600; letter-spacing: 0; line-height: 1.2;
}
.nt-meter .nt-meter-facts { font-family: var(--nt-font-mono); font-size: 13px; color: var(--nt-muted); margin: 0; }
.nt-meter-trays { margin-left: auto; font-family: var(--nt-font-mono); font-size: 12px; color: var(--nt-ink-2); font-variant-numeric: tabular-nums; }
.nt-meter .nt-trays {
  display: flex; flex-wrap: nowrap; gap: 1px; height: 10px; border-radius: 5px; overflow: hidden;
  background: var(--nt-carton); margin-top: 9px;
}
.nt-meter .nt-tray { flex: 1 1 0; width: auto; height: 100%; border: 0; border-radius: 0; background: var(--nt-carton); }
.nt-meter .nt-tray--done { background: var(--nt-saffron); }
.nt-meter-packs { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 8px; font-size: 12px; color: var(--nt-ink-2); }
.nt-meter-packs b { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; }
.nt-meter-orders { margin-left: auto; color: var(--nt-muted); }
.nt-meter-kpis { flex: 2 1 380px; display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 10px; min-width: 0; }
.nt-kpi { background: var(--nt-shell); border: 1px solid var(--nt-line); border-radius: 10px; padding: 11px 13px; min-width: 0; }
.nt-kpi-label { font-size: 12px; color: var(--nt-muted); font-weight: 600; }
.nt-kpi-row { display: flex; align-items: baseline; gap: 6px; margin-top: 4px; flex-wrap: wrap; }
.nt-kpi-value { font-family: var(--nt-font-mono); font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums; }
.nt-kpi-sub { font-size: 12px; color: var(--nt-ink-2); overflow: hidden; text-overflow: ellipsis; }
.nt-meter .nt-meter-foot { flex: 1 1 100%; border-top: 0; padding-top: 0; }

.nt-route {
  position: relative; background: var(--nt-wash); border: 1px solid var(--nt-line); border-radius: 10px;
  min-height: 104px; overflow: hidden; margin-bottom: 12px;
}
.nt-route-empty { margin: 0; padding: 40px 16px; color: var(--nt-muted); font-size: 13px; }
.nt-route-svg { display: block; width: 100%; height: 104px; }
.nt-route-road { stroke: var(--nt-carton); stroke-width: 10; fill: none; }
.nt-route-line { stroke: var(--nt-edge); stroke-width: 2; stroke-dasharray: 4 4; fill: none; }
.nt-route-line--done { stroke: var(--nt-ok); stroke-width: 2.5; stroke-dasharray: none; }
.nt-route-hub { fill: var(--nt-ink); }
.nt-route-pin circle { fill: var(--nt-shell); stroke: var(--nt-ink); stroke-width: 1.5; }
.nt-route-pin.is-done circle { fill: var(--nt-ok); }
.nt-route-num { font-family: var(--nt-font-mono); font-size: 10px; font-weight: 600; fill: var(--nt-ink); }
.nt-route-pin.is-done .nt-route-num { fill: var(--nt-shell); }
.nt-route-name { font-family: var(--nt-font-body); font-size: 10.5px; fill: var(--nt-ink-2); }
.nt-route-chip {
  position: absolute; right: 10px; top: 8px; display: flex; align-items: center; gap: 6px;
  background: var(--nt-shell); border: 1px solid var(--nt-line); border-radius: 6px; padding: 3px 8px;
  font-size: 11.5px; color: var(--nt-ink-2);
}

.nt-board-card-sheet { display: block; padding: 0 10px 8px; font-size: 11.5px; color: var(--nt-link); }

.nt-stop { padding: 14px 16px; display: flex; flex-direction: column; gap: 14px; }
.nt-stop-seg { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px; background: var(--nt-wash); border-radius: 8px; padding: 3px; }
.nt-stop-seg-item { height: 28px; display: flex; align-items: center; justify-content: center; border-radius: 6px; font-size: 12px; font-weight: 600; color: var(--nt-ink-2); }
.nt-stop-seg-item.is-on { background: var(--nt-shell); color: var(--nt-ink); box-shadow: 0 1px 2px rgba(10, 32, 30, .2); }
.nt-stop-problem { margin: 0; color: var(--nt-bad); font-weight: 600; font-size: 13px; }
.nt-stop-lines { border: 1px solid var(--nt-line); border-radius: 9px; }
.nt-stop-lines-head { display: flex; justify-content: space-between; padding: 8px 11px; border-bottom: 1px solid var(--nt-line); font-size: 12px; color: var(--nt-muted); font-weight: 600; }
.nt-stop-line { display: flex; justify-content: space-between; gap: 10px; padding: 6px 11px; font-size: 13px; }
.nt-stop-line .nt-num { font-family: var(--nt-font-mono); }
.nt-stop-line--total { border-top: 1px solid var(--nt-line); font-weight: 600; padding: 8px 11px; }
.nt-stop-pay { border: 1px solid var(--nt-line); border-radius: 9px; padding: 8px 11px; display: flex; flex-direction: column; gap: 6px; font-size: 12.5px; }
.nt-stop-pay-row { display: flex; justify-content: space-between; gap: 8px; align-items: center; }
.nt-stop-pay-state { font-size: 11.5px; font-weight: 600; border-radius: 10px; padding: 2px 8px; background: var(--nt-wash); color: var(--nt-ink-2); }
.nt-stop-pay-state--verified { background: var(--nt-wash-ok); color: var(--nt-ok); }
.nt-stop-pay-state--mismatch { background: var(--nt-wash-bad); color: var(--nt-bad); }
.nt-stop-pay-state--unreadable { background: var(--nt-wash-warn); color: var(--nt-warn); }
.nt-stop-links { display: flex; gap: 8px; flex-wrap: wrap; }
.nt-stop-link {
  flex: 1 1 0; min-width: 110px; display: flex; align-items: center; justify-content: center; gap: 6px; height: 32px;
  border: 1px solid var(--nt-rule); border-radius: 7px; color: var(--nt-ink); text-decoration: none; font-size: 12.5px; font-weight: 600;
}
.nt-stop-link:hover { background: var(--nt-wash); color: var(--nt-ink); }
.nt-stop-note p { margin: 4px 0 0; font-size: 13px; }
.nt-stop-note-label { font-size: 12px; color: var(--nt-muted); font-weight: 600; }
.nt-stop-timeline { display: flex; flex-direction: column; gap: 8px; font-size: 12.5px; margin-top: -6px; }
.nt-stop-timeline > div { display: flex; gap: 9px; }
.nt-stop-timeline .nt-num { font-family: var(--nt-font-mono); color: var(--nt-muted); width: 40px; flex: none; }
.nt-stop-acts { display: flex; gap: 8px; width: 100%; }
.nt-stop-form { flex: 1 1 0; margin: 0; display: flex; }
.nt-stop-form--main { flex: 2 1 0; }
.nt-stop-deliver, .nt-stop-btn {
  flex: 1; height: 38px; border-radius: 8px; font: 600 13px var(--nt-font-body); cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 7px;
}
.nt-stop-deliver { border: 0; background: var(--nt-ok); color: var(--nt-shell); }
.nt-stop-btn { border: 1px solid var(--nt-rule); background: var(--nt-shell); color: var(--nt-ink); }
.nt-stop-btn--bad { color: var(--nt-bad); }

.nt-toast {
  display: flex; align-items: center; gap: 12px; background: var(--nt-ink); color: var(--nt-shell);
  border-radius: 10px; padding: 10px 12px 10px 14px; font-size: 13px; box-shadow: 0 12px 30px -12px rgba(10, 32, 30, .6);
}
.nt-toast-icon { color: var(--nt-wash-ok); display: flex; }
.nt-toast-form { margin: 0; }
.nt-toast-undo {
  border: 0; background: transparent; color: var(--nt-wash-warn); font: 600 13px var(--nt-font-body);
  cursor: pointer; display: flex; align-items: center; gap: 5px;
}
.nt-toast-undo kbd { background: none; color: var(--nt-rail-muted); font-size: 11px; padding: 0; }

.nt-packing-title { font-family: var(--nt-font-display); font-size: 22px; margin: 0 0 12px; }
.nt-packing-sheet { margin-bottom: 18px; break-inside: avoid; }
.nt-packing-sheet h2 { font-size: 16px; display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; }
.nt-packing-sum { font-family: var(--nt-font-mono); font-size: 12.5px; color: var(--nt-muted); font-weight: 500; }
.nt-packing-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.nt-packing-table th, .nt-packing-table td { border-bottom: 1px solid var(--nt-line); padding: 5px 8px; text-align: left; }
.nt-packing-table .nt-num { font-family: var(--nt-font-mono); }
.nt-packing-box { width: 28px; text-align: center; }
@media print {
  .nt-no-print, .nt-rail, .nt-topbar, .nt-tabbar { display: none !important; }
}
@media (max-width: 575.98px) {
  .nt-meter .nt-meter-big { font-size: 20px; }
  .nt-route-name { display: none; }
}

/* ---- Setup (D11, Task 29): one page, a grouped sub-nav beside the section's
   list. The list is its own controller's index inside turbo-frame#setup_section. */
.nt-setup-body {
  display: grid;
  grid-template-columns: 208px minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}

.nt-setup-nav {
  position: sticky;
  top: 12px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 12px 10px;
  border: 1px solid var(--nt-line);
  border-radius: 10px;
  background-color: var(--nt-shell);
}

.nt-setup-nav-group {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.nt-setup-nav-label {
  padding: 0 8px 4px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--nt-muted);
}

.nt-setup-nav-link {
  position: relative;
  padding: 5px 8px;
  border-radius: 6px;
  font-size: 13.5px;
  color: var(--nt-ink);
}

.nt-setup-nav-link:hover {
  background-color: var(--nt-wash);
  text-decoration: none;
}

.nt-setup-nav-link.is-active {
  background-color: var(--nt-wash);
  font-weight: 600;
}

.nt-setup-nav-link.is-active::before {
  content: "";
  position: absolute;
  left: -10px;
  top: 7px;
  width: 3px;
  height: 16px;
  border-radius: 2px;
  background-color: var(--nt-saffron);
}

.nt-setup-section {
  min-width: 0;
  padding: 14px 16px;
  border: 1px solid var(--nt-line);
  border-radius: 10px;
  background-color: var(--nt-shell);
}

.nt-setup-list-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
  margin-bottom: 12px;
}

.nt-setup-list-head h1 { margin: 0; flex: 1 0 100%; }

.nt-setup-note {
  flex: 1 1 320px;
  margin: 0;
  font-size: 13px;
  color: var(--nt-ink-3);
}

.nt-setup-new {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.nt-setup-subhead {
  margin: 16px 0 8px;
  font-family: var(--nt-font-display);
  font-size: 15px;
}

.nt-setup-table { margin-bottom: 0; }
.nt-setup-list .nt-setup-table { font-size: 13.5px; }

.nt-setup-price {
  display: inline-block;
  margin-right: 10px;
  white-space: nowrap;
}

.nt-setup .nt-num,
.nt-setup-table .nt-num {
  font-family: var(--nt-font-mono);
  font-variant-numeric: tabular-nums;
}

/* A phone: the sub-nav is one scrolling row of pills above the list. */
@media (max-width: 860px) {
  .nt-setup-body { grid-template-columns: minmax(0, 1fr); gap: 12px; }

  .nt-setup-nav {
    position: static;
    flex-direction: row;
    gap: 6px;
    padding: 0;
    border: 0;
    background: none;
    overflow-x: auto;
  }

  .nt-setup-nav-group { flex-direction: row; gap: 6px; flex: none; }
  .nt-setup-nav-label { display: none; }

  .nt-setup-nav-link {
    flex: none;
    padding: 5px 11px;
    border: 1px solid var(--nt-line);
    border-radius: 999px;
    background-color: var(--nt-shell);
    white-space: nowrap;
  }

  .nt-setup-nav-link.is-active { background-color: var(--nt-spruce); color: var(--nt-rail-ink); }
  .nt-setup-nav-link.is-active::before { display: none; }

  .nt-setup-section { padding: 10px; overflow-x: auto; }
}

/* Setup › Locations' pin map (Task 30). */
.nt-setup-map { margin-bottom: 12px; min-height: 240px; }
.nt-setup-map .nt-overview-map-canvas { min-height: 240px; }

/* Task 31: the two-pane pages (Customers, Chats) sit under the page head, so
   their fixed height gives up the head's share of the viewport. */
.nt-page-head + .nt-spa,
.nt-page-head + .nt-wa { height: calc(100vh - 11.5rem); margin-top: 12px; }
@media (max-width: 767.98px) {
  .nt-page-head + .nt-spa,
  .nt-page-head + .nt-wa { height: calc(100vh - 12rem); }
}

/* ---- Today on a phone (Task 32, Phone-Today.dc.html) ----------------------
   Below 860px Today is the next door and two big buttons; the meter, route
   and board (`.nt-desk-only`) are the desk's. */
.nt-phone-only { display: none; }
@media (max-width: 860px) {
  .nt-phone-only { display: block; }
  .nt-desk-only { display: none; }
}
.nt-phone { display: flex; flex-direction: column; margin: 4px 0 18px; }
.nt-phone-progress-text {
  display: flex; justify-content: space-between; font-size: 12.5px; color: var(--nt-ink-2); margin-bottom: 6px;
}
.nt-phone-progress-text b { color: var(--nt-ink); }
.nt-phone-bar { height: 8px; border-radius: 4px; background: var(--nt-carton); overflow: hidden; }
.nt-phone-bar > span { display: block; height: 100%; background: var(--nt-leaf); }
.nt-phone-card {
  margin-top: 14px; background: var(--nt-shell); border: 1px solid var(--nt-rule); border-radius: 16px;
  padding: 16px; box-shadow: var(--nt-shadow);
}
.nt-phone-eyebrow {
  display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 700; color: var(--nt-muted);
  letter-spacing: .06em; text-transform: uppercase;
}
.nt-phone-eyebrow .nt-num { margin-left: auto; letter-spacing: 0; }
.nt-phone-flat { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-size: 34px; font-weight: 600; margin-top: 6px; letter-spacing: -.02em; }
.nt-phone-name { font-size: 17px; font-weight: 600; margin-top: 2px; }
.nt-phone-where { font-size: 13.5px; color: var(--nt-ink-2); margin-top: 2px; }
.nt-phone-packs { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.nt-phone-pack {
  flex: 1 1 140px; display: flex; align-items: center; gap: 8px; background: var(--nt-wash-yolk);
  border-radius: 10px; padding: 10px 12px; color: var(--nt-ink-2);
}
.nt-phone-pack-qty { display: block; font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-size: 20px; font-weight: 600; color: var(--nt-ink); }
.nt-phone-pack-label { display: block; font-size: 12px; color: var(--nt-ink-2); }
.nt-phone-note { margin-top: 12px; font-size: 13.5px; background: var(--nt-wash); border-radius: 9px; padding: 9px 11px; }
.nt-phone-links { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-top: 12px; }
.nt-phone-link {
  height: 42px; border: 1px solid var(--nt-rule); border-radius: 10px; display: flex; align-items: center;
  justify-content: center; gap: 6px; color: var(--nt-ink); text-decoration: none; font-size: 13.5px; font-weight: 600;
}
.nt-phone-then { margin-top: 14px; }
.nt-phone-then .nt-phone-eyebrow { margin-bottom: 6px; }
.nt-phone-then-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--nt-line); }
.nt-phone-then-seq { font-family: var(--nt-font-mono); font-size: 12px; color: var(--nt-muted); width: 26px; }
.nt-phone-then-flat { font-family: var(--nt-font-mono); font-size: 14px; font-weight: 600; }
.nt-phone-then-name { font-size: 13.5px; color: var(--nt-ink-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nt-phone-then-packs { margin-left: auto; font-family: var(--nt-font-mono); font-size: 12.5px; color: var(--nt-ink-2); }
.nt-phone-collect { display: flex; align-items: center; gap: 8px; margin-top: 14px; font-size: 14px; font-weight: 600; }
.nt-phone-collect > span { flex: 1; }
.nt-phone-collect-btn {
  height: 44px; padding: 0 16px; border: 1px solid var(--nt-rule); border-radius: 12px; background: var(--nt-shell);
  color: var(--nt-ink); font: 600 14px var(--nt-font-body); cursor: pointer;
}
.nt-phone-form { margin: 0; }
.nt-phone-acts {
  position: sticky; bottom: 0; z-index: 2; display: flex; gap: 10px; margin: 14px -16px 0; padding: 12px 16px 18px;
  background: var(--nt-paper); border-top: 1px solid var(--nt-line);
}
.nt-phone-form--skip { flex: 1; }
.nt-phone-form--deliver { flex: 2; }
.nt-phone-skip, .nt-phone-deliver { width: 100%; height: 64px; border-radius: 16px; cursor: pointer; }
.nt-phone-skip { border: 1.5px solid var(--nt-ink); background: var(--nt-shell); color: var(--nt-ink); font: 700 18px var(--nt-font-body); }
.nt-phone-deliver {
  border: 0; background: var(--nt-leaf); color: var(--nt-shell); font: 700 19px var(--nt-font-body);
  display: flex; align-items: center; justify-content: center; gap: 9px;
}
.nt-phone-empty { margin: 16px 0 0; color: var(--nt-ink-2); }

/* ---- Sheet cards: the Rows tab as one card per order (SheetCards.dc.html) ---- */
.nt-ocards { display: flex; flex-direction: column; gap: 10px; padding-bottom: 12px; }
.nt-ocards-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.nt-ocards-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.nt-ocards-chip { flex-shrink: 0; height: 30px; padding: 0 11px; border: 1px solid var(--nt-rule); border-radius: 15px;
  background: var(--nt-shell); color: var(--nt-ink-2); font: 600 12.5px var(--nt-font-body); cursor: pointer; white-space: nowrap; }
.nt-ocards-chip[aria-pressed="true"] { border-color: var(--nt-spruce); background: var(--nt-spruce); color: var(--nt-shell); }
.nt-ocards-count { margin-left: 5px; font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-size: 11px; opacity: .8; }
.nt-ocards-tools { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.nt-ocards-search { display: flex; align-items: center; gap: 6px; width: 200px; height: 30px; padding: 0 9px; margin: 0; box-sizing: border-box;
  border: 1px solid var(--nt-rule); border-radius: 8px; background: var(--nt-shell); color: var(--nt-muted); }
.nt-ocards-search input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; font: 13px var(--nt-font-body); color: var(--nt-ink); }
.nt-ocards-search:focus-within { outline: 2px solid var(--nt-saffron-deep); outline-offset: 1px; }
.nt-ocards-sort { display: flex; padding: 2px; border: 1px solid var(--nt-line); border-radius: 8px; background: var(--nt-wash); }
.nt-ocards-sort button { height: 24px; padding: 0 9px; border: 0; border-radius: 6px; background: transparent; color: var(--nt-ink-2);
  font: 600 12px var(--nt-font-body); cursor: pointer; }
.nt-ocards-sort button[aria-pressed="true"] { background: var(--nt-shell); color: var(--nt-ink); box-shadow: 0 1px 2px rgba(10, 32, 30, .18); }
.nt-ocards-head { display: flex; align-items: baseline; gap: 8px; }
.nt-ocards-title { font-size: 13.5px; font-weight: 700; color: var(--nt-ink); }
.nt-ocards-sub { font-size: 12px; color: var(--nt-muted); }
.nt-ocards-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; align-items: start; }
.nt-ocards-grid[hidden], .nt-ocards-head[hidden], .nt-ghosts[hidden], .nt-ocard[hidden] { display: none; }
.nt-ocards-rows { display: contents; }
.nt-ocards-empty { padding: 40px; text-align: center; color: var(--nt-muted); font-size: 13px; margin: 0; }
.nt-ocards-none { padding: 24px; text-align: center; color: var(--nt-muted); font-size: 13px; margin: 0; }
.nt-ocards.has-orders .nt-ocards-none { display: none; }
@media (max-width: 1279px) { .nt-ocards-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 1080px) { .nt-ocards-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* One card. */
.nt-ocard { position: relative; display: flex; flex-direction: column; padding: 12px 12px 10px; border: 1px solid var(--nt-line);
  border-radius: 12px; background: var(--nt-shell); box-shadow: 0 1px 2px rgba(10, 32, 30, .06); min-width: 0; }
.nt-ocard:has(.nt-menu-button[aria-expanded="true"]) { border-color: var(--nt-spruce); z-index: 5; }
.nt-ocard.is-flagged { box-shadow: 0 0 0 2px var(--nt-saffron); }
.nt-ocard--cancelled { opacity: .6; }
.nt-ocard.is-saving { border-color: var(--nt-saffron-deep); }
.nt-ocard-top { display: flex; align-items: flex-start; gap: 8px; }
.nt-ocard-flat { font-family: var(--nt-font-display); font-size: 20px; font-weight: 700; letter-spacing: -.01em; line-height: 1.1; color: var(--nt-ink);
  overflow-wrap: anywhere; }
.nt-ocard-flat.is-none { color: var(--nt-muted); }
.nt-ocard-status { margin-left: auto; display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; font-size: 11.5px; font-weight: 600;
  border-radius: 10px; padding: 1px 8px; border: 1px solid transparent; }
.nt-ocard-status--draft { color: var(--nt-ink-2); background: var(--nt-shell); border: 1px dashed var(--nt-edge); }
.nt-ocard-status--confirmed { color: var(--nt-ok); background: var(--nt-wash-ok); }
.nt-ocard-status--delivered { color: var(--nt-info); background: var(--nt-wash-info); }
.nt-ocard-status--cancelled, .nt-ocard-status--skipped { color: var(--nt-muted); background: var(--nt-wash); }
.nt-ocard-status--proposed { color: var(--nt-shell); background: var(--nt-spruce); }
.nt-ocard-who { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; min-height: 22px; margin-top: 6px; }
.nt-ocard-buyer { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nt-ocard-buyer { font-size: 13.5px; font-weight: 600; color: var(--nt-ink); }
.nt-ocard-phone { font-family: var(--nt-font-mono); font-size: 11px; color: var(--nt-ink-2); background: var(--nt-wash); border-radius: 5px; padding: 1px 6px; }
.nt-ocard-unknown { font-size: 12px; font-weight: 600; color: var(--nt-warn); background: var(--nt-wash-warn); border-radius: 10px; padding: 2px 9px; text-decoration: none; }
a.nt-ocard-unknown:hover { text-decoration: underline; }
.nt-ocard-problem { font-size: 11.5px; font-weight: 600; color: var(--nt-bad); background: var(--nt-wash-bad); border-radius: 10px; padding: 1px 8px; }

/* Pack steppers. */
.nt-ocard-packs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; margin: 10px 0 0; }
.nt-ocard-pack { display: flex; flex-direction: column; gap: 1px; padding: 3px 2px; border: 1px solid var(--nt-line); border-radius: 8px; background: var(--nt-paper); min-width: 0; }
.nt-ocard-pack.is-on { background: var(--nt-saffron-wash); border-color: var(--nt-saffron-wash-3); }
.nt-ocard-pack-label { font-size: 11px; font-weight: 600; color: var(--nt-muted); text-align: center; }
.nt-ocard-pack-row { display: flex; align-items: center; justify-content: space-between; }
.nt-ocard-step { flex-shrink: 0; width: 26px; height: 26px; border: 0; border-radius: 6px; background: transparent; color: var(--nt-ink);
  display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0; }
.nt-ocard-step:hover { background: var(--nt-shell); }
.nt-ocard-qty { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-size: 14px; font-weight: 600; color: var(--nt-ink); text-align: center; }
input.nt-ocard-qty { width: 100%; min-width: 0; border: 0; background: transparent; padding: 0; -moz-appearance: textfield; appearance: textfield; }
input.nt-ocard-qty::-webkit-outer-spin-button, input.nt-ocard-qty::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
input.nt-ocard-qty:focus { outline: 2px solid var(--nt-saffron-deep); border-radius: 4px; }
.nt-ocard-packs.is-read .nt-ocard-qty { display: block; padding: 3px 0; }

/* Money, footer, actions. */
.nt-ocard-due { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.nt-ocard-due-label { font-size: 12px; color: var(--nt-muted); }
.nt-ocard-money { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; font-size: 16px; font-weight: 600; color: var(--nt-ink); }
.nt-ocard-right { margin-left: auto; font-size: 15px; }
.nt-ocard-disc { font-size: 11px; color: var(--nt-muted); }
.nt-ocard-offers { display: flex; flex-wrap: wrap; gap: 4px 14px; border: 0; margin: 0; padding: 0; }
.nt-ocard-offers legend { width: 100%; margin: 0; float: none; }
.nt-ocard-offer-choice { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--nt-ink); }
/* An offer a person added (an optional discount rule, e.g. Pre-order 15%). */
.nt-ocard-offer-chip { font-size: 11px; font-weight: 600; white-space: nowrap; color: var(--nt-ok); background: var(--nt-wash-ok); border-radius: 10px; padding: 1px 8px; }
.nt-ocard-pay { margin-left: auto; white-space: nowrap; font-size: 11.5px; font-weight: 600; border-radius: 10px; padding: 1px 8px; border: 1px solid transparent; }
.nt-ocard-pay--verified { color: var(--nt-ok); background: var(--nt-wash-ok); }
.nt-ocard-pay--unverified { color: var(--nt-ink-2); background: var(--nt-carton); }
.nt-ocard-pay--mismatch { color: var(--nt-bad); background: var(--nt-wash-bad); }
.nt-ocard-pay--unpaid { color: var(--nt-bad); background: var(--nt-shell); border-color: var(--nt-edge-bad, var(--nt-bad)); }
.nt-ocard-packtext { font-family: var(--nt-font-mono); font-size: 12.5px; font-weight: 600; color: var(--nt-ink); background: var(--nt-shell);
  border: 1px solid var(--nt-rule); border-radius: 6px; padding: 3px 8px; }
.nt-ocard-sentence { margin: 8px 0 0; font-size: 12px; color: var(--nt-bad); }
.nt-ocard-foot { display: flex; align-items: center; gap: 4px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--nt-line); }
.nt-ocard-grow { flex: 1; }
.nt-ocard-icon { width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; color: var(--nt-ink-2); border-radius: 7px; flex-shrink: 0; }
.nt-ocard-iconbtn { border: 0; background: transparent; cursor: pointer; padding: 0; }
.nt-ocard-iconbtn:hover { background: var(--nt-wash); color: var(--nt-ink); }
.nt-ocard-copy { display: contents; }
.nt-ocard-form { display: contents; }
.nt-ocard-primary { height: 30px; padding: 0 12px; border: 0; border-radius: 8px; background: var(--nt-spruce); color: var(--nt-shell);
  font: 600 12.5px var(--nt-font-body); display: inline-flex; align-items: center; justify-content: center; gap: 6px; cursor: pointer;
  text-decoration: none; white-space: nowrap; }
.nt-ocard-primary:hover { background: var(--nt-spruce-2); color: var(--nt-shell); }
.nt-ocard-ghostbtn { height: 30px; padding: 0 12px; border: 1px solid var(--nt-rule); border-radius: 8px; background: var(--nt-shell); color: var(--nt-ink);
  font: 600 12.5px var(--nt-font-body); display: inline-flex; align-items: center; justify-content: center; gap: 6px; cursor: pointer; text-decoration: none; box-sizing: border-box; }
.nt-ocard-ghostbtn:hover { background: var(--nt-wash); color: var(--nt-ink); }
.nt-ocard-done { display: flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 600; color: var(--nt-ok); }
.nt-ocard-menu .nt-menu-list { top: auto; bottom: 38px; width: 220px; }
.nt-ocard-more { width: 30px; height: 30px; }

/* The ⋯ Edit panel and the add card's form. */
.nt-ocard-edit, .nt-ocard-addform { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.nt-ocard-edit { padding-top: 10px; border-top: 1px dashed var(--nt-rule); }
.nt-ocard-edit[hidden], .nt-ocard-addform[hidden], .nt-ocard-addbtn[hidden] { display: none; }
.nt-ocard-field { display: flex; flex-direction: column; gap: 4px; margin: 0; font-size: 12px; font-weight: 600; color: var(--nt-muted); }
.nt-ocard-input { width: 100%; height: 32px; box-sizing: border-box; padding: 0 9px; border: 1px solid var(--nt-edge); border-radius: 7px;
  background: var(--nt-shell); color: var(--nt-ink); font: 13.5px var(--nt-font-body); }
.nt-ocard-mono { font-family: var(--nt-font-mono); }
.nt-ocard-hint { margin: -4px 0 0; font-size: 11.5px; color: var(--nt-muted); }
.nt-ocard-edit-actions { display: flex; gap: 6px; }
.nt-ocard-edit-actions > :first-child { flex: 1; }
.nt-ocard-add { min-width: 0; }
.nt-ocard-addbtn { width: 100%; min-height: 236px; border: 1.5px dashed var(--nt-edge); border-radius: 12px; background: transparent; color: var(--nt-ink-2);
  font: 600 14px var(--nt-font-body); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; cursor: pointer; }
.nt-ocard-addbtn:hover { background: var(--nt-shell); }
.nt-ocard-addkey { font-family: var(--nt-font-mono); font-size: 11px; font-weight: 500; color: var(--nt-muted); }
.nt-ocard-add.is-open { padding: 12px; border: 1.5px dashed var(--nt-spruce); border-radius: 12px; background: var(--nt-shell); }
.nt-ocard-add.is-open .nt-ocard-addform { margin-top: 0; }
.nt-ocard-save { height: 30px; border: 0; border-radius: 8px; background: var(--nt-saffron); color: var(--nt-ink); font: 700 13px var(--nt-font-body); cursor: pointer; }

/* NT Agent's ghost cards. */
.nt-ghosts { display: flex; flex-direction: column; gap: 8px; margin-bottom: 8px; }
.nt-ghosts-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; color: var(--nt-spruce); }
.nt-ghosts-title { font-size: 13.5px; font-weight: 700; color: var(--nt-ink); }
.nt-ghosts-sub { font-size: 12px; color: var(--nt-muted); }
.nt-ghosts-actions { margin-left: auto; display: flex; gap: 6px; }
.nt-ocard--ghost { border: 1.5px dashed var(--nt-spruce); background: var(--nt-saffron-wash-2); box-shadow: none; }
.nt-ocard-cite { display: block; margin-top: 8px; font-size: 12px; color: var(--nt-link); text-decoration: none; }
a.nt-ocard-cite:hover { text-decoration: underline; }
.nt-ocard-ghostacts { display: flex; gap: 6px; margin-top: 10px; }
.nt-ocard-ghostacts > form { display: contents; }
.nt-ocard-ghostacts button { flex: 1; }
/* A proposed change to a row (cancel, confirm, remarks, a payment): one line. */
.nt-ocard-change { margin: 8px 0 0; font-size: 13px; font-weight: 600; color: var(--nt-ink); line-height: 1.35; }
.nt-ocard-quote { font-weight: 400; color: var(--nt-ink-2); }
.nt-ocard--ghost-cancel-row, .nt-ocard--ghost-remove-row { border-color: var(--nt-bad); background: var(--nt-wash-bad); }
.nt-ocard--ghost-cancel-row .nt-ocard-status--proposed, .nt-ocard--ghost-remove-row .nt-ocard-status--proposed { background: var(--nt-bad); }
.nt-ocard--ghost-cancel-row .nt-ocard-hint, .nt-ocard--ghost-remove-row .nt-ocard-hint { color: var(--nt-bad); font-weight: 600; }
.nt-ocard--ghost-cancel-row .nt-ocard-flat, .nt-ocard--ghost-remove-row .nt-ocard-flat { text-decoration: line-through; text-decoration-color: var(--nt-bad); }
/* The drawer's answer: its proposals as the same cards, one column. */
.nt-agent-ghosts { display: grid; gap: 8px; margin-top: 8px; container-type: normal; }
.nt-agent-ghosts .nt-ocard { display: block; }

/* Taking orders off: the card's in-page confirm, and Select mode. */
.nt-ocard-danger { height: 30px; padding: 0 12px; border: 0; border-radius: 8px; background: var(--nt-bad); color: var(--nt-shell);
  font: 600 12.5px var(--nt-font-body); display: inline-flex; align-items: center; justify-content: center; gap: 6px; cursor: pointer; white-space: nowrap; }
.nt-ocard-danger:hover { filter: brightness(.92); }
.nt-ocard-danger:focus-visible, .nt-ocards-select:focus-visible, .nt-ocard-pick input:focus-visible { outline: 2px solid var(--nt-saffron-deep); outline-offset: 2px; }
.nt-ocard-ghostbtn--bad { color: var(--nt-bad); border-color: var(--nt-bad); }
.nt-ocard-ghostbtn--bad:hover { background: var(--nt-wash-bad); color: var(--nt-bad); }
.nt-ocard-confirm { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; padding: 10px; border: 1px solid var(--nt-bad);
  border-radius: 10px; background: var(--nt-wash-bad); }
.nt-ocard-confirm[hidden], .nt-ocards-bulk[hidden], .nt-ocards-bulk-confirm[hidden], .nt-ocard-ghostbtn[hidden], .nt-ghosts-confirm[hidden] { display: none; }
.nt-ocard-confirm-text { margin: 0; font-size: 13px; font-weight: 600; color: var(--nt-ink); }
.nt-ocards-select { height: 30px; padding: 0 11px; border: 1px solid var(--nt-rule); border-radius: 8px; background: var(--nt-shell); color: var(--nt-ink-2);
  font: 600 12.5px var(--nt-font-body); display: inline-flex; align-items: center; gap: 5px; cursor: pointer; }
.nt-ocards-select[aria-pressed="true"] { border-color: var(--nt-spruce); background: var(--nt-spruce); color: var(--nt-shell); }
.nt-ocards-bulk { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 8px 10px; border: 1px solid var(--nt-spruce);
  border-radius: 10px; background: var(--nt-shell); position: sticky; top: 0; z-index: 6; }
.nt-ocards-bulk-count { font-size: 13px; font-weight: 600; color: var(--nt-ink); }
.nt-ocards-bulk-actions { margin-left: auto; display: flex; gap: 6px; flex-wrap: wrap; }
.nt-ocards-bulk-confirm { flex-basis: 100%; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 8px 10px;
  border: 1px solid var(--nt-bad); border-radius: 8px; background: var(--nt-wash-bad); }
.nt-ocards-bulk-confirm .nt-ocard-edit-actions { margin-left: auto; }
.nt-ocard-pick { display: none; align-items: center; justify-content: center; margin: -4px 2px -4px -4px; width: 30px; height: 30px; cursor: pointer; flex: none; }
.nt-ocard-pick input { width: 18px; height: 18px; margin: 0; accent-color: var(--nt-spruce); cursor: pointer; }
.nt-ocards.is-selecting .nt-ocard-pick { display: inline-flex; }
.nt-ocard:has(.nt-ocard-pick input:checked) { border-color: var(--nt-spruce); box-shadow: 0 0 0 1px var(--nt-spruce); }
/* A cancelled sheet says so, with Reopen for who may. */
.nt-sheet-banner { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 12px; padding: 10px 14px; border: 1px solid var(--nt-bad);
  border-radius: 10px; background: var(--nt-wash-bad); color: var(--nt-ink); font-size: 13.5px; }
.nt-sheet-banner strong { color: var(--nt-bad); }
.nt-sheet-banner-sub { color: var(--nt-ink-2); font-size: 12.5px; }
.nt-sheet-banner form { margin-left: auto; }
.nt-ghosts-note { font-size: 12px; font-weight: 600; color: var(--nt-bad); }
.nt-apply-all { position: relative; display: inline-flex; }
.nt-agent-approve-list { margin: 8px 0; padding-left: 18px; font-size: 13px; display: grid; gap: 3px; }
.nt-agent-approve-list .is-bad { color: var(--nt-bad); }
.nt-ghosts-confirm { position: absolute; right: 0; top: calc(100% + 6px); z-index: 20; width: min(380px, calc(100vw - 32px));
  display: flex; flex-direction: column; gap: 6px; padding: 12px; border: 1px solid var(--nt-spruce); border-radius: 10px;
  background: var(--nt-shell); color: var(--nt-ink); font-size: 13px; text-align: left; box-shadow: 0 6px 20px rgba(10, 32, 30, .16); }
.nt-ghosts-confirm-line { margin: 0; }
/* Inside an answer's card (overflow: hidden) and anywhere in the drawer or
   the Agents page, a floating panel is clipped to its button — so there the
   confirm opens inline, under the button, across the full width. */
.nt-agent-card-foot .nt-apply-all, .nt-drawer-panel .nt-apply-all, .nt-agents-conv .nt-apply-all { flex-direction: column; align-items: flex-start; gap: 8px; }
.nt-agent-card-foot .nt-apply-all:has(> .nt-ghosts-confirm:not([hidden])),
.nt-drawer-panel .nt-apply-all:has(> .nt-ghosts-confirm:not([hidden])),
.nt-agents-conv .nt-apply-all:has(> .nt-ghosts-confirm:not([hidden])) { flex-basis: 100%; width: 100%; }
.nt-agent-card-foot .nt-ghosts-confirm, .nt-drawer-panel .nt-ghosts-confirm, .nt-agents-conv .nt-ghosts-confirm {
  position: static; width: 100%; box-shadow: none; }
.nt-ghosts-confirm ul { margin: 0; padding-left: 18px; max-height: 40vh; overflow: auto; }
.nt-ghosts-confirm .is-bad { color: var(--nt-bad); font-weight: 600; }
@media (max-width: 640px) {
  .nt-ocard-danger, .nt-ocards-select { height: 44px; padding: 0 16px; font-size: 14px; }
  .nt-ocard-pick { width: 44px; height: 44px; }
  .nt-ocard-pick input { width: 22px; height: 22px; }
  .nt-sheet-banner form, .nt-sheet-banner button { width: 100%; margin-left: 0; }
}

/* The totals bar's one line (phone). */
.nt-sheet-totals-line { display: none; }

/* Phone: one column, chips scroll sideways, 44px targets, one-line totals. */
@media (max-width: 640px) {
  .nt-ocards-grid { grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .nt-ocards-bar { flex-direction: column; align-items: stretch; }
  .nt-ocards-chips { flex-wrap: nowrap; overflow-x: auto; margin: 0 -16px; padding: 0 16px 2px; scrollbar-width: none; }
  .nt-ocards-chip { height: 40px; border-radius: 20px; }
  .nt-ocards-tools { margin-left: 0; }
  .nt-ocards-search { flex: 1; width: auto; height: 40px; }
  .nt-ocards-sort button { height: 34px; }
  .nt-ocards-sub { display: none; }
  .nt-ocard-flat { font-size: 22px; }
  .nt-ocard-step { width: 44px; height: 40px; }
  .nt-ocard-qty { font-size: 16px; }
  .nt-ocard-icon, .nt-ocard-more { width: 44px; height: 44px; }
  .nt-ocard-primary, .nt-ocard-ghostbtn, .nt-ocard-save { height: 44px; padding: 0 16px; font-size: 14px; }
  .nt-ocard-input { height: 44px; }
  .nt-ocard-addbtn { min-height: 120px; }
  .nt-ghosts-actions .nt-ocard-primary, .nt-ghosts-actions .nt-ocard-ghostbtn { height: 40px; }
  .nt-sheet-totals > .nt-sheet-totals-cell { display: none; }
  .nt-sheet-totals-line { display: flex; align-items: center; gap: 10px; width: 100%; padding: 12px 16px; font-size: 13px; }
  .nt-sheet-totals-line .nt-sheet-totals-num { font-size: 13px; }
  .nt-sheet-totals-push { margin-left: auto; }
  .nt-sheet-totals-line .is-strong { font-weight: 700; }
  .nt-sheet-totals-dot { color: var(--nt-muted); }
}
.nt-ocard-offer { display: block; margin-top: 6px; font-size: 12px; color: var(--nt-link); }
.nt-sheet-main, .nt-ocards, .nt-ocards-bar > * { min-width: 0; }
@media (max-width: 640px) { .nt-ocards-bar { width: 100%; max-width: 100%; } .nt-ocards-chips { max-width: calc(100% + 32px); } }
.nt-ocard-lines { margin: 4px 0 0; font-size: 11.5px; color: var(--nt-muted); }
.nt-ocard-remarks { display: flex; align-items: flex-start; gap: 5px; width: 100%; margin: 6px 0 0; padding: 0; border: 0; background: none;
  font: inherit; font-size: 12px; line-height: 1.35; color: var(--nt-ink-2, var(--nt-muted)); text-align: left; }
.nt-ocard-remarks svg { flex: none; margin-top: 2px; color: var(--nt-muted); }
button.nt-ocard-remarks { cursor: pointer; }
.nt-ocard-followup { width: 100%; margin: 6px 0 0; }
button.nt-ocard-remarks:hover span { text-decoration: underline; text-decoration-color: var(--nt-muted); }

/* Wide: one order per line, full width — flat, buyer, packs, due, actions —
   and anything else on the card (edit form, receipt offer, sentence, cite)
   drops to a full-width line under it. Measured on the cards' own width, so
   an open payment panel beside them folds them back into stacked cards. */
.nt-ocards { container: ocards / inline-size; }
@container ocards (min-width: 900px) {
  .nt-ocards-grid { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .nt-ocard { display: grid; align-items: center; padding: 10px 14px; column-gap: 12px;
    grid-template-columns: 120px minmax(110px, 1fr) minmax(220px, 260px) minmax(160px, 200px) 210px; }
  .nt-ocard > .nt-ocard-due { flex-wrap: wrap; }
  .nt-ocard > * { grid-column: 1 / -1; }
  .nt-ocard > .nt-ocard-top { grid-column: 1; grid-row: 1; flex-direction: column; gap: 4px; }
  .nt-ocard > .nt-ocard-top .nt-ocard-status { margin-left: 0; }
  .nt-ocard > .nt-ocard-who { grid-column: 2; grid-row: 1; margin-top: 0; }
  .nt-ocard > .nt-ocard-packs { grid-column: 3; grid-row: 1; margin: 0; }
  .nt-ocard > .nt-ocard-due { grid-column: 4; grid-row: 1; margin-top: 0; }
  .nt-ocard > .nt-ocard-foot { grid-column: 5; grid-row: 1; margin: 0; padding: 0; border-top: 0; justify-content: flex-end; }
  .nt-ocard--ghost > .nt-ocard-due, .nt-ocard--ghost > .nt-ocard-change { grid-column: 3 / 5; grid-row: 1; margin-top: 0; }
  .nt-ocard--ghost > .nt-ocard-ghostacts { grid-column: 5; grid-row: 1; margin-top: 0; justify-content: flex-end; }
  .nt-ocard--ghost > .nt-ocard-ghostacts button { flex: 0 0 auto; }
  .nt-ocard-cite, .nt-ocard-lines, .nt-ocard-offer, .nt-ocard-sentence { margin-top: 6px; }
  .nt-ocard-edit { flex-direction: row; flex-wrap: wrap; align-items: flex-end; }
  .nt-ocard-edit > .nt-ocard-field, .nt-ocard-edit > * { flex: 1 1 200px; }
  .nt-ocard-edit > .nt-ocard-edit-actions { flex: 0 0 auto; }
  .nt-ocard-addbtn { min-height: 52px; }
}

/* Match villas' cards in the community drawer (nt_agent/_villa_cards). */
.nt-villas-list { list-style: none; margin: 0; padding: 0; }
.nt-villa { padding: 9px 10px; border-top: 1px solid var(--nt-line); display: grid; gap: 4px; }
.nt-villa:first-child { border-top: 0; }
.nt-villa.is-decided { opacity: .65; }
.nt-villa.is-conflict { box-shadow: inset 3px 0 0 var(--nt-warn); }
.nt-villa-cite { font-size: 12px; color: var(--nt-muted); }
.nt-villa-note { display: block; font-size: 12px; color: var(--nt-muted); }
.nt-villa-conflict { color: var(--nt-warn); font-weight: 600; }
.nt-villa-acts { display: flex; gap: 8px; flex-wrap: wrap; }
@media (max-width: 720px) { .nt-villa-btn { min-height: 44px; } }

/* Buyer search on "+ Add order" / Edit buyer (buyer_search_controller). */
.nt-buyer-search { position: relative; }
.nt-buyer-results { position: absolute; z-index: 30; left: 0; right: 0; top: 100%; margin: 4px 0 0; padding: 4px; list-style: none;
  background: var(--nt-shell); border: 1px solid var(--nt-rule); border-radius: 9px; box-shadow: 0 8px 24px rgb(0 0 0 / .12);
  max-height: 280px; overflow-y: auto; }
.nt-buyer-results[hidden] { display: none; }
.nt-buyer-option { display: flex; flex-direction: column; justify-content: center; min-height: 40px; padding: 6px 9px; border-radius: 7px; cursor: pointer; }
.nt-buyer-option[aria-selected="true"], .nt-buyer-option:hover { background: var(--nt-wash); }
.nt-buyer-option-sub { font-size: 12px; color: var(--nt-muted); }
.nt-buyer-empty { padding: 8px 9px; font-size: 13px; color: var(--nt-muted); }
@media (max-width: 720px) { .nt-buyer-option { min-height: 44px; } }

/* ---- The sheet's top card (#sheet_head): Facts, Figures, Settings
   (mockups/sheet-head-and-runner-sheet.html). Tiles sit on a hairline
   ground, so the rules follow whatever the grid does on a phone. */
.nt-sheet-head.nt-hcard { padding: 0; margin-bottom: 12px; overflow: visible; }
.nt-hfacts { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 22px; padding: 14px 18px; border-bottom: 1px solid var(--nt-line); }
.nt-hfact { display: inline-flex; align-items: center; gap: 7px; min-width: 0; font-size: 13px; color: var(--nt-ink-2); }
.nt-hfact b { color: var(--nt-ink); font-weight: 600; }
.nt-hfact .nt-icon { flex-shrink: 0; color: var(--nt-muted); }
.nt-hfact a { color: var(--nt-link); font-weight: 600; text-decoration: none; }
.nt-hfact a:hover { text-decoration: underline; }
.nt-hfact-note b { font-weight: 500; }
.nt-hchip-phone { font: 11px var(--nt-font-mono); background: var(--nt-wash); border-radius: 5px; padding: 1px 6px; color: var(--nt-ink-2); }
.nt-htiles { display: grid; grid-template-columns: 1.1fr 1.2fr 1fr 1.3fr 1fr; gap: 1px; background: var(--nt-line);
  border-bottom: 1px solid var(--nt-line); }
.nt-htiles.is-plain { grid-template-columns: 1fr 1.6fr; }
.nt-htiles .nt-sheet-money { display: contents; }
.nt-htile { display: flex; flex-direction: column; gap: 6px; min-width: 0; padding: 14px 18px; background: var(--nt-shell); }
.nt-hlabel { font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--nt-muted); }
.nt-hbig { font: 700 26px/1 var(--nt-font-display); font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.nt-hbig.is-money { font: 600 22px/1.1 var(--nt-font-mono); }
.nt-hbig.is-ok { color: var(--nt-ok); }
.nt-hbig.is-bad { color: var(--nt-bad); }
.nt-hsub { font-size: 12px; color: var(--nt-muted); }
.nt-hsub a { color: var(--nt-link); font-weight: 600; text-decoration: none; }
.nt-hbar { display: flex; height: 6px; border-radius: 3px; background: var(--nt-carton); overflow: hidden; }
.nt-hbar i { display: block; height: 100%; }
.nt-hbar i.is-ok { background: var(--nt-ok); }
.nt-hbar i.is-draft { background: var(--nt-saffron); }
.nt-hpacks { display: flex; flex-wrap: wrap; gap: 6px; }
.nt-hpk { font: 600 12px var(--nt-font-mono); background: var(--nt-saffron-wash); border-radius: 6px; padding: 2px 7px; color: var(--nt-ink); }
.nt-hmono { font-family: var(--nt-font-mono); font-variant-numeric: tabular-nums; }

.nt-hcontrols { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 12px 18px;
  background: var(--nt-saffron-wash-2); border-radius: 0 0 var(--nt-r-pane) var(--nt-r-pane); }
.nt-hctl { position: relative; display: flex; align-items: center; gap: 8px; padding: 5px 6px 5px 11px; font-size: 13px;
  background: var(--nt-shell); border: 1px solid var(--nt-line); border-radius: 10px; }
.nt-hctl-main { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.nt-hctl-acts { display: inline-flex; align-items: center; gap: 6px; }
.nt-hctl-k { color: var(--nt-muted); font-size: 12px; }
.nt-hctl b { font-weight: 600; }
.nt-hdot { width: 8px; height: 8px; border-radius: 50%; background: var(--nt-ok); display: inline-block; }
.nt-hdot.is-off { background: var(--nt-edge); }
.nt-hctl.is-runner { margin-left: auto; background: var(--nt-spruce); border-color: var(--nt-spruce); color: var(--nt-shell); }
.nt-hctl.is-runner .nt-hctl-k { color: var(--nt-shell); opacity: .85; }
.nt-hctl.is-runner > .nt-hctl-acts .nt-hbtn { background: transparent; border-color: rgba(255, 255, 255, .35); color: var(--nt-shell); }
.nt-hctl.is-runner > .nt-hctl-acts .nt-hbtn:hover { background: var(--nt-spruce-2); }
.nt-hform { display: inline-flex; margin: 0; }
.nt-hcopy { display: inline-flex; }
.nt-hbtn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 28px; padding: 0 10px;
  border-radius: 8px; border: 1px solid var(--nt-rule); background: var(--nt-shell); color: var(--nt-ink);
  font: 600 12.5px var(--nt-font-body); white-space: nowrap; text-decoration: none; cursor: pointer; }
.nt-hbtn:hover { background: var(--nt-wash); color: var(--nt-ink); }
.nt-hbtn:focus-visible, .nt-hquick button:focus-visible { outline: 2px solid var(--nt-saffron-deep); outline-offset: 2px; }
.nt-hbtn.is-pri { background: var(--nt-spruce); border-color: var(--nt-spruce); color: var(--nt-shell); }
.nt-hbtn.is-pri:hover { background: var(--nt-spruce-2); }
.nt-hbtn.is-link { border: 0; background: transparent; color: var(--nt-bad); padding: 0; height: auto; }
.nt-hpop { position: absolute; top: calc(100% + 8px); left: 0; z-index: 20; width: 272px; max-width: calc(100vw - 32px);
  display: flex; flex-direction: column; gap: 9px; padding: 12px; color: var(--nt-ink);
  background: var(--nt-shell); border: 1px solid var(--nt-rule); border-radius: 12px; box-shadow: 0 10px 30px rgba(10, 32, 30, .18); }
.nt-hpop[hidden] { display: none; }
.nt-hpop.is-end { left: auto; right: 0; }
.nt-hpop-form { display: flex; flex-direction: column; gap: 9px; margin: 0; }
.nt-hpop-form > label { font-size: 12px; font-weight: 600; color: var(--nt-muted); }
.nt-hpop-form input[type=number], .nt-hpop-form input[type=datetime-local] { height: 34px; padding: 0 9px; font: 14px var(--nt-font-mono);
  border: 1px solid var(--nt-edge); border-radius: 7px; background: var(--nt-shell); color: var(--nt-ink); }
.nt-hpop-row { display: flex; gap: 6px; flex-wrap: wrap; }
.nt-hquick { display: flex; gap: 5px; flex-wrap: wrap; }
.nt-hquick button { font: 12px var(--nt-font-body); border: 1px solid var(--nt-rule); border-radius: 12px; padding: 1px 9px;
  background: var(--nt-shell); color: var(--nt-ink-2); cursor: pointer; }
.nt-hquick button:hover { background: var(--nt-wash); }
.nt-htoggle { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 500; color: var(--nt-ink); }
.nt-htoggle input { width: 18px; height: 18px; accent-color: var(--nt-spruce); }

@media (max-width: 980px) {
  .nt-htiles { grid-template-columns: 1fr 1fr; }
  .nt-hctl.is-runner { margin-left: 0; }
}
/* Phone: two tiles to a row with Eggs across, and each setting one
   full-width row with 44px targets. */
@media (max-width: 640px) {
  .nt-hfacts { padding: 12px 14px; gap: 6px 14px; }
  .nt-htile { padding: 11px 14px; }
  .nt-hbig { font-size: 22px; }
  .nt-htiles.is-plain { grid-template-columns: 1fr 1fr; }
  .nt-htile.nt-htile-eggs { grid-column: 1 / -1; order: 2; }
  .nt-htile.is-outstanding { order: 1; }
  .nt-htile.is-due, .nt-htile.is-collected { order: 3; }
  .nt-hcontrols { padding: 10px 12px; gap: 8px; }
  .nt-hctl { flex: 1 1 100%; justify-content: space-between; min-height: 44px; }
  .nt-hbtn { height: 44px; padding: 0 14px; font-size: 13px; }
  .nt-hquick button { min-height: 36px; padding: 0 12px; }
  .nt-hpop { width: auto; left: 0; right: 0; max-width: none; }
}

/* The sheet's Members quick view in the drawer (sheet_members/show). */
.nt-hfact-link { color: inherit; text-decoration: none; border-radius: 8px; }
.nt-hfact-link:hover { color: var(--nt-link); }
.nt-hfact-key { font-size: 10.5px; padding: 0 4px; border-radius: 4px; background: var(--nt-shell); color: var(--nt-muted); }
.nt-smembers-search { display: flex; gap: 6px; margin-bottom: 10px; }
.nt-smembers-summary { margin: 0 0 8px; font-size: 12px; color: var(--nt-muted); }
.nt-smembers-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.nt-smembers-row { padding: 8px 10px; border: 1px solid var(--nt-line); border-radius: 10px; }
.nt-smembers-top { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.nt-smembers-name { font-weight: 700; color: var(--nt-ink); }
.nt-smembers-flat { font-family: var(--nt-font-mono); font-size: 12px; color: var(--nt-ink-2); }
.nt-smembers-mark { margin-left: auto; font-size: 11px; font-weight: 600; color: var(--nt-muted); }
.nt-smembers-mark.is-on { color: var(--nt-spruce); }
.nt-smembers-sub { margin-top: 2px; font-size: 12px; color: var(--nt-ink-2); }
.nt-smembers-phone { display: flex; align-items: center; gap: 6px; margin-top: 6px; font-size: 12.5px; }
.nt-smembers-btn { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border: 1px solid var(--nt-line);
  border-radius: 8px; background: none; font: inherit; font-size: 12px; color: var(--nt-ink); text-decoration: none; cursor: pointer; }

/* The chat's NT Agent (nt_agent/_chat_cards): a draft reply, editable in place. */
.nt-chat-draft-form { margin: 0; }
.nt-chat-draft-text { display: block; width: 100%; box-sizing: border-box; border: 0; border-top: 1px solid var(--nt-line);
  padding: 10px 12px; font: inherit; font-size: 12.5px; line-height: 1.55; color: var(--nt-ink); background: transparent; resize: vertical; }
.nt-chat-draft-text:focus { outline: 2px solid var(--nt-spruce-soft); outline-offset: -2px; }
.nt-chat-draft-quote { margin: 0; padding: 6px 12px; font-size: 11.5px; color: var(--nt-ink-3, var(--nt-ink)); border-top: 1px solid var(--nt-line); }
.nt-thread-agent { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
