:root {
  /* Neutral greys with no blue in them, and a near-white menu. The blue-grey
     undertone is what Sarah named, 2026-10-04: "maybe it's the gray undertone
     just makes it look like an old school app", then "build it". UX-001. */
  color-scheme: light;
  --background: #f7f7f8;
  --foreground: #18181b;
  --card: #ffffff;
  --card-foreground: #18181b;
  --primary: #3f66d7;
  --primary-foreground: #ffffff;
  --secondary: #f4f4f5;
  --muted-foreground: #71717a;
  --accent: #eef3ff;
  --destructive: #bd3f31;
  --border: #ebebed;
  --input: #d4d4d8;
  /* The chrome steps down from the content area rather than matching it: the
     rail is darkest, then the sidebar, then the page. #f4f6f8 against a #f6f7f9
     background was a difference of one shade and read as no difference at all. */
  --sidebar: #fbfbfb;
  --sidebar-foreground: #27272a;
  --rail: #f4f4f5;
  --rail-foreground: #52525b;
  --chrome-line: #ebebed;
  --sidebar-line: #ebebed;
  --chrome-hover: rgba(24, 24, 27, .05);
  --chrome-panel: rgba(24, 24, 27, .03);
  --chrome-field: rgba(255, 255, 255, .85);
  --chrome-field-line: rgba(0, 0, 0, .16);
  --radius: 12px;
  --radius-sm: 8px;
  --client-1-color: #4353c9;
  --client-2-color: #0e7c86;
  --client-3-color: #b8790e;
  --client-4-color: #1f8a5f;
  --client-5-color: #a23e7c;
  --client-6-color: #c1502d;
  --client-7-color: #6a3fa0;
  --client-8-color: #47586b;
  --client-9-color: #b23b4e;
  --client-10-color: #1f7dbd;
  --client-11-color: #707c1f;
  --client-12-color: #1f3f73;
  --tone-neutral-bg: #f4f4f5;
  --tone-neutral-fg: #52525b;
  --tone-info-bg: #e8efff;
  --tone-info-fg: #3764bd;
  --tone-active-bg: #e2f3f2;
  --tone-active-fg: #377882;
  --tone-ready-bg: #fff4cf;
  --tone-ready-fg: #9b6b13;
  --tone-review-bg: #f1e9fb;
  --tone-review-fg: #7a42b2;
  --tone-warn-bg: #fde8dd;
  --tone-warn-fg: #b9482e;
  --tone-approved-bg: #e1f5e9;
  --tone-approved-fg: #2f7d52;
  --tone-done-bg: #eaf1f0;
  --tone-done-fg: #607d7b;
}

body[data-theme="dark"] {
  color-scheme: dark;
  --background: #111318;
  --foreground: #f1f3f5;
  --card: #191c22;
  --card-foreground: #f1f3f5;
  --secondary: #232832;
  --muted-foreground: #9da9b7;
  --accent: #203654;
  --border: #333740;
  --input: #3a4756;
  --sidebar: #20232a;
  --sidebar-foreground: #f1f3f5;
  --rail: #17191f;
  --rail-foreground: #b8bec8;
  --chrome-line: color-mix(in srgb, white 8%, transparent);
  --sidebar-line: color-mix(in srgb, black 20%, transparent);
  --chrome-hover: color-mix(in srgb, white 10%, transparent);
  --chrome-panel: color-mix(in srgb, white 6%, transparent);
  --chrome-field: color-mix(in srgb, black 16%, transparent);
  --chrome-field-line: color-mix(in srgb, white 16%, transparent);
  --client-1-color: #9aa4f5;
  --client-2-color: #6fdbe2;
  --client-3-color: #f0c066;
  --client-4-color: #74e0ac;
  --client-5-color: #e79bcd;
  --client-6-color: #f4ac82;
  --client-7-color: #c9a8ee;
  --client-8-color: #adbecd;
  --client-9-color: #f2a3ae;
  --client-10-color: #8cc9f0;
  --client-11-color: #c7d47f;
  --client-12-color: #9fb8e8;
  --tone-neutral-bg: #26313b;
  --tone-neutral-fg: #b5c0cc;
  --tone-info-bg: #18345f;
  --tone-info-fg: #9fc4ff;
  --tone-active-bg: #163f40;
  --tone-active-fg: #8ed7d2;
  --tone-ready-bg: #493816;
  --tone-ready-fg: #f1c66d;
  --tone-review-bg: #39284e;
  --tone-review-fg: #ceb2f3;
  --tone-warn-bg: #4a241d;
  --tone-warn-fg: #f1a28f;
  --tone-approved-bg: #183d28;
  --tone-approved-fg: #92d7ad;
  --tone-done-bg: #243236;
  --tone-done-fg: #abc0c2;
}

/* The accent: one color each person picks, a preset or their own, set on
   body as --accent-base with --accent-ink for text on it. The tint and the dark
   mode version are mixed from it here, so any color works in both themes.
   THEME-001, patch 430. */
body[data-accent="custom"] {
  --primary: var(--accent-base);
  --primary-foreground: var(--accent-ink);
  --accent: color-mix(in srgb, var(--accent-base) 11%, white);
}

body[data-theme="dark"][data-accent="custom"] {
  --primary: color-mix(in oklab, var(--accent-base) 62%, white);
  --primary-foreground: #14171a;
  --accent: color-mix(in srgb, var(--accent-base) 24%, #121417);
}

* {
  box-sizing: border-box;
}

html {
  background: var(--background);
}

body {
  margin: 0;
  min-height: 100vh;
  /* Manrope, loaded in the layouts, with the system font behind it; its
     letters a little apart. Inter, pulled .005em tight, until patch 771.
     Sarah, 2026-10-24: "the kerning is close ... separated would give a font
     a sense of space", then "C is clearly better". UX-040. */
  font-family: Manrope, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  letter-spacing: .025em;
  -webkit-font-smoothing: antialiased;
  font-size: 14px;
  line-height: 1.5;
  color: var(--foreground);
  background: var(--background);
}

/* The rail and the menu sit under the header, because they belong to the
   workspace rather than above it. Sarah, 2026-09-29. NAV-001. */
.app-body {
  display: grid;
  grid-template-columns: 58px 188px minmax(0, 1fr);
  min-height: calc(100vh - 52px);
}

body.limited-shell .app-body {
  grid-template-columns: 188px minmax(0, 1fr);
}

/* The one row across the top: the product, then the workspace, what is waiting
   and the account. */
.app-header {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 52px;
  border-bottom: 1px solid var(--chrome-line);
  background: var(--sidebar);
  color: var(--sidebar-foreground);
  padding: 6px 16px;
}

.app-header .brand { padding: 0; color: inherit; text-decoration: none; }
.app-header .brand:hover strong { color: var(--primary); }
.app-header-actions { display: flex; align-items: center; gap: 10px; min-width: 0; }
.bell-button.invite-link { display: none; }
.workspace-name { color: var(--muted-foreground); font-size: 13px; font-weight: 600; }

/* A red dot with the number in it, which is the whole message. */
.alert-count {
  display: inline-grid;
  place-items: center;
  min-width: 24px;
  height: 24px;
  border-radius: 999px;
  background: var(--destructive);
  color: #ffffff;
  padding: 0 7px;
  font-size: 12px;
  font-weight: 600;
  text-decoration: none;
}
.alert-count:hover { filter: brightness(1.08); }

/* The account, with logout inside its menu rather than beside it. A details
   element, so it opens before any script runs. */
.user-menu { position: relative; }
.user-menu > summary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--chrome-field-line);
  border-radius: 999px;
  background: var(--chrome-field);
  padding: 3px 10px 3px 3px;
  cursor: pointer;
  list-style: none;
  font-size: 13px;
}
.user-menu > summary::-webkit-details-marker { display: none; }
.user-menu > summary:hover { border-color: var(--primary); }
.user-menu-who { display: grid; gap: 0; line-height: 1.25; }
.user-menu-who > strong { font-weight: 600; }
.user-menu-who > span { color: var(--muted-foreground); font-size: 11px; }
.user-menu-panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 30;
  display: grid;
  min-width: 180px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  box-shadow: 0 14px 34px rgba(19, 34, 38, .16);
  padding: 6px;
}
.user-menu-panel a,
.user-menu-panel button {
  justify-content: flex-start;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--foreground);
  padding: 8px 10px;
  font-size: 13px;
  font-weight: 400;
  text-align: left;
  text-decoration: none;
}
.user-menu-panel a:hover,
.user-menu-panel button:hover { background: var(--secondary); }
.user-menu-panel form { margin: 0; display: grid; }

a {
  color: inherit;
}

.app-rail {
  /* The hover labels sit outside the rail, so it must not clip them. */
  overflow: visible;
  position: sticky;
  top: 0;
  z-index: 5;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  border-right: 1px solid var(--chrome-line);
  background: var(--rail);
}

/* The collapse control, a real button since 2026-09-16. It was a decorative ☰
   wired to nothing. What it collapses is the menu beside the rail: the rail of
   letters stays, which is the standard arrangement and the reason the rail is
   there. NAV-001. */
.rail-top {
  width: 100%;
  height: 48px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-bottom: 1px solid var(--chrome-line);
  background: none;
  color: var(--rail-foreground);
  font: inherit;
  line-height: 1;
  cursor: pointer;
}

.rail-top:hover,
.rail-top:focus-visible {
  color: white;
  background: color-mix(in srgb, var(--primary) 82%, white 4%);
}

/* Two borders rotated into a chevron, so this needs no icon font and inherits
   its colour. It points the way the menu will move. */
.rail-caret {
  width: 8px;
  height: 8px;
  margin-left: 2px;
  border-left: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform .12s ease;
}

html.rail-collapsed .rail-caret {
  margin-left: -2px;
  transform: rotate(-135deg);
}

/* Only where there is a rail to collapse into. A limited user gets no rail, so
   hiding their menu would leave them with no navigation at all; and below 760px
   the layout is not this grid and the caret is hidden anyway. */
@media (min-width: 761px) {
  /* Two columns, not a zero-width middle one. The hidden menu leaves the grid
     entirely, so with three columns the main area was placed in the empty
     middle one - 0px wide - and every page squeezed into a column of single
     words with its cards on top of each other. Measured on the live System
     page on 2026-09-18: 0px collapsed, 1207px with this. UX-021. */
  /* The grid moved onto .app-body in patch 361 when the header took the top
     row, and this rule kept pointing at body - so collapsing hid the menu and
     left its 188px column empty. Sarah, 2026-09-29: *"when you collapse the 2nd
     menu the main area doesn't expand to take it up making the value of
     collapsing none."* */
  html.rail-collapsed body:not(.limited-shell) .app-body {
    grid-template-columns: 58px minmax(0, 1fr);
  }

  html.rail-collapsed body:not(.limited-shell) .sidebar {
    display: none;
  }

  /* The rail is the height of the window, not of the page, so Admin at its foot
     is always in view. It was as tall as the page, which on People put Admin
     1,262px down. NAV-001. */
  .app-rail { align-self: start; top: 52px; min-height: 0; height: calc(100vh - 52px); }
}

.rail-nav {
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 10px 8px;
}

/* The line between the work and the people, and the space that puts Admin at
   the bottom. NAV-001. */
/* Written as .rail-nav .x so they outrank .rail-nav span, which draws the
   boxed letters; patch 414 had them as plain classes and the line came out as
   one more empty box. */
/* Two pixels at half the strength of the letters: the 1px hairline in 415 was
   barely visible. Sarah, 2026-10-03. Mixed from the rail's own text color, so it
   holds up in dark mode too. */
.rail-nav .rail-rule { display: block; flex: none; width: 28px; height: 2px; margin: 4px 0; border: 0; border-radius: 1px; background: color-mix(in srgb, var(--rail-foreground) 50%, transparent); }
.rail-nav .rail-push { display: block; flex: 1 1 auto; width: auto; height: auto; border: 0; }

.rail-nav a {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: 9px;
  color: var(--rail-foreground);
  text-decoration: none;
}

.rail-nav a:hover,
.rail-nav a.active {
  color: white;
  background: color-mix(in srgb, var(--primary) 82%, white 4%);
}

/* The rail is a column of single letters, and a letter is only obvious once you
   already know what it means. `title` was doing this job badly: about a second
   of delay, no styling, and it appears wherever the pointer happens to be. This
   names the item immediately, beside it, in the app's own type.

   `position: relative` on the link and `left: 100%` on the label means the rail
   itself must not clip - hence `overflow: visible` above it. */
.rail-nav a {
  position: relative;
}
.rail-nav a::after {
  content: attr(data-rail-label);
  position: absolute;
  left: calc(100% + 10px);
  top: 50%;
  z-index: 20;
  transform: translateY(-50%);
  padding: 5px 9px;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: var(--card);
  color: var(--foreground);
  box-shadow: 0 4px 14px rgba(19, 34, 38, .16);
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity .12s ease;
}
.rail-nav a:hover::after,
.rail-nav a:focus-visible::after { opacity: 1; }
/* A touch screen has no hover, and the label would otherwise stick after a tap. */
@media (hover: none) {
  .rail-nav a::after { content: none; }
}

.rail-nav span {
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  border: 1px solid color-mix(in srgb, currentColor 45%, transparent);
  border-radius: 7px;
  font-size: 10px;
  font-weight: 600;
  line-height: 1;
}

/* Home on a band of its own above the space's rail, a light tint of the main
   color, so it reads as the one part that stays put. NAV-009, patch 656. */
.rail-home { width: 100%; display: grid; place-items: center; padding: 8px 0; border-bottom: 1px solid color-mix(in srgb, var(--primary) 14%, var(--chrome-line)); background: color-mix(in srgb, var(--primary) 9%, var(--rail)); }
.rail-home a { position: relative; width: 38px; height: 38px; display: grid; place-items: center; border-radius: 9px; color: var(--rail-foreground); text-decoration: none; }
.rail-home a:hover, .rail-home a.active { color: white; background: color-mix(in srgb, var(--primary) 82%, white 4%); }
.rail-home svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linejoin: round; }
/* The rail's line icons, drawn as Home's is, at the rail's own size. Patch 751. */
.rail-nav .rail-ico { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.rail-home a::after { content: attr(data-rail-label); position: absolute; left: calc(100% + 10px); top: 50%; z-index: 20; transform: translateY(-50%); padding: 5px 9px; border: 1px solid var(--border); border-radius: 7px; background: var(--card); color: var(--foreground); box-shadow: 0 4px 14px rgba(19, 34, 38, .16); font-size: 12px; font-weight: 600; line-height: 1; white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity .12s ease; }
.rail-home a:hover::after, .rail-home a:focus-visible::after { opacity: 1; }
@media (hover: none) { .rail-home a::after { content: none; } }
/* Whose menu this is, at its top. Patch 656. */
.nav-space { display: flex; align-items: center; gap: 8px; min-width: 0; margin: 0 0 8px; padding: 2px 8px 10px; border-bottom: 1px solid var(--border); color: var(--foreground); font-size: 13px; font-weight: 600; }
.nav-space span:last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-space .home-nav-pic { width: 24px; height: 24px; }
/* Your home's menu: Your home at its head, then Your spaces, which filter
   the Feed. NAV-009, patch 657. */
.nav-space-home { display: grid; place-items: center; flex: none; width: 24px; height: 24px; border-radius: 7px; background: color-mix(in srgb, var(--primary) 12%, var(--card)); color: var(--primary); }
.nav-space-home svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; }
.home-nav-link.active { background: color-mix(in srgb, var(--primary) 10%, transparent); color: color-mix(in srgb, var(--primary) 88%, #000000); box-shadow: none; }
.home-nav-link.active .home-nav-name { font-weight: 600; }
.home-nav-pic.is-all { background: var(--secondary); color: var(--muted-foreground); font-size: 13px; }
.home-nav-go-mark { flex: none; color: var(--muted-foreground); }
.home-nav-open { flex: none; margin: 0; }
.home-nav-open button { min-height: 28px; border: 0; border-radius: 6px; background: none; padding: 0 6px; color: var(--primary); font-size: 11.5px; font-weight: 600; box-shadow: none; cursor: pointer; white-space: nowrap; }
.home-nav-open button:hover { background: var(--secondary); }
/* Open always shows on a group's row: on hover only it was buried. Sarah,
   2026-10-18. Patch 667. */
.home-nav.is-editing .home-nav-open { display: none; }
/* The eye in Edit: in All spaces, or kept out of it. Patch 658. */
.home-nav-eye { display: grid; place-items: center; flex: none; width: 28px; height: 28px; min-height: 0; margin: 0; border: 1px solid var(--border); border-radius: 6px; background: var(--card); padding: 0; color: var(--foreground); box-shadow: none; cursor: pointer; }
.home-nav-eye[hidden] { display: none; }
.home-nav-eye svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
.home-nav-eye-off { display: none; }
.home-nav-eye[aria-pressed="false"] { color: var(--muted-foreground); }
.home-nav-eye[aria-pressed="false"] .home-nav-eye-off { display: inline; }
.home-nav-link.is-off .home-nav-name, .home-nav-link.is-off .home-nav-pic { opacity: .5; }
/* While editing, the eye takes the picture's place, so the names keep their
   room in the menu. Names cut to a letter at 815 in the patch 658 test. */
.home-nav.is-editing .home-nav-eye { order: -1; }
.home-nav.is-editing .home-nav-row:has([data-home-eye]) .home-nav-pic { display: none; }

.sidebar {
  position: sticky;
  top: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--sidebar-line);
  background: var(--sidebar);
  color: var(--sidebar-foreground);
}

/* The phone band, its menu button, and what the button opens. All three are off
   entirely on a desktop, where the second menu is a column of its own and says
   the same word at its top; the rules that turn them on live in the 760px block
   with the rest of the phone shell. NAV-001, MOBILE-001. */
.nav-band,
.nav-sheet-toggle,
.nav-sheet-backdrop,
.phone-menu { display: none; }

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 16px 12px;
}

.brand-mark {
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border-radius: 7px;
  color: var(--primary-foreground);
  background: var(--primary);
  font-size: 16px;
  font-weight: 800;
  line-height: 1;
}

.brand strong {
  display: block;
  font-size: 13px;
}

/* The signed-out brand line, drawn by partials/auth-brand.php on all three of
   login, create account and password reset - it was a placeholder letter C on
   each, left from the old product name. The wordmark carries it alone here:
   the wordmark already contains the r, so a mark beside it drew the same
   letter twice within an inch of itself. */
.auth-brand {
  padding: 0 0 28px;
}

.auth-brand strong {
  font-size: 28px;
  letter-spacing: .01em;
}

/* The mark, in the sidebar, where there is no wordmark and something has to
   stand for the product. It replaced a diamond glyph in a coloured square. */
.brand-mark-img {
  width: 32px;
  height: 32px;
  object-fit: contain;
}

.brand-by {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--muted-foreground);
  font-size: 14px;
}

/* Set large on purpose, and larger than it first looks like it should be. The
   wordmark is mid-grey (#808080) fine-lined type whose letters fill only about
   three quarters of the image height, so the number here is roughly double the
   size the word actually comes out at. Two rounds of raising it were still too
   small to read comfortably; this is the size where the name reads as a name. */
.brand-by img {
  display: block;
  width: auto;
  height: 54px;
}

.sidebar .brand span,
.workspace span {
  color: color-mix(in srgb, var(--sidebar-foreground) 56%, transparent);
}

.muted,
small {
  color: var(--muted-foreground);
}

.context-nav {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 3px;
  padding: 0 8px;
}

.nav-label {
  padding: 14px 8px 5px;
  color: var(--muted-foreground);
  font-size: 12px;
  font-weight: 500;
}

.context-nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  /* A little more room and air: 34px rows, 14px, letters at their natural
     spacing. Sarah, 2026-10-22: "the menu items are too close together. The
     kerning of the letters could be a little bit more". Patch 751. */
  min-height: 34px;
  padding: 7px 10px;
  border-radius: 8px;
  color: color-mix(in srgb, var(--sidebar-foreground) 88%, transparent);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0;
}

/* An icon before each item, and a project's client logo or initial, added by
   assets/js/nav-icons.js. Sarah, 2026-10-04: icons in the menus, and "the
   project icon should be the client logo unless something else is selected".
   NAV-001, UX-001. */
.context-nav .nav-ico { flex: none; width: 16px; height: 16px; color: color-mix(in srgb, var(--sidebar-foreground) 42%, transparent); }
.context-nav .nav-logo { flex: none; width: 20px; height: 20px; padding: 1px; border-radius: 5px; background: #fff; object-fit: contain; box-shadow: 0 0 0 1px rgba(24, 24, 27, .08); }
.context-nav .nav-initial { flex: none; display: inline-grid; place-items: center; width: 20px; height: 20px; border-radius: 5px; background: var(--mark, var(--primary)); color: #fff; font-size: 10px; font-weight: 600; }

/* A page under another in the menu - the reports under Reports. SYS-011. */
.context-nav a.nav-child { padding-left: 24px; font-weight: 400; }
.context-nav a.nav-child.is-deeper { padding-left: 35px; }

.context-nav a:hover {
  color: var(--sidebar-foreground);
  background: var(--chrome-hover);
}
/* Where you are: a soft fill in your accent, with no edge or shadow, so it
   reads as a place, not a button. Sarah, 2026-10-22: "not be buttons". Patch 751. */
.context-nav a.active {
  color: color-mix(in srgb, var(--primary) 88%, #000000);
  background: color-mix(in srgb, var(--primary) 10%, transparent);
  box-shadow: none;
}
.context-nav a.active .nav-ico { color: var(--primary); }
.context-nav a.nav-more { color: var(--muted-foreground); }

.nav-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 3px;
}

.nav-editing .nav-row {
  grid-template-columns: auto minmax(0, 1fr) auto;
}

.nav-row > a {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nav-inline-form {
  margin: 0;
}

.nav-head-actions {
  display: flex;
  align-items: center;
  gap: 4px;
}

.nav-edit-action {
  display: none;
}

.nav-editing .nav-edit-action {
  display: grid;
}

.nav-drag-handle {
  width: 22px;
  height: 24px;
  place-items: center;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: color-mix(in srgb, var(--sidebar-foreground) 58%, transparent);
  cursor: grab;
  padding: 0;
  font-size: 12px;
  letter-spacing: -3px;
  line-height: 1;
}

.nav-drag-handle:active {
  cursor: grabbing;
}

.nav-inline-form button {
  width: 21px;
  height: 24px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: color-mix(in srgb, var(--sidebar-foreground) 58%, transparent);
  padding: 0;
  font-size: 15px;
  line-height: 1;
}

.nav-row:hover .nav-inline-form button,
.nav-inline-form button:focus,
.nav-drag-handle:hover,
.nav-drag-handle:focus {
  background: var(--chrome-hover);
  color: var(--sidebar-foreground);
}

.nav-row.is-dragging {
  opacity: .55;
}

/* Favorites, the star and the drag, with no Edit mode. NAV-001.
   The star shows on a row you point at, and stays lit on a favorite. */
.nav-row { cursor: default; }
.nav-star {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  min-height: 0;
  margin: 0;
  border: 0;
  border-radius: 6px;
  background: transparent;
  padding: 0;
  color: color-mix(in srgb, var(--sidebar-foreground) 45%, transparent);
  opacity: 0;
  cursor: pointer;
}
.nav-star svg { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linejoin: round; }
.nav-row:hover .nav-star, .nav-star:focus-visible { opacity: 1; }
.nav-star:hover { background: var(--chrome-hover); color: var(--sidebar-foreground); }
.nav-star.is-on { opacity: 1; color: #d4a017; }
.nav-star.is-on svg { fill: currentColor; }
/* In Favorites itself every star is lit, so it only shows on the row you are on. */
.nav-favorites .nav-star.is-on { opacity: 0; }
.nav-favorites .nav-row:hover .nav-star.is-on { opacity: 1; }

.nav-favorites { display: grid; gap: 1px; margin-bottom: 4px; border-radius: 8px; }
.nav-favorites.is-empty { display: none; }
body.nav-dragging .nav-favorites.is-empty { display: grid; min-height: 64px; }
body.nav-dragging .nav-favorites { outline: 1px dashed color-mix(in srgb, var(--sidebar-foreground) 22%, transparent); outline-offset: 2px; }
.nav-favorites.is-drop { outline-color: var(--primary); background: color-mix(in srgb, var(--accent) 45%, transparent); }
.nav-row.is-ghost { opacity: .6; }
.nav-row[draggable="true"]:active { cursor: grabbing; }

.nav-rename-input {
  width: 100%;
  min-height: 30px;
  margin: 1px 0;
  border-color: var(--primary);
  background: var(--card);
  padding: 4px 8px;
  font-size: 13.5px;
}

/* The way back to hidden items, under their list. */
.nav-hidden-toggle {
  justify-self: start;
  min-height: 0;
  margin: 2px 0 0;
  border: 0;
  background: transparent;
  padding: 4px 8px;
  color: var(--muted-foreground);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
}
.nav-hidden-toggle:hover { color: var(--sidebar-foreground); background: transparent; }
.nav-editor button.nav-editor-quiet { border-color: transparent; background: transparent; color: var(--muted-foreground); font-weight: 500; }
.nav-editor button.nav-editor-quiet:hover { color: var(--destructive); }

.nav-divider {
  height: 1px;
  margin: 7px 8px;
  background: color-mix(in srgb, var(--sidebar-foreground) 12%, transparent);
}

.nav-subhead {
  min-height: 30px;
  margin-top: 7px;
  padding-bottom: 4px;
  /* Plain case, like the other headings, since patch 447. UX-001. */
  color: var(--muted-foreground);
  font-size: 12px;
}

.nav-editor {
  display: grid;
  gap: 7px;
  margin: 7px 0 9px;
  border: 1px solid var(--chrome-line);
  border-radius: 7px;
  background: var(--chrome-panel);
  padding: 8px;
}

.nav-editor[hidden] {
  display: none;
}

.nav-editor label:not(.checkbox-line) {
  display: grid;
  gap: 4px;
  color: color-mix(in srgb, var(--sidebar-foreground) 68%, transparent);
  font-size: 10px;
  font-weight: 800;
  text-transform: uppercase;
}

.nav-editor input,
.nav-editor select {
  width: 100%;
  min-height: 30px;
  border-color: var(--chrome-field-line);
  background: var(--chrome-field);
  color: var(--sidebar-foreground);
  font-size: 12px;
}

.nav-editor button {
  min-height: 30px;
  border: 1px solid var(--chrome-field-line);
  border-radius: 7px;
  background: color-mix(in srgb, var(--primary) 72%, black 8%);
  color: white;
  font-size: 12px;
  font-weight: 800;
}

.nav-section-head {
  min-height: 38px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px;
  color: var(--sidebar-foreground);
  font-size: 13px;
  /* 600 is the cap in this app; this one was written at 800 before that. */
  font-weight: 600;
}

.nav-section-head > span {
  color: var(--muted-foreground);
  font-size: 12px;
  font-weight: 500;
}

.nav-section-head button,
.nav-section-head a {
  min-height: 26px;
  width: auto;
  /* A plain control that tints on hover, not an outlined box. Patch 751. */
  border: 1px solid transparent;
  border-radius: 7px;
  background: transparent;
  color: var(--sidebar-foreground);
  padding: 3px 8px;
  font-size: 12px;
  font-weight: 600;
  text-decoration: none;
}

.nav-empty {
  margin: 0;
  padding: 4px 8px;
  color: color-mix(in srgb, var(--sidebar-foreground) 62%, transparent);
  font-size: 12px;
  line-height: 1.4;
}

.nav-more {
  margin-top: 4px;
  color: var(--sidebar-foreground);
}

.workspace {
  margin: 8px;
  padding: 10px;
  border-top: 1px solid var(--chrome-line);
  border-radius: 7px;
  background: var(--chrome-panel);
  font-size: 12px;
  font-weight: 650;
}

.app-frame {
  min-width: 0;
}

.workspace-switcher {
  margin: 0;
}

.workspace-switcher label {
  display: flex;
  align-items: center;
  gap: 8px;
}

.workspace-switcher span {
  color: var(--muted-foreground);
  font-size: 12px;
  font-weight: 700;
}

.workspace-switcher select {
  min-height: 32px;
  width: min(320px, 42vw);
  border-radius: 999px;
  padding: 4px 28px 4px 10px;
  font-size: 13px;
}

.report-mail-note { margin: 4px 0 0; color: var(--muted-foreground); font-size: 12px; }

/* Who you are, when you are not the owner. A strip, not a banner: it is a
   permanent condition for a partner or a client, so it must not read as an
   error. The left edge carries the role colour; the bar itself stays quiet. */
.role-strip {
  border-bottom: 1px solid var(--border);
  border-left: 3px solid var(--muted-foreground);
  background: var(--secondary);
  padding: 5px 16px;
  color: var(--muted-foreground);
  font-size: 12px;
}
.role-strip strong { color: var(--foreground); font-weight: 650; }
.role-strip--partner { border-left-color: var(--tone-review-fg, var(--primary)); }
.role-strip--client { border-left-color: var(--tone-approved-fg, var(--primary)); }
.role-strip--vendor { border-left-color: var(--tone-warn-fg, var(--primary)); }

.logout-form {
  margin: 0;
}

.logout-button {
  min-height: 32px;
  border-color: var(--border);
  background: var(--card);
  color: var(--muted-foreground);
  padding: 5px 10px;
  font-size: 12px;
}

.logout-button:hover {
  border-color: var(--destructive);
  background: var(--card);
  color: var(--destructive);
}

.avatar {
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  color: white;
  background: var(--primary);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
}

/* Always the last column of the page grid, so no hidden panel before it can
   shift it into a narrower one. UX-021. */
.app-frame { grid-column: -2 / -1; min-width: 0; }

.main {
  padding: 20px 24px 28px;
}

.page-header {
  margin-bottom: 14px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

h1,
h2,
h3,
p {
  margin-top: 0;
}

h1 {
  margin-bottom: 4px;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 0;
}

h2 {
  margin-bottom: 10px;
  font-size: 15px;
  font-weight: 700;
}

h3 {
  margin-bottom: 8px;
  /* 15px: a section heading at 13px sat smaller than the 14px words under
     it. Patch 827. */
  font-size: 15px;
  font-weight: 700;
}

.page-header p {
  margin-bottom: 0;
  color: var(--muted-foreground);
}

/* The grey band names the page, so the page does not say it again: the title is
   kept for a screen reader, the subtext goes. UX-025. */
.header-in-band .page-header { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

.card,
.quick-panel,
.setup-card,
.stat-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--card-foreground);
  box-shadow: 0 1px 2px rgba(19, 34, 38, .04);
}

.quick-panel {
  margin-bottom: 14px;
  padding: 10px;
}

.quick-form {
  display: grid;
  grid-template-columns: minmax(220px, 1fr) minmax(170px, 220px) minmax(140px, 170px) auto;
  gap: 10px;
}

/* The Tasks quick-add has five fields - title, project, assignee, due date,
   button - in a four-column grid, so the button dropped to a row of its own.
   The same fault as the Projects add bar in patch 165.
   Flex rather than a five-column template, because the assignee select only
   exists in a team workspace: a fixed count is wrong for one mode or the other,
   and this is right for both. */
/* Two lines in four columns: the title and the detail above, then the project,
   the assignee, the date and the button. It used to run the full width of the
   page as one line, which is the length Sarah asked to cut. UX-020. */
.quick-form[data-task-form] {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  align-items: center;
}
.quick-form[data-task-form] > input[name="title"],
.quick-form[data-task-form] > input[name="description"] { grid-column: span 2; }
.quick-form[data-task-form] > select { width: auto; }
/* An individual workspace has no assignee, so the project takes that slot and
   the second line still fills. */
.quick-form[data-task-form]:not(:has(select)) > .typeahead { grid-column: span 2; }

/* A phone keeps the two that decide where a task lands: its name and its
   project. The detail, the assignee and the date are set by opening the task,
   which is what the small screen has room for. Sarah, 2026-09-29. */
@media (max-width: 760px) {
  .quick-form[data-task-form] { grid-template-columns: minmax(0, 1fr) auto; }
  .quick-form[data-task-form] > input[name="title"] { grid-column: span 2; }
  .quick-form[data-task-form] > .typeahead { grid-column: span 1; }
  .quick-form[data-task-form] > input[name="description"],
  .quick-form[data-task-form] > select,
  .quick-form[data-task-form] > input[type="date"] { display: none; }
}

input,
select,
textarea,
button,
.button {
  min-height: 34px;
  border-radius: 7px;
  border: 1px solid var(--input);
  font: inherit;
  font-size: 13px;
}

/* A checkbox or radio is its own size. The 34px above made each one a tall box
   with the tick drawn in its middle, so beside a line of text it hung below it.
   Sarah, 2026-10-03, on Create a new workspace. */
input[type="checkbox"],
input[type="radio"] {
  flex: none;
  min-height: 0;
  height: auto;
}

input,
select,
textarea {
  width: 100%;
  padding: 7px 10px;
  color: var(--foreground);
  background: var(--card);
}

textarea {
  min-height: 112px;
  resize: vertical;
}

/* Buttons are outlines, not blocks.
 *
 * Every button used to be a solid slab of --primary, so a screen with six of
 * them read as six equally urgent demands and the page had no quiet state at
 * all. They are now an accent outline with accent text, which is why the
 * lettering follows whichever accent the person picked - --primary is set by
 * body[data-accent], so the theme choice reaches the type rather than only the
 * fill. Filling in on hover keeps the affordance without shouting at rest.
 *
 * The exception is deliberate and narrow: `.is-primary` on the one action a
 * screen is actually asking for. If a page marks three things primary it has
 * not understood the point, and the reviewer should say so. See UX-001. */
button,
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 7px 12px;
  border-color: color-mix(in srgb, var(--primary) 45%, var(--border));
  color: var(--primary);
  background: transparent;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}

button:hover,
.button:hover {
  border-color: var(--primary);
  color: var(--primary);
  background: color-mix(in srgb, var(--primary) 10%, transparent);
}

button:focus-visible,
.button:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

button:disabled,
.button:disabled {
  border-color: var(--border);
  color: var(--muted-foreground);
  background: transparent;
  cursor: not-allowed;
  opacity: .6;
}

/* The one action a screen is asking for. Still an outline, but filled, so it
   reads as the answer to the page rather than as one option among six. */
button.is-primary,
.button.is-primary {
  color: var(--primary-foreground);
  background: var(--primary);
  border-color: var(--primary);
}
button.is-primary:hover,
.button.is-primary:hover {
  color: var(--primary-foreground);
  background: color-mix(in srgb, var(--primary) 84%, var(--foreground));
}

/* Now the quieter of two quiet things: neutral rather than accent, for an
   action that is genuinely secondary to the one beside it. */
.secondary-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 34px;
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 7px 12px;
  color: var(--muted-foreground);
  background: transparent;
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
}
.secondary-button:hover {
  border-color: color-mix(in srgb, var(--foreground) 30%, var(--border));
  color: var(--foreground);
  background: color-mix(in srgb, var(--foreground) 4%, transparent);
}

.form-error {
  margin: 0;
  border: 1px solid color-mix(in srgb, var(--destructive) 45%, var(--border));
  border-radius: 7px;
  padding: 9px 10px;
  color: var(--destructive);
  background: color-mix(in srgb, var(--destructive) 10%, var(--card));
  font-size: 13px;
}

/* Shared success counterpart to .form-error. Previously redefined inside
   several page <style> blocks, which left it unstyled on pages that used it
   without carrying their own copy. */
.form-success {
  margin: 0;
  border: 1px solid color-mix(in srgb, var(--tone-approved-fg) 35%, var(--border));
  border-radius: 7px;
  padding: 9px 10px;
  color: var(--tone-approved-fg);
  background: var(--tone-approved-bg);
  font-size: 13px;
}

/* Shared inline form row: fields and their button stay on one row while there
   is width for it, and wrap to full width below. */
.inline-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 16px 18px;
  margin: 0;
}

.inline-form label:not(.checkbox-line) {
  display: flex;
  flex: 1 1 220px;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  color: var(--muted-foreground);
  font-size: 12px;
  font-weight: 700;
}

.inline-form input,
.inline-form select {
  min-height: 40px;
}

.inline-form button {
  flex: 0 0 auto;
  min-height: 40px;
  padding: 0 20px;
  white-space: nowrap;
}

.inline-form .secondary-link {
  flex: 0 0 auto;
  align-self: center;
  padding-bottom: 10px;
}

@media (max-width: 760px) {
  .inline-form { align-items: stretch; }
  .inline-form label { flex-basis: 100%; }
  .inline-form button { width: 100%; }
}

/* Label and value pairs in a card, two across and one across on a phone. Shared
   so a card drawn on more than one page (the test freeze, QA-001) is styled
   wherever it lands rather than only on the page that first carried it. */
.detail-pairs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin: 0 0 16px; }
.detail-pairs > div { border-top: 1px solid var(--border); padding-top: 10px; min-width: 0; }
.detail-pairs > div > dt { color: var(--muted-foreground); font-size: 11px; font-weight: 600; text-transform: uppercase; }
.detail-pairs > div > dd { margin: 4px 0 0; color: var(--foreground); font-weight: 600; overflow-wrap: anywhere; }
@media (max-width: 760px) { .detail-pairs { grid-template-columns: 1fr; } }

/* The test freeze card: the tester list form and the record of past runs. */
.freeze-testers { display: grid; gap: 8px; margin: 18px 0 0; }
.freeze-testers > label { display: grid; gap: 6px; color: var(--muted-foreground); font-size: 12px; font-weight: 600; }
.freeze-testers > button { justify-self: start; }
.freeze-past-heading { margin: 20px 0 8px; font-size: 14px; font-weight: 600; }
.freeze-past { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
.freeze-past > li { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; border-bottom: 1px solid var(--border); padding-bottom: 8px; font-size: 13px; }
.freeze-past > li:last-child { border-bottom: 0; padding-bottom: 0; }
.freeze-past > li > .muted { font-size: 12px; }
@media (max-width: 760px) { .freeze-testers > button { justify-self: stretch; } }

/* Roomier variant of .data-table for admin screens with long rows. */
.data-table.is-wide { min-width: 1040px; }

.data-table.is-roomy th,
.data-table.is-roomy td {
  padding: 14px 16px;
  vertical-align: top;
}

.data-table.is-roomy td small {
  display: block;
  margin-top: 6px;
  color: var(--muted-foreground);
  line-height: 1.35;
}

.data-table .row-actions {
  min-width: 132px;
  white-space: nowrap;
}

.table-action-form {
  display: inline-flex;
  margin: 0;
}

.table-action-form button {
  min-height: 34px;
  padding: 0 16px;
}

/* Calendar events: things that happen, drawn as a run of chips across the days
   they cover. Only the first day carries the label so a multi-day run reads as
   one bar; the ends are rounded and the middle is square. */
.calendar-day-events {
  display: grid;
  gap: 2px;
  padding: 0 2px 3px;
}

.calendar-event {
  display: block;
  min-height: 16px;
  /* The client's colour, at the strength the task cards use. At 16% with a 3px
     edge an event read as grey, so an unfiltered calendar gave no clue whose it
     was. Sarah, 2026-09-29: *"events should share client color so it is obvious
     when not filtered (or filtered) who they belong to."* */
  border-left: 4px solid var(--client-color, var(--primary));
  background: color-mix(in srgb, var(--client-color, var(--primary)) 26%, var(--card));
  color: var(--foreground);
  padding: 2px 5px;
  font-size: 11px;
  line-height: 1.25;
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* An event chip truncates, and unlike a task card there is nothing to open to
   read the rest. The title attribute gives a native tooltip, which is slow and
   plain, so the chip expands over its neighbours on hover instead. */
.calendar-event:hover,
.calendar-event:focus-visible {
  position: relative;
  z-index: 5;
  overflow: visible;
  white-space: normal;
  box-shadow: 0 2px 10px rgba(19, 34, 38, .16);
}

.calendar-event.is-start { border-radius: 5px 0 0 5px; }
.calendar-event.is-end { border-radius: 0 5px 5px 0; }
.calendar-event.is-start.is-end { border-radius: 5px; }
.calendar-event:not(.is-start) { border-left-color: transparent; }
.calendar-event:hover { background: color-mix(in srgb, var(--client-color, var(--primary)) 28%, var(--card)); }
.calendar-event strong { font-weight: 600; }
/* Whose it is, said in the day view, where there is room for it. */
.calendar-event-client { color: var(--muted-foreground); font-weight: 400; }
.calendar-event-continues { display: block; min-height: 12px; }

/* An event on a single day is a tag; only a run across days keeps its bar.
   Sarah, 2026-09-29: tags in every case. */
.calendar-day-events.is-tags { display: flex; flex-wrap: wrap; gap: 3px; }
/* A run across days still takes the whole width of each cell it crosses; in a
   flex row it would otherwise shrink to its text and the run would break. */
.calendar-day-events.is-tags > .calendar-event:not(.is-tag) { flex: 1 1 100%; }
.calendar-event.is-tag {
  display: inline-block;
  width: auto;
  max-width: 100%;
  border-left: 0;
  border-radius: 999px;
  box-shadow: inset 0 0 0 1px var(--client-color, var(--primary));
  padding: 1px 8px;
}
.calendar-event.is-tag:hover { box-shadow: inset 0 0 0 1px var(--client-color, var(--primary)); }

/* A request marker: something the client asked for on this day, which nobody has
   agreed to yet. It has to read as provisional beside real work, so it drops the
   client colour entirely and takes a dashed outline instead of a solid left bar.
   Both rules are written at .calendar-event.is-request rather than at
   .is-request alone, because the base chip and its :hover both match at the same
   specificity and the last matching rule would otherwise decide the colour. */
.calendar-event.is-request,
.calendar-event.is-request:hover {
  border: 1px dashed color-mix(in srgb, var(--muted-foreground) 55%, transparent);
  border-left-width: 1px;
  border-radius: 5px;
  background: transparent;
  color: var(--muted-foreground);
  font-style: italic;
}
.calendar-event.is-request strong { font-weight: 600; }

/* A client's own event: a fact about their world, added by them. Dashed so the
   team can tell it from their own, but in the client colour and upright, since
   unlike a request it is already on the calendar. CAL-001. */
.calendar-event.is-client,
.calendar-event.is-client:hover {
  border: 1px dashed var(--client-color, var(--primary));
  border-left-width: 1px;
}
.calendar-event.is-client:not(.is-start) { border-left-color: transparent; }
.calendar-event.is-mine { cursor: pointer; }

/* The day number and the add control travel together, so the head keeps its
   weekday-left / number-right layout rather than spreading three children. */
.calendar-day-meta {
  display: flex;
  align-items: center;
  gap: 4px;
}

/* Adding is its own control so it never competes with dropping a task onto the
   day. A button since CAL-002 (it opens the day menu), so the shared button
   look is reset here. */
.calendar-day-add {
  display: grid;
  place-items: center;
  width: 16px;
  height: 16px;
  min-height: 0;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  border-radius: 5px;
  color: var(--muted-foreground);
  font-size: 13px;
  line-height: 1;
  text-decoration: none;
  opacity: 0;
}

.calendar-day:hover .calendar-day-add,
.calendar-day-add:focus-visible { opacity: 1; }
.calendar-day-add:hover { background: var(--secondary); color: var(--foreground); }
/* No hover on a touch screen, so the + is always there. CAL-002, UX-002. */
@media (hover: none) { .calendar-day-add { opacity: 1; } }

/* Press and hold opens the menu on a touch screen, so the system callout and
   the text selection that the same gesture would otherwise start are off on
   anything that carries a menu. Only there: the rest of the page stays
   selectable. UX-002. */
@media (hover: none) {
  [data-context-menu] {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
  }
}

/* The Add block: one component on the dashboard and on Tasks, holding a task, a
   project or an event behind three pills, and folding away on a phone. Sarah,
   2026-09-29: *"on mobile that the add block should just be collapsible. And it
   should be called add. And it opens up, and then you can see all the things in
   there."* MOBILE-001. */
.add-block {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
}

.add-block-head {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 44px;
  margin: 0;
  border: 0;
  border-radius: var(--radius) var(--radius) 0 0;
  background: transparent;
  color: var(--foreground);
  padding: 0 14px;
  font-size: 14px;
  font-weight: 600;
  text-align: left;
}

.add-block-head span { flex: 1 1 auto; }
.add-block-head svg:first-child { color: var(--primary); }
/* Nothing folds above a phone, so the caret would be pointing at nothing. */
.add-block-caret { display: none; }
.add-filter-proxy { display: none; }

.add-block-body {
  display: grid;
  gap: 10px;
  padding: 0 14px 14px;
}

.add-pills { display: flex; gap: 6px; }

.add-pill {
  min-height: 30px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card);
  color: var(--muted-foreground);
  padding: 0 13px;
  font-size: 12px;
  font-weight: 600;
}

.add-pill.is-on {
  border-color: color-mix(in srgb, var(--primary) 55%, var(--border));
  background: color-mix(in srgb, var(--accent) 65%, var(--card));
  color: color-mix(in srgb, var(--primary) 85%, #000000);
}

/* One row on a desktop, which is what the bars it replaces were. The `hidden`
   attribute has to be spelled out because `display: flex` here would otherwise
   beat the browser's own rule for it, and all three forms would show at once. */
.add-form {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: 10px;
}

.add-form[hidden] { display: none; }

.add-field { display: grid; gap: 4px; flex: 1 1 160px; min-width: 0; }
/* The project on a project page, said rather than asked. */
.add-field-fixed { display: flex; align-items: center; min-height: 38px; border: 1px dashed var(--border); border-radius: 7px; padding: 0 12px; color: var(--muted-foreground); font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.add-field.typeahead { position: relative; }
.add-field-label { color: var(--muted-foreground); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; }
.add-form > button { flex: 0 0 auto; }

/* On a phone: closed to begin with, and every field on its own line when it is
   open, because two fields side by side at 390 are two fields you cannot read. */
/* Another box folding the same way: its head shows only on a phone. */
.phone-fold-head { display: none; }

@media (max-width: 760px) {
  .phone-fold-head { display: flex; padding: 0 4px; }
  /* !important because the Add and Import switch shows its form by id, which
     outranks any class. Patch 411 shipped without it and did not fold. */
  [data-phone-fold].is-folded > :not(.phone-fold-head) { display: none !important; }
  [data-phone-fold].is-folded .add-block-caret { transform: rotate(-90deg); }
  /* A phone has Day, Week and Month again, drawn as phone calendars draw
     them; Planning stays a computer's. MOBILE-004, patch 781. */
  /* Filters as an icon at the right of a folded Add; Add spreads over it
     when opened. The page's own Filters button is hidden, its panel kept.
     MOBILE-001. */
  .add-block { position: relative; }
  body.has-filter-proxy .add-block.is-folded { margin-right: 52px; }
  .add-block.is-folded .add-filter-proxy:not([hidden]) { position: absolute; top: -1px; right: -53px; bottom: -1px; display: inline-flex; align-items: center; justify-content: center; gap: 3px; width: 44px; min-height: 0; margin: 0; border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); padding: 0; color: var(--foreground); }
  .add-filter-proxy.is-on { border-color: var(--primary); background: var(--accent); color: var(--primary); }
  .add-filter-count { font-size: 11px; font-weight: 600; }
  .add-filter-count:empty { display: none; }
  body.has-filter-proxy .view-toolbar .filter-open > .filter-button,
  body.has-filter-proxy .view-toolbar .filter-open > .filter-clear,
  body.has-filter-proxy .dash-filter > .filter-button { display: none; }
  body.has-filter-proxy .dashboard-zone:has(> .dash-filter) { padding: 0; border: 0; }
  .add-block.is-folded .add-block-body { display: none; }
  .add-block.is-folded .add-block-head { border-radius: var(--radius); }
  .add-block-caret { display: block; color: var(--muted-foreground); }
  .add-block.is-folded .add-block-caret { transform: rotate(-90deg); }
  .add-form { display: grid; gap: 10px; }
  .add-field { flex: none; }
}

/* A record page: the head, the tabs under it, and the two columns inside a tab.
   Written for the task page when it was rebuilt around tabs, and kept here
   rather than in that page, because every other detail page is getting the same
   shape. Sarah, 2026-10-01: *"make sure it is built in a way that its components
   can be shared."* UX-025. */
.record-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 14px;
}

.record-head-main { min-width: 0; }
.record-head h1 { margin: 0; font-size: 26px; font-weight: 600; line-height: 1.2; }
.record-head h1 .record-state { margin: 0 0 0 8px; vertical-align: 4px; }
/* The part of a record page refreshed after a background save. */
.record-top { display: block; }
/* The trail: Back, then where the record lives. Codex's wireframe, 2026-09-30. */
.record-crumbs { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; margin: 0 0 14px; color: var(--muted-foreground); font-size: 13px; }
.record-crumbs .back-link { margin: 0; }
.record-crumbs span::before { content: "/"; margin-right: 6px; color: var(--border); }
.record-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin: 7px 0 0; color: var(--muted-foreground); font-size: 13px; }
.record-meta > span + span::before,
.record-meta > .ticket-badge + span::before { content: "\00b7"; margin-right: 8px; }
.record-meta .ticket-badge { margin: 0; }
.record-meta-project { display: inline-flex; align-items: center; gap: 4px; }
/* A select that reads as words in a sentence until it is opened. */
.record-inline-control select { width: auto; min-height: 0; border: 0; background-color: transparent; padding: 0 18px 0 2px; color: var(--foreground); font-size: 13px; font-weight: 600; cursor: pointer; }
/* A select is as wide as its longest option, which put a gap the width of the
   longest project name before the arrow. field-sizing fits it to the one shown;
   where that is not supported, the cap keeps the gap small. Patch 389. */
.record-inline-control select { field-sizing: content; max-width: 440px; }
.record-actions { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.completion-form { display: flex; }
.complete-button { min-height: 38px; border: 0; background: var(--tone-approved-fg); color: #ffffff; }
.complete-button:hover { filter: brightness(1.06); }

/* The dots: everything that is not the one obvious action. */
.record-more { position: relative; }
.record-more > summary {
  display: grid;
  place-items: center;
  width: 38px;
  min-height: 38px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--card);
  color: var(--muted-foreground);
  list-style: none;
  cursor: pointer;
}
.record-more > summary::-webkit-details-marker { display: none; }
/* Share with someone, beside the dots, with how many it is shared with.
   Patches 609 and 611. */
.record-share-button { display: inline-flex; align-items: center; justify-content: center; gap: 4px; min-width: 38px; min-height: 38px; padding: 0 9px; border: 1px solid var(--border); border-radius: 8px; background: var(--card); color: var(--muted-foreground); font-size: 13px; font-weight: 600; box-shadow: none; }
.record-share-button:hover, .record-share-button:focus-visible { color: var(--foreground); }
.record-share-count { color: var(--foreground); }
.share-list { list-style: none; margin: 12px 0 4px; padding: 0; }
.share-list li { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 0; border-top: 1px solid var(--border); }
.share-list li:first-child { border-top: 0; }
.share-list-who { display: grid; min-width: 0; }
.share-list-who strong { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.share-list-who small { color: var(--muted-foreground); font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.share-list-remove { display: inline-grid; place-items: center; flex: 0 0 auto; width: 38px; height: 38px; min-height: 0; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--muted-foreground); font-size: 20px; line-height: 1; box-shadow: none; }
.share-list-remove:hover, .share-list-remove:focus-visible { background: var(--secondary); color: var(--foreground); }
.record-more-menu {
  position: absolute;
  z-index: 20;
  top: calc(100% + 6px);
  right: 0;
  min-width: 170px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--card);
  box-shadow: 0 16px 40px rgba(19, 34, 38, .16);
  padding: 8px;
}

/* Text tabs with a line under the open one, for record pages. The open tab's
   colour and line come from partials/record-tabs.php. */
.view-tabs.is-underline { display: flex; gap: 28px; margin: 22px 0 20px; padding: 0; border: 0; border-bottom: 1px solid var(--border); border-radius: 0; background: transparent; }
.view-tabs.is-underline label { padding: 12px 1px 10px; border-bottom: 3px solid transparent; border-radius: 0; font-size: 14px; font-weight: 600; text-transform: none; letter-spacing: 0; }
.record-tabs .view-tabs label small {
  margin-left: 5px;
  padding: 1px 6px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--foreground) 9%, transparent);
  font-size: 10.5px;
}

/* The work and the talking, side by side; the rail drops under on a narrow
   screen rather than squeezing. */
.record-split { display: grid; grid-template-columns: minmax(0, 2fr) minmax(285px, .75fr); gap: 18px; align-items: start; }
.record-column { display: grid; gap: 14px; min-width: 0; }
.record-rail { display: grid; gap: 14px; min-width: 0; }

/* The rail is as wide as its column and no wider. Its grid had no minimum, so a
   long link that cannot wrap - a Dropbox address in Team notes - stretched the
   Team discussion card to 621px inside a 304px column and the page scrolled
   sideways. Sarah, 2026-10-03: "The task view is still making you scroll in
   the browser to the right to see the full right column." */
.record-rail { grid-template-columns: minmax(0, 1fr); }
.record-rail > *, .record-rail .card { min-width: 0; }
.record-rail .card { grid-template-columns: minmax(0, 1fr); }
.discussion-card, .discussion-note, .comment-list, .thread { overflow-wrap: anywhere; }

/* Every property on one row, as compact controls - status, who, when,
   priority, repeats. Sarah, 2026-10-02: "This should be on a single row." It
   wraps only when the window cannot hold it. Codex's wireframe, 2026-09-30. */
.record-props { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; padding: 14px; }
.record-prop { display: grid; gap: 5px; min-width: 0; margin: 0; }
.record-prop-label { color: var(--muted-foreground); font-size: 11.5px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase; }
.record-control { display: inline-flex; align-items: center; gap: 7px; min-height: 34px; border: 1px solid var(--border); border-radius: 6px; background: var(--card); padding: 0 8px; white-space: nowrap; }
.record-control select,
.record-control input[type="date"] { width: auto; min-height: 32px; border: 0; background-color: transparent; padding: 0 18px 0 0; color: var(--foreground); font-size: 13.5px; font-weight: 600; box-shadow: none; }
.record-control select { padding-right: 2px; }
.record-control input[type="date"] { padding-right: 0; }
.record-control:focus-within { border-color: var(--primary); }
.record-status-dot { width: 8px; height: 8px; flex: 0 0 auto; border-radius: 50%; background: var(--primary); }
.record-control.is-late,
.record-control.is-late input[type="date"] { color: color-mix(in srgb, var(--destructive) 88%, #000000); border-color: color-mix(in srgb, var(--destructive) 35%, var(--border)); }
.record-late { font-size: 13.5px; font-weight: 600; }
/* A control never runs past its column: a long late note drops under its
   date. Seen in the 739 test at 960. Patch 742. */
.task-details { min-width: 0; }
.record-prop { max-width: 100%; }
.record-control { max-width: 100%; }
/* Repeats, an icon beside the Due date: grey, or the main color when the
   task repeats; it opens a small menu. Patch 817 (the chips of 754 are gone). */
.due-control { position: relative; }
.repeat-pick { position: relative; display: inline-flex; }
.repeat-icon { display: inline-grid; place-items: center; width: 28px; height: 28px; border-radius: 6px; color: var(--muted-foreground); cursor: pointer; list-style: none; }
.repeat-icon::-webkit-details-marker { display: none; }
.repeat-icon:hover, .repeat-pick[open] > .repeat-icon { background: var(--secondary); color: var(--foreground); }
.repeat-icon.is-on { color: var(--primary); }
.repeat-pop { position: absolute; top: calc(100% + 6px); right: -8px; z-index: 40; display: grid; min-width: 210px; padding: 6px; border: 1px solid var(--border); border-radius: 8px; background: var(--card); box-shadow: 0 10px 30px rgba(15, 23, 42, .16); white-space: nowrap; }
.repeat-row { display: flex; align-items: center; gap: 8px; min-height: 36px; padding: 0 8px; border-radius: 6px; font-size: 14px; font-weight: 400; cursor: pointer; }
.repeat-row:hover { background: var(--secondary); }
.repeat-row input { width: 15px; height: 15px; min-height: 0; margin: 0; accent-color: var(--primary); }
.repeat-row.is-stop { color: var(--muted-foreground); }
.repeat-until { display: flex; align-items: center; gap: 8px; margin: 4px 0; padding: 6px 8px 2px; border-top: 1px solid var(--border); font-size: 13.5px; color: var(--muted-foreground); }
.repeat-until input { min-width: 0; flex: 1; min-height: 32px; }
.repeat-row[hidden], .repeat-until[hidden] { display: none; }
@media (max-width: 760px) { .repeat-icon { width: 44px; height: 44px; margin-right: -8px; } .repeat-row { min-height: 44px; } }
.record-check { display: inline-flex; align-items: center; gap: 8px; min-height: 34px; margin: 0; font-size: 13.5px; font-weight: 600; cursor: pointer; }
.record-check input { width: 17px; height: 17px; min-height: 0; margin: 0; }
@media (max-width: 780px) {
  .record-prop { flex: 1 1 140px; }
  .record-control { width: 100%; justify-content: space-between; }
}
@media (max-width: 460px) {
  .record-prop { flex-basis: 100%; }
}

/* A card with a title bar: the name on the left, one action or a count on the right. */
.record-card-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: -2px 0 14px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
.record-card-bar h2 { margin: 0; font-size: 16px; font-weight: 600; white-space: nowrap; }
/* In the narrow rail a heading and two buttons do not fit on one line, so the
   buttons go under the heading rather than squeezing it onto two. */
.record-rail .record-card-bar { flex-wrap: wrap; }
.record-card-body { display: grid; gap: 12px; }

/* The description: text to read, and Edit for the title and the text together. */
.record-brief .record-brief-edit-only { display: none; }
.record-brief.is-editing .record-brief-edit-only { display: grid; }
.record-brief-actions { grid-auto-flow: column; justify-content: end; gap: 8px; }

/* A sentence across the top of a tab saying whose move it is, with the same
   colours as the chip: green done, amber with the client, red ours to answer. */
.record-banner { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 11px; margin: 0 0 18px; border-radius: 8px; background: color-mix(in srgb, var(--primary) 9%, var(--card)); padding: 12px 15px; font-size: 13.5px; }
.record-banner strong { font-weight: 600; }
.record-banner::before { content: ""; width: 10px; height: 10px; flex: 0 0 auto; border-radius: 50%; background: var(--muted-foreground); }
.record-banner.is-done::before { background: var(--tone-approved-fg); }
.record-banner.is-waiting::before { background: #c58a10; }
.record-banner.is-late::before { background: var(--destructive); }
.record-bar-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px; }
.record-bar-actions form { display: flex; margin: 0; }
.record-bar-actions .secondary-button { min-height: 34px; }
.record-visibility { margin: 4px 0 0; font-size: 12.5px; }
.record-card-body.record-client-view { gap: 20px; }
/* Text that turns into a box when clicked, lined up with the text around it. */
.record-client-view .field-read { margin-left: -10px; }
.record-rail-note { margin: 0 0 10px; font-size: 12.5px; }

/* A timeline: newest at the top, a dot for each step, a line joining them. */
.record-timeline { display: grid; margin: 0; padding: 0; list-style: none; }
.record-timeline li { position: relative; display: grid; gap: 2px; padding: 0 0 16px 22px; font-size: 13.5px; }
.record-timeline li::before { content: ""; position: absolute; top: 5px; left: 0; width: 10px; height: 10px; border-radius: 50%; background: var(--border); }
.record-timeline li:not(:last-child)::after { content: ""; position: absolute; top: 17px; bottom: 0; left: 4.5px; width: 1px; background: var(--border); }
.record-timeline li.is-latest::before { background: var(--tone-approved-fg); }
.record-timeline p { margin: 2px 0; line-height: 1.5; }
.record-timeline small { color: var(--muted-foreground); font-size: 12px; }

/* History: a date, then what happened, one line each. */
.record-history { display: grid; margin: 0; padding: 0; list-style: none; }
.record-history li { display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 20px; padding: 13px 0; border-bottom: 1px solid var(--border); font-size: 13.5px; }
.record-history li:last-child { border-bottom: 0; }
@media (max-width: 460px) {
  .record-history li { grid-template-columns: 1fr; gap: 2px; }
}

/* The thread's box waits behind one line until somebody wants it. */
.discussion-compose > summary { color: var(--primary); font-size: 13.5px; font-weight: 600; list-style: none; cursor: pointer; }
.discussion-compose > summary::-webkit-details-marker { display: none; }
.discussion-compose[open] > summary { margin-bottom: 10px; }
.record-brief { display: grid; gap: 0; }
.record-card-head { margin: 0 0 12px; font-size: 15px; font-weight: 600; }
.record-client-view { display: grid; gap: 14px; font-size: 13.5px; line-height: 1.55; }
.record-facts { display: flex; flex-wrap: wrap; gap: 10px 26px; margin-bottom: 14px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
.record-facts > div { display: grid; gap: 3px; font-size: 13.5px; }

/* Whose move it is, in a word and a colour. Red is late or blocked, amber is
   waiting on somebody else, green is done; anything else carries no colour at
   all, because most work is simply in progress. The word is always there, so
   the colour is never the only thing saying it. Sarah, 2026-10-01. */
.record-state {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 8px 0 0;
  border-radius: 999px;
  padding: 3px 11px;
  font-size: 12px;
  font-weight: 600;
}
.record-state::before { content: ""; width: 7px; height: 7px; border-radius: 4px; background: currentColor; }
.record-state.is-late { background: color-mix(in srgb, var(--destructive) 12%, var(--card)); color: color-mix(in srgb, var(--destructive) 88%, #000000); }
.record-state.is-waiting { background: #fdf3df; color: #8a5a06; }
.record-state.is-done { background: var(--tone-approved-bg); color: var(--tone-approved-fg); }

/* Saved, said beside the field that saved itself. */
.saved-mark { margin-left: 8px; color: var(--tone-approved-fg); font-size: 11.5px; font-weight: 600; opacity: 0; transition: opacity .15s ease; }
.saved-mark.is-on { opacity: 1; }


/* Files as a list you read across: what it is, who put it there, when, and
   whether the client sees it. */
.file-table-wrap { overflow-x: auto; }
.file-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.file-table th {
  padding: 8px 12px 8px 0;
  border-bottom: 1px solid var(--border);
  color: var(--muted-foreground);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  text-align: left;
}
.file-table td { padding: 11px 12px 11px 0; border-bottom: 1px solid var(--border); vertical-align: top; }
.file-table tr:last-child td { border-bottom: 0; }
.file-table-name { min-width: 220px; }
.file-table-note { margin-top: 3px; color: var(--muted-foreground); font-size: 12.5px; }
.file-table-actions { width: 1%; white-space: nowrap; }

/* The team note, at the top of the column in a soft box. */
.discussion-note {
  display: grid;
  gap: 4px;
  border-radius: 8px;
  background: var(--secondary);
  padding: 10px 12px;
  font-size: 13px;
  line-height: 1.5;
}
.discussion-note-label { color: var(--muted-foreground); font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }

/* The thread, as Codex drew it: initials, name and day, then the words. */
.thread { display: grid; gap: 16px; }
.thread-msg { display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 10px; }
.thread-avatar { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 8px; background: var(--secondary); color: var(--muted-foreground); font-size: 11px; font-weight: 600; }
.thread-meta { margin: 0 0 3px; font-size: 13px; }
.thread-meta span { color: var(--muted-foreground); }
.thread-text { font-size: 13px; line-height: 1.5; overflow-wrap: anywhere; }
.thread-text a, .discussion-note a { color: var(--primary); text-decoration: underline; }
.thread-event { margin: 0 0 0 38px; color: var(--muted-foreground); font-size: 12.5px; }
.thread-event strong { color: var(--foreground); font-weight: 600; }
.thread-history { margin: 0; border-top: 1px solid var(--border); padding-top: 10px; font-size: 12px; }
.thread-history label { color: var(--muted-foreground); text-decoration: underline; cursor: pointer; }

/* What MyOps recorded, in the same thread as what people said, and quieter. */
.comment-event { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; padding: 7px 0; color: var(--muted-foreground); font-size: 12.5px; }
.comment-event strong { color: var(--foreground); font-weight: 600; }
.comment-event small { margin-left: auto; font-size: 11.5px; }
.comment-form-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.comment-attach input[type="file"] { max-width: 190px; font-size: 12px; }

/* The team's own conversation, wherever it appears. */
.discussion-card { display: grid; gap: 12px; }
.discussion-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.discussion-head h2 { margin: 0; font-size: 15px; font-weight: 600; }
.discussion-head .muted { font-size: 12px; }
.comment-form { display: grid; gap: 8px; }
.comment-form button { justify-self: end; }

/* What happened, in order. Moved out of pages/task.php with the list itself. */
.activity-item { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 14px; padding: 8px 0; border-bottom: 1px solid var(--border); }
.activity-item:last-child { border-bottom: 0; }
.activity-line { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; min-width: 0; }
.activity-role { color: var(--muted-foreground); font-size: 11px; }
.activity-item small { color: var(--muted-foreground); font-size: 12px; white-space: nowrap; }

/* Below 1360 the menu and the rail leave too little room for the property row
   to stay on one line, so the rail moves under the work. Measured on the live
   page, 2026-10-02: at 1280 the row broke after Due with the rail beside it. */
@media (max-width: 1360px) {
  .record-split { grid-template-columns: 1fr; }
}

@media (max-width: 760px) {
  .record-head { flex-direction: column; gap: 12px; }
  .record-actions { width: 100%; }
  .record-actions .completion-form { flex: 1 1 auto; }
  .record-actions .completion-form button { width: 100%; }
}

/* The pieces of the old task page that are still used by it and by the file
 list: the editable text fields, the file card and its menus, and the two small
 notes. They were written in that page's own <style> block; the page no longer
 has one, and a second page now shows files. UX-025. */
/* Says who reads a box, under the box. The field blocks it belongs to are
   defined with it. TASK-030. */
.field-block { display: grid; gap: 6px; }
.field-label { color: var(--muted-foreground); font-size: 12px; font-weight: 700; }
/* Hidden until the script collapses the field, so no-JS keeps the editor. */
.field-read { display: none; border: 1px solid transparent; border-radius: 7px; padding: 8px 10px; min-height: 38px; line-height: 1.5; cursor: text; overflow-wrap: anywhere; }
.field-read:hover, .field-read:focus-visible { border-color: var(--border); background: color-mix(in srgb, var(--secondary) 40%, transparent); }
.field-read a { color: var(--primary); }
.field-block.is-collapsed .field-read { display: block; }
.field-block.is-collapsed textarea { display: none; }
.form-success { margin: 0; border: 1px solid color-mix(in srgb, var(--tone-approved-fg) 35%, var(--border)); border-radius: 7px; background: var(--tone-approved-bg); color: var(--tone-approved-fg); padding: 9px 10px; font-size: 13px; }
.attachment-header { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 12px; }
.attachment-add { position: relative; flex-shrink: 0; }
.attachment-edit { position: relative; flex: 0 0 auto; }
.attachment-edit summary { list-style: none; }
.attachment-edit summary::-webkit-details-marker { display: none; }
.attachment-form label small { display: block; margin-top: 4px; font-weight: 400; }
.chosen-files-note { margin: -4px 0 0; font-size: 12px; }
.attachment-add summary { min-height: 32px; border: 1px solid var(--border); border-radius: 7px; background: var(--card); color: var(--foreground); padding: 7px 11px; font-size: 13px; font-weight: 600; list-style: none; cursor: pointer; }
.attachment-add summary::-webkit-details-marker { display: none; }
.attachment-add[open] summary { border-color: var(--primary); color: var(--primary); }
.attachment-form { position: absolute; z-index: 20; top: calc(100% + 8px); right: 0; display: grid; width: min(320px, calc(100vw - 40px)); gap: 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--card); box-shadow: 0 16px 40px rgba(19, 34, 38, .16); padding: 14px; }
.project-files-form { position: absolute; z-index: 20; top: calc(100% + 8px); right: 0; display: grid; width: min(320px, calc(100vw - 40px)); gap: 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--card); box-shadow: 0 16px 40px rgba(19, 34, 38, .16); padding: 14px; }
.project-files-pick { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; max-height: 280px; overflow-y: auto; }
.project-files-pick .checkbox-line { align-items: flex-start; font-size: 13px; }
@media (max-width: 560px) { .project-files-form { position: static; width: 100%; margin-top: 8px; box-shadow: none; } }
.empty-note { margin: 0; padding: 10px 0; color: var(--muted-foreground); font-size: 13px; }
@media (max-width: 560px) { .attachment-header { flex-direction: column; } .attachment-add { width: 100%; } .attachment-add summary { text-align: center; } .attachment-form { position: static; width: 100%; margin-top: 8px; box-shadow: none; } .attachment-row { flex-wrap: wrap; } .attachment-edit[open] { flex-basis: 100%; } }

/* Destructive-action card. Only the treatment is shared — each page sets its
   own layout, since Project and Task lay theirs out differently. */
.danger-card {
  border-color: color-mix(in srgb, var(--destructive) 35%, var(--border));
}

.danger-card h2,
.danger-card p { margin: 0; }

/* The cron line on System Activity: made to be selected and copied, so it wraps
   rather than running off the card. MAIL-013. */
.system-command {
  display: block;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--secondary);
  padding: 10px 12px;
  font-size: 12.5px;
  line-height: 1.5;
  overflow-wrap: anywhere;
  user-select: all;
}

.system-steps { margin: 0 0 10px; padding-left: 20px; display: grid; gap: 4px; font-size: 13.5px; }
.digest-test { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin: 0 0 12px; }
.digest-test .muted { font-size: 12.5px; }

.admin-table-wrap { margin-top: 18px; }

/* Standalone banner that needs to clear the block beneath it. */
.form-success.is-block,
.form-error.is-block { margin-bottom: 14px; }

/* An ⓘ inside a red line opens across the line's own width, so its words
   stay on a phone screen. The World Map's stop reason, patch 823. */
.form-error:has(> .info-tip) { position: relative; }
.form-error > .info-tip { position: static; }
.form-error > .info-tip .info-tip-text { left: 0; right: 0; width: auto; max-width: none; }

/* Project typeahead. Used by the Dashboard and Tasks quick-add forms; was
   defined only inside dashboard.php, so on Tasks the menu had no positioning
   and sat in the layout instead of floating over it. */
.typeahead { position: relative; }

.typeahead input { width: 100%; }

.typeahead-menu {
  position: absolute;
  z-index: 30;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  display: none;
  max-height: 220px;
  overflow: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--card);
  box-shadow: 0 12px 30px rgba(19, 34, 38, .14);
  padding: 4px;
}

.typeahead-menu.is-open {
  display: grid;
  gap: 2px;
}

.typeahead-option {
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--foreground);
  padding: 8px 9px;
  text-align: left;
}

.typeahead-option:hover,
.typeahead-option:focus,
.typeahead-option.is-active { background: var(--secondary); }

/* The shared type-ahead (assets/js/typeahead.js). Its options are rows rather
   than buttons, and its list sits in the flow - inside a right-click menu a
   floating list would hang off the menu edge. */
div.typeahead-option { display: flex; align-items: baseline; gap: 8px; cursor: pointer; font-size: 13px; }
div.typeahead-option small { margin-left: auto; color: var(--muted-foreground); font-size: 11px; }
.typeahead.is-inline .typeahead-menu { position: static; margin-top: 4px; max-height: 200px; box-shadow: none; }

.typeahead-hint {
  border-top: 1px solid var(--border);
  color: var(--muted-foreground);
  padding: 8px 9px;
  font-size: 12px;
}

/* Empty-state line for a panel. Used by seven views, previously defined in
   only two of them. task.php keeps a tighter local override. */
.empty-note {
  margin: 0;
  padding: 22px 4px;
  color: var(--muted-foreground);
  text-align: center;
  font-size: 13px;
}

/* Drag affordance. Used by the sidebar, Dashboard, and Project board. */
.drag-handle {
  flex-shrink: 0;
  color: color-mix(in srgb, var(--muted-foreground) 65%, transparent);
  font-size: 13px;
  line-height: 1.3;
  letter-spacing: -2px;
}

/* Public auth shell. Rendered by layouts/public.php for login, register, and
   reset-password, which each carried an identical copy. */
/* The signed-out pages: a soft wash of the rTheory colors with a faint dot
   pattern, in place of plain grey. Sarah, 2026-10-04: "the gray screams old
   school", then "go ahead with 446". UX-001. */
body.public-page:not([data-theme="dark"]) {
  background:
    radial-gradient(1200px 700px at 8% 12%, rgba(219, 39, 119, .22), transparent 60%),
    radial-gradient(900px 700px at 92% 18%, rgba(124, 58, 237, .20), transparent 60%),
    radial-gradient(1000px 800px at 60% 100%, rgba(37, 99, 235, .18), transparent 60%),
    #fbfaff;
  background-attachment: fixed;
}
body.public-page::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: radial-gradient(rgba(24, 24, 27, .10) 1px, transparent 1px);
  background-size: 18px 18px;
  -webkit-mask-image: linear-gradient(180deg, #000, transparent 85%);
  mask-image: linear-gradient(180deg, #000, transparent 85%);
}
body.public-page > * { position: relative; z-index: 1; }
/* A message on the login card keeps its distance from what comes next. */
.auth-card > .form-success,
.auth-card > .form-error,
.auth-tab-panel > .form-success,
.auth-tab-panel > .form-error { margin: 0 0 14px; }

.public-page {
  display: block;
  min-height: 100vh;
  background: var(--background);
}

.public-shell {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 28px;
}

/* Base styling for a secondary/inline link. The auth pages additionally centre
   it; .tasks-filters narrows it further. Neither carried the base rule for
   other pages, so admin screens rendered it as plain underlined body text. */
.secondary-link {
  color: var(--primary);
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
}

/* Roomier card for admin screens, matching .data-table.is-roomy. */
.card.is-roomy { padding: 20px; }

.card.is-roomy .card-header {
  margin: -20px -20px 18px;
  padding: 14px 20px;
}

.stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  margin-bottom: 14px;
}

.stat-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px;
}

.stat-icon {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  font-size: 18px;
  line-height: 1;
}

.stat-card strong {
  display: block;
  font-size: 20px;
  line-height: 1;
}

/* `:not(.stat-icon)` matters. The icon is a span inside .stat-card too, so a
   bare `.stat-card span` outranked `.stat-icon` on specificity and quietly
   replaced its grid centring with `display: block`, its 18px glyph with 12px,
   and pushed it down 4px - which is why every stat icon sat small in the
   top-left corner of its tinted square. */
.stat-card span:not(.stat-icon) {
  display: block;
  margin-top: 4px;
  color: var(--muted-foreground);
  font-size: 12px;
}

.grid-dashboard {
  display: grid;
  grid-template-columns: 288px minmax(0, 1fr);
  gap: 16px;
}

.grid-two {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 16px;
}

/* Several cards in one column of .grid-two, stacked with the same gap. Without
   it a third card wraps into whichever column has room, not the one it belongs to. */
.grid-stack {
  display: grid;
  gap: 16px;
  align-content: start;
  min-width: 0;
}

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 16px;
}

.card {
  padding: 14px;
}

.card-header {
  margin: -14px -14px 12px;
  border-bottom: 1px solid var(--border);
  padding: 10px 14px;
}

.link-card {
  display: block;
  color: inherit;
  text-decoration: none;
  transition: border-color .15s ease;
}

.link-card:hover {
  border-color: color-mix(in srgb, var(--primary) 55%, var(--border));
}

.progress-track {
  height: 6px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--secondary);
}

.progress-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--primary);
}

.task-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.task-row {
  display: block;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  padding: 10px;
  color: inherit;
  text-decoration: none;
}

.task-row:hover {
  border-color: color-mix(in srgb, var(--primary) 45%, var(--border));
}

.task-row strong {
  display: block;
  margin-bottom: 4px;
  font-size: 13px;
}

.task-meta {
  display: block;
  margin-top: 3px;
  overflow-wrap: break-word;
  color: var(--muted-foreground);
  font-size: 11px;
  white-space: normal;
}

.task-foot {
  margin-top: 9px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

/* The date keeps its line and a long label shortens with an ellipsis, rather
   than the label refusing to shrink and pushing out of the card while the date
   breaks over three lines. Seen on a narrow board column with a long project
   name. Shared, because a dozen screens use this footer. UX-021. */
.task-foot { min-width: 0; }
.task-foot > small { flex-shrink: 0; white-space: nowrap; }
.task-foot > .badge { display: inline-block; min-width: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }

.badge {
  display: inline-flex;
  align-items: center;
  border-radius: 6px;
  padding: 3px 7px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

.tone-neutral { color: var(--tone-neutral-fg); background: var(--tone-neutral-bg); }
.tone-info { color: var(--tone-info-fg); background: var(--tone-info-bg); }
.tone-active { color: var(--tone-active-fg); background: var(--tone-active-bg); }
.tone-ready { color: var(--tone-ready-fg); background: var(--tone-ready-bg); }
.tone-review { color: var(--tone-review-fg); background: var(--tone-review-bg); }
.tone-warn { color: var(--tone-warn-fg); background: var(--tone-warn-bg); }
.tone-approved { color: var(--tone-approved-fg); background: var(--tone-approved-bg); }
.tone-done { color: var(--tone-done-fg); background: var(--tone-done-bg); }

.client-color-swatch {
  display: inline-block;
  width: 16px;
  height: 16px;
  border: 1px solid var(--border);
  border-radius: 999px;
}
.client-color-swatch-auto {
  background: var(--card);
  border-style: dashed;
}
.client-color-swatch-1 { background: var(--client-1-color); }
.client-color-swatch-2 { background: var(--client-2-color); }
.client-color-swatch-3 { background: var(--client-3-color); }
.client-color-swatch-4 { background: var(--client-4-color); }
.client-color-swatch-5 { background: var(--client-5-color); }
.client-color-swatch-6 { background: var(--client-6-color); }
.client-color-swatch-7 { background: var(--client-7-color); }
.client-color-swatch-8 { background: var(--client-8-color); }
.client-color-swatch-9 { background: var(--client-9-color); }
.client-color-swatch-10 { background: var(--client-10-color); }
.client-color-swatch-11 { background: var(--client-11-color); }
.client-color-swatch-12 { background: var(--client-12-color); }

/* ----------------------------------------------------------------
   Shared calendar component. Used by the dashboard calendar and the
   client-facing calendar alike (assets/js/calendar.js renders the
   day cells and task cards below into whichever page includes it).
   Per-surface differences are config (view toggle, drag/drop,
   per-client color) rather than separate markup/CSS.
   ---------------------------------------------------------------- */

.calendar-shell {
  overflow: hidden;
  padding: 0;
}

.calendar-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  border-bottom: 1px solid var(--border);
  padding: 12px 16px;
}

.calendar-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}

.calendar-view-nav {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.calendar-nav,
.calendar-today {
  min-height: 32px;
  border-color: var(--border);
  background: var(--card);
  color: var(--foreground);
}

.calendar-nav:hover,
.calendar-today:hover {
  border-color: var(--primary);
  background: var(--card);
  color: var(--primary);
}

.calendar-nav {
  min-width: 34px;
  padding-inline: 9px;
  font-size: 18px;
  line-height: 1;
}

.calendar-today {
  padding-inline: 12px;
}

.segmented {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--secondary) 45%, transparent);
  padding: 2px;
}

.segmented span,
.segmented button {
  min-height: 28px;
  border: 0;
  border-radius: 5px;
  background: transparent;
  color: var(--muted-foreground);
  padding: 5px 9px;
  font-size: 12px;
  font-weight: 600;
}

.segmented .active {
  color: var(--foreground);
  background: var(--card);
  box-shadow: 0 1px 2px rgba(19, 34, 38, .06);
}

.calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(104px, 1fr));
  gap: 1px;
  overflow: auto;
  background: var(--border);
}

.calendar-grid.is-five-day {
  grid-template-columns: repeat(5, minmax(104px, 1fr));
}

.calendar-grid.is-week .calendar-day {
  min-height: 440px;
}

.calendar-day {
  min-height: 118px;
  background: var(--card);
}

.calendar-day.is-muted {
  background: color-mix(in srgb, var(--accent) 10%, var(--card));
}

.calendar-day.is-muted .calendar-day-head {
  color: color-mix(in srgb, var(--muted-foreground) 72%, var(--foreground));
}

.calendar-day.is-today .calendar-day-number {
  background: var(--primary);
  color: var(--primary-foreground);
}

.calendar-day.drop-target {
  background: color-mix(in srgb, var(--accent) 55%, var(--card));
}

.calendar-day-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: 32px;
  border-bottom: 1px solid var(--border);
  padding: 7px 9px;
  color: var(--muted-foreground);
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
}

.calendar-day-number {
  display: inline-grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 999px;
  color: var(--foreground);
  font-size: 12px;
  text-transform: none;
  letter-spacing: 0;
}

.calendar-day-body {
  display: grid;
  gap: 6px;
  padding: 8px;
  align-content: start;
}

.calendar-task {
  display: block;
  border: 1px solid var(--border);
  border-left: 3px solid var(--client-color, var(--primary));
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--card) 88%, var(--secondary));
  padding: 7px 8px;
  color: inherit;
  text-decoration: none;
  transition: box-shadow .12s ease, transform .12s ease;
}

.calendar-task[draggable="true"] {
  cursor: grab;
}

.calendar-task:hover {
  box-shadow: 0 1px 2px rgba(19, 34, 38, .06);
}

.calendar-task.dragging {
  opacity: .48;
}

.calendar-task-note {
  cursor: default;
}

.calendar-task a {
  color: inherit;
  text-decoration: none;
}

.calendar-task a:hover {
  color: var(--primary);
  text-decoration: underline;
}

.calendar-task strong {
  display: block;
  overflow-wrap: break-word;
  color: var(--client-color, var(--foreground));
  font-size: 12.5px;
  font-weight: 650;
  line-height: 1.3;
  white-space: normal;
}

.calendar-task-badge {
  display: block;
  margin-top: 6px;
}

/* The board lays out however many columns the project has. It was pinned to
   repeat(4, ...), so a fifth and sixth column wrapped onto a second row below
   the first four instead of continuing across — which reads as the board not
   having them at all. auto-flow keeps every column on one row and lets the
   container scroll once they no longer fit. The unassigned bucket counts as a
   column here too. */
.board {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(220px, 1fr);
  gap: 12px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  padding-bottom: 4px;
}

.board-col {
  border: 1px solid var(--border);
  border-radius: 8px;
  background: color-mix(in srgb, var(--secondary) 45%, transparent);
}

.board-col h3 {
  display: flex;
  justify-content: space-between;
  border-bottom: 1px solid var(--border);
  padding: 11px 12px;
}

.board-col-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px;
}

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--card);
}

.data-table {
  width: 100%;
  min-width: 720px;
  border-collapse: collapse;
  font-size: 13px;
}

.data-table th,
.data-table td {
  border-bottom: 1px solid var(--border);
  padding: 9px 12px;
  text-align: left;
}

.data-table th {
  color: var(--muted-foreground);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
}

.form-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.form-card label:not(.checkbox-line) {
  display: flex;
  flex-direction: column;
  gap: 6px;
  color: var(--muted-foreground);
  font-size: 13px;
  font-weight: 650;
}

.activity-item {
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}

.activity-item span {
  display: block;
  color: var(--muted-foreground);
  font-size: 13px;
}

.back-link {
  display: inline-block;
  margin-bottom: 10px;
  color: var(--muted-foreground);
  text-decoration: none;
  font-size: 14px;
}

.setup-page {
  display: block;
  padding: 30px;
}

.setup-card {
  max-width: 900px;
  margin: 0 auto;
  padding: 24px;
}

.diagnostic-table {
  width: 100%;
  border-collapse: collapse;
}

.diagnostic-table th,
.diagnostic-table td {
  border-bottom: 1px solid var(--border);
  padding: 10px;
  text-align: left;
}

.pass {
  color: var(--tone-approved-fg);
  font-weight: 700;
}

.fail,
.warning {
  color: var(--destructive);
}

.notice,
.warning {
  padding: 12px;
  border-radius: 7px;
  background: color-mix(in srgb, var(--tone-ready-bg) 70%, var(--card));
}

@media (max-width: 1100px) {
  .stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .grid-dashboard,
  .grid-two {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 760px) {
  .app-body {
    display: block;
  }

  /* One row on a phone: the product, then the workspace, the count and the
     account. The switcher keeps its width down so all four fit. NAV-001. */
  .app-header { flex-wrap: nowrap; gap: 8px; padding: 6px 12px; }
  .app-header .brand span { display: none; }
  .workspace-switcher select { width: min(150px, 34vw); }
  .user-menu-who { display: none; }
  .user-menu > summary { padding: 3px; }

  /* Said on a screen where there is no rail beside the page, and a footer that
     repeats what the header already says. */
  .nav-empty,
  .sidebar .workspace { display: none; }

  .app-rail {
    position: static;
    min-height: auto;
  }

  .rail-top {
    display: none;
  }

  .rail-nav {
    min-height: 52px;
    flex-direction: row;
    justify-content: flex-start;
    overflow-x: auto;
  }
  .rail-nav .rail-rule { width: 2px; height: 24px; margin: 0 4px; }

  /* No hover label below this width. The rail becomes a horizontal strip with
     `overflow-x: auto`, and a scroll container clips in both directions - so
     the label cannot escape it whether it sits beside the item or under it.
     Moving it out would mean positioning it in JavaScript, which is a lot of
     machinery for a layout that is nearly always a touch screen, where there
     is no hover to begin with. */
  .rail-nav a::after { content: none; }

  /* Two fixed heights, so the sheet can be positioned under both without
     measuring anything in script: 52 of header, 38 of band, 90 to the top of the
     menu. Everything inside them is shorter than that, so the numbers are true
     by construction rather than by luck. */
  .app-header { min-height: 52px; }

  /* The band: where you are, and the way to the rest of the menu. It is the
     strip that used to head the second menu, kept on its own now that the menu
     is behind a button. */
  .nav-band {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 38px;
    padding: 0 10px;
    border-bottom: 1px solid var(--sidebar-line);
    background: var(--sidebar);
    color: var(--sidebar-foreground);
  }

  .nav-band-name {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
  }

  .nav-sheet-toggle {
    display: flex;
    flex-direction: column;
    /* Both of these undo a button default that applies app-wide: `align-items:
       center` left the three bars at zero width - a blank grey square, which is
       what patch 370 shipped - and the shared `min-height` made the button
       taller than the band it sits in. */
    align-items: stretch;
    justify-content: center;
    gap: 3px;
    flex: 0 0 auto;
    width: 30px;
    height: 28px;
    min-height: 0;
    padding: 0 6px;
    border: 0;
    border-radius: 8px;
    background: var(--chrome-panel);
    cursor: pointer;
  }
  .nav-sheet-toggle span { display: block; width: 100%; height: 2px; border-radius: 2px; background: var(--sidebar-foreground); }
  .nav-sheet-toggle[aria-expanded="true"] { background: var(--chrome-hover); }

  /* The menu is away until the button opens it. Open, it is a sheet under the
     header rather than a block pushing the page down - the whole complaint was
     that it sat above the page and shoved it off the screen. It scrolls on its
     own, because on Tasks it is every saved view and every project. */
  .sidebar {
    position: static;
    min-height: auto;
    display: none;
  }

  /* The section menu as one row under the page name, built by
     assets/js/phone-menu.js; it replaces the menu behind a button. NAV-001. */
  .phone-menu { display: block; border-bottom: 1px solid var(--sidebar-line); background: var(--sidebar); }
  .phone-menu[hidden] { display: none; }
  .phone-menu-row { display: flex; gap: 6px; overflow-x: auto; padding: 8px 10px; scrollbar-width: none; -webkit-mask-image: linear-gradient(90deg, #000 88%, transparent); mask-image: linear-gradient(90deg, #000 88%, transparent); }
  .phone-menu-row::-webkit-scrollbar { display: none; }
  .phone-menu-pill { flex: none; display: inline-flex; align-items: center; gap: 4px; min-height: 30px; margin: 0; border: 1px solid var(--border); border-radius: 999px; background: var(--card); padding: 4px 12px; color: var(--foreground); font-size: 13px; font-weight: 600; text-decoration: none; white-space: nowrap; }
  .phone-menu-pill.is-active { border-color: var(--primary); background: var(--primary); color: var(--primary-foreground); }
  .phone-menu-pill.is-fold { color: var(--muted-foreground); }
  .phone-menu-pill.is-fold.is-current, .phone-menu-pill.is-fold[aria-expanded="true"] { border-color: var(--primary); color: var(--primary); }
  .phone-menu-sheet { display: grid; padding: 0 10px 10px; }
  .phone-menu-sheet[hidden] { display: none; }
  .phone-menu-sheet a { padding: 10px 6px; border-top: 1px solid var(--border); color: var(--foreground); font-size: 14px; text-decoration: none; }
  .phone-menu-sheet a.is-active { color: var(--primary); font-weight: 600; }
  /* The old menu and its button are not used on a phone any more. */
  .nav-sheet-toggle, .nav-sheet-backdrop { display: none !important; }

  html.nav-open .sidebar {
    position: fixed;
    top: 90px;
    right: 0;
    left: 0;
    z-index: 30;
    display: flex;
    max-height: calc(100vh - 90px);
    overflow-y: auto;
    border-right: 0;
    border-bottom: 1px solid var(--sidebar-line);
    box-shadow: 0 14px 28px rgba(0, 0, 0, .18);
  }

  html.nav-open .nav-sheet-backdrop {
    position: fixed;
    top: 90px;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 20;
    display: block;
    background: rgba(0, 0, 0, .26);
  }

  .main {
    padding: 16px;
  }

  .quick-form,
  .stats {
    grid-template-columns: 1fr;
  }

  .calendar-grid {
    grid-template-columns: repeat(7, minmax(96px, 1fr));
  }

  .calendar-grid.is-five-day {
    grid-template-columns: repeat(5, minmax(96px, 1fr));
  }

  .calendar-toolbar {
    align-items: flex-start;
    flex-direction: column;
  }

  .calendar-actions {
    justify-content: flex-start;
  }
}

/* Promoted from task.php in patch 111: client.php used .button-light with no
   definition of its own, so the link rendered unstyled there. */
.button-light { display: inline-flex; align-items: center; justify-content: center; width: fit-content; min-height: 34px; border: 1px solid var(--border); border-radius: 7px; background: var(--card); color: var(--foreground); padding: 8px 12px; font-size: 13px; font-weight: 600; text-decoration: none; }
.button-light:hover { border-color: var(--primary); color: var(--primary); }

/* Client-requested date moves (CLIENT-003). */
.calendar-drag-hint { margin: 0 0 8px; font-size: 12px; }
.calendar-drag-status { margin-top: 10px; }
.calendar-drag-status.is-error { border-color: var(--destructive); color: var(--destructive); }
.calendar-task-request { cursor: grab; }
.calendar-task-request:active { cursor: grabbing; }
.calendar-task-pending { display: block; margin-top: 4px; font-size: 11px; font-weight: 700; color: var(--primary); }
/* On the day a client asked for: dashed and tinted, unlike any other card. CAL-019, patch 532. */
.calendar-task.is-move-requested { border-style: dashed; border-color: var(--primary); background: color-mix(in srgb, var(--primary) 8%, var(--card)); }
.request-decision { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 10px; }
.request-decision .inline-form { margin: 0; }

/* Declining carries the reason the client reads, so the note sits with the
   button rather than on a screen of its own. Shared by the Inbox and the client
   page. CLIENT-009. */
.request-decline { margin-top: 8px; }
.request-decline summary { cursor: pointer; font-size: 13px; color: var(--muted-foreground); width: max-content; }
.request-decline summary:hover { color: var(--destructive); }
.request-decline form { display: grid; gap: 8px; margin-top: 8px; max-width: 420px; }
.request-decline textarea { min-height: 70px; }

/* What the client says their request is, on their own request form. */
.request-kind { display: grid; gap: 6px; border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; margin: 0 0 4px; }
.request-kind legend { padding: 0 4px; font-size: 12px; font-weight: 600; color: var(--muted-foreground); }
.request-kind p { margin: 2px 0 0; font-size: 12px; }

/* The reason a request was declined, shown to the client under the request. */
.request-note { border-left: 2px solid var(--border); padding-left: 10px; }

/* Topbar alert for client requests waiting on a decision (CLIENT-003). */
.alert-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--destructive); flex: none; }

/* Cross-client requests queue (CLIENT-003). */
.request-list { display: grid; gap: 10px; }
.request-row { display: grid; gap: 6px; }
.request-head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.request-head strong { font-size: 15px; }

/* Explains why the workflow bulk option is absent without a project filter. */
.bulk-note { flex-basis: 100%; margin: 4px 0 0; font-size: 12px; }

/* Completed work is hidden by default on internal lists; this is the way back. */
/* Backups kept, on System Activity. SYS-012. */
.backup-kind { margin: 16px 0 6px; font-size: 13px; font-weight: 600; }
.backup-list { display: grid; gap: 2px; margin: 0; padding: 0; list-style: none; }
.backup-list li { display: flex; align-items: center; gap: 12px; padding: 4px 0; border-bottom: 1px solid var(--border); }
.backup-list li > span:first-child { flex: 1 1 auto; font-variant-numeric: tabular-nums; }
.backup-list form { margin: 0; }

/* Color by. A card carries its client color as --cc and its project color as
   --pc; the page's choice decides which one is --client-color, so switching
   repaints without redrawing. Board cards get the same edge as calendar cards.
   CAL-021. */
[style*="--cc"] { --client-color: var(--cc); }
.color-by-project [style*="--pc"] { --client-color: var(--pc); }
.kanban-card[style*="--cc"] { border-left: 3px solid var(--client-color); }
.color-by { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted-foreground); }
.color-by .segmented button { min-height: 28px; padding: 3px 10px; font-size: 12px; }

/* The color picker: swatches, then Custom with a wheel and a hex box. */
.color-picker { display: grid; gap: 10px; }
.project-color-fieldset { display: grid; gap: 10px; margin: 0; border: 1px solid var(--border); border-radius: 8px; padding: 12px; }
.project-color-fieldset legend { padding: 0 4px; color: var(--muted-foreground); font-size: 12px; font-weight: 600; text-transform: uppercase; }
.project-color-fieldset p { margin: 0; }
/* A record's color dot on a list, opening the picker in place. CAL-021. */
.color-dot { position: relative; display: inline-block; vertical-align: middle; }
.color-dot > summary { display: inline-grid; place-items: center; width: 20px; height: 20px; border-radius: 50%; list-style: none; cursor: pointer; }
.color-dot > summary::-webkit-details-marker { display: none; }
.color-dot > summary:hover { background: var(--secondary); }
.color-dot-panel { position: absolute; top: calc(100% + 6px); left: 0; z-index: 40; display: grid; gap: 12px; width: 300px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); box-shadow: 0 18px 44px rgba(19, 34, 38, .16); padding: 14px; white-space: normal; cursor: default; }
.color-dot-actions { display: flex; justify-content: flex-end; }
.color-dot-scope { display: flex; gap: 16px; font-size: 13px; }
.color-dot-hint { margin: 0; font-size: 12px; }
/* A color you picked for yourself: a ring around the dot. Patch 435. */
.color-dot-static.is-own { box-shadow: 0 0 0 2px var(--card), 0 0 0 3.5px var(--foreground); }
.record-name-line { display: inline-flex; align-items: center; gap: 6px; }
/* A color shown, not chosen: a client's color to a member, and the list dots. */
.color-dot-static { display: inline-block; width: 12px; height: 12px; border-radius: 50%; background: var(--swatch); vertical-align: -1px; }
.color-picker-swatches { display: flex; flex-wrap: wrap; gap: 8px; }
.color-swatch { position: relative; display: inline-grid; place-items: center; cursor: pointer; }
.color-swatch input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.color-swatch > span:first-of-type { display: block; width: 26px; height: 26px; border-radius: 50%; background: var(--swatch, transparent); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12); }
.color-swatch.is-auto > span:first-of-type { background: repeating-linear-gradient(45deg, var(--secondary) 0 4px, var(--card) 4px 8px); box-shadow: inset 0 0 0 1px var(--border); }
.color-swatch input:checked + span { box-shadow: 0 0 0 2px var(--card), 0 0 0 4px var(--foreground); }
.color-swatch input:focus-visible + span { outline: 2px solid var(--primary); outline-offset: 3px; }
.color-picker-custom { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.color-picker-custom-label { font-size: 13px; font-weight: 600; }
.color-picker-custom input[type="color"] { width: 38px; min-height: 30px; height: 30px; padding: 2px; border-radius: 7px; cursor: pointer; }
.color-picker-custom input[type="text"] { width: 96px; font-family: ui-monospace, Menlo, monospace; font-size: 12.5px; text-transform: lowercase; }
.color-picker-custom input.is-invalid { border-color: var(--destructive); }

/* The Columns panel: a short list to tick and drag. UX-026. */
.list-overdue { color: var(--destructive); font-weight: 600; }
.columns-open.is-busy { opacity: .7; }
.columns-panel { min-width: 240px; }
.columns-hint { margin: 0 0 8px; font-size: 12px; }
.columns-items { display: grid; gap: 2px; margin: 0; padding: 0; list-style: none; }
.columns-item { display: flex; align-items: center; gap: 8px; border-radius: 6px; padding: 4px 6px; background: var(--card); cursor: grab; }
.columns-item:hover { background: color-mix(in srgb, var(--foreground) 5%, var(--card)); }
.columns-item.is-dragging { opacity: .5; }
.columns-item .checkbox-line { flex: 1 1 auto; margin: 0; cursor: pointer; }
.columns-grip { color: var(--muted-foreground); font-size: 12px; letter-spacing: -2px; }

/* File storage down, from StorageWatch. STORE-007. */
.storage-watch-banner { margin-bottom: 16px; }
.storage-watch-reason { display: block; margin: 4px 0; font-size: 12.5px; opacity: .9; white-space: pre-line; }
.storage-watch-ok { margin: 0 0 12px; font-size: 12.5px; }

/* A list page's bar: the search box and the Filters button side by side,
   then the count. Projects and Clients. UX-020. */
.list-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 12px; }
.list-toolbar .list-search { flex: 0 1 340px; margin: 0; }
.list-count { margin: 0 0 10px; font-size: 13px; }
/* A company you might work with. CLIENT-023. */
.prospect-tag { display: inline-block; margin-left: 6px; border: 1px solid color-mix(in srgb, var(--primary) 40%, var(--border)); border-radius: 999px; padding: 1px 8px; color: var(--primary); font-size: 11px; font-weight: 600; letter-spacing: .02em; vertical-align: middle; }
/* A list's own buttons, at the right of its Search and Filters row. UX-025. */
.list-toolbar-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-left: auto; }
/* The lighter list table: no rule between columns, a soft line between rows,
   the whole row lit and clickable, the name bold with a second line under it.
   Projects and Clients, 2026-10-02. */
.record-list-table td { padding-top: 12px; padding-bottom: 12px; vertical-align: middle; }
.record-list-table tbody tr[data-row-href] { cursor: pointer; transition: background .12s ease; }
.record-list-table tbody tr[data-row-href]:hover { background: color-mix(in srgb, var(--primary) 5%, var(--card)); }
.record-name-cell a { color: var(--foreground); font-weight: 600; text-decoration: none; }
.record-name-cell a:hover { color: var(--primary); }
.record-name-cell small { display: block; margin-top: 2px; color: var(--muted-foreground); font-size: 12px; }
.record-name-with-logo { display: inline-flex; align-items: center; gap: 10px; }
.record-list-logo { width: 28px; height: 28px; flex: 0 0 auto; box-sizing: border-box; border: 1px solid var(--border); border-radius: 6px; background: var(--card); object-fit: contain; padding: 2px; }
.record-list-logo.is-initials { display: inline-grid; place-items: center; padding: 0; background: color-mix(in srgb, var(--foreground) 6%, var(--card)); color: var(--muted-foreground); font-size: 11px; font-weight: 600; }

/* Show or hide completed: a quiet outlined control the height of the buttons
   beside it, with the same gap as everything else in its row. */
.completed-switch { display: inline-flex; align-items: center; min-height: 34px; border: 1px solid var(--border); border-radius: 7px; background: var(--card); padding: 0 12px; color: var(--muted-foreground); font-size: 12.5px; font-weight: 600; text-decoration: none; white-space: nowrap; }
.completed-switch:hover { border-color: var(--primary); color: var(--primary); }
.completed-switch.is-on { border-color: color-mix(in srgb, var(--primary) 40%, var(--border)); color: var(--primary); }
/* A card heading with a note on the left and one control on the right. */
.card-header.is-split { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; }
.card-header.is-split > p { margin: 0; }

/* Promoted from task.php in patch 119: the partner task page renders the same
   comment thread, and these had no definition outside that one page. */
.comment-form { display: grid; gap: 12px; margin-bottom: 16px; }
.comment-list { display: grid; gap: 10px; }
.comment-item { border: 1px solid var(--border); border-radius: 8px; background: var(--card); padding: 12px; }
.comment-item p { margin: 8px 0 0; color: var(--foreground); line-height: 1.5; }
.comment-meta { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; color: var(--muted-foreground); font-size: 12px; }
.comment-meta strong { color: var(--foreground); }

/* A plain stacked form. Distinct from .attachment-form, which is the popover
   inside task detail's Add file control and is positioned absolutely. */
.stacked-form { display: grid; gap: 12px; margin-bottom: 16px; }

/* Error variant of the shared success panel. */
.form-success.is-error { border-color: var(--destructive); color: var(--destructive); }

/* Tasks whose workflow key no longer matches any column on their project. */
.board-col.is-orphan { border: 1px dashed var(--destructive); border-radius: var(--radius-sm); }
.board-col.is-orphan h3 span { color: var(--destructive); }

/* Drop-to-upload on the task Files card. */
.drop-hint { order: 3; flex-basis: 100%; margin: 0; font-size: 12px; }
[data-attachment-card].is-dropping { outline: 2px dashed var(--primary); outline-offset: -4px; }
[data-attachment-card].is-dropping .drop-hint { color: var(--primary); font-weight: 700; }

/* Shared list tools: type-to-filter and sortable headers (assets/js/list-tools.js). */
.is-filtered-out { display: none !important; }
.list-search { display: grid; gap: 6px; margin: 0 0 12px; max-width: 320px; }
.list-search span { color: var(--muted-foreground); font-size: 12px; font-weight: 700; }
.data-table th.is-sortable { cursor: pointer; user-select: none; white-space: nowrap; }
.data-table th.is-sortable:hover { color: var(--primary); }
.data-table th.is-sortable::after { content: ' \2195'; opacity: .35; font-size: 11px; }
.data-table th.is-sorted-asc::after { content: ' \2191'; opacity: 1; }
.data-table th.is-sorted-desc::after { content: ' \2193'; opacity: 1; }

/* Files chosen but not yet uploaded (assets/js/uploads.js). */
.chosen-files { display: grid; gap: 4px; margin: 0; border: 1px solid var(--border); border-radius: 7px; background: var(--secondary); padding: 8px 10px 8px 26px; color: var(--foreground); font-size: 12px; }

/* Ticket number for a task synced from the backlog file (SYS-003). It is read
   from import_source_id and never lives in an editable field. */
.ticket-badge { display: inline-block; margin-right: 6px; border: 1px solid var(--border); border-radius: 5px; background: var(--secondary); padding: 1px 6px; color: var(--muted-foreground); font-size: 11px; font-weight: 700; letter-spacing: .02em; white-space: nowrap; }
.page-header .ticket-badge { font-size: 13px; padding: 4px 10px; }
.kanban-card .ticket-badge { margin: 0 0 4px; }

/* Rename control on a saved task view, revealed with the other edit actions. */
.nav-rename-toggle { border: 0; background: transparent; color: inherit; padding: 0 4px; font-size: 12px; line-height: 1; cursor: pointer; }
.nav-rename-toggle:hover { background: transparent; color: var(--primary); }

/* Promoted from client-view.php in patch 139: the saved-view rename form in the
   layout uses it too, and it had no definition outside that one page. */
/* `:not(.checkbox-line)` throughout: a container rule that lays out bare labels
   also matches a checkbox row and outranks `.checkbox-line` on specificity, so
   the box stacks above its own text and centres. That is what happened to every
   checkbox in Add access and Add client. Fifth outing for the shape recorded in
   CLAUDE.md - and the case where an exception, rather than scoping by position,
   is the honest expression: a checkbox row is a *kind* of label, not one in a
   particular place, and its siblings are ordinary fields. */
.checkbox-line { display: flex; align-items: center; gap: 8px; color: var(--foreground); font-size: 13px; font-weight: 600; }
.checkbox-line input { width: auto; }

/* Destructive action button. Was defined identically inside three page style
   blocks and nowhere shared, so a fourth page using it would have rendered it
   unstyled — the .inline-form and .form-success failure again. */
/* Outline like everything else, in the destructive colour. It fills on hover,
   so the moment of actually pressing it is the moment it goes loud. */
.danger-button { border-color: color-mix(in srgb, var(--destructive) 45%, var(--border)); background: transparent; color: var(--destructive); }
.danger-button:hover { border-color: var(--destructive); background: var(--destructive); color: white; }

/* A badge that is also a control. Used where a state is worth showing and worth
   changing in the same place, so a context menu is never the only route. */
.badge-button {
  display: inline-flex;
  align-items: center;
  min-height: 0;
  padding: 3px 9px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--secondary);
  color: var(--muted-foreground);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .02em;
  cursor: pointer;
}
.badge-button:hover { border-color: var(--primary); color: var(--primary); background: var(--card); }
.badge-button.is-shared {
  border-color: color-mix(in srgb, var(--tone-approved-fg) 35%, var(--border));
  background: var(--tone-approved-bg);
  color: var(--tone-approved-fg);
}

/* Planning: an unscheduled list beside a calendar, drag between the two. Shared
   because the Tasks page has it now and the project page is next. */
.planning-split {
  display: grid;
  grid-template-columns: minmax(230px, 300px) minmax(0, 1fr);
  align-items: start;
  gap: 16px;
}
/* The Comes back checkbox on a task. A label and an explanation, because the
   word alone does not say what happens - and what happens is unusual enough
   that it needs one line. */
.standing-toggle { align-items: flex-start; gap: 10px; }
.standing-toggle input { width: auto; min-height: auto; margin-top: 3px; }
.standing-toggle strong { display: block; font-size: 13px; }
.standing-toggle small { display: block; margin-top: 2px; color: var(--muted-foreground); font-size: 12px; line-height: 1.4; }

/* The left column holds two lists, stacked. It is one grid child, so the
   calendar keeps the width it had before Standing existed. */
/* min-width: 0, because a grid item defaults to min-width: auto and so refuses
   to shrink below its content - which is how this column overflowed its 300px
   track instead of its text wrapping. */
.planning-lists { display: grid; gap: 12px; align-content: start; min-width: 0; }
/* The lists stay in view while the calendar scrolls, so a card can be dragged
   to the fourth week of a month. Sarah, 2026-10-04: *"The whole left bar
   doesn't stay in frame with me. So that I can grab things from it and drag to
   a further week down."* Beside the calendar the column is as tall as the
   window under the header and scrolls on its own when the open lists are
   taller. Where the lists sit above the calendar (a phone, a narrow window),
   they pin under the header instead: *"1 pin them, 2 yes"*, the 2 being the
   dashboard too. CAL-017. */
.planning-lists {
  position: sticky;
  top: 64px;
  max-height: calc(100vh - 76px);
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Room for the card shadows and the drop outline, which a scroll box clips. */
  padding: 2px 4px 4px 2px;
}
@media (max-width: 900px) {
  .planning-lists {
    top: 52px;
    z-index: 4;
    max-height: 55vh;
    background: var(--background);
    padding: 8px 0;
  }
}
/* The two panels beside a calendar are styled as .planning-panel further down,
   from partials/planning-panels.php. The <details> markup these rules dressed,
   and the separate .planning-unscheduled card, went in patch 267. */
/* A recurring card is a source, not a piece of work waiting to be done. The
   accent edge says it will still be here after you drag it. */
.planning-card.is-recurring { border-left: 3px solid var(--primary); }

.planning-panel.is-drop-hint,
.planning-unscheduled.drop-target {
  border-color: var(--primary);
  background: color-mix(in srgb, var(--accent) 55%, var(--card));
}
.planning-card {
  display: grid;
  gap: 3px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  padding: 9px 10px;
  cursor: grab;
}
.planning-card + .planning-card { margin-top: 8px; }
/* Finished, wherever it is drawn. Matches .calendar-task.is-done exactly, since
   the same task can be on the month and in a panel at once and reading as two
   different things would be worse than reading as neither. */
/* And on a board card, which is the other place a finished task sits beside
   unfinished ones. One rule for .task-row covers every board. */
.task-row.is-done { opacity: .62; }
.task-row.is-done strong { text-decoration: line-through; text-decoration-thickness: 1px; }
.task-row.is-done .task-meta, .task-row.is-done .task-foot { text-decoration: none; }

.planning-card.is-done { opacity: .62; }
.planning-card.is-done strong { text-decoration: line-through; text-decoration-thickness: 1px; }
.planning-card.is-done small { text-decoration: none; }
.planning-card small { color: var(--muted-foreground); font-size: 12px; }
/* Real task names run long - "Fremont - Corewell - MRI Room - Subcontractor -
   Rockford Construction" is one from Gerber. They wrap here rather than setting
   how wide the column has to be. */
.planning-card > * { min-width: 0; overflow-wrap: anywhere; }
.planning-card:hover { border-color: var(--primary); }
@media (max-width: 900px) { .planning-split { grid-template-columns: 1fr; } }

/* Tabbed views. CSS-only: radios drive it, so switching is instant and needs no
   JavaScript. Shared because the project page uses it now and the Tasks page is
   next - the per-page part is only the three :checked rules, since CSS cannot
   pair an input with a panel generically. */
/* The wrapper needs no styling of its own - it exists so the hidden radios can
   be siblings of the tabs and the panels. Declared anyway so the shared-class
   check does not report it as styled only inside a narrowed selector. */
.view-tabs-wrap { display: block; }
/* Pinned to the top of the row. Left where the layout put them, the grid row
   of patch 405 dropped them thousands of pixels down, and clicking a tab
   focused its radio and scrolled the page there. Sarah, 2026-10-03:
   "clicking the calendar/tasks tabs is pulling me to the bottom". */
.view-tabs-wrap { position: relative; }
.view-tabs-wrap > input[type="radio"] { position: absolute; top: 0; left: 0; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.view-tabs {
  display: inline-flex;
  gap: 2px;
  margin: 0 0 18px;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: 10px;
  /* --secondary is one shade off --background, so the track read as nothing and
     the tabs got lost on the page. A firmer step down, and the active tab keeps
     the accent colour, so the control announces itself. */
  background: color-mix(in srgb, var(--foreground) 8%, var(--background));
}
.view-tabs label {
  padding: 7px 16px;
  border-radius: 7px;
  color: var(--muted-foreground);
  /* Uppercase and letter-spaced, matching the section markers already used in
     the sidebar and the context menu. Small, because the spacing carries it. */
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  cursor: pointer;
  transition: color .12s ease, background .12s ease;
}
.view-tabs label:hover { color: var(--foreground); }
/* The same look for two pages linked as one switch: People | Contacts. */
.page-switch { display: flex; width: fit-content; }
.page-switch a { padding: 7px 16px; border-radius: 7px; color: var(--muted-foreground); font-size: 11px; font-weight: 600; letter-spacing: .06em; text-decoration: none; text-transform: uppercase; }
.page-switch a:hover { color: var(--foreground); }
.page-switch a.is-active { background: var(--card); color: var(--primary); box-shadow: 0 1px 2px rgba(19, 34, 38, .12), 0 0 0 1px rgba(19, 34, 38, .05); }
.view-panel { display: none; }
.view-panel.is-open { display: block; }
/* Was defined inside pages/team.php and used on pages/project.php, where it
   therefore rendered unstyled. Moved here by the shared-resources rule, before a
   third page inherited the same bug. Reported by tools/check-shared-classes.py. */
.icon-button {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: var(--card);
  color: var(--foreground);
  padding: 0;
  line-height: 1;
}
.icon-button:hover { border-color: var(--primary); background: var(--card); color: var(--primary); }
.icon-button:disabled { cursor: not-allowed; opacity: .45; }

/* A list of rows in a card, and the rows themselves. Three pages draw these
   now - both client pages and the Projects deleted list - so they live here
   rather than being copied a third time. `a.client-row:hover` stays hover-only
   for links; a plain article row is not clickable and should not pretend. */
.client-list { display: grid; gap: 12px; }
.client-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px;
  color: inherit;
  text-decoration: none;
}
a.client-row:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); }
/* A badge or a button inside a row keeps its own look. Before patch 569 these
   two rules reached them too: the Give input button read gray on blue, and an
   Input Needed badge stretched across the row. */
.client-row strong, .client-row span:where(:not(.badge, .review-go)) { display: block; }
.client-row span:where(:not(.badge, .review-go)) { margin-top: 4px; color: var(--muted-foreground); font-size: 13px; line-height: 1.4; }
.client-row-meta { display: grid; justify-items: end; gap: 6px; flex-shrink: 0; }
@media (max-width: 640px) {
  .client-row { align-items: flex-start; flex-direction: column; }
  .client-row-meta { justify-items: start; }
}

/* Archive beside each finished item on the client view, and the Archived
   fold at the foot of its Review and Requests tabs. CLIENT-022, patch 521. */
.client-archivable { display: flex; align-items: center; gap: 10px; }
.client-archivable > .client-row { flex: 1; min-width: 0; }
.client-archive-form { margin: 0; flex-shrink: 0; }
.task-foot .client-archive-form { margin-left: auto; }
.client-archived:not(.card) { margin-top: 18px; border-top: 1px solid var(--border); padding-top: 12px; }
.client-archived:not(.card) > summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 8px; }
.client-archived:not(.card) > summary::-webkit-details-marker { display: none; }
.client-archived:not(.card) > summary h2 { font-size: 15px; margin: 0; }
.client-archived:not(.card) > summary::after { content: ''; width: 7px; height: 7px; margin-left: auto; border-right: 2px solid var(--muted-foreground); border-bottom: 2px solid var(--muted-foreground); transform: rotate(45deg); transition: transform .15s; }
.client-archived:not(.card)[open] > summary::after { transform: rotate(-135deg); }
.client-archived:not(.card)[open] > summary { margin-bottom: 12px; }

/* An owner setting somebody else's password. Folded away behind a summary
   rather than sitting open on the row: it is the exception, not the way in.
   AUTH-012. */
.set-password { margin-top: 8px; }
.set-password > summary { color: var(--primary); font-size: 12px; font-weight: 600; cursor: pointer; }
.set-password > form { margin-top: 10px; max-width: 340px; }
.set-password-note { margin: 0; font-size: 12px; line-height: 1.45; }

/* A button that reads as a link. Was inside pages/client.php and is now wanted
   on the Reports page too, so it moves before it becomes the next leak. */
.text-button { border: 0; background: transparent; color: var(--primary); padding: 0; font-size: 12px; font-weight: 700; cursor: pointer; }
.text-button:hover { background: transparent; color: var(--primary); text-decoration: underline; }
.text-button.is-danger { color: var(--destructive); }
/* The quiet form of a destructive button: reads as an option rather than as an
   alarm, which suits an action you only reach after already deleting once. */
.secondary-button.is-danger { border-color: color-mix(in srgb, var(--destructive) 40%, var(--border)); color: var(--destructive); }
.secondary-button.is-danger:hover { border-color: var(--destructive); background: color-mix(in srgb, var(--destructive) 8%, var(--card)); color: var(--destructive); }

/* A count beside a tab or a nav row. Lives here because three places draw one
   now - the client portal tabs, the client page tabs, and the admin nav - and
   the third made it a leak the moment it was written. */
.tab-count {
  display: inline-grid;
  min-width: 17px;
  height: 17px;
  margin-left: 6px;
  place-items: center;
  padding: 0 4px;
  border-radius: 9px;
  background: var(--primary);
  color: var(--primary-foreground);
  font-size: 10px;
}

/* The report dock. Fixed to the bottom-right of every page, because the point
   is filing from where you already are - a report you have to navigate to is a
   report nobody writes. CSS only: a checkbox holds open and closed, and the
   form is a plain post, so it works before any JavaScript has loaded and on a
   page whose JavaScript has broken - which is exactly when someone wants to
   report something. */
.report-dock { position: fixed; right: 18px; bottom: 0; z-index: 900; }
.report-dock > input[type="checkbox"] { position: absolute; opacity: 0; pointer-events: none; }
.report-tab {
  display: flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--border);
  border-bottom: 0;
  border-radius: 10px 10px 0 0;
  padding: 7px 14px;
  background: var(--card);
  color: var(--muted-foreground);
  box-shadow: 0 -2px 10px rgba(19, 34, 38, .08);
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  cursor: pointer;
}
.report-tab:hover { color: var(--primary); }
.report-panel {
  display: none;
  width: min(360px, calc(100vw - 36px));
  max-height: min(70vh, 560px);
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 12px 12px 0 0;
  padding: 14px 14px 18px;
  background: var(--card);
  box-shadow: 0 -6px 28px rgba(19, 34, 38, .18);
}
#report-dock-open:checked ~ .report-tab { display: none; }
#report-dock-open:checked ~ .report-panel { display: block; }
.report-panel-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.report-close { color: var(--muted-foreground); font-size: 18px; line-height: 1; cursor: pointer; }
.report-close:hover { color: var(--foreground); }
.report-form { display: grid; gap: 10px; }
.report-kind { display: flex; gap: 14px; }
.report-kind label { display: flex; align-items: center; gap: 6px; font-size: 13px; }
.report-kind input { width: auto; min-height: auto; }
.report-form input[type="file"] { padding: 6px; font-size: 12px; }
.report-context { font-size: 11px; word-break: break-all; }
.report-context code { font-size: 11px; }
@media (max-width: 640px) { .report-dock { right: 10px; } }

/* A line of help under a field. Was defined on the task page only; the client
   page needs it too. */
.field-hint { margin: 4px 0 0; font-size: 12.5px; }

/* Two fields side by side in a form - first and last name, start and end. Was
   copied into the project and client pages; a third page needed it, so it
   lives here now. */
.form-grid-two { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
@media (max-width: 640px) { .form-grid-two { grid-template-columns: 1fr; } }

/* The acceptance tick, on the signup form and on a setup link - two pages, so
   the rule is shared rather than copied into either. LEGAL-001. */
.terms-accept { align-items: flex-start; font-size: 12px; font-weight: 400; line-height: 1.5; }

/* The screen that asks for agreement before any page. Public layout, so it
   carries its own width. LEGAL-001. */
.accept-terms-panel { width: min(520px, 100%); margin: 48px auto; padding: 0 16px; display: grid; gap: 12px; }
.accept-terms-card { display: grid; gap: 12px; }
.accept-terms-changes { margin: 0; padding-left: 20px; display: grid; gap: 4px; }
.accept-terms-signout { justify-self: center; margin: 0; }
.link-button { border: 0; background: none; padding: 4px 8px; color: var(--muted-foreground); font: inherit; font-size: 13px; cursor: pointer; text-decoration: underline; }
.link-button:hover { color: var(--foreground); }

/* The beta terms, read signed in or signed out, so it carries its own width
   rather than relying on a page grid. LEGAL-001. */
.legal-page { width: min(760px, 100%); margin: 0 auto; padding: 24px 16px 48px; }
.legal-body { display: grid; gap: 4px; }
.legal-body h2 { margin: 18px 0 2px; font-size: 15px; }
.legal-body h2:first-of-type { margin-top: 4px; }
.legal-body p, .legal-body li { margin: 0 0 8px; line-height: 1.65; }
.legal-body ul { margin: 0 0 8px; padding-left: 20px; }

/* Right-click menus (UX-002). One component, every surface that opts in with
   data-context-menu. */
.ctx-menu {
  position: fixed;
  z-index: 1000;
  min-width: 210px;
  max-width: 280px;
  margin: 0;
  padding: 5px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--foreground);
  box-shadow: 0 8px 28px rgba(19, 34, 38, .16), 0 2px 6px rgba(19, 34, 38, .08);
  font-size: 13px;
}
.ctx-menu[hidden] { display: none !important; }
.ctx-menu button {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 0;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: inherit;
  padding: 6px 9px;
  font: inherit;
  font-size: 13px;
  text-align: left;
  white-space: normal;
}
/* Pick a date… under Schedule: a menu row over an unseen date field, so a tap
   opens the phone's own picker. DASH-002, patch 527. */
.ctx-menu .ctx-pick { position: relative; display: flex; align-items: center; border-radius: 6px; padding: 6px 9px; font-size: 13px; cursor: pointer; }
.ctx-menu .ctx-pick:hover, .ctx-menu .ctx-pick:focus-within { background: var(--accent); }
.ctx-menu .ctx-pick input[type="date"] { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0; border: 0; opacity: 0; cursor: pointer; }
.ctx-menu button:hover,
.ctx-menu button:focus { background: var(--accent); outline: none; }
.ctx-menu button.is-nested { padding-left: 22px; }
.ctx-menu button[aria-expanded]::after {
  content: "\203A";
  margin-left: auto;
  color: var(--muted-foreground);
}
/* A menu that only reads. Rows of label and value, then the description -
   used by the partner calendar, where every entry is information rather than
   an action. */
/* A field and its own button on one row. Written at `.ctx-menu .ctx-entry button`
   rather than `.ctx-entry button`, because `.ctx-menu button` above styles every
   menu item as a full-width row and would otherwise win on source order and
   stretch this one across the menu. */
.ctx-entry { display: flex; gap: 6px; align-items: center; padding: 4px 9px 6px; }
.ctx-entry input { flex: 1; min-width: 0; min-height: 30px; font-size: 13px; }
.ctx-entry.is-end { justify-content: flex-end; }
.ctx-entry > .typeahead { flex: 1; min-width: 0; }
.ctx-menu .ctx-entry button {
  flex: none;
  width: auto;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--card);
  padding: 5px 9px;
  color: var(--foreground);
  font-size: 12px;
  font-weight: 650;
  text-align: center;
}
.ctx-menu .ctx-entry button:hover,
.ctx-menu .ctx-entry button:focus { border-color: var(--primary); background: var(--accent); }

.ctx-read-row { display: flex; justify-content: space-between; gap: 12px; padding: 3px 9px; font-size: 12px; }
.ctx-read-row span { color: var(--muted-foreground); }
.ctx-read-row strong { text-align: right; }
.ctx-read-detail { margin: 0; padding: 4px 9px 6px; font-size: 12px; line-height: 1.45; white-space: pre-wrap; }
.ctx-read-detail.is-empty { color: var(--muted-foreground); font-style: italic; }
/* The attached picture inside a read-only panel. Capped in height so a tall
   photograph cannot push the decision off the bottom of the screen, and
   letterboxed rather than cropped so nothing is hidden. CLIENT-012. */
.ctx-read-thumb { margin: 4px 9px 2px; overflow: hidden; border: 1px solid var(--border); border-radius: var(--radius-sm); background: color-mix(in srgb, var(--secondary) 50%, transparent); }
.ctx-read-thumb img { display: block; width: 100%; max-height: 180px; object-fit: contain; }
/* A card that opens a panel says so with the cursor. */
[data-context-menu-click] { cursor: pointer; }
.ctx-menu .is-danger { color: var(--destructive); }
.ctx-menu .is-danger:hover,
.ctx-menu .is-danger:focus { background: color-mix(in srgb, var(--destructive) 10%, var(--card)); }
.ctx-sep { height: 1px; margin: 5px 4px; background: var(--border); }
/* The end date on its own row in the day menus' add box. CAL-001. */
.ctx-entry-date { font-size: 12px; color: var(--muted-foreground); }
.ctx-entry-date span { flex: none; }
.ctx-label {
  padding: 5px 9px 3px;
  color: var(--muted-foreground);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.ctx-menu input[type="date"],
.ctx-menu input[type="text"] {
  width: calc(100% - 18px);
  margin: 2px 9px 4px;
  padding: 5px 7px;
}

/* Per-member access on the Team page (TEAM-004). */
.access-summary { margin: 6px 0 0; font-size: 12px; }
.access-editor { margin-top: 6px; }
.access-editor summary { color: var(--primary); font-size: 12px; font-weight: 700; cursor: pointer; }
.access-editor .stacked-form { margin-top: 8px; }
/* A quick-form is a row of fields, so anything that belongs under the whole row
   — the access picker, a note about why the button is disabled — has to be told
   to span it rather than landing in the first column of a new row. */
.quick-form .access-editor,
.quick-form .entry-note { grid-column: 1 / -1; }
.quick-form .entry-note { margin: 0; font-size: 12px; }
/* MyOps' own confirm box, in the app's colours and dark mode, in place of the
   browser's "ops.mktgpm.com says". assets/js/confirm.js. UX-007. */
.confirm-dialog { width: min(420px, calc(100vw - 32px)); border: 1px solid var(--border); border-radius: var(--radius-sm, 10px); background: var(--card); color: var(--foreground); padding: 20px; box-shadow: 0 16px 48px rgba(19, 34, 38, .22); }
.confirm-dialog::backdrop { background: rgba(19, 34, 38, .38); }
.confirm-message { margin: 0 0 18px; font-size: 14px; line-height: 1.55; }
.confirm-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
/* A small form in a box of its own, opened by a button with
   data-open-dialog="<id>". Same frame as the confirm box. assets/js/dialogs.js.
   First used for the beta invitation and the row edit on Beta Access. */
.form-dialog { width: min(480px, calc(100vw - 32px)); border: 1px solid var(--border); border-radius: var(--radius-sm, 10px); background: var(--card); color: var(--foreground); padding: 20px; box-shadow: 0 16px 48px rgba(19, 34, 38, .22); }
.form-dialog::backdrop { background: rgba(19, 34, 38, .38); }
/* Written inside a table's row-actions cell, which is nowrap; without this the
   labels sit beside their fields and the box scrolls sideways. Patch 385. */
.form-dialog { white-space: normal; }
.form-dialog h2 { margin: 0 0 4px; font-size: 16px; font-weight: 600; }
.form-dialog .stacked-form { margin: 14px 0 0; }
.form-dialog textarea { min-height: 120px; }
/* A short boxed note beside a form: a bold lead-in, then the rest. First used
   for two-factor on sign-up and Profile. */
.form-note { margin: 0; border: 1px solid var(--border); border-radius: 8px; background: var(--card); padding: 12px 14px; color: var(--muted-foreground); font-size: 13px; line-height: 1.5; }
.form-note strong { color: var(--foreground); font-weight: 600; }
/* A walk-through box: rows of what is affected, a choice on each. Turn off
   and turn on clients. WORKSPACE-001, patches 618 and 620. */
.walk-box { width: min(560px, calc(100vw - 32px)); }
.walk-box .off-row { display: grid; gap: 6px; margin: 0; border: 0; border-top: 1px solid var(--border); padding: 12px 0 0; }
.walk-box .off-row legend { display: grid; gap: 2px; float: left; width: 100%; margin-bottom: 4px; padding: 0; }
.walk-box .off-row legend + * { clear: both; }
.walk-box .off-row strong { font-weight: 600; }
.walk-box .off-row small { color: var(--muted-foreground); font-size: 12.5px; }
.walk-box .off-choice { display: flex; align-items: center; gap: 8px; min-height: 36px; font-size: 14px; cursor: pointer; }
.walk-box .off-choice input { width: 18px; height: 18px; margin: 0; }
.walk-box .off-until { margin: 4px 0 0; color: var(--muted-foreground); font-size: 13px; }
.form-dialog-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }

/* A card that folds: a header line that says where things stand, and the body
   underneath. <details>, so it works with no script and from the keyboard.
   First used on a project's Settings; meant for any page that needs to give
   space back (UX-018). UX-022. */
.card.fold-card { padding: 0; }
.fold-head { display: flex; align-items: baseline; gap: 10px; padding: 14px 16px; cursor: pointer; list-style: none; }
.fold-head::-webkit-details-marker { display: none; }
.fold-head::before { content: "\25B8"; flex: none; color: var(--muted-foreground); transition: transform .15s ease; }
.fold-card[open] > .fold-head::before { transform: rotate(90deg); }
.fold-head strong { font-size: 14px; }
.fold-head small { min-width: 0; margin-left: auto; overflow: hidden; color: var(--muted-foreground); font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
.fold-head:hover strong, .fold-head:focus-visible strong { color: var(--primary); }
.fold-body { display: grid; gap: 12px; padding: 0 16px 16px; }
.fold-divider { border-top: 1px solid var(--border); }

/* Who can reach a project, on its Settings tab. TEAM-004. */
.project-access-form { display: grid; gap: 10px; }
.grant-set { display: grid; gap: 6px; margin: 0; border: 1px solid var(--border); border-radius: 7px; padding: 10px 12px; }
.grant-set legend { color: var(--muted-foreground); font-size: 11px; font-weight: 700; text-transform: uppercase; }
.grant-set .muted { font-size: 11px; }

/* Attachment row. Shared: the task page and the client review page both list
   files this way, and the partner task page will when it gains thumbnails.
   It lived in two page style blocks until patch 213, and they had already
   drifted - the review page had lost the hover tint and the truncation, so a
   long filename wrapped there and clipped on the task page. Same symptom the
   danger-button duplication produced in patch 150: nobody chose to duplicate
   it, each page just needed it and had nowhere shared to put it.

   strong and span are styled by position inside the component rather than by
   name, which is safe here because they are this component's own markup - and
   the text sits in .attachment-text so both rules keep matching once a
   thumbnail is beside them. */
/* A file and what can be done to it, on one line. The anchor keeps the file;
   the badge and the switch sit beside it rather than inside a link. CLIENT-018. */
.attachment-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.attachment-row > .attachment-item { flex: 1 1 auto; min-width: 0; }
.attachment-visibility { margin: 0; flex: 0 0 auto; }

/* A list of files on a task - the team page and the partner page. */
.attachment-list { display: grid; gap: 8px; }
.attachment-item { display: grid; gap: 3px; border: 1px solid var(--border); border-radius: 8px; background: var(--card); padding: 11px 12px; color: var(--foreground); text-decoration: none; }
.attachment-item:hover { border-color: var(--primary); background: color-mix(in srgb, var(--accent) 18%, var(--card)); }
.attachment-item strong { overflow: hidden; font-size: 13px; text-overflow: ellipsis; white-space: nowrap; }
.attachment-item span { overflow: hidden; color: var(--muted-foreground); font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
.attachment-item.has-thumb { grid-template-columns: 40px minmax(0, 1fr); align-items: center; gap: 10px; }
.attachment-text { display: grid; gap: 3px; min-width: 0; }
.attachment-thumb { width: 40px; height: 40px; border-radius: 6px; background: var(--secondary); object-fit: cover; }

/* Counts that filter the list under them. The System page has its own copy of
   this shape under .mail-tally, written before there was a second page wanting
   it; convert that one when the System page is next touched rather than
   sweeping both now. */
.tally-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 10px; margin-bottom: 14px; }
.tally { display: grid; gap: 1px; border: 1px solid var(--border); border-radius: 8px; padding: 9px 11px; color: inherit; text-decoration: none; }
.tally:hover { border-color: var(--primary); }
/* At .tally rather than .tally-strip a, so the open state beats the base rule
   without an !important and without depending on source order. */
.tally.is-open { border-color: var(--primary); background: color-mix(in srgb, var(--primary) 10%, var(--card)); }
.tally > strong { font-size: 19px; font-variant-numeric: tabular-nums; }
.tally > span { color: var(--muted-foreground); font-size: 12px; }

/* A wide table carries a narrow screen by scrolling inside its own box, rather
   than the columns squeezing until words break mid-syllable. */
.table-scroll { overflow-x: auto; }

/* The sentence under a table that explains what it is not telling you. */
.card-note { margin: 12px 0 0; color: var(--muted-foreground); font-size: 13px; }

/* The file sent with a client request, shown wherever a request is listed: the
   client's own Requests tab, the agency client page, and the Requests inbox.
   Three places from the start, so it goes here rather than into the first page
   that needed it. */
.request-file { display: inline-flex; align-items: center; gap: 6px; margin: 4px 0; font-size: 12px; }
.request-file-tag { border: 1px solid var(--border); border-radius: 5px; padding: 1px 5px; color: var(--muted-foreground); font-size: 10px; }

/* The photo picker, on the client's request form and on a review item.
   Two pages from the start, so it lives here rather than in whichever one
   happened to be written first.

   grid-auto-rows: max-content is the load-bearing line. Without it the rows
   were compressed to fit the scroll box, and because each tile clips its
   overflow the result was a letterbox strip of the top of every photograph -
   which reads as broken images rather than as a layout that gave way. */
/* The wrapper the request form's picker sits in: the open link, the grid and
   the chosen-photo line, stacked. */
.request-library { display: grid; gap: 10px; margin-bottom: 14px; }
.library-hint { margin: 0 0 10px; color: var(--muted-foreground); font-size: 13px; }
.library-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); align-content: start; grid-auto-rows: max-content; gap: 12px; max-height: 520px; overflow-y: auto; }
.library-tile { display: grid; gap: 0; align-content: start; overflow: hidden; border: 1px solid var(--border); border-radius: 8px; background: var(--card); }
.library-tile.is-chosen { border-color: var(--primary); box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 35%, transparent); }
/* The picture opens the full photograph; the button underneath is what
   attaches it. Two targets, because clicking a face to look at it and clicking
   it to commit are different intentions and were the same click before. */
.library-view { display: block; }
.library-view img { display: block; width: 100%; aspect-ratio: 4 / 3; background: var(--secondary); object-fit: cover; }
.library-name { display: block; overflow: hidden; padding: 6px 8px 0; color: var(--muted-foreground); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }
.library-pick { display: block; margin: 6px 8px 8px; border: 1px solid var(--border); border-radius: 6px; background: var(--card); padding: 5px 8px; color: var(--foreground); font-size: 12px; font-weight: 600; text-align: center; text-decoration: none; cursor: pointer; }
.library-pick:hover { border-color: var(--primary); color: var(--primary); }
.library-tile.is-chosen .library-pick { border-color: var(--primary); color: var(--primary); }

/* The panel a file opens in. ASSET-002: a new window loses the reviewer their
   place, and on a phone leaves a second window to close.

   ::backdrop is the browser's own layer behind a <dialog> - one of the things
   that comes free with the native element and has to be hand-built otherwise. */
.file-viewer { width: min(1100px, 94vw); max-height: 92vh; border: 1px solid var(--border); border-radius: 10px; background: var(--card); padding: 0; color: var(--foreground); }
.file-viewer::backdrop { background: rgba(19, 34, 38, .62); }
.file-viewer-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; border-bottom: 1px solid var(--border); padding: 12px 14px; }
.file-viewer-head strong { overflow: hidden; font-size: 14px; text-overflow: ellipsis; white-space: nowrap; }
.file-viewer-head-actions { display: flex; gap: 8px; }
/* The picture sizes to the panel rather than the panel to the picture, so a
   large photograph cannot push the Close button off the screen. */
.file-viewer-body { display: grid; place-items: center; padding: 12px; }
.file-viewer-body img { display: block; max-width: 100%; max-height: calc(92vh - 92px); object-fit: contain; }
/* A long picture fits the width and scrolls under the header. ASSET-002. */
.file-viewer.is-tall[open] { display: flex; flex-direction: column; }
.file-viewer.is-tall .file-viewer-body { flex: 1 1 auto; min-height: 0; overflow: auto; place-items: start center; }
.file-viewer.is-tall .file-viewer-body img { max-height: none; }
/* A PDF takes the whole panel, so its pages are readable. ASSET-002. */
.file-viewer.is-document[open] { display: flex; flex-direction: column; height: 92vh; }
.file-viewer.is-document .file-viewer-body { flex: 1 1 auto; min-height: 0; place-items: stretch; padding: 0; }
.file-viewer-body iframe { display: block; width: 100%; height: 100%; border: 0; }

/* Finished work on the client calendar: still there, visibly done. CLIENT-011.

   Greyed rather than hidden, because a client asking whether something went out
   should be able to answer it by looking - and a card that disappears on
   completion looks like work that was dropped.

   Only drawn where a page supplies `done`, which today is the client calendar
   alone, so no team view changes appearance. */
.calendar-task.is-done { opacity: .62; }
.calendar-task.is-done strong { text-decoration: line-through; text-decoration-thickness: 1px; }
.calendar-task.is-done .task-meta { text-decoration: none; }

/* The key under it. Three states, in the order somebody meets them. */
.calendar-key { display: flex; flex-wrap: wrap; gap: 14px; margin: 12px 0 0; color: var(--muted-foreground); font-size: 12px; }
.calendar-key-item { display: inline-flex; align-items: center; gap: 6px; }
.calendar-key-swatch { display: inline-block; width: 12px; height: 12px; border: 1px solid var(--border); border-radius: 3px; background: var(--card); }
.calendar-key-swatch.is-done { opacity: .62; background: var(--secondary); }
.calendar-key-swatch.is-yours { border: 1px dashed var(--primary); } /* CAL-001 */
/* The third entry is not a card colour - a requested date shows as a small
   coloured note on the card - so the key shows the note rather than inventing a
   swatch that appears nowhere. A legend that does not match the thing it
   explains is worse than no legend. */
.calendar-key-note { color: var(--primary); font-size: 11px; font-weight: 600; }

/* Planning panels beside a calendar - Recurring and Unscheduled. Lifted out of
   dashboard.php in patch 267 so the dashboard, the Tasks page and the project
   page look the same because they are the same, rather than because two sets of
   rules agree. The header carries a hover affordance deliberately: Sarah named
   the dashboard treatment as the one that reads right. CAL-014. */
/* No padding of its own - `.card` supplies 14px, and the header below reaches
   past it with negative margins matched to that number. Patch 267 set 16px here
   and 16px there, which was wrong twice: it overrode the card, and it disagreed
   with the 14px the dashboard rule was written against. */
/* No padding on the panel itself - the header and the body carry their own.
   Three earlier attempts all tried to let the header reach PAST the panel's
   padding with negative margins, and each failed differently: calc(100% + 32px)
   inflated the column so the whole thing overflowed; width: auto let the button
   shrink-wrap its own text, because a <button> is not a block box and sizes to
   content; and making the panel a grid did not help, because stretch alignment
   does not override a form control's shrink-to-fit width either.
   Taking the padding off removes the reason for any of it: the header is simply
   the full width of the panel, with its own padding inside. CAL-016. */
.planning-panel {
  min-width: 0;
  padding: 0;
  /* The guarantee, and it is not new: the panel this replaced carried
     `overflow: hidden` and that is why the Tasks page never showed this. Patch
     267 dropped it while lifting the rules, and three attempts at sizing the
     header followed - calc(100% + 32px), then auto, then stretching as a grid
     item - none of which could hold, because a <button> sizes to its own text
     whatever its container says. Clipping the panel makes the header's width
     irrelevant: nothing can leave the box. Wrapping above means it does not come
     to that, and this is here so it cannot come to that again. CAL-016. */
  overflow: hidden;
}

.planning-panel-toggle {
  /* THE actual cause of CAL-016, found on the fourth attempt.
     `button, .button { white-space: nowrap }` at the top of this file applies to
     every button in the app, and this header is a button - so its description
     could never wrap, whatever was done to the width. That is why all three
     earlier fixes failed the same way and why the last one clipped instead:
     calc(100% + 32px) made a wide button with unwrappable text, `auto` let it
     shrink-wrap to that same unwrappable text, and capping the width left the
     text nowhere to go. One declaration undoes all of it. */
  white-space: normal;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  /* The hard cap. Without it a button grows to fit its text whatever the
     container says, which is what put the description out over the calendar. */
  max-width: 100%;
  min-width: 0;
  margin: 0;
  border: 0;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  background: transparent;
  color: var(--foreground);
  padding: 13px 14px;
  text-align: left;
}

.planning-panel-toggle:hover {
  background: color-mix(in srgb, var(--secondary) 70%, transparent);
  color: var(--foreground);
}

.planning-panel-toggle span {
  display: grid;
  gap: 3px;
  min-width: 0;
}

.planning-panel-toggle strong {
  font-size: 15px;
}

.planning-panel-toggle small {
  min-width: 0;
  color: var(--muted-foreground);
  font-size: 12px;
  overflow-wrap: anywhere;
}

.planning-panel-toggle em {
  display: inline-grid;
  place-items: center;
  min-width: 28px;
  height: 24px;
  flex: 0 0 auto;
  border-radius: 999px;
  background: var(--secondary);
  color: var(--foreground);
  font-size: 12px;
  font-style: normal;
  font-weight: 600;
  line-height: 1;
}

.planning-panel-body {
  min-width: 0;
  padding: 12px 14px 14px;
}

/* The way out of a capped list, and it needs a class of its own because it sits
   above the list rather than in the header. */
.planning-panel-actions {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 10px;
}

/* A link that reads as a link inside a card header or panel. Lived in the
   dashboard's inline <style> while the shared panel partial used it, which is
   the shared-class leak this project keeps finding - a class that resolves on
   one page and renders as plain text everywhere else. */
.panel-link {
  color: var(--primary);
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}

.panel-link:hover {
  text-decoration: underline;
}

/* Ten cards, then scroll. Sarah, 2026-09-13: *"10 in each before they scroll
   and they shorten to however many are in the column if less than 10"*. CAL-017.
   The two pages disagreed: the dashboard capped at 320px, which showed about one
   card out of 63 and read as broken, and the Tasks page had no cap at all and
   ran a column of 61 down past the calendar.

   A cap in pixels rather than a count, because CSS cannot count children and a
   card is not a fixed height - names wrap, which patch 269 made them do on
   purpose. The arithmetic is written out so it can be re-derived: a card is
   9+9 padding, 2 border, a 14px/1.5 title, a 3px gap and a 12px/1.5 line under
   it, and cards sit 8px apart. So ten of them, nine gaps between. A long name
   that wraps makes its own card taller and shows a little under ten, which is
   the honest trade for keeping the wrap. Fewer than ten and the panel shrinks
   to fit, because this is a maximum. */
.planning-panel-body .task-list {
  --planning-card-height: 62px;
  --planning-card-gap: 8px;
  max-height: calc(10 * var(--planning-card-height) + 9 * var(--planning-card-gap));
  /* On a shorter window, as many as fit beside the three headers, so one open
     list scrolls by itself without the pinned column scrolling around it. */
  max-height: min(calc(10 * var(--planning-card-height) + 9 * var(--planning-card-gap)), max(180px, calc(100vh - 420px)));
  /* Room for the hover border and focus ring, which a scroll box clips. */
  padding: 2px;
  overflow-y: auto;
}

/* Narrow, where the panels sit above the calendar rather than beside it and the
   page scrolls as one. A scroll box inside a scrolling page is the worse of the
   two there. */
@media (max-width: 900px) {
  .planning-panel-body .task-list { max-height: none; }
}

.planning-panel.is-collapsed .planning-panel-body {
  display: none;
}

/* The icon is drawn in the markup for every width and shown only on a phone,
   where the three panels become small boxes. A desktop keeps the header it has
   always had. Written with the button in the selector because
   `.planning-panel-toggle span` sets `display: grid` on every span in there and
   would otherwise win on specificity - which drew the icon on the desktop
   header. */
.planning-panel-toggle .planning-panel-icon { display: none; }

/* Three small boxes with icons, side by side, and the list opens underneath
   them. Sarah, 2026-09-29: *"i think the recurring unscheduled and unassigned
   need to become small boxes with icons... on the mobile view"*, with *"a
   recurring symbol a calendar and a person icon? the last two with overlayed ?
   marks"*. A box is its icon and its count; the words are hidden from the eye
   and still read aloud, and the box you opened stays lit in the row rather than
   moving or disappearing.

   `display: contents` is what lets the list sit under the row: the panel stops
   being a box of its own, so its header and its list are both items of the same
   three-column grid - the header keeping its column, the list spanning all three
   on the line below. `order` is what keeps the three headers together: without
   it an open list would land between the headers and push the third one onto a
   row of its own. MOBILE-001. */
@media (max-width: 760px) {
  .planning-lists {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
  }

  .planning-panel { display: contents; }

  /* The header is the box now, so it carries what the card used to. Icon and
     count sit side by side rather than stacked: Sarah, 2026-09-29, *"I don't
     think that the recurring and the seven need to be stacked. There's no reason
     they can't be side by side taking up less room"*, and the rule under it -
     *"every instance, we should be reducing the amount of scrolling required."* */
  .planning-panel-toggle {
    order: 1;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 7px;
    min-height: 44px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--card);
    padding: 8px 6px;
    text-align: center;
  }

  .planning-panel-toggle[aria-expanded="true"] {
    border-color: color-mix(in srgb, var(--primary) 45%, var(--border));
    background: color-mix(in srgb, var(--accent) 60%, var(--card));
  }

  /* Hidden from the eye, not from a screen reader: the box still says which
     list it is. The icon is a direct child span too, so it is spelled out of
     this rule rather than hidden along with the words. */
  .planning-panel-toggle > span:not(.planning-panel-icon) {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .planning-panel-toggle .planning-panel-icon {
    display: block;
    color: var(--muted-foreground);
  }

  .planning-panel-toggle em {
    min-width: 24px;
    height: 20px;
    font-size: 11px;
  }

  /* The list itself, on the line below the three boxes and as wide as all of
     them, with the card edges the panel used to give it. */
  .planning-panel-body {
    order: 2;
    grid-column: 1 / -1;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--card);
  }
}

.planning-panel.drop-target {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
}

/* The Admin pages: System Activity and the reports under Reports. Moved here
   from system.php when that page was split into five, SYS-011. */
/* Scoped to the direct children the rule was written for, so a badge or any
   other shared component inside a dd keeps its own layout. */
.storage-note { display: block; margin-top: 3px; color: var(--muted-foreground); font-size: 12px; font-weight: 400; }
.storage-test { margin-top: 14px; border-top: 1px solid var(--border); padding-top: 12px; }
.storage-test-head { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
.storage-test-head .storage-note { margin-top: 0; }
.storage-steps { display: grid; gap: 8px; margin: 0; padding-left: 18px; }
/* Named classes rather than bare strong/span inside the li: a span in here is
   also the shared badge, and a descendant rule would have flattened it. That
   mistake has shipped four times in this app - see CLAUDE.md. */
.storage-step-label { display: block; margin-top: 3px; }
.storage-step-detail { display: block; color: var(--muted-foreground); font-size: 12px; overflow-wrap: anywhere; }
.mail-tallies { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 10px; margin-bottom: 14px; }
/* Written at .mail-tally rather than at .mail-tallies a, so the open state can
   beat the base rule without an !important and without depending on order. */
.mail-tally { display: grid; gap: 1px; border: 1px solid var(--border); border-radius: 8px; padding: 9px 11px; color: inherit; text-decoration: none; }
.mail-tally:hover { border-color: var(--primary); }
.mail-tally.is-open { border-color: var(--primary); background: color-mix(in srgb, var(--primary) 10%, var(--card)); }
.mail-tally > strong { font-size: 19px; font-variant-numeric: tabular-nums; }
.mail-tally > span { color: var(--muted-foreground); font-size: 12px; }
.mail-showing { margin: 0 0 12px; color: var(--muted-foreground); font-size: 13px; }
.mail-showing strong { color: var(--foreground); }
.system-failures { display: grid; gap: 12px; margin: 14px 0 10px; padding: 0; list-style: none; }
.system-failures li { border-bottom: 1px solid var(--border); padding-bottom: 12px; }
.system-failures li:last-child { border-bottom: 0; padding-bottom: 0; }
.system-failure-head { display: flex; align-items: center; gap: 8px; margin: 0 0 4px; font-size: 12px; }
.system-failure-line { margin: 0; font-size: 13px; line-height: 1.5; overflow-wrap: anywhere; }
.system-failure-detail { margin: 8px 0 0; padding: 10px; border-radius: var(--radius-sm); background: var(--secondary); font-size: 12px; line-height: 1.5; overflow-x: auto; white-space: pre-wrap; word-break: break-word; }
.system-presence { display: grid; gap: 8px; margin: 14px 0 10px; padding: 0; list-style: none; }
.system-presence li { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; border-bottom: 1px solid var(--border); padding-bottom: 8px; }
.system-presence li:last-child { border-bottom: 0; padding-bottom: 0; }
.system-presence strong { font-size: 14px; }
.system-presence .muted { font-size: 12px; }
.mail-log-scroll { overflow-x: auto; }
/* The scroll container carries a narrow screen, rather than the columns
   squeezing: without a min-width the To column broke addresses mid-word
   ("tucker@exa / mple.com"), which is unreadable and looks like corruption. */
.mail-log { width: 100%; min-width: 620px; border-collapse: collapse; font-size: 13px; }
.mail-log th { border-bottom: 1px solid var(--border); padding: 0 10px 6px 0; color: var(--muted-foreground); font-size: 11px; letter-spacing: .06em; text-align: left; text-transform: uppercase; }
.mail-log td { border-bottom: 1px solid var(--border); padding: 8px 10px 8px 0; vertical-align: top; }
.mail-log tr:last-child td { border-bottom: 0; }
.mail-when { color: var(--muted-foreground); font-variant-numeric: tabular-nums; white-space: nowrap; }
.mail-to, .mail-subject { overflow-wrap: anywhere; }
/* The reason a message was not sent is a sentence, so Result needs room:
   these three widths leave it roughly a quarter of the table. */
.mail-to { width: 21%; }
.mail-subject { width: 27%; }
.mail-bcc, .mail-error, .mail-reason { display: block; color: var(--muted-foreground); font-size: 11px; }
.mail-error { color: var(--destructive); }
.system-layout { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(280px, .8fr); gap: 16px; align-items: start; }
/* Backlog Sync and the Codex API used to sit full width below the grid, which
   put the two things you actually come here to click underneath the whole
   changed-file list. They are in the left column now, directly under the
   release box. */
.system-main { display: grid; gap: 16px; align-content: start; min-width: 0; }
.system-patch-number { display: inline-grid; gap: 4px; width: fit-content; border: 1px solid var(--border); border-radius: 8px; background: color-mix(in srgb, var(--secondary) 45%, transparent); padding: 12px 16px; }
.system-patch-number span { color: var(--muted-foreground); font-size: 11px; font-weight: 600; text-transform: uppercase; }
.system-patch-number strong { font-size: 34px; line-height: 1; }
.system-detail-list { display: grid; grid-template-columns: repeat(2, minmax(180px, 1fr)); gap: 10px; margin: 0; }
.system-detail-list div { border-top: 1px solid var(--border); padding-top: 10px; }
.system-detail-list dt { color: var(--muted-foreground); font-size: 11px; font-weight: 600; text-transform: uppercase; }
.system-detail-list dd { margin: 4px 0 0; color: var(--foreground); font-weight: 600; }
.system-subsection { display: grid; gap: 8px; border-top: 1px solid var(--border); padding-top: 14px; }
.system-subsection h2 { margin: 0; font-size: 15px; }
.system-subsection p { margin: 0; color: var(--muted-foreground); }
.system-file-list { display: grid; gap: 6px; margin: 0; padding-left: 18px; }
.system-file-list code { font-size: 12px; }
.system-history { display: grid; gap: 12px; }
.system-history article { display: grid; gap: 8px; border-top: 1px solid var(--border); padding-top: 12px; }
.system-history article:first-child { border-top: 0; padding-top: 0; }
.system-history strong, .system-history span { display: block; }
.system-history span { margin-top: 3px; color: var(--muted-foreground); font-size: 12px; }
.system-history p { margin: 0; color: var(--muted-foreground); font-size: 13px; line-height: 1.4; }
/* The tickets a release was part of, linked to their cards. DEPLOY-002. */
.release-tickets { margin: 0; font-size: 12px; }
/* The older patches, folded away. Sits with the rules above because the
   history markup it wraps is defined on this page. SYNC-001. */
.system-history-more { border-top: 1px solid var(--border); padding-top: 12px; display: grid; gap: 12px; }
.system-history-more summary { cursor: pointer; color: var(--muted-foreground); font-size: 13px; width: max-content; }
.system-history-more summary:hover { color: var(--primary); }
.system-api-note { margin: 12px 0 0; color: var(--muted-foreground); font-size: 13px; }
.system-side { display: grid; gap: 16px; align-content: start; min-width: 0; }
/* Patch / Releases is half and half: the patch, database and failures on one
   side, the releases before it on the other. Sarah's drawing, SYS-011. */
.system-layout.is-even { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
/* Reports opens onto the list of reports. */
.report-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }
.report-link { display: grid; gap: 6px; color: inherit; text-decoration: none; }
.report-link:hover { border-color: var(--primary); }
.report-link h2 { margin: 0; font-size: 15px; }
.report-link p { margin: 0; color: var(--muted-foreground); font-size: 13px; }
.report-link .report-state { color: var(--foreground); font-size: 13px; font-weight: 600; }
@media (max-width: 900px) { .system-layout, .system-layout.is-even, .system-detail-list { grid-template-columns: 1fr; } }

/* The one filter control: a search box, a Filters button, and the choices in a
   panel under it. Shared so every list can take it, phone included. UX-020. */
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

.filter-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.filter-bar.is-busy { opacity: .72; }
.filter-search { flex: 1 1 260px; max-width: 420px; display: block; }
.filter-search input { width: 100%; }
.filter-open { position: relative; display: flex; align-items: center; gap: 6px; }

.filter-button {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--input);
  background: var(--card);
  color: var(--foreground);
  font-size: 13px;
  font-weight: 600;
}
.filter-button.is-on { border-color: var(--primary); background: var(--accent); color: var(--primary); }
.filter-clear {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--muted-foreground);
}
.filter-clear:hover { border-color: var(--primary); color: var(--primary); }

.filter-panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 30;
  width: min(560px, calc(100vw - 32px));
  display: grid;
  gap: 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: 0 18px 44px rgba(19, 34, 38, .16);
  padding: 16px;
}
.filter-panel[hidden] { display: none; }
.filter-panel-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.filter-section { display: grid; gap: 10px; }
.filter-section + .filter-section { border-top: 1px solid var(--border); padding-top: 12px; }
.filter-section-title { color: var(--muted-foreground); font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; }

.filter-quick { display: flex; flex-wrap: wrap; gap: 8px; }
.filter-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 32px;
  border: 1px solid var(--input);
  border-radius: 999px;
  background: var(--card);
  padding: 4px 12px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.filter-pill.is-on { border-color: var(--primary); background: var(--accent); color: var(--primary); }
.filter-pill input { width: auto; margin: 0; }

.filter-group { display: flex; align-items: flex-start; gap: 10px; border-bottom: 1px solid var(--border); padding-bottom: 8px; }
.filter-group[hidden] { display: none; }
.filter-group-label { flex: 0 0 76px; padding-top: 4px; color: var(--muted-foreground); font-size: 12px; font-weight: 600; }
.filter-options { flex: 1 1 auto; display: flex; flex-wrap: wrap; gap: 6px 16px; min-width: 0; }
.filter-options .checkbox-line { font-weight: 400; }
/* A project of a client not ticked. .checkbox-line sets display: flex, which
   would otherwise outrank the hidden attribute. UX-020. */
.filter-options .checkbox-line[hidden] { display: none; }
.filter-group-remove {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  min-height: 0;
  padding: 0;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--muted-foreground);
}
.filter-group-remove:hover { border-color: var(--primary); color: var(--primary); }
.filter-add { display: flex; flex-wrap: wrap; gap: 8px; }
.filter-add-button { min-height: 30px; border: 1px dashed var(--input); border-radius: 999px; background: var(--card); padding: 4px 11px; font-size: 12px; font-weight: 400; }

/* On a phone the panel is a sheet at the bottom: it closes with a thumb and
   leaves the list visible above it. Sarah, 2026-09-29. */
@media (max-width: 760px) {
  .filter-search { max-width: none; }
  .filter-panel {
    position: fixed;
    inset: auto 0 0 0;
    width: auto;
    max-height: 62vh;
    overflow: auto;
    border-radius: var(--radius) var(--radius) 0 0;
    box-shadow: 0 -14px 40px rgba(19, 34, 38, .18);
  }
  .filter-group { flex-wrap: wrap; }
  .filter-options { flex-direction: column; gap: 2px; }
  .filter-options .checkbox-line { min-height: 36px; }
  .filter-pill { min-height: 40px; font-size: 13px; }
  .filter-add-button { min-height: 40px; font-size: 13px; }
}

/* Filters as one button per field. On a computer the buttons sit in the bar
   and each drops its own list; on a phone one Filters button opens a sheet of
   rows, and a row opens its list on its own screen. Sarah approved the mockup
   on 2026-10-10 (mockups/filters-rows.html). UX-020, patch 574. */
.filter-quick-section, .filter-fields-section { min-width: 0; }
.filter-field { position: relative; }
.filter-field-button { display: inline-flex; align-items: center; gap: 4px; min-height: 36px; max-width: 260px; margin: 0; border: 1px solid var(--input); border-radius: 8px; background: var(--card); color: var(--foreground); padding: 0 9px 0 11px; font-size: 13px; font-weight: 500; white-space: nowrap; }
.filter-field-button.is-on { border-color: color-mix(in srgb, var(--primary) 55%, var(--border)); background: var(--accent); color: color-mix(in srgb, var(--primary) 85%, #000000); font-weight: 600; }
.filter-field.is-open > .filter-field-button { border-color: var(--primary); }
.filter-field-button:not(.is-on) .filter-field-colon { display: none; }
.filter-field-colon { margin-left: -4px; }
.filter-field-value { min-width: 0; max-width: 150px; overflow: hidden; text-overflow: ellipsis; }
.filter-field-caret { flex: none; margin-left: 2px; color: var(--muted-foreground); }
.filter-field-list { position: absolute; top: calc(100% + 6px); left: 0; z-index: 45; display: grid; gap: 6px; width: 280px; border: 1px solid var(--border); border-radius: 12px; background: var(--card); box-shadow: 0 16px 40px rgba(19, 34, 38, .16); padding: 8px; }
.filter-field.is-right .filter-field-list { left: auto; right: 0; }
.filter-field-list[hidden] { display: none; }
.filter-field-head { display: none; }
.filter-field-find { width: 100%; min-height: 36px; }
.filter-field-list .filter-options { display: grid; gap: 0; max-height: 280px; overflow-y: auto; }
.filter-field-list .checkbox-line { min-height: 36px; border-radius: 7px; padding: 0 6px; font-weight: 400; }
.filter-field-list .checkbox-line:hover { background: var(--secondary); }
.filter-field-list .checkbox-line[hidden] { display: none; }
.filter-field-list .checkbox-line.is-extra { border-bottom: 1px solid var(--border); border-radius: 7px 7px 0 0; margin-bottom: 2px; }
.filter-field-foot { display: flex; align-items: center; justify-content: space-between; border-top: 1px solid var(--border); padding: 8px 4px 2px; color: var(--muted-foreground); font-size: 12px; }
.filter-field-clear { min-height: 0; margin: 0; border: 0; padding: 2px 4px; background: none; color: var(--primary); font-size: 12.5px; font-weight: 600; }
.filter-done { min-height: 34px; margin: 0; border: 1px solid var(--primary); border-radius: 8px; padding: 0 14px; background: var(--primary); color: var(--primary-foreground, #fff); font-size: 13px; font-weight: 600; }
@media (min-width: 761px) {
  /* The field buttons join the bar: the panel and its sections step out of
     the way and leave only the buttons. */
  .filter-open.has-fields > .filter-button { display: none; }
  .filter-open.has-fields .filter-panel,
  .filter-open.has-fields .filter-panel[hidden],
  .filter-open.has-fields .filter-fields-section,
  .filter-open.has-fields .filter-fields { display: contents; }
  .filter-open.has-fields .filter-panel-head,
  .filter-open.has-fields .filter-quick-section,
  .filter-open.has-fields .filter-fields-section > .filter-section-title { display: none; }
  .filter-open.has-fields { flex-wrap: wrap; }
  .filter-open.has-fields > .filter-clear { order: 99; width: auto; height: auto; border: 0; background: none; color: var(--primary); font-size: 13px; font-weight: 600; }
  .filter-open.has-fields > .filter-clear svg { display: none; }
  .filter-open.has-fields > .filter-clear::after { content: "Clear all"; }
}
@media (max-width: 760px) {
  /* A sheet that covers the screen, so nothing at the bottom sits over it. */
  .filter-panel { inset: 6vh 0 0 0; z-index: 960; display: flex; flex-direction: column; gap: 12px; max-height: none; border-radius: 18px 18px 0 0; padding: 14px 14px calc(18px + env(safe-area-inset-bottom)); }
  .filter-panel[hidden] { display: none; }
  .filter-panel-head { align-items: center; gap: 10px; }
  .filter-panel-head strong { flex: 1; font-size: 16px; }
  .filter-fields { border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }
  .filter-field { position: static; }
  .filter-field + .filter-field { border-top: 1px solid var(--border); }
  .filter-field-button { display: flex; width: 100%; max-width: none; min-height: 52px; border: 0; border-radius: 0; background: var(--card); padding: 0 14px; font-size: 14px; }
  .filter-field-button.is-on { background: var(--card); }
  .filter-field-name { flex: 0 0 96px; font-weight: 600; text-align: left; }
  .filter-field-colon { display: none; }
  .filter-field-value { flex: 1; max-width: none; color: var(--muted-foreground); text-align: left; }
  .filter-field-button.is-on .filter-field-value { color: color-mix(in srgb, var(--primary) 85%, #000000); font-weight: 600; }
  .filter-field-value:empty::before { content: "Any"; }
  .filter-field-caret { transform: rotate(-90deg); }
  .filter-field-list { position: absolute; inset: 0; z-index: 2; display: flex; flex-direction: column; width: auto; border: 0; border-radius: 18px 18px 0 0; box-shadow: none; padding: 14px 14px calc(18px + env(safe-area-inset-bottom)); }
  .filter-field-head { display: flex; align-items: center; gap: 8px; }
  .filter-field-head strong { flex: 1; font-size: 16px; }
  .filter-field-back { width: 38px; height: 38px; min-height: 0; margin: 0; border: 0; padding: 0; background: none; font-size: 24px; line-height: 1; }
  .filter-field-list .filter-options { flex: 1; max-height: none; }
  .filter-field-list .checkbox-line { min-height: 46px; font-size: 15px; }
  .filter-field-foot { display: none; }
  .filter-field-find { min-height: 44px; font-size: 16px; }
}

/* The Tasks header is the Add block alone, full width, so its fields sit on
   one line. Search and filters moved up beside the view tabs. Sarah's mock,
   2026-10-03. UX-020. */
.tasks-header { margin-bottom: 16px; }
.tasks-header > .add-block { margin-bottom: 0; }

/* A view switch with its tools on the same row: the boxed Calendar / Tasks /
   Board, then search and Filters, then anything a page puts at the far right.
   Shared by Tasks and a project. The panels below take the full width. */
.view-tabs-wrap.has-toolbar { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 16px; }
.view-tabs-wrap.has-toolbar > .view-tabs { margin: 0; }
.view-tabs-wrap.has-toolbar > .view-panel { grid-column: 1 / -1; }
.view-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; min-width: 0; }
.view-toolbar .filter-bar { flex: 1 1 auto; flex-wrap: nowrap; }
/* A basis of 260px once stood the search box 260px tall when this row became
   a column; a narrow basis, so it shrinks beside the button instead. */
.view-toolbar .filter-search { flex: 0 1 240px; min-width: 140px; max-width: none; }
.view-toolbar .filter-open { flex: 0 0 auto; }
.view-toolbar-end { margin-left: auto; }

/* The view bar: tabs on the left, then search, Filters, ··· and + Add at the
   right, on one row under the page head on every tab. Sarah approved the
   mockup on 2026-10-09 (mockups/project-view-bar.html). UX-029, patch 570. */
.view-tabs-wrap.has-toolbar > .view-toolbar { justify-content: flex-end; flex-wrap: wrap; }
.view-tabs-wrap.has-toolbar > .view-toolbar .filter-bar { flex: 0 1 auto; flex-wrap: wrap; justify-content: flex-end; }
/* On a computer: tabs, ··· and + Add on the first row; search and the filter
   buttons on the second, from the left. One row overflowed beside the menu
   column and wrapped three ways. The tabs never move. Patch 575. */
@media (min-width: 761px) {
  .view-tabs-wrap.has-toolbar { grid-template-columns: minmax(0, 1fr) auto auto; column-gap: 8px; row-gap: 12px; }
  .view-tabs-wrap.has-toolbar > .view-tabs { grid-column: 1; grid-row: 1; justify-self: start; }
  .view-tabs-wrap.has-toolbar > .view-toolbar { display: contents; }
  .view-tabs-wrap.has-toolbar > .view-toolbar > .filter-bar { grid-column: 1 / -1; grid-row: 2; justify-content: flex-start; flex-wrap: wrap; }
  .view-tabs-wrap.has-toolbar > .view-toolbar > .view-more { grid-column: 2; grid-row: 1; }
  .view-tabs-wrap.has-toolbar > .view-toolbar > .view-add { grid-column: 3; grid-row: 1; }
}
.view-more { position: relative; flex: none; }
.view-more > summary { list-style: none; display: inline-grid; place-items: center; width: 38px; height: 38px; border: 1px solid var(--border); border-radius: 8px; background: var(--card); color: var(--foreground); cursor: pointer; }
.view-more > summary::-webkit-details-marker { display: none; }
.view-more[open] > summary { border-color: var(--primary); color: var(--primary); }
.view-more-menu { position: absolute; right: 0; top: calc(100% + 8px); z-index: 45; display: grid; gap: 4px; min-width: 230px; border: 1px solid var(--border); border-radius: 12px; background: var(--card); box-shadow: 0 16px 40px rgba(19, 34, 38, .16); padding: 8px; }
.view-more-color { display: block; }
.view-more-menu .color-by { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 4px 8px; }
.view-more-item { display: block; border-radius: 7px; padding: 9px 8px; color: var(--foreground); font-size: 13px; font-weight: 500; cursor: pointer; text-decoration: none; }
.view-more-item:hover { background: var(--secondary); }
.view-add { position: relative; flex: none; }
.view-add-button { display: inline-flex; align-items: center; gap: 6px; min-height: 38px; margin: 0; border: 1px solid var(--primary); border-radius: 8px; background: var(--primary); color: var(--primary-foreground, #fff); padding: 0 14px; font-size: 13px; font-weight: 600; }
.view-add.is-open .view-add-button { filter: brightness(.92); }
.view-add-pop { position: absolute; right: 0; top: calc(100% + 8px); z-index: 45; width: min(440px, calc(100vw - 32px)); }
.view-add-pop[hidden] { display: none; }
.view-add-pop .add-block { margin: 0 !important; box-shadow: 0 16px 40px rgba(19, 34, 38, .16); }
.view-add-pop .add-block-head, .view-add-pop .add-filter-proxy { display: none !important; }
.view-add-pop .add-block-body { display: grid !important; padding: 14px; }
.view-add-pop .add-form { display: grid; gap: 10px; }
.view-add-pop .add-form[hidden] { display: none; }
.view-add-pop .add-field { flex: none; }
.view-add-pop .add-form > button { justify-self: stretch; min-height: 40px; }
@media (max-width: 760px) {
  /* minmax(0, 1fr), not 1fr: a plain 1fr grows to fit its widest child, so the
     Tasks table (720px) widened the whole page to 768px and the phone zoomed
     out - rail and all. Sarah, 2026-10-03: "note how the menu size reduces the
     rail menu. When you go to that view, on the mobile." MOBILE-001. */
  .view-tabs-wrap.has-toolbar { grid-template-columns: minmax(0, 1fr); gap: 10px; }
  /* On a phone: the tabs fill one row, and search, Filters, ··· and + share
     the next. UX-029, patch 570. */
  .view-tabs-wrap.has-toolbar > .view-tabs { display: flex; width: 100%; }
  .view-tabs-wrap.has-toolbar > .view-tabs label { flex: 1 1 0; min-width: 0; display: inline-flex; align-items: center; justify-content: center; gap: 2px; padding: 8px 4px; letter-spacing: .02em; }
  .view-tabs-wrap.has-toolbar > .view-toolbar { gap: 8px; }
  .view-tabs-wrap.has-toolbar > .view-toolbar .filter-bar { flex: 1 1 auto; min-width: 0; }
  .view-tabs-wrap.has-toolbar > .view-toolbar .filter-search { flex: 1 1 auto; min-width: 0; }
  .view-add-button { width: 42px; padding: 0; justify-content: center; }
  .view-add-button span { display: none; }
  .view-add-pop { position: fixed; left: 0; right: 0; top: auto; bottom: 0; z-index: 61; width: auto; max-height: 85vh; overflow-y: auto; }
  .view-add-pop .add-block { border-radius: 18px 18px 0 0; padding-bottom: env(safe-area-inset-bottom); }
  body.view-add-open::before { content: ""; position: fixed; inset: 0; z-index: 60; background: rgba(0, 0, 0, .3); }
}

/* One day, as a list grouped by project: the view a phone can read, and the one
   with room to group on a desktop. Sarah, 2026-09-29. MOBILE-001. */
.calendar-grid.is-day { display: block; border: 0; background: none; padding: 0 4px; }
.calendar-day-head-line { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 4px 6px 12px; }
.calendar-day-head-line strong { font-size: 15px; font-weight: 600; }
.calendar-day-head-line span { color: var(--muted-foreground); font-size: 12px; }
/* The + has no cell to hover in a day view, so it is simply there, and a
   little larger because it sits on a full-width header. CAL-002. */
.calendar-day-head-line .calendar-day-add { flex: 0 0 auto; opacity: 1; width: 22px; height: 22px; font-size: 15px; }
.calendar-day-events { display: grid; gap: 4px; margin-bottom: 14px; }
.calendar-grid.is-day .calendar-day-events.is-tags { gap: 6px; margin-bottom: 16px; }
.calendar-grid.is-day .calendar-event.is-tag { font-size: 12px; padding: 3px 11px; }
.calendar-day-group { margin-bottom: 18px; }
/* A label, not a section rule: a dot in the client's colour, the project, the
   count. Sarah, 2026-09-29, on the first version reading as dated. */
.calendar-day-group h3 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 8px;
  padding: 0 2px 0 4px;
  color: var(--muted-foreground);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.calendar-day-group h3 small { color: var(--muted-foreground); font-size: 11px; font-weight: 400; letter-spacing: 0; }
.calendar-day-dot { width: 8px; height: 8px; flex: 0 0 auto; border-radius: 50%; background: var(--client-color, var(--muted-foreground)); }
.calendar-day-dot.is-none { background: transparent; border: 1px solid var(--input); }
/* Two or three across on a desktop, one on a phone: the room the day view was
   asked for in the first place. */
.calendar-day-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 8px; }
.calendar-day-more { margin-top: 8px; border: 1px dashed var(--input); background: var(--card); color: var(--foreground); font-size: 12px; font-weight: 400; }
.calendar-day-more:hover { border-color: var(--primary); color: var(--primary); }
@media (max-width: 760px) {
  .calendar-day-cards { grid-template-columns: 1fr; }
}

/* Planning: three months under each other, the lists beside them. The button
   sits after the arrows; a computer only. Sarah, 2026-10-04. CAL-024. */
.calendar-planning-button {
  min-height: 30px;
  margin-left: 6px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--card);
  padding: 4px 12px;
  color: var(--foreground);
  font-size: 12.5px;
  font-weight: 500;
}
.calendar-planning-button:hover { border-color: var(--primary); color: var(--primary); background: var(--card); }
.calendar-planning-button.active { border-color: var(--primary); background: var(--primary); color: var(--primary-foreground); }
@media (max-width: 900px) {
  .calendar-planning-button { display: none; }
}
/* overflow: visible, or the calendar box scrolls on its own. In 451 it did,
   and the month name, made to stay in view, sat over the first week. Sarah,
   2026-10-04: "the October 2026 band is hovering over the top of the
   calendar, cutting off the dates." The name now scrolls with its month. */
.calendar-grid.is-planning { display: block; overflow: visible; max-height: none; border: 0; background: transparent; }
/* Each month's name on a band in the accent color, set in from the sides so
   its rounded corners do not meet the edge of the calendar. Sarah,
   2026-10-04: "more of a visual distinction between the calendars", "a
   little bit of space between the first letter of the month and the ...
   margin", then "if you're going to have the edges rounded like that, you
   should keep them away from the margins." */
.planning-month + .planning-month { margin-top: 24px; }
.planning-month-name {
  margin: 8px 10px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--primary) 12%, var(--card));
  padding: 9px 14px;
  color: color-mix(in srgb, var(--primary) 85%, #000);
  font-size: 15px;
  font-weight: 600;
}
/* One line a card, as in the preview, so three months stay readable; the
   rest is a click or a hover away. A long name is cut to fit its day. */
.planning-month .calendar-day,
.planning-month .calendar-day-body,
.planning-month .calendar-task,
.planning-month .calendar-task a { min-width: 0; max-width: 100%; }
.planning-month .calendar-task { overflow: hidden; padding: 2px 6px; gap: 0; }
.planning-month .calendar-task > :not(a) { display: none; }
.planning-month .calendar-task a strong { display: block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 12px; font-weight: 500; }
.planning-month .calendar-day-more { margin-top: 2px; border: 0; background: transparent; padding: 1px 4px; min-height: 0; color: var(--muted-foreground); font-size: 11.5px; text-align: left; }
.planning-month .calendar-day-more:hover { color: var(--primary); background: transparent; }
/* The calendar takes the room the menu beside the rail was using. Everything
   else stays - Add, Filters and the view tabs: "I'd want to be able to filter
   by a client while doing this", and "I don't know why we would lose a lot of
   things". */
@media (min-width: 761px) {
  body.is-planning:not(.limited-shell) .app-body { grid-template-columns: 58px minmax(0, 1fr); }
  body.is-planning .sidebar { display: none; }
}

/* A task's details on a resting pointer, and at the top of a phone's task
   menu. assets/js/task-peek.js. CAL-024. */
.task-peek {
  position: fixed;
  z-index: 90;
  width: 300px;
  max-width: calc(100vw - 16px);
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--card);
  box-shadow: 0 14px 36px rgba(24, 24, 27, .16);
  padding: 12px 14px;
  color: var(--foreground);
  font-size: 12.5px;
  line-height: 1.45;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity .12s;
}
.task-peek.is-open { opacity: 1; visibility: visible; }
.task-peek.is-in-menu { position: static; width: auto; max-width: none; border: 0; box-shadow: none; padding: 6px 10px 8px; opacity: 1; visibility: visible; }
.task-peek-title { margin: 0 0 6px; font-size: 14px; font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.task-peek-rows { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 2px 10px; margin: 0 0 8px; }
.task-peek-rows dt { color: var(--muted-foreground); }
.task-peek-rows dd { margin: 0; overflow-wrap: anywhere; }
.task-peek-picture { display: block; width: 100%; max-height: 160px; margin: 0 0 8px; border-radius: 6px; object-fit: cover; background: var(--secondary); }
.task-peek-text { margin: 0; border-top: 1px solid var(--border); padding-top: 8px; white-space: pre-line; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 7; -webkit-box-orient: vertical; overflow: hidden; }
.task-peek-text.is-empty { color: var(--muted-foreground); }

/* On a phone, the block above the calendar folds behind one bar.
   assets/js/phone-fold.js. MOBILE-001. */
[data-phone-fold-bar] { display: none; }
@media (max-width: 760px) {
  [data-phone-fold-bar] { display: block; }
  .phone-fold-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    min-height: 44px;
    margin: 0 0 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--card);
    padding: 0 14px;
    color: var(--foreground);
    font-size: 14px;
    font-weight: 500;
    text-align: left;
  }
  .phone-fold-bar small { color: var(--muted-foreground); font-size: 12.5px; font-weight: 400; }
  .phone-fold-bar svg { flex: none; transition: transform .15s; }
  .phone-fold-bar[aria-expanded="true"] svg { transform: rotate(180deg); }
  body.phone-fold-closed [data-phone-fold] { display: none !important; }
  /* Color, moved inside Filters. */
  .color-by.is-in-filters { display: flex; align-items: center; gap: 10px; margin-top: 12px; border-top: 1px solid var(--border); padding-top: 12px; }
}
/* The date bar on one line on a phone: the date, then Today and the arrows.
   It was two rows. Part of the Folded preview Sarah chose. MOBILE-001. */
@media (max-width: 760px) {
  .calendar-shell .calendar-toolbar { display: flex; flex-direction: row; align-items: center; justify-content: space-between; gap: 8px; }
  .calendar-shell .calendar-toolbar > div:first-child p { margin: 0; color: var(--foreground); font-size: 13.5px; font-weight: 600; }
  .calendar-shell .calendar-toolbar .calendar-actions { display: flex; align-items: center; gap: 6px; margin: 0; }
}

/* The task title, renamed by tapping it. TASK-018. */
.record-head h1.is-renamable { cursor: text; }
.record-head h1.is-renamable:hover { text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--foreground) 25%, transparent); text-underline-offset: 6px; }
.record-title-input {
  width: 100%;
  min-height: 0;
  margin: 0;
  border: 0;
  border-bottom: 2px solid var(--primary);
  border-radius: 0;
  background: transparent;
  padding: 0 0 2px;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
}
.record-title-input:focus { outline: none; box-shadow: none; }

/* ---- People, places and projects on a client's photos. BRAND-007. ---- */
.asset-mode { display: flex; margin: 0 0 14px; }
.segmented a { display: inline-flex; align-items: center; min-height: 28px; border-radius: 5px; padding: 5px 12px; color: var(--muted-foreground); font-size: 12.5px; font-weight: 500; text-decoration: none; }
.segmented a.active { color: var(--foreground); background: var(--card); box-shadow: 0 1px 2px rgba(19, 34, 38, .06); }

.pl { display: grid; grid-template-columns: minmax(280px, 360px) minmax(0, 1fr); gap: 16px; align-items: start; }
@media (max-width: 900px) { .pl { grid-template-columns: 1fr; } .pl-tray { position: static; max-height: none; } }
.pl-tray { position: sticky; top: 64px; display: grid; gap: 10px; max-height: calc(100vh - 80px); overflow-y: auto; }
.pl-tray-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.pl-tray-head strong { font-size: 15px; font-weight: 600; }
.pl-tray-head span { color: var(--muted-foreground); font-size: 12.5px; }
.pl-search { width: 100%; }
.pl-thumbs { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 8px; }
.pl-thumbs[hidden] { display: none; }
.pl-thumb { position: relative; aspect-ratio: 4 / 3; border-radius: 8px; overflow: hidden; background: var(--secondary); cursor: grab; outline: 2px solid transparent; outline-offset: 1px; }
.pl-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.pl-thumb.is-selected { outline-color: var(--primary); }
.pl-thumb.is-selected::after { content: "✓"; position: absolute; top: 5px; left: 5px; width: 18px; height: 18px; border-radius: 5px; background: var(--primary); color: var(--primary-foreground); font-size: 11px; display: grid; place-items: center; }
.pl-none { grid-column: 1 / -1; margin: 6px 0; }
.pl-tray-actions { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.pl-side { display: grid; gap: 12px; min-width: 0; }
.pl-kinds { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; }
.pl-edit { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px; align-items: end; }
.pl-edit[hidden] { display: none; }
.pl-edit label[hidden] { display: none; }
.pl-edit-actions { display: flex; gap: 8px; grid-column: 1 / -1; }
.pl-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px; }
.pl-card { display: grid; gap: 8px; padding: 12px; cursor: pointer; transition: border-color .12s, background .12s; }
.pl-card.is-over { border-color: var(--primary); background: color-mix(in srgb, var(--accent) 45%, var(--card)); }
.pl-card.is-open { grid-column: 1 / -1; }
.pl-card-top { display: flex; align-items: center; gap: 10px; min-width: 0; }
.pl-face { flex: none; width: 40px; height: 40px; border-radius: 999px; background-color: var(--secondary); display: grid; place-items: center; color: var(--muted-foreground); font-size: 13px; font-weight: 600; background-repeat: no-repeat; }
.pl-face.is-square { border-radius: 8px; }
.pl-card-words { flex: 1; min-width: 0; }
.pl-card-words strong { display: block; font-size: 14px; font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; }
.pl-card-words small { display: block; color: var(--muted-foreground); font-size: 12px; }
.pl-card-edit { flex: none; }
.pl-stack { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; min-height: 44px; }
.pl-stack-item { width: 58px; height: 44px; border-radius: 6px; overflow: hidden; background: var(--secondary); }
.pl-stack-item img { display: block; width: 100%; height: 100%; object-fit: cover; }
.pl-card.is-open .pl-stack-item { width: 120px; height: 90px; }
.pl-drop { font-size: 12.5px; }

.asset-picker { position: fixed; z-index: 95; width: 260px; display: grid; gap: 4px; border: 1px solid var(--border); border-radius: 10px; background: var(--card); box-shadow: 0 14px 36px rgba(24, 24, 27, .18); padding: 8px; }
.asset-picker input { width: 100%; }
.asset-picker-list { display: grid; gap: 1px; max-height: 260px; overflow-y: auto; }
.asset-picker-list button { min-height: 0; border: 0; border-radius: 6px; background: transparent; padding: 7px 9px; color: var(--foreground); font-size: 13px; font-weight: 400; text-align: left; white-space: normal; }
.asset-picker-list button:hover, .asset-picker-list button:focus-visible { background: var(--secondary); }
.asset-picker-list button.is-add { color: var(--primary); font-weight: 500; }
.asset-toast { position: fixed; left: 50%; bottom: 24px; z-index: 96; transform: translateX(-50%); border-radius: 999px; background: #18181b; color: #fff; padding: 8px 16px; font-size: 13px; opacity: 0; pointer-events: none; transition: opacity .2s; }
.asset-toast.is-on { opacity: 1; }

.asset-tags { display: flex; flex-wrap: wrap; gap: 4px; padding: 4px 2px 0; }
.asset-chip { display: inline-flex; align-items: center; gap: 4px; border-radius: 999px; background: var(--secondary); padding: 2px 9px; font-size: 12px; font-weight: 500; }
.asset-chip.is-person { background: color-mix(in srgb, #f0a83c 20%, var(--card)); }
.asset-chip.is-place { background: color-mix(in srgb, #2f6fd0 14%, var(--card)); }
.asset-chip.is-project { background: color-mix(in srgb, #8a3fb5 14%, var(--card)); }
.asset-chip button { min-height: 0; border: 0; background: transparent; padding: 0 0 0 2px; color: var(--muted-foreground); font-size: 14px; line-height: 1; }
.asset-cell.is-excluded { opacity: .45; }

.photo-layout { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 16px; align-items: start; }
@media (max-width: 900px) { .photo-layout { grid-template-columns: 1fr; } }
.photo-stage { padding: 12px; }
.photo-frame { position: relative; cursor: crosshair; border-radius: 8px; overflow: hidden; background: var(--secondary); line-height: 0; }
.photo-frame img { display: block; width: 100%; height: auto; user-select: none; }
.photo-ring { position: absolute; width: 11%; aspect-ratio: 1; transform: translate(-50%, -50%); border: 3px solid #f0a83c; border-radius: 999px; box-shadow: 0 0 0 2px rgba(0, 0, 0, .3); cursor: pointer; line-height: 1.4; }
.photo-ring span { position: absolute; left: 50%; top: 100%; transform: translate(-50%, 6px); white-space: nowrap; border-radius: 999px; background: rgba(17, 17, 19, .82); color: #fff; padding: 2px 8px; font-size: 12px; font-weight: 500; pointer-events: none; }
.photo-hint { margin: 8px 2px 0; font-size: 12.5px; }
.photo-facts { display: grid; gap: 16px; }
.photo-facts h2 { margin: 0 0 6px; color: var(--muted-foreground); font-size: 12px; font-weight: 500; }
.photo-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 4px; }
.photo-title { overflow-wrap: anywhere; }
.photo-exclude { border-top: 1px solid var(--border); padding-top: 12px; }

/* Asking the client who is in their photos, and what came back. BRAND-007. */
.pl-flag { justify-self: start; border-radius: 999px; background: color-mix(in srgb, #c2410c 10%, var(--card)); padding: 2px 9px; color: #c2410c; font-size: 11.5px; font-weight: 500; }
.pl-ask { display: grid; gap: 12px; }
.pl-ask[hidden] { display: none; }
.pl-ask fieldset { display: grid; gap: 6px; margin: 0; border: 0; padding: 0; }
.pl-ask legend { margin-bottom: 4px; color: var(--muted-foreground); font-size: 12.5px; font-weight: 500; }
.pl-ask-people { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 4px 12px; max-height: 220px; overflow-y: auto; }
.pl-answers { display: grid; gap: 10px; border-color: color-mix(in srgb, #f0a83c 55%, var(--border)); background: color-mix(in srgb, #f0a83c 7%, var(--card)); }
.pl-answers[hidden] { display: none; }
.pl-answers-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.pl-answers-head .secondary-button { margin-left: auto; }
.pl-answers-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 8px; }
.pl-answer { display: flex; align-items: center; gap: 9px; min-width: 0; border: 1px solid var(--border); border-radius: 10px; background: var(--card); padding: 8px 10px; }
.pl-answer .pl-card-words { color: inherit; text-decoration: none; }
.pl-answer button { flex: none; min-height: 30px; padding: 4px 10px; font-size: 12.5px; }
.pl-answer-note { margin: 0; color: var(--muted-foreground); font-size: 13px; }

.whos-who-card { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; border-color: color-mix(in srgb, #f0a83c 55%, var(--border)); }
.whos-who-card strong { display: block; font-size: 15px; font-weight: 600; }
.whos-who { display: grid; gap: 14px; }
.whos-who-names { display: grid; gap: 8px; }
.whos-who-message { margin: 0 0 4px; max-width: 70ch; }
.whos-who-label { color: var(--muted-foreground); font-size: 12.5px; font-weight: 500; }
.whos-who-chips, .whos-who-results { display: flex; flex-wrap: wrap; gap: 6px; }
.whos-who-chip { min-height: 34px; border: 1px solid var(--border); border-radius: 999px; background: var(--card); padding: 5px 14px; color: var(--foreground); font-size: 13.5px; font-weight: 500; }
.whos-who-chip.is-on { border-color: #f0a83c; background: #f0a83c; color: #1a1205; }
.whos-who-chip.is-done::after { content: " ✓"; }
.whos-who-chip.is-typed { color: var(--primary); }
.whos-who-someone { display: grid; gap: 6px; max-width: 420px; }
.whos-who-how { margin: 4px 0 0; font-size: 13px; }
.whos-who-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; }
.whos-who-photo { position: relative; margin: 0; border-radius: 10px; overflow: hidden; background: var(--secondary); cursor: pointer; line-height: 0; }
.whos-who-photo img { display: block; width: 100%; height: auto; }
.whos-who-ring { position: absolute; width: 12%; aspect-ratio: 1; transform: translate(-50%, -50%); border: 3px solid #f0a83c; border-radius: 999px; box-shadow: 0 0 0 2px rgba(0, 0, 0, .3); line-height: 1.4; cursor: pointer; }
.whos-who-ring span { position: absolute; left: 50%; top: 100%; transform: translate(-50%, 4px); white-space: nowrap; border-radius: 999px; background: rgba(17, 17, 19, .82); color: #fff; padding: 1px 7px; font-size: 11.5px; font-weight: 500; pointer-events: none; }
.whos-who-photo .whos-who-ring { border-width: 2px; }
.whos-who-send { display: grid; gap: 10px; }
.whos-who-send button { justify-self: start; }
.whos-who-viewer { width: min(1100px, 96vw); max-height: 94vh; border: 0; border-radius: 12px; padding: 12px; background: var(--card); color: var(--foreground); }
.whos-who-viewer::backdrop { background: rgba(0, 0, 0, .6); }
.whos-who-viewer-bar { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; font-weight: 600; }
.whos-who-stage { position: relative; display: block; width: fit-content; max-width: 100%; margin: 0 auto; line-height: 0; cursor: crosshair; }
/* Sized from the window, since a percentage inside a box that sizes to its
   picture collapses to nothing. */
.whos-who-stage img { display: block; width: auto; max-width: calc(min(1100px, 96vw) - 24px); max-height: 78vh; height: auto; }

/* Teams at a client: the filter on People, the ticks on a person, and
   "Everyone at" in the Ask form. BRAND-007. */
.pl-team-filter, .pl-ask-teams { display: flex; flex-wrap: wrap; gap: 6px; }
.pl-team-filter[hidden] { display: none; }
.pl-ask-teams { grid-column: 1 / -1; margin-bottom: 6px; }
.pl-team-chip { min-height: 30px; border: 1px solid var(--border); border-radius: 999px; background: var(--card); padding: 4px 12px; color: var(--foreground); font-size: 12.5px; font-weight: 500; }
.pl-team-chip.is-on { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); background: var(--accent); color: var(--primary); }
.pl-edit-teams { grid-column: 1 / -1; margin: 0; border: 0; padding: 0; }
.pl-edit-teams[hidden] { display: none; }
.pl-edit-teams legend { margin-bottom: 4px; color: var(--muted-foreground); font-size: 12.5px; font-weight: 500; }
.pl-edit-team-list { display: flex; flex-wrap: wrap; gap: 4px 16px; }
.asset-chip.is-team { background: color-mix(in srgb, #1f8a70 14%, var(--card)); }
/* A person's birthday and start date in Edit. BRAND-005. */
.pl-edit-dates { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px; grid-column: 1 / -1; }
.pl-edit-dates[hidden] { display: none; }
.pl-edit-birthday { display: flex; gap: 6px; }
.pl-edit-birthday select { flex: 1; }
.pl-edit-birthday input { width: 80px; }

/* The client's own Photos tab. BRAND-007. */
.cp { display: grid; gap: 14px; }
.cp-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.cp-bar [hidden] { display: none; }
.cp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 10px; }
.cp-grid[hidden], .cp-people[hidden] { display: none; }
.cp-tile { position: relative; display: block; aspect-ratio: 4 / 3; min-height: 0; margin: 0; border: 0; border-radius: 10px; overflow: hidden; background: var(--secondary); padding: 0; cursor: pointer; }
.cp-tile img { display: block; width: 100%; height: 100%; object-fit: cover; }
.cp-count { position: absolute; left: 6px; bottom: 6px; border-radius: 999px; background: rgba(17, 17, 19, .75); color: #fff; padding: 2px 8px; font-size: 11.5px; font-weight: 500; }
.cp-viewer { width: min(1180px, 96vw); max-height: 94vh; border: 0; border-radius: 12px; padding: 12px; background: var(--card); color: var(--foreground); }
.cp-viewer::backdrop { background: rgba(0, 0, 0, .6); }
.cp-viewer-bar { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.cp-viewer-body { display: grid; grid-template-columns: minmax(0, 1fr) 240px; gap: 14px; align-items: start; }
@media (max-width: 760px) { .cp-viewer-body { grid-template-columns: 1fr; } }
.cp-stage { position: relative; width: fit-content; max-width: 100%; margin: 0 auto; line-height: 0; cursor: crosshair; }
.cp-stage img { display: block; width: auto; max-width: calc(min(1180px, 96vw) - 290px); max-height: 76vh; height: auto; }
@media (max-width: 760px) { .cp-stage img { max-width: calc(96vw - 24px); max-height: 60vh; } }
.cp-ring { position: absolute; width: 11%; aspect-ratio: 1; transform: translate(-50%, -50%); border: 3px solid #f0a83c; border-radius: 999px; box-shadow: 0 0 0 2px rgba(0, 0, 0, .3); line-height: 1.4; }
.cp-ring.is-waiting { border-style: dashed; border-color: #fff; cursor: pointer; }
.cp-ring span { position: absolute; left: 50%; top: 100%; transform: translate(-50%, 6px); white-space: nowrap; border-radius: 999px; background: rgba(17, 17, 19, .82); color: #fff; padding: 2px 8px; font-size: 12px; font-weight: 500; pointer-events: none; }
.cp-facts { display: grid; gap: 14px; }
.cp-facts h3 { margin: 0 0 6px; color: var(--muted-foreground); font-size: 12px; font-weight: 500; }
.cp-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 4px; }
.cp-people { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 10px; }
.cp-person { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; padding: 12px; }
.cp-person strong { display: block; font-size: 14px; font-weight: 600; }
.cp-person small { display: block; color: var(--muted-foreground); font-size: 12px; margin-bottom: 4px; }
.cp-form { display: grid; gap: 10px; grid-column: 1 / -1; }
.cp-form fieldset { margin: 0; border: 0; padding: 0; }
.cp-form fieldset[hidden] { display: none; }
.cp-form legend { margin-bottom: 4px; color: var(--muted-foreground); font-size: 12.5px; font-weight: 500; }
.cp-form-teams { display: flex; flex-wrap: wrap; gap: 4px 16px; }

/* Someone no longer with the client: kept, greyed, with the date. Patch 468. */
.pl-card.is-left { opacity: .72; }
.pl-left { justify-self: start; border-radius: 999px; background: var(--secondary); padding: 2px 9px; color: var(--muted-foreground); font-size: 11.5px; font-weight: 500; }
.pl-edit-left { display: flex; flex-wrap: wrap; align-items: end; gap: 10px 16px; grid-column: 1 / -1; }
.pl-edit-left[hidden] { display: none; }
.pl-filter-gap { width: 10px; }
.pl[hidden] { display: none; }
.photo-ring.is-waiting { border-style: dashed; border-color: #fff; }
/* Not tagged yet, Tagged, All photos. Patch 469. */
.pl-tray-head { flex-wrap: wrap; align-items: center; }
.pl-tray-view button { padding: 4px 9px; font-size: 12px; }
/* Add from Google Photos. ASSET-001. */
.asset-google { margin: 10px 0 0; }
.google-photos { display: grid; gap: 14px; }
.google-photos [hidden] { display: none; }
.google-photos-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.google-photos-bar [data-gp-bring] { margin-left: auto; }
.google-photos-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; }
.google-photo { position: relative; display: grid; gap: 4px; padding: 6px; border: 1px solid var(--border); border-radius: 8px; background: var(--card); cursor: pointer; }
.google-photo input { position: absolute; top: 10px; left: 10px; width: 18px; height: 18px; }
.google-photo img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 5px; background: var(--secondary); }
.google-photo-name { font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.google-photo-note { font-size: 11px; color: var(--muted-foreground); }
.google-photo.is-video { opacity: .55; cursor: default; }
@media (max-width: 600px) {
  .google-photos-grid { grid-template-columns: repeat(2, 1fr); }
  .google-photos-bar [data-gp-bring] { margin-left: 0; width: 100%; }
}
/* A card's picture from the computer, on Edit. Patch 471. */
.pl-edit-photo { grid-column: 1 / -1; display: grid; gap: 8px; border: 1px dashed var(--border); border-radius: 8px; padding: 10px; }
.pl-edit-photo[hidden], .pl-edit-photo [hidden] { display: none; }
.pl-edit-photo.is-over { border-color: var(--primary); background: color-mix(in srgb, var(--accent) 45%, var(--card)); }
.pl-edit-photo-label { font-size: 13px; font-weight: 500; }
.pl-edit-photo-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.pl-edit-photo-row [data-pl-photo-name] { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 260px; }
.pl-edit-photo-stage { display: grid; gap: 4px; justify-items: start; }
.pl-edit-photo-frame { position: relative; display: inline-block; line-height: 0; cursor: crosshair; border-radius: 6px; overflow: hidden; background: var(--secondary); }
.pl-edit-photo-frame img { display: block; max-width: 100%; max-height: 280px; width: auto; height: auto; user-select: none; }
.pl-edit-photo-frame .photo-ring { width: 18%; pointer-events: none; }
/* Photos that look the same. Patch 474. */
.google-photo.has-match { grid-column: span 2; grid-template-columns: 1fr 1fr; column-gap: 8px; }
.google-photo.has-match > img { grid-row: 1; }
.google-photo.has-match .google-photo-name { grid-row: 2; }
.google-photo.has-match .google-photo-note { grid-column: 1 / -1; }
.google-photo-twin { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 5px; background: var(--secondary); }
.asset-lookalikes { display: grid; gap: 12px; margin: 12px 0; }
.asset-lookalikes h3 { margin: 0; font-size: 15px; font-weight: 600; }
.dupe-pair { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; padding-top: 12px; border-top: 1px solid var(--border); }
.dupe-pair figure { margin: 0; display: grid; gap: 4px; width: 160px; }
.dupe-pair img { width: 160px; height: 160px; object-fit: cover; border-radius: 6px; background: var(--secondary); }
.dupe-pair figcaption { font-size: 12px; color: var(--muted-foreground); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dupe-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.dupes { display: grid; gap: 14px; }
.dupes-groups { display: grid; gap: 14px; }
.dupes-group { display: grid; gap: 12px; }
.dupes-row { display: flex; flex-wrap: wrap; gap: 12px; }
.dupes-photo { position: relative; display: grid; gap: 6px; width: 200px; padding: 8px; border: 2px solid var(--border); border-radius: 8px; cursor: pointer; }
.dupes-photo.is-kept { border-color: var(--primary); }
.dupes-photo input { position: absolute; top: 14px; left: 14px; width: 18px; height: 18px; }
.dupes-photo img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 5px; background: var(--secondary); display: block; }
.dupes-words { display: grid; gap: 2px; min-width: 0; }
.dupes-words strong { font-size: 13px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dupes-words small { color: var(--muted-foreground); font-size: 12px; }
.dupes-flag { font-size: 12px; font-weight: 600; }
.dupes-photo.is-kept .dupes-flag { color: var(--primary); }
@media (max-width: 600px) {
  .dupes-photo { width: calc(50% - 6px); }
  .dupe-pair figure, .dupe-pair img { width: calc(50vw - 40px); }
  .dupe-pair img { height: calc(50vw - 40px); }
}
/* Albums and Events. Patch 476. */
.pl-edit-album { grid-column: 1 / -1; display: grid; gap: 10px; }
.pl-edit-album[hidden], .pl-edit-album [hidden] { display: none; }
.pl-edit-event-dates { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; }
.pl-edit-album textarea { width: 100%; resize: vertical; }
.pl-edit-tags { display: grid; gap: 6px; }
.pl-tag-chips, .pl-tag-results { display: flex; flex-wrap: wrap; gap: 6px; }
.pl-tag-results button { cursor: pointer; border: 1px dashed var(--border); }
.asset-chip.is-event { background: color-mix(in srgb, #d0412f 14%, var(--card)); }
.asset-chip.is-album { background: color-mix(in srgb, #6b7a8f 18%, var(--card)); }
.google-photos-album { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; }
.google-photos-bar [data-gp-album-name] { min-width: 180px; }
/* Delete stays hidden on a new card and on the client's side; a button's own
   display rule was beating the hidden attribute. Patch 476. */
.pl-edit-actions [hidden] { display: none; }
/* Formatted descriptions and review instructions, and the toolbar that
   writes them. Patch 478. */
.formatted-text { display: grid; gap: 8px; line-height: 1.55; }
.formatted-text p, .formatted-text ul, .formatted-text ol, .formatted-text h4 { margin: 0; }
.formatted-text ul, .formatted-text ol { padding-left: 1.3em; display: grid; gap: 3px; }
.formatted-text h4 { font-size: 15px; font-weight: 600; margin-top: 4px; }
.formatted-text h4.fmt-h1 { font-size: 16px; }
.formatted-text strong { font-weight: 600; }
.format-toolbar { display: flex; flex-wrap: wrap; gap: 4px; }
.field-block.is-collapsed .format-toolbar { display: none; }
.format-toolbar button { min-height: 0; padding: 3px 9px; font-size: 12px; border: 1px solid var(--border); border-radius: 6px; background: var(--card); color: var(--foreground); }
.format-toolbar button:hover { border-color: var(--primary); }
.format-toolbar button:first-child { font-weight: 600; }
.format-toolbar button:nth-child(2) { font-style: italic; }
/* Albums with the photos, and a wider photo column. Sarah, 2026-10-05: "1,
   albums on the left", and the column "being wider". Patch 479. */
.pl { grid-template-columns: minmax(320px, 40%) minmax(0, 1fr); }
@media (max-width: 900px) { .pl { grid-template-columns: 1fr; } }
.pl-tray-actions { flex-wrap: wrap; justify-content: flex-start; }
.pl-albums { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.pl-album { min-height: 0; padding: 4px 10px; border: 1px solid var(--border); border-radius: 999px; background: var(--card); color: var(--foreground); font-size: 12.5px; }
.pl-album.active { border-color: var(--primary); background: color-mix(in srgb, var(--primary) 14%, var(--card)); }
.pl-album.is-over { border-color: var(--primary); background: color-mix(in srgb, var(--accent) 45%, var(--card)); }
.pl-album.is-waiting { border-style: dashed; }
/* The photo column's width and the photo size, set by hand. Patch 480. */
.pl { grid-template-columns: var(--pl-left, minmax(320px, 40%)) 12px minmax(0, 1fr); column-gap: 4px; }
.pl-thumbs { grid-template-columns: repeat(auto-fill, minmax(var(--pl-thumb, 92px), 1fr)); }
.pl-resizer { align-self: stretch; min-height: 120px; cursor: col-resize; border-radius: 6px; position: relative; touch-action: none; }
.pl-resizer::after { content: ''; position: absolute; top: 0; bottom: 0; left: 50%; width: 2px; transform: translateX(-50%); border-radius: 2px; background: var(--border); }
.pl-resizer:hover::after, .pl-resizer:focus-visible::after, .pl-resizer.is-dragging::after { background: var(--primary); width: 3px; }
.pl-size { width: 110px; accent-color: var(--primary); }
@media (max-width: 900px) {
  .pl { grid-template-columns: 1fr; }
  .pl-resizer { display: none; }
}
/* The photo you last opened, outlined when you come back. Patch 483. */
.pl-thumb.is-recent { outline: 3px solid #f0a83c; outline-offset: 1px; }
.pl-team-chip.is-over { border-color: var(--primary); background: color-mix(in srgb, var(--accent) 45%, var(--card)); }
/* What a drag of several photos carries. Patch 484. */
.pl-drag-ghost { position: fixed; top: -200px; left: -200px; width: 96px; height: 72px; border-radius: 8px; background: var(--card); box-shadow: 4px 4px 0 0 var(--border), 8px 8px 0 0 color-mix(in srgb, var(--border) 60%, transparent); }
.pl-drag-ghost img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; display: block; }
.pl-drag-ghost span { position: absolute; right: -6px; bottom: -8px; padding: 2px 8px; border-radius: 999px; background: var(--primary); color: var(--primary-foreground); font-size: 12px; font-weight: 600; white-space: nowrap; }
/* Add a zip. Patch 485. */
.zip-album { display: grid; gap: 10px; margin: 10px 0; padding: 14px 16px; }
.zip-album-name { display: grid; gap: 4px; font-size: 13px; max-width: 420px; }
.zip-album-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.zip-album-progress { margin: 0; font-size: 14px; }
.pl-albums .zip-album, .pl-tray .zip-album { margin: 0; }
/* View as. Patch 488. */
.view-as-bar { position: sticky; top: 0; z-index: 60; display: flex; align-items: center; justify-content: center; gap: 14px; margin: 0; padding: 7px 14px; background: #f0a83c; color: #1d1b16; font-size: 13.5px; }
.view-as-bar button { min-height: 0; padding: 4px 12px; border: 1px solid #1d1b16; border-radius: 6px; background: transparent; color: #1d1b16; font-size: 13px; font-weight: 600; }
.view-as-bar button:hover { background: rgba(255, 255, 255, .35); }
/* A description in the calendar panel, formatted and compact. Patch 490. */
.ctx-read-detail .formatted-text { gap: 6px; font-size: 12.5px; line-height: 1.45; white-space: normal; }
.ctx-read-detail .formatted-text h4 { font-size: 13px; margin-top: 2px; }
.ctx-read-detail .formatted-text ul, .ctx-read-detail .formatted-text ol { padding-left: 1.1em; gap: 2px; }
/* Yours, and with the client, on every calendar. Patch 490. */
.calendar-task.is-mine { background: color-mix(in srgb, var(--primary) 12%, var(--card)); }
.calendar-task.is-mine strong { font-weight: 600; }
.calendar-task-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 3px; }
.calendar-tag { display: inline-block; padding: 0 6px; border-radius: 999px; font-size: 10.5px; font-weight: 600; line-height: 1.6; white-space: nowrap; }
.calendar-tag.is-you { background: var(--primary); color: var(--primary-foreground); }
.calendar-tag.is-client { background: color-mix(in srgb, #f0a83c 28%, var(--card)); color: var(--foreground); }
/* Whoever holds a task, as a dot with their initials. Patch 492. */
.calendar-owner { display: inline-grid; place-items: center; width: 18px; height: 18px; border-radius: 50%; background: var(--secondary); border: 1px solid var(--border); color: var(--foreground); font-size: 8.5px; font-weight: 600; letter-spacing: -.02em; }

/* Copying a task photo into the client photo library. ASSET-005. */
.file-table-library { display: inline-block; margin-right: 10px; }
.task-library-all { margin: 0 0 10px; }

/* Add from the photo library, on a task: the picker and the chips waiting in a
   comment box. Shared by the team and partner task pages. ASSET-006. */
.library-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.library-chip { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; border: 1px solid var(--border); border-radius: 999px; padding: 3px 4px 3px 3px; max-width: 240px; }
.library-chip img { width: 22px; height: 22px; border-radius: 50%; object-fit: cover; }
.library-chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.library-chip button { border: 0; background: none; color: var(--muted-foreground); cursor: pointer; padding: 0 6px; font-size: 14px; }
.library-picker-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; overflow-y: auto; min-height: 0; flex: 1 1 auto; align-content: start; }
.library-picker-grid button { position: relative; padding: 0; border: 0; border-radius: 8px; overflow: hidden; aspect-ratio: 1; background: var(--muted, #f1f1f3); cursor: pointer; }
.library-picker-grid img { width: 100%; height: 100%; object-fit: cover; display: block; }
.library-picker-grid button.is-picked { outline: 3px solid var(--primary); outline-offset: -3px; }
.library-picker-grid button.is-picked::after { content: "\2713"; position: absolute; top: 6px; right: 6px; width: 20px; height: 20px; border-radius: 50%; background: var(--primary); color: #fff; font-size: 12px; display: grid; place-items: center; }
.task-library-add { display: inline-block; margin-right: 8px; }

/* The photo library as a side panel, so the work stays in view. Patch 510. */
.library-panel { position: fixed; top: 0; right: 0; bottom: 0; z-index: 60; width: 380px; max-width: 100vw; display: flex; flex-direction: column; gap: 8px; padding: 14px; background: var(--card); border-left: 1px solid var(--border); box-shadow: -8px 0 24px rgba(0,0,0,.08); }
.library-panel[hidden] { display: none; }
.library-panel-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.library-panel-head h2 { margin: 0; font-size: 15px; font-weight: 600; }
.library-panel-search { width: 100%; }
.library-panel-kinds, .library-panel-records { display: flex; flex-wrap: wrap; gap: 4px; }
.library-panel-records { max-height: 120px; overflow-y: auto; }
.library-kind, .library-record { font-size: 12px; padding: 3px 9px; border: 1px solid var(--border); border-radius: 999px; background: var(--card); color: var(--muted-foreground); cursor: pointer; }
.library-kind.is-on, .library-record.is-on { color: var(--primary); border-color: color-mix(in srgb, var(--primary) 40%, var(--border)); background: color-mix(in srgb, var(--primary) 10%, var(--card)); font-weight: 600; }
.library-panel-result { margin: 0; font-size: 12px; }
.library-who { position: absolute; left: 4px; right: 4px; bottom: 4px; font-style: normal; font-size: 10px; line-height: 1.4; color: #fff; background: rgba(0,0,0,.55); border-radius: 4px; padding: 1px 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: left; }
.library-panel-actions { display: flex; gap: 6px; flex: none; }
.library-panel-head { flex-wrap: wrap; padding-bottom: 8px; border-bottom: 1px solid var(--border); }
@media (min-width: 1100px) { body.has-library-panel { padding-right: 380px; } }

/* The work on a task, beside its description. UX-027, patch 511. */
.work-view { margin-top: 16px; }
.work-stage { border: 1px solid var(--border); border-radius: 10px; overflow: hidden; background: color-mix(in srgb, var(--border) 30%, var(--card)); display: grid; place-items: center; min-height: 220px; }
.work-stage img { display: block; max-width: 100%; max-height: 70vh; object-fit: contain; }
.work-stage iframe { width: 100%; height: 70vh; border: 0; background: #fff; }
.work-cap { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px; margin-top: 6px; font-size: 12px; color: var(--muted-foreground); }
.work-thumbs { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.work-thumb { width: 64px; height: 52px; padding: 0; border: 2px solid transparent; border-radius: 6px; overflow: hidden; background: color-mix(in srgb, var(--primary) 8%, var(--card)); cursor: pointer; display: grid; place-items: center; }
.work-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.work-thumb span { font-size: 11px; font-weight: 600; color: var(--primary); }
.work-thumb.is-on { border-color: var(--primary); }
.work-other { margin: 10px 0 0; font-size: 13px; color: var(--muted-foreground); }
/* A task's files by review round: For this review, then Earlier · N folded,
   on the Work area and the Files tab; and Replace with a new version.
   TASK-026, patch 523. */
.work-round, .file-round { margin: 0 0 8px; font-size: 13px; font-weight: 600; color: var(--muted-foreground); }
.work-earlier, .file-earlier { margin-top: 14px; }
.work-earlier > summary, .file-earlier > summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--muted-foreground); }
.file-earlier[open] > summary { margin-bottom: 8px; }
.replace-file { margin: 0; }
.replace-file-button { position: relative; cursor: pointer; }
.replace-file-button input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.work-view.is-bare { margin-top: 26px; }

/* The client review and client view library box, lost in patch 510 when the
   picker's own style of the same name was removed. Restored in patch 512. */
.library-picker { margin-bottom: 14px; border: 1px solid var(--border); border-radius: 8px; padding: 12px; }
.work-view-title { margin: 0 0 10px; font-size: 15px; font-weight: 600; }

/* Add file and Add from the photo library together. Patch 513. */
.attachment-actions { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px; }
.attachment-actions .task-library-add { margin: 0; }

/* Client review on one screen: the work on the left, the reply beside it.
   UX-027, patch 514. */
.review-one { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(300px, 1fr); gap: 24px; align-items: start; }
.review-one.is-read-only { grid-template-columns: minmax(0, 1fr); }
.review-reply-side { border-left: 1px solid var(--border); padding-left: 20px; }
.review-reply-side .review-region-title { margin-top: 0; }
.review-library-form { margin: 0; }
@media (max-width: 900px) {
  .review-one { grid-template-columns: 1fr; }
  .review-reply-side { border-left: 0; padding-left: 0; border-top: 1px solid var(--border); padding-top: 16px; }
}

/* Files and library photos with a client request. Patch 515. */
.request-attach-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.request-attach input[type="file"] { display: none; }
.request-attach { cursor: pointer; }

/* Comments: Edit and Delete on your own, deleted ones for the owner, and the
   @ list. TASK-001, patch 518. */
.comment-own { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-start; margin-top: 4px; }
.comment-own-edit[open] { flex-basis: 100%; }
.comment-own-form { display: grid; gap: 6px; margin-top: 6px; }
.comment-own-form button { justify-self: start; }
.thread-edited { color: var(--muted-foreground); }
.thread-deleted { margin-top: 12px; font-size: 13px; color: var(--muted-foreground); }
.thread-deleted summary { cursor: pointer; }
.thread-deleted-item { border-top: 1px solid var(--border); padding: 8px 0; }
.mention-list { list-style: none; margin: 4px 0 0; padding: 4px; border: 1px solid var(--border); border-radius: 8px; background: var(--card); box-shadow: 0 6px 18px rgba(0,0,0,.08); max-width: 280px; position: relative; z-index: 20; }
.mention-list[hidden] { display: none; }
.mention-list li { padding: 6px 10px; border-radius: 6px; font-size: 13px; cursor: pointer; }
.mention-list li.is-active, .mention-list li:hover { background: color-mix(in srgb, var(--primary) 12%, var(--card)); color: var(--primary); }

/* A card saving after a drag, and the line that says when one did not.
   DASH-002, patch 519. */
.is-saving { opacity: .55; animation: plan-saving 1s ease-in-out infinite alternate; }
@keyframes plan-saving { from { opacity: .55; } to { opacity: .85; } }
.plan-notice { position: fixed; left: 50%; bottom: 20px; transform: translate(-50%, 12px); z-index: 70; max-width: calc(100vw - 32px); padding: 10px 16px; border-radius: 10px; background: var(--foreground); color: var(--background); font-size: 14px; opacity: 0; pointer-events: none; transition: opacity .2s, transform .2s; }
.plan-notice.is-on { opacity: 1; transform: translate(-50%, 0); }

/* The client's Review tab: Waiting on you and In Progress easy to tell apart.
   CLIENT-015, patch 520. */
.review-group-head { display: flex; justify-content: space-between; margin: 10px 0 4px; padding: 8px 12px; border-radius: 8px; font-size: 14px; font-weight: 600; }
.review-group-head.is-waiting { background: #fff4e5; color: #8a4b00; }
.review-group-head.is-in-progress { background: color-mix(in srgb, var(--primary) 9%, var(--card)); color: var(--primary); }
.review-go { display: inline-block; padding: 4px 10px; border-radius: 7px; background: var(--primary); color: #fff; font-size: 12px; font-weight: 600; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .review-group-head.is-waiting { background: #3a2a12; color: #f3c98b; } }
:root[data-theme="dark"] .review-group-head.is-waiting { background: #3a2a12; color: #f3c98b; }

/* A client request's story. CLIENT-015, patch 520. */
.request-story { margin-top: 6px; font-size: 13px; }
.request-story summary { cursor: pointer; color: var(--primary); }
.request-story-steps { list-style: none; margin: 8px 0 4px; padding: 0 0 0 14px; border-left: 2px solid var(--border); }
.request-story-steps li { position: relative; padding: 0 0 10px 12px; }
.request-story-steps li::before { content: ""; position: absolute; left: -21px; top: 5px; width: 9px; height: 9px; border-radius: 50%; background: var(--card); border: 2px solid var(--primary); }
.request-story-steps li.is-now::before { background: var(--primary); }
.request-story-steps small { display: block; color: var(--muted-foreground); font-size: 12px; }
.request-story-steps q { display: block; margin-top: 3px; font-style: italic; quotes: none; }

/* System Emails: one table, a heading row for each group. MAIL-008, patch 524. */
.system-emails-group th { padding-top: 18px; font-size: 12px; font-weight: 600; color: var(--muted-foreground); text-align: left; background: transparent; }
.system-emails-table td .badge { margin-left: 6px; vertical-align: middle; }

/* The words before a change, under its line in a task's History. Patch 525. */
.record-history-before { margin-top: 4px; font-size: 13px; }
.record-history-before > summary { cursor: pointer; color: var(--muted-foreground); }
.record-history-before > div { margin-top: 6px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 7px; background: var(--secondary); overflow-wrap: anywhere; }

/* The System Emails editor: the form beside its preview. MAIL-008, patch 526. */
.system-email-title { margin: 4px 0 4px; font-size: 22px; font-weight: 600; }
.system-email-title .badge { vertical-align: middle; margin-left: 6px; }
.system-email-meta { margin: 0 0 16px; }
.system-email-card { padding: 16px 20px; margin-bottom: 18px; }
.system-email-card > h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; }
.system-email-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 24px; align-items: start; }
@media (max-width: 900px) { .system-email-split { grid-template-columns: 1fr; } }
.system-email-form textarea { min-height: 90px; }
.system-email-words { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 2px 0; font-size: 13px; }
.system-email-words .muted { margin-right: 4px; }
.system-email-words code { font-size: 12px; padding: 2px 6px; border-radius: 5px; background: var(--secondary); }
.system-email-lock { font-size: 12px; padding: 2px 8px; border: 1px solid var(--border); border-radius: 5px; }
.system-email-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.system-email-edited { margin: 4px 0 0; font-size: 12px; }
.system-email-preview { border: 1px solid var(--border); border-radius: 10px; padding: 14px; background: var(--secondary); }
.system-email-preview-label { margin: 0 0 6px; font-size: 12px; }
.system-email-preview-subject { margin: 0 0 10px; font-weight: 600; font-size: 14px; }
.system-email-paper { background: #ffffff; color: #444c55; border: 1px solid #e2e6ea; border-radius: 8px; padding: 18px 20px; font-size: 14px; line-height: 1.55; }
.system-email-paper h3 { margin: 0 0 12px; font-size: 18px; color: #1a1a1a; font-weight: 600; }
.system-email-paper p { margin: 0 0 12px; }
.system-email-button { display: inline-block; margin: 2px 0 16px; padding: 10px 20px; border-radius: 6px; background: #9018a8; color: #ffffff; font-weight: 600; font-size: 14px; }
.system-email-foot { font-size: 12px; color: #7c8794; border-top: 1px solid #e2e6ea; padding-top: 10px; }

/* The ⓘ beside Individual and Team: hover with a mouse, tap with a finger.
   Patch 530. */
.info-tip { position: relative; display: inline-flex; vertical-align: middle; margin-left: 4px; }
.info-tip-button { display: inline-grid; place-items: center; width: 17px; height: 17px; min-height: 0; padding: 0; border: 1px solid var(--muted-foreground); border-radius: 50%; background: transparent; color: var(--muted-foreground); font: italic 600 11px/1 Georgia, serif; cursor: pointer; }
.info-tip-button:hover, .info-tip.is-open .info-tip-button { border-color: var(--primary); color: var(--primary); background: transparent; }
.info-tip-text { display: none; position: absolute; z-index: 50; left: -8px; bottom: calc(100% + 8px); width: 260px; max-width: calc(100vw - 48px); padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--card); color: var(--foreground); box-shadow: 0 8px 24px rgba(19, 34, 38, .16); font-size: 13px; font-weight: 400; font-style: normal; line-height: 1.45; text-align: left; white-space: normal; }
.info-tip.is-open .info-tip-text { display: block; }
/* A mouse only: a phone's tap left one tip "hovered" while another opened.
   On a phone the box opens below, so it does not cover the choice. Patch 601. */
@media (hover: hover) and (pointer: fine) { .info-tip:hover .info-tip-text { display: block; } }
@media (max-width: 760px) { .info-tip-text { top: calc(100% + 8px); bottom: auto; } }

/* The Inbox: unread entries stand out; read ones sit quiet. NOTIF-005, patch 531. */
.inbox-row { border-left: 3px solid transparent; padding-left: 10px; }
.inbox-row.is-unread { border-left-color: var(--primary); }
.inbox-row:not(.is-unread) .request-head strong { font-weight: 500; }
.inbox-excerpt { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; white-space: pre-line; }
.inbox-actions { gap: 12px; }
.inbox-archived { margin-top: 14px; border-top: 1px solid var(--border); padding-top: 10px; }
.inbox-archived > summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--muted-foreground); }
.inbox-archived[open] > summary { margin-bottom: 10px; }

/* A board card with nobody on it. TASK-014, patch 534. */
.card-unassigned { font-size: 11px; font-weight: 600; color: var(--muted-foreground); border: 1px dashed var(--border); border-radius: 5px; padding: 0 6px; }

/* Invite to the beta, on the People page. AUTH-009, patch 540. */
.beta-invite-form { max-width: 520px; }

/* A client's decision, and the quiet line under any approval. The seal with a
   check, in an amber pill; the card keeps its client color. TASK-033, patch 541. */
.decision-pill { display: inline-flex; align-items: center; gap: 4px; width: fit-content; margin-top: 4px; padding: 1px 8px 1px 6px; border: 1px solid #ef9f27; border-radius: 999px; background: #faeeda; color: #633806; font-size: 11px; font-weight: 600; line-height: 1.5; }
.decision-pill .decision-seal { flex-shrink: 0; }
.decision-line { display: block; margin-top: 3px; font-size: 11px; color: var(--tone-approved-fg, #2f7d4f); }
.decision-line.is-decided { color: #854f0b; }
.decision-box { margin-top: 10px; padding: 10px 12px; border: 1px solid #ef9f27; border-radius: 8px; background: #fdf6ea; }
.decision-box p { margin: 4px 0 0; }
.decision-edit { margin-top: 10px; }
.decision-edit > summary { list-style: none; cursor: pointer; display: inline-flex; }
.decision-edit > summary::-webkit-details-marker { display: none; }
.decision-edit[open] > summary { margin-bottom: 8px; }

/* What is this?, on Send for review. The platform shows for a social post only.
   TASK-004, patch 542. */
.review-send > summary { list-style: none; cursor: pointer; }
.review-send > summary::-webkit-details-marker { display: none; }
.review-send[open] { flex-basis: 100%; }
.review-type-form { display: grid; gap: 8px; margin-top: 10px; padding: 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--card); }
.review-type-choice { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; border: 0; }
.review-type-choice legend { margin-bottom: 6px; font-size: 13px; font-weight: 600; }
.review-type-option input { position: absolute; opacity: 0; pointer-events: none; }
.review-type-option span { display: inline-block; padding: 4px 10px; border: 1px solid var(--border); border-radius: 999px; font-size: 13px; cursor: pointer; }
.review-type-option input:checked + span { border-color: var(--primary); color: var(--primary); background: color-mix(in srgb, var(--primary) 8%, var(--card)); }
.review-type-option input:focus-visible + span { outline: 2px solid var(--primary); outline-offset: 2px; }
.review-type-note { margin: 0; font-size: 12px; }
.review-platform { display: none; }
.review-type-form:has(input[value="social"]:checked) .review-platform { display: grid; }

/* The client review page, shaped by what is being reviewed. TASK-004, patch 542. */
.review-copy-text { max-width: 62ch; font-family: Georgia, "Times New Roman", serif; font-size: 17px; line-height: 1.7; }
.review-copy-count { margin: 4px 0 0; font-size: 12px; }
.review-social { justify-items: center; }
.social-frame { width: min(340px, 100%); border: 1px solid var(--border); border-radius: 24px; padding: 12px; background: var(--card); box-shadow: 0 6px 20px rgba(19, 34, 38, .08); }
.social-platform { margin: 0 0 8px; font-size: 12px; font-weight: 600; color: var(--muted-foreground); text-align: center; }
.social-images { display: flex; gap: 6px; overflow-x: auto; scroll-snap-type: x mandatory; border-radius: 12px; }
.social-images img { flex: 0 0 100%; width: 100%; aspect-ratio: 1 / 1; object-fit: cover; scroll-snap-align: start; border-radius: 12px; }
.social-count { margin: 6px 0 0; font-size: 12px; color: var(--muted-foreground); text-align: center; }
.social-caption { margin-top: 10px; font-size: 14px; line-height: 1.5; }
.social-caption strong { font-weight: 600; }
.social-posts { margin: 6px 0 0; font-size: 12px; text-align: center; }
.review-video { display: grid; gap: 8px; justify-items: start; }
.review-watch { display: inline-flex; align-items: center; padding: 12px 20px; border-radius: 8px; background: var(--primary); color: var(--primary-foreground, #fff); font-weight: 600; text-decoration: none; }
.ad-sizes { display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-end; }
.ad-size { margin: 0; display: grid; gap: 4px; }
.ad-size img { display: block; max-width: min(100%, 728px); max-height: 600px; height: auto; border: 1px solid var(--border); }
.ad-size figcaption { font-size: 12px; color: var(--muted-foreground); }
.review-download { display: inline-block; margin-top: 8px; font-size: 13px; }

/* A client contact's invitations and level. USER-001, patch 543. */
.member-history { font-size: 12px; }
.member-level-form select { min-height: 0; padding: 2px 6px; font-size: 12px; }

/* Access history under a person on the People page. AUTH-006, patch 547. */
.access-history > summary { cursor: pointer; font-weight: 600; font-size: 13px; }
.access-history ul { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 6px; font-size: 13px; }
.access-history li { display: grid; gap: 1px; }
.access-history small { color: var(--muted-foreground); font-size: 12px; }

/* The two right-hand columns, cleaned up. Sarah, 2026-10-08, with screenshots:
   "styling issues across right hand interaction columns", "3 build it".
   Patch 550. */
.review-start { display: grid; gap: 10px; margin-bottom: 14px; }
.review-start-buttons { display: flex; flex-wrap: wrap; gap: 8px; }
.review-start-buttons [aria-expanded="true"] { border-color: var(--primary); color: var(--primary); }
.review-start .review-type-form { margin-top: 0; }
.review-start .review-type-form[hidden] { display: none; }
.review-start .review-type-form > button[type="submit"] { justify-self: start; }
.client-sees-line { padding: 10px 12px; border-radius: 8px; background: color-mix(in srgb, var(--primary) 6%, var(--card)); }
.client-sees-line p { margin: 4px 0 0; }
.review-reply-side { display: grid; align-content: start; gap: 14px; }
.review-decision-buttons { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.review-decision-buttons .danger-button { margin-left: auto; }
.review-send-back { padding-top: 14px; border-top: 1px solid var(--border); gap: 8px; }
.review-attach-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.review-attach-row form { margin: 0; }

/* How clients see work, the team's guide. CLIENT-024, patch 552. */
.client-guide { max-width: 860px; }
.client-guide h2 { margin: 26px 0 8px; font-size: 16px; font-weight: 600; }
.client-guide p, .client-guide li { line-height: 1.55; }
.client-guide-lead { font-size: 15px; }
.client-guide ol { margin: 0 0 12px; padding-left: 22px; }
.client-guide li { margin-bottom: 6px; }
.client-guide .table-wrap { margin: 0 0 12px; }
.client-guide strong { font-weight: 600; }

/* Options on the client review page: lettered images, Yes or No, a note.
   Mockup approved by Sarah, 2026-10-08. REVIEW-011, patch 553. */
.pick-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 14px; }
.pick-card { margin: 0; border: 2px solid var(--border); border-radius: 10px; overflow: hidden; background: var(--card); transition: border-color .15s, opacity .15s; }
.pick-pic { position: relative; display: block; aspect-ratio: 4 / 3; background: var(--muted, #f4f4f5); cursor: zoom-in; }
.pick-pic img { width: 100%; height: 100%; object-fit: cover; display: block; transition: filter .15s, opacity .15s; }
.pick-letter { position: absolute; top: 8px; left: 8px; width: 28px; height: 28px; border-radius: 50%; background: #fff; color: #18181b; font-weight: 600; display: grid; place-items: center; box-shadow: 0 1px 4px rgba(0, 0, 0, .2); }
.pick-check { position: absolute; top: 8px; right: 8px; width: 26px; height: 26px; border-radius: 50%; background: var(--success, #2f7d4f); color: #fff; font-weight: 600; display: none; place-items: center; }
.pick-yn { display: flex; gap: 6px; padding: 8px 10px 0; }
.pick-yn button { flex: 1; min-height: 32px; padding: 0; border: 1px solid var(--border); border-radius: 7px; background: var(--card); color: var(--foreground); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; }
.pick-note { display: block; width: calc(100% - 20px); margin: 8px 10px 10px; font-size: 13px; }
.pick-note-read { margin: 0; padding: 8px 10px; font-size: 13px; color: var(--muted-foreground); }
.pick-card.is-yes { border-color: var(--success, #2f7d4f); }
.pick-card.is-yes .pick-check { display: grid; }
.pick-card.is-yes [data-pick="yes"] { background: var(--success, #2f7d4f); border-color: var(--success, #2f7d4f); color: #fff; }
.pick-card.is-no { opacity: .8; }
.pick-card.is-no .pick-pic img { filter: grayscale(1); opacity: .35; }
.pick-card.is-no [data-pick="no"] { background: #3f3f46; border-color: #3f3f46; color: #fff; }
.file-pick { display: inline-block; margin-right: 6px; padding: 0 7px; border-radius: 999px; font-size: 11px; font-weight: 600; background: var(--border); color: var(--foreground); }
.file-pick.is-yes { background: color-mix(in srgb, var(--success, #2f7d4f) 14%, var(--card)); color: var(--success, #2f7d4f); }

/* The team's preview of a client review. Patch 554. */
.review-preview-band { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; margin: 0 0 14px; padding: 10px 14px; border-radius: 10px; background: color-mix(in srgb, var(--primary) 10%, var(--card)); border: 1px solid color-mix(in srgb, var(--primary) 30%, var(--border)); }
.review-preview-band strong { font-weight: 600; }
.review-preview-off { display: grid; gap: 14px; margin: 0; padding: 0; border: 0; min-width: 0; }
/* Shown as the client sees them, only not pressable. Sarah, 2026-10-08: "still
   unclear where they approve" - faded, Approve did not look like an answer.
   Patch 556. */
.review-preview-off button, .review-preview-off .button-light { cursor: not-allowed; }

/* Arrows through the pictures in the viewer, and the large picture as the way
   in. Patch 555. */
.file-viewer-stage { position: relative; }
.file-viewer-step { position: absolute; top: 50%; z-index: 1; width: 40px; height: 40px; margin-top: -20px; border: 1px solid var(--border); border-radius: 50%; background: var(--card); color: var(--foreground); font-size: 24px; line-height: 1; cursor: pointer; box-shadow: 0 2px 8px rgba(0, 0, 0, .15); }
.file-viewer-step.is-prev { left: 10px; }
.file-viewer-step.is-next { right: 10px; }
.file-viewer-step[hidden] { display: none; }
/* Full screen, the photo the feature: a Feed post's photos. FEED-001, patch 641. */
.file-viewer.is-full { width: 100vw; max-width: none; height: 100vh; height: 100dvh; max-height: none; margin: 0; border: 0; border-radius: 0; background: #0b0b0c; color: #fff; }
.file-viewer.is-full[open] { display: flex; flex-direction: column; }
.file-viewer.is-full::backdrop { background: #0b0b0c; }
.file-viewer.is-full .file-viewer-head { border: 0; background: transparent; }
.file-viewer.is-full .file-viewer-head .secondary-button, .file-viewer.is-full .file-viewer-head a, .file-viewer.is-full .file-viewer-head button { border-color: rgba(255, 255, 255, .25); background: rgba(255, 255, 255, .1); color: #fff; }
.file-viewer.is-full .file-viewer-stage { flex: 1 1 auto; min-height: 0; display: flex; }
.file-viewer.is-full .file-viewer-body { flex: 1 1 auto; min-height: 0; padding: 0 8px 8px; }
.file-viewer.is-full .file-viewer-body img { max-width: 100%; max-height: calc(100dvh - 72px); }
.file-viewer.is-full.is-tall .file-viewer-body { overflow: hidden; place-items: center; }
.file-viewer.is-full.is-tall .file-viewer-body img { max-height: calc(100dvh - 72px); }
.file-viewer.is-full .file-viewer-step { border-color: rgba(255, 255, 255, .25); background: rgba(255, 255, 255, .14); color: #fff; }
.file-viewer-count { margin: 0; padding: 0 14px 10px; text-align: center; font-size: 12px; color: var(--muted-foreground); }
.work-stage img { cursor: zoom-in; }
.review-preview-off .review-file-button { cursor: not-allowed; pointer-events: none; }

/* The client review: thumbnails above a smaller picture. Patch 556. */
.work-view.is-compact .work-stage img { max-height: 380px; }
.work-view.is-compact .work-stage iframe { height: 420px; }
.work-view.is-compact .work-stage { min-height: 0; }
.work-thumbs.is-above { margin: 0 0 10px; }

/* Dragging the thumbnails into the order the client sees. Patch 557. */
.work-thumbs.is-arrangeable .work-thumb { cursor: grab; }
.work-thumbs.is-arrangeable .work-thumb.is-dragging { opacity: .4; cursor: grabbing; }
.work-arrange-note { margin: 6px 0 0; font-size: 12px; min-height: 1em; }

/* Delete in sight on the Files tab and the Work area. Patch 559. */
.file-table-delete, .work-delete { display: inline; margin: 0 0 0 10px; }

/* Who gets the review email. Patch 562. */
.review-people { display: grid; gap: 4px; margin: 0; padding: 0; border: 0; }
.review-people legend { margin-bottom: 4px; font-size: 13px; font-weight: 600; }

/* Mark approved, in the bar of Review activity: the form stacks. Patch 563. */
.record-bar-actions .review-record form { display: grid; }

/* Make first, Move earlier, Move later under the large picture. Patch 564. */
.work-place { display: inline-flex; flex-wrap: wrap; gap: 10px; margin-left: 10px; }
.work-place .text-button { padding: 0; }

/* The team's phone shell: ☰ in place of the rail and the section row, and
   Task, Note and Photo at the thumb on every screen. A computer shows none of
   it. Sarah's phone mockup, 2026-10-09 (mockups/phone-today.html). UX-029,
   patch 571. */
.phone-menu-button, .phone-shell, .phone-title { display: none; }
/* Your home on its band at the top of the phone menu, above the space; the
   menu itself shows only on a phone. NAV-009, patch 656. */
.phone-drawer-home { margin: 0 0 10px; }
.phone-drawer .phone-drawer-home { justify-content: flex-start; gap: 10px; border: 1px solid color-mix(in srgb, var(--primary) 14%, var(--border)); background: color-mix(in srgb, var(--primary) 9%, var(--card)); font-weight: 600; }
.phone-drawer .phone-drawer-home svg { flex: none; width: 20px; height: 20px; fill: none; stroke: var(--primary); stroke-width: 1.8; stroke-linejoin: round; }
.phone-drawer .phone-drawer-home.is-on { background: color-mix(in srgb, var(--primary) 16%, var(--card)); color: var(--primary); }
@media (max-width: 760px) {
  body.has-phone-shell .phone-shell { display: block; }
  body.has-phone-shell .app-rail,
  body.has-phone-shell .nav-band,
  body.has-phone-shell .phone-menu,
  body.has-phone-shell .app-header .workspace-switcher { display: none; }
  body.has-phone-shell .app-header .brand > div { display: none; }
  /* Room for the bar and the + button below the last row. Patch 669. */
  body.has-phone-shell .main { padding-bottom: 150px; }
  /* An iPhone zooms in on any field under 16px when tapped, and the zoom
     leaves bars pinned to the bottom floating mid-screen. Patch 601. */
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]), select, textarea { font-size: 16px; }
  /* An iPhone's date field ignores the width it is given. Patch 601. */
  input[type="date"], input[type="time"] { -webkit-appearance: none; appearance: none; display: block; min-width: 0; max-width: 100%; box-sizing: border-box; }
  input[type="date"]::-webkit-date-and-time-value { text-align: left; }
  body.has-phone-shell .view-add { display: none; }
  /* Report opens from More on a phone; its tab does not float over the page.
     UX-035, patch 669. */
  body.has-phone-shell .report-dock { bottom: 96px; }
  body.has-phone-shell .report-tab { display: none; }
  body.phone-layer-open { overflow: hidden; }
  /* An open Filters panel comes up from the bottom too; Task, Note and Photo
     and the Report tab step aside so none of its choices are covered.
     Patch 573. */
  body.has-phone-shell:has([data-filter-panel]:not([hidden])) .phone-fab,
  body.has-phone-shell:has([data-filter-panel]:not([hidden])) .phone-bar,
  body.has-phone-shell:has([data-filter-panel]:not([hidden])) .report-dock { display: none; }
  .phone-menu-button { display: inline-grid; place-items: center; flex: none; width: 42px; height: 42px; min-height: 0; margin: 0 -4px 0 -6px; border: 0; border-radius: 10px; padding: 0; background: transparent; color: var(--foreground); }
  .phone-menu-button svg, .phone-x svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; }
  .phone-scrim { position: fixed; inset: 0; z-index: 950; background: rgba(0, 0, 0, .32); }
  .phone-scrim[hidden], .phone-drawer[hidden], .phone-sheet[hidden] { display: none; }

  .phone-drawer { position: fixed; top: 0; bottom: 0; left: 0; z-index: 951; display: flex; flex-direction: column; width: min(84vw, 330px); overflow-y: auto; padding: 10px 10px calc(16px + env(safe-area-inset-bottom)); background: var(--card); box-shadow: 8px 0 30px rgba(0, 0, 0, .18); }
  .phone-drawer-head { display: flex; align-items: center; justify-content: space-between; padding: 4px 6px 8px 12px; }
  .phone-drawer-head strong { font-size: 16px; font-weight: 600; }
  .phone-x { display: inline-grid; place-items: center; width: 42px; height: 42px; min-height: 0; margin: 0; border: 0; border-radius: 10px; padding: 0; background: transparent; color: var(--foreground); }
  .phone-drawer-ws { padding: 0 8px 8px; }
  .phone-drawer-ws .workspace-switcher { display: block !important; }
  .phone-drawer-ws select { width: 100%; min-height: 42px; }
  .phone-drawer a { display: flex; align-items: center; justify-content: space-between; min-height: 48px; padding: 0 12px; border-radius: 10px; color: var(--foreground); font-size: 15px; font-weight: 500; text-decoration: none; }
  .phone-drawer a span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .phone-drawer a.is-on { background: color-mix(in srgb, var(--accent) 70%, var(--card)); color: var(--primary); font-weight: 600; }
  .phone-drawer a small { min-width: 22px; border-radius: 999px; background: #dc2626; color: #fff; font-size: 11px; font-weight: 600; text-align: center; }
  .phone-drawer hr { margin: 6px 8px; border: 0; border-top: 1px solid var(--border); }
  .phone-drawer-group { display: flex; align-items: center; justify-content: space-between; width: 100%; min-height: 48px; margin: 0; border: 0; border-radius: 10px; background: transparent; padding: 0 12px; color: var(--foreground); font-size: 15px; font-weight: 500; text-align: left; }
  .phone-drawer-group.is-on { color: var(--primary); font-weight: 600; }
  .phone-drawer-group i { width: 8px; height: 8px; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(45deg) translateY(-2px); transition: transform .15s; }
  .phone-drawer-group[aria-expanded="true"] i { transform: rotate(-135deg) translateY(-2px); }
  .phone-drawer-sub { display: grid; padding-left: 12px; }
  .phone-drawer-sub[hidden] { display: none; }
  .phone-drawer-sub a { min-height: 44px; font-size: 14.5px; }
  .phone-drawer-label { margin: 12px 12px 4px; color: var(--muted-foreground); font-size: 11.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; }

  /* The bar along the bottom: four places and More, slim line icons, the
     place you are on in the main color. Sarah, 2026-10-18, "as drawn";
     docs/mockups/design-review.html. UX-035, patch 669. */
  .phone-bar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 940; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; border-top: 1px solid var(--border); background: color-mix(in srgb, var(--card) 92%, transparent); padding: 6px 4px calc(6px + env(safe-area-inset-bottom)); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); }
  .phone-bar a, .phone-bar button { position: relative; display: grid; justify-items: center; gap: 2px; min-height: 48px; margin: 0; border: 0; border-radius: 10px; background: none; padding: 4px 0 0; color: var(--muted-foreground); font: inherit; font-size: 10.5px; font-weight: 500; text-decoration: none; box-shadow: none; }
  .phone-bar svg { width: 23px; height: 23px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
  .phone-bar .is-on { color: var(--primary); }
  .phone-bar-count { position: absolute; top: 0; left: calc(50% + 6px); min-width: 17px; height: 17px; border-radius: 999px; background: var(--primary); padding: 0 4px; color: #fff; font-size: 10px; font-weight: 600; line-height: 17px; text-align: center; }
  /* One + for adding, above the bar. */
  .phone-fab { position: fixed; right: 16px; bottom: calc(76px + env(safe-area-inset-bottom)); z-index: 941; display: grid; place-items: center; width: 56px; height: 56px; min-height: 0; margin: 0; border: 0; border-radius: 18px; background: var(--primary); padding: 0; color: var(--primary-foreground, #fff); box-shadow: 0 6px 18px color-mix(in srgb, var(--primary) 35%, transparent); }
  .phone-fab svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 2.1; stroke-linecap: round; }
  .phone-add-list { display: grid; gap: 4px; }
  .phone-add-item { display: flex; justify-content: flex-start; align-items: center; gap: 14px; min-height: 52px; margin: 0; border: 0; border-radius: 12px; background: none; padding: 0 12px; color: var(--foreground); font: inherit; font-size: 16px; font-weight: 500; text-align: left; text-decoration: none; box-shadow: none; }
  .phone-add-item:active { background: var(--secondary); }
  .phone-add-item svg { width: 22px; height: 22px; fill: none; stroke: var(--primary); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
  .phone-add { gap: 6px; }
  .phone-drawer-report { width: 100%; }
  .phone-drawer .phone-drawer-report { display: flex; justify-content: flex-start; align-items: center; min-height: 48px; margin: 0; border: 0; border-radius: 10px; background: none; padding: 0 12px; color: var(--muted-foreground); font: inherit; font-size: 15px; font-weight: 500; text-align: left; box-shadow: none; }
  /* The header: the space's picture and name beside the menu, or Your home. */
  body.has-phone-shell .app-header .brand.has-phone-title { display: none; }
  body.has-phone-shell .phone-title { display: inline-flex; align-items: center; gap: 8px; min-width: 0; margin-right: auto; font-size: 17px; font-weight: 600; }
  body.has-phone-shell .phone-title > span:last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* The name takes the cut; the bell and your picture keep their size. Found
     in the patch 669 test. Patch 670. */
  body.has-phone-shell .phone-title { flex: 1 1 auto; }
  body.has-phone-shell .app-header-actions { flex: none; }
  /* The + keeps its color after a tap, and steps aside for the report box. */
  .phone-fab:hover, .phone-fab:focus, .phone-fab:active { background: var(--primary); color: var(--primary-foreground, #fff); }
  body:has(#report-dock-open:checked) .phone-fab { display: none; }
  body.has-phone-shell .phone-title .home-nav-pic { width: 26px; height: 26px; }

  .phone-sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 951; display: grid; gap: 10px; max-height: 88vh; overflow-y: auto; margin: 0; padding: 8px 16px calc(18px + env(safe-area-inset-bottom)); border-radius: 18px 18px 0 0; background: var(--card); box-shadow: 0 -8px 30px rgba(0, 0, 0, .16); }
  .phone-grab { width: 40px; height: 5px; margin: 0 auto 4px; border-radius: 9px; background: var(--border); }
  .phone-sheet h2 { margin: 0; font-size: 17px; font-weight: 600; }
  .phone-field { display: block; width: 100%; min-height: 46px; font-size: 16px; }
  .phone-note { min-height: 120px; resize: vertical; }
  .phone-hint { margin: 2px 0 -4px; color: var(--muted-foreground); font-size: 12.5px; }
  .phone-chips { display: flex; flex-wrap: wrap; gap: 6px; }
  .phone-chip { position: relative; display: inline-flex; align-items: center; max-width: 100%; min-height: 38px; margin: 0; border: 1px solid var(--border); border-radius: 999px; padding: 0 13px; background: var(--card); color: var(--foreground); font-size: 13.5px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
  .phone-chip[aria-pressed="true"] { border-color: var(--primary); background: color-mix(in srgb, var(--accent) 70%, var(--card)); color: var(--primary); font-weight: 600; }
  .phone-photo-pick { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
  .phone-file { justify-content: center; min-height: 52px; border-radius: 12px; font-weight: 600; }
  .phone-file input { position: absolute; inset: 0; opacity: 0; }
  .phone-chosen { margin: 0; color: var(--muted-foreground); font-size: 13px; }
  .phone-find { display: grid; gap: 6px; }
  .phone-find[hidden] { display: none; }
  .phone-find-list { display: grid; gap: 2px; max-height: 220px; margin: 0; padding: 0; overflow-y: auto; list-style: none; }
  .phone-find-item { display: flex; flex-direction: column; align-items: flex-start; justify-content: center; width: 100%; min-height: 48px; margin: 0; border: 0; border-radius: 10px; padding: 6px 10px; background: transparent; color: var(--foreground); text-align: left; }
  .phone-find-item span, .phone-find-item small { display: block; max-width: 100%; }
  .phone-find-item span { overflow: hidden; font-size: 14px; font-weight: 500; text-overflow: ellipsis; white-space: nowrap; }
  .phone-find-item small { color: var(--muted-foreground); font-size: 12px; }
  .phone-find-item.is-on { background: color-mix(in srgb, var(--accent) 70%, var(--card)); }
  .phone-go { min-height: 50px; margin: 4px 0 0; border: 1px solid var(--primary); border-radius: 12px; background: var(--primary); color: var(--primary-foreground, #fff); font-size: 15px; font-weight: 600; }
}

/* Ask for input in amber, so a question reads apart from a review: the
   button on a task, its Send, and the client's Your input needed card.
   Sarah, 2026-10-10: "Amber for input". Patch 576. */
.secondary-button.is-input { border-color: #e3a857; background: #fff4e5; color: #8a4b00; }
.secondary-button.is-input:hover, .secondary-button.is-input[aria-expanded="true"] { border-color: #b45309; }
button.is-input[type="submit"] { border-color: #b45309; background: #b45309; color: #fff; }
.review-input-card { box-shadow: inset 3px 0 0 #d97706; }
.review-input-card .review-go { background: #b45309; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .secondary-button.is-input { border-color: #7a5420; background: #3a2a12; color: #f3c98b; } }
:root[data-theme="dark"] .secondary-button.is-input { border-color: #7a5420; background: #3a2a12; color: #f3c98b; }

/* A goal as a card, on the dashboard and on Goals, and its form. No counts, no
   percent complete. GOAL-001, patch 579. */
.home-goals { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(190px, 100%), 1fr)); gap: 12px; }
.goal-card { display: flex; flex-direction: column; overflow: hidden; border: 1px solid var(--border); border-radius: 12px; background: var(--card); color: var(--foreground); text-decoration: none; }
.goal-card:hover { border-color: color-mix(in srgb, var(--primary) 50%, var(--border)); }
.goal-card.is-dragging { opacity: .45; }
.goal-card-art { display: grid; place-items: center; height: 70px; font-size: 28px; }
.goal-card-art img { max-width: 70%; max-height: 52px; object-fit: contain; }
.goal-card-body { display: grid; gap: 5px; padding: 9px 11px 11px; }
.goal-card-body strong { font-size: 13.5px; font-weight: 600; line-height: 1.3; }
.goal-kind { width: max-content; border-radius: 999px; padding: 0 7px; font-size: 11px; font-weight: 600; line-height: 1.7; background: var(--secondary); color: var(--foreground); }
.goal-kind.is-business { background: #e8f0fe; color: #1d4ed8; } .goal-kind.is-client { background: #fdf2e9; color: #9a3412; } .goal-kind.is-personal { background: #f3e8ff; color: #6b21a8; } .goal-kind.is-family { background: #e0f2f1; color: #0f766e; } .goal-kind.is-project { background: #eef5e6; color: #3f6212; }
.goal-state { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600; }
.goal-state i { width: 8px; height: 8px; border-radius: 50%; }
.goal-state.is-moving { color: #3f6212; } .goal-state.is-moving i { background: #65a30d; }
.goal-state.is-drifting { color: #92400e; } .goal-state.is-drifting i { background: #d97706; }
.goal-state.is-stuck { color: #991b1b; } .goal-state.is-stuck i { background: #dc2626; }
.goal-where { color: var(--muted-foreground); font-size: 12.5px; }
.goal-gap { width: max-content; max-width: 100%; overflow: hidden; border-radius: 999px; padding: 1px 8px; background: #fff7ed; color: #9a3412; font-size: 11.5px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.goal-card.is-new { align-items: center; justify-content: center; min-height: 150px; border-style: dashed; border-color: color-mix(in srgb, var(--muted-foreground) 45%, var(--border)); color: var(--muted-foreground); font-weight: 600; }
.goal-kinds, .goal-icons { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; border: 0; padding: 0; }
.goal-kinds legend, .goal-icons legend { margin-bottom: 6px; padding: 0; font-size: 13px; font-weight: 600; }
.goal-kind-pick, .goal-icon-pick { position: relative; display: inline-flex; cursor: pointer; }
.goal-kind-pick input, .goal-icon-pick input { position: absolute; opacity: 0; pointer-events: none; }
.goal-kind-pick span { display: inline-flex; align-items: center; min-height: 36px; border: 1px solid var(--border); border-radius: 999px; padding: 0 13px; background: var(--card); font-size: 13px; }
.goal-icon-pick span { display: grid; place-items: center; width: 40px; height: 40px; border: 1px solid var(--border); border-radius: 10px; background: var(--card); font-size: 20px; }
.goal-kind-pick input:checked + span, .goal-icon-pick input:checked + span { border-color: var(--primary); background: var(--accent); color: color-mix(in srgb, var(--primary) 85%, #000000); font-weight: 600; }
.goal-kind-pick input:focus-visible + span, .goal-icon-pick input:focus-visible + span { outline: 2px solid var(--primary); outline-offset: 2px; }
.goal-dialog { width: min(560px, calc(100vw - 32px)); }
.goal-form { display: grid; gap: 12px; }
.goal-form label[hidden] { display: none; }
@media (max-width: 760px) {
  .home-goals { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; gap: 10px; padding-bottom: 4px; }
  .home-goals .goal-card { flex: 0 0 72%; scroll-snap-align: start; }
  .goals-page-list { display: grid; grid-template-columns: 1fr 1fr; overflow: visible; }
}

/* The task counts at the end of the filter row on Tasks: Today, Open,
   Overdue, Review, each a link. Patch 579. */
.task-counts { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; margin-left: auto; font-size: 12.5px; }
.task-counts a { color: var(--muted-foreground); text-decoration: none; white-space: nowrap; }
.task-counts a:hover { color: var(--primary); }
.task-counts b { color: var(--foreground); font-weight: 600; }
.task-counts a.is-late b { color: color-mix(in srgb, var(--destructive) 88%, #000000); }
/* A phone keeps its two rows; Today on the menu carries the day. */
@media (max-width: 760px) { .task-counts { display: none; } }

/* Your own picture on a goal fills its picture area. Patch 583. */
.goal-photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.goal-card-art { position: relative; overflow: hidden; }
.goal-card-art.has-photo img.goal-photo { max-width: none; max-height: none; }

/* The Feed, on the dashboard and on its own page. Patches 582 and 585. FEED-001. */
.feed-compose { display: grid; gap: 8px; margin-bottom: 12px; border: 1px solid var(--border); border-radius: 10px; padding: 10px; }
.feed-compose textarea { width: 100%; min-height: 56px; resize: vertical; }
.feed-compose-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.feed-compose-row select { flex: 1 1 180px; min-width: 0; }
.feed-tags { display: grid; gap: 6px; }
.feed-tag-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.feed-tag-chips:empty { display: none; }
.feed-tag-chip { display: inline-flex; align-items: center; gap: 2px; min-height: 32px; border-radius: 999px; background: var(--accent); padding: 0 4px 0 12px; color: color-mix(in srgb, var(--primary) 85%, #000000); font-size: 13px; font-weight: 500; }
.feed-tag-chip button { display: grid; place-items: center; width: 28px; height: 28px; min-height: 0; margin: 0; border: 0; border-radius: 50%; background: transparent; padding: 0; color: inherit; font-size: 12px; }
.feed-tag-new { justify-self: start; min-height: 32px; margin: 0; border: 1px dashed var(--border); border-radius: 999px; background: transparent; padding: 0 12px; color: var(--foreground); font-size: 13px; }
.feed-tag-new[hidden] { display: none; }
.feed-photo { position: relative; overflow: hidden; cursor: pointer; }
.feed-photo input { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.feed-team { font-size: 12.5px; }
.feed-chosen { margin: 0; color: var(--muted-foreground); font-size: 12.5px; }
.feed-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.feed-chip { min-height: 0; margin: 0; border: 1px solid var(--border); border-radius: 999px; padding: 3px 10px; background: var(--card); color: var(--foreground); font-size: 12px; font-weight: 500; }
.feed-chip[aria-pressed="true"] { border-color: var(--foreground); background: var(--foreground); color: var(--card); }
.feed-pictures { min-height: 0; margin: 0; border: 0; padding: 0; background: none; cursor: pointer; }
.feed-list { margin: 0; padding: 0; list-style: none; }
.feed-entry { display: grid; grid-template-columns: 30px minmax(0, 1fr); gap: 10px; padding: 10px 0; }
.feed-entry + .feed-entry { border-top: 1px solid var(--border); }
.feed-entry[hidden] { display: none; }
.feed-entry { position: relative; }
.feed-more-button { position: absolute; top: 6px; right: 0; display: grid; place-items: center; width: 36px; height: 32px; min-height: 0; margin: 0; border: 0; border-radius: 8px; background: transparent; padding: 0; color: var(--muted-foreground); font-size: 15px; letter-spacing: 1px; }
.feed-more-button:hover, .feed-more-button:focus-visible { background: var(--accent); color: var(--foreground); }
.feed-entry .feed-who { padding-right: 40px; }
.feed-ctx button { justify-content: flex-start; text-align: left; }
.feed-hidden { margin-top: 14px; border-top: 1px solid var(--border); padding-top: 10px; }
.feed-hidden[hidden] { display: none; }
.feed-hidden summary { min-height: 36px; color: var(--muted-foreground); font-size: 13px; cursor: pointer; }
.feed-undo { position: fixed; left: 50%; bottom: calc(84px + env(safe-area-inset-bottom)); z-index: 60; display: flex; align-items: center; gap: 14px; transform: translateX(-50%); border-radius: 12px; background: #18181b; padding: 6px 6px 6px 16px; color: #fff; font-size: 14px; box-shadow: 0 8px 24px rgba(0, 0, 0, .2); }
.feed-undo[hidden] { display: none; }
.feed-undo button { min-height: 40px; margin: 0; border: 0; border-radius: 8px; background: transparent; padding: 0 12px; color: #a7f3d0; font-weight: 600; }
/* Team only, where a workspace has clients: a light tint behind the post,
   in place of the gray line. Sarah, 2026-10-17: "something else would be
   better (like a lightly colored background indicator". NAV-009, patch 659. */
.feed-entry.is-team { margin: 0 -8px; border-radius: 8px; background: color-mix(in srgb, #f59e0b 8%, var(--card)); padding-left: 8px; padding-right: 8px; }
.feed-av { display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%; color: #fff; font-size: 11px; font-weight: 600; }
.feed-main { min-width: 0; }
.feed-none { margin: 8px 0 0; }
.feed-who { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font-size: 13px; }
.feed-who strong { font-weight: 600; }
.feed-who time { color: var(--muted-foreground); font-size: 12px; }
.feed-pill { border-radius: 999px; padding: 0 7px; background: var(--secondary); font-size: 11px; font-weight: 600; line-height: 1.7; }
.feed-pill.is-decision { background: color-mix(in srgb, #65a30d 16%, var(--card)); color: color-mix(in srgb, #3f6212 85%, var(--foreground)); }
.feed-pill.is-review { background: color-mix(in srgb, #9333ea 13%, var(--card)); color: color-mix(in srgb, #6b21a8 85%, var(--foreground)); }
.feed-pill.is-request { background: color-mix(in srgb, #f59e0b 20%, var(--card)); color: color-mix(in srgb, #92400e 85%, var(--foreground)); }
.feed-pill.is-date { background: color-mix(in srgb, #0d9488 15%, var(--card)); color: color-mix(in srgb, #0f766e 85%, var(--foreground)); }
.feed-pill.is-file { background: color-mix(in srgb, #2563eb 14%, var(--card)); color: color-mix(in srgb, #1d4ed8 85%, var(--foreground)); }
.feed-body { overflow-wrap: anywhere; font-size: 13.5px; }
.feed-body p { margin: 2px 0 0; }
/* A post's photos, the feature: a mosaic on a computer, one at a time on a
   phone. Sarah, 2026-10-16. FEED-001, patch 641. */
.feed-photos { display: grid; gap: 3px; overflow: hidden; margin-top: 8px; border-radius: 8px; }
.feed-shot { position: relative; display: block; overflow: hidden; min-width: 0; min-height: 0; background: var(--secondary); }
.feed-shot img { display: block; width: 100%; height: 100%; object-fit: cover; }
.feed-shot.is-extra { display: none; }
.feed-photos.is-n1 .feed-shot { background: none; }
.feed-photos.is-n1 { container-type: inline-size; }
.feed-photos.is-n1 .feed-shot img { width: 100%; max-width: none; height: auto; max-height: 125cqw; border-radius: 0; object-fit: cover; }
/* Photos take the whole width of the post, out under the poster's picture;
   one photo always fills it, at its own shape, a tall one cut to 4 by 5 as
   Instagram and Facebook do (patch 659; 658 cut at 80% of the screen), the
   whole of it a tap away. Sarah: "match industry standards". Sarah, 2026-10-17: "i'd prefer if pics were taking
   up the entire space and not being constrained", then "yes to all three".
   NAV-009, patch 658 (one photo kept its own width up to 640px from 642). */
.feed-entry .feed-main > .feed-photos { margin-left: -40px; }

.feed-photos.is-n2 { grid-template-columns: 1fr 1fr; aspect-ratio: 2 / 1; }
.feed-photos.is-n3 { grid-template-columns: 2fr 1fr; grid-template-rows: 1fr 1fr; aspect-ratio: 3 / 2; }
.feed-photos.is-n3 .feed-shot:first-child { grid-row: 1 / 3; }
.feed-photos.is-n4 { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; aspect-ratio: 4 / 3; }
.feed-shot-more { position: absolute; inset: 0; display: grid; place-items: center; background: rgba(0, 0, 0, .45); color: #fff; font-size: 26px; font-weight: 600; }
.feed-shot-count { display: none; }
@media (max-width: 760px) {
  .feed-photos, .feed-photos.is-n2, .feed-photos.is-n3, .feed-photos.is-n4 { display: flex; aspect-ratio: auto; max-height: none; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; margin-inline: -2px; border-radius: 8px; }
  .feed-photos::-webkit-scrollbar { display: none; }
  .feed-shot, .feed-shot.is-extra { display: block; flex: 0 0 100%; scroll-snap-align: center; }
  .feed-shot img { height: auto; max-height: 75vh; aspect-ratio: auto; }
  .feed-photos.is-n1 .feed-shot img { height: auto; max-height: 125cqw; aspect-ratio: auto; }
  .feed-photos:not(.is-n1) .feed-shot img { height: min(100vw, 75vh); }
  .feed-shot-more { display: none; }
  .feed-shot-count { position: absolute; top: 8px; right: 8px; display: block; border-radius: 999px; background: rgba(0, 0, 0, .55); padding: 1px 8px; color: #fff; font-size: 12px; font-weight: 600; }
}
/* Pictures off hides them at every width, after the phone rule above.
   Found in the patch 641 test. */
.no-pictures [data-feed-images].feed-photos { display: none; }
/* A long post, folded after four lines. */
.feed-body.is-folded { max-height: 6.2em; overflow: hidden; -webkit-mask-image: linear-gradient(#000 60%, transparent); mask-image: linear-gradient(#000 60%, transparent); }
.feed-unfold { display: inline; min-height: 0; border: 0; background: none; padding: 0; color: var(--muted-foreground); font-size: 13.5px; font-weight: 600; box-shadow: none; cursor: pointer; }
.feed-unfold:hover { color: var(--foreground); text-decoration: underline; }
.feed-refs { display: flex; flex-wrap: wrap; gap: 4px 12px; margin-top: 4px; font-size: 12px; }
.feed-refs a { color: var(--muted-foreground); text-decoration: none; }
.feed-refs a:hover { color: var(--primary); }
.feed-refs span { color: var(--muted-foreground); }
.feed-pill.is-goal { background: color-mix(in srgb, #65a30d 22%, var(--card)); color: color-mix(in srgb, #3f6212 85%, var(--foreground)); }

/* Choose what shows, opening in place. Patch 585. */
.feed-settings { margin: 0 0 10px; }
.feed-settings > summary { display: inline-block; list-style: none; cursor: pointer; }
.feed-settings > summary::-webkit-details-marker { display: none; }
.feed-settings-form { display: grid; gap: 12px; margin-top: 8px; border: 1px solid var(--border); border-radius: 10px; background: var(--card); padding: 12px; }
.feed-settings-form fieldset { margin: 0; border: 0; padding: 0; }
.feed-settings-form legend { margin-bottom: 6px; padding: 0; font-size: 13px; font-weight: 600; }
.feed-settings-form legend small { color: var(--muted-foreground); font-weight: 500; }
.feed-settings-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 2px 14px; }
.feed-settings-grid.is-scroll { max-height: 180px; overflow-y: auto; }
.feed-settings-grid .checkbox-line { font-size: 13px; font-weight: 400; }
.feed-settings-row { display: flex; flex-wrap: wrap; gap: 12px; }
.feed-settings-row label { display: grid; gap: 4px; font-size: 12.5px; }
.feed-results { transition: opacity .15s; }
.feed-results.is-loading { opacity: .5; }
.feed-more { display: block; margin-top: 10px; color: var(--primary); font-size: 13px; font-weight: 600; text-decoration: none; }

/* A small link in a box's heading: All goals, More, Choose what shows. Patch 585. */
.box-link { color: var(--primary); font-size: 12.5px; font-weight: 600; text-decoration: none; }

/* Reactions and comments: the Feed, a goal's posts and a project's
   conversation. A Like that holds or hovers for six; a comment thread under
   each entry. FEED-001, patch 626. */
.react { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 8px; }
.react.is-small { margin-top: 0; }
.react-button, .react-summary { display: inline-flex; align-items: center; gap: 5px; min-height: 32px; border: 1px solid var(--border); border-radius: 999px; background: var(--card); padding: 0 11px; color: var(--muted-foreground); font-size: 13px; font-weight: 600; box-shadow: none; -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
.react.is-small .react-button, .react.is-small .react-summary { min-height: 28px; padding: 0 8px; font-size: 12px; }
.react-button:hover, .react-summary:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); color: var(--foreground); background: var(--card); }
.react-button.is-mine { border-color: color-mix(in srgb, var(--primary) 55%, var(--border)); background: var(--accent); color: var(--primary); }
.react-face { font-size: 15px; line-height: 1; }
.react-summary[hidden] { display: none; }
.react-faces { letter-spacing: -2px; font-size: 14px; }
.react-people { flex: 1 1 100%; margin: 2px 0 0; padding: 8px 10px; list-style: none; border: 1px solid var(--border); border-radius: 10px; background: var(--card); font-size: 13px; }
.react-people[hidden] { display: none; }
.react-people li + li { margin-top: 4px; }
.react-picker { position: fixed; z-index: 1200; display: flex; gap: 2px; border: 1px solid var(--border); border-radius: 999px; background: var(--card); padding: 4px; box-shadow: 0 10px 30px rgba(19, 34, 38, .18); }
.react-picker button { display: grid; place-items: center; width: 40px; height: 40px; min-height: 0; border: 0; border-radius: 50%; background: transparent; padding: 0; font-size: 22px; box-shadow: none; transition: transform .1s; }
.react-picker button:hover, .react-picker button:focus-visible { transform: scale(1.18); background: var(--secondary); }
.feed-comments { display: grid; gap: 8px; margin-top: 8px; padding-top: 10px; border-top: 1px solid var(--border); }
.feed-comments[hidden] { display: none; }
.feed-comment-list { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
.feed-comment-list:empty { display: none; }
.feed-comment { display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 8px; align-items: start; }
.feed-comment[hidden] { display: none; }
.feed-av.is-small { width: 28px; height: 28px; font-size: 10.5px; }
.feed-comment-main { min-width: 0; }
.feed-comment-bubble { display: inline-block; max-width: 100%; border-radius: 12px; background: var(--secondary); padding: 7px 11px; font-size: 13.5px; overflow-wrap: anywhere; }
.feed-comment-bubble strong { font-weight: 600; }
.feed-comment-bubble p { display: inline; margin: 0; }
.feed-comment-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 3px; padding-left: 4px; color: var(--muted-foreground); font-size: 12px; }
.feed-comment-form { display: flex; gap: 8px; align-items: flex-end; }
.feed-comment-form textarea { flex: 1 1 auto; min-height: 38px; height: 38px; border-radius: 19px; padding: 8px 14px; resize: none; }
.feed-comment-form button { min-height: 38px; }

/* A Feed post's one line: Like and Comment as quiet text buttons, the faces
   and count at the right. Sarah, 2026-10-14: "One line. So it doesn't take up
   a bunch of extra room." Patch 627. */
.react.is-line { gap: 2px; margin-top: 6px; }
.react.is-line .react-button { min-height: 34px; border-color: transparent; background: transparent; padding: 0 10px; }
.react.is-line .react-button:hover { border-color: transparent; background: var(--secondary); color: var(--foreground); }
.react.is-line .react-button.is-mine { border-color: transparent; background: transparent; color: var(--primary); }
.react.is-line .react-button:first-child { margin-left: -10px; }
.react.is-line .react-summary { margin-left: auto; border-color: transparent; background: transparent; padding: 0 4px; }
.react.is-line .react-summary:hover { background: var(--secondary); }
.react-icon { flex: 0 0 auto; }
.feed-comment-count { color: var(--muted-foreground); font-weight: 500; }
.feed-comment-count[hidden] { display: none; }
.feed-comment-toggle[aria-expanded="true"] { color: var(--foreground); }
.react-thumb { display: block; }
.react.is-small .react-thumb { width: 15px; height: 15px; }

/* Items in a layout you arrange: the dashboard and a project's Overview.
   Two thirds and one third either way round, or three equal columns; an item
   stays in the column it was put in. Layout and Add at the top right, ··· and
   × on each item. Sarah, 2026-10-14, after Matomo. Patch 625, shared in 628. */
.box-tools { display: flex; gap: 8px; }
.box-tool { position: relative; }
.box-tool > button { display: inline-flex; align-items: center; gap: 6px; }
.box-tool > button[aria-expanded="true"] { border-color: var(--primary); color: var(--primary); }
.box-layout-panel { position: absolute; top: calc(100% + 6px); right: 0; z-index: 20; display: flex; gap: 6px; border: 1px solid var(--border); border-radius: 12px; background: var(--card); padding: 8px; box-shadow: 0 8px 28px rgba(19, 34, 38, .16); }
.box-layout-panel[hidden] { display: none; }
.box-layout-pick { display: grid; place-items: center; width: 64px; height: 48px; min-height: 0; border: 1.5px solid var(--border); border-radius: 9px; background: var(--card); padding: 0; color: var(--muted-foreground); box-shadow: none; }
.box-layout-pick svg { width: 40px; height: 27px; }
.box-layout-pick:hover { border-color: color-mix(in srgb, var(--primary) 50%, var(--border)); color: var(--foreground); }
.box-layout-pick[aria-checked="true"] { border-color: var(--primary); background: var(--accent); color: var(--primary); }
.box-cols { display: grid; gap: 16px; align-items: start; }
.box-cols.is-wide-left { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
.box-cols.is-wide-right { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); }
.box-cols.is-thirds { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.box-col { display: grid; gap: 16px; align-content: start; min-width: 0; }
.box-col[hidden] { display: none; }
[data-box] { min-width: 0; }
[data-box].is-hidden { display: none; }
.box-more { min-width: 32px; min-height: 32px; margin: -6px -8px -6px 0; border: 0; border-radius: 8px; padding: 0 6px; background: transparent; color: var(--muted-foreground); font-size: 15px; font-weight: 600; letter-spacing: 1px; line-height: 1; cursor: pointer; }
.box-more:hover, .box-more:focus-visible, .box-more[aria-expanded="true"] { background: var(--secondary); color: var(--foreground); }
.box-remove { display: grid; place-items: center; width: 32px; height: 32px; min-height: 0; margin: -6px -8px -6px 0; border: 0; border-radius: 8px; padding: 0; background: transparent; color: var(--muted-foreground); box-shadow: none; cursor: pointer; }
.box-remove:hover, .box-remove:focus-visible { background: var(--secondary); color: var(--foreground); }
/* While an item is moving: it follows the pointer, a dashed space shows where
   it will land, and an empty column shows it can take one. */
[data-box].is-lifted { position: fixed; z-index: 1000; margin: 0; pointer-events: none; box-shadow: 0 18px 40px rgba(19, 34, 38, .22); opacity: .95; cursor: grabbing; }
.box-drop { border: 2px dashed color-mix(in srgb, var(--primary) 55%, transparent); border-radius: 14px; background: color-mix(in srgb, var(--primary) 6%, transparent); }
[data-box-layout].is-moving, [data-box-layout].is-moving * { cursor: grabbing !important; -webkit-user-select: none; user-select: none; }
[data-box-layout].is-moving .box-col { min-height: 64px; border-radius: 14px; outline: 1px dashed var(--border); outline-offset: 4px; }
/* Three columns become two on a narrower screen, the third under the other
   two; a phone shows one column, the wide column first. */
@media (max-width: 1100px) {
  .box-cols.is-thirds { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .box-cols.is-thirds > .box-col:nth-child(3) { grid-column: 1 / -1; }
}
@media (max-width: 760px) {
  .box-cols.is-wide-left, .box-cols.is-wide-right, .box-cols.is-thirds { grid-template-columns: minmax(0, 1fr); }
  .box-cols.is-wide-right > .box-col:nth-child(2) { order: -1; }
  .box-cols.is-thirds > .box-col:nth-child(3) { grid-column: auto; }
  .box-remove { width: 40px; height: 40px; }
  .box-more { min-width: 40px; min-height: 40px; }
}

/* The bell in the top bar and its list: a number for what is new, each line
   bold until opened, a ··· on each line. Sarah, 2026-10-15. NOTIF-006,
   patch 631. */
.bell { position: relative; }
.bell-button { position: relative; display: grid; place-items: center; width: 36px; height: 36px; min-height: 0; border: 0; border-radius: 999px; background: transparent; padding: 0; color: var(--muted-foreground); box-shadow: none; cursor: pointer; }
.bell-button:hover, .bell-button:focus-visible, .bell-button[aria-expanded="true"] { background: var(--secondary); color: var(--foreground); }
.bell-count { position: absolute; top: 2px; right: 1px; display: grid; place-items: center; min-width: 17px; height: 17px; border-radius: 999px; background: var(--destructive); padding: 0 4px; color: #ffffff; font-size: 10.5px; font-weight: 600; line-height: 1; }
.bell-count[hidden] { display: none; }
.bell-panel { position: absolute; top: calc(100% + 8px); right: -8px; z-index: 60; width: min(380px, calc(100vw - 24px)); max-height: min(520px, calc(100vh - 90px)); overflow-y: auto; border: 1px solid var(--border); border-radius: 12px; background: var(--card); padding: 6px; box-shadow: 0 12px 32px rgba(19, 34, 38, .18); }
.bell-panel[hidden] { display: none; }
.bell-head { margin: 4px 8px 6px; font-size: 14px; font-weight: 600; }
.bell-empty { margin: 6px 8px 10px; color: var(--muted-foreground); font-size: 13px; }
.bell-empty[hidden] { display: none; }
.bell-list { margin: 0; padding: 0; list-style: none; }
.bell-item { position: relative; display: flex; align-items: flex-start; border-radius: 8px; -webkit-touch-callout: none; }
.bell-item:hover, .bell-item:focus-within { background: var(--secondary); }
.bell-link { display: grid; flex: 1; gap: 2px; min-width: 0; padding: 8px 4px 8px 14px; color: var(--muted-foreground); font-size: 13px; text-decoration: none; }
.bell-line strong { color: var(--foreground); font-weight: 500; }
.bell-item.is-unread .bell-link { color: var(--foreground); }
.bell-item.is-unread .bell-line strong { font-weight: 600; }
.bell-item.is-unread::before { content: ""; position: absolute; top: 14px; left: 4px; width: 6px; height: 6px; border-radius: 50%; background: var(--primary); }
.bell-item:not(.is-unread) .bell-unread-word { display: none; }
.bell-excerpt { overflow: hidden; color: var(--muted-foreground); font-size: 12.5px; text-overflow: ellipsis; white-space: nowrap; }
.bell-more { flex: none; width: 32px; height: 32px; min-height: 0; margin: 4px 4px 0 0; border: 0; border-radius: 8px; background: transparent; padding: 0; color: var(--muted-foreground); font-size: 15px; letter-spacing: 1px; box-shadow: none; cursor: pointer; }
.bell-more:hover, .bell-more:focus-visible, .bell-more[aria-expanded="true"] { background: var(--card); color: var(--foreground); }
@media (max-width: 760px) {
  .bell-panel { position: fixed; top: 58px; right: 12px; left: 12px; width: auto; }
  .bell-more { width: 40px; height: 40px; }
}

/* @ everywhere you write: the list sits under a one-line comment box, and
   your own name is picked out where someone named you. FEED-003, patch 632. */
.feed-comment-form { position: relative; }
.feed-comment-form .mention-list { position: absolute; top: 100%; left: 0; }
.mention-me { border-radius: 4px; background: color-mix(in srgb, var(--primary) 14%, transparent); padding: 0 2px; color: var(--primary); font-weight: 600; }
/* Where the bell brought you: a moment of color. Patch 633. */
.feed-entry.is-arrived, .feed-comment.is-arrived { animation: arrived 2.4s ease-out; }
@keyframes arrived { from { background: color-mix(in srgb, var(--primary) 14%, transparent); } to { background: transparent; } }
/* The @ list on a phone: each name a full finger tall. Patch 633. */
@media (max-width: 760px) {
  .mention-list li { min-height: 44px; display: flex; align-items: center; padding: 10px 12px; font-size: 15px; }
  .mention-list { max-width: none; right: 0; }
}
/* Arriving at a post or comment by its address keeps it clear of the top
   bar. Patch 634. */
.feed-entry, .feed-comment, .ov-entry { scroll-margin-top: 96px; }

/* A page that starts something: a new workspace or a group. Moved here from
   new-workspace.php to be shared, patch 635. */
.cw-wrap { max-width: 640px; margin: 8px auto 40px; }
.cw-box { display: grid; gap: 14px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); padding: 24px; }
.cw-box h2 { margin: 0; font-size: 20px; font-weight: 600; }
.cw-box form { display: grid; gap: 14px; }
.cw-box form > label:not(.billing-ack):not(.group-switch) { display: grid; gap: 6px; font-size: 13px; font-weight: 600; }
.cw-intro { display: grid; gap: 8px; color: var(--muted-foreground); font-size: 13px; line-height: 1.5; }
.cw-intro p { margin: 0; }
.cw-intro strong { color: var(--foreground); font-weight: 600; }
.cw-box .billing-ack { display: flex; align-items: flex-start; gap: 8px; font-size: 13px; font-weight: 400; }
.cw-box .billing-ack input { width: auto; margin-top: 3px; }
.cw-box form > .billing-ack:first-of-type { border-top: 1px solid var(--border); padding-top: 12px; }
.cw-pricing { margin: 0; font-size: 13px; color: var(--muted-foreground); }
.cw-pricing strong { color: var(--foreground); font-weight: 600; }
.cw-back { margin: 14px 0 0; text-align: center; font-size: 13px; }

/* A group's header: its header picture, picture, name and about. Sarah,
   2026-10-15. GROUP-002, patch 635. */
.group-head { overflow: hidden; margin-bottom: 16px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); }
.group-cover { height: 160px; background: linear-gradient(135deg, #86efac 0%, #16a34a 40%, #0c4a6e 100%) center / cover no-repeat; }
.group-info { display: flex; align-items: flex-end; gap: 14px; margin-top: -36px; padding: 0 18px 14px; }
.group-pic { display: grid; place-items: center; flex: none; width: 76px; height: 76px; border: 4px solid var(--card); border-radius: 18px; background: linear-gradient(135deg, #0ea5e9, #0f766e); color: #ffffff; font-size: 26px; font-weight: 600; object-fit: cover; }
.group-name { flex: 1; min-width: 0; padding-top: 40px; }
.group-name h1, .group-name h2 { margin: 0; font-size: 22px; font-weight: 600; }
.group-name p { margin: 2px 0 0; color: var(--muted-foreground); font-size: 13px; }
@media (max-width: 760px) {
  .group-cover { height: 110px; }
  .group-info { display: block; margin-top: -30px; }
  .group-pic { width: 62px; height: 62px; font-size: 22px; }
  .group-name { padding-top: 6px; }
  .group-info .secondary-button { display: flex; justify-content: center; margin-top: 10px; }
}

/* A group's members and settings. GROUP-002, patch 635. */
.group-members { max-width: 760px; }
.group-invite { display: flex; gap: 8px; margin-bottom: 8px; }
.group-invite input { flex: 1; min-width: 0; }
.group-member-list { margin: 0; padding: 0; list-style: none; }
.group-member-list li { display: flex; align-items: center; gap: 12px; min-height: 60px; border-top: 1px solid var(--border); }
.group-member-list li:first-child { border-top: 0; }
.group-member-who { flex: 1; min-width: 0; }
.group-member-who strong { display: block; overflow: hidden; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.group-member-who small { color: var(--muted-foreground); font-size: 12.5px; }
.group-role { border-radius: 999px; background: var(--secondary); padding: 1px 9px; color: var(--foreground); font-size: 12px; font-weight: 600; }
.group-role.is-admin { background: var(--accent); color: var(--primary); }
.group-more { position: relative; }
.group-more > summary { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 8px; color: var(--muted-foreground); font-size: 15px; letter-spacing: 1px; list-style: none; cursor: pointer; }
.group-more > summary::-webkit-details-marker { display: none; }
.group-more > summary:hover, .group-more[open] > summary { background: var(--secondary); color: var(--foreground); }
.group-more-menu { position: absolute; top: calc(100% + 4px); right: 0; z-index: 30; display: grid; min-width: 200px; border: 1px solid var(--border); border-radius: 10px; background: var(--card); padding: 4px; box-shadow: 0 10px 28px rgba(19, 34, 38, .16); }
.group-more-menu form { margin: 0; }
.group-more-menu button { width: 100%; min-height: 40px; border: 0; border-radius: 7px; background: transparent; padding: 0 10px; color: var(--foreground); font-size: 13.5px; font-weight: 500; text-align: left; box-shadow: none; }
.group-more-menu button:hover { background: var(--secondary); }
.group-more-menu button.is-danger { color: var(--destructive); }
/* The shared button style centers its words; menu lines start at the left,
   as the Change link does. GROUP-005, found in the patch 639 test. */
.group-more-menu button { justify-content: flex-start; }
.group-settings .group-head { margin-bottom: 0; }
/* Leave the group, and Posts stay when someone leaves. GROUP-004, patch 637. */
.group-leave { margin: 12px 0 0; border-top: 1px solid var(--border); padding-top: 14px; }
.group-switch { display: flex; align-items: center; justify-content: space-between; gap: 16px; min-height: 44px; cursor: pointer; }
.group-switch strong { font-size: 14px; font-weight: 600; }
.group-switch input { flex: none; width: 20px; height: 20px; margin: 0; }
/* A group's two pictures side by side on sign-up. GROUP-004, patch 637. */
.signup-pic-row { display: grid; gap: 12px; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
@media (max-width: 520px) { .signup-pic-row { grid-template-columns: minmax(0, 1fr); } }
/* A group's Resources and its settings headings. GROUP-005, patch 639. */
.group-settings-head { margin: 8px 0 -6px; color: var(--muted-foreground); font-size: 11.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
.group-more-menu a { display: flex; align-items: center; min-height: 40px; border-radius: 7px; padding: 0 10px; color: var(--foreground); font-size: 13.5px; font-weight: 500; text-decoration: none; }
.group-more-menu a:hover { background: var(--secondary); }
.res-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; }
.res-head .group-back { margin: 0 0 4px; }
.res-folder-menu { min-width: 260px; gap: 4px; }
.res-rename { display: flex; gap: 6px; padding: 4px; }
.res-rename input { flex: 1; min-width: 0; }
.res-rename button { width: auto; background: var(--primary); color: var(--primary-foreground); }
.res-tools { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px; margin-bottom: 14px; }
.res-add { position: relative; }
.res-for-file, .res-for-link { display: grid; }
.res-list { padding: 14px 16px; }
.res-add > summary { list-style: none; cursor: pointer; }
.res-add > summary::-webkit-details-marker { display: none; }
.res-add[open] { flex-basis: 100%; }
.res-add-form { display: grid; gap: 12px; max-width: 520px; margin-top: 8px; padding: 16px; }
.res-add-form > label, .res-edit > label { display: grid; gap: 6px; font-size: 13px; font-weight: 600; }
.res-kind { display: flex; gap: 16px; font-size: 14px; }
.res-kind label { display: flex; align-items: center; gap: 6px; min-height: 36px; cursor: pointer; }
.res-kind input { width: auto; min-height: 0; margin: 0; }
.res-add-form:has([name="kind"][value="file"]:checked) .res-for-link,
.res-add-form:has([name="kind"][value="link"]:checked) .res-for-file { display: none; }
.res-folders { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; margin-bottom: 14px; }
.res-folder { display: grid; gap: 2px; padding: 14px; color: var(--foreground); text-decoration: none; }
.res-folder:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); }
.res-folder span { font-size: 20px; }
.res-folder strong { font-weight: 600; }
.res-folder small { color: var(--muted-foreground); font-size: 12.5px; }
.res-list h2 { margin: 4px 0 6px; font-size: 13px; font-weight: 600; color: var(--muted-foreground); }
.res-list h2 + ul + h2 { margin-top: 16px; }
.res-list ul, .res-deleted ul { margin: 0; padding: 0; list-style: none; }
.res-row { display: flex; align-items: center; gap: 12px; min-height: 56px; border-top: 1px solid var(--border); }
.res-list ul .res-row:first-child { border-top: 0; }
.res-tag { flex: none; display: grid; place-items: center; width: 44px; height: 32px; border-radius: 6px; background: var(--secondary); color: var(--muted-foreground); font-size: 11px; font-weight: 600; letter-spacing: .04em; }
.res-tag.is-link { background: var(--accent); color: var(--primary); }
.res-main { flex: 1; min-width: 0; display: grid; }
.res-main a, .res-main span { overflow: hidden; color: var(--foreground); font-weight: 600; text-overflow: ellipsis; white-space: nowrap; text-decoration: none; }
.res-main a:hover { color: var(--primary); }
.res-main small { color: var(--muted-foreground); font-size: 12.5px; }
.res-pinned { flex: none; border-radius: 999px; background: var(--accent); padding: 1px 9px; color: var(--primary); font-size: 12px; font-weight: 600; }
.res-edit { flex: 1; display: grid; gap: 10px; padding: 12px 0; }
.res-deleted { margin-top: 14px; }
.res-deleted > summary { cursor: pointer; font-weight: 600; }
@media (max-width: 760px) { .res-pinned { display: none; } }
/* A group's Marketplace: the grid, a listing, its form, and its card in
   the Feed. GROUP-006, patch 640. */
.market-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.market-search { margin: 0 0 10px; }
.market-search input { width: 100%; max-width: 420px; }
.market-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.market-chips .feed-chip { text-decoration: none; }
.market-none { margin: 24px 0; }
.market-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 12px; }
.market-card { display: grid; overflow: hidden; padding: 0; color: var(--foreground); text-decoration: none; }
.market-card:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); }
.market-card.is-done .market-pic img { opacity: .55; }
.market-pic { position: relative; display: grid; place-items: center; aspect-ratio: 4 / 3; background: var(--secondary); color: var(--muted-foreground); font-size: 13px; font-weight: 600; }
.market-pic img { width: 100%; height: 100%; object-fit: cover; }
.market-icon { font-size: 34px; opacity: .7; }
.market-badges { position: absolute; top: 8px; left: 8px; display: flex; flex-wrap: wrap; gap: 4px; }
.market-kind, .market-status { border-radius: 999px; background: var(--card); padding: 1px 8px; color: var(--foreground); font-size: 11.5px; font-weight: 600; box-shadow: 0 1px 2px rgba(19, 34, 38, .12); }
.market-kind.is-selling { color: var(--primary); }
.market-kind.is-giving { color: #047857; }
.market-kind.is-looking { color: #b45309; }
.market-status { background: #fef3c7; color: #92400e; }
.market-status.is-available { background: #d1fae5; color: #065f46; }
.market-text { display: grid; gap: 2px; padding: 10px 12px 12px; min-width: 0; }
.market-text b { font-size: 15px; font-weight: 600; }
.market-text strong { overflow: hidden; font-weight: 500; text-overflow: ellipsis; white-space: nowrap; }
.market-text small { overflow: hidden; color: var(--muted-foreground); font-size: 12.5px; text-overflow: ellipsis; white-space: nowrap; }
.market-reported { display: grid; gap: 10px; margin-bottom: 14px; padding: 14px 16px; border-color: #fcd34d; }
.market-reported h2 { margin: 0; font-size: 15px; font-weight: 600; }
.market-reported-row { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 10px; border-top: 1px solid var(--border); padding-top: 10px; }
.market-reported-what { display: grid; gap: 2px; min-width: 0; }
.market-reported-what a { font-weight: 600; }
.market-reported-what small { color: var(--muted-foreground); }
.market-reported-what ul { margin: 4px 0 0; padding-left: 18px; font-size: 13px; }
.market-reported-acts { display: flex; gap: 8px; }
.market-reported-acts .is-danger { background: var(--destructive); color: #fff; }
.listing { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 14px; align-items: start; }
.listing-pics { display: grid; gap: 8px; padding: 10px; }
.listing-pics.is-empty { place-items: center; aspect-ratio: 4 / 3; background: var(--secondary); color: var(--muted-foreground); font-weight: 600; }
.listing-main-pic { display: block; }
.listing-reason { display: flex; align-items: center; gap: 8px; }
.listing-main-pic img { display: block; width: 100%; max-height: 520px; border-radius: 8px; object-fit: contain; background: var(--secondary); }
.listing-thumbs { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; }
.listing-thumbs img { display: block; width: 100%; aspect-ratio: 1; border-radius: 6px; object-fit: cover; }
.listing-info { display: grid; gap: 8px; padding: 16px; }
.listing-tags { display: flex; align-items: center; gap: 6px; }
.listing-more { margin-left: auto; }
.listing-tags .market-kind, .listing-tags .market-status { box-shadow: none; border: 1px solid var(--border); }
.listing-title { margin: 0; font-size: 22px; font-weight: 600; }
.listing-price-text { margin: 0; font-size: 20px; font-weight: 600; }
.listing-when, .listing-taken { margin: 0; font-size: 13px; }
.listing-words { line-height: 1.5; }
.listing-tag-words { margin: 0; color: var(--primary); font-size: 13px; }
.listing-who { display: flex; align-items: center; gap: 10px; border-top: 1px solid var(--border); padding-top: 10px; }
.listing-who strong { font-weight: 600; }
.listing-interest { margin: 4px 0 0; }
.listing-interest button { min-width: 160px; }
.listing-interest .is-on { background: var(--accent); color: var(--primary); }
.listing-interested { margin: 0; font-size: 13.5px; }
.listing-taken-form, .listing-report { display: grid; gap: 10px; border: 1px solid var(--border); border-radius: 10px; padding: 12px; }
.listing-taken-form label, .listing-report > label { display: grid; gap: 6px; font-size: 13px; font-weight: 600; }
.listing-report .listing-reason { display: flex; align-items: center; gap: 8px; min-height: 36px; font-weight: 400; }
.listing-reason input { width: auto; margin: 0; }
.listing-form { display: grid; gap: 14px; }
.listing-kinds { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.listing-kind { position: relative; display: grid; gap: 4px; align-content: start; min-width: 0; border: 1.5px solid var(--border); border-radius: 12px; background: var(--card); padding: 12px 34px 12px 12px; cursor: pointer; }
.listing-kind input { position: absolute; opacity: 0; pointer-events: none; }
.listing-kind strong { font-size: 14px; font-weight: 600; }
.listing-kind small { color: var(--muted-foreground); font-size: 12.5px; font-weight: 400; line-height: 1.35; }
.listing-tick { position: absolute; top: 10px; right: 10px; width: 18px; height: 18px; border: 2px solid var(--border); border-radius: 50%; }
.listing-kind:has(input:checked) { border-color: var(--primary); background: var(--accent); }
.listing-kind:has(input:checked) .listing-tick { border-color: var(--primary); background: var(--primary); box-shadow: inset 0 0 0 3px var(--card); }
.listing-kind:has(input:focus-visible) { outline: 2px solid var(--primary); outline-offset: 2px; }
.listing-price { display: grid; }
.listing-form:has([name="kind"][value="giving"]:checked) .listing-price { display: none; }
.listing-keep { display: flex; flex-wrap: wrap; gap: 8px; }
.listing-keep-photo { display: grid; gap: 4px; width: 92px; font-size: 12px; font-weight: 400; }
.listing-keep-photo img { width: 92px; height: 92px; border-radius: 8px; object-fit: cover; }
.listing-keep-photo input { width: auto; margin: 0; }
.listing-rules { border-radius: 10px; background: var(--secondary); padding: 10px 12px; font-size: 13px; }
.listing-rules strong { font-weight: 600; }
.listing-rules ul { margin: 6px 0 0; padding-left: 18px; color: var(--muted-foreground); }
.listing-card { display: flex; align-items: center; gap: 12px; margin-top: 8px; border: 1px solid var(--border); border-radius: 12px; background: var(--card); padding: 8px; color: var(--foreground); text-decoration: none; }
.listing-card:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); }
.listing-card-pic { display: grid; flex: none; place-items: center; overflow: hidden; width: 64px; height: 64px; border-radius: 8px; background: var(--secondary); color: var(--muted-foreground); font-size: 10.5px; font-weight: 600; text-align: center; }
.listing-card-pic.is-empty { font-size: 26px; }
.listing-card-pic img { width: 100%; height: 100%; object-fit: cover; }
.listing-card-text { display: grid; gap: 1px; min-width: 0; }
.listing-card-text small { color: var(--muted-foreground); font-size: 12px; }
.listing-card-text strong { overflow: hidden; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.listing-card-text span { font-weight: 600; }
@media (max-width: 760px) {
  .listing { grid-template-columns: minmax(0, 1fr); }
  .market-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .listing-kinds { grid-template-columns: minmax(0, 1fr); }
  .listing-kind { padding: 10px 34px 10px 12px; }
}
/* A group's public page and Discover groups, open to anyone. GROUP-007,
   patch 646. */
.pub-page { align-self: start; display: grid; gap: 16px; width: min(1040px, 100%); }
.pub-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.pub-brand { color: var(--foreground); font-size: 17px; font-weight: 600; text-decoration: none; }
.pub-gap { flex: 1; }
.pub-head { overflow: hidden; padding: 0; }
.pub-cover { height: 180px; background: linear-gradient(135deg, #86efac 0%, #16a34a 40%, #0c4a6e 100%) center / cover no-repeat; }
.pub-info { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 14px; margin-top: -36px; padding: 0 18px 16px; }
.pub-pic { display: grid; place-items: center; flex: none; width: 76px; height: 76px; border: 4px solid var(--card); border-radius: 16px; background: var(--secondary); object-fit: cover; }
.pub-pic.is-letters { background: linear-gradient(135deg, #0ea5e9, #0f766e); color: #fff; font-size: 26px; font-weight: 600; }
.pub-name { flex: 1; min-width: 200px; padding-top: 40px; }
.pub-name h1 { margin: 0; font-size: 24px; font-weight: 600; }
.pub-name p { margin: 2px 0 0; color: var(--muted-foreground); font-size: 13.5px; }
.pub-cols { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 16px; align-items: start; }
.pub-posts { display: grid; gap: 4px; padding: 16px; }
.pub-note { margin: 0 0 6px; border-radius: 10px; background: var(--secondary); padding: 10px 12px; color: var(--muted-foreground); font-size: 13px; }
.pub-post { display: grid; grid-template-columns: 32px minmax(0, 1fr); gap: 10px; border-top: 1px solid var(--border); padding: 12px 0; }
.pub-post:first-of-type { border-top: 0; }
.pub-post-main { min-width: 0; }
.pub-who { font-size: 13.5px; }
.pub-who strong { font-weight: 600; }
.pub-who time { color: var(--muted-foreground); font-size: 12.5px; }
.pub-count { margin: 8px 0 0; color: var(--muted-foreground); font-size: 13px; }
.pub-side { display: grid; gap: 16px; }
.pub-side .card { padding: 16px; }
.pub-side h2 { margin: 0 0 8px; font-size: 15px; font-weight: 600; }
.pub-side p { margin: 0 0 6px; font-size: 13.5px; }
.pub-ask { scroll-margin-top: 16px; }
.pub-ask-form { display: grid; gap: 10px; }
.pub-ask-form label { display: grid; gap: 6px; font-size: 13px; font-weight: 600; }
.pub-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.pub-missing { justify-self: center; display: grid; gap: 8px; max-width: 420px; padding: 24px; text-align: center; }
.pub-missing h1 { margin: 0; font-size: 22px; font-weight: 600; }
.disc-title { margin: 4px 0 0; font-size: 26px; font-weight: 600; }
.disc-search { margin: 0; }
.disc-search input { width: 100%; max-width: 480px; }
.disc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; }
.disc-card { display: grid; overflow: hidden; padding: 0; color: var(--foreground); text-decoration: none; }
.disc-card:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); }
.disc-cover { display: block; height: 90px; background: linear-gradient(135deg, #86efac 0%, #16a34a 40%, #0c4a6e 100%) center / cover no-repeat; }
.disc-info { display: grid; gap: 4px; margin-top: -24px; padding: 0 12px 12px; }
.disc-pic { display: grid; place-items: center; width: 48px; height: 48px; border: 3px solid var(--card); border-radius: 12px; background: var(--secondary); object-fit: cover; }
.disc-pic.is-letters { background: linear-gradient(135deg, #0ea5e9, #0f766e); color: #fff; font-size: 16px; font-weight: 600; }
.disc-info strong { margin-top: 2px; font-weight: 600; }
.disc-info small { color: var(--muted-foreground); font-size: 12.5px; line-height: 1.35; }
.disc-view { justify-content: center; margin-top: 6px; }
.group-address { display: flex; align-items: stretch; overflow: hidden; border: 1px solid var(--border); border-radius: 8px; background: var(--card); font-weight: 400; }
.group-address > span { display: flex; align-items: center; background: var(--secondary); padding: 0 10px; color: var(--muted-foreground); font-size: 13px; white-space: nowrap; }
.group-address input { flex: 1; min-width: 0; border: 0; border-radius: 0; }
.group-address-open { margin: -6px 0 0; font-size: 13px; }
.group-asks { margin: 0 0 14px; border: 1px solid #fcd34d; border-radius: 10px; padding: 12px; }
.group-asks h2 { margin: 0 0 6px; font-size: 15px; font-weight: 600; }
.group-asks ul { margin: 0; padding: 0; list-style: none; }
.group-asks li { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; border-top: 1px solid var(--border); padding: 10px 0; }
.group-asks li:first-child { border-top: 0; }
.group-asks p { margin: 4px 0 0; font-size: 13px; }
.group-ask-acts { display: flex; gap: 8px; margin: 0; }
.feed-public { margin-left: 6px; border-radius: 999px; background: var(--accent); padding: 0 8px; color: var(--primary); font-size: 11.5px; font-weight: 600; }
/* Its own width, at the right beside Post; the post box's wider rule for a
   select stretched it. Found in the patch 646 test. */
.feed-audience { width: auto; }
.feed-compose-row .feed-audience { flex: 0 0 auto; width: auto; min-height: 36px; margin-left: auto; }
@media (max-width: 760px) {
  .pub-cols { grid-template-columns: minmax(0, 1fr); }
  .pub-cover { height: 120px; }
  .pub-name { flex-basis: 100%; padding-top: 4px; }
  .pub-info .button { width: 100%; justify-content: center; }
}
/* The Links card on a project's Overview. PROJECT-006, patch 648. */
.ov-links { margin: 0; padding: 0; list-style: none; }
.ov-linkrow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-height: 40px; border-top: 1px solid var(--border); }
.ov-linkrow:first-child { border-top: 0; }
.ov-linkrow.is-dragging { opacity: .45; }
.ov-linkgrip { color: var(--muted-foreground); font-size: 12px; letter-spacing: -2px; cursor: grab; user-select: none; }
.ov-linkname { flex: 1; min-width: 0; overflow: hidden; color: var(--primary); font-weight: 600; text-decoration: none; text-overflow: ellipsis; white-space: nowrap; }
.ov-linkname:hover { text-decoration: underline; }
.ov-linkedit { margin-left: auto; }
.ov-linkedit > summary { list-style: none; cursor: pointer; }
.ov-linkedit > summary::-webkit-details-marker { display: none; }
.ov-linkedit[open] { flex-basis: 100%; order: 3; padding-bottom: 10px; }
.ov-linkform { display: grid; gap: 8px; }
.ov-linkform label { display: grid; gap: 4px; font-size: 12.5px; font-weight: 600; }
.ov-linkform .ov-form-row { flex-wrap: wrap; }
.ov-linkadd { display: flex; flex-wrap: wrap; gap: 6px; }
.ov-linkadd input { flex: 1 1 140px; min-width: 0; }
@media (hover: none) { .ov-linkgrip { display: none; } }
/* Your home. NAV-009, patch 651. */
.home-compose { margin: 0; grid-template-columns: minmax(0, 1fr); min-width: 0; }
.home-compose .feed-audience, .home-compose textarea { max-width: 100%; }
.home-nav { display: grid; grid-template-columns: minmax(0, 1fr); min-width: 0; }
.home-nav-list { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1px; min-width: 0; }
.home-cols { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: 16px; align-items: start; }
/* With the menu back beside the rail, a smaller computer screen left the
   Feed under 200px wide; Coming up goes above it there, as on a phone.
   NAV-009, patch 658. */
@media (max-width: 1100px) {
  .home-cols { grid-template-columns: minmax(0, 1fr); }
  .home-side { order: -1; }
}
.home-feed { padding: 16px; }
.home-feed .feed-list { margin-top: 8px; }
.home-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0 0; }
/* On a computer the menu does the chips' job; a phone keeps them. After the
   rule above, which outranked it in patch 657. */
@media (min-width: 761px) { .home-chips { display: none; } }
.home-postto { display: flex; align-items: center; gap: 6px; margin-left: auto; color: var(--muted-foreground); font-size: 12.5px; font-weight: 600; }
.home-compose .feed-compose-row .feed-audience { margin-left: 0; }
.home-compose [data-home-audience][hidden] { display: none; }
.home-compose [data-home-subgroup][hidden] { display: none; }
/* The subgroup choice sits beside Group or Public, at the end of the row.
   Found in the patch 664 test. */
.feed-compose-row:has(#feed-subgroup) #feed-audience { margin-left: 0; }
/* The words stay together beside the picker. Found in the patch 655 test. */
.home-postto { white-space: nowrap; }
/* The post box's own width decides the row, as on a phone: a narrow box puts
   Post to on a line of its own; a wide one keeps Photo, Post to, Group or
   Public and Post on one line, Post to giving way. Found in the patch 653 and
   654 tests. NAV-009, patches 654 and 655. */
.home-compose { container-type: inline-size; }
.home-compose .feed-compose-row > * { flex-shrink: 0; }
.home-compose .feed-compose-row > .home-postto { flex: 1 1 100%; min-width: 0; margin-left: 0; }
.home-postto .feed-audience { flex: 1 1 auto; min-width: 0; max-width: 100%; }
/* 560 since a subgroup choice can join the row. Patch 664. */
@container (min-width: 560px) {
  .home-compose .feed-compose-row { flex-wrap: nowrap; }
  .home-compose .feed-compose-row > .home-postto { flex: 0 1 auto; margin-left: auto; }
}
.home-empty { display: grid; gap: 8px; }
.home-empty p { margin: 0; }
.home-side { display: grid; gap: 16px; }
.home-coming { padding: 14px 16px; }
.home-coming h2 { margin: 0 0 8px; font-size: 15px; font-weight: 600; }
.home-coming ul { margin: 0; padding: 0; list-style: none; }
.home-coming li a { display: flex; align-items: center; gap: 10px; padding: 6px 0; color: var(--foreground); text-decoration: none; }
.home-coming-text { display: grid; min-width: 0; }
.home-coming-text strong { overflow: hidden; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.home-coming-text small { color: var(--muted-foreground); font-size: 12px; }
.feed-where { margin-left: 6px; color: var(--muted-foreground); font-size: 12px; text-decoration: none; }
.feed-where b { color: var(--foreground); font-weight: 600; }
.feed-where:hover b { text-decoration: underline; }
.home-nav-row { display: flex; align-items: center; gap: 4px; min-width: 0; }
.home-nav-row.is-dragging { opacity: .45; }
.home-nav-go { flex: 1; min-width: 0; margin: 0; }
.home-nav-link { overflow: hidden; display: flex; align-items: center; gap: 8px; width: 100%; min-height: 36px; border: 0; border-radius: 8px; background: transparent; padding: 0 8px; color: var(--foreground); font: inherit; font-size: 13.5px; font-weight: 500; text-align: left; box-shadow: none; cursor: pointer; }
.home-nav-link:hover { background: var(--secondary); }
.home-nav-pic { display: grid; place-items: center; flex: none; width: 24px; height: 24px; border-radius: 7px; background: linear-gradient(135deg, #0ea5e9, #0f766e); color: #fff; font-size: 10px; font-weight: 600; object-fit: cover; }
.home-nav-pic.is-personal { background: linear-gradient(135deg, #a855f7, #be185d); }
.home-nav-pic.is-work { background: linear-gradient(135deg, #64748b, #334155); }
.home-nav-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.home-nav-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--primary); }
.home-nav-edit { min-height: 0; border: 0; background: none; padding: 0; color: var(--primary); font-size: 11.5px; font-weight: 600; box-shadow: none; cursor: pointer; text-transform: none; letter-spacing: 0; }
.home-nav-move { display: inline-flex; flex: none; gap: 2px; }
/* Only while Edit is on. Found in the patch 651 test. */
.home-nav-move[hidden] { display: none; }
.home-nav-move button { min-width: 28px; min-height: 28px; border: 1px solid var(--border); border-radius: 6px; background: var(--card); padding: 0; color: var(--foreground); box-shadow: none; }
.home-nav.is-editing .home-nav-row { cursor: grab; }
.home-strip { display: none; }
@media (max-width: 760px) {
  .home-cols { grid-template-columns: minmax(0, 1fr); }
  .home-side { order: -1; }
  .home-strip { display: flex; gap: 10px; overflow-x: auto; margin: 0 -2px 12px; padding: 2px 2px 6px; scrollbar-width: none; }
  .home-strip-go { flex: none; margin: 0; }
  .home-strip button { display: grid; justify-items: center; gap: 4px; width: 68px; border: 0; background: none; padding: 0; color: var(--foreground); font-size: 11px; font-weight: 500; box-shadow: none; }
  .home-strip button span:last-child { display: -webkit-box; width: 100%; overflow: hidden; white-space: normal; overflow-wrap: anywhere; -webkit-box-orient: vertical; -webkit-line-clamp: 2; text-align: center; }
  .home-compose textarea { width: 100%; box-sizing: border-box; }
  .home-compose .feed-compose-row { flex-wrap: wrap; }
  .home-postto { flex: 1 1 100%; min-width: 0; }
  .home-postto .feed-audience { flex: 1; min-width: 0; max-width: 100%; }
  .home-feed { min-width: 0; overflow: hidden; }
  .home-strip .home-nav-pic { width: 52px; height: 52px; border-radius: 16px; font-size: 16px; }
  .home-postto { margin-left: 0; }
}
/* Welcome: someone in no group, with no other workspace. GROUP-004, patch 637. */
.welcome-panel { width: min(560px, 100%); margin: 48px auto; padding: 0 16px; display: grid; gap: 14px; }
.welcome-panel h1 { margin: 0; font-size: 26px; font-weight: 600; }
.welcome-choices { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; }
.welcome-choice { display: grid; gap: 6px; align-content: start; margin: 0; border: 1.5px solid var(--border); border-radius: 12px; background: var(--card); padding: 16px; }
.welcome-ic { display: inline-grid; color: var(--primary); font-size: 24px; line-height: 1; }
.welcome-choice small { color: var(--muted-foreground); font-size: 13px; line-height: 1.4; }
.welcome-choice .button, .welcome-choice button { justify-self: start; margin-top: 6px; }
.welcome-signout { justify-self: center; margin: 0; }
@media (max-width: 520px) { .welcome-choices { grid-template-columns: minmax(0, 1fr); } }

/* A group's event as a card, its calendar and its page. GROUP-003, patch 636. */
.event-card { display: flex; align-items: center; gap: 12px; margin-top: 8px; border: 1px solid var(--border); border-radius: 12px; background: var(--card); padding: 10px 12px; color: var(--foreground); text-decoration: none; }
.event-card:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); }
.event-date { display: grid; flex: none; place-items: center; width: 46px; height: 50px; border-radius: 10px; background: var(--accent); color: var(--primary); line-height: 1.05; }
.event-date small { font-size: 10.5px; font-weight: 600; letter-spacing: .05em; }
.event-date b { font-size: 19px; font-weight: 600; }
.event-text { display: grid; gap: 2px; min-width: 0; }
.event-text strong { font-weight: 600; }
.event-text > span { color: var(--muted-foreground); font-size: 12.5px; }
.event-card.is-canceled strong { text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--foreground) 45%, transparent); }
.event-tag { display: inline-block; margin-left: 6px; border-radius: 999px; background: #fef3c7; padding: 0 8px; color: #92400e; font-size: 11px; font-weight: 600; text-decoration: none; vertical-align: 1px; }
.event-tag.is-canceled { background: color-mix(in srgb, var(--destructive) 12%, var(--card)); color: var(--destructive); }
.group-cal-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.group-waiting h2, .group-event-side h2 { margin: 0 0 8px; font-size: 15px; font-weight: 600; }
.group-waiting-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.group-waiting-row .event-card { flex: 1 1 260px; }
.group-waiting-acts { display: flex; gap: 8px; margin-top: 8px; }
.group-cal { padding: 0; overflow: hidden; }
.group-cal-bar { display: flex; align-items: center; gap: 8px; border-bottom: 1px solid var(--border); padding: 10px 12px; }
.group-cal-bar strong { flex: 1; font-size: 16px; font-weight: 600; }
.group-cal-bar strong { order: -1; }
.group-cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.group-cal-dow { border-bottom: 1px solid var(--border); padding: 6px 8px; color: var(--muted-foreground); font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; }
.group-cal-day { min-width: 0; min-height: 100px; border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); padding: 6px; }
.group-cal-day:nth-child(7n) { border-right: 0; }
.group-cal-day.is-out { background: color-mix(in srgb, var(--secondary) 45%, var(--card)); }
.group-cal-num { display: inline-grid; place-items: center; width: 24px; height: 24px; border-radius: 50%; color: var(--muted-foreground); font-size: 12px; text-decoration: none; }
.group-cal-num:hover { background: var(--secondary); color: var(--foreground); }
.group-cal-day.is-today .group-cal-num { background: var(--primary); color: #ffffff; font-weight: 600; }
.group-cal-ev { display: block; overflow: hidden; margin-top: 4px; border-radius: 6px; background: var(--accent); padding: 3px 6px; color: var(--primary); font-size: 11.5px; font-weight: 600; text-decoration: none; text-overflow: ellipsis; white-space: nowrap; }
.group-cal-ev.is-waiting { background: #fef3c7; color: #92400e; }
.group-cal-ev.is-canceled, .group-cal-ev.is-declined { background: var(--secondary); color: var(--muted-foreground); text-decoration: line-through; }
.group-cal-list { display: none; padding: 0 12px 14px; }
.group-cal-listday { margin: 14px 0 0; color: var(--muted-foreground); font-size: 11.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; }
.group-back { margin: 0 0 10px; font-size: 13px; }
.group-event { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: 16px; align-items: start; }
.group-event-title { margin: 0 0 10px; font-size: 22px; font-weight: 600; }
.group-event-facts { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; margin: 0 0 12px; font-size: 14px; }
.group-event-facts dt { color: var(--muted-foreground); }
.group-event-facts dd { margin: 0; }
/* An event's own small map, the card's full width. Patch 825. */
.event-map { display: block; height: 160px; margin: 0 0 12px; border-radius: 6px; overflow: hidden; background: #eef2e6; cursor: pointer; }
.group-event-note { margin-bottom: 12px; }
.group-going { display: flex; gap: 8px; margin: 12px 0; }
.group-going button { flex: 1; min-height: 44px; }
.group-going button.is-on { background: var(--primary); border-color: var(--primary); color: #ffffff; }
.group-going button.is-on-quiet { border-color: var(--foreground); color: var(--foreground); }
.group-event-acts { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0; }
.group-event-acts form { margin: 0; }
.group-event-thread { margin-top: 12px; border-top: 1px solid var(--border); padding-top: 4px; }
.group-event-two { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.group-event-two label { display: grid; gap: 6px; font-size: 13px; font-weight: 600; }
.group-spots { height: 8px; overflow: hidden; margin: 6px 0 8px; border-radius: 99px; background: var(--secondary); }
.group-spots i { display: block; height: 100%; border-radius: 99px; background: var(--primary); }
.group-event-side h3 { margin: 14px 0 4px; color: var(--muted-foreground); font-size: 12px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }
.group-people { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; font-size: 13.5px; }
.group-people li { display: flex; align-items: center; gap: 8px; }
.group-photos { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 10px; }
.group-photo { position: relative; display: block; overflow: hidden; border-radius: 10px; aspect-ratio: 1; background: var(--secondary); }
.group-photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
.group-photo span { position: absolute; right: 0; bottom: 0; left: 0; overflow: hidden; background: linear-gradient(transparent, rgba(0, 0, 0, .55)); padding: 16px 8px 6px; color: #ffffff; font-size: 11.5px; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 760px) {
  .group-cal-grid { display: none; }
  .group-cal-list { display: block; }
  .group-event { grid-template-columns: 1fr; }
  .group-event-two { grid-template-columns: 1fr; }
  .group-photos { grid-template-columns: repeat(2, 1fr); gap: 6px; }
}

/* A group's subgroups. GROUP-001, patch 663. */
.sub-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.sub-label { margin: 18px 0 8px; color: var(--muted-foreground); font-size: 12px; font-weight: 600; }
.sub-list { display: grid; gap: 10px; }
.sub-card { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: start; gap: 12px; padding: 14px 16px; }
.sub-swatch { width: 12px; height: 12px; margin-top: 4px; border-radius: 4px; }
.sub-main { display: grid; gap: 2px; min-width: 0; }
.sub-main strong { font-weight: 600; }
.sub-main small { color: var(--muted-foreground); font-size: 12.5px; }
.sub-main p { margin: 4px 0 0; font-size: 13px; }
.sub-faces { display: flex; align-items: center; margin-top: 6px; }
.sub-faces .feed-av { margin-right: -4px; border: 2px solid var(--card); }
.sub-more { margin-left: 8px; color: var(--muted-foreground); font-size: 12px; }
.sub-acts { display: flex; align-items: center; gap: 4px; }
.sub-acts form { margin: 0; }
.sub-joined { min-width: 96px; color: var(--primary); }
.sub-out { display: none; }
.sub-in { display: inline; }
@media (hover: hover) {
  .sub-joined:hover .sub-in { display: none; }
  .sub-joined:hover .sub-out { display: inline; }
}
.sub-none { margin-top: 12px; }
.sub-form-acts { display: flex; justify-content: flex-end; gap: 8px; }
.sub-form { display: grid; gap: 12px; max-width: 560px; margin: 0 0 16px; padding: 16px; }
.sub-form h2 { margin: 0; font-size: 16px; font-weight: 600; }
.sub-form fieldset { display: grid; gap: 8px; margin: 0; border: 0; padding: 0; }
.sub-form legend { margin: 0 0 4px; padding: 0; font-size: 13px; font-weight: 600; }
.sub-place-kinds { display: flex; flex-wrap: wrap; gap: 8px 14px; }
.sub-place-kinds label { display: inline-flex; align-items: center; gap: 6px; font-weight: 500; white-space: nowrap; }
/* A radio at its own size, beside its words: the form's input width made
   each one 86px in the patch 663 test. */
.sub-place-kinds input, .subgroups-yesno input { flex: none; width: auto; min-width: 0; min-height: 0; margin: 0; }
.sub-miles { display: grid; grid-template-columns: 110px minmax(0, 1fr); gap: 10px; }
.sub-miles[hidden], .sub-form [data-sub-kind][hidden] { display: none; }
.sub-colors { display: flex !important; flex-wrap: wrap; gap: 10px; }
.sub-colors legend { width: 100%; }
.sub-colors label { position: relative; display: inline-grid; cursor: pointer; }
.sub-colors input { position: absolute; opacity: 0; }
.sub-colors span { width: 26px; height: 26px; border-radius: 8px; }
.sub-colors input:checked + span { outline: 2px solid var(--foreground); outline-offset: 2px; }
.sub-colors input:focus-visible + span { outline: 2px solid var(--primary); outline-offset: 2px; }
/* Subgroups and their word, on Start a group and in Group settings. */
.subgroups-word { display: grid; gap: 10px; }
.subgroups-yesno { display: flex; flex-wrap: wrap; gap: 8px 16px; margin: 0; border: 0; padding: 0; }
.subgroups-yesno legend { width: 100%; margin: 0 0 4px; padding: 0; font-weight: 600; }
.subgroups-yesno label { display: inline-flex; align-items: center; gap: 6px; font-weight: 500; white-space: nowrap; }
.subgroups-more { display: grid; gap: 10px; }
.subgroups-more[hidden], .subgroups-own[hidden] { display: none; }
.subgroups-own { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
@media (max-width: 760px) {
  .sub-card { grid-template-columns: auto minmax(0, 1fr); }
  .sub-acts { grid-column: 1 / -1; }
  .sub-acts form:first-child { flex: 1; }
  .sub-acts form:first-child button { width: 100%; min-height: 44px; }
  .subgroups-own { grid-template-columns: 1fr; }
}
/* A post's subgroup, and the Feed's subgroup filter. GROUP-001, patch 664. */
.feed-sub { display: inline-flex; align-items: center; gap: 4px; margin-left: 6px; color: var(--muted-foreground); font-size: 12px; text-decoration: none; }
.feed-sub i { width: 9px; height: 9px; border-radius: 3px; }
.feed-sub:hover { color: var(--foreground); }
.feed-sub-pick { position: relative; display: inline-block; }
.feed-sub-pick > summary { list-style: none; cursor: pointer; }
.feed-sub-pick > summary::-webkit-details-marker { display: none; }
.feed-sub-menu { position: absolute; top: calc(100% + 6px); left: 0; z-index: 30; display: grid; gap: 2px; min-width: 220px; border: 1px solid var(--border); border-radius: 10px; background: var(--card); padding: 6px; box-shadow: 0 8px 24px rgba(0, 0, 0, .12); }
.feed-sub-head { margin: 4px 8px 2px; color: var(--muted-foreground); font-size: 11px; font-weight: 600; }
.feed-sub-menu a { display: flex; align-items: center; gap: 8px; min-height: 36px; border-radius: 7px; padding: 0 8px; color: var(--foreground); font-size: 13px; text-decoration: none; }
.feed-sub-menu a:hover { background: var(--secondary); }
.feed-sub-menu a[aria-current="true"] { background: color-mix(in srgb, var(--primary) 10%, var(--card)); color: var(--primary); font-weight: 600; }
.feed-sub-menu a i { width: 10px; height: 10px; border-radius: 3px; }
.feed-sub-all { color: var(--muted-foreground); }
.feed-sub-menu a.feed-sub-all { color: var(--muted-foreground); }
/* Subgroups on Calendar, Marketplace and Members. GROUP-001, patch 666. */
.sub-filter-row { margin: 0 0 12px; }
.member-subs { display: flex; flex-wrap: wrap; gap: 2px 10px; margin-top: 2px; }
.member-subs .feed-sub { margin-left: 0; }
.market-sub { margin: 2px 0 0; }
.member-sub-add { display: flex; gap: 6px; padding: 6px 8px; }
.member-sub-add select { flex: 1 1 auto; width: auto; min-width: 120px; min-height: 32px; }
/* Add at its own size: the menu's full-width buttons left the select 22px
   in the patch 666 test. */
.member-sub-add button { flex: none; width: auto; min-height: 32px; padding: 0 10px; }
.subgroup-pick { display: grid; gap: 4px; }

/* Every place the shared post list shows carries feed-surface (the Feed
   page, Your home, the Dashboard's Feed box), so its look is set once.
   Patch 679. */
.feed-surface { min-width: 0; }

/* Phone design, part 2: posts and photos. No box around the Feed or a post;
   each post on white with a thin gray band between; photos edge to edge of
   the screen; Like and Comment as plain icons; chips tinted in one row; the
   post box one line until it is tapped. Sarah, 2026-10-18: "What I don't
   think we need is all this outline behind every post", "a box inside of a
   box ... looks archaic", "the images should take up the full width";
   docs/mockups/design-review.html screens 2 and 3. UX-035, patch 670. */
@media (max-width: 760px) {
  body.has-phone-shell .feed-page,
  body.has-phone-shell .home-feed { margin: 0 -16px; border: 0; border-radius: 0; background: transparent; padding: 0; box-shadow: none; overflow: visible; }
  body.has-phone-shell .feed-surface .feed-compose { margin: 0; border: 0; border-radius: 0; background: var(--card); padding: 12px 16px 10px; }
  body.has-phone-shell .feed-surface .feed-chips { margin: 0; background: var(--card); padding: 0 16px 12px; }
  body.has-phone-shell .feed-surface .feed-list { margin: 0; }
  body.has-phone-shell .feed-surface .feed-entry { margin: 8px 0 0; border: 0; border-radius: 0; background: var(--card); padding: 12px 16px 6px; }
  body.has-phone-shell .feed-surface .feed-entry + .feed-entry { border-top: 0; }
  body.has-phone-shell .feed-surface .feed-entry.is-team { background: color-mix(in srgb, #f59e0b 8%, var(--card)); }
  body.has-phone-shell .feed-surface .feed-more-button { top: 10px; right: 8px; }
  /* Photos edge to edge: out past the post's padding on both sides. */
  body.has-phone-shell .feed-surface .feed-entry .feed-main > .feed-photos { margin-left: -56px; margin-right: -16px; border-radius: 0; }
  body.has-phone-shell .feed-surface .feed-body { font-size: 15px; }
  body.has-phone-shell .feed-page > .feed-none,
  body.has-phone-shell .feed-page .feed-results > .muted,
  body.has-phone-shell .home-feed [data-home-none] { margin: 12px 16px; }
  /* Like and Comment as plain icons. */
  body.has-phone-shell .react-button,
  body.has-phone-shell .react-summary { min-height: 40px; border: 0; background: none; padding: 0 8px; }
  body.has-phone-shell .react-button:hover,
  body.has-phone-shell .react-summary:hover { background: none; }
  body.has-phone-shell .react-button.is-mine { background: none; color: var(--primary); }
  body.has-phone-shell .react .react-button:first-child { margin-left: -8px; }
  /* Chips: tinted, one row that scrolls sideways. */
  body.has-phone-shell .feed-chips,
  body.has-phone-shell .home-chips { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  body.has-phone-shell .feed-chips::-webkit-scrollbar,
  body.has-phone-shell .home-chips::-webkit-scrollbar { display: none; }
  body.has-phone-shell .feed-chip { flex: none; border: 0; background: var(--secondary); padding: 7px 13px; font-size: 13px; white-space: nowrap; }
  body.has-phone-shell .feed-chip[aria-pressed="true"] { background: var(--foreground); color: var(--card); }
  /* The post box: one tinted line until it is tapped or holds something. */
  body.has-phone-shell .feed-compose textarea { height: 44px; min-height: 44px; border: 0; border-radius: 22px; background: var(--secondary); padding: 11px 16px; font-size: 16px; line-height: 22px; resize: none; transition: height .15s; }
  body.has-phone-shell .feed-compose:focus-within textarea,
  body.has-phone-shell .feed-compose.is-open textarea,
  body.has-phone-shell .feed-compose textarea:not(:placeholder-shown) { height: 96px; border-radius: 14px; }
  /* A plain comment needs no label; notes, photos and the rest keep theirs. */
  body.has-phone-shell .feed-entry .feed-pill.is-plain { display: none; }
  /* An event's card in a post: tinted, no line around it. */
  body.has-phone-shell .feed-entry .event-card { border: 0; background: var(--secondary); }
  body.has-phone-shell .feed-compose:not(:focus-within):not(.is-open):has(textarea:placeholder-shown):not(:has([data-feed-chosen]:not([hidden]))) .feed-compose-row,
  body.has-phone-shell .feed-compose:not(:focus-within):not(.is-open):has(textarea:placeholder-shown):not(:has([data-feed-chosen]:not([hidden]))) .feed-tags { display: none; }
  /* Your spaces at the top of Your home: round pictures. */
  body.has-phone-shell .home-strip .home-nav-pic { width: 48px; height: 48px; border-radius: 50%; font-size: 14px; }
}

/* Phone design, part 3: lists and controls. Cards lose their outline and sit
   white on the gray page; secondary buttons are tinted with no outline and
   44px to tap; boxes inside boxes lose their lines. Sarah, 2026-10-18, the
   design review. UX-035, patch 671. */
@media (max-width: 760px) {
  body.has-phone-shell .card { border-color: transparent; border-radius: 16px; box-shadow: none; }
  body.has-phone-shell .card .card { background: var(--secondary); }
  body.has-phone-shell .secondary-button,
  body.has-phone-shell a.secondary-button { min-height: 44px; border-color: transparent; background: var(--secondary); box-shadow: none; }
  body.has-phone-shell .secondary-button:hover { border-color: transparent; background: color-mix(in srgb, var(--foreground) 10%, var(--secondary)); }
  body.has-phone-shell .secondary-button.is-danger { border-color: transparent; background: color-mix(in srgb, var(--destructive) 10%, var(--card)); }
  /* A group's Feed opens with one thin line, its name and Invite. */
  body.has-phone-shell .group-head.is-on-feed { margin: -16px -16px 0; border: 0; border-radius: 0; }
  body.has-phone-shell .group-head.is-on-feed .group-cover,
  body.has-phone-shell .group-head.is-on-feed .group-pic,
  body.has-phone-shell .group-head.is-on-feed .group-name p { display: none; }
  body.has-phone-shell .group-head.is-on-feed .group-info { display: flex; align-items: center; gap: 12px; margin: 0; padding: 10px 16px; }
  body.has-phone-shell .group-head.is-on-feed .group-name { padding: 0; }
  body.has-phone-shell .group-head.is-on-feed .group-name h1 { overflow: hidden; font-size: 16px; text-overflow: ellipsis; white-space: nowrap; }
  body.has-phone-shell .group-head.is-on-feed .group-info .secondary-button { flex: none; min-height: 44px; margin: 0 0 0 auto; padding: 0 16px; font-size: 14px; }
  /* The top bar already names the group and carries Invite as an icon, so
     the line above its Feed goes. Sarah, 2026-10-21: "not sure we need to
     repeat the header", then "invite could be a little icon in the header".
     MOBILE-009, patches 719 and 720. */
  body.has-phone-shell .group-head.is-on-feed { display: none; }
  body.has-phone-shell .bell-button.invite-link { display: grid; }
  /* The bar along the bottom on a light tint, so it stands apart from the
     page. Sarah, 2026-10-18: "the nav bar at the bottom needs a light color
     so as to make it visible". */
  body.has-phone-shell .phone-bar { border-top-color: color-mix(in srgb, var(--foreground) 12%, transparent); background: color-mix(in srgb, var(--primary) 7%, var(--card)); }
  /* From the patch 670 test: no gray left behind a tapped Like or Comment;
     the + steps aside while comments are open; "in" a space on its own line;
     Post filled. */
  body.has-phone-shell .react-button:focus,
  body.has-phone-shell .react-button:active,
  body.has-phone-shell .react-summary:focus { background: none; box-shadow: none; }
  body:has(.feed-comments:not([hidden])) .phone-fab { display: none; }
  /* On its own line inside the row of name and time: the row wraps, so it
     takes the whole width. Fixed after the patch 671 test. */
  body.has-phone-shell .feed-entry .feed-where { display: block; flex: 0 0 100%; margin: 1px 0 0; }
  /* Tasks and Members: the last outlines. From the 671 test. Patch 672. */
  body.has-phone-shell .table-wrap { border: 0; }
  body.has-phone-shell .filter-button,
  body.has-phone-shell .view-more > summary { min-height: 40px; border-color: transparent; background: var(--secondary); box-shadow: none; }
  body.has-phone-shell .group-invite button { min-height: 44px; border-color: var(--primary); background: var(--primary); color: var(--primary-foreground, #fff); }
  body.has-phone-shell .feed-compose-row button[type="submit"] { border-color: var(--primary); background: var(--primary); color: var(--primary-foreground, #fff); }
}

/* A computer's Feed at the width feeds use: a post column of 580px, about
   Facebook's, and one photo no taller than 560px (70% of a short screen);
   680px and 75% in patch 674 still looked huge. Sarah,
   2026-10-18: "the image is giant on my computer screen so we probably need
   to employ some normal limit (best practice for feeds)". UX-035, patch 674. */
@media (min-width: 761px) {
  .feed-page { max-width: 580px; }
  .home-cols { max-width: 580px; }
  .feed-photos.is-n1 .feed-shot img { max-height: min(125cqw, 70vh, 560px); }
}
@media (min-width: 1101px) {
  .home-cols { max-width: none; grid-template-columns: minmax(0, 580px) 280px; }
}

/* The computer, lighter. Sarah, 2026-10-18: "half height, centered, yes
   lighter cards elsewhere"; docs/mockups/design-review-desktop.html. Cards
   are white without an outline on the gray page (a faint shadow keeps their
   edge); secondary buttons are tinted; the Feed is centered, each post on its
   own white surface with the photo across the whole post, chips tinted, Like
   and Comment plain, the post box one line until clicked; a group's cover at
   half height. Tables keep their lines. UX-035, patch 678. */
@media (min-width: 761px) {
  .card { border-color: transparent; box-shadow: 0 1px 2px rgba(16, 24, 40, .05); }
  .card .card { background: var(--secondary); box-shadow: none; }
  .secondary-button, a.secondary-button { border-color: transparent; background: var(--secondary); box-shadow: none; }
  .secondary-button:hover { border-color: transparent; background: color-mix(in srgb, var(--foreground) 9%, var(--secondary)); }
  .secondary-button.is-danger { border-color: transparent; background: color-mix(in srgb, var(--destructive) 10%, var(--card)); }
  /* Centered: the Feed page, Your home's two columns. */
  .feed-page { margin-left: auto; margin-right: auto; }
  .home-cols { justify-content: center; margin-left: auto; margin-right: auto; }
  /* The Feed: no box around it; each post its own white surface. */
  .feed-page, .home-feed { border: 0; background: transparent; padding: 0; box-shadow: none; overflow: visible; }
  .feed-surface .feed-compose { margin: 0 0 10px; border: 0; border-radius: 16px; background: var(--card); padding: 12px 14px; box-shadow: 0 1px 2px rgba(16, 24, 40, .05); }
  .feed-surface .feed-chips { margin: 0 0 4px; }
  .feed-surface .feed-entry { margin: 12px 0 0; border: 0; border-radius: 16px; background: var(--card); padding: 14px 16px 8px; overflow: hidden; box-shadow: 0 1px 2px rgba(16, 24, 40, .05); }
  .feed-surface .feed-entry + .feed-entry { border-top: 0; }
  .feed-surface .feed-entry.is-team { background: color-mix(in srgb, #f59e0b 8%, var(--card)); margin: 12px 0 0; }
  .feed-surface .feed-entry .feed-main > .feed-photos { margin-left: -56px; margin-right: -16px; border-radius: 0; }
  .feed-surface .feed-more-button { top: 10px; right: 8px; }
  .feed-page > .feed-results > .muted, .home-feed [data-home-none] { margin: 12px 4px; }
  .feed-surface .feed-body { font-size: 15px; }
  .feed-chip { border: 0; background: color-mix(in srgb, var(--foreground) 6%, var(--secondary)); padding: 6px 12px; font-size: 13px; }
  .feed-chip[aria-pressed="true"] { background: var(--foreground); color: var(--card); }
  .react-button, .react-summary { border: 0; background: none; }
  .react-button:hover, .react-summary:hover, .react-button:focus { background: var(--secondary); }
  .react-button.is-mine { background: none; color: var(--primary); }
  .react .react-button:first-child { margin-left: -8px; }
  /* The post box: one tinted line until clicked or holding something. */
  .feed-compose textarea { height: 42px; min-height: 42px; border: 0; border-radius: 21px; background: var(--secondary); padding: 10px 16px; line-height: 22px; resize: none; }
  .feed-compose:focus-within textarea, .feed-compose.is-open textarea, .feed-compose textarea:not(:placeholder-shown) { height: 96px; border-radius: 14px; }
  .feed-compose:not(:focus-within):not(.is-open):has(textarea:placeholder-shown):not(:has([data-feed-chosen]:not([hidden]))) .feed-compose-row,
  .feed-compose:not(:focus-within):not(.is-open):has(textarea:placeholder-shown):not(:has([data-feed-chosen]:not([hidden]))) .feed-tags { display: none; }
  .feed-compose-row button[type="submit"] { border-color: var(--primary); background: var(--primary); color: var(--primary-foreground, #fff); }
  .feed-entry .feed-pill.is-plain { display: none; }
  .feed-entry .event-card { border: 0; background: var(--secondary); }
  /* A group's cover at half height, its picture smaller. */
  .group-head { border: 0; border-radius: 16px; box-shadow: 0 1px 2px rgba(16, 24, 40, .05); }
  /* As wide as the Feed's boxes under it since patch 773 (UX-040). */
  .group-head.is-on-feed { max-width: none; }
  .group-cover { height: 80px; }
  .group-info { align-items: center; margin-top: -26px; padding: 0 16px 12px; }
  .group-pic { width: 56px; height: 56px; border-width: 3px; border-radius: 14px; font-size: 19px; }
  .group-name { padding-top: 26px; }
  .group-name h1, .group-name h2 { font-size: 19px; }
  /* In a Dashboard box the posts share the box, a line between them, the
     photos out to the box's edges: the same post, without a box in a box.
     Sarah, 2026-10-18: "It doesn't look like you've applied the same feed
     changes to the other locations that the feeds exist ... I thought we were
     sharing more things". One marker, feed-surface, on every place the shared
     post list shows. Patch 679. */
  .feed-surface.is-boxed .feed-compose { margin: 0 0 8px; border-radius: 0; background: none; padding: 0; box-shadow: none; }
  .feed-surface.is-boxed .feed-entry { margin: 0; border-radius: 0; background: none; padding: 12px 0 6px; box-shadow: none; }
  .feed-surface.is-boxed .feed-entry + .feed-entry { border-top: 1px solid var(--border); }
  .feed-surface.is-boxed .feed-entry.is-team { margin: 0; background: color-mix(in srgb, #f59e0b 8%, var(--card)); }
}

/* The shared post list in a box (a Dashboard box, a project's Overview): the
   posts share the box with a line between, the photos out to the box's
   edges, on the phone as on a computer. --box-pad is the box's own padding.
   Sarah, 2026-10-18: "yes move Overview to shared", "all as recommended".
   UX-035, patch 680. */
.feed-surface.is-boxed { --box-pad: 16px; }
.ov-sec .feed-surface.is-boxed { --box-pad: 18px; }
body .feed-surface.is-boxed .feed-entry .feed-main > .feed-photos { margin-left: calc(-40px - var(--box-pad)); margin-right: calc(-1 * var(--box-pad)); border-radius: 0; }
@media (max-width: 760px) {
  .ov-sec .feed-surface.is-boxed { --box-pad: 14px; }
  body.has-phone-shell .feed-surface.is-boxed .feed-compose { margin: 0 0 8px; padding: 0; background: none; }
  body.has-phone-shell .feed-surface.is-boxed .feed-chips { margin: 0 0 4px; padding: 0; background: none; }
  body.has-phone-shell .feed-surface.is-boxed .feed-entry { margin: 0; padding: 12px 0 6px; background: none; }
  body.has-phone-shell .feed-surface.is-boxed .feed-entry + .feed-entry { border-top: 1px solid var(--border); }
  body.has-phone-shell .feed-surface.is-boxed .feed-entry.is-team { background: color-mix(in srgb, #f59e0b 8%, var(--card)); }
}
/* The Overview's post box keeps Comment, Note, Decision and Team only, laid
   out as the Feed's post box. */
.ov-composer.feed-compose { border: 0; border-radius: 0; background: none; margin: 0 0 8px; }
.ov-composer.feed-compose textarea { display: block; width: 100%; height: 42px; min-height: 42px; border: 0; border-radius: 21px; background: var(--secondary); padding: 10px 16px; line-height: 22px; resize: none; }
.ov-composer.feed-compose:focus-within textarea,
.ov-composer.feed-compose.is-open textarea,
.ov-composer.feed-compose textarea:not(:placeholder-shown) { height: 96px; border-radius: 14px; }
.ov-composer.feed-compose .ov-composer-row { border: 0; background: none; padding: 8px 0 0; }
.ov-composer.feed-compose:not(:focus-within):not(.is-open):has(textarea:placeholder-shown) .ov-composer-row { display: none; }
.ov-composer.feed-compose .ov-composer-row button[type="submit"] { border-color: var(--primary); background: var(--primary); color: var(--primary-foreground, #fff); }
.ov-chips .feed-chip { border: 0; background: color-mix(in srgb, var(--foreground) 6%, var(--secondary)); border-radius: 999px; padding: 6px 12px; font-size: 13px; min-height: 0; }
.ov-chips .feed-chip[aria-pressed="true"] { background: var(--foreground); color: var(--card); }
/* Edit in place, and a comment's ···. */
.feed-edited { color: var(--muted-foreground); font-size: 12px; }
.feed-who .feed-edited { margin-left: 6px; }
.feed-edit { display: grid; gap: 8px; margin-top: 6px; }
.feed-edit textarea { width: 100%; min-height: 72px; border-radius: 12px; font-size: 15px; }
.feed-edit-row { display: flex; justify-content: flex-end; gap: 8px; }
.feed-comment-more { min-height: 0; border: 0; background: none; padding: 0 6px; color: var(--muted-foreground); font-size: 13px; line-height: 1; cursor: pointer; }
.feed-comment-more:hover, .feed-comment-more:focus-visible { color: var(--foreground); }
.ctx-menu button.is-danger { color: var(--destructive); }

/* The computer, lighter, in the places patch 678 missed: the Dashboard's
   boxes and the goal cards in them, and buttons a page restyles (Profile).
   Found in the patch 678 and 679 tests. UX-035, patch 680. */
@media (min-width: 761px) {
  body .home-box:not(.is-big) { border-color: transparent; box-shadow: 0 1px 2px rgba(16, 24, 40, .05); }
  body .goal-card:not(.is-new) { border-color: transparent; box-shadow: 0 1px 2px rgba(16, 24, 40, .05); }
  body .home-box .goal-card:not(.is-new) { background: var(--secondary); box-shadow: none; }
  body .secondary-button, body a.secondary-button { border-color: transparent; background: var(--secondary); box-shadow: none; }
  body .secondary-button:hover { border-color: transparent; background: color-mix(in srgb, var(--foreground) 9%, var(--secondary)); }
}

/* Games: a picture and a few lines per game, one card, on every width.
   GAME-001, patch 681. */
.games-page { width: min(760px, 100%); }
.game-promo { display: grid; overflow: hidden; padding: 0; }
.game-art { display: block; line-height: 0; }
.game-art svg { display: block; width: 100%; height: auto; }
.game-info { display: grid; gap: 12px; padding: 18px 20px 20px; }
.game-info h2 { margin: 0; font-size: 22px; font-weight: 600; }
.game-info p { margin: 0; font-size: 16px; line-height: 1.5; color: var(--foreground); }
.game-scenes { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.game-scenes li { display: inline-flex; align-items: center; gap: 8px; border-radius: 999px; background: var(--secondary); padding: 6px 12px; font-size: 13px; }
.game-scenes i { width: 14px; height: 14px; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08); }
.game-play { justify-self: start; display: inline-flex; align-items: center; justify-content: center; min-height: 48px; border-color: var(--primary); background: var(--primary); padding: 0 24px; color: var(--primary-foreground, #fff); font-size: 16px; text-decoration: none; }
.game-play:hover { border-color: var(--primary); background: color-mix(in srgb, var(--primary) 88%, #000); color: var(--primary-foreground, #fff); }
@media (max-width: 760px) {
  .game-info { padding: 16px; }
  .game-play { justify-self: stretch; }
}

/* From the patch 680 test: the Overview's one-line box keeps its hint on one
   line; on a phone the Edit box takes 16px text, a comment's ··· and the
   Comment, Note and Decision choices are big enough to tap. UX-035, 681. */
.ov-composer.feed-compose textarea:not(:focus):placeholder-shown { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.feed-edit-row button { min-height: 40px; padding: 0 18px; }
@media (max-width: 760px) {
  .feed-edit textarea { font-size: 16px; }
  .feed-comment-more { min-width: 40px; min-height: 32px; padding: 0 10px; font-size: 15px; }
  .ov-composer.feed-compose .ov-seg label { display: inline-flex; align-items: center; min-height: 40px; padding: 0 14px; font-size: 14px; }
  .ov-composer.feed-compose .ov-teamtoggle { min-height: 40px; font-size: 14px; }
}

/* Edit's Save is the filled button, Cancel the tinted one; a comment's ···
   easier to hit on a computer too. Found in the patch 682 test. UX-035,
   patch 683. */
.feed-edit-row button[type="submit"] { border-color: var(--primary); background: var(--primary); color: var(--primary-foreground, #fff); }
.feed-edit-row button[type="submit"]:hover { border-color: var(--primary); background: color-mix(in srgb, var(--primary) 88%, #000); color: var(--primary-foreground, #fff); }
@media (min-width: 761px) { .feed-comment-more { min-width: 32px; min-height: 24px; } }

/* Tasks' four counts on a phone: one row of tinted chips under search and
   Filters, sliding sideways if they need to; a computer keeps them at the
   end of the filter row. Patch 685. */
.task-counts-phone { display: none; }
@media (max-width: 760px) {
  .task-counts-phone { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; }
  .task-counts-phone::-webkit-scrollbar { display: none; }
  .task-counts-phone a { display: inline-flex; flex: none; align-items: center; gap: 6px; min-height: 40px; border-radius: 999px; background: var(--secondary); padding: 0 14px; color: var(--muted-foreground); font-size: 14px; text-decoration: none; white-space: nowrap; }
  .task-counts-phone b { color: var(--foreground); font-weight: 600; }
  .task-counts-phone a.is-late b { color: color-mix(in srgb, var(--destructive) 88%, #000000); }
}

/* A link for another account. MAIL-013, patch 686. */
.link-other { width: min(480px, 100%); }
.link-other-card { display: grid; gap: 14px; padding: 22px; }
.link-other-card h1 { margin: 0; font-size: 22px; font-weight: 600; }
.link-other-card p { margin: 0; font-size: 16px; line-height: 1.5; overflow-wrap: anywhere; }
.link-other-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.link-other-actions button { border-color: var(--primary); background: var(--primary); color: var(--primary-foreground, #fff); }
.link-other-actions > * { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 18px; text-decoration: none; }
@media (max-width: 760px) { .link-other-actions > * { flex: 1 1 100%; } }

/* The phone layout check, 2026-10-21. Sarah: "help text that is being hidden
   or covering other fields that it should not be but generally layout
   issues", "field overlap or oversized rows". MOBILE-006, patch 687. */

/* Blocking or broken. */
/* The photo library's tray: its phone rule sat above the base rule, which won,
   so the tray stayed pinned over the whole screen. */
@media (max-width: 900px) { .pl-tray { position: static; max-height: none; overflow: visible; } }
/* A field hidden until asked for stays hidden (+ > New task's project and date). */
.phone-field[hidden] { display: none; }
@media (max-width: 760px) {
  /* A task page as wide as the phone: the project menu in the header no
     longer grows to its longest project. */
  .record-inline-control, .record-inline-control select { min-width: 0; max-width: 100%; }
  .record-inline-control select { field-sizing: fixed; width: 100%; }
  /* Add an update: the file field on its own full-width line, then the photo
     library and Post. */
  .comment-form-foot { flex-wrap: wrap; justify-content: flex-end; }
  .comment-attach { flex: 1 1 100%; }
  .comment-attach input[type="file"] { width: 100%; max-width: none; min-height: 44px; font-size: 16px; }
  /* The + steps aside while you type, so it never sits on Post or a field. */
  body.has-phone-shell:has(main :is(textarea, input:not([type="checkbox"]):not([type="radio"]):not([type="file"]), select):focus) .phone-fab { display: none; }
  /* Overlays above the bar and the +. */
  body.has-phone-shell .library-panel { z-index: 960; padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px)); }
  body.has-phone-shell .bell-panel { z-index: 960; max-height: calc(100vh - 140px); }
  /* A file list stays inside its card; names wrap whole. */
  .file-table-wrap { position: relative; max-width: 100%; }
  .file-table-name { min-width: 0; }
  .file-table-name, .file-table-name * { white-space: normal; overflow-wrap: anywhere; text-overflow: clip; }
  /* Record tabs that do not fit slide sideways in their own row. */
  .view-tabs.is-underline { gap: 20px; overflow-x: auto; flex-wrap: nowrap; scrollbar-width: none; max-width: 100%; }
  .view-tabs.is-underline::-webkit-scrollbar { display: none; }
  .view-tabs.is-underline label { flex: none; white-space: nowrap; }
  /* Drag and drop is for a mouse. */
  .drop-hint { display: none; }
}

/* Sizes on a phone: 16px text in fields, 44px fields and buttons, 20px
   checkboxes, 40px icon buttons. */
@media (max-width: 760px) {
  .record-control { min-height: 44px; }
  .record-control select, .record-control input { font-size: 16px; min-height: 42px; }
  .record-control input[type="checkbox"] { width: 20px; height: 20px; min-height: 0; }
  main input[type="checkbox"], main input[type="radio"]:not(.visually-hidden):not([data-tab-value]) { width: 20px; height: 20px; min-height: 0; }
  main input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="hidden"]), main select, main textarea { font-size: 16px; }
  main input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]), main select { min-height: 44px; }
  main form button[type="submit"], main .secondary-button { min-height: 44px; }
  .feed-compose-row button[type="submit"] { min-width: 64px; }
  .ov-factions { gap: 18px; }
  .ov-factions .ov-link, .ov-factions button { display: inline-flex; align-items: center; min-height: 40px; }
  .ctx-menu button, .ctx-menu a { min-height: 44px; font-size: 15px; }
  .calendar-day-head-line .calendar-day-add { width: 40px; height: 40px; }
  .bell-button { width: 40px; height: 40px; }
  .user-menu > summary .avatar { min-width: 40px; min-height: 40px; }
}

/* From the patch 687 test. UX-035 and MOBILE-006, patch 688. */
/* A menu never runs past the screen: it scrolls inside itself. On a phone the
   task menu at 44px rows was 884 tall, Delete below the screen. */
.ctx-menu { max-height: calc(100vh - 16px); max-height: calc(100dvh - 16px); overflow-y: auto; overscroll-behavior: contain; }
@media (max-width: 760px) {
  /* The Overview's Open and Delete far enough apart; the page's own style set
     10px after this file. */
  .ov-sec .ov-factions { gap: 18px; }
  .ov-sec .ov-factions .ov-link { min-width: 44px; justify-content: center; }
  /* The task header's project menu at 16px, so tapping it does not zoom. */
  .record-inline-control select { font-size: 16px; min-height: 40px; }
}

/* The × after a date that may be empty. TASK-036, patch 689. */
.date-clear { display: inline-grid; place-items: center; flex: none; width: 28px; height: 28px; min-height: 0; margin: 0 0 0 4px; border: 0; border-radius: 999px; background: transparent; padding: 0; color: var(--muted-foreground); font-size: 18px; line-height: 1; cursor: pointer; box-shadow: none; vertical-align: middle; }
.date-clear:hover, .date-clear:focus-visible { background: var(--secondary); color: var(--foreground); }
.date-clear[hidden] { display: none; }
@media (max-width: 760px) { .date-clear { width: 40px; height: 40px; font-size: 20px; } }

/* One Attach on a phone, opening the client's photo library or the phone's
   own chooser; the two buttons it stands for step aside. A computer keeps
   them. UX-037, patch 689. */
.attach-menu-button, .attach-menu-chosen { display: none; }
@media (max-width: 760px) {
  .has-attach-menu .attach-menu-button { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 18px; }
  .has-attach-menu .attach-menu-chosen:not([hidden]) { display: inline-block; max-width: 50%; overflow: hidden; color: var(--muted-foreground); font-size: 14px; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }
  .has-attach-menu [data-library-open].attach-menu-hidden { display: none; }
  /* Clipped, not removed, so the file field can still be opened. */
  .has-attach-menu .attach-menu-hidden:not([data-library-open]) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  form.has-attach-menu .comment-attach { flex: 0 1 auto; }
  form.has-attach-menu .comment-form-foot { flex-wrap: nowrap; align-items: center; justify-content: space-between; }
}

/* Your home with no groups: your other spaces, each with Open. NAV-010,
   patch 689. */
.home-empty-spaces { display: grid; gap: 8px; margin: 12px 0 16px; padding: 0; list-style: none; text-align: left; }
.home-empty-spaces li { display: flex; align-items: center; gap: 10px; border-radius: 12px; background: var(--secondary); padding: 8px 10px; }
.home-empty-spaces li > span:not(.home-nav-pic) { flex: 1; min-width: 0; overflow: hidden; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
/* The name takes the row's spare width, and the space's picture keeps its own
   size; it had taken the name's share and stretched once it became a ring.
   Sarah, 2026-10-26, screenshot. Patch 822. */
.home-empty-spaces form { margin: 0; }

/* A client contact with no client, marked on People. CLIENT-026, patch 689. */
.people-no-client { display: inline-block; border-radius: 999px; background: color-mix(in srgb, #f59e0b 16%, var(--card)); padding: 2px 9px; color: #8a4b00; font-size: 12.5px; font-weight: 600; }

/* A portal's rail: Home and the portal's places, on a computer. A phone
   keeps its menu, which now names the client and links Your home. NAV-012,
   patch 691. */
.home-nav-pic.is-portal { background: linear-gradient(135deg, #0ea5e9, #0369a1); }
@media (min-width: 761px) {
  body.limited-shell.has-portal-rail .app-body { grid-template-columns: 58px 188px minmax(0, 1fr); }
}
@media (max-width: 760px) {
  .app-rail.is-portal-rail { display: none; }
}

/* A portal's heading whole: the client, and its space under it. NAV-012,
   patch 694. */
.nav-space.is-portal { align-items: flex-start; }
.nav-space.is-portal span:last-child { white-space: normal; overflow-wrap: anywhere; line-height: 1.3; }
.nav-space.is-portal small { display: block; color: var(--muted-foreground); font-size: 12px; font-weight: 500; }

/* The chosen-files list stays out of sight until a file is chosen; its grid
   rule had drawn it as an empty gray strip. Found in the patch 695 test.
   UX-037, patch 696. */
.chosen-files[hidden] { display: none; }

/* The Map: a group's Map page, and Add a place. GROUP-008, patch 697. */
.group-map-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; }
.group-map-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.group-map-sub select { min-height: 36px; }
.group-map-wrap { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 14px; align-items: start; }
.group-map-view { height: calc(100vh - 210px); min-height: 420px; border-radius: 14px; overflow: hidden; background: #eef2e6; }
.group-map-list { max-height: calc(100vh - 210px); overflow-y: auto; padding: 14px; }
.group-map-list h2 { margin: 0 0 8px; font-size: 15px; font-weight: 600; }
.group-map-list ul { display: grid; gap: 2px; margin: 0; padding: 0; list-style: none; }
.group-map-list li { display: grid; grid-template-columns: 12px minmax(0, 1fr); column-gap: 8px; border-radius: 8px; padding: 8px; }
.group-map-list li:hover { background: var(--secondary); }
.group-map-list li i { grid-row: span 2; width: 10px; height: 10px; margin-top: 5px; border-radius: 50%; }
.group-map-list li a { font-weight: 600; color: var(--foreground); text-decoration: none; overflow-wrap: anywhere; }
.group-map-list li small { color: var(--muted-foreground); font-size: 12.5px; }
.map-card { display: grid; gap: 2px; font-family: inherit; }
.map-card small { color: var(--muted-foreground); font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em; }
.map-card a { font-weight: 600; font-size: 14px; color: var(--foreground); }
.map-card span { color: var(--muted-foreground); font-size: 12.5px; }
.place-picker { display: grid; gap: 8px; }
.place-picker-label { font-size: 13px; font-weight: 600; }
.place-picker-search { display: flex; gap: 8px; }
.place-picker-search input { flex: 1; min-width: 0; }
.place-picker-results { display: grid; gap: 2px; margin: 0; border: 1px solid var(--border); border-radius: 10px; padding: 4px; list-style: none; background: var(--card); }
.place-picker-results[hidden] { display: none; }
.place-picker-results button { width: 100%; min-height: 40px; border: 0; border-radius: 8px; background: none; padding: 6px 10px; color: var(--foreground); text-align: left; font-size: 14px; white-space: normal; box-shadow: none; }
.place-picker-results button:hover { background: var(--secondary); }
.place-picker-map { height: 260px; border-radius: 12px; overflow: hidden; background: #eef2e6; }
.place-picker-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 13px; }
.place-picker-foot [hidden] { display: none; }
@media (max-width: 900px) {
  .group-map-wrap { grid-template-columns: 1fr; }
  .group-map-view { height: 60vh; min-height: 320px; }
  .group-map-list { max-height: none; }
}
.map-card img { width: 100%; max-height: 140px; margin-bottom: 4px; border-radius: 8px; object-fit: cover; }
/* The post box's Place, and a photo's place offered. Patch 698. */
.feed-place-panel { margin-top: 10px; border-top: 1px solid var(--border); padding-top: 10px; }
.feed-place-panel[hidden] { display: none; }
.feed-place[aria-expanded="true"] { background: color-mix(in srgb, var(--primary) 14%, var(--secondary)); }
.place-picker-photo { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0; border-radius: 10px; background: color-mix(in srgb, var(--primary) 8%, var(--card)); padding: 8px 10px; font-size: 13.5px; }
.place-picker-photo[hidden] { display: none; }
/* A subgroup's area card: Join for one you are not in. Patch 699. */
.map-card .map-card-join { justify-self: start; margin-top: 6px; border-radius: 999px; background: var(--primary); padding: 4px 12px; color: var(--primary-foreground, #fff); font-size: 13px; text-decoration: none; }

/* An open Place keeps the post box open, so its buttons and the map never
   part. Found in the patch 698 test. Patch 700. */
.feed-compose:has([data-place-panel]:not([hidden])) .feed-compose-row { display: flex !important; }
.feed-compose:has([data-place-panel]:not([hidden])) textarea { height: 96px; border-radius: 14px; }

/* An opened post box stays open with its buttons until you post or tap
   away with nothing in it: on a phone, tapping Photo or Group moved focus
   off the words and the buttons folded away under the tap. Sarah,
   2026-10-21, in Wine Time on her phone: "when I click on that, that line
   option disappears ... I click the photo button and then also it
   disappears again". UX-035, patch 702. */
@media (max-width: 760px) { body.has-phone-shell:has(.feed-compose.is-open) .phone-fab { display: none; } }

/* Phone gestures: the band a swipe reveals, its Undo, the Pick a date sheet
   and the hold menus. Sarah, 2026-10-21, after trying the mockup on her
   phone: "Build all of them as shown." MOBILE-007, patch 706. */
.gesture-band { position: fixed; z-index: 940; display: flex; align-items: center; overflow: hidden; border-radius: 10px; color: #fff; font-size: 14px; font-weight: 600; white-space: nowrap; pointer-events: none; }
.gesture-band span { display: inline-flex; align-items: center; gap: 8px; padding: 0 18px; }
.gesture-band.from-right { justify-content: flex-end; }
.gesture-band svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; transition: transform .15s ease; }
.gesture-band.is-past svg { transform: scale(1.25); }
.gesture-band.is-done { background: var(--success, #2f7d4f); }
.gesture-band.is-later { background: var(--primary); color: var(--primary-foreground, #fff); }
.gesture-band.is-archive, .gesture-band.is-restore { background: #5f6b7a; }
.gesture-toast { position: fixed; left: 12px; right: 12px; bottom: calc(96px + env(safe-area-inset-bottom, 0px)); z-index: 960; display: flex; align-items: center; gap: 12px; border-radius: 12px; padding: 10px 8px 10px 16px; background: var(--foreground); color: var(--background); font-size: 15px; box-shadow: 0 8px 24px rgba(0, 0, 0, .2); }
.gesture-toast[hidden] { display: none; }
.gesture-toast span { flex: 1; min-width: 0; }
.gesture-toast button { min-height: 40px; border: 0; border-radius: 8px; padding: 0 12px; background: transparent; color: inherit; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
.gesture-sheet { transition: transform .25s ease; }
.gesture-sheet h2 { overflow: hidden; color: var(--muted-foreground); font-size: 14px; text-align: center; text-overflow: ellipsis; white-space: nowrap; }
.gesture-opts { display: grid; }
.gesture-opt { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 52px; margin: 0; border: 0; border-top: 1px solid var(--border); border-radius: 0; padding: 0 4px; background: transparent; color: var(--foreground); font-size: 16px; font-weight: 500; text-align: left; box-shadow: none; }
.gesture-opt:first-child { border-top: 0; }
.gesture-opt small { margin-left: auto; color: var(--muted-foreground); font-size: 14px; font-weight: 400; }
.gesture-opt input[type="date"] { width: auto; margin-left: auto; }
@media (hover: none) {
  /* Holding a post or an Inbox item opens its menu, not the phone's text
     selection or link preview, as on anything with a menu (UX-002). */
  .feed-entry, .inbox-item { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
}

/* On a phone every menu, from a hold or from ···, slides up from the bottom
   with the page dimmed behind it, as in the gestures mockup. A tap on the
   dimmed page closes it, as a click outside always has. Sarah, 2026-10-21:
   "make the hold menus slide up from the bottom like the mockup."
   MOBILE-007, patch 707. */
@media (max-width: 760px) {
  .ctx-menu { top: auto !important; right: 0 !important; bottom: 0 !important; left: 0 !important; min-width: 0; max-width: none; max-height: 80vh; max-height: 80dvh; border: 0; border-radius: 18px 18px 0 0; padding: 22px 12px calc(14px + env(safe-area-inset-bottom, 0px)); box-shadow: 0 -8px 30px rgba(0, 0, 0, .18); animation: ctx-sheet-up .24s cubic-bezier(.2, .8, .2, 1); }
  .ctx-menu::before { content: ""; position: absolute; top: 8px; left: 50%; width: 40px; height: 5px; margin-left: -20px; border-radius: 9px; background: var(--border); }
  .ctx-menu button, .ctx-menu a, .ctx-menu .ctx-pick { justify-content: flex-start; min-height: 48px; padding: 0 12px; font-size: 16px; text-align: left; }
  body:has(.ctx-menu:not([hidden]))::after { content: ""; position: fixed; inset: 0; z-index: 999; background: rgba(0, 0, 0, .32); }
}
@keyframes ctx-sheet-up { from { transform: translateY(100%); } }
@media (max-width: 760px) and (prefers-reduced-motion: reduce) { .ctx-menu { animation: none; } }

/* Messages: the list beside the open conversation, New message, and the
   Inbox | Messages tabs. On a phone, the list and then the conversation full
   screen. Sarah, 2026-10-21: "Build Messages as shown."
   docs/mockups/messages.html. MSG-001, patch 708. */
.msg-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.msg-header-tools { display: flex; align-items: center; gap: 8px; }
.msg-tabs { display: flex; gap: 4px; margin: 0 0 14px; border-bottom: 1px solid var(--border); }
.msg-tabs a { display: inline-flex; align-items: center; gap: 7px; border-bottom: 2.5px solid transparent; padding: 10px 12px 9px; color: var(--muted-foreground); font-size: 14px; font-weight: 600; text-decoration: none; }
.msg-tabs a[aria-current="page"] { border-bottom-color: var(--primary); color: var(--foreground); }
.msg-tabs i { border-radius: 9px; background: var(--secondary); padding: 1px 7px; font-size: 11.5px; font-style: normal; font-weight: 600; }
.msg-tabs a[aria-current="page"] i { background: var(--accent); color: var(--primary); }
.msg-tabs i[hidden] { display: none; }
.msg-empty { display: grid; place-items: center; gap: 6px; padding: 56px 16px; text-align: center; }
.msg-empty strong { font-size: 15px; font-weight: 600; }
.msg-empty p { max-width: 46ch; margin: 0; color: var(--muted-foreground); }
.msg-split { display: grid; grid-template-columns: minmax(280px, 360px) minmax(0, 1fr); gap: 16px; align-items: start; }
.msg-list { overflow: hidden; border: 1px solid var(--border); border-radius: 12px; background: var(--card); }
.msg-list-empty { margin: 0; padding: 18px 14px; color: var(--muted-foreground); }
.msg-item { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 2px 10px; align-items: start; border-top: 1px solid var(--border); padding: 12px 14px; color: var(--foreground); text-decoration: none; }
.msg-item:first-child { border-top: 0; }
.msg-item:hover strong { text-decoration: underline; }
.msg-item.is-current { background: color-mix(in srgb, var(--primary) 9%, var(--card)); box-shadow: inset 3px 0 0 var(--primary); }
.msg-item .feed-av { width: 38px; height: 38px; font-size: 12.5px; }
.msg-item-text { min-width: 0; }
.msg-item-text strong { display: block; overflow: hidden; font-size: 14.5px; font-weight: 500; text-overflow: ellipsis; white-space: nowrap; }
.msg-item.is-unread strong { font-weight: 600; }
.msg-item-text small, .msg-last { display: block; overflow: hidden; color: var(--muted-foreground); font-size: 12.5px; text-overflow: ellipsis; white-space: nowrap; }
.msg-last { margin-top: 2px; font-size: 13px; }
.msg-item.is-unread .msg-last { color: var(--foreground); }
.msg-when { display: flex; align-items: center; gap: 6px; color: var(--muted-foreground); font-size: 12px; white-space: nowrap; }
.msg-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--primary); }
.msg-conv { display: flex; flex-direction: column; height: calc(100vh - 230px); height: calc(100dvh - 230px); min-height: 420px; overflow: hidden; padding: 0; }
.msg-head { display: flex; align-items: center; gap: 12px; border-bottom: 1px solid var(--border); padding: 10px 12px 10px 14px; }
.msg-head .feed-av { width: 34px; height: 34px; }
.msg-who { flex: 1; min-width: 0; }
.msg-who strong { display: block; overflow: hidden; font-size: 15.5px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.msg-who small { display: block; color: var(--muted-foreground); font-size: 12.5px; }
.msg-back { display: none; padding: 6px 8px 6px 0; color: var(--primary); font-size: 20px; text-decoration: none; }
.msg-more { display: grid; place-items: center; width: 36px; height: 36px; min-height: 0; border: 0; border-radius: 9px; background: transparent; padding: 0; color: var(--muted-foreground); box-shadow: none; font-size: 15px; letter-spacing: 1px; }
.msg-more:hover, .msg-more:focus-visible { background: var(--secondary); color: var(--foreground); }
.msg-about { display: flex; gap: 8px; align-items: center; border-bottom: 1px solid var(--border); padding: 8px 14px; color: var(--foreground); font-size: 14px; text-decoration: none; }
.msg-about span { border-radius: 6px; background: var(--accent); padding: 1px 7px; color: var(--primary); font-size: 12px; font-weight: 600; }
.msg-thread { display: flex; flex: 1; flex-direction: column; gap: 6px; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 14px 14px 10px; }
.msg-day { align-self: center; margin: 10px 0 4px; color: var(--muted-foreground); font-size: 12px; font-weight: 600; }
.msg-row { display: flex; align-items: flex-end; gap: 4px; max-width: 80%; }
.msg-row.is-mine { flex-direction: row-reverse; align-self: flex-end; }
.msg-bubble { border-radius: 16px; background: var(--secondary); padding: 9px 12px; font-size: 15px; line-height: 1.4; overflow-wrap: anywhere; }
.msg-row.is-mine .msg-bubble { background: color-mix(in srgb, var(--primary) 16%, var(--card)); }
.msg-bubble.is-gone { color: var(--muted-foreground); font-style: italic; }
.msg-words a { color: inherit; text-decoration: underline; }
.msg-meta { display: block; margin-top: 3px; color: var(--muted-foreground); font-size: 11.5px; }
.msg-row .msg-more { width: 30px; height: 30px; opacity: 0; }
.msg-row:hover .msg-more, .msg-row .msg-more:focus-visible { opacity: 1; }
.msg-reported { color: var(--muted-foreground); font-size: 12px; }
.msg-editing { display: flex; align-items: center; gap: 8px; border-top: 1px solid var(--border); background: var(--accent); padding: 6px 14px; font-size: 13px; }
.msg-editing[hidden] { display: none; }
.msg-editing span { flex: 1; }
.msg-compose { display: flex; align-items: flex-end; gap: 8px; margin: 0; border-top: 1px solid var(--border); padding: 10px 12px 12px; }
.msg-compose textarea { flex: 1; min-width: 0; min-height: 44px; max-height: 160px; resize: none; border-radius: 12px; padding: 11px 12px; font-size: 16px; line-height: 1.35; }
.msg-send { display: grid; place-items: center; width: 44px; height: 44px; min-height: 0; border-color: var(--primary); border-radius: 12px; background: var(--primary); padding: 0; color: var(--primary-foreground, #fff); }
.msg-note { margin: 0; border-top: 1px solid var(--border); padding: 12px 14px; color: var(--muted-foreground); font-size: 14px; }
.msg-picker { display: grid; gap: 4px; padding: 16px; }
.msg-picker-head { display: flex; align-items: center; gap: 8px; }
.msg-picker-head h2 { margin: 0; font-size: 18px; font-weight: 600; }
.msg-search { width: 100%; margin: 8px 0 4px; }
.msg-letter[hidden], .msg-person-form[hidden] { display: none; }
.msg-letter { margin: 12px 2px 2px; color: var(--muted-foreground); font-size: 13px; font-weight: 600; }
.msg-chips { display: flex; gap: 6px; margin: 2px 0 4px; overflow-x: auto; scrollbar-width: none; }
.msg-chip { flex: none; min-height: 36px; border: 1px solid var(--border); border-radius: 999px; background: var(--card); padding: 0 13px; color: var(--foreground); font-size: 13.5px; font-weight: 500; box-shadow: none; }
.msg-chip[aria-pressed="true"] { border-color: var(--primary); background: color-mix(in srgb, var(--accent) 70%, var(--card)); color: var(--primary); font-weight: 600; }
.msg-person-form { margin: 0; }
.msg-person { display: flex; align-items: center; justify-content: flex-start; gap: 10px; width: 100%; min-height: 52px; border: 0; border-top: 1px solid var(--border); border-radius: 0; background: transparent; padding: 6px 4px; color: var(--foreground); font-weight: 500; text-align: left; box-shadow: none; }
.msg-person small { display: block; color: var(--muted-foreground); font-size: 12.5px; font-weight: 400; }
.msg-person.is-off { opacity: .55; }
button.msg-person:hover { background: var(--secondary); }
.msg-menu-text { max-width: 280px; margin: 6px 10px 8px; font-size: 14px; }
.msg-menu button { justify-content: flex-start; }
.ctx-menu button.is-danger { color: var(--destructive); }
.msg-start { display: inline-flex; margin: 0; }
@media (max-width: 760px) {
  .msg-split { grid-template-columns: minmax(0, 1fr); }
  .msg-page.has-pick .msg-list, .msg-page:not(.has-pick) .msg-pane { display: none; }
  .msg-page.has-pick .msg-header, .msg-page.has-pick .msg-tabs { display: none; }
  .msg-back { display: inline-block; }
  .msg-conv { height: calc(100vh - 100px); height: calc(100dvh - 100px); min-height: 0; margin: -4px -16px -150px; border: 0; border-radius: 0; }
  .msg-picker { margin: 0 -16px; border: 0; border-radius: 0; }
  .msg-row { max-width: 86%; }
  .msg-row .msg-more { opacity: 1; }
  .msg-compose { padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
  /* A conversation is the whole screen: the quick bar steps aside, as it
     does for an open Inbox item. */
  body.has-phone-shell:has(.msg-page.has-pick) .phone-fab,
  body.has-phone-shell:has(.msg-page.has-pick) .phone-bar,
  body.has-phone-shell:has(.msg-page.has-pick) .report-dock { display: none; }
}
.msg-blocked-head { display: block; margin-top: 16px; }
.msg-blocked { display: flex; align-items: center; gap: 10px; margin: 6px 0 0; }
.msg-blocked span { flex: 1; }
.msg-reports { display: grid; gap: 14px; margin-bottom: 18px; }
.msg-reports h2 { margin: 0; font-size: 17px; font-weight: 600; }
.msg-report { display: grid; gap: 6px; border-top: 1px solid var(--border); padding-top: 12px; }
.msg-report blockquote { margin: 0; border-left: 3px solid var(--border); padding: 4px 12px; overflow-wrap: anywhere; }
.msg-report-acts { display: flex; flex-wrap: wrap; gap: 8px; }

/* Too much going on in mobile view. Sarah, 2026-10-21, "All as
   recommended". MOBILE-008, patch 710. */
/* Complete, when a task is swiped left: the page's ink, so it never reads as
   the workspace's own color on the other side, nor as delete. */
.gesture-band.is-done { background: var(--foreground); color: var(--background); }
/* Feed words line up with the post's edge, under the person's picture, as
   its photos already do. */
.feed-entry .feed-main > .feed-body, .feed-entry .feed-main > .feed-unfold { margin-left: -40px; }
/* And everything under them: the Team or tag line, Like and Comment, and
   the comments. Sarah, 2026-10-21: "yes, line them up". Patch 711. */
.feed-entry .feed-main > .feed-refs, .feed-entry .feed-main > .react, .feed-entry .feed-main > .feed-comments { margin-left: -40px; }
/* The name line is as tall as the picture, so the words start below it. */
.feed-entry .feed-main > .feed-who { min-height: 30px; }
.record-project-open { display: none; }
@media (max-width: 760px) {
  /* A task's project line repeats the crumbs above it; Change project, in
     the ··· menu, brings it back. */
  .record-meta-project { display: none; }
  .record-head.show-project .record-meta-project { display: inline-flex; }
  /* With the project line off, the line starts clean: no dot before it.
     Found in the patch 710 test. Patch 711. */
  .record-head:not(.show-project) .record-meta-project + span::before { content: none; }
  /* Opened and by whom is on the History tab; on a phone the line keeps only
     the ticket number. Sarah, 2026-10-21. Patch 712. */
  .record-meta .record-opened { display: none; }
  /* Repeats and Show to the client say what they are, so on a phone they
     drop the titles above them and share one line. Sarah, 2026-10-21. */
  .record-prop.is-check { flex: 0 1 auto; }
  .record-prop.is-check .record-prop-label { display: none; }
  .record-props:has(.record-prop.is-check) .record-prop.is-check + .record-prop.is-check { margin-left: 8px; }
  .record-project-open { display: block; width: 100%; margin-bottom: 4px; text-align: left; }
  /* One pull-down: words on the left, one small chevron on the right, no
     status dot and no up and down arrows. */
  .record-status-dot { display: none; }
  .record-control { justify-content: flex-start; }
  .record-control select { flex: 1 1 auto; width: 100%; -webkit-appearance: none; appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5l3 3 3-3' fill='none' stroke='%238a8f98' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 2px center; background-size: 12px 12px; padding-right: 22px; text-align: left; }
}

/* One space switcher on a phone: your spaces as circles, from the top bar
   and in More, as on Your home. Sarah, 2026-10-21: "Yeah that works".
   NAV-013, patch 713. */
.space-switch { display: grid; grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); gap: 14px 8px; }
.space-switch-form { margin: 0; }
.space-switch-go { display: grid; justify-items: center; gap: 5px; width: 100%; min-height: 0; border: 0; background: none; padding: 4px 0; color: var(--foreground); font-size: 12px; font-weight: 500; text-align: center; text-decoration: none; box-shadow: none; }
.space-switch-go .home-nav-pic { width: 52px; height: 52px; border-radius: 50%; font-size: 16px; }
.space-switch-go .home-nav-pic.is-home { display: grid; place-items: center; background: var(--secondary); color: var(--foreground); }
.space-switch-go .home-nav-pic.is-home svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linejoin: round; }
.space-switch-go.is-current .home-nav-pic { box-shadow: 0 0 0 2px var(--card), 0 0 0 4px var(--primary); }
.space-switch-go.is-current .space-switch-name { color: var(--primary); font-weight: 600; }
.space-switch-name { display: -webkit-box; width: 100%; overflow: hidden; white-space: normal; overflow-wrap: anywhere; line-height: 1.25; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
.phone-spaces .space-switch { max-height: 60vh; overflow-y: auto; padding: 4px 0 6px; }
.phone-drawer-ws .space-switch { padding: 6px 4px 12px; }
.space-picture-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 16px; }
.space-picture-row .home-nav-pic { width: 52px; height: 52px; border-radius: 50%; font-size: 16px; }
.space-picture-form { margin: 0; }
.space-picture-pick { position: relative; overflow: hidden; cursor: pointer; }
.space-picture-pick input { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
@media (max-width: 760px) {
  body.has-phone-shell .phone-title { min-height: 40px; border: 0; background: none; padding: 0; color: var(--foreground); box-shadow: none; text-align: left; cursor: pointer; }
  body.has-phone-shell .phone-title > span:not(.home-nav-pic) { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .phone-title-more { flex: none; width: 12px; height: 12px; fill: none; stroke: var(--muted-foreground); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
}

/* A lighter post box: icons, a chip for a choice, thumbnails with ×, Cancel
   and a progress bar. Sarah, 2026-10-21: "Yes as proposed". FEED-005,
   patch 714. */
.compose-native { display: none !important; }
.feed-compose-row .compose-icon { position: relative; display: inline-grid; place-items: center; flex: none; width: 40px; height: 40px; min-height: 0; margin: 0; border: 0; border-radius: 10px; background: transparent; padding: 0; color: var(--muted-foreground); box-shadow: none; cursor: pointer; }
.feed-compose-row .compose-icon:hover, .feed-compose-row .compose-icon:focus-within, .feed-compose-row .compose-icon[aria-expanded="true"] { background: var(--secondary); color: var(--foreground); }
.compose-icon svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.compose-toggle input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.compose-toggle:has(input:checked) { background: color-mix(in srgb, var(--primary) 14%, var(--card)); color: var(--primary); }
.feed-compose-row .compose-chip { display: inline-flex; flex: 0 1 auto; align-items: center; gap: 6px; max-width: 200px; min-height: 36px; margin: 0; border: 1px solid var(--border); border-radius: 999px; background: var(--card); padding: 0 12px; color: var(--foreground); font-size: 13.5px; font-weight: 500; box-shadow: none; white-space: nowrap; }
.compose-chip span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.compose-chip[hidden] { display: none; }
.compose-chev { flex: none; width: 12px; height: 12px; fill: none; stroke: var(--muted-foreground); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.feed-compose-row .compose-actions { display: inline-flex; align-items: center; gap: 8px; margin-left: auto; }
.feed-compose:not(.is-open) .compose-cancel { display: none; }
.compose-menu [aria-checked="true"] { color: var(--primary); font-weight: 600; }
.compose-menu button { justify-content: flex-start; }
.compose-previews { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.compose-previews[hidden] { display: none; }
.compose-thumb { position: relative; width: 72px; height: 72px; overflow: hidden; border-radius: 10px; background: var(--secondary); }
.compose-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.compose-thumb-x { position: absolute; top: 4px; right: 4px; display: grid; place-items: center; width: 24px; height: 24px; min-height: 0; border: 0; border-radius: 50%; background: rgba(0, 0, 0, .6); padding: 0; color: #fff; font-size: 16px; line-height: 1; box-shadow: none; }
.feed-compose:has(.compose-previews:not([hidden])) .feed-chosen { display: none; }
.compose-progress { display: grid; gap: 4px; margin-top: 8px; }
.compose-progress[hidden] { display: none; }
.compose-progress-track { display: block; height: 4px; overflow: hidden; border-radius: 2px; background: var(--secondary); }
.compose-progress-track i { display: block; width: 0; height: 100%; background: var(--primary); transition: width .2s ease; }
.compose-progress-text { color: var(--muted-foreground); font-size: 12.5px; }

/* Where am I: every page names itself on a phone, and More names the space.
   UX-039, patch 718. */
@media (max-width: 760px) {
  body.has-phone-shell.header-in-band .page-header { position: static; width: auto; height: auto; margin: 0 0 12px; overflow: visible; clip: auto; white-space: normal; }
  body.has-phone-shell.header-in-band .page-header p { display: none; }
  body.has-phone-shell .page-header h1, body.has-phone-shell h1.phone-page-h1 { font-size: 22px; font-weight: 600; letter-spacing: .01em; }
  body.has-phone-shell h1.phone-page-h1 { position: static; width: auto; height: auto; margin: 0 0 10px; overflow: visible; clip: auto; white-space: normal; }
  .phone-drawer-space { display: inline-flex; align-items: center; gap: 8px; min-width: 0; font-size: 16px; font-weight: 600; }
  .phone-drawer-space .home-nav-pic { width: 28px; height: 28px; border-radius: 50%; font-size: 11px; flex: none; }
  .phone-drawer-space span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

/* Taps a thumb can hit, fields a thumb can fill, and the last pull-downs as
   a tap and a short list. Sarah, 2026-10-21, yes to the phone review.
   MOBILE-012, patch 718. */
.sheet-native { display: none !important; }
.sheet-chip { display: inline-flex; align-items: center; justify-content: space-between; gap: 8px; width: auto; min-height: 32px; margin: 0; border: 0; background: transparent; padding: 0 2px; color: var(--foreground); font-size: 13.5px; font-weight: 600; text-align: left; box-shadow: none; cursor: pointer; }
.sheet-chip span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sheet-chip-chev { flex: none; width: 12px; height: 12px; fill: none; stroke: var(--muted-foreground); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.sheet-menu [aria-checked="true"] { color: var(--primary); font-weight: 600; }
.sheet-menu button { justify-content: flex-start; }
.picture-picks { display: flex; flex-wrap: wrap; gap: 16px; }
.picture-pick { position: relative; display: grid; justify-items: center; gap: 6px; cursor: pointer; }
.picture-pick input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.picture-pick-face { display: grid; place-items: center; overflow: hidden; border: 1px dashed var(--border); background: var(--secondary); color: var(--muted-foreground); }
.picture-pick.is-picture .picture-pick-face { width: 72px; height: 72px; border-radius: 50%; }
.picture-pick.is-header .picture-pick-face { width: 160px; height: 72px; border-radius: 12px; }
.picture-pick-face img { width: 100%; height: 100%; object-fit: cover; }
.picture-pick-empty { font-size: 26px; line-height: 1; }
.picture-pick-name { font-size: 13px; font-weight: 500; }
.picture-pick:focus-within .picture-pick-face { outline: 2px solid var(--primary); outline-offset: 2px; }
@media (max-width: 760px) {
  .record-control .sheet-chip { flex: 1 1 auto; width: 100%; min-height: 44px; font-size: 16px; }
  .react-button, .react-summary, .react.is-small .react-button, .react.is-small .react-summary, .react.is-line .react-button { min-height: 44px; min-width: 44px; }
  .feed-more-button, .feed-comment-more, .msg-row .msg-more, .msg-head .msg-more { min-width: 44px; min-height: 44px; width: 44px; height: 44px; }
  .feed-more-button { top: 0; right: -6px; }
  .feed-chip, .compose-chip, .msg-chip { min-height: 44px; }
  main input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="file"]):not([type="range"]), main select { min-height: 52px; }
  main textarea { min-height: 52px; }
  /* Three that older, more exact rules kept small: the post box's Post to
     chip, the comment box (44, as the Messages box), and a task's Assigned
     (44, as Status and Priority beside it). From the 718 test, 2026-10-21.
     MOBILE-012, patch 721. */
  .feed-compose-row .compose-chip { min-height: 44px; }
  .feed-comment-form textarea { min-height: 44px; height: 44px; border-radius: 22px; padding: 11px 16px; font-size: 16px; }
  .feed-comment-form button { min-height: 44px; }
  .record-control { min-height: 44px; }
  .record-control select { min-height: 42px; font-size: 16px; }
  /* Room for the space's name in the top bar: the icons sit edge to edge
     (each is still a 40 tap). From the 720 test: the name had 51px.
     UX-039, patch 721. */
  body.has-phone-shell .app-header { gap: 4px; }
  body.has-phone-shell .app-header-actions { gap: 0; }
}

/* Lists are rows on a phone: the name, and one line of what matters under
   it, as Today and the Tasks list already do. A table opts in with
   phone-rows; its name cell is record-name-cell or data-phone-main, and each
   cell kept for the line carries data-phone-meta (its value is a short label
   before it). Sarah, 2026-10-21, yes to the phone review. MOBILE-009,
   patch 719. */
@media (max-width: 760px) {
  .table-wrap:has(> table.phone-rows) { overflow: visible; }
  table.phone-rows { width: 100%; min-width: 0 !important; }
  table.phone-rows thead { display: none; }
  table.phone-rows, table.phone-rows tbody, table.phone-rows tr { display: block; }
  table.phone-rows tbody tr { padding: 12px 16px; border-bottom: 1px solid var(--border); }
  table.phone-rows td { display: none; padding: 0; border: 0; }
  table.phone-rows td.record-name-cell, table.phone-rows td[data-phone-main], table.phone-rows td[colspan] { display: block; }
  table.phone-rows td[data-phone-meta] { display: inline-flex; align-items: center; gap: 4px; margin: 4px 12px 0 0; color: var(--muted-foreground); font-size: 13px; }
  table.phone-rows td[data-phone-meta]:not([data-phone-meta=""])::before { content: attr(data-phone-meta); }
  table.phone-rows td[data-phone-meta] small { display: none; }
  table.phone-rows td[data-phone-meta]:has(> .muted:only-child) { display: none; }
  table.phone-rows td[data-phone-meta]:has(> [data-task-date]:empty) { display: none; }
  table.phone-rows td[data-phone-main] a, table.phone-rows td.record-name-cell a { text-decoration: none; }
  table.phone-rows tr.people-group td { padding-top: 6px; }
}

/* A portal on a phone: the top bar names the client and the bottom bar is its
   places, so the page's own heading, its sentence, the second row of tabs,
   the client pull-down and the Signed in as strip step aside. The page's tabs
   still work underneath: the bar opens each one by its address. Sarah,
   2026-10-22: "Calendar, Reviews, Requests, Photos, More". MOBILE-010,
   patch 724. */
@media (max-width: 760px) {
  body.has-phone-shell.limited-shell .role-strip,
  body.has-phone-shell.limited-shell .portal-page-head,
  body.has-phone-shell.limited-shell .portal-tabs > .view-tabs { display: none; }
}

/* Who sees a listing: one tap between the group, everyone on MyOps and the
   public Market, as chips. GROUP-009, patch 726. */
.market-head h1 { margin-right: auto; }
.listing-reach { margin: 0; border: 0; padding: 0; }
.listing-reach legend { margin-bottom: 6px; padding: 0; font-size: 13px; font-weight: 600; }
.listing-reach-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.listing-reach-chips .feed-chip { position: relative; cursor: pointer; }
.listing-reach-chips .feed-chip input { position: absolute; opacity: 0; pointer-events: none; }
.listing-reach-chips .feed-chip:has(input:checked) { border-color: var(--primary); background: color-mix(in srgb, var(--primary) 12%, var(--card)); color: var(--primary); }
.listing-reach-chips .feed-chip:has(input:focus-visible) { outline: 2px solid var(--primary); outline-offset: 2px; }
@media (max-width: 760px) {
  .listing-reach-chips .feed-chip { min-height: 44px; }
  .market-head { flex-wrap: wrap; }
}
.listing-reach-chips .feed-chip { display: inline-flex; align-items: center; gap: 4px; padding: 6px 14px; font-size: 14px; }
/* A listing's tags stay whole on a phone. Found in the patch 726 test. */
.listing-tags .market-kind, .listing-tags .market-status { white-space: nowrap; }
.listing-tags { flex-wrap: wrap; }

/* A client's own photos, into their library. ASSET-008, patch 729. */
.photo-add-form { display: flex; justify-content: flex-end; margin: 0 0 12px; }
.photo-add-button { cursor: pointer; }
.phone-add-form { margin: 0; }
.phone-add-form .phone-add-item { cursor: pointer; }
@media (max-width: 760px) {
  .photo-add-form .photo-add-button { width: 100%; min-height: 52px; justify-content: center; }
}

/* A client's Calendar: each project in its own color, and a chip per project
   with its color dot. CLIENT-027, patch 731. */
.client-calendar [style*="--pc"] { --client-color: var(--pc); }
.client-cal-chips { margin: 0 0 12px; }
.client-cal-chips .feed-chip { display: inline-flex; align-items: center; gap: 6px; }
.client-cal-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--pc, var(--muted-foreground)); }
/* On a phone the project chips slide in one row, as Your home's do, so the
   calendar starts right under them. Found in the patch 731 test. CLIENT-027,
   patch 732. */
@media (max-width: 760px) {
  .client-cal-chips { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin-right: -16px; padding-right: 16px; }
  .client-cal-chips::-webkit-scrollbar { display: none; }
  .client-cal-chips .feed-chip { flex: none; white-space: nowrap; }
}

/* Money: expenses with what was spent and what is deductible. The owner's
   only. COST-001, patch 735. */
.money-panel .record-card-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.money-panel .record-card-bar h2 { margin: 0; }
.money-totals { display: flex; flex-wrap: wrap; gap: 24px; margin: 4px 0 14px; }
/* A task's Money: one line with the total that opens to the list, and only
   once there is an expense. Patch 743. */
.money-fold { padding: 0; }
.money-fold > .money-fold-line { display: flex; align-items: center; gap: 12px; min-height: 48px; padding: 0 14px; cursor: pointer; list-style: none; }
.money-fold > .money-fold-line::-webkit-details-marker { display: none; }
.money-fold > .money-fold-line::after { content: ""; width: 7px; height: 7px; margin-left: auto; border-right: 1.6px solid var(--muted-foreground); border-bottom: 1.6px solid var(--muted-foreground); transform: rotate(-45deg); transition: transform .15s; }
.money-fold[open] > .money-fold-line::after { transform: rotate(45deg); }
.money-fold-title { font-weight: 600; }
.money-fold-line .muted { min-width: 0; padding: 12px 0; }
.money-fold > .money-fold-line { flex-wrap: nowrap; }
.money-fold[open] > .money-fold-line { border-bottom: 1px solid var(--border); }
.money-fold > :not(summary) { margin-left: 14px; margin-right: 14px; }
.money-fold > .record-card-bar { margin-top: 12px; justify-content: flex-end; }
.money-fold > .record-card-bar h2 { display: none; }
.money-fold > :last-child { margin-bottom: 14px; }
.money-note { margin: 8px 0 0; }
/* A lead's page: stage chips, details and people. LEAD-001, patch 746. */
.lead-card { margin-bottom: 16px; }
.lead-card > h2 { margin: 0 0 10px; font-size: 15px; }
.lead-stages { display: flex; flex-wrap: wrap; gap: 8px; }
.lead-link { margin: 0 0 12px; overflow-wrap: anywhere; }
.lead-add-steps { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin-top: 14px; }
.lead-add-steps form { margin: 0; }
.lead-people { list-style: none; margin: 0 0 12px; padding: 0; }
.lead-people li { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 0; border-top: 1px solid var(--border); }
.lead-people li:first-child { border-top: 0; }
.lead-people small { display: block; font-size: 12.5px; }
.lead-add-person { display: flex; gap: 8px; }
.lead-add-person input { flex: 1 1 auto; min-width: 0; }
@media (max-width: 760px) {
  body .lead-stages .feed-chip, body.has-phone-shell .lead-stages .feed-chip { min-height: 44px; font-size: 16px; }
  .lead-add-person input { min-height: 52px; font-size: 16px; }
  /* Won and Lost the same height, side by side. Found in the 746 test. Patch 747. */
  .record-actions > button, .record-actions .inline-form button { min-height: 44px; font-size: 16px; }
  /* Deleted projects, tasks and files read at 16px on a phone. Found in the 748 test. Patch 749. */
  .deleted-project-row, .deleted-project-row span, .deleted-project-row button { font-size: 16px; }
  /* Found in the 749 test. Patch 750. */
  .lead-add-steps button, .lead-add-steps a { font-size: 16px; }
  .lead-add-steps a { display: inline-flex; align-items: center; min-height: 44px; }
  .danger-card .danger-button { min-height: 44px; font-size: 16px; }
}
/* Remove vendor, under its details. Patch 745. */
.vendor-remove { margin: 16px 0 0; padding-top: 14px; border-top: 1px solid var(--border); }
.record-more-menu .record-more-item { display: block; width: 100%; min-height: 36px; margin-bottom: 4px; text-align: left; }
/* On a phone the menu reads at 16px, every item tap-sized. Found in the 743 test. Patch 744. */
@media (max-width: 760px) { .record-more-menu .text-button { min-height: 44px; font-size: 16px; } }
.money-totals div { display: grid; gap: 2px; }
.money-totals span { font-size: 12px; }
.money-totals strong { font-size: 20px; font-weight: 600; font-variant-numeric: tabular-nums; }
.money-table .money-amount { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.money-table small { display: block; }
.money-acts { white-space: nowrap; }
.money-acts form { display: inline; margin: 0; }
.money-acts a, .money-acts .text-button { margin-left: 10px; }
.money-two { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.money-deduct { margin: 0; border: 0; padding: 0; }
.money-deduct legend { margin-bottom: 6px; padding: 0; font-size: 13px; font-weight: 600; }
.money-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.money-chips .feed-chip { position: relative; display: inline-flex; align-items: center; padding: 6px 14px; font-size: 14px; cursor: pointer; }
.money-chips .feed-chip input { position: absolute; opacity: 0; pointer-events: none; }
.money-chips .feed-chip:has(input:checked) { border-color: var(--primary); background: color-mix(in srgb, var(--primary) 12%, var(--card)); color: var(--primary); }
.money-percent { margin-top: 8px; max-width: 200px; }
.money-deduct:not(:has(input[value="part"]:checked)) .money-percent { display: none; }
.money-categories { margin-top: 14px; }
.money-categories summary { cursor: pointer; font-weight: 600; font-size: 14px; }
.money-categories form { margin-top: 10px; }
@media (max-width: 760px) {
  .money-chips .feed-chip { min-height: 44px; }
  .money-acts a, .money-acts .text-button { min-height: 44px; display: inline-flex; align-items: center; }
  .money-two { grid-template-columns: 1fr; }
}
.money-table .money-date { white-space: nowrap; }
/* Removing an unused category; + Add expense full tap size. Patch 736. */
.money-category-row { display: flex; align-items: center; gap: 10px; }
.money-category-row input { flex: 1; }
.money-category-row .muted { flex: none; font-size: 13px; }
@media (max-width: 760px) {
  .money-panel .record-card-bar button { min-height: 44px; }
}

/* The update box's attach row fits its column at any width: the row wraps,
   and the photo library button shortens with an ellipsis rather than pushing
   the others out. Sarah, 2026-10-22, on a task in rTheory Operations: "the
   sidebar display of fields didn't resolve correctly without expanding my
   screen". TASK-037, patch 738. */
.discussion-compose .comment-form-foot { flex-wrap: wrap; justify-content: flex-start; }
.discussion-compose .comment-form-foot > * { min-width: 0; }
.discussion-compose .comment-form-foot [data-library-open] { flex: 1 1 140px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.discussion-compose .comment-form-foot button[type="submit"] { margin-left: auto; }
.discussion-compose .comment-attach input[type="file"] { max-width: 100%; }

/* Dropping documents in, and checking them before they are saved. COST-006,
   patch 739. */
.doc-drop-zone { margin: 0 0 14px; border: 1.5px dashed var(--border); border-radius: 12px; background: color-mix(in srgb, var(--secondary) 50%, var(--card)); transition: border-color .15s, background .15s; }
.doc-drop-zone.is-over { border-color: var(--primary); background: color-mix(in srgb, var(--primary) 8%, var(--card)); }
.doc-drop-zone.is-sending { opacity: .6; pointer-events: none; }
.doc-drop-label { display: grid; justify-items: center; gap: 2px; padding: 16px; cursor: pointer; text-align: center; }
.doc-drop-label input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.doc-drop-label strong { font-size: 14px; font-weight: 600; color: var(--primary); }
.doc-drop-label span { font-size: 12.5px; }
.doc-consent { margin-bottom: 16px; }
.doc-consent h2 { margin: 0 0 6px; }
.doc-consent-actions { display: flex; gap: 10px; margin-top: 10px; }
.doc-check { display: grid; gap: 14px; }
.doc-place { max-width: 420px; }
.doc-progress { display: grid; gap: 6px; font-size: 13px; color: var(--muted-foreground); }
.doc-progress i { display: block; height: 6px; border-radius: 3px; background: var(--secondary); overflow: hidden; }
.doc-progress b { display: block; height: 100%; width: 0; background: var(--primary); transition: width .3s; }
.doc-row { display: grid; grid-template-columns: 140px minmax(0, 1fr); gap: 16px; align-items: start; }
.doc-thumb { display: grid; place-items: center; aspect-ratio: 3 / 4; border: 1px solid var(--border); border-radius: 8px; background: var(--secondary); overflow: hidden; text-decoration: none; }
.doc-thumb img { width: 100%; height: 100%; object-fit: cover; }
.doc-pdf { font-size: 18px; font-weight: 600; color: var(--muted-foreground); }
.doc-fields { display: grid; gap: 10px; }
.doc-fields label { margin: 0; }
.doc-name { margin: 0; }
.doc-row.is-other .doc-money { display: none; }
.doc-row:has(.doc-drop input:checked) { opacity: .5; }
.doc-save { display: flex; justify-content: flex-end; }
@media (max-width: 760px) {
  .doc-row { grid-template-columns: minmax(0, 1fr); }
  .doc-thumb { aspect-ratio: auto; height: 160px; }
  .doc-save button { width: 100%; min-height: 52px; }
  .doc-consent-actions button { flex: 1; min-height: 44px; }
}
/* Reading documents already on tasks. COST-006, patch 741. */
.doc-from-tasks { margin: 0 0 14px; }
@media (max-width: 760px) {
  .doc-from-tasks button { width: 100%; min-height: 44px; }
}

/* One chip, everywhere: 8px corners, a light outline, 14px words centered in
   a fixed height; the picked one fills with a tint of your color and shows a
   check, so it never rests on color alone. Tags stay labels (contact-tag,
   prospect-tag): smaller, square-ish, tinted, never outlined. Sarah,
   2026-10-22: "I think the better ones are the less rounded version", the
   chip study's B. Written for both page kinds so it outranks every older
   chip rule above. Patch 751. */
body.has-phone-shell .feed-chip,
body:not(.has-phone-shell) .feed-chip,
body.has-phone-shell .msg-chip,
body:not(.has-phone-shell) .msg-chip,
body.has-phone-shell .phone-chip,
body:not(.has-phone-shell) .phone-chip,
body.has-phone-shell .whos-who-chip,
body:not(.has-phone-shell) .whos-who-chip,
body.has-phone-shell .pl-team-chip,
body:not(.has-phone-shell) .pl-team-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 32px;
  margin: 0;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--card);
  color: var(--foreground);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0;
  box-shadow: none;
  white-space: nowrap;
}
body.has-phone-shell .feed-chip:hover,
body:not(.has-phone-shell) .feed-chip:hover,
body.has-phone-shell .msg-chip:hover,
body:not(.has-phone-shell) .msg-chip:hover,
body.has-phone-shell .phone-chip:hover,
body:not(.has-phone-shell) .phone-chip:hover,
body.has-phone-shell .whos-who-chip:hover,
body:not(.has-phone-shell) .whos-who-chip:hover,
body.has-phone-shell .pl-team-chip:hover,
body:not(.has-phone-shell) .pl-team-chip:hover { background: color-mix(in srgb, var(--foreground) 4%, var(--card)); }
body.has-phone-shell .feed-chip[aria-pressed="true"],
body:not(.has-phone-shell) .feed-chip[aria-pressed="true"],
body.has-phone-shell .msg-chip[aria-pressed="true"],
body:not(.has-phone-shell) .msg-chip[aria-pressed="true"],
body.has-phone-shell .phone-chip[aria-pressed="true"],
body:not(.has-phone-shell) .phone-chip[aria-pressed="true"],
body.has-phone-shell .whos-who-chip[aria-pressed="true"],
body:not(.has-phone-shell) .whos-who-chip[aria-pressed="true"],
body.has-phone-shell .pl-team-chip[aria-pressed="true"],
body:not(.has-phone-shell) .pl-team-chip[aria-pressed="true"],
body.has-phone-shell .feed-chip.is-on,
body:not(.has-phone-shell) .feed-chip.is-on,
body.has-phone-shell .msg-chip.is-on,
body:not(.has-phone-shell) .msg-chip.is-on,
body.has-phone-shell .phone-chip.is-on,
body:not(.has-phone-shell) .phone-chip.is-on,
body.has-phone-shell .whos-who-chip.is-on,
body:not(.has-phone-shell) .whos-who-chip.is-on,
body.has-phone-shell .pl-team-chip.is-on,
body:not(.has-phone-shell) .pl-team-chip.is-on,
body.has-phone-shell .feed-chip.is-active,
body:not(.has-phone-shell) .feed-chip.is-active,
body.has-phone-shell .msg-chip.is-active,
body:not(.has-phone-shell) .msg-chip.is-active,
body.has-phone-shell .phone-chip.is-active,
body:not(.has-phone-shell) .phone-chip.is-active,
body.has-phone-shell .whos-who-chip.is-active,
body:not(.has-phone-shell) .whos-who-chip.is-active,
body.has-phone-shell .pl-team-chip.is-active,
body:not(.has-phone-shell) .pl-team-chip.is-active,
body.has-phone-shell .feed-chip:has(input:checked),
body:not(.has-phone-shell) .feed-chip:has(input:checked),
body.has-phone-shell .msg-chip:has(input:checked),
body:not(.has-phone-shell) .msg-chip:has(input:checked),
body.has-phone-shell .phone-chip:has(input:checked),
body:not(.has-phone-shell) .phone-chip:has(input:checked),
body.has-phone-shell .whos-who-chip:has(input:checked),
body:not(.has-phone-shell) .whos-who-chip:has(input:checked),
body.has-phone-shell .pl-team-chip:has(input:checked),
body:not(.has-phone-shell) .pl-team-chip:has(input:checked) {
  border-color: transparent;
  background: color-mix(in srgb, var(--primary) 13%, var(--card));
  color: color-mix(in srgb, var(--primary) 82%, #000000);
  font-weight: 500;
}
body.has-phone-shell .feed-chip[aria-pressed="true"]::before,
body:not(.has-phone-shell) .feed-chip[aria-pressed="true"]::before,
body.has-phone-shell .msg-chip[aria-pressed="true"]::before,
body:not(.has-phone-shell) .msg-chip[aria-pressed="true"]::before,
body.has-phone-shell .phone-chip[aria-pressed="true"]::before,
body:not(.has-phone-shell) .phone-chip[aria-pressed="true"]::before,
body.has-phone-shell .whos-who-chip[aria-pressed="true"]::before,
body:not(.has-phone-shell) .whos-who-chip[aria-pressed="true"]::before,
body.has-phone-shell .pl-team-chip[aria-pressed="true"]::before,
body:not(.has-phone-shell) .pl-team-chip[aria-pressed="true"]::before,
body.has-phone-shell .feed-chip.is-on::before,
body:not(.has-phone-shell) .feed-chip.is-on::before,
body.has-phone-shell .msg-chip.is-on::before,
body:not(.has-phone-shell) .msg-chip.is-on::before,
body.has-phone-shell .phone-chip.is-on::before,
body:not(.has-phone-shell) .phone-chip.is-on::before,
body.has-phone-shell .whos-who-chip.is-on::before,
body:not(.has-phone-shell) .whos-who-chip.is-on::before,
body.has-phone-shell .pl-team-chip.is-on::before,
body:not(.has-phone-shell) .pl-team-chip.is-on::before,
body.has-phone-shell .feed-chip.is-active::before,
body:not(.has-phone-shell) .feed-chip.is-active::before,
body.has-phone-shell .msg-chip.is-active::before,
body:not(.has-phone-shell) .msg-chip.is-active::before,
body.has-phone-shell .phone-chip.is-active::before,
body:not(.has-phone-shell) .phone-chip.is-active::before,
body.has-phone-shell .whos-who-chip.is-active::before,
body:not(.has-phone-shell) .whos-who-chip.is-active::before,
body.has-phone-shell .pl-team-chip.is-active::before,
body:not(.has-phone-shell) .pl-team-chip.is-active::before,
body.has-phone-shell .feed-chip:has(input:checked)::before,
body:not(.has-phone-shell) .feed-chip:has(input:checked)::before,
body.has-phone-shell .msg-chip:has(input:checked)::before,
body:not(.has-phone-shell) .msg-chip:has(input:checked)::before,
body.has-phone-shell .phone-chip:has(input:checked)::before,
body:not(.has-phone-shell) .phone-chip:has(input:checked)::before,
body.has-phone-shell .whos-who-chip:has(input:checked)::before,
body:not(.has-phone-shell) .whos-who-chip:has(input:checked)::before,
body.has-phone-shell .pl-team-chip:has(input:checked)::before,
body:not(.has-phone-shell) .pl-team-chip:has(input:checked)::before {
  content: "";
  flex: none;
  width: 14px;
  height: 14px;
  margin-left: -2px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12 5 5 9-10'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12 5 5 9-10'/%3E%3C/svg%3E") center / contain no-repeat;
}
@media (max-width: 760px) {
  body.has-phone-shell .feed-chip,
body:not(.has-phone-shell) .feed-chip,
body.has-phone-shell .msg-chip,
body:not(.has-phone-shell) .msg-chip,
body.has-phone-shell .phone-chip,
body:not(.has-phone-shell) .phone-chip,
body.has-phone-shell .whos-who-chip,
body:not(.has-phone-shell) .whos-who-chip,
body.has-phone-shell .pl-team-chip,
body:not(.has-phone-shell) .pl-team-chip { min-height: 44px; padding: 0 14px; font-size: 15px; }
}
.contact-tag, .prospect-tag { display: inline-flex; align-items: center; min-height: 22px; margin: 0 4px 0 0; border: 0; border-radius: 6px; padding: 0 8px; background: color-mix(in srgb, var(--primary) 12%, var(--card)); color: color-mix(in srgb, var(--primary) 82%, #000000); font-size: 12px; font-weight: 500; letter-spacing: 0; vertical-align: middle; }
.prospect-tag { margin-left: 6px; }
.nav-section-head button:hover, .nav-section-head a:hover { background: var(--chrome-hover); }
/* The rest of the chips (found in the 751 test, patch 752): photo and Feed
   tags are labels with a remove, so square-ish like the Lead tag; compose and
   library chips take the same 8px corners. One check mark for every picked
   chip, set once. */
:root { --chip-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12 5 5 9-10'/%3E%3C/svg%3E"); }
.asset-chip { border-radius: 6px; padding: 2px 8px; font-size: 12.5px; }
.feed-tag-chip, .library-chip { border-radius: 8px; }
.feed-compose-row .compose-chip { border-radius: 8px; }
/* Dark: the picked chip's words and the active rail icon keep their contrast. */
body[data-theme="dark"] .feed-chip[aria-pressed="true"], body[data-theme="dark"] .feed-chip:has(input:checked),
body[data-theme="dark"] .msg-chip[aria-pressed="true"], body[data-theme="dark"] .phone-chip[aria-pressed="true"],
body[data-theme="dark"] .whos-who-chip.is-on, body[data-theme="dark"] .pl-team-chip.is-on,
body[data-theme="dark"] .goal-chip input:checked + span { background: color-mix(in srgb, var(--primary) 26%, var(--card)); color: color-mix(in srgb, var(--primary) 45%, #ffffff); }
body[data-theme="dark"] .rail-nav a.active, body[data-theme="dark"] .rail-nav a:hover { background: color-mix(in srgb, var(--primary) 70%, #000000); }
body[data-theme="dark"] .context-nav a.active { color: color-mix(in srgb, var(--primary) 45%, #ffffff); background: color-mix(in srgb, var(--primary) 22%, transparent); }

/* The phone task list, as Sarah approved it, 2026-10-22: "Yes, build the
   phone task list as drawn". docs/mockups/_refresh/phone-tasks.html. The
   desktop table is unchanged: these parts show only on a phone. UX-043, patch 753. */
.task-check-cell, .task-who-cell, .phone-task-meta, .phone-list-chips { display: none; }
@media (max-width: 760px) {
  /* Tabs in words, a line under the open one, no tray; the pin only on the
     open tab (partials/record-tabs.php). */
  .view-tabs:not(.is-underline), .view-tabs-wrap.has-toolbar > .view-tabs:not(.is-underline) { gap: 20px; margin-bottom: 4px; padding: 0; border: 0; border-bottom: 1px solid var(--border); border-radius: 0; background: transparent; overflow-x: auto; scrollbar-width: none; }
  .view-tabs:not(.is-underline)::-webkit-scrollbar { display: none; }
  .view-tabs:not(.is-underline) label, .view-tabs-wrap.has-toolbar > .view-tabs:not(.is-underline) label { flex: none; min-height: 44px; padding: 10px 0; border-bottom: 2px solid transparent; border-radius: 0; font-size: 15px; font-weight: 500; text-transform: none; letter-spacing: 0; }
  .view-tabs label .tab-pin { display: none; }
  /* Search, Filters and ··· on one row; Filters as its icon. */
  .view-tabs-wrap.has-toolbar > .view-toolbar { flex-wrap: nowrap; align-items: center; }
  .view-tabs-wrap.has-toolbar > .view-toolbar .filter-bar { flex-wrap: nowrap; }
  .view-tabs-wrap.has-toolbar > .view-toolbar .filter-button [data-filter-count] { display: none; }
  .view-tabs-wrap.has-toolbar > .view-toolbar .filter-button.is-on [data-filter-count] { display: inline; }
  /* One search: the one above filters the list. Open and Completed as chips. */
  .card:has(> .table-wrap > .task-list-table) > .list-search { display: none; }
  .card:has(> .table-wrap > #project-tasks-table) .completed-switch { display: none; }
  .phone-list-chips { display: flex; gap: 8px; }
  .phone-list-chips .feed-chip small { color: inherit; opacity: .7; font-size: 13px; }
  /* Each row: a checkbox, the title, its column and a readable date, and who has it. */
  .task-list-table tbody tr.task-phone-row { display: grid; grid-template-columns: 28px minmax(0, 1fr) 22px; column-gap: 12px; align-items: start; padding: 13px 16px; }
  .task-list-table td.task-check-cell { display: block; grid-column: 1; grid-row: 1; }
  .task-list-table td[data-phone-main] { grid-column: 2; grid-row: 1; }
  .task-list-table td.task-who-cell { display: block; grid-column: 3; grid-row: 1; }
  .task-check-cell form { margin: 0; }
  .task-check-cell button { display: grid; place-items: center; width: 44px; height: 44px; min-height: 0; margin: -10px 0 0 -10px; padding: 0; border: 0; background: none; box-shadow: none; }
  .task-check-cell span { display: grid; place-items: center; width: 24px; height: 24px; border: 1.6px solid #a1a1aa; border-radius: 50%; }
  tr.is-done .task-check-cell span { border-color: var(--primary); background: var(--primary); }
  tr.is-done .task-check-cell span::after { content: ""; width: 9px; height: 5px; border: 2px solid #fff; border-top: 0; border-right: 0; transform: rotate(-45deg) translateY(-1px); }
  .task-list-table td[data-phone-main] a { font-size: 16px; line-height: 1.35; color: var(--foreground); }
  .task-list-table tr.is-done td[data-phone-main] a { color: var(--muted-foreground); }
  .task-list-table .ticket-badge, .task-list-table td[data-phone-main] small { display: none; }
  .phone-task-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin-top: 6px; color: var(--muted-foreground); font-size: 13.5px; }
  .phone-task-meta:not(:has(*)) { display: none; }
  .phone-task-meta .is-late { color: var(--destructive); font-weight: 500; }
  .phone-task-tag { display: inline-flex; align-items: center; min-height: 22px; padding: 0 8px; border-radius: 6px; background: var(--secondary); color: var(--foreground); font-size: 12.5px; font-weight: 500; }
  .task-who { display: grid; place-items: center; width: 22px; height: 22px; margin-top: 1px; border-radius: 50%; background: color-mix(in srgb, var(--primary) 72%, #000000); color: #fff; font-size: 10px; font-weight: 600; }
  /* Room at the end, so the last task scrolls clear of the + button. */
  .view-panel[data-view="tasks"] { padding-bottom: 96px; }
  /* The picture at the top: 32px, no ring, still a 44px tap. */
  .user-menu > summary { border-color: transparent; background: transparent; padding: 6px; }
  .user-menu > summary .avatar { min-width: 32px; min-height: 32px; width: 32px; height: 32px; }
}
/* Found in the 754 test. Patch 755. The × beside Filters is a full tap on a
   phone; in dark mode a picked goal chip keeps its state color. */
@media (max-width: 760px) { .filter-open .filter-clear { display: inline-grid; place-items: center; width: 44px; height: 44px; } }
body[data-theme="dark"] .goal-chip.is-drifting input:checked + span { background: #3a2c0c; color: #f5c56a; }
body[data-theme="dark"] .goal-chip.is-stuck input:checked + span { background: #3b1717; color: #f4a3a3; }
body[data-theme="dark"] .goal-chip.is-gap input:checked + span { background: #3a2212; color: #f7b98a; }
/* Menu sections you fold and move (assets/js/nav-sections.js). NAV-017, patch 756. */
.nav-section { display: flex; flex-direction: column; gap: 3px; }
.nav-section-head.is-foldable { cursor: pointer; user-select: none; touch-action: none; border-radius: 8px; }
.nav-section-head.is-foldable:hover { background: var(--chrome-hover); }
.nav-section-head.is-foldable > span:first-child::after { content: ""; display: inline-block; width: 6px; height: 6px; margin: 0 0 2px 8px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(45deg); opacity: .6; transition: transform .15s; }
.nav-section.is-folded > .nav-section-head > span:first-child::after { transform: rotate(-45deg); margin-bottom: 0; }
.nav-section.is-folded > :not(.nav-section-head) { display: none !important; }
.nav-section.is-dragging { opacity: .6; }
.nav-section.is-dragging > .nav-section-head { background: var(--chrome-hover); cursor: grabbing; }
/* The main button on Groups, the Market and Your home. NAV-018, patch 757. */
.disc-act { margin: 0 0 16px; }
.market-list-pick { position: relative; display: inline-block; }
.market-list-pick > summary { list-style: none; cursor: pointer; }
.market-list-pick > summary::-webkit-details-marker { display: none; }
.market-list-groups { position: absolute; z-index: 20; top: calc(100% + 6px); left: 0; min-width: 220px; display: grid; gap: 2px; padding: 8px; border: 1px solid var(--border); border-radius: 12px; background: var(--card); box-shadow: 0 8px 24px rgba(0, 0, 0, .12); }
.market-list-groups .muted { padding: 4px 10px 6px; font-size: 13px; }
.market-list-groups a { display: flex; align-items: center; min-height: 40px; padding: 0 10px; border-radius: 8px; color: var(--foreground); text-decoration: none; }
.market-list-groups a:hover { background: var(--chrome-hover); }
.page-header .home-create-space { margin-left: auto; }
.group-market-link { margin: 8px 0 4px; }
.public-places-form { margin: 16px 0 0; }
@media (max-width: 760px) { .market-list-groups a { min-height: 48px; font-size: 16px; } .disc-act .button, .market-list-pick > summary { min-height: 44px; } }
/* An on/off switch with its title and a line under it, shared by a client's
   photo setting and Profile's Groups and Market. Found in the 757 test, patch 758. */
.photo-owner-label { display: flex; align-items: center; justify-content: space-between; gap: 16px; cursor: pointer; }
.photo-owner-label strong { display: block; font-size: 14px; font-weight: 600; }
.photo-owner-label small { color: var(--muted-foreground); font-size: 13px; }
.photo-owner-label input[type="checkbox"] { appearance: none; -webkit-appearance: none; width: 40px; height: 22px; border-radius: 999px; background: var(--border); position: relative; flex: none; cursor: pointer; transition: background .15s; margin: 0; }
.photo-owner-label input[type="checkbox"]::after { content: ""; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: #fff; transition: left .15s; }
.photo-owner-label input[type="checkbox"]:checked { background: var(--primary); }
.photo-owner-label input[type="checkbox"]:checked::after { left: 21px; }
.photo-owner-label small { display: block; }
.photo-owner-label > span { min-width: 0; }
/* Paused accounts on System Activity, and a one-time message. SECURITY-023, patch 759. */
.paced-list { list-style: none; margin: 8px 0 0; padding: 0; }
.paced-list li { padding: 8px 0; border-top: 1px solid var(--border); }
.app-notice { margin: 0 0 16px; }
/* The agree-again screen: the terms link on top, what changed highlighted. LEGAL-001, patch 761. */
.accept-terms-link { margin: 0 0 12px; font-weight: 500; }
.accept-terms-changes { margin: 8px 0 12px; padding: 12px 14px 12px 32px; border-radius: 10px; background: color-mix(in srgb, var(--primary) 9%, var(--card)); }
.accept-terms-changes li { margin: 4px 0; }

/* Pages: the group's public page with Follow, Posts, About and Events under
   the name, and the cover and picture changed on the pictures themselves.
   docs/mockups/pages.html. PAGE-001, patch 767. */
.page-cover { position: relative; }
.page-pic-wrap { position: relative; flex: none; }
.page-photo-form { margin: 0; }
.page-photo-edit { display: inline-flex; align-items: center; gap: 6px; border: 0; cursor: pointer; }
.page-photo-edit input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.page-photo-edit svg { flex: none; width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.page-photo-edit:focus-within { outline: 2px solid var(--primary); outline-offset: 2px; }
.page-photo-edit.is-cover { position: absolute; right: 14px; bottom: 14px; min-height: 36px; border-radius: 8px; background: rgba(255, 255, 255, .92); color: #18181b; padding: 0 12px; font-size: 13px; font-weight: 600; box-shadow: 0 1px 3px rgba(0, 0, 0, .15); }
.page-photo-edit.is-cover:hover { background: #fff; }
.page-photo-edit.is-pic { position: absolute; right: -4px; bottom: -2px; justify-content: center; width: 32px; height: 32px; border: 2px solid var(--card); border-radius: 50%; background: var(--secondary); color: var(--foreground); }
.page-photo-edit.is-pic:hover { background: var(--muted); }
.page-acts { display: flex; flex-wrap: wrap; gap: 8px; }
.page-acts form { margin: 0; }
.page-acts svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.page-acts .button, .page-acts .secondary-button { display: inline-flex; align-items: center; gap: 6px; }
.page-tabs { display: flex; gap: 28px; margin: 0 18px; border-top: 1px solid var(--border); overflow-x: auto; scrollbar-width: none; }
.page-tabs::-webkit-scrollbar { display: none; }
.page-tabs a { flex: none; min-height: 44px; padding: 12px 1px 10px; border-bottom: 3px solid transparent; color: var(--muted-foreground); font-size: 14px; font-weight: 600; text-decoration: none; white-space: nowrap; }
.page-tabs a:hover { color: var(--foreground); }
.page-tabs a[aria-current="page"] { border-bottom-color: var(--primary); color: var(--primary); }
.page-about-full { display: grid; gap: 14px; padding: 18px; }
.page-about-full h2 { margin: 0; font-size: 15px; font-weight: 600; }
.page-about-words { max-width: 62ch; }
.page-about-full dl { display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 10px 16px; margin: 0; font-size: 13.5px; }
.page-about-full dt { color: var(--muted-foreground); }
.page-about-full dd { min-width: 0; margin: 0; overflow-wrap: anywhere; }
.page-facts { display: grid; gap: 8px; margin: 10px 0 0; padding: 0; list-style: none; font-size: 13.5px; }
.page-facts li { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 8px; align-items: start; }
.page-facts li span { min-width: 0; overflow-wrap: anywhere; }
.page-facts svg { width: 16px; height: 16px; margin-top: 2px; fill: none; stroke: var(--muted-foreground); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.page-faces { display: flex; margin: 8px 0 6px; }
.page-faces span { display: grid; place-items: center; width: 30px; height: 30px; margin-right: -6px; border: 2px solid var(--card); border-radius: 50%; color: #fff; font-size: 11px; font-weight: 600; }
.page-reach { display: inline-flex; align-items: center; gap: 6px; border-radius: 6px; background: var(--secondary); padding: 3px 8px; font-size: 12.5px; font-weight: 500; }
.page-reach-line { margin-top: 12px; }
.page-form-page { width: min(640px, 100%); }
.page-form-page .cw-box h1 { margin: 0; font-size: 20px; font-weight: 600; }
.page-form-page .cw-box h2 { font-size: 16px; }
.page-follower-list { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; font-size: 14px; }
@media (max-width: 760px) {
  .page-acts { width: 100%; }
  .page-acts > a, .page-acts > button, .page-acts > form, .page-acts > form button { flex: 1; justify-content: center; width: 100%; }
  .page-tabs { gap: 22px; margin: 0 14px; }
  .page-about-full dl { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .page-about-full dd { margin-bottom: 10px; }
  .page-photo-edit.is-cover span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .page-photo-edit.is-cover { top: 10px; right: 10px; bottom: auto; justify-content: center; width: 40px; min-height: 40px; padding: 0; border-radius: 50%; }
}

/* A Page's category: type what it is, pick from the list or use your own
   words. Patch 768. */
.cat-field { display: grid; gap: 6px; font-size: 13px; font-weight: 600; }
.cat-field [hidden] { display: none !important; }
.cat-box { position: relative; }
.cat-box input { width: 100%; }
.cat-list { position: absolute; top: 100%; left: 0; right: 0; z-index: 20; max-height: 340px; margin: 4px 0 0; padding: 4px; overflow-y: auto; list-style: none; border: 1px solid var(--border); border-radius: 10px; background: var(--card); box-shadow: 0 8px 24px rgba(0, 0, 0, .12); }
.cat-list li { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 44px; padding: 8px 10px; border-radius: 7px; cursor: pointer; font-weight: 400; }
.cat-list li[aria-selected="true"], .cat-list li:hover { background: var(--secondary); }
.cat-name { display: grid; gap: 1px; min-width: 0; }
.cat-name strong { font-size: 14px; font-weight: 500; }
.cat-name small { color: var(--muted-foreground); font-size: 12px; }
.cat-main { flex: none; border-radius: 6px; background: var(--secondary); padding: 2px 8px; color: var(--muted-foreground); font-size: 12px; font-weight: 500; }
.cat-list li[aria-selected="true"] .cat-main, .cat-list li:hover .cat-main { background: var(--card); }
.cat-chosen { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.cat-chip { display: inline-flex; align-items: center; gap: 8px; min-height: 36px; border: 1px solid var(--border); border-radius: 8px; background: var(--card); padding: 0 6px 0 12px; font-size: 14px; font-weight: 500; }
.cat-chip button { display: grid; place-items: center; width: 28px; height: 28px; border: 0; border-radius: 6px; background: transparent; color: var(--muted-foreground); cursor: pointer; font-size: 16px; }
.cat-chip button:hover { background: var(--secondary); color: var(--foreground); }
.cat-under { color: var(--muted-foreground); font-size: 13px; font-weight: 400; }
.cat-pick { display: grid; gap: 8px; border-top: 1px solid var(--border); padding-top: 12px; }
.cat-pick p { margin: 0; font-size: 13px; font-weight: 600; }
.cat-pick.is-needed p { color: var(--destructive, #b91c1c); }
.cat-mains { display: flex; flex-wrap: wrap; gap: 6px; }
.cat-mains button { min-height: 36px; border: 1px solid var(--border); border-radius: 6px; background: var(--card); padding: 0 12px; color: var(--foreground); cursor: pointer; font: inherit; font-size: 13px; font-weight: 500; }
.cat-mains button[aria-pressed="true"] { border-color: var(--primary); background: var(--primary); color: var(--primary-foreground, #fff); }
.category-ask { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; }
.category-ask-acts { display: flex; gap: 8px; margin: 0; }
@media (max-width: 760px) { .cat-main { display: none; } }

/* The on/off look for a group's and a Page's settings switches, the same as
   the Profile switch. Found in the 767 test. Patch 768. */
.group-switch input[role="switch"] { appearance: none; -webkit-appearance: none; position: relative; flex: none; width: 40px; height: 22px; margin: 0; border-radius: 999px; background: var(--border); cursor: pointer; transition: background .15s; }
.group-switch input[role="switch"]::after { content: ""; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: #fff; transition: left .15s; }
.group-switch input[role="switch"]:checked { background: var(--primary); }
.group-switch input[role="switch"]:checked::after { left: 21px; }
.group-switch input[role="switch"]:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

/* Posts on a Page and in the Feed. Patch 769. */
.page-compose { margin-bottom: 8px; }
.page-compose textarea { width: 100%; }
.page-compose .feed-compose-row { display: flex; align-items: center; gap: 8px; }
.page-compose .feed-compose-row .button { margin-left: auto; }
.page-compose .feed-photo input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; }
.page-compose-count { font-size: 13px; }
.page-by { color: var(--muted-foreground); font-size: 12.5px; }
img.feed-av.page-post-pic { object-fit: cover; }
.page-post-delete { margin: 6px 0 0; }

/* The 768 test: phone forms keep 16px edges, main-category chips are 44px
   to tap. Patch 769. */
@media (max-width: 760px) {
  .public-shell:has(.page-form-page) { padding: 12px 0 24px; }
  .page-form-page .pub-bar, .page-form-page > .group-back, .page-form-page > .form-error { padding: 0 16px; }
  .page-form-page .cw-box { border-right: 0; border-left: 0; border-radius: 0; padding: 20px 16px; }
  .cat-mains button { min-height: 44px; }
}

/* A Page on a phone: edge to edge, with 16px inside, as Create a page and
   Edit page. Found in the 769 test. Patch 770. */
@media (max-width: 760px) {
  .public-shell:has(.page-view) { padding: 12px 0 24px; }
  .page-view > .pub-bar, .page-view > .form-error { padding: 0 16px; }
  .page-view > .card, .page-view .pub-cols > .card, .page-view .pub-side > .card { border-right: 0; border-left: 0; border-radius: 0; }
  .page-view .pub-posts, .page-view .pub-side .card, .page-view .page-about-full { padding-right: 16px; padding-left: 16px; }
  .page-view .pub-info { padding-right: 16px; padding-left: 16px; }
  .page-view .page-tabs { margin: 0 16px; }
  .page-view .page-compose { padding: 0; border: 0; background: transparent; box-shadow: none; }
}

/* Option C: running words get a little more room between lines, and no
   heading pulls its letters in. Patch 771. UX-040. */
.feed-body, .formatted-text, .page-about-words, .pub-posts p { line-height: 1.6; }
h1, h2, h3 { letter-spacing: .01em; }

/* Your home on a computer: a wider Feed and right column, with Messages above
   Coming up; on a phone Messages stays in the header's icon. Sarah,
   2026-10-24: "the feed is so narrow. It just looks odd", then "yes with
   messages ... events should be below messages". UX-040, patch 772. */
.home-messages .home-msg-av { display: grid; place-items: center; flex: none; width: 32px; height: 32px; border-radius: 50%; color: #fff; font-size: 11px; font-weight: 600; }
.home-messages li.is-unread strong::after { content: ""; display: inline-block; width: 8px; height: 8px; margin-left: 6px; border-radius: 50%; background: var(--primary); vertical-align: middle; }
.home-messages .home-coming-text small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.home-side-more { display: inline-block; margin-top: 6px; font-size: 13px; font-weight: 600; text-decoration: none; }

/* An arranged page's head and boxes: the Dashboard, Your home and a group's
   Feed. Moved from home.php so all three share them. Sarah, 2026-10-24: "I
   think the grid is the way to go. Across the board". UX-040, patch 773. */
.home-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; }
.home-head p { margin: 0; color: var(--muted-foreground); font-size: 13px; }
.home-head h2 { margin: 0; font-size: 24px; font-weight: 600; letter-spacing: .01em; }
@media (max-width: 760px) {
  .home-head { flex-wrap: wrap; }
  .home-head h2 { font-size: 21px; }
}
.home-box { position: relative; min-width: 0; border: 1px solid var(--border); border-radius: 14px; background: var(--card); }
.home-box.is-big { border: 0; background: transparent; }
.box-head { display: flex; align-items: center; gap: 8px; padding: 12px 16px; cursor: grab; -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
.box-big-tools { position: absolute; top: 8px; right: 8px; z-index: 2; display: flex; gap: 4px; }
.box-big-tools .box-more, .box-big-tools .box-remove { margin: 0; background: rgba(255, 255, 255, .14); color: #fff; }
.box-big-tools .box-more:hover, .box-big-tools .box-more:focus-visible, .box-big-tools .box-remove:hover, .box-big-tools .box-remove:focus-visible { background: rgba(255, 255, 255, .26); color: #fff; }
.home-box.is-big .home-big { -webkit-touch-callout: none; }

/* A long box name shortens with … in a narrow column, so the box's ··· and
   × stay inside it. Found in the patch 656 test. DASH-003, patch 657. */
.box-fold { display: inline-flex; flex: 1; align-items: center; justify-content: flex-start; gap: 6px; min-width: 0; min-height: 0; margin: 0; border: 0; padding: 0; background: none; color: var(--foreground); text-align: left; cursor: pointer; }
.home-late { border-radius: 8px; background: #fef2f2; padding: 6px 8px; color: #991b1b; font-size: 13px; font-weight: 600; text-decoration: none; }
.home-none { padding: 5px 2px; font-size: 12.5px; }
.box-fold h3 { min-width: 0; margin: 0; overflow: hidden; font-size: 15px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.box-chev { flex: none; width: 16px; height: 16px; color: var(--muted-foreground); transition: transform .15s; }
.home-box.is-folded .box-chev { transform: rotate(-90deg); }
.home-box.is-folded .box-body { display: none; }
.box-body { padding: 0 16px 16px; }

/* An arranged page's frame, and Coming up and Messages inside their boxes.
   UX-040, patch 773. */
.arranged { display: grid; gap: 16px; }
.home-box .home-coming { padding: 0; }
.home-box .home-coming ul { margin: 0; }
/* On a phone, Your home's and a group's Feed stay edge to edge as before,
   with no box around them and no Add or Layout; Messages and Coming up
   follow as boxes. Patch 773. */
@media (max-width: 760px) {
  .arranged > .home-head { display: none; }
  .arranged .home-box[data-box="feed"] { margin: 0 -16px; border: 0; border-radius: 0; background: transparent; box-shadow: none; }
  .arranged .home-box[data-box="feed"] > .box-head { display: none; }
  .arranged .home-box[data-box="feed"] > .box-body { padding: 0 16px; }
  body.has-phone-shell .arranged .home-feed { margin: 0; }
}

/* The brand, bigger and stacked: the name above "by rTheory", nudged right
   and centered beside the mark. Sarah, 2026-10-24, from three at actual size:
   "Bigger, stacked". UX-040, patch 775. */
.app-header .brand > div { display: grid; gap: 1px; padding-left: 4px; }
.app-header .brand strong { font-size: 21px; font-weight: 500; line-height: 1.1; letter-spacing: .02em; }
.app-header .brand span { font-size: 14px; line-height: 1.25; color: var(--muted-foreground); letter-spacing: .03em; }

/* Goal pictures: line icons first, in the goal's color, then the emoji; and a
   picture big enough to see on a card. Sarah, 2026-10-24: "It's this tiny
   little speck in the middle of a goal". UX-040, patch 775. */
.goal-icons { display: grid; gap: 8px; }
.goal-icon-row { display: flex; flex-wrap: wrap; gap: 6px; }
.goal-icon-pick.is-line span { color: var(--goal-color, var(--foreground)); }
.goal-icon-pick.is-line input:checked + span { border-color: var(--goal-color, var(--primary)); background: color-mix(in srgb, var(--goal-color, var(--primary)) 12%, var(--card)); color: var(--goal-color, var(--primary)); }
.goal-color { display: grid; gap: 6px; }
.goal-color-label { font-size: 13px; font-weight: 600; }
.goal-card-art { height: 96px; font-size: 40px; }
.goal-card-art .goal-emoji { font-size: 40px; line-height: 1; }
.goal-line { display: block; }
.goal-hero-art { color: var(--goal-color, var(--foreground)); }
.goal-hero-art .goal-emoji { font-size: 44px; line-height: 1; }
.home-big-art { color: #fff; }
.home-big-art .goal-emoji { font-size: 44px; line-height: 1; }

/* The space switcher on a computer: where you are, opening Your home and your
   spaces by kind, each with its own picture. Phones keep their circles.
   UX-040, patch 775. */
.space-menu { position: relative; }
.space-menu > summary { list-style: none; }
.space-menu > summary::-webkit-details-marker { display: none; }
.space-menu-button { display: inline-flex; align-items: center; gap: 8px; min-height: 38px; max-width: 280px; border: 1px solid var(--border); border-radius: 10px; background: var(--card); padding: 4px 10px 4px 6px; color: var(--foreground); font-size: 14px; font-weight: 500; cursor: pointer; }
.space-menu-button:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); }
.space-menu[open] > .space-menu-button { border-color: var(--primary); }
.space-menu-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.space-menu-chev { flex: none; color: var(--muted-foreground); transition: transform .15s; }
.space-menu[open] .space-menu-chev { transform: rotate(180deg); }
.space-menu-panel { position: absolute; top: calc(100% + 6px); right: 0; z-index: 60; display: grid; width: 300px; max-height: min(70vh, 560px); overflow-y: auto; border: 1px solid var(--border); border-radius: 12px; background: var(--card); padding: 6px; box-shadow: 0 10px 30px rgba(19, 34, 38, .16); }
.space-menu-head { margin: 8px 10px 2px; color: var(--muted-foreground); font-size: 12px; font-weight: 500; }
.space-menu-form { margin: 0; }
.space-menu-item { display: flex; align-items: center; justify-content: flex-start; gap: 10px; width: 100%; min-height: 40px; border: 0; border-radius: 8px; background: transparent; padding: 6px 10px; color: var(--foreground); font: inherit; font-size: 14px; text-align: left; text-decoration: none; cursor: pointer; box-shadow: none; }
.space-menu-item:hover, .space-menu-item:focus-visible { background: var(--secondary); }
.space-menu-item.is-current { background: color-mix(in srgb, var(--primary) 10%, transparent); color: color-mix(in srgb, var(--primary) 88%, var(--foreground)); }
.space-menu-item span:last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.home-nav-pic.is-home { background: var(--secondary); color: var(--foreground); }
@media (max-width: 760px) {
  body.has-phone-shell .app-header .space-menu { display: none; }
}

/* Room all the way around the brand, so it doesn't crowd the bar; the bar
   grows to fit. Sarah, 2026-10-24: "needs a little white space all the way
   around. It might make the header bar bigger, but that's okay". On a phone
   the bar shows the mark alone and keeps its height. UX-040, patch 777. */
@media (min-width: 761px) {
  .app-header .brand { padding: 12px 20px 12px 8px; }
}

/* All seven days always fit beside the lists on a computer: the days get
   narrower and long task names are cut short, with no sideways scroll. Sarah,
   2026-10-24, of two shown: "Narrower days". UX-033, patch 779. */
@media (min-width: 761px) {
  .calendar-grid.is-month, .calendar-grid.is-week { grid-template-columns: repeat(7, minmax(0, 1fr)); }
  .calendar-grid.is-five-day { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .calendar-grid .calendar-day { min-width: 0; }
  .calendar-grid.is-month .calendar-task { overflow: hidden; min-width: 0; }
}
/* Inside a Dashboard box the seven days fit the box too, names cut short;
   the box stacks its lists above the calendar when narrow (dashboard.php).
   Sarah, 2026-10-24: "see calendar in right column - bug". UX-033, patch 786
   (in place of 785's sideways scroll). */
@media (min-width: 761px) {
  .home-box .calendar-day-head { min-width: 0; overflow: hidden; }
  .home-box .calendar-grid.is-month .calendar-task * { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
  .home-box .calendar-grid.is-month .calendar-task strong { white-space: nowrap; }
}
/* Names are cut short only where the days are narrow; wider windows keep
   them whole, as before. */
@media (min-width: 761px) and (max-width: 1279px) {
  .calendar-grid.is-month .calendar-task * { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
  .calendar-grid.is-month .calendar-task strong { white-space: nowrap; }
}

/* A phone's Month: a small grid of days with a dot under a busy one, the
   chosen day filled, and that day's work under it. A phone's Week: the days one
   under the next. Sarah, 2026-10-24, of two shown: "Like phone calendars".
   MOBILE-004, patch 781. */
.phone-month { display: grid; gap: 2px; margin: 0 0 14px; border-bottom: 1px solid var(--border); padding: 2px 0 10px; }
.phone-month-head, .phone-month-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.phone-month-head span { padding: 4px 0; color: var(--muted-foreground); font-size: 12px; text-align: center; }
.phone-month-day { display: grid; justify-items: center; align-content: center; gap: 3px; min-height: 48px; margin: 0; border: 0; border-radius: var(--radius-sm); background: transparent; padding: 3px 0; color: var(--foreground); box-shadow: none; font-size: 16px; cursor: pointer; }
.phone-month-day:hover, .phone-month-day:focus-visible { background: var(--secondary); }
.phone-month-num { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 999px; font-weight: 500; line-height: 1; }
.phone-month-day.is-muted { color: var(--muted-foreground); }
.phone-month-day.is-today .phone-month-num { color: var(--primary); font-weight: 600; }
.phone-month-day.is-selected .phone-month-num { background: var(--primary); color: var(--primary-foreground); }
.phone-month-dot { width: 5px; height: 5px; border-radius: 999px; background: var(--primary); }
.phone-month-dot[hidden] { display: block; visibility: hidden; }
.calendar-grid.is-phone-week .calendar-day-pane + .calendar-day-pane { margin-top: 14px; border-top: 1px solid var(--border); padding-top: 12px; }
.calendar-grid.is-phone-week .empty-note { margin: 0; padding: 2px 8px 0; color: var(--muted-foreground); font-size: 14px; text-align: left; }
.calendar-grid.is-phone-week .calendar-day-head-line { margin-bottom: 6px; }

/* A phone cannot drag or right-click, so the hint line goes; tapping a card
   offers Move to another day. Sarah, 2026-10-24: "Hide it on phones".
   MOBILE-002, patch 782. */
@media (max-width: 760px) {
  .calendar-drag-hint { display: none; }
}

/* Your home and a group's Feed on a phone, as the mockup Sarah approved on
   2026-10-24 ("Build Your home on a phone as the mockup shows"): the post box
   folded away until the + opens it; each post's header on its own, the name
   then one grey line, the words starting below it, full width; Like and
   Comment as small outlined buttons, close together, then Comment…; the
   circles filter, All first. UX-040, NAV-015, patch 783. */
.feed-say { display: none; }
@media (max-width: 760px) {
  body.has-phone-shell.is-social-feed .feed-surface .feed-compose:not(.is-open) { display: none; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-entry { grid-template-columns: 40px minmax(0, 1fr); column-gap: 10px; row-gap: 0; align-items: center; padding: 14px 16px 8px; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-entry > .feed-av { grid-row: 1; width: 40px; height: 40px; font-size: 14px; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-main { display: contents; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-main > * { grid-column: 1 / -1; margin-left: 0; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-main > .feed-who { display: flex; flex-wrap: wrap; align-items: baseline; grid-column: 2; grid-row: 1; min-height: 0; padding-right: 34px; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-who { gap: 1px 6px; color: var(--muted-foreground); font-size: 13px; line-height: 1.35; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-who strong { flex: 0 0 100%; color: var(--foreground); font-size: 15px; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-who time { flex: none; font-size: 13px; white-space: nowrap; }
  /* The space and the time on one line; a long space name is cut short. */
  body.has-phone-shell.is-social-feed .feed-entry .feed-where { display: inline; flex: 1 1 0; min-width: 0; max-width: fit-content; margin: 0; overflow: hidden; font-size: 13px; white-space: nowrap; text-overflow: ellipsis; }
  body.has-phone-shell.is-social-feed .feed-entry .feed-where b { color: var(--muted-foreground); font-weight: 500; }
  body.has-phone-shell.is-social-feed .feed-entry .feed-in { display: none; }
  body.has-phone-shell.is-social-feed .feed-entry .feed-where ~ time::before { content: "·"; margin-right: 6px; }
  /* Filtered to one space, the space goes without saying. */
  body.has-phone-shell .home-feed[data-showing] .feed-where { display: none; }
  body.has-phone-shell .home-feed[data-showing] .feed-where ~ time::before { content: none; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-body { margin-top: 12px; font-size: 15.5px; line-height: 1.5; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-unfold { margin-top: 2px; color: var(--primary); font-size: 15px; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-entry .feed-main > .feed-photos { margin: 12px -16px 0; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-refs:empty { display: none; }
  body.has-phone-shell.is-social-feed .feed-surface .react.is-line { gap: 8px; margin-top: 14px; }
  body.has-phone-shell.is-social-feed .feed-surface .react.is-line .react-button,
  body.has-phone-shell.is-social-feed .feed-surface .react.is-line .react-summary,
  body.has-phone-shell.is-social-feed .feed-surface .feed-say { min-height: 36px; margin: 0; border: 1px solid var(--border); border-radius: 999px; background: var(--background); padding: 0 12px; color: var(--foreground); font-size: 13.5px; font-weight: 500; }
  body.has-phone-shell.is-social-feed .feed-surface .react.is-line .react-button.is-mine { color: var(--primary); }
  body.has-phone-shell.is-social-feed .feed-surface .feed-say { display: inline-flex; flex: 1; align-items: center; order: 9; color: var(--muted-foreground); font-weight: 400; box-shadow: none; text-align: left; }
  body.has-phone-shell .home-strip button[aria-pressed="true"] .home-nav-pic { outline: 2px solid var(--primary); outline-offset: 2px; }
  body.has-phone-shell .home-strip button[aria-pressed="true"] span:last-child { font-weight: 600; }
  body.has-phone-shell .home-strip .home-strip-all-pic { display: grid; place-items: center; background: var(--accent); color: var(--primary); font-size: 14px; font-weight: 600; }
  body.has-phone-shell .phone-pick-space .home-nav-pic { width: 28px; height: 28px; margin-right: 4px; border-radius: 9px; font-size: 11px; }
}

/* One menu on a phone, under your picture: the ☰ at the top and the picture
   beside the bell go, More becomes your picture, last in the bar, and the menu
   ends with what the picture's menu held. Sarah, 2026-10-24: the Your home
   mockup. UX-040, patch 784. */
@media (max-width: 760px) {
  body.has-phone-shell .phone-menu-button,
  body.has-phone-shell .app-header .user-menu { display: none; }
  .phone-bar .phone-bar-you .avatar { display: grid; place-items: center; width: 24px; height: 24px; border-radius: 50%; font-size: 10px; font-weight: 600; line-height: 1; }
  .phone-drawer-you { display: flex; align-items: center; gap: 10px; padding: 6px 16px 4px; }
  .phone-drawer-you .avatar { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; font-size: 13px; font-weight: 600; }
  .phone-drawer-out { margin: 0; }
}

/* Fixes from Sarah's phone, 2026-10-24, after 783 and 784: the logo mark at
   the left in every space (with the ☰ gone the corner was empty: "i cant see
   the logo mark or hamburger menu in the top left corner"); the space's name
   beside it from the left; More and Comment… at the left; a long space name
   cut without a gap before the time. UX-040, patch 787. */
@media (max-width: 760px) {
  body.has-phone-shell .app-header .brand.has-phone-title { display: flex; }
  body.has-phone-shell .phone-title { justify-content: flex-start; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-unfold { justify-self: start; text-align: left; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-say { justify-content: flex-start; }
  body.has-phone-shell.is-social-feed .feed-entry .feed-where { flex: none; max-width: 38%; }
}

/* From the 783-786 test, 2026-10-24: in the Plan this week box's narrow days
   the first week's + was cut off behind the weekday name, and a card's second
   line broke one word per line; the head wraps under its date now and every
   card line stays on one line, cut short. On a phone the circles line up
   across the row whether a name takes one line or two. UX-033, UX-040,
   patch 788. */
@media (min-width: 761px) {
  .home-box .calendar-day-head { flex-wrap: wrap; row-gap: 2px; padding-left: 6px; padding-right: 6px; }
  .home-box .calendar-grid.is-month .calendar-task * { white-space: nowrap; }
}
@media (max-width: 760px) {
  body.has-phone-shell .home-strip { align-items: flex-start; }
  body.has-phone-shell .home-strip button { align-content: start; }
}

/* The space, any label and the time on one grey line under the name: the
   space's name gives way first, cut short. From the 787 test: 8 of 28 posts
   dropped the time to a line of its own. UX-040, patch 790. */
@media (max-width: 760px) {
  body.has-phone-shell.is-social-feed .feed-surface .feed-main > .feed-who { display: grid; grid-template-columns: minmax(0, max-content) repeat(6, max-content); column-gap: 0; justify-content: start; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-main > .feed-who > strong { grid-column: 1 / -1; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-main > .feed-who > :not(strong) { grid-row: 2; min-width: 0; margin-right: 6px; }
  body.has-phone-shell.is-social-feed .feed-entry .feed-where { max-width: none; }
}

/* Like and Comment as Facebook draws them: plain icons with their counts,
   side by side at the left, the faces at the right, no outlines; and a grey
   band between posts so each stands apart. Sarah, 2026-10-25, with a Facebook
   screenshot: "how they add the icons below each post and keep things clean
   and separated". Comment… goes; Comment opens the box. UX-040, patch 791. */
@media (max-width: 760px) {
  body.has-phone-shell.is-social-feed .feed-surface .feed-entry,
  body.has-phone-shell.is-social-feed .feed-surface.is-boxed .feed-entry + .feed-entry,
  body.has-phone-shell.is-social-feed .feed-surface .feed-entry + .feed-entry { margin: 0; border-top: 8px solid color-mix(in srgb, var(--foreground) 9%, var(--background)); }
  body.has-phone-shell.is-social-feed .feed-surface .feed-entry:first-child { border-top: 0; }
  body.has-phone-shell.is-social-feed .feed-surface .react.is-line { gap: 22px; margin-top: 8px; padding: 2px 0; }
  body.has-phone-shell.is-social-feed .feed-surface .react.is-line .react-button,
  body.has-phone-shell.is-social-feed .feed-surface .react.is-line .react-summary { justify-content: flex-start; gap: 6px; min-width: 32px; min-height: 40px; border: 0; background: none; padding: 0; color: var(--muted-foreground); font-size: 14px; font-weight: 500; }
  body.has-phone-shell.is-social-feed .feed-surface .react.is-line .react-button svg { width: 21px; height: 21px; }
  body.has-phone-shell.is-social-feed .feed-surface .react.is-line .react-summary { margin-left: auto; }
  body.has-phone-shell.is-social-feed .feed-surface .feed-say { display: none; }
}

/* One space picked on Your home: its name and Open, which goes into it.
   Sarah, 2026-10-25: "Add open". NAV-015, patch 792. */
.home-open { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0 0 10px; border-radius: var(--radius-sm); background: var(--accent); padding: 8px 12px; }
.home-open[hidden] { display: none; }
.home-open strong { min-width: 0; overflow: hidden; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.home-open-go { flex: none; min-height: 36px; border: 0; background: none; padding: 0 4px; color: var(--primary); font-weight: 600; box-shadow: none; }
@media (max-width: 760px) {
  body.has-phone-shell .home-open { margin: 0; border-radius: 0; padding: 8px 16px; }
}

/* Groups and Pages, signed out: the logo and name lead the bar, as in the
   app, and the screens behind them take the soft fade chosen on 23 Oct ("C,
   the soft fade") in place of the wash and dots. Inside the app the bar keeps
   only its action. Sarah, 2026-10-25: "Go with A". UX-040, patch 794. */
.pub-brand { display: inline-flex; align-items: center; gap: 10px; }
.pub-brand .brand-mark-img { width: 28px; height: 28px; }
.pub-brand strong { display: block; font-size: 18px; font-weight: 500; line-height: 1.1; }
.pub-brand small { display: block; color: var(--muted-foreground); font-size: 12px; font-weight: 400; }
.pub-bar.is-in-app { justify-content: flex-end; }
body.public-page:not([data-theme="dark"]) {
  background: linear-gradient(180deg, #e7f2e9 0, #f6f5f0 380px, #f7f6f2 100%);
  background-attachment: fixed;
}
body.public-page::before { content: none; }

/* Inside the app, a page's one action sits on its title's row, at the right,
   as the app's own pages put theirs; the title starts where the Market's
   does. Sarah, 2026-10-25: "there is a spacing issue on the header applied to
   new sections". UX-040, patch 795. */
.pub-page:has(> .pub-bar.is-in-app) { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
.pub-page:has(> .pub-bar.is-in-app) > * { grid-column: 1 / -1; }
.pub-page > .pub-bar.is-in-app { grid-column: 2; grid-row: 1; }
.pub-page:has(> .pub-bar.is-in-app) > .disc-title:first-of-type { grid-column: 1; grid-row: 1; margin: 0; }

/* The space's name atop the menu, in a 48px row level with the rail's
   collapse button beside it, so it no longer sits against the header. Sarah,
   2026-10-25: "there is no spacing between the menu column top item and the
   header row". UX-040, patch 796. */
.context-nav > .nav-space { min-height: 48px; padding-top: 0; padding-bottom: 0; }

/* Only the page's first h1 takes the title row: on Discover pages "Your
   pages" is the h1 and "Discover pages" an h2 below its cards, and 795 put
   both on the row. From the 793-796 test. UX-040, patch 797. */
/* :first-of-type too, to outweigh the 795 rule. Patch 798. */
.pub-page:has(> .pub-bar.is-in-app) > h2.disc-title:first-of-type { grid-column: 1 / -1; grid-row: auto; margin: 0; }

/* Today on Your home: your work due today and earlier, from every space,
   each with its space's picture. NAV-014, UX-041, patch 799. */
.home-today { display: grid; gap: 2px; margin: 0 0 12px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); padding: 10px 14px 8px; }
.home-today-head { display: flex; justify-content: space-between; align-items: baseline; margin: 0 0 2px; color: var(--muted-foreground); font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
.home-today-head.is-earlier { margin-top: 8px; }
.home-today-list { display: grid; margin: 0; padding: 0; list-style: none; }
.home-today-row { display: flex; align-items: center; gap: 10px; min-height: 48px; border-top: 1px solid var(--border); }
.home-today-row:first-child { border-top: 0; }
.home-today-row[hidden] { display: none; }
.home-today-check { margin: 0; }
.home-today-check button { display: grid; place-items: center; width: 32px; height: 32px; min-height: 0; margin: 0 -6px 0 -6px; border: 0; background: none; padding: 0; box-shadow: none; }
.home-today-check button span { width: 20px; height: 20px; border: 1.5px solid color-mix(in srgb, var(--muted-foreground) 70%, transparent); border-radius: 50%; }
.home-today-check button:hover span { border-color: var(--primary); }
.home-today-open { display: grid; gap: 1px; min-width: 0; flex: 1; padding: 6px 0; color: var(--foreground); text-decoration: none; }
.home-today-title { overflow: hidden; font-size: 15px; text-overflow: ellipsis; white-space: nowrap; }
.home-today-sub { display: flex; align-items: center; gap: 6px; min-width: 0; color: var(--muted-foreground); font-size: 12.5px; }
.home-today-sub > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.home-today-sub .home-nav-pic { width: 16px; height: 16px; border-radius: 5px; font-size: 8px; }
.home-today-all { justify-self: start; min-height: 36px; margin: 2px 0 0; border: 0; background: none; padding: 0; color: var(--primary); font-weight: 600; box-shadow: none; }
@media (max-width: 760px) {
  body.has-phone-shell .home-today { margin: 0; border-width: 0 0 8px; border-color: color-mix(in srgb, var(--foreground) 9%, var(--background)); border-radius: 0; padding: 10px 16px 6px; }
}

/* Today as its own box (patch 800): the box is the card, so the list inside
   draws no border of its own; its number sits beside its name. On a phone it
   comes above the Feed. Sarah, 2026-10-25: "on a phone above the Feed".
   NAV-014. */
.home-box[data-box="today"] .home-today { margin: 0; border: 0; border-radius: 0; background: none; padding: 0; }
.home-box[data-box="today"] .box-count { margin-left: auto; color: var(--muted-foreground); font-size: 13px; font-weight: 600; }
.home-today-none { margin: 0; }
@media (max-width: 760px) {
  body.has-phone-shell .home-box[data-box="today"] .home-today { border: 0; padding: 0; }
  .arranged[data-box-layout="home"] .box-cols { display: flex; flex-direction: column; gap: 12px; }
  .arranged[data-box-layout="home"] .box-col:not([hidden]) { display: contents; }
  .arranged[data-box-layout="home"] .home-box[data-box="today"] { order: -1; }
}

/* From the 799 test: the circle that completes a task is a full 44px tap,
   and Show all folds back with Show less. NAV-014, patch 801. */
.home-today-check button { width: 44px; height: 44px; margin: 0 -10px 0 -12px; }

/* Accounts: what they are, under the heading; on an account, the others as
   chips to switch to, and Add account. ACCOUNT-001, patch 802. */
.accounts-line { max-width: 62ch; margin: 4px 0 0; color: var(--muted-foreground); font-size: 14px; }
.account-switch { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.account-chip { display: inline-flex; align-items: center; min-height: 36px; border: 1px solid var(--border); border-radius: 999px; background: var(--card); padding: 0 14px; color: var(--foreground); font-size: 13.5px; font-weight: 500; text-decoration: none; }
.account-chip.is-on { border-color: var(--primary); background: var(--accent); color: var(--primary); }
.account-chip.is-add { border-style: dashed; color: var(--muted-foreground); }
.accounts-features-head { margin: 10px 0 2px; color: var(--muted-foreground); font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
.accounts-features { max-width: 520px; margin: 0; padding-left: 18px; color: var(--muted-foreground); font-size: 14px; columns: 2 160px; column-gap: 24px; }
.accounts-intro { display: grid; gap: 4px; max-width: 620px; padding: 18px 20px; }
.accounts-intro .accounts-line { margin: 0; color: var(--foreground); font-size: 15px; }
.accounts-cta { margin: 12px 0 0; }

/* Scrolling back to a box or a post stops below the header, not under it.
   From the 803 test: Show less left Today's heading under the top bar.
   NAV-014, patch 804. */
.home-box, .feed-entry { scroll-margin-top: 92px; }
@media (max-width: 760px) { .home-box, .feed-entry { scroll-margin-top: 64px; } }

/* One icon for notifications and messages, and a quieter bell: a small dot
   for something new in place of the red number, two tabs, Mark all read; on a
   phone it opens from the bottom. Approved 2026-10-21; Sarah, 2026-10-25:
   "Yes, start with the bell". UX-040, NOTIF-007, patch 808. */
.bell-dot { position: absolute; top: 7px; right: 7px; width: 9px; height: 9px; border: 2px solid var(--background); border-radius: 50%; background: var(--destructive); }
.bell-dot[hidden] { display: none; }
.bell-grab { display: none; }
.bell-tabs { display: flex; gap: 4px; margin: 2px 4px 6px; border-bottom: 1px solid var(--border); }
.bell-tabs button { position: relative; display: inline-flex; align-items: center; gap: 6px; min-height: 40px; margin: 0 0 -1px; border: 0; border-bottom: 2px solid transparent; border-radius: 0; background: none; padding: 0 10px; color: var(--muted-foreground); font-size: 14px; font-weight: 500; box-shadow: none; }
.bell-tabs button[aria-selected="true"] { border-bottom-color: var(--primary); color: var(--foreground); font-weight: 600; }
.bell-tab-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--destructive); }
.bell-tab-dot[hidden] { display: none; }
.bell-pane[hidden] { display: none; }
.bell-head-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 0; }
.bell-read-all { margin: 0 4px 4px auto; min-height: 32px; border: 0; background: none; padding: 0 6px; color: var(--primary); font-size: 13px; font-weight: 600; box-shadow: none; }
.bell-read-all[hidden] { display: none; }
.bell-all { display: block; margin: 6px 8px 4px; color: var(--primary); font-size: 13.5px; font-weight: 600; text-decoration: none; }
@media (max-width: 760px) {
  body.has-phone-shell .bell-panel { position: fixed; top: auto; right: 0; bottom: 0; left: 0; z-index: 1000; width: auto; max-height: 82vh; border: 0; border-radius: 18px 18px 0 0; padding: 6px 10px calc(12px + env(safe-area-inset-bottom)); box-shadow: 0 0 0 100vmax rgba(15, 18, 24, .35); }
  body.has-phone-shell .bell-grab { display: block; width: 40px; height: 4px; margin: 4px auto 8px; border-radius: 999px; background: var(--border); }
  body.has-phone-shell .bell-tabs button { min-height: 44px; font-size: 15px; }
}

/* The one task list: Tasks and a project's Tasks tab draw the same rows, and
   ticking rows brings up a bar of changes at the foot of the screen. On a
   phone there are no tick boxes and no bar; each row has its complete circle.
   Sarah, 2026-10-25: "Yes: one task list everywhere, select all, and the bulk
   bar as proposed." TASK-035, UX-041, patch 809. */
.task-list-table th.task-tick-cell, .task-list-table td.task-tick-cell { width: 36px; min-width: 36px; }
.task-list-table .task-tick-cell input { min-height: auto; }
/* The name cell on a computer; a phone has its own rows above. Patch 810. */
@media (min-width: 761px) {
  .task-list-table td[data-phone-main] { min-width: 220px; }
  .task-list-table td[data-phone-main] > a { display: block; color: var(--foreground); font-weight: 600; text-decoration: none; }
  .task-list-table td[data-phone-main] > a:hover { color: var(--primary); text-decoration: underline; }
  .task-list-table td[data-phone-main] > small { display: block; margin-top: 3px; color: var(--muted-foreground); }
}
.task-list-table tr:has(.task-tick-cell input:checked) { background: color-mix(in srgb, var(--primary) 7%, transparent); }
.bulk-bar { position: fixed; left: 50%; bottom: calc(20px + env(safe-area-inset-bottom, 0px)); z-index: 60; display: flex; align-items: center; gap: 4px; max-width: calc(100vw - 32px); padding: 6px 6px 6px 16px; transform: translateX(-50%); border: 1px solid var(--border); border-radius: 12px; background: var(--card); box-shadow: 0 10px 30px rgba(15, 23, 42, .16); }
.bulk-bar[hidden], .bulk-bar > button[hidden] { display: none; }
.bulk-count { margin-right: 8px; color: var(--muted-foreground); font-size: 13.5px; white-space: nowrap; }
.bulk-bar > button, .bulk-menu > summary { display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 0 12px; border: 0; border-radius: 8px; background: transparent; box-shadow: none; color: var(--foreground); font: inherit; font-size: 14px; font-weight: 500; white-space: nowrap; cursor: pointer; list-style: none; }
.bulk-menu > summary::-webkit-details-marker { display: none; }
.bulk-menu > summary::after { content: ""; width: 6px; height: 6px; margin-top: -3px; border: solid currentColor; border-width: 0 1.5px 1.5px 0; transform: rotate(45deg); opacity: .6; }
.bulk-bar > button:hover, .bulk-menu > summary:hover, .bulk-menu[open] > summary { background: var(--secondary); }
.bulk-bar > .bulk-delete { color: var(--destructive); }
.bulk-bar > .bulk-clear { width: 36px; padding: 0; justify-content: center; color: var(--muted-foreground); font-size: 20px; }
.bulk-menu { position: relative; }
.bulk-pop { position: absolute; left: 0; bottom: calc(100% + 10px); display: grid; min-width: 200px; max-height: min(360px, 60vh); overflow-y: auto; padding: 6px; border: 1px solid var(--border); border-radius: 10px; background: var(--card); box-shadow: 0 10px 30px rgba(15, 23, 42, .16); }
.bulk-pop > button { justify-content: flex-start; min-height: 36px; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; box-shadow: none; color: var(--foreground); font-size: 14px; font-weight: 400; text-align: left; }
.bulk-pop > button:hover { background: var(--secondary); }
.bulk-pick-date { display: flex; gap: 6px; margin-top: 4px; padding: 6px 4px 2px; border-top: 1px solid var(--border); }
.bulk-pick-date input { min-width: 0; flex: 1; min-height: 36px; }
.bulk-pick-date button { min-height: 36px; padding: 0 12px; }
/* Room at the end, so the last rows scroll clear of the bar. */
@media (min-width: 761px) { .card:has(.bulk-bar:not([hidden])) { padding-bottom: 72px; } }
@media (max-width: 760px) {
  .bulk-bar { display: none !important; }
  .view-panel[data-view="list"]:has(.task-list-table) { padding-bottom: 96px; }
}

/* Pictures without a photo are outlined: a thin ring in the person's or the
   space's own color, initials in that color, on the card. A photo or logo
   shows as it is. Everywhere, community and portals included. Sarah,
   2026-10-26: "a colored outline with initials unless an image has been added
   would be preferred throughout", then "Yes, switch to outlined initials
   everywhere, as proposed." Patch 817. Each kind keeps its size and shape;
   only the fill becomes a ring. */
span.feed-av, .home-msg-av, .ov-av, .page-faces span, .avatar, .task-who, .nav-initial,
span.home-nav-pic:not(.is-home):not(.is-all):not(.home-strip-all-pic), span.group-pic, .pub-pic.is-letters, .disc-pic.is-letters,
.record-list-logo.is-initials, .thread-avatar, .pl-face:not([style*="background-image"]), .home-project-mark {
  --ring: var(--hue, var(--primary));
  background: var(--card) !important;
  border: 1.5px solid var(--ring) !important;
  color: var(--ring) !important;
  font-weight: 600;
}
.avatar, .task-who { --hue: var(--primary); }
.nav-initial { --hue: var(--mark, var(--primary)); }
span.home-nav-pic { --hue: #0f766e; }
span.home-nav-pic.is-personal { --hue: #be185d; }
span.home-nav-pic.is-work { --hue: #475569; }
span.home-nav-pic.is-portal { --hue: #0369a1; }
span.group-pic, .pub-pic.is-letters, .disc-pic.is-letters { --hue: #0f766e; box-shadow: 0 0 0 3px var(--card); }
body[data-theme="dark"] :is(span.feed-av, .home-msg-av, .ov-av, .page-faces span, .avatar, .task-who, .nav-initial, span.home-nav-pic, span.group-pic, .pub-pic.is-letters, .disc-pic.is-letters, .record-list-logo.is-initials, .thread-avatar, .pl-face, .home-project-mark) {
  --ring: color-mix(in srgb, var(--hue, var(--primary)) 58%, #fff);
}
/* The user menu's picture, its ring on the header. */
.user-menu > summary .avatar { box-sizing: border-box; }

/* What a workspace calls its clients: chips, an ⓘ, and its own word.
   CLIENT-028, patch 818. */
.client-word { display: grid; gap: 8px; }
.client-word[hidden] { display: none; }
.client-word-head { display: flex; align-items: center; gap: 6px; margin: 0; color: var(--muted-foreground); font-size: 11.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
.client-word-chips .feed-chip:has(input:checked) { border-color: var(--primary); background: color-mix(in srgb, var(--primary) 12%, var(--card)); color: var(--primary); }
.client-word-chips .feed-chip:has(input:focus-visible) { outline: 2px solid var(--primary); outline-offset: 2px; }
.client-word-own { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.client-word-own[hidden] { display: none; }
.client-word-own label { display: grid; gap: 4px; font-size: 13px; color: var(--muted-foreground); }
@media (max-width: 520px) { .client-word-own { grid-template-columns: minmax(0, 1fr); } }

/* The workspace's name, beside its picture in Settings. Patch 821. */
.space-name-form { display: flex; align-items: flex-end; gap: 10px; max-width: 460px; margin-top: 12px; }
.space-name-form label { display: grid; flex: 1; gap: 4px; min-width: 0; color: var(--muted-foreground); font-size: 13px; }
@media (max-width: 760px) { .space-name-form { max-width: none; } .space-name-form button { min-height: 52px; } }

/* Headings in order, patch 827. Manrope now has a real 600, so anything set
   600 or heavier is truly bold. A page title stays at the lighter 500 it has
   looked like since 771; words of help inside a button keep the 500 they
   have looked like since 771. Sarah,
   2026-10-27: "I think the title is an option two and three are too much, but
   I like the bold subheadings", then "1: keep Manrope, with real bold
   subheadings and the headings in order." UX-043. */
h1, h1[class] { font-weight: 500 !important; }
button small, .button small { font-weight: 500; }

/* The community layer: Your home, groups and Pages only (body.is-community,
   set in the layout), on top of everything above. Sarah, 2026-10-27, on the
   side-by-side mockup: "the buttons were where I was seeing the problem ...
   nothing should be indented anywhere. But yeah, I guess this is okay to go
   with." Patch 828. */

/* Regular letter spacing, as social apps set it. */
body.is-community, body.is-community h1, body.is-community h2, body.is-community h3 { letter-spacing: 0; }

/* Names stand out, in the true 600 that 827 brought. */
body.is-community .feed-who strong,
body.is-community .home-coming-text strong { font-weight: 600; }
body.is-community .group-name h1 { font-weight: 600 !important; }
body.is-community .feed-who strong { font-size: 14px; }

/* Filled pictures: initials in white on the person's or group's color. */
body.is-community span.feed-av,
body.is-community .home-msg-av,
body.is-community .avatar,
body.is-community.has-phone-shell span.home-nav-pic:not(.is-home):not(.is-all),
body.is-community span.group-pic {
  background: var(--hue, var(--primary)) !important;
  border-color: transparent !important;
  color: #fff !important;
}

/* Round pill chips: soft gray, the picked one in a tint of your color, no check. */
body.is-community.has-phone-shell .feed-chip {
  border-color: transparent;
  border-radius: 999px;
  background: var(--secondary);
  color: var(--foreground);
}
body.is-community.has-phone-shell .feed-chip[aria-pressed="true"] {
  background: color-mix(in srgb, var(--primary) 14%, var(--card));
  color: color-mix(in srgb, var(--primary) 82%, #000000);
}
body.is-community.has-phone-shell .feed-chip[aria-pressed="true"]::before { display: none; }

/* Buttons as social apps draw them: filled, 8px corners, dark lettering at
   600; the screen's main action (Invite, Post) in your color. */
body.is-community .secondary-button,
body.is-community a.secondary-button,
body.is-community .feed-compose-row button[type="submit"] {
  gap: 6px;
  min-height: 36px;
  border: 0;
  border-radius: 8px;
  padding: 8px 14px;
  font-size: 14px;
  font-weight: 600;
  box-shadow: none;
}
body.is-community .secondary-button { background: var(--secondary); color: var(--foreground); }
body.is-community .secondary-button:hover { background: color-mix(in srgb, var(--foreground) 9%, var(--secondary)); color: var(--foreground); }
body.is-community .group-info .secondary-button,
body.is-community .feed-compose-row button[type="submit"] { background: var(--primary); color: var(--primary-foreground, #fff); }
@media (max-width: 760px) {
  body.is-community .secondary-button,
  body.is-community a.secondary-button,
  body.is-community .feed-compose-row button[type="submit"] { min-height: 44px; }
}

/* Nothing indented: an event or listing in a post starts at the post's left
   edge, like its words and photos. Every screen, business side included. */
.feed-entry .feed-main > .event-card,
.feed-entry .feed-main > .listing-card { margin-left: -40px; }
