:root {
  /* Surfaces */
  --bg: #F7F6FB;
  --surface: #ffffff;
  --surface-2: #FAFAFE;
  --border: #E4E3EE;
  --border-soft: #F3F4F6;

  /* Text */
  --text: #1F2033;
  --text-2: #3F3F52;
  --muted: #6B6B80;
  /* The palest text. It was #9CA3AF, 2.5:1 on white, set on 23 kinds of
     text including the view switcher and secondary buttons; 4.5:1 is the
     floor for reading (WCAG AA). #6E7183 at first, which measured 4.49:1
     where a view switcher sits on the page grey (Appointments, CRM); now
     5.1:1 on white and 4.8:1 on the page grey (4 October 2026). Still a
     step lighter than --muted. */
  --faint: #6A6D7F;

  /* Accent and states */
  --accent: #4F46E5;
  --accent-dark: #4338CA;
  --accent-soft: #EEF2FF;
  --ok: #065F46;
  --ok-soft: #D1FAE5;
  --warn: #92400E;
  --warn-soft: #FEF3C7;
  --danger: #991B1B;
  --danger-soft: #FEE2E2;

  --sans: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --r-card: 14px;
  --r-control: 10px;
  --r-pill: 9999px;
  --shadow-sm: 0 2px 12px rgba(31, 32, 51, 0.06), 0 1px 3px rgba(31, 32, 51, 0.04);
  --shadow-md: 0 8px 24px rgba(31, 32, 51, 0.08);
  --shadow-pop: 0 32px 80px rgba(79, 70, 229, 0.12), 0 8px 24px rgba(31, 32, 51, 0.08);

  --rail: 240px;

  /* Named in the dark-mode work (4 October 2026): these were written into
     rules as plain colours, so they could not change with the theme. The
     light values are the ones they had. */
  --border-strong: #d0d7e2;
  --border-dashed: #d6dde6;
  --track: #eef1f5;
  --track-2: #e3e8ef;
  --pill-bg: #F3F4F6;
  --pill-text: #374151;
  --chip-bg: #f2f4f7;
  --neutral-soft: #F1F1F5;
  --high-bg: #E8E9F1;
  --accent-line: #C7D2FE;
  --ok-line: #a6f4c5;
  --warn-line: #f6cfa8;
  --warn-softer: #fffbeb;
  --danger-line: #fecdc9;
  /* Indigo as a background under white text (buttons, the chat button).
     The same as --accent in light; in dark --accent is brighter, for text
     and lines on a dark page, and buttons keep a deeper one. */
  --accent-solid: #4F46E5;
  --accent-solid-hover: #4338CA;

  /* The sign-in pages' navy panel and the white card drawn on it (from
     the Codex design preview, 8 October 2026). Not redefined for dark
     mode on purpose: the panel is dark in both themes, and the card is a
     drawing of the light app. Every text colour is at least 4.5:1 on the
     surface it sits on. */
  --auth-navy: #080F27;
  --auth-on-navy: #FFFFFF;
  --auth-navy-text: #AAB7D1;
  --auth-navy-faint: #8D9BBD;
  --auth-navy-accent: #8E9FFF;
  --auth-navy-line: rgba(255, 255, 255, 0.09);
  --auth-card: #FFFFFF;
  --auth-card-bar: #F7F9FE;
  --auth-card-border: #DBE3F2;
  --auth-card-text: #253557;
  --auth-card-muted: #5F6B85;
  --auth-card-soft: #EDF1FF;
  --auth-card-blue: #4458E0;
  --auth-card-line: #E3E9F6;
  --auth-toast: rgba(23, 37, 64, 0.94);
  --auth-toast-border: rgba(83, 101, 140, 0.4);
  --auth-toast-text: #E0E7FC;
  --auth-toast-muted: #A3B1CE;
  --auth-toast-icon: rgba(109, 135, 252, 0.1);
  --auth-toast-icon-border: rgba(124, 148, 253, 0.19);
  --auth-grid: rgba(113, 132, 181, 0.07);
  --auth-card-shadow: 0 24px 65px rgba(1, 6, 22, 0.4);
  --auth-toast-shadow: 0 14px 35px rgba(3, 8, 25, 0.31);
  --auth-card-teal-bg: #E6F1F4;
  --auth-card-teal: #2F6676;
  --auth-mini: #172542;
  --auth-mini-border: rgba(113, 136, 196, 0.27);
  --auth-mini-bar: rgba(126, 145, 189, 0.44);
  --auth-mini-dash: rgba(127, 148, 196, 0.38);
  --auth-mini-text: #B4C4E8;
  /* An edge for the navy panel, needed only on a dark page. */
  --auth-panel-edge: transparent;

  /* The top bar on a laptop (9 October 2026): deep indigo in both themes,
     like the sign-in panel, so not redefined for dark. Text on it: white
     16:1, --gbar-muted 10:1, and 8.6:1 on --gbar-field. */
  --gbar: #17153B;
  --gbar-text: #FFFFFF;
  --gbar-muted: #C9C8EC;
  --gbar-field: #26235A;
  --gbar-line: #3A3770;

  color-scheme: light;
}

/* Dark: chosen in Settings (data-theme="dark" on <html>), or the device's
   own setting when the choice is Automatic. Two copies of the same values
   because CSS cannot say "dark, unless Light was chosen" in one selector.
   Every text colour here is at least 4.5:1 on the surfaces it sits on
   (measured 4 October 2026: --faint 5.4:1 on --surface-2, --accent 7.2:1
   on --surface, white on --accent-solid 5.4:1). */
:root[data-theme='dark'] {
  --bg: #0F1020;
  --surface: #181A2B;
  --surface-2: #1E2033;
  --border: #2E3048;
  --border-soft: #25273B;
  --text: #ECEDF5;
  --text-2: #C9CBDA;
  --muted: #A6A9BD;
  --faint: #9295AB;
  --accent: #A29DFF;
  --accent-dark: #C4C1FF;
  --accent-soft: #28264D;
  --ok: #6EE7B7;
  --ok-soft: #123329;
  --warn: #FCD34D;
  --warn-soft: #3A2E12;
  --danger: #FCA5A5;
  --danger-soft: #3D1C21;
  --shadow-sm: 0 2px 12px rgba(0, 0, 0, 0.35), 0 1px 3px rgba(0, 0, 0, 0.3);
  --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.45);
  --shadow-pop: 0 32px 80px rgba(0, 0, 0, 0.55), 0 8px 24px rgba(0, 0, 0, 0.4);
  --border-strong: #3B3E5A;
  --border-dashed: #3A3D58;
  --track: #2A2C42;
  --track-2: #34364F;
  --pill-bg: #2A2C42;
  --pill-text: #D7D9E6;
  --chip-bg: #24263A;
  --neutral-soft: #26283C;
  --high-bg: #34364F;
  --accent-line: #3C3A70;
  --ok-line: #1E5A47;
  --warn-line: #5C4718;
  --warn-softer: #2A2414;
  --danger-line: #6A2A31;
  --accent-solid: #5B54E8;
  --accent-solid-hover: #6A63F0;
  --auth-panel-edge: rgba(255, 255, 255, 0.08);
  color-scheme: dark;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --bg: #0F1020;
    --surface: #181A2B;
    --surface-2: #1E2033;
    --border: #2E3048;
    --border-soft: #25273B;
    --text: #ECEDF5;
    --text-2: #C9CBDA;
    --muted: #A6A9BD;
    --faint: #9295AB;
    --accent: #A29DFF;
    --accent-dark: #C4C1FF;
    --accent-soft: #28264D;
    --ok: #6EE7B7;
    --ok-soft: #123329;
    --warn: #FCD34D;
    --warn-soft: #3A2E12;
    --danger: #FCA5A5;
    --danger-soft: #3D1C21;
    --shadow-sm: 0 2px 12px rgba(0, 0, 0, 0.35), 0 1px 3px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.45);
    --shadow-pop: 0 32px 80px rgba(0, 0, 0, 0.55), 0 8px 24px rgba(0, 0, 0, 0.4);
    --border-strong: #3B3E5A;
    --border-dashed: #3A3D58;
    --track: #2A2C42;
    --track-2: #34364F;
    --pill-bg: #2A2C42;
    --pill-text: #D7D9E6;
    --chip-bg: #24263A;
    --neutral-soft: #26283C;
    --high-bg: #34364F;
    --accent-line: #3C3A70;
    --ok-line: #1E5A47;
    --warn-line: #5C4718;
    --warn-softer: #2A2414;
    --danger-line: #6A2A31;
    --accent-solid: #5B54E8;
    --accent-solid-hover: #6A63F0;
    --auth-panel-edge: rgba(255, 255, 255, 0.08);
    color-scheme: dark;
  }
}

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

html,
body,
#root {
  height: 100%;
}

/* Placeholders were the browser's own grey, which is 3.7:1 on a dark
   field (found 4 October 2026: the dark-mode contrast scan looked only at
   text, not at placeholders). --faint is 5.1:1 on white and passes in
   dark. opacity: Firefox dims placeholders on its own. */
::placeholder {
  color: var(--faint);
  opacity: 1;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 0.875rem;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  font-feature-settings: 'cv05' 1;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

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

/* ============================ shell ============================ */

.app {
  display: grid;
  grid-template-columns: var(--rail) 1fr;
  min-height: 100%;
}

.rail {
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  padding: 1.25rem 0 1rem;
  /* A grid item defaults to min-width:auto, so it refuses to shrink below the
     width of its widest content. On a phone the navigation turns into a row
     of nine items that do not wrap, and without this the rail stretched the
     whole grid column to about 1160px: the page was three times wider than
     the screen and every screen had to be scrolled sideways. */
  min-width: 0;
}

.rail__brand {
  padding: 0 1.125rem 1rem;
}

.brandlogo {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
}

.brandmark {
  flex: 0 0 auto;
  display: block;
}

.brandlogo__word {
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rail__org {
  padding: 0 1.125rem 1rem;
  margin-bottom: 0.5rem;
  border-bottom: 1px solid var(--border-soft);
}

.rail__org-name {
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.35;
  color: var(--text);
}

.rail__org-meta {
  font-size: 0.75rem;
  color: var(--muted);
  margin-top: 0.125rem;
}

.rail__nav {
  display: flex;
  flex-direction: column;
  padding: 0.25rem 0.625rem;
  gap: 0.125rem;
  flex: 1;
}

/* On a laptop the More wrapper takes no part in the layout and the More
   button is not shown: the rail lists everything, as before. */
.rail__more {
  display: contents;
}

.rail__nav .navitem--more,
.navitem__short {
  display: none;
}

.navitem {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  width: 100%;
  font-family: var(--sans);
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text-2);
  background: none;
  border: none;
  border-radius: var(--r-control);
  padding: 0.5rem 0.625rem;
  cursor: pointer;
  text-align: left;
  transition: background 0.12s ease, color 0.12s ease;
}

.navitem:hover {
  background: var(--bg);
  color: var(--text);
}

.navitem--active {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}

.navitem__body {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  min-width: 0;
}

.navitem__icon {
  width: 18px;
  height: 18px;
  flex: 0 0 18px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  color: var(--faint);
}

.navitem:hover .navitem__icon {
  color: var(--muted);
}

.navitem--active .navitem__icon {
  color: var(--accent);
}

.navitem__count {
  font-size: 0.75rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--faint);
}

.navitem--active .navitem__count {
  color: var(--accent-dark);
}

/* Listed twice because the active rule above is more specific: on the
   selected item the count was drawn in #4338ca on its own #4f46e5 pill,
   so the number vanished exactly where you were looking. */
.navitem__count--flag,
.navitem--active .navitem__count--flag {
  color: #fff;
  background: var(--accent-solid);
  border-radius: var(--r-pill);
  padding: 0.0625rem 0.4375rem;
  font-weight: 700;
}

.rail__foot {
  padding: 0.875rem 1.125rem 0;
  border-top: 1px solid var(--border-soft);
  font-size: 0.8125rem;
}

.rail__user {
  color: var(--muted);
  word-break: break-all;
  margin-bottom: 0.375rem;
}

.raillink {
  font-family: var(--sans);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--muted);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

.raillink:hover {
  color: var(--accent);
}

.raillink + .raillink {
  margin-left: 0.875rem;
}

/* Filled on a laptop only (placeShellTools); on a phone search, New and
   the bell are in the page header and this is empty. */
.rail__tools {
  display: none;
}

/* ====================== top bar (laptop) ======================
   The left rail became a dark top bar over a row of rounded section
   tabs (9 October 2026, from the design the founder chose: the layout
   of enterprise workspaces, in Macsen's own colours and shapes). The
   same rail element as the phone's: the phone rules (max-width: 860px)
   are untouched, and these only apply above them. */
@media (min-width: 861px) {
  .app {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto 1fr;
  }

  /* The page uses the width the bar does. The 1400px cap was set while
     the menu was a rail down the left; under a full-width bar it left a
     strip of empty page on the right of any wider screen (reported by
     the founder, 9 October 2026). Two classes: this block comes before
     the plain .content rule in the file, which would otherwise win. */
  .app .content {
    max-width: none;
  }

  /* Two rows: the bar (3.5rem, drawn by the background) and the tabs.
     Above the page (z-index) so the bell and New menus open over it. */
  .rail {
    position: relative;
    z-index: 50;
    display: grid;
    grid-template-columns: auto minmax(0, max-content) minmax(0, 1fr) auto;
    grid-template-rows: 3.5rem auto;
    grid-template-areas:
      'brand org tools foot'
      'nav   nav nav   nav';
    align-items: center;
    padding: 0;
    border-right: none;
    border-bottom: 1px solid var(--border);
    background: linear-gradient(var(--gbar) 0 3.5rem, var(--surface) 3.5rem);
  }

  .rail__brand {
    grid-area: brand;
    padding: 0 1rem 0 1.25rem;
  }

  .rail .brandlogo__word {
    color: var(--gbar-text);
  }

  /* A cap, because the grid would not shrink it: a long name
     ("Provincial Government of Negros Oriental, Office of the
     Governor") took 440px and pushed the page 99px wider than an
     861px screen. It ends in an ellipsis; the full name is its title. */
  .rail__org {
    grid-area: org;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
    max-width: 20rem;
    margin: 0;
    padding: 0.25rem 0 0.25rem 1rem;
    border-bottom: none;
    border-left: 1px solid var(--gbar-line);
  }

  .rail__org-name {
    color: var(--gbar-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* "Support session" and "Platform staff" change what you are looking
     at, so they are a badge, not small print. */
  .rail__org-meta {
    margin: 0;
    flex: none;
    padding: 0.0625rem 0.5rem;
    border-radius: var(--r-pill);
    background: var(--gbar-field);
    color: var(--gbar-muted);
    font-weight: 600;
  }

  .rail__tools {
    grid-area: tools;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
    padding: 0 0.75rem 0 1.25rem;
  }

  .rail__tools .searchtrigger {
    flex: 0 1 26rem;
    width: auto;
    min-width: 9rem;
    margin-right: auto;
    background: var(--gbar-field);
    border-color: var(--gbar-line);
    box-shadow: none;
    color: var(--gbar-muted);
  }

  .rail__tools .searchtrigger:hover {
    border-color: var(--gbar-muted);
  }

  .rail__tools .searchtrigger__hint {
    color: var(--gbar-muted);
    border-color: var(--gbar-line);
  }

  .rail__tools .bellbtn {
    background: transparent;
    border-color: transparent;
    color: var(--gbar-muted);
  }

  .rail__tools .bellbtn:hover {
    background: var(--gbar-field);
    color: var(--gbar-text);
  }

  .rail__foot {
    grid-area: foot;
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.25rem 1.25rem 0.25rem 1rem;
    border-top: none;
    border-left: 1px solid var(--gbar-line);
  }

  /* The address is what Account opens. */
  .rail__user {
    display: none;
  }

  .rail__foot .raillink {
    color: var(--gbar-muted);
    white-space: nowrap;
  }

  .rail__foot .raillink:hover {
    color: var(--gbar-text);
  }

  .rail__foot .raillink + .raillink {
    margin: 0;
  }

  /* The sections: one row of rounded tabs, scrolling sideways only if a
     narrow laptop cannot fit them all. */
  .rail__nav {
    grid-area: nav;
    flex-direction: row;
    align-items: center;
    gap: 0.25rem;
    padding: 0.5rem 1rem;
    overflow-x: auto;
    scrollbar-width: thin;
  }

  .rail__nav .navitem {
    width: auto;
    flex: none;
    gap: 0.375rem;
    padding: 0.4375rem 0.875rem;
    border-radius: var(--r-pill);
    white-space: nowrap;
  }

  .rail__nav .navitem__icon {
    display: none;
  }

  .rail__nav .navitem:hover {
    background: var(--accent-soft);
    color: var(--text);
  }

  .rail__nav .navitem--active,
  .rail__nav .navitem--active:hover {
    background: var(--accent-solid);
    color: #ffffff;
  }

  .rail__nav .navitem__count {
    color: var(--muted);
  }

  /* On the filled tab the count is a white chip with the tab's colour;
     a flagged one too (its own fill is the tab's colour and would
     vanish). White text on a translucent chip was 4.0:1 (3.6:1 dark). */
  .rail__nav .navitem--active .navitem__count,
  .rail__nav .navitem--active .navitem__count--flag {
    color: var(--accent-solid);
    background: #ffffff;
    border-radius: var(--r-pill);
    padding: 0.0625rem 0.4375rem;
  }

  .rail__nav .navitem__count--flag {
    color: #ffffff;
  }

  .rail__tools .searchtrigger {
    white-space: nowrap;
    overflow: hidden;
  }
}

/* A narrow laptop: at 861px the tabs ran 78px past the screen (Settings
   half hidden) and "Search or jump to…" broke onto two lines in a 151px
   box, making the bar taller. Tighter tabs and the short label. */
@media (min-width: 861px) and (max-width: 1040px) {
  .rail__nav {
    gap: 0.125rem;
    padding-left: 0.75rem;
    padding-right: 0.75rem;
  }

  .rail__nav .navitem {
    padding-left: 0.625rem;
    padding-right: 0.625rem;
  }

  .rail__tools .searchtrigger__long {
    display: none;
  }

  .rail__org {
    max-width: 12rem;
  }

  .rail__tools .searchtrigger {
    min-width: 6rem;
  }

  .rail__tools .searchtrigger__short {
    display: inline;
  }
}

/* ============================ main ============================ */

.main {
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.topbar {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: 1rem 1.75rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  align-items: center;
  justify-content: space-between;
}

.topbar__left {
  min-width: 0;
}

.topbar__title {
  font-size: 1.25rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.25;
  margin: 0;
}

.topbar__actions {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}

.content {
  padding: 1.5rem 1.75rem 4rem;
  max-width: 1400px;
}

.content--wide {
  max-width: none;
}

.crumbs {
  display: flex;
  align-items: center;
  gap: 0.3125rem;
  font-size: 0.8125rem;
  color: var(--muted);
  margin-bottom: 0.1875rem;
}

.crumbs__link {
  font-family: var(--sans);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--muted);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

.crumbs__link:hover {
  color: var(--accent);
}

/* ======================= attention block ======================= */

.attention {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--warn);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-sm);
  padding: 1rem 1.25rem;
  margin-bottom: 1.25rem;
}

.attention__title {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--warn);
  margin-bottom: 0.625rem;
}

.attention__list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2rem;
}

.attention__item {
  display: flex;
  align-items: baseline;
  gap: 0.4375rem;
  font-size: 0.875rem;
  color: var(--text-2);
}

.attention__count {
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 1;
  color: var(--warn);
  font-variant-numeric: tabular-nums;
}

.calm {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-sm);
  padding: 0.875rem 1.25rem;
  margin-bottom: 1.25rem;
  color: var(--muted);
}

/* ======================== metric cards ======================== */

.register {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 0.875rem;
  margin-bottom: 1.5rem;
}

.figure {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-sm);
  padding: 1.25rem;
}

.figure__value {
  font-size: 1.75rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.figure__label {
  font-size: 0.8125rem;
  color: var(--muted);
  margin-top: 0.25rem;
}

.figure--muted .figure__value {
  color: var(--faint);
}

.figure--link {
  cursor: pointer;
  text-align: left;
  width: 100%;
  font-family: var(--sans);
  transition: box-shadow 0.12s ease, border-color 0.12s ease;
}

.figure--link:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md);
}

/* ========================== panels =========================== */

.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  margin-bottom: 1.25rem;
}

.panel__head {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  align-items: center;
  justify-content: space-between;
  padding: 1.125rem 1.25rem 0.875rem;
}

.panel__heading {
  min-width: 0;
}

/* Not shown (4 October 2026). Every panel carried a small capital label
   over its title ("OVERVIEW", "CHECKPOINTS", "COLLABORATION") that only
   restated it, and on a record page that was eight of them. The page-level
   .eyebrow above the page title stays. panel() still accepts one, so a
   label can come back for a panel where it says something new. */
.panel__eyebrow {
  display: none;
}

.panel__title {
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  margin: 0;
}

.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
  align-items: start;
}

@media (max-width: 980px) {
  .split {
    grid-template-columns: 1fr;
    gap: 0;
  }
}

/* =========================== rows ============================ */

.rows {
  list-style: none;
  margin: 0;
  padding: 0.5rem 1.25rem 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.row {
  display: grid;
  grid-template-columns: 3.5rem minmax(0, 1fr) auto auto;
  gap: 0.625rem 1rem;
  align-items: center;
  padding: 0.8125rem 0.9375rem;
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.row:hover {
  background: var(--surface);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-sm);
}

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

.rowhead,
.rowhead:hover {
  background: transparent;
  border: none;
  box-shadow: none;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 0.25rem 0.9375rem 0;
}

.row__ref {
  font-size: 0.8125rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.row__link {
  font-family: var(--sans);
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  text-align: left;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.row__link:hover {
  color: var(--accent);
}

/* The subject and, under it, the street. The track is minmax(0, 1fr), so
   the cell itself cannot widen; what keeps a long street inside it is the
   street's own nowrap + overflow + ellipsis. Measured 3 October 2026 at
   1280px: without the overflow, "Intersection of Martin Luther King Jr
   Boulevard..." painted to 1030px, over the status column at 735px.
   min-width: 0 is kept for any flex parent this ends up in. */
.row__main {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.row__sub {
  font-size: 0.8125rem;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.row__where,
.row__when {
  font-size: 0.8125rem;
  color: var(--muted);
  white-space: nowrap;
}

.row__when {
  font-variant-numeric: tabular-nums;
}

.row__person {
  display: flex;
  align-items: center;
  gap: 0.4375rem;
  min-width: 0;
  font-size: 0.8125rem;
  color: var(--muted);
}

.row__person span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.row--req {
  /* 1.5rem the tick box (9 October 2026); 8.5rem fits "REQ-2026-00012",
     the reference as the requester sees it; 9rem the longest status,
     "Waiting on requester" (8rem cut it off once pills became 12px and
     capitalised, 4 October 2026); 6rem a due day with "3 days over"
     under it. Columns are counted from the tick box: 2 reference,
     3 subject, 4 status, 5 due, 6 priority, 7 department, 8 assignee. */
  grid-template-columns: 1.5rem 8.5rem minmax(0, 1fr) 9rem 6rem 5.5rem 9rem 9rem;
}

/* Below 1400px seven columns left the subject 70px wide at 1280, so the
   department goes (the filter above the list covers it) and the subject
   gets roughly 280px back. */
@media (max-width: 1400px) {
  .row--req {
    grid-template-columns: 1.5rem 8.5rem minmax(0, 1fr) 9rem 6rem 5.5rem 9rem;
  }
  .row--req > :nth-child(7) {
    display: none;
  }
}

/* And below 1250px the priority too: at 1100 the subject was down to 82px.
   Ref, subject, status, due and assignee are what a desk scans for. */
@media (max-width: 1250px) {
  .row--req {
    grid-template-columns: 1.5rem 8.5rem minmax(0, 1fr) 9rem 6rem 9rem;
  }
  .row--req > :nth-child(6) {
    display: none;
  }
}

.row--when {
  grid-template-columns: 8.5rem minmax(0, 1fr) auto auto;
}

/* The projects table: project, stage, owner, progress, spent, deadline.
   Measured 4 October 2026 at 1280: "In progress" 81px, "Alex Rivera" with
   avatar 104px, "24% of ₱2,500,000" 121px, "Overdue Sep 30" 107px. Wider
   columns (9rem for owner and spent) left the project name 198px. Longer
   values are cut with an ellipsis; the full figure is in the title. */
.row--project {
  grid-template-columns: minmax(0, 1fr) 7rem 8rem 6.5rem 8rem 7.5rem;
}

.row--project > .row__where {
  overflow: hidden;
  text-overflow: ellipsis;
}

.row__progress {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
}

.row__progress .progress__track {
  display: block;
  flex: 1 1 auto;
  min-width: 1.5rem;
}

/* The table builds the bar from spans, and an inline span ignores its
   width: the bar drew empty at 20% until this. */
.row__progress .progress__fill {
  display: block;
}

/* The tasks table: ref, task (project underneath), status, due, priority,
   assignee. Its own columns, not the requests list's: see taskTable. */
.row--task {
  grid-template-columns: 3rem minmax(0, 1fr) 7rem 7rem 5rem 9rem;
}

/* A grid item stretches to its column, which would draw each pill as a
   bar the column's full width. */
.row--project > .pill,
.row--task > .pill {
  justify-self: start;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Both tables drop columns as the screen narrows, least needed first, so
   the name keeps roughly 200px or more. Measured 4 October 2026: at 1024
   with every column the project name was 0px wide and the task title 80px;
   now the narrowest is about 210px, just above each breakpoint.
   Projects lose spent, then progress, then owner; tasks lose priority,
   then the reference, then the assignee. */
@media (max-width: 1250px) {
  .row--project {
    grid-template-columns: minmax(0, 1fr) 7rem 8rem 6.5rem 7.5rem;
  }
  .row--project > :nth-child(5) {
    display: none;
  }
  .row--task {
    grid-template-columns: 3rem minmax(0, 1fr) 7rem 7rem 9rem;
  }
  .row--task > :nth-child(5) {
    display: none;
  }
}

@media (max-width: 1100px) {
  .row--project {
    grid-template-columns: minmax(0, 1fr) 7rem 8rem 7.5rem;
  }
  .row--project > :nth-child(4) {
    display: none;
  }
  .row--task {
    grid-template-columns: minmax(0, 1fr) 7rem 7rem 9rem;
  }
  .row--task > :nth-child(1) {
    display: none;
  }
}

/* 7.5rem for the date at every width: pills are 12px (since 4 October
   2026; below 860px they always were) and "Overdue Sep 30" needs 115px. */
@media (max-width: 1000px) {
  .row--project {
    grid-template-columns: minmax(0, 1fr) 7rem 7.5rem;
  }
  .row--project > :nth-child(3) {
    display: none;
  }
  .row--task {
    grid-template-columns: minmax(0, 1fr) 7rem 7.5rem;
  }
  .row--task > :nth-child(6) {
    display: none;
  }
}

/* On a phone each row is a small card of two columns, with no header row
   (it would stack into a column of orphan labels, as the Settings
   categories table did). Everything dropped above comes back except the
   task reference and priority: name and stage or status first, then who
   and when, then progress and spending. */
@media (max-width: 620px) {
  .row--project.rowhead,
  .row--task.rowhead {
    display: none;
  }
  /* .row.row-- so it outranks the general phone rule for .row further
     down, which stacks every row into one column (and, with justify-items:
     start, let a long task title run to 482px on a 375px screen). */
  .row.row--project,
  .row.row--task {
    grid-template-columns: minmax(0, 1fr) auto;
    justify-items: stretch;
    column-gap: 0.75rem;
  }
  .row--project > :nth-child(n),
  .row--task > :nth-child(n) {
    display: revert;
  }
  .row--project > .row__main,
  .row--task > .row__main,
  .row--project > .row__progress,
  .row--task > .row__person,
  .row--project > .row__person {
    display: flex;
  }
  /* Without column headings a lone dash for "nothing spent" says nothing. */
  .row--task > .row__ref,
  .row--task > :nth-child(5),
  .row--project > .row__none {
    display: none;
  }
  .row--project > .row__person { order: 3; }
  .row--project > :nth-child(6) { order: 4; justify-self: end; }
  .row--project > .row__progress { order: 5; }
  .row--project > :nth-child(5) { order: 6; justify-self: end; }
  .row--task > :nth-child(4) { order: 3; justify-self: start; }
  .row--task > .row__person { order: 4; justify-self: end; }
}

@media (max-width: 1150px) {
  /* Ref, subject, status and due: the due day matters more here than
     priority or department. From 1150px, not 1000: with the assignee still
     showing, the subject was 96px wide at 1010. */
  .row--req {
    grid-template-columns: 1.5rem 8.5rem minmax(0, 1fr) 9rem 6rem;
  }
  .row--req > :nth-child(n + 6) {
    display: none;
  }
}

@media (max-width: 620px) {
  /* No tick boxes on a phone: acting on many at once is desk work. */
  .row--req {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .row--req > :nth-child(1),
  .row--req > :nth-child(2) {
    display: none;
  }
  .bulkbar {
    display: none;
  }
  .row--when {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  /* Three columns of which two never wrap: on a phone the date pill and the
     place together wanted more than the row had, so the title column — a
     minmax(0, 1fr) that is allowed to reach zero — collapsed to nothing and
     rows appeared with no title at all. Two columns, and the third item
     drops to a second line. */
  .row--plain {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .row__where {
    white-space: normal;
  }
}

/* =========================== pills =========================== */

.pill {
  display: inline-block;
  /* 12px, was 11px: a status is often the one thing on a row someone is
     looking for. */
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  line-height: 1.5;
  padding: 0.125rem 0.625rem;
  border-radius: var(--r-pill);
  white-space: nowrap;
  background: var(--pill-bg);
  color: var(--pill-text);
}

.pill--open {
  background: var(--accent-soft);
  color: var(--accent-dark);
}

.pill--attention {
  background: var(--warn-soft);
  color: var(--warn);
}

.pill--done {
  background: var(--ok-soft);
  color: var(--ok);
}

/* Cancelled, no-show and the like: finished without happening, which is
   a fact to note, not an alarm. They were red, the colour now kept for
   Urgent. */
.pill--stop {
  background: var(--neutral-soft);
  color: var(--muted);
}

/* Priority. Amber meant overdue, blocked, high priority, in review, on
   hold and waiting for approval at once, so it stopped meaning anything
   (4 October 2026). Now amber is "late or stuck", red is Urgent, and High
   is a darker neutral that stands out without raising an alarm. */
.pill--urgent {
  background: var(--danger-soft);
  color: var(--danger);
}

.pill--high {
  background: var(--high-bg);
  color: var(--text);
}

/* ========================== avatars ========================== */

.avatar {
  width: 28px;
  height: 28px;
  flex: 0 0 28px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent-dark);
  font-size: 0.6875rem;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
}

.assigned {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
}

/* ========================== buttons ========================== */

.button {
  font-family: var(--sans);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: #ffffff;
  background: var(--accent-solid);
  border: none;
  border-radius: var(--r-pill);
  padding: 0.5rem 1.0625rem;
  cursor: pointer;
  transition: background 0.15s ease, transform 0.15s ease;
}

.button:hover:not(:disabled) {
  background: var(--accent-solid-hover);
  transform: translateY(-1px);
}

.button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.button--block {
  width: 100%;
  padding: 0.5625rem 1rem;
}

/* The same shape, size and type as .button, outlined. Ghost buttons had
   only a colour and a border, so they took the browser's square corners
   and font: "Share to chat" and "Remove" sat square beside the rounded
   "Edit project" (4 October 2026). */
.button--ghost {
  font-family: var(--sans);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  padding: calc(0.5rem - 1px) 1.0625rem;
  cursor: pointer;
  transition: border-color 0.15s ease, transform 0.15s ease, color 0.15s ease;
}

.button--ghost:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.button--ghost:hover:not(:disabled) {
  color: var(--text);
  border-color: var(--border-strong);
  transform: translateY(-1px);
}

.button--small {
  font-size: 0.8125rem;
  padding: 0.25rem 0.75rem;
}

.button--ghost.button--small {
  padding: calc(0.25rem - 1px) 0.75rem;
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1.25rem;
}

.linkbutton {
  font-family: var(--sans);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--accent);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

.linkbutton:hover {
  text-decoration: underline;
}

.segmented {
  display: inline-flex;
  gap: 4px;
  padding: 0;
  background: transparent;
  border-radius: var(--r-control);
}

.segmented .button,
.segmented .button--ghost {
  box-shadow: none;
  border-color: transparent;
}

.segmented .button--ghost {
  background: transparent;
  border: none;
  color: var(--faint);
  border-radius: 8px;
  padding: 0.3125rem 0.875rem;
}

.segmented .button--ghost:hover {
  background: var(--surface);
  color: var(--text);
}

.segmented .button {
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: 8px;
  padding: 0.3125rem 0.875rem;
  transform: none;
}

.segmented .button:hover:not(:disabled) {
  background: var(--accent-soft);
  transform: none;
}

/* ========================== forms ============================ */

.form {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-sm);
  padding: 1.375rem;
  max-width: 44rem;
  margin-bottom: 1.25rem;
}

.group {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text);
  margin: 1.5rem 0 0.875rem;
  padding-top: 1.125rem;
  border-top: 1px solid var(--border-soft);
}

.group:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

.field {
  display: block;
  margin-bottom: 1rem;
}

/* A field shown only sometimes (Why it was lost). */
.field[hidden] {
  display: none;
}

.field__label {
  display: block;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-2);
  margin-bottom: 0.3125rem;
}

.field__input,
.field__select,
.field__textarea {
  width: 100%;
  padding: 0.5rem 0.6875rem;
  font-family: var(--sans);
  font-size: 0.875rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-control);
  box-shadow: var(--shadow-sm);
}

.field__textarea {
  min-height: 5.5rem;
  resize: vertical;
}

.field__input:focus,
.field__select:focus,
.field__textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(14, 124, 107, 0.12);
}

.field__input:disabled,
.field__select:disabled,
.field__textarea:disabled {
  background: var(--bg);
  color: var(--muted);
  box-shadow: none;
}

.field__hint {
  font-size: 0.8125rem;
  color: var(--muted);
  margin-top: 0.25rem;
}

.fieldpair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 1rem;
}

@media (max-width: 700px) {
  .fieldpair {
    grid-template-columns: 1fr;
  }
}

/* Town, state and ZIP of a request's location side by side, wrapping to
   one per line when they no longer fit. min(100%, ...) so a phone narrower
   than one column still gets a single full-width column rather than a
   track wider than the form. */
.fieldtrio {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr));
  gap: 0 1rem;
}

.checkline {
  display: flex;
  gap: 0.625rem;
  align-items: flex-start;
  margin-bottom: 1rem;
}

.checkline input {
  margin-top: 0.25rem;
}

.checkline__text {
  font-size: 0.875rem;
  font-weight: 500;
}

.checkline__hint {
  font-size: 0.8125rem;
  color: var(--muted);
  margin-top: 0.125rem;
}

/* Notification settings: one row per category, a column per channel.
   minmax(0, 1fr) rather than 1fr: a plain 1fr track will not shrink below its
   longest word, and the hints are long enough to push the checkboxes off a
   phone screen. */
.notifygrid {
  display: grid;
  margin-top: 0.75rem;
}

.notifygrid__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 5.5rem 5.5rem 5.5rem;
  gap: 0 0.75rem;
  align-items: start;
  padding: 0.75rem 0;
  border-top: 1px solid var(--border-soft);
}

.notifygrid__row--head {
  border-top: 0;
  padding-top: 0;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
}

.notifygrid__name {
  min-width: 0;
}

.notifygrid__col {
  text-align: center;
}

.notifygrid__col input {
  width: 1.125rem;
  height: 1.125rem;
  margin-top: 0.125rem;
}

.notifygrid__always {
  font-size: 0.8125rem;
  color: var(--muted);
}

/* Three switches on a phone: narrower columns, so the names keep about
   120px at 375 wide; the headings wrap onto two lines instead. */
@media (max-width: 480px) {
  .notifygrid__row {
    grid-template-columns: minmax(0, 1fr) 3.5rem 3.5rem 3.5rem;
    gap: 0 0.375rem;
  }
}

.notifygrid__col input:disabled {
  opacity: 0.45;
}

/* A meeting's "Are you going?", under its header for whoever is invited. */
.answerbox {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.25rem;
  padding: 0.875rem 1.125rem;
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-card);
}

.answerbox__text {
  min-width: 0;
  font-size: 0.875rem;
  color: var(--text);
}

.answerbox__question {
  font-size: 0.9375rem;
  font-weight: 600;
}

.answerbox__status {
  margin-top: 0.125rem;
  color: var(--muted);
}

.answerbox__choices {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.answerbox .notice {
  flex-basis: 100%;
  margin: 0;
}

.attendees__tally {
  margin: 0;
  padding: 0.75rem 1.125rem 0;
  font-size: 0.8125rem;
  color: var(--muted);
}

/* Settings > "Your meetings in your phone's calendar". */
.calfeed__intro {
  margin-top: 0;
}

.calfeed__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0.75rem 0;
}

/* The buttons are links here (webcal: and Google's page), so they carry
   the button look without an underline. */
.calfeed__actions a {
  text-decoration: none;
  display: inline-flex;
  align-items: center;
}

.calfeed__url {
  width: 100%;
  font-size: 1rem;
}

.calfeed__note {
  margin-bottom: 0;
}

/* Settings > Notifications: whether this device gets alerts. */
.devicealerts {
  margin-top: 0.875rem;
  padding: 0.875rem 1rem;
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-control);
}

.devicealerts__title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text);
}

.devicealerts__text {
  margin: 0.25rem 0 0;
  font-size: 0.875rem;
  color: var(--muted);
}

.devicealerts__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.devicealerts__actions:not(:empty) {
  margin-top: 0.75rem;
}

.devicealerts .notice,
.devicealerts .flash {
  margin: 0.75rem 0 0;
}

/* The Overview's offer to turn alerts on, on phones. Indigo, not amber:
   amber means late or stuck, and this is neither. */
.pushprompt {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.25rem;
  padding: 0.875rem 1.125rem;
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-card);
}

.pushprompt__title {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--text);
}

.pushprompt__text {
  margin-top: 0.125rem;
  font-size: 0.875rem;
  color: var(--muted);
}

.pushprompt__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.pushprompt .notice {
  flex-basis: 100%;
  margin: 0;
}

.readout {
  padding: 0.5625rem 0;
  border-top: 1px solid var(--border-soft);
  font-size: 0.875rem;
}

.readout__label {
  font-size: 0.75rem;
  color: var(--muted);
}

.formbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: flex-end;
  padding-bottom: 1rem;
  margin-bottom: 1.125rem;
  border-bottom: 1px solid var(--border-soft);
}

.inline-form {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0.875rem 1.125rem;
  border-top: 1px solid var(--border-soft);
  background: var(--surface-2);
}

.inline-form .field__input,
.inline-form .field__select {
  flex: 1 1 13rem;
  width: auto;
}

/* ======================== record header ====================== */

.metastrip {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2rem;
  align-items: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-sm);
  padding: 0.9375rem 1.125rem;
  margin-bottom: 1.25rem;
}

.metaitem__label {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.1875rem;
}

.metaitem__value {
  font-size: 0.875rem;
  font-weight: 500;
}

/* ========================= messages ========================== */

.notice {
  margin: 0 0 1rem;
  padding: 0.625rem 0.875rem;
  font-size: 0.875rem;
  color: var(--danger);
  background: var(--danger-soft);
  border: 1px solid var(--danger-line);
  border-radius: var(--r-control);
}

.flash {
  margin-bottom: 1.25rem;
  padding: 0.625rem 0.875rem;
  font-size: 0.875rem;
  color: var(--ok);
  background: var(--ok-soft);
  border: 1px solid var(--ok-line);
  border-radius: var(--r-control);
}

.banner {
  background: var(--warn-soft);
  border: 1px solid var(--warn-line);
  border-left: 3px solid var(--warn);
  border-radius: var(--r-card);
  padding: 0.875rem 1.125rem;
  margin-bottom: 1.25rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.625rem 1rem;
  align-items: center;
  justify-content: space-between;
}

.banner__text {
  font-size: 0.875rem;
}

.banner__strong {
  font-weight: 600;
}

.banner__meta {
  font-size: 0.8125rem;
  color: var(--muted);
  margin-top: 0.125rem;
}

.empty {
  padding: 1.25rem 1.125rem;
  color: var(--muted);
  font-size: 0.875rem;
}

.state {
  padding: 1.25rem 0;
  color: var(--muted);
  font-size: 0.875rem;
}

.emptystate {
  padding: 2.25rem 1.25rem;
  text-align: center;
}

.emptystate__title {
  font-size: 1rem;
  font-weight: 600;
  margin-bottom: 0.25rem;
}

.emptystate__text {
  font-size: 0.875rem;
  color: var(--muted);
  max-width: 34rem;
  margin: 0 auto 0.875rem;
}

/* ========================== search =========================== */

.search {
  position: relative;
  flex: 0 1 18rem;
}

.search__input {
  width: 100%;
  padding: 0.4375rem 0.6875rem;
  font-family: var(--sans);
  font-size: 0.875rem;
  border: 1px solid var(--border);
  border-radius: var(--r-control);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}

.search__input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(14, 124, 107, 0.12);
}

.search__results {
  position: absolute;
  z-index: 30;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-pop);
  max-height: 22rem;
  overflow-y: auto;
}

.searchrow {
  display: block;
  width: 100%;
  text-align: left;
  font-family: var(--sans);
  font-size: 0.875rem;
  background: none;
  border: none;
  border-bottom: 1px solid var(--border-soft);
  padding: 0.5rem 0.75rem;
  cursor: pointer;
}

.searchrow:last-child {
  border-bottom: none;
}

.searchrow:hover {
  background: var(--bg);
}

.searchrow__kind {
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

/* ========================= filters =========================== */

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  align-items: center;
  padding: 0.75rem 1.125rem;
  border-bottom: 1px solid var(--border-soft);
  background: var(--surface-2);
}

.filters__select {
  font-family: var(--sans);
  font-size: 0.8125rem;
  padding: 0.3125rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--r-control);
  background: var(--surface);
  color: var(--text);
}

.filters__search {
  /* 1rem: iOS Safari zooms into any smaller field and never zooms back. */
  font-family: var(--sans);
  font-size: 1rem;
  flex: 1 1 14rem;
  min-width: 0;
  padding: 0.3125rem 0.625rem;
  border: 1px solid var(--border);
  border-radius: var(--r-control);
  background: var(--surface);
  color: var(--text);
}

.filters__count {
  margin-left: auto;
  font-size: 0.8125rem;
  color: var(--muted);
}

/* ===================== list views and filters =====================
   The enterprise lists (9 October 2026): saved views as rounded choices
   with counts, the filters in use as removable tags, a filter panel
   beside the List (above the Inbox and Board), and a bar for what to do
   with ticked rows. */
.listviews {
  display: flex;
  gap: 0.5rem;
  padding: 0.75rem 1.25rem 0.25rem;
  overflow-x: auto;
  scrollbar-width: thin;
}

.listview {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.4375rem;
  min-height: 2.125rem;
  padding: 0 0.875rem;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--text-2);
  font-family: var(--sans);
  font-size: 0.8125rem;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
}

.listview:hover {
  border-color: var(--border-strong);
  color: var(--text);
}

.listview--on,
.listview--on:hover {
  background: var(--accent-soft);
  border-color: var(--accent-line);
  color: var(--accent-dark);
  font-weight: 600;
}

.listview__n {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.listview--on .listview__n {
  color: var(--accent-dark);
}

/* Overdue's count in the late colour, in words beside it already. */
.listview__n--late {
  color: var(--warn);
}

.filtertag {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  min-height: 1.75rem;
  padding: 0 0.25rem 0 0.625rem;
  border: 1px solid var(--accent-line);
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent-dark);
  font-size: 0.8125rem;
  font-weight: 500;
  white-space: nowrap;
}

.filtertag__x {
  width: 1.375rem;
  height: 1.375rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  border-radius: var(--r-pill);
  background: transparent;
  color: inherit;
  cursor: pointer;
}

.filtertag__x:hover {
  background: var(--surface);
}

.filtertag__x svg {
  width: 12px;
  height: 12px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
}

.listlayout {
  display: flex;
  flex-direction: column;
}

.listlayout__main {
  min-width: 0;
}

.filterpanel {
  padding: 0.875rem 1.25rem 0.25rem;
  border-bottom: 1px solid var(--border-soft);
  background: var(--surface-2);
}

.filterpanel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.625rem;
}

.filterpanel__title {
  margin: 0;
  font-size: 0.9375rem;
  font-weight: 700;
}

.filterpanel__fields {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
  gap: 0 1rem;
}

.filterpanel .filters__select {
  width: 100%;
  min-height: 2.25rem;
}

/* Beside the List on a laptop: the table keeps the width it needs and
   the panel takes a column on the right, wrapping under it below. */
@media (min-width: 1100px) {
  .listlayout--side {
    flex-direction: row;
    align-items: flex-start;
  }

  .listlayout--side .listlayout__main {
    flex: 1 1 0;
  }

  .listlayout--side .filterpanel {
    order: 2;
    flex: 0 0 15rem;
    align-self: stretch;
    border-bottom: none;
    border-left: 1px solid var(--border-soft);
  }

  .listlayout--side .filterpanel__fields {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* With the panel beside it the table loses 15rem: at 1280 and 1440 the
   subject was 182px. Priority and department, both in the panel, make
   way for it. */
@media (min-width: 1100px) and (max-width: 1700px) {
  .listlayout--side:has(> .filterpanel) .row--req {
    grid-template-columns: 1.5rem 8.5rem minmax(0, 1fr) 9rem 6rem 9rem;
  }

  .listlayout--side:has(> .filterpanel) .row--req > :nth-child(6),
  .listlayout--side:has(> .filterpanel) .row--req > :nth-child(7) {
    display: none;
  }
}

.bulkbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  padding: 0.5rem 1.25rem;
  border-bottom: 1px solid var(--accent-line);
  background: var(--accent-soft);
  font-size: 0.875rem;
}

.bulkbar[hidden] {
  display: none;
}

.bulkbar__count {
  color: var(--accent-dark);
}

.bulkbar__clear {
  margin-left: auto;
}

.row__tick {
  display: flex;
  align-items: center;
}

.row__tick input {
  width: 16px;
  height: 16px;
  margin: 0;
  accent-color: var(--accent-solid);
}

.row--ticked {
  background: var(--accent-soft);
}

/* Tick boxes on the project and task tables (addTicks): in the row's
   left padding, out of the column grid, so the tables' column rules are
   untouched. An absolutely placed child takes no grid cell. Only above
   phone width; on a phone the box and the bar are not shown. */
/* Three classes: the phone rule that shows every cell of these rows
   (.row--project > :nth-child(n), display: revert) outranked one class,
   and the boxes showed on a phone. */
.rows--tick > .row > .rowtick,
.rows--tick > .contactitem > .rowtick {
  display: none;
}

/* Contacts: each row (a button) in a wrapper, so a tick box can sit
   beside it. The rows' dividing line was drawn on every row but the
   last; in a wrapper every row is its wrapper's last child, so the line
   moves to the wrapper. */
.contactitem {
  position: relative;
  border-bottom: 1px solid var(--border-soft);
}

.contactitem:last-child {
  border-bottom: none;
}

.contactitem > .contactrow {
  border-bottom: none;
}

.contactitem--ticked,
.contactitem.row--ticked {
  background: var(--accent-soft);
}

.contacthead {
  display: none;
  padding: 0.5rem 1.25rem 0.5rem 2.75rem;
  font-size: 0.8125rem;
  color: var(--muted);
}

@media (min-width: 621px) {
  .rows--tick > .row {
    position: relative;
    padding-left: 2.75rem;
  }

  .rows--tick > .contactitem > .contactrow {
    padding-left: 2.75rem;
  }

  .rows--tick > .contacthead {
    display: block;
  }

  .rows--tick > .contactitem > .rowtick,
  .rows--tick > .row > .rowtick {
    display: block;
    position: absolute;
    left: 0.9375rem;
    top: 50%;
    width: 16px;
    height: 16px;
    margin: -8px 0 0;
    accent-color: var(--accent-solid);
  }
}

/* The due day, and under it how far off in words: "Tomorrow", "3 days
   over" (in the late colour), "Paused" while waiting on the requester. */
.row__due {
  display: flex;
  flex-direction: column;
  font-size: 0.8125rem;
  color: var(--text-2);
  white-space: nowrap;
}

.row__duewords {
  font-size: 0.75rem;
  color: var(--muted);
}

.row__duewords--late {
  color: var(--warn);
  font-weight: 600;
}

/* ======================= activity feed ======================= */

.event {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto;
  gap: 0.75rem;
  align-items: start;
  padding: 0.75rem 1.125rem;
  border-bottom: 1px solid var(--border-soft);
}

.event:last-child {
  border-bottom: none;
}

.event__text {
  font-size: 0.875rem;
  line-height: 1.45;
  color: var(--text-2);
}

.event__actor {
  font-weight: 600;
  color: var(--text);
}

.event__when {
  font-size: 0.75rem;
  color: var(--faint);
  white-space: nowrap;
}

/* ====================== workload bars ======================== */

.bars {
  padding: 1rem 1.125rem;
}

.bar {
  margin-bottom: 0.875rem;
}

.bar:last-child {
  margin-bottom: 0;
}

.bar__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 0.8125rem;
  margin-bottom: 0.3125rem;
}

.bar__count {
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

.bar__track {
  height: 8px;
  background: var(--track);
  border-radius: 999px;
  overflow: hidden;
}

.bar__fill {
  height: 100%;
  background: var(--accent);
  border-radius: 999px;
}

.bar__fill--flag {
  background: var(--warn);
}

/* ========================= skeletons ========================= */

.skeleton {
  padding: 1rem 1.125rem;
}

.skel {
  height: 11px;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--track) 25%, var(--track-2) 37%, var(--track) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.3s ease-in-out infinite;
  margin-bottom: 0.625rem;
}

.skel:last-child {
  margin-bottom: 0;
}

.skel--w40 { width: 40%; }
.skel--w70 { width: 70%; }
.skel--w55 { width: 55%; }

@keyframes shimmer {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

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

/* =========================== board =========================== */

.board {
  display: flex;
  gap: 0.875rem;
  padding: 1rem 1.125rem 1.25rem;
  align-items: stretch;
}

.column {
  flex: 1 1 0;
  min-width: 0;
  background: var(--bg);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-card);
  padding: 0.625rem;
  display: flex;
  flex-direction: column;
}

.column--over {
  background: var(--accent-soft);
  border-color: var(--accent);
}

/* An empty column keeps a narrow strip, still a place to drop a card, and
   gives its width to the columns with work in them. Five equal columns
   left each project card 156px at 1280, and a long name ran to six lines. */
.column:has(> .column__empty) {
  flex: 0 0 7.5rem;
}

.column__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0 0.25rem 0.5rem;
}

.column__name {
  display: flex;
  align-items: center;
  font-size: 0.8125rem;
  font-weight: 600;
}

.column__count {
  font-size: 0.75rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.column__dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  margin-right: 0.4375rem;
  background: var(--faint);
}

.column__dot--open { background: var(--accent); }
.column__dot--attention { background: var(--warn); }
.column__dot--done { background: var(--ok); }
.column__dot--stop { background: var(--faint); }

.column__empty {
  flex: 1;
  min-height: 4.5rem;
  border: 1px dashed var(--border-dashed);
  border-radius: var(--r-control);
  margin-top: 0.125rem;
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--faint);
  border-radius: var(--r-control);
  box-shadow: var(--shadow-sm);
  padding: 0.625rem 0.6875rem;
  margin-bottom: 0.5rem;
  cursor: grab;
  transition: box-shadow 0.12s ease;
}

.card:hover {
  box-shadow: var(--shadow-md);
}

.card:last-child {
  margin-bottom: 0;
}

.card--dragging {
  opacity: 0.45;
}

.card--open { border-left-color: var(--accent); }
.card--attention { border-left-color: var(--warn); }
.card--done { border-left-color: var(--ok); }
.card--stop { border-left-color: var(--faint); }

.card__title {
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.35;
  margin-bottom: 0.375rem;
  cursor: pointer;
  /* Three lines at most; the whole title is in the tooltip and on the
     record. Long names made one card as tall as the column. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
  overflow-wrap: anywhere;
}

.card__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.5rem;
  align-items: center;
  font-size: 0.75rem;
  color: var(--muted);
}

/* One line, like the inbox's: the whole street is in the tooltip. */
.card__where {
  font-size: 0.75rem;
  color: var(--muted);
  margin: -0.125rem 0 0.375rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.card__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

.card__progress {
  font-size: 0.6875rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.card .avatar {
  width: 22px;
  height: 22px;
  flex: 0 0 22px;
  font-size: 0.5625rem;
}

.card__move {
  display: none;
  margin-top: 0.5rem;
  width: 100%;
  font-family: var(--sans);
  font-size: 0.75rem;
  padding: 0.1875rem 0.25rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--surface);
  color: var(--muted);
}

@media (hover: none), (pointer: coarse) {
  /* 16px: this list appears only on touch screens, and at 12px iPhone
     Safari zoomed in on tapping it and never zoomed back out. */
  .card__move { display: block; font-size: 1rem; }
  .card { cursor: default; }
}

@media (max-width: 1100px) {
  .board { overflow-x: auto; }
  .column { flex: 0 0 262px; }
}

/* ========================= timeline ========================== */

.timeline {
  padding: 1rem 1.125rem 1.25rem;
  overflow-x: auto;
}

.tlhead {
  display: grid;
  grid-template-columns: 12rem 1fr;
  gap: 0.75rem;
  align-items: end;
  margin-bottom: 0.5rem;
}

.tlmonths {
  display: flex;
  border-bottom: 1px solid var(--border);
}

.tlmonth {
  flex: 1;
  font-size: 0.6875rem;
  color: var(--muted);
  padding-bottom: 0.25rem;
  padding-left: 0.25rem;
  border-left: 1px solid var(--border-soft);
}

.tlmonth:first-child {
  border-left: none;
}

.tlrow {
  display: grid;
  grid-template-columns: 12rem 1fr;
  gap: 0.75rem;
  align-items: center;
  padding: 0.375rem 0;
}

.tlname {
  font-family: var(--sans);
  font-size: 0.8125rem;
  font-weight: 500;
  text-align: left;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tlname:hover {
  color: var(--accent);
}

.tltrack {
  position: relative;
  height: 22px;
  background: var(--bg);
  border-radius: var(--r-control);
}

.tlbar {
  position: absolute;
  top: 3px;
  height: 16px;
  border-radius: 4px;
  background: var(--accent);
  min-width: 4px;
}

.tlbar--attention { background: var(--warn); }
.tlbar--done { background: var(--ok); }
.tlbar--stop { background: var(--faint); }

.tltoday {
  position: absolute;
  top: -2px;
  bottom: -2px;
  width: 2px;
  background: var(--warn);
  opacity: 0.75;
}

.tlnote {
  font-size: 0.75rem;
  color: var(--muted);
  padding: 0 1.125rem 1rem;
}

/* ========================= schedule ========================== */

.dayhead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.6875rem 1.125rem 0.5rem;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border-soft);
}

.dayhead__label {
  font-size: 0.8125rem;
  font-weight: 600;
}

.dayhead__date {
  font-size: 0.8125rem;
  color: var(--muted);
}

.dayhead--today .dayhead__label {
  color: var(--accent);
}

.slot {
  display: grid;
  grid-template-columns: 7.5rem minmax(0, 1fr) auto auto;
  gap: 0.5rem 1rem;
  align-items: center;
  padding: 0.6875rem 1.125rem;
  border-bottom: 1px solid var(--border-soft);
}

.slot:hover {
  background: var(--surface-2);
}

.slot__time {
  font-variant-numeric: tabular-nums;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-2);
}

.slot__time--allday {
  color: var(--muted);
  font-weight: 400;
}

.slot__sub {
  font-size: 0.8125rem;
  color: var(--muted);
  grid-column: 2 / -1;
  margin-top: -0.25rem;
}

.slot--cancelled .row__link {
  text-decoration: line-through;
  color: var(--muted);
}

@media (max-width: 860px) {
  .slot {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .slot__time {
    grid-column: 1 / -1;
  }
}

/* ==================== duration picker ======================== */

.timerow {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 0.75rem;
}

.presets {
  display: flex;
  gap: 0.375rem;
  margin-bottom: 0.75rem;
  flex-wrap: wrap;
}

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

/* The Attendees panel's body has no padding of its own; each part
   carries 20px at the sides, so the clash warnings do too. */
.attendees__clash {
  padding: 0 20px;
}

.conflict {
  margin: 0 0 1rem;
  padding: 0.625rem 0.875rem;
  font-size: 0.875rem;
  color: var(--warn);
  background: var(--warn-soft);
  border: 1px solid var(--warn-line);
  border-radius: var(--r-control);
}

@media (max-width: 860px) {
  .timerow {
    grid-template-columns: 1fr;
  }
}

/* ====================== week calendar ======================== */

.weeknav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
}

.weekgrid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  border-top: 1px solid var(--border-soft);
}

.weekday {
  border-right: 1px solid var(--border-soft);
  min-height: 9rem;
  padding: 0.5rem;
}

.weekday:last-child {
  border-right: none;
}

.weekday--today {
  background: var(--accent-soft);
}

.weekday--past {
  background: var(--surface-2);
}

.weekday__name {
  font-size: 0.6875rem;
  font-weight: 500;
  color: var(--muted);
}

.weekday__num {
  font-size: 1.0625rem;
  font-weight: 600;
  line-height: 1.1;
  margin-bottom: 0.5rem;
}

.weekday--today .weekday__num {
  color: var(--accent-dark);
}

.chip {
  display: block;
  width: 100%;
  text-align: left;
  font-family: var(--sans);
  font-size: 0.75rem;
  line-height: 1.3;
  color: var(--text);
  background: var(--chip-bg);
  border: none;
  border-left: 3px solid var(--faint);
  border-radius: 4px;
  padding: 0.25rem 0.375rem;
  margin-bottom: 0.25rem;
  cursor: pointer;
}

.chip:hover {
  filter: brightness(0.97);
}

.chip--open {
  background: var(--accent-soft);
  border-left-color: var(--accent);
}

.chip--attention {
  background: var(--warn-soft);
  border-left-color: var(--warn);
}

/* The project under a task on the calendar. One line, cut with an
   ellipsis: in a 140px day a long project name would otherwise double the
   chip's height. */
.chip__sub {
  display: block;
  margin-top: 0.125rem;
  font-size: 0.6875rem;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chip--stop {
  background: var(--neutral-soft);
  border-left-color: var(--faint);
  text-decoration: line-through;
  color: var(--muted);
}

.chip__time {
  display: block;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

/* Said on a phone only, where empty days are hidden; on a laptop the
   empty grid says it. */
.weekgrid__none {
  display: none;
  margin: 0;
  padding: 1rem 1.125rem;
  font-size: 0.875rem;
  color: var(--muted);
}

@media (max-width: 860px) {
  .weekgrid {
    grid-template-columns: 1fr;
  }
  .weekday {
    border-right: none;
    border-bottom: 1px solid var(--border-soft);
    min-height: 0;
  }
  .weekday--empty {
    display: none;
  }
  .weekgrid__none {
    display: block;
  }
}


/* ========================= comments ========================== */

.comment {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  gap: 0.75rem;
  padding: 0.875rem 1.125rem;
  border-bottom: 1px solid var(--border-soft);
}

.comment:last-of-type {
  border-bottom: none;
}

.comment__head {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem 0.625rem;
  align-items: baseline;
  margin-bottom: 0.1875rem;
}

.comment__author {
  font-size: 0.875rem;
  font-weight: 600;
}

.comment__when {
  font-size: 0.75rem;
  color: var(--faint);
}

.comment__body {
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--text-2);
  white-space: pre-wrap;
}

.mention {
  font-size: 0.75rem;
  padding: 0.0625rem 0.4375rem;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent-dark);
}

.composer {
  padding: 0.875rem 1.125rem;
  border-top: 1px solid var(--border-soft);
  background: var(--surface-2);
}

.composer__row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  margin-top: 0.5rem;
}

.tagpick {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin-top: 0.5rem;
}

.tagbtn {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 500;
  padding: 0.1875rem 0.5625rem 0.1875rem 0.1875rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
}

.tagbtn:hover {
  border-color: var(--border-strong);
}

.tagbtn--on {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent-dark);
}

.tagbtn .avatar {
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
  font-size: 0.5625rem;
}

/* ======================== attachments ======================== */

/* Flex rather than a fixed four-column grid: a row carries a different
   number of parts depending on whether the file came from the requester and
   whether the viewer may remove it, and a fixed grid put the buttons in
   different columns from one row to the next. */
.file {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.875rem;
  align-items: center;
  padding: 0.625rem 1.125rem;
  border-bottom: 1px solid var(--border-soft);
  font-size: 0.875rem;
}

.file:last-of-type {
  border-bottom: none;
}

.file__name {
  /* Takes the room, so everything after it sits to the right. */
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
}

.file__size {
  font-size: 0.75rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.dropzone {
  margin: 0.875rem 1.125rem 1.125rem;
  padding: 1.125rem;
  border: 1px dashed var(--border-dashed);
  border-radius: var(--r-card);
  text-align: center;
  font-size: 0.875rem;
  color: var(--muted);
  background: var(--surface-2);
}

.dropzone--over {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent-dark);
}

@media (max-width: 700px) {
  .file {
    grid-template-columns: minmax(0, 1fr) auto;
  }
}

/* ==================== platform console ======================= */

.clients {
  list-style: none;
  margin: 0;
  padding: 0;
}

.client {
  display: grid;
  /* The details line used to be an "auto" column, which takes its whole
     width before the name gets any: on a phone the name's column was 0px
     and the name ran 52px over the details. Both can shrink now; on a
     phone they stack (below). */
  grid-template-columns: minmax(10rem, 1fr) minmax(0, max-content);
  gap: 0.75rem 1rem;
  align-items: center;
  padding: 1rem 1.125rem;
  border-bottom: 1px solid var(--border-soft);
}

.client:last-child {
  border-bottom: none;
}

.client__name {
  font-size: 0.9375rem;
  font-weight: 600;
  min-width: 0;
  overflow-wrap: anywhere;
}

/* A client's modules: name, on or off, where that comes from, and up to two
   buttons, in one line that wraps. A plain row is a three-column grid, so
   the buttons fell onto a line of their own at the panel's full width. */
.row--module {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
}

.row--module .row__link {
  flex: 1 1 10rem;
  min-width: 0;
}

.row--module .row__where {
  min-width: 6.5rem;
}

.row--module .row__btns {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  min-width: 12.5rem;
}

@media (max-width: 620px) {
  .row--module .row__btns {
    min-width: 0;
  }
}

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

  /* Four totals one per row filled the whole first screen of the console
     before any client appeared. */
  .register {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* A client's name in the control panel's Recent changes: a long one ran
   97px past a 375px screen as one line. */
.pill.pill--org {
  white-space: normal;
  max-width: 100%;
  overflow-wrap: anywhere;
}

/* The control panel's two attention figures, when they count anything. */
.figure.figure--flag .figure__value {
  color: var(--warn);
}

/* A line of text and a row of buttons inside a panel, in its padding. */
.panelnote {
  margin: 0;
  padding: 0.25rem 1.25rem 0.875rem;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--muted);
}

.panelactions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0 1.25rem 1.25rem;
}

/* Links with what each is for under the name (services, public pages). */
.linklist {
  list-style: none;
  margin: 0;
  padding: 0 0.75rem 0.75rem;
}

.linklist__item {
  display: grid;
  gap: 0.125rem;
  padding: 0.625rem 0.5rem;
  border-radius: var(--r-sm, 0.5rem);
  color: var(--text);
  text-decoration: none;
}

.linklist__item:hover,
.linklist__item:focus-visible {
  background: var(--surface-2);
}

.linklist__name {
  font-size: 0.875rem;
  font-weight: 600;
}

.linklist__arrow {
  color: var(--muted);
  font-weight: 400;
}

.linklist__what {
  font-size: 0.8125rem;
  color: var(--muted);
}

/* A form inside a panel, without a card of its own. */
.form.form--flat {
  border: none;
  box-shadow: none;
  border-radius: 0;
  background: transparent;
  margin: 0;
  padding: 0.25rem 1.25rem 1.25rem;
}

/* A client's use: four figures in a row (two on a phone). */
.usegrid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.75rem;
  padding: 0.25rem 1.25rem 1rem;
}

.usegrid__cell {
  padding: 0.75rem 0.875rem;
  border: 1px solid var(--border-soft);
  border-radius: 0.625rem;
  background: var(--surface-2);
  min-width: 0;
}

.usegrid__label {
  font-size: 0.75rem;
  color: var(--muted);
}

.usegrid__value {
  margin-top: 0.25rem;
  font-size: 1rem;
  font-weight: 700;
}

.usegrid__note {
  grid-column: 1 / -1;
  margin: 0;
  font-size: 0.8125rem;
  color: var(--muted);
}

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

/* A client's trial on its page: no trial, open-ended, or a date. */
.trialform {
  padding: 0.875rem 1.25rem 1.25rem;
  border-top: 1px solid var(--border-soft);
}

.trialform__choices {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0.5rem 0 0.375rem;
}

.trialform__choice {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.9375rem;
}

.trialform__dated {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
}

.trialform__date {
  width: auto;
  max-width: 12rem;
}

.client__info {
  min-width: 0;
}

.client__meta {
  font-size: 0.8125rem;
  color: var(--muted);
  margin-top: 0.1875rem;
}

.client__actions {
  display: flex;
  gap: 0.5rem;
}

/* ========================== sign in ========================== */

/* The layout of the Codex design preview (8 October 2026): a navy panel
   with the headline and a drawn workflow card beside a light panel with
   the form, both inside a 14px margin. Below 641px the navy panel becomes
   a short header with a small card in its corner and the form follows.
   Colours are the --auth-* tokens at the top of this file. */
.auth {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  min-height: 100%;
  padding: 14px;
  background: var(--bg);
}

.auth__brand {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
  padding: 2.4375rem 3rem 1.8125rem;
  border-radius: 15px;
  background: var(--auth-navy);
  box-shadow: inset 0 0 0 1px var(--auth-panel-edge);
  color: var(--auth-on-navy);
}

.auth__brand .brandlogo__word {
  color: var(--auth-on-navy);
  font-size: 1.625rem;
  font-weight: 800;
  letter-spacing: -0.04em;
}

.auth__brand .brandlogo {
  gap: 0.625rem;
}

.auth__story {
  position: relative;
  z-index: 1;
  margin-top: 3.5rem;
}

.auth__eyebrow {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  margin: 0 0 1.1875rem;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--auth-navy-text);
}

.auth__eyebrowline {
  width: 22px;
  height: 2px;
  background: var(--auth-navy-accent);
}

.auth__headline {
  /* Two lines on a laptop ("A clearer day / starts here.", as in the
     preview). The 5 October headline was longer and took three at this
     size, pushing the panel past a 1000px screen; this width is from it. */
  max-width: 22ch;
  margin: 0 0 1.375rem;
  font-size: clamp(2.125rem, 3.2vw, 3.25rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.035em;
  color: var(--auth-on-navy);
  /* Even lines rather than a lone word on the last one. */
  text-wrap: balance;
}

.auth__headline em {
  font-style: normal;
  color: var(--auth-navy-accent);
}

.auth__note {
  max-width: 44ch;
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.75;
  color: var(--auth-navy-text);
}

/* The workflow card. */
.authflow {
  position: relative;
  isolation: isolate;
  flex: 1;
  min-height: 24.375rem;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 -0.75rem;
  padding: 2rem 1.25rem 3.125rem;
}

.authflow__grid {
  position: absolute;
  inset: 14px -20px 10px;
  z-index: -1;
  background-image:
    linear-gradient(var(--auth-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--auth-grid) 1px, transparent 1px);
  background-size: 38px 38px;
  -webkit-mask-image: radial-gradient(ellipse, #000 15%, transparent 70%);
  mask-image: radial-gradient(ellipse, #000 15%, transparent 70%);
}

.authflow__tick {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.authflow__stack {
  position: relative;
  width: 100%;
  max-width: 26rem;
}

.authflow__card {
  width: 100%;
  overflow: hidden;
  background: var(--auth-card);
  border: 1px solid var(--auth-card-border);
  border-radius: 12px;
  box-shadow: var(--auth-card-shadow);
  color: var(--auth-card-text);
  transform: rotate(-3deg);
}

.authflow__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.75rem 1.125rem;
  background: var(--auth-card-bar);
  border-bottom: 1px solid var(--auth-card-line);
}

.authflow__app {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--auth-card-muted);
}

.authflow__sample,
.authflow__label {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--auth-card-muted);
}

.authflow__body {
  padding: 1.1875rem 1.375rem 1.25rem;
}

.authflow__title {
  margin: 0.625rem 0 0.25rem;
  font-size: 1.1875rem;
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: -0.02em;
}

.authflow__subtitle {
  font-size: 0.75rem;
  color: var(--auth-card-muted);
}

.authflow__stages {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin: 1.5rem 0 1.25rem;
}

.authflow__stages > i {
  flex: 1;
  height: 1px;
  margin: 14px 10px 0;
  background: var(--auth-card-border);
}

.authflow__stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex-shrink: 0;
  gap: 0.5rem;
  font-size: 0.6875rem;
  color: var(--auth-card-muted);
}

.authflow__dot {
  display: grid;
  place-items: center;
  width: 29px;
  height: 29px;
  border-radius: 50%;
  background: var(--auth-card-soft);
  color: var(--auth-card-blue);
}

.authflow__stage--done {
  font-weight: 600;
  color: var(--auth-card-blue);
}

.authflow__stage--done .authflow__dot {
  background: var(--auth-card-blue);
  color: var(--auth-card);
  box-shadow: 0 0 0 4px var(--auth-card-soft);
}

.authflow__task {
  display: flex;
  align-items: center;
  gap: 0.5625rem;
  padding: 0.6875rem 0;
  border-top: 1px solid var(--auth-card-line);
  font-size: 0.75rem;
  color: var(--auth-card-muted);
}

.authflow__check {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  background: var(--auth-card-soft);
  border: 1px solid var(--auth-card-border);
  border-radius: 4px;
  color: var(--auth-card-blue);
}

.authflow__check .authflow__tick {
  width: 12px;
  height: 12px;
  stroke-width: 2.4;
}

.authflow__person {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  margin-left: auto;
  border-radius: 50%;
  background: var(--auth-card-soft);
  color: var(--auth-card-blue);
  font-size: 0.625rem;
  font-weight: 600;
}

.authflow__person--2 {
  background: var(--auth-card-teal-bg);
  color: var(--auth-card-teal);
}

.authflow__progress {
  padding-top: 0.625rem;
}

.authflow__progress > div:first-child {
  display: flex;
  justify-content: space-between;
  gap: 0.625rem;
  font-size: 0.6875rem;
  color: var(--auth-card-muted);
}

.authflow__progress strong {
  font-weight: 600;
  color: var(--auth-card-blue);
}

.authflow__track {
  height: 4px;
  margin-top: 0.5625rem;
  overflow: hidden;
  border-radius: 5px;
  background: var(--auth-card-line);
}

.authflow__track span {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--auth-navy-accent), var(--auth-card-blue));
}

.authflow__toast {
  position: absolute;
  left: -3.5rem;
  bottom: -1.75rem;
  width: min(23rem, calc(100% + 2rem));
  display: flex;
  align-items: center;
  gap: 0.6875rem;
  padding: 0.9375rem 1.0625rem;
  background: var(--auth-toast);
  border: 1px solid var(--auth-toast-border);
  border-radius: 10px;
  box-shadow: var(--auth-toast-shadow);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  transform: rotate(2deg);
}

.authflow__toasticon {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  background: var(--auth-toast-icon);
  border: 1px solid var(--auth-toast-icon-border);
  color: var(--auth-navy-accent);
}

.authflow__toast strong {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--auth-toast-text);
}

.authflow__toast div > span {
  display: block;
  margin-top: 0.1875rem;
  font-size: 0.6875rem;
  color: var(--auth-toast-muted);
}

.authflow__mini {
  display: none;
}

.auth__brandfoot {
  position: relative;
  z-index: 1;
  margin-top: 0.75rem;
  padding-top: 1.375rem;
  border-top: 1px solid var(--auth-navy-line);
}

.auth__tagline {
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--auth-navy-faint);
}

.auth__features {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  margin-top: 0.5625rem;
  font-size: 0.75rem;
  color: var(--auth-navy-text);
}

.auth__features i {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--auth-navy-faint);
}

/* The form panel. */
.auth__form {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 2rem 3rem 1rem;
}

.auth__inner {
  width: 100%;
  max-width: 24rem;
  margin: auto;
  padding: 2.5rem 0;
}

.auth__padlock {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin-bottom: 1.5rem;
  border-radius: 12px;
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  color: var(--accent);
}

.auth__padlock svg {
  width: 27px;
  height: 27px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.auth__heading {
  margin: 0 0 0.75rem;
  font-size: 2.1875rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.035em;
}

.auth__sub {
  margin: 0 0 1.875rem;
  font-size: 0.9375rem;
  line-height: 1.7;
  color: var(--muted);
}

.auth__fields {
  display: flex;
  flex-direction: column;
}

.auth .field {
  margin-bottom: 1.3125rem;
}

.auth .field__label {
  margin-bottom: 0.5rem;
  font-weight: 600;
}

/* Password's label and "Forgot password?" on one line. */
.auth__labelrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.5rem;
}

.auth__labelrow .field__label {
  margin: 0;
}

.authinput {
  position: relative;
  display: block;
}

.authinput__icon {
  position: absolute;
  top: 50%;
  left: 14px;
  z-index: 1;
  width: 19px;
  height: 19px;
  transform: translateY(-50%);
  color: var(--faint);
  pointer-events: none;
}

.authinput__icon svg {
  display: block;
  width: 100%;
  height: 100%;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The one form everyone uses every day gets full-size targets on every
   screen. 16px text so a phone does not zoom into the box (see the
   landmine about iOS). */
.auth .field__input {
  min-height: 3rem;
  padding-left: 2.75rem;
  font-size: 1rem;
}

.auth .button--block {
  min-height: 3rem;
  border-radius: var(--r-control);
  font-size: 0.9375rem;
}

.auth__caps {
  margin: -0.5rem 0 1rem;
  font-size: 0.8125rem;
  color: var(--warn);
}

/* "No account yet?" under a rule, as the preview has it. */
.auth__account {
  margin-top: 1.75rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--border);
  text-align: center;
  font-size: 0.8125rem;
  color: var(--muted);
}

.auth__account p {
  margin: 0.25rem 0 0;
  color: var(--text-2);
}

.auth__help {
  margin: 1.25rem 0 0;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--muted);
}

.auth__foot {
  /* "© year Macsen" at the left, "Made for your everyday." at the right. */
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.25rem 1rem;
  font-size: 0.75rem;
  color: var(--faint);
}

@media (min-width: 1450px) {
  .auth__brand {
    padding: 3rem 4.25rem 2.1875rem;
  }

  .auth__story {
    margin-top: 4.5rem;
  }

  .authflow__stack {
    max-width: 27.8rem;
  }

  .auth__form {
    padding: 2.4375rem 4.125rem 1.5rem;
  }

  .auth__inner {
    max-width: 25.625rem;
  }
}

@media (max-width: 1100px) {
  .auth__brand {
    padding: 2.125rem 2rem 1.6875rem;
  }

  .auth__story {
    margin-top: 3rem;
  }

  .auth__form {
    padding: 1.625rem 2rem 1rem;
  }

  .authflow {
    min-height: 22.8rem;
    margin: 0 -0.8rem;
    padding: 2.125rem 0.4rem 3.5rem;
  }

  .authflow__body {
    padding: 1rem;
  }

  .authflow__title {
    font-size: 1.0625rem;
  }

  .authflow__toast {
    left: -1rem;
    padding: 0.75rem;
  }
}

@media (max-width: 800px) {
  .auth {
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1fr);
    padding: 10px;
  }

  .auth__brand {
    padding: 1.8rem 1.5rem 1.5rem;
  }

  .auth__form {
    padding: 1.375rem 1.5rem 0.875rem;
  }

  .auth__headline {
    font-size: 1.875rem;
  }

  .auth__heading {
    font-size: 1.875rem;
  }

  .auth__sub {
    font-size: 0.875rem;
  }

  .authflow__stages > i {
    margin-left: 4px;
    margin-right: 4px;
  }

  .authflow__toast {
    left: -0.5rem;
    width: 100%;
    gap: 0.5rem;
  }
}

/* Laptop screens are shorter than the panel's content (at 1280 by 800
   it ran 143px past the foot of the screen, 8 October 2026), so below
   960px of height the line at the foot goes and the card is drawn
   smaller, in steps. zoom rather than transform: scale, because zoom
   shrinks the space the card takes as well as the drawing. Measured
   with no page scroll at 1920x1080, 1440x1000, 1440x900, 1366x768,
   1280x800, 1280x680, 1024x768, 760x1000 and 660x900. */
@media (min-width: 641px) and (max-height: 960px) {
  .auth__story {
    margin-top: 2rem;
  }

  .authflow {
    min-height: 0;
    padding-top: 1rem;
    padding-bottom: 2.75rem;
    zoom: 0.82;
  }

  .auth__brandfoot {
    display: none;
  }

  .auth__inner {
    padding: 1.5rem 0;
  }
}

@media (min-width: 641px) and (max-height: 820px) {
  .authflow {
    zoom: 0.68;
  }
}

@media (min-width: 641px) and (max-height: 700px) {
  .authflow {
    zoom: 0.55;
  }

  .auth__form {
    padding-top: 1rem;
  }

  .auth__inner {
    padding: 0.5rem 0;
  }
}

@media (min-width: 641px) and (max-height: 580px) {
  .authflow {
    display: none;
  }
}

/* On a phone the navy panel is a short header: logo, eyebrow and
   headline, with a small card drawn in its corner; the form follows. A
   column of two blocks rather than a grid, because two auto rows in a
   min-height: 100% grid share out the spare height (see the landmine). */
@media (max-width: 640px) {
  .auth {
    display: flex;
    flex-direction: column;
    padding: 0;
    background: var(--surface);
  }

  /* min-height: the small card hangs from the header's bottom, so a
     shorter header lifts it. "A clearer day / starts here." is a line
     shorter than the headline before it, and the card rose over the end
     of "Your workday, connected" (8 October 2026). 14rem puts the card's
     top just under the eyebrow at every phone width. */
  .auth__brand {
    display: block;
    min-height: 14rem;
    padding: 1.4375rem 1.5625rem 1.5625rem;
    border-radius: 0;
  }

  .auth__brand .brandlogo__word {
    font-size: 1.375rem;
  }

  .auth__story {
    margin-top: 1.5rem;
  }

  .auth__eyebrow {
    margin-bottom: 0.75rem;
    letter-spacing: 0.08em;
    white-space: nowrap;
  }

  /* Clear of the small card in the corner (about 140px wide). */
  .auth__headline {
    max-width: calc(100% - 9rem);
    margin: 0;
    font-size: 1.5rem;
    line-height: 1.2;
    letter-spacing: -0.02em;
  }

  .auth__note,
  .auth__brandfoot,
  .authflow__card,
  .authflow__grid,
  .authflow__toast {
    display: none;
  }

  .authflow {
    position: absolute;
    right: 15px;
    bottom: 20px;
    z-index: 0;
    display: block;
    width: 130px;
    min-height: 0;
    margin: 0;
    padding: 0;
  }

  .authflow__mini {
    display: block;
    transform: rotate(-7deg);
  }

  .authflow__minicard {
    display: flex;
    align-items: center;
    gap: 0.5625rem;
    width: 130px;
    height: 58px;
    padding: 10px;
    background: var(--auth-mini);
    border: 1px solid var(--auth-mini-border);
    border-radius: 9px;
    box-shadow: var(--auth-toast-shadow);
  }

  .authflow__minilines {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: 6px;
  }

  .authflow__minilines span {
    width: 32px;
    height: 3px;
    border-radius: 2px;
    background: var(--auth-mini-bar);
  }

  .authflow__minilines span + span {
    width: 22px;
    opacity: 0.6;
  }

  .authflow__minicheck {
    display: grid;
    place-items: center;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--auth-card-blue);
    color: var(--auth-on-navy);
  }

  .authflow__minicheck .authflow__tick {
    width: 11px;
    height: 11px;
    stroke-width: 2.6;
  }

  .authflow__miniline {
    display: block;
    height: 12px;
    margin-left: 105px;
    border-left: 1px dashed var(--auth-mini-dash);
  }

  .authflow__minidone {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    margin-left: 26px;
    padding: 5px 7px;
    background: var(--auth-mini);
    border: 1px solid var(--auth-mini-border);
    border-radius: 5px;
    font-size: 0.6875rem;
    white-space: nowrap;
    color: var(--auth-mini-text);
  }

  .authflow__minidone .authflow__tick {
    width: 12px;
    height: 12px;
    color: var(--auth-navy-accent);
  }

  .auth__form {
    flex: 1;
    padding: 1.5rem 1.25rem 1.25rem;
  }

  .auth__inner {
    max-width: 26rem;
    margin: 0 auto;
    padding: 1.5rem 0 2rem;
  }

  .auth__padlock {
    display: none;
  }

  .auth__heading {
    font-size: 1.875rem;
  }

  .auth__foot {
    width: 100%;
    max-width: 26rem;
    margin: 0 auto;
  }
}

/* Too narrow for the headline and the small card side by side: at
   320px the card sat over "Every request,". */
@media (max-width: 359px) {
  .authflow {
    display: none;
  }

  .auth__headline {
    max-width: none;
  }
}

/* ====================== narrow screens ======================= */

@media (max-width: 860px) {
  .app {
    grid-template-columns: 1fr;
    /* Two auto rows in a grid with min-height:100% share the leftover height
       between them. With a full page of content that is invisible, because
       there is no leftover. The moment a screen is short or empty — which is
       exactly what every view looks like for the instant after you switch to
       it, before its rows arrive — the header was handed 360px of the 844px
       screen and its logo, navigation and account links drifted apart into
       the middle of it. The header takes the height it needs; the page takes
       the rest. */
    grid-template-rows: auto 1fr;
  }

  /* Stacked, the four bands of the rail — brand, organisation, navigation,
     account — took 215px, and with the page header under them a phone showed
     426px of chrome before a single row of content: more than half the
     screen. The brand and the account links share a row instead, and the
     organisation name goes, because the page header's eyebrow already says
     it on every screen. */
  .rail {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-areas:
      'brand account'
      'org   org'
      'nav   nav';
    align-items: center;
    padding: 0.375rem 0 0.25rem;
    border-right: none;
    border-bottom: 1px solid var(--border);
  }

  .rail__brand {
    grid-area: brand;
    padding: 0 0 0 1rem;
  }

  /* Kept in the layout, but only the "Support session" or "Platform staff"
     line can show: those change what the person is looking at, so they must
     survive. With no such line the row collapses to nothing. */
  .rail__org {
    grid-area: org;
    padding: 0 1rem;
    margin: 0;
    border-bottom: none;
  }

  .rail__org-name {
    display: none;
  }

  /* The navigation is a bar fixed along the bottom (see shellWith): four
     sections and More. It was a sideways-scrolling strip of nine under the
     logo, most of them off the screen (4 October 2026). */
  .rail__nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 120;
    flex-direction: row;
    align-items: stretch;
    gap: 0;
    padding: 0.25rem 0.25rem calc(0.25rem + env(safe-area-inset-bottom));
    background: var(--surface);
    border-top: 1px solid var(--border);
    box-shadow: 0 -4px 16px rgba(31, 32, 51, 0.06);
  }

  /* Platform staff outside an organisation have one section, Clients:
     a bar with one button switches to nothing. */
  .rail__nav:has(> .navitem:only-child) {
    display: none;
  }

  .rail__nav > .navitem {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
    min-height: 3.5rem;
    flex-direction: column;
    justify-content: center;
    gap: 0;
    padding: 0.375rem 0.125rem;
    font-size: 0.6875rem;
    text-align: center;
  }

  .rail__nav > .navitem .navitem__body {
    flex-direction: column;
    gap: 0.1875rem;
    min-width: 0;
    max-width: 100%;
  }

  .rail__nav > .navitem .navitem__body span {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .rail__nav > .navitem .navitem__icon {
    width: 22px;
    height: 22px;
  }

  .rail__nav > .navitem:has(.navitem__short) .navitem__label {
    display: none;
  }

  .rail__nav > .navitem .navitem__short {
    display: block;
  }

  /* A plain count ("Projects 4") has no room in the bar; one that needs
     attention sits on the icon's corner as a badge. */
  .rail__nav > .navitem .navitem__count {
    display: none;
  }

  .rail__nav > .navitem .navitem__count--flag {
    display: block;
    position: absolute;
    top: 0.25rem;
    left: calc(50% + 0.375rem);
    font-size: 0.6875rem;
    line-height: 1.3;
  }

  /* Something under More needs attention (unread chat, say): a dot on
     More. :has() follows setNavCount, which changes the class in place. */
  .rail__nav:has(.rail__more .navitem__count--flag) .navitem--more::after {
    content: '';
    position: absolute;
    top: 0.5rem;
    left: calc(50% + 0.5rem);
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent);
  }

  .rail__nav > .navitem--more {
    display: flex;
  }

  .rail__nav > .navitem--more[aria-expanded='true'] {
    background: var(--bg);
    color: var(--text);
  }

  /* The rest, in a panel above the bar while More is open. */
  .rail__more {
    display: none;
    position: fixed;
    left: 0.5rem;
    right: 0.5rem;
    bottom: calc(4.25rem + env(safe-area-inset-bottom));
    z-index: 121;
    flex-direction: column;
    gap: 0.125rem;
    padding: 0.5rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-card);
    box-shadow: var(--shadow-md);
  }

  .rail--more .rail__more {
    display: flex;
  }

  .rail__more .navitem {
    min-height: 2.75rem;
  }

  /* The page already ends 5.5rem above the foot of the screen on a phone
     (.content, below), which clears the 4rem bar; extra padding here only
     doubled the gap. Measured 4 October 2026: the last panel ends 43px
     above the bar. */

  /* The floating chat button sat over the content in the bottom corner;
     on a phone Chat is under More, with a dot when there is something
     unread. */
  /* Doubled class: the button's own rule comes later in the file and
     would otherwise win. */
  .chatfab.chatfab {
    display: none;
  }

  /* Everything else pinned to the foot of the screen sits above the bar:
     chat windows, and the bell and Create menus. Doubled classes for the
     same reason as above. */
  .dockrail.dockrail {
    bottom: calc(4.5rem + env(safe-area-inset-bottom));
  }

  .bellmenu.bellmenu,
  .createmenu.createmenu {
    bottom: calc(4.5rem + env(safe-area-inset-bottom));
    max-height: calc(100vh - 7rem);
  }

  .rail__foot {
    grid-area: account;
    justify-self: end;
    display: flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0 0.625rem 0 0;
  }

  /* The address is what "Account" opens; on a phone it is a long string
     competing with the brand for one row. */
  .rail__user {
    display: none;
  }

  /* 15px tall was not a target anyone could hit reliably. */
  .rail__foot .raillink {
    min-height: 40px;
    display: inline-flex;
    align-items: center;
    padding: 0 0.5rem;
  }

  .rail__foot .raillink + .raillink {
    margin: 0;
  }

  .topbar,
  .content {
    padding-left: 1rem;
    padding-right: 1rem;
  }

  .form {
    padding: 1.125rem;
  }

  .search {
    flex: 1 1 100%;
  }

  /* Rows of controls that were never told they may wrap. Each one was wider
     than the screen and, because the panel around it clips rather than
     scrolls, the controls past the edge could not be reached at all: the
     "Mine" filter on Requests and the view switches on Projects were simply
     gone on a phone. */
  .segmented {
    display: flex;
    flex-wrap: wrap;
  }

  .topbar__actions {
    flex-wrap: wrap;
  }

  /* Safari on iPhone zooms the page in whenever a focused field is set below
     16px, and does not zoom back out afterwards. Fields here ran from 12 to
     14px, so working through a form on a phone meant pinching the page back
     into place after every one of them. 16px only at phone widths; the
     denser sizes are kept on larger screens. */
  input,
  select,
  textarea,
  .field__input,
  .field__select,
  .field__textarea,
  .filters__select,
  .chatsearch__input,
  .chatsearch__scope {
    font-size: 1rem;
  }
}

/* ===================== page header ===================== */

.eyebrow {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.375rem;
}

.eyebrow::before {
  content: '';
  width: 18px;
  height: 2px;
  border-radius: 2px;
  background: var(--accent);
}

.pagelede {
  font-size: 0.9375rem;
  color: var(--muted);
  margin: 0.25rem 0 0;
  max-width: 60ch;
}

.sectionlabel {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin: 1.75rem 0 0.75rem;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
}

.sectionlabel__hint {
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--faint);
}

/* ===================== operational brief ===================== */

.brief {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) repeat(3, minmax(120px, 0.5fr));
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  margin-bottom: 1.5rem;
}

.brief__main {
  padding: 1.125rem 1.25rem;
  border-right: 1px solid var(--border-soft);
}

.brief__label {
  display: block;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.brief__headline {
  display: block;
  margin-top: 0.4375rem;
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.brief__note {
  margin: 0.3125rem 0 0;
  font-size: 0.8125rem;
  color: var(--muted);
}

.brief__item {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0.9375rem 1.0625rem;
  border-right: 1px solid var(--border-soft);
}

.brief__item:last-child {
  border-right: none;
}

.brief__value {
  margin-top: 0.3125rem;
  font-size: 1.25rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

.brief__item--flag .brief__value {
  color: var(--warn);
}

.brief__item--ok .brief__value {
  color: var(--ok);
}

@media (max-width: 900px) {
  .brief {
    grid-template-columns: 1fr 1fr;
  }
  .brief__main {
    grid-column: 1 / -1;
    border-right: none;
    border-bottom: 1px solid var(--border-soft);
  }
}

/* ===================== command palette ===================== */

.cmdback {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  align-items: start;
  justify-items: center;
  padding: 12vh 1rem 1.5rem;
  background: rgba(16, 24, 40, 0.4);
  backdrop-filter: blur(3px);
}

.cmd {
  width: min(680px, 100%);
  max-height: min(70vh, 640px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 24px 64px rgba(16, 24, 40, 0.24);
}

.cmd__search {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.625rem;
  padding: 0.75rem 0.875rem;
  border-bottom: 1px solid var(--border);
}

.cmd__input {
  height: 2.25rem;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--text);
  font-family: var(--sans);
  font-size: 1rem;
}

.cmd__esc {
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--bg);
  color: var(--muted);
  font-size: 0.6875rem;
  font-weight: 600;
  padding: 0.25rem 0.4375rem;
}

.cmd__body {
  overflow-y: auto;
  padding: 0.5rem;
}

.cmd__group {
  padding: 0.375rem 0.25rem 0.5rem;
}

.cmd__label {
  margin: 0 0 0.375rem 0.375rem;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.cmditem {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.625rem;
  width: 100%;
  padding: 0.5rem 0.5rem;
  border: 1px solid transparent;
  border-radius: var(--r-control);
  background: transparent;
  color: var(--text);
  font-family: var(--sans);
  text-align: left;
  cursor: pointer;
}

.cmditem:hover,
.cmditem--active {
  background: var(--accent-soft);
  border-color: transparent;
}

.cmditem__icon {
  display: grid;
  width: 28px;
  height: 28px;
  place-items: center;
  border-radius: var(--r-control);
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 700;
  font-size: 0.75rem;
}

.cmditem--active .cmditem__icon {
  background: var(--surface);
}

.cmditem__title {
  font-size: 0.875rem;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cmditem__sub {
  font-size: 0.75rem;
  color: var(--muted);
  margin-top: 0.0625rem;
}

.cmditem__kind {
  font-size: 0.6875rem;
  color: var(--faint);
  white-space: nowrap;
}

.cmd__empty {
  padding: 1.25rem;
  text-align: center;
  color: var(--muted);
  font-size: 0.875rem;
}

/* ===================== search trigger + create ===================== */

.searchtrigger {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 16rem;
  padding: 0.4375rem 0.6875rem;
  border: 1px solid var(--border);
  border-radius: var(--r-control);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  color: var(--muted);
  font-family: var(--sans);
  font-size: 0.875rem;
  cursor: pointer;
  text-align: left;
}

.searchtrigger:hover {
  border-color: var(--border-strong);
}

.searchtrigger__short {
  display: none;
}

.searchtrigger__hint {
  margin-left: auto;
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--faint);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.0625rem 0.3125rem;
}

.createwrap {
  position: relative;
}

.createmenu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 40;
  min-width: 15rem;
  padding: 0.3125rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-pop);
}

.createmenu button {
  display: block;
  width: 100%;
  padding: 0.5rem 0.625rem;
  border: 0;
  border-radius: var(--r-control);
  background: transparent;
  color: var(--text);
  font-family: var(--sans);
  font-size: 0.875rem;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}

.createmenu button:hover {
  background: var(--accent-soft);
  color: var(--accent-dark);
}

@media (max-width: 860px) {
  .searchtrigger {
    width: 100%;
  }
}

/* ===================== view bar ===================== */

.viewbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1.125rem;
  border-bottom: 1px solid var(--border-soft);
  background: var(--surface-2);
}

.viewbar__left,
.viewbar__right {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  align-items: center;
}

.scopelabel {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ===================== month calendar ===================== */

.monthgrid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  border-top: 1px solid var(--border-soft);
}

.monthhead {
  padding: 0.4375rem 0.5rem;
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--muted);
  background: var(--surface-2);
  border-right: 1px solid var(--border-soft);
  border-bottom: 1px solid var(--border-soft);
}

.monthhead:nth-child(7n) {
  border-right: none;
}

.daycell {
  min-height: 7rem;
  padding: 0.375rem;
  border-right: 1px solid var(--border-soft);
  border-bottom: 1px solid var(--border-soft);
}

.daycell:nth-child(7n) {
  border-right: none;
}

.daycell--out {
  background: var(--surface-2);
}

.daycell--today {
  background: var(--accent-soft);
}

.daycell__num {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--text-2);
  margin-bottom: 0.25rem;
}

.daycell--out .daycell__num {
  color: var(--faint);
}

.daycell--today .daycell__num {
  color: var(--accent-dark);
}

/* Late work from before the grid's first day (see monthCalendar). */
.monthlate {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem 0.5rem;
  padding: 0.75rem 1.125rem;
  border-top: 1px solid var(--border-soft);
}

.monthlate__label {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--warn);
}

/* A chip is a full-width block inside a day; here they sit in a row. */
.monthlate .chip {
  width: auto;
  margin: 0;
  max-width: 100%;
}

/* The full date ("Wed, Sep 30") is for the phone list; the grid's column
   headings already say the weekday. Likewise the empty-month line. */
.daycell__date,
.monthgrid__none {
  display: none;
}

.monthgrid__none {
  margin: 0;
  padding: 1rem 1.125rem;
  font-size: 0.875rem;
  color: var(--muted);
}

/* On a phone the month is a list of the days with something on them (see
   monthCalendar). Days from the neighbouring months are kept when they
   have something: they were hidden outright, and with them a project
   overdue since the end of last month. */
@media (max-width: 860px) {
  .monthgrid {
    grid-template-columns: 1fr;
  }
  .monthhead {
    display: none;
  }
  .daycell {
    min-height: 0;
    border-right: none;
    padding: 0.625rem 0.75rem;
  }
  .daycell--empty {
    display: none;
  }
  .daycell__day {
    display: none;
  }
  .daycell__date {
    display: inline;
  }
  .daycell__num {
    font-size: 0.8125rem;
    margin-bottom: 0.375rem;
  }
  .monthgrid__none {
    display: block;
  }
}

/* ===================== portfolio overview ===================== */

.healthrow {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  border-bottom: 1px solid var(--border-soft);
}

.healthcell {
  padding: 0.875rem 1.125rem;
  border-right: 1px solid var(--border-soft);
}

.healthcell:last-child {
  border-right: none;
}

.healthcell__label {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
}

.healthcell__value {
  margin-top: 0.3125rem;
  font-size: 1.375rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

.healthcell--flag .healthcell__value {
  color: var(--warn);
}

/* A figure you can open. Rendered as a button, so it needs the button
   defaults stripped back to what the div looked like, and it needs to say
   it is pressable — otherwise it is a number that happens to respond. */
.healthcell--open {
  display: block;
  width: 100%;
  text-align: left;
  font-family: var(--sans);
  background: none;
  border: none;
  border-right: 1px solid var(--border-soft);
  cursor: pointer;
  transition: background 0.12s ease;
}

.healthcell--open:hover {
  background: var(--surface-2);
}

.healthcell--open .healthcell__label::after {
  content: ' \203a';
  color: var(--faint);
}

.healthcell--on {
  background: var(--accent-soft);
}

.healthcell--on .healthcell__label {
  color: var(--accent-dark);
}

.healthdrawer {
  padding: 0.875rem 1.125rem;
  border-bottom: 1px solid var(--border-soft);
  background: var(--surface-2);
}

.healthdrawer .sectionlabel {
  margin-bottom: 0.5rem;
}

/* The Projects page's Overview: headings in line with the rows under
   them. The lists are padded 1.25rem; the headings sat flush against the
   panel's edge (the founder's screenshot, 13 October 2026). */
.overviewlists {
  padding-bottom: 1.25rem;
}

.overviewlists > .sectionlabel,
.overviewlists > .linkbutton {
  margin-left: 1.25rem;
  margin-right: 1.25rem;
}

.unscheduled {
  padding: 0.75rem 1.125rem;
  border-top: 1px solid var(--border-soft);
  background: var(--surface-2);
  font-size: 0.8125rem;
  color: var(--muted);
}

/* ===================== record header ===================== */

.rechead {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-sm);
  padding: 1.125rem 1.25rem;
  margin-bottom: 1.25rem;
  display: grid;
  grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
  gap: 1.25rem;
  align-items: start;
}

.rechead__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  align-items: center;
}

/* The subject over the header, in the inbox pane only (see
   fillRequestDetail). */
.rechead__title {
  display: none;
  grid-column: 1 / -1;
  margin: 0;
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.35;
  overflow-wrap: anywhere;
}

.reqdetail .rechead__title {
  display: block;
}

/* Pinned (laptop only, as the pinning is), the title takes the place of
   the reference line, on one line, so the header barely changes height
   as it pins. */
/* Pinned (laptop only), the title shows over the reference line, in its
   space, so the header keeps exactly its height (setStuck): any change
   in height made the page bounce. In the inbox the title is already
   shown, so nothing changes there. */
@media (min-width: 861px) {
  .rechead__ref {
    position: relative;
  }

  .rechead--stuck .rechead__ref[data-title] {
    color: transparent;
  }

  .rechead--stuck .rechead__ref[data-title]::after {
    content: attr(data-title);
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text);
    font-size: 0.9375rem;
    font-weight: 600;
    letter-spacing: normal;
    text-transform: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .reqdetail .rechead--stuck .rechead__ref[data-title] {
    color: var(--muted);
  }

  .reqdetail .rechead--stuck .rechead__ref[data-title]::after {
    content: none;
  }
}

/* The summary row and tags: a card of their own under the header that
   reads as part of it, out of the pinned header so it keeps one height. */
.rechead:has(+ .recsummary) {
  margin-bottom: 0;
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

.recsummary {
  display: grid;
  gap: 0.75rem;
  margin-bottom: 1.25rem;
  padding: 0.875rem 1.25rem 1.125rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: 1px solid var(--border-soft);
  border-radius: 0 0 var(--r-card) var(--r-card);
  box-shadow: var(--shadow-sm);
}

/* On its own, not under a record header (a client in the control panel). */
.recsummary.recsummary--alone {
  border-radius: var(--r-card);
}

.recsummary .recfacts {
  padding-top: 0;
  border-top: none;
}

/* Pinned, the header is a card on its own again (paint only). */
.rechead.rechead--stuck {
  border-radius: var(--r-card);
}

/* On a laptop a record's header, with its actions, stays at the top while
   the page scrolls: Edit, Mark resolved and the rest were a long scroll
   back up from the conversation (4 October 2026). While pinned, a second
   shadow in the page colour fills the gap above the header so rows do
   not show through it. Not on a phone, where the header is two rows of buttons and
   would take a third of the screen. */
@media (min-width: 861px) {
  .rechead {
    position: sticky;
    top: 0.75rem;
    z-index: 30;
  }

  /* Only while pinned: unpinned, the strip reached 1.75rem above the
     header and covered the inbox's "3 requests" count. */
  .rechead.rechead--stuck {
    box-shadow: var(--shadow-sm), 0 -1rem 0 0.75rem var(--bg);
  }
}

.rechead__ref {
  display: block;
  width: 100%;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.375rem;
}

.rechead__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-content: start;
}

/* ============ record pages (9 October 2026, enterprise) ============
   The summary row across the header, the stage track under it, and the
   tabs over the main column. */
.recfacts {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
  gap: 0.75rem 1.25rem;
  margin: 0;
  padding-top: 0.875rem;
  border-top: 1px solid var(--border-soft);
}

.recfacts__item {
  min-width: 0;
}

.recfacts__label {
  font-size: 0.75rem;
  color: var(--muted);
  margin-bottom: 0.25rem;
}

.recfacts__value {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.375rem;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text);
  overflow-wrap: anywhere;
}

.recfacts__stack {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
}

.recfacts__person {
  display: inline-flex;
  align-items: center;
  gap: 0.4375rem;
  min-width: 0;
}

.recfacts__note {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--accent-dark);
}

.recfacts__note--late {
  color: var(--warn);
}

.recfacts__note--paused {
  color: var(--muted);
}

/* Two to a row on a phone: one column made six facts 260px tall at
   375 (two of 152px did not quite fit in 305). */
@media (max-width: 620px) {
  .recfacts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.75rem 1rem;
  }
}


/* Dots joined by a line: ticked (green) before the current stage, the
   current one ringed in indigo, the rest empty. From the sign-in page's
   illustration. */
.stagetrack {
  display: flex;
  align-items: flex-start;
  margin: 0 0 1.25rem;
  padding: 1rem 0.5rem 0.875rem;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-sm);
  overflow-x: auto;
}

.stagetrack__step {
  position: relative;
  flex: 1 1 0;
  min-width: 5.5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4375rem;
  text-align: center;
}

.stagetrack__step::before {
  content: '';
  position: absolute;
  top: 0.8125rem;
  left: -50%;
  width: 100%;
  height: 2px;
  background: var(--track-2);
}

.stagetrack__step:first-child::before {
  display: none;
}

.stagetrack__step--done::before,
.stagetrack__step--now::before {
  background: var(--ok);
}

.stagetrack__dot {
  position: relative;
  z-index: 1;
  width: 1.75rem;
  height: 1.75rem;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--border-strong);
  border-radius: 50%;
  background: var(--surface);
}

.stagetrack__dot svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.stagetrack__step--done .stagetrack__dot {
  border-color: var(--ok);
  background: var(--ok);
  color: var(--surface);
}

.stagetrack__step--now .stagetrack__dot {
  border-color: var(--accent-solid);
  background: var(--accent-solid);
  box-shadow: 0 0 0 4px var(--accent-soft);
}

.stagetrack__step--now .stagetrack__dot::after {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #ffffff;
}

/* Lost or cancelled: grey with a cross. The line into it stays grey, and
   so does the one into a won stage it skipped. */
.stagetrack__step--lost .stagetrack__dot {
  border-color: var(--muted);
  background: var(--muted);
  color: var(--surface);
}

.stagetrack__step--lost .stagetrack__name {
  color: var(--text-2);
}

.stagetrack__name {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text-2);
  padding: 0 0.25rem;
}

.stagetrack__step--done .stagetrack__name {
  color: var(--ok);
}

.stagetrack__step--now .stagetrack__name {
  color: var(--accent-dark);
}

.stagetrack__note {
  font-size: 0.75rem;
  color: var(--muted);
}

.rectabs {
  display: flex;
  gap: 0.25rem;
  margin-bottom: 1rem;
  padding: 0.25rem;
  border-radius: var(--r-pill);
  background: var(--neutral-soft);
  overflow-x: auto;
  scrollbar-width: thin;
}

.rectabs__tab {
  flex: none;
  min-height: 2.25rem;
  padding: 0 1rem;
  border: none;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--text-2);
  font-family: var(--sans);
  font-size: 0.875rem;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
}

.rectabs__tab:hover {
  color: var(--text);
}

.rectabs__tab--on,
.rectabs__tab--on:hover {
  background: var(--surface);
  color: var(--text);
  font-weight: 600;
  box-shadow: var(--shadow-sm);
}

.panel[hidden] {
  display: none;
}

/* A labelled status list among the header's buttons (task page), the
   same height as a ghost button. */
.statuspick {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-width: 0;
}

.statuspick__label {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--muted);
}

.statuspick__select {
  font-family: var(--sans);
  font-size: 0.8125rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-control);
  padding: 0.3125rem 0.5rem;
  min-width: 0;
  /* The height of the ghost buttons beside it (32px). */
  min-height: 2rem;
}

.statuspick__select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* 16px on phones: iPhone Safari zooms in on a smaller field and stays. */
@media (max-width: 860px) {
  .statuspick__select {
    font-size: 1rem;
  }
}

.progress {
  width: 100%;
  margin-top: 0.75rem;
}

.progress__head {
  display: flex;
  justify-content: space-between;
  font-size: 0.75rem;
  color: var(--muted);
  margin-bottom: 0.25rem;
}

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

.progress__fill {
  height: 100%;
  border-radius: 999px;
  background: var(--accent);
}

/* 1100 rather than 860: on a 1024px laptop the request list takes most of the
   width and leaves the detail pane about 326px, which squeezed the actions
   column of this header to 24px and left the "Edit request" button hanging
   out of it. The header is narrow long before the screen is. */
@media (max-width: 1100px) {
  .rechead {
    grid-template-columns: 1fr;
  }
}

/* ===================== record two-column body ===================== */

.reclayout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 22rem;
  gap: 1.25rem;
  align-items: start;
}

@media (max-width: 1100px) {
  /* minmax(0, …) rather than a bare 1fr: a 1fr track's minimum is auto, so it
     grows to its widest content instead of to the space available. Every
     record page built on this layout was 409px wide inside a 358px column on
     a phone, and had been all along — the earlier audit only ever opened a
     request, which uses a layout of its own. */
  .reclayout {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ===================== read-only field tiles ===================== */

/* Two fixed columns meant a full-width field — a description, a subject —
   could not sit beside a narrow one, so it dropped to the next row and left
   the cell next to it empty. Two of the five rows on a project page were half
   blank. Auto-fit gives a wide panel three or four columns instead of two,
   and dense backfills the gaps a wide field leaves behind. Every tile carries
   its own label, so filling a gap out of order still reads correctly. */
.tiles {
  display: grid;
  /* 11rem, not 13: a record's detail panel sits in a two-column layout of its
     own and is only about 412px wide at 1440, where a 13rem minimum fell just
     short of fitting two tracks and gave one column — worse than the two it
     replaced. At 11rem that panel keeps two, and a full-width one gets four. */
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  grid-auto-flow: dense;
  gap: 0.25rem 1.5rem;
  padding: 1.125rem;
}

/* A label and its value, divided by a line rather than each in its own
   grey box: the details were boxes inside a panel inside the page
   (4 October 2026). */
.tile {
  background: none;
  border: none;
  border-top: 1px solid var(--border-soft);
  border-radius: 0;
  padding: 0.625rem 0 0.375rem;
  min-width: 0;
}

.tile--wide {
  grid-column: 1 / -1;
}

/* Sentence case, not small capitals: the labels are quiet now and the
   values carry the weight. */
.tile__label {
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--muted);
  margin-bottom: 0.125rem;
}

/* The address under a link in a details tile (the video call's URL), so
   people can see where it goes; long ones wrap rather than widen the
   tile. */
.tile__sub {
  margin-top: 0.125rem;
  font-size: 0.75rem;
  color: var(--muted);
  overflow-wrap: anywhere;
}

.tile__value {
  font-size: 0.875rem;
  font-weight: 500;
  white-space: pre-wrap;
  word-break: break-word;
}

.tile__link {
  color: var(--accent);
  text-decoration: none;
}

.tile__link:hover {
  text-decoration: underline;
}

@media (max-width: 700px) {
  .tiles {
    grid-template-columns: 1fr;
  }
}

/* ===================== assignment block ===================== */

.assignbox {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.625rem 0.75rem;
  background: var(--accent-soft);
  border-radius: var(--r-control);
  margin-bottom: 0.75rem;
}

.assignbox__label {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--accent-dark);
}

.assignbox__name {
  font-size: 0.875rem;
  font-weight: 600;
}

.factlist {
  padding: 0 1.125rem 1.125rem;
}

.fact {
  padding: 0.625rem 0;
  border-top: 1px solid var(--border-soft);
}

.fact__label {
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--muted);
}

.fact__value {
  font-size: 0.875rem;
  font-weight: 500;
  margin-top: 0.1875rem;
}

/* ===================== activity timeline ===================== */

.trail {
  padding: 1rem 1.125rem;
}

.trailitem {
  position: relative;
  padding: 0 0 0.875rem 1.125rem;
  border-left: 2px solid var(--border-soft);
}

.trailitem:last-child {
  border-left-color: transparent;
  padding-bottom: 0;
}

.trailitem::before {
  content: '';
  position: absolute;
  left: -6px;
  top: 3px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid var(--surface);
  box-shadow: 0 0 0 1px var(--border);
}

.trailitem__text {
  font-size: 0.875rem;
  color: var(--text-2);
}

.trailitem__when {
  font-size: 0.75rem;
  color: var(--faint);
  margin-top: 0.125rem;
}

/* ===== card treatment for the remaining list types ===== */

.slot,
.comment,
.event,
.file,
.client,
.attendee {
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  margin: 0 1.25rem 0.5rem;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.slot:hover,
.file:hover,
.client:hover {
  background: var(--surface);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-sm);
}

.slot,
.file,
.client,
.comment,
.event {
  border-bottom: 1px solid var(--border-soft);
}

.dayhead {
  background: transparent;
  border-bottom: none;
  padding: 0.875rem 1.25rem 0.375rem;
}

.offices,
.records {
  padding: 0.5rem 1.25rem 1.25rem;
}

.offices__row {
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  padding: 0.8125rem 0.9375rem;
  margin-bottom: 0.5rem;
}

.offices__row:last-child {
  margin-bottom: 0;
}

/* Panels that hold a grid or chart need their own breathing room */
.bars,
.trail,
.tiles,
.factlist,
.skeleton {
  padding-left: 1.25rem;
  padding-right: 1.25rem;
}

.filters,
.viewbar,
.inline-form,
.composer {
  background: transparent;
  border-top: none;
  border-bottom: none;
  padding-left: 1.25rem;
  padding-right: 1.25rem;
}

.inline-form,
.composer {
  border-top: 1px solid var(--border-soft);
  padding-top: 1rem;
  margin-top: 0.25rem;
}

/* Empty states read as a placeholder card, matching the reference design */
.empty {
  margin: 0 1.25rem 1.25rem;
  padding: 1.5rem 1.125rem;
  text-align: center;
  border: 1px dashed var(--border-dashed);
  border-radius: 10px;
  background: var(--surface-2);
}

.emptystate {
  margin: 0 1.25rem 1.25rem;
  border: 1px dashed var(--border-dashed);
  border-radius: 10px;
  background: var(--surface-2);
}

/* Metric cards get the softer radius too */
.figure,
.card,
.column {
  border-radius: 11px;
}

.brief,
.metastrip,
.attention,
.calm,
.form,
.rechead {
  border-radius: var(--r-card);
}

.chosen {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  align-items: center;
  margin-top: 0.5rem;
}

.chosen__label {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
}

/* ===== threaded comments ===== */

.thread {
  margin: 0 1.25rem 0.5rem;
  border: 1px solid var(--border-soft);
  border-radius: 11px;
  background: var(--surface-2);
  overflow: hidden;
}

.thread .comment {
  margin: 0;
  border: none;
  border-radius: 0;
  background: transparent;
  border-bottom: 1px solid var(--border-soft);
}

.thread .comment:last-child {
  border-bottom: none;
}

.comment--reply {
  padding-left: 3rem;
  background: var(--surface) !important;
}

.replybar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4375rem 0.625rem;
  margin-bottom: 0.5rem;
  border-radius: var(--r-control);
  background: var(--accent-soft);
  color: var(--accent-dark);
  font-size: 0.75rem;
  font-weight: 600;
}

@media (max-width: 700px) {
  .comment--reply {
    padding-left: 1.5rem;
  }
}

/* Avatar background now set per-person in JS; keep only the text/shape rule */
.avatar {
  color: #ffffff;
  font-weight: 600;
}

/* ===== checkbox-style completion toggle, from the source task list ===== */

.checkbox {
  width: 17px;
  height: 17px;
  border-radius: 5px;
  border: 2px solid var(--border);
  background: transparent;
  flex: 0 0 17px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.checkbox--done {
  background: var(--ok-soft);
  border-color: #10B981;
}

.checkbox--done svg {
  stroke: #059669;
}

.checkbox:hover {
  border-color: var(--accent);
}

/* ===================== dashboard stat cards ===================== */

.statgrid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
  margin-bottom: 1.75rem;
}

@media (max-width: 900px) {
  .statgrid {
    grid-template-columns: repeat(2, 1fr);
  }
}

.statcard {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-sm);
  padding: 1.25rem;
  cursor: pointer;
  text-align: left;
  width: 100%;
  font-family: var(--sans);
}

.statcard__icon {
  width: 40px;
  height: 40px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0.75rem;
}

.statcard__icon svg {
  width: 18px;
  height: 18px;
}

.statcard__value {
  font-size: 1.75rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--text);
}

.statcard__label {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--muted);
  margin-top: 0.25rem;
}

.statcard__change {
  font-size: 0.75rem;
  font-weight: 600;
  margin-top: 0.375rem;
}

/* ===================== dashboard split ratios ===================== */

.split--dash {
  grid-template-columns: minmax(0, 1fr) 22.5rem;
}

.split--appt {
  grid-template-columns: minmax(0, 1fr) 21.25rem;
}

@media (max-width: 980px) {
  .split--dash,
  .split--appt {
    grid-template-columns: 1fr;
  }
}

/* ===================== agenda list (schedule items) ===================== */

/* The overview Schedule's two parts, Today and Coming up for you. */
.schedsep {
  padding: 0.25rem 1.25rem 0.375rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
}

.agendalist {
  padding: 0.5rem 1.125rem 1.125rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.agendaitem {
  display: flex;
  gap: 0.875rem;
  align-items: center;
}

.agendaitem__time {
  width: 3.75rem;
  flex: 0 0 3.75rem;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--faint);
}

.agendaitem__box {
  flex: 1;
  min-width: 0;
  background: var(--bg);
  border-radius: var(--r-control);
  padding: 0.625rem 0.875rem;
  border-left: 3px solid var(--accent);
}

.agendaitem__title {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text);
}

.agendaitem__sub {
  font-size: 0.6875rem;
  color: var(--muted);
  margin-top: 0.125rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Day-number list item, used for "Upcoming this week" style panels */
.dayitem {
  display: flex;
  gap: 0.75rem;
  align-items: center;
}

.dnum {
  width: 2.5rem;
  flex: 0 0 2.5rem;
  text-align: center;
}

.dnum__wd {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--faint);
}

.dnum__d {
  font-size: 1rem;
  font-weight: 800;
  line-height: 1.2;
  color: var(--text);
}

/* ===================== promo / callout card ===================== */

.callout {
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-card);
  padding: 1.375rem;
}

.callout__title {
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--accent-dark);
  margin-bottom: 0.5rem;
}

.callout__text {
  font-size: 0.8125rem;
  color: var(--accent-dark);
  line-height: 1.55;
  margin-bottom: 1rem;
}

.callout__count {
  font-size: 1.5rem;
  font-weight: 800;
  color: var(--accent);
  margin-bottom: 0.25rem;
}

/* ===================== project card grid ===================== */

.projectgrid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.875rem;
  margin-bottom: 1.5rem;
}

@media (max-width: 980px) {
  .projectgrid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 620px) {
  .projectgrid {
    grid-template-columns: 1fr;
  }
}

.projectcard {
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-sm);
  padding: 1rem 1.125rem;
  cursor: pointer;
  text-align: left;
  width: 100%;
  font-family: var(--sans);
}

.projectcard--active {
  border-color: var(--accent);
}

.projectcard__head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 0.75rem;
}

.projectcard__dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  margin-top: 0.1875rem;
}

.projectcard__name {
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 0.5rem;
}

.projectcard__meta {
  display: flex;
  justify-content: space-between;
  margin-top: 0.625rem;
  font-size: 0.6875rem;
  color: var(--muted);
}

.projectcard__footer {
  margin-top: 0.75rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.projectcard__owner {
  display: flex;
  align-items: center;
  gap: 0.375rem;
}

.projectcard__owner .avatar {
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
  font-size: 0.5625rem;
}

.projectcard__owner span {
  font-size: 0.6875rem;
  color: var(--muted);
}

/* ===================== single-project task panel ===================== */

.taskpanelhead {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.taskpanelhead__title {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  font-size: 0.9375rem;
  font-weight: 700;
  min-width: 0;
}

.taskpanelhead__sub {
  font-size: 0.75rem;
  color: var(--faint);
  font-weight: 400;
}

.tasklisthead {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 6.5rem 5.5rem 6rem 8rem;
  gap: 0.75rem;
  padding: 0.625rem 1.25rem;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--faint);
  border-bottom: 1px solid var(--border-soft);
}

.taskrow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 6.5rem 5.5rem 6rem 8rem;
  gap: 0.75rem;
  align-items: center;
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.taskrow:hover {
  background: var(--surface-2);
}

.taskrow:last-child {
  border-bottom: none;
}

.taskrow__title {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  min-width: 0;
}

.taskrow__title span {
  font-size: 0.8125rem;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 900px) {
  .tasklisthead {
    display: none;
  }
  .taskrow {
    grid-template-columns: minmax(0, 1fr) auto;
    row-gap: 0.375rem;
  }
  .taskrow > :nth-child(n + 3) {
    display: none;
  }
}

/* ===================== mini month calendar ===================== */

.minical {
  padding: 1.125rem 1.25rem 1.25rem;
}

.minical__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.875rem;
}

.minical__title {
  font-size: 0.875rem;
  font-weight: 700;
}

.minical__nav {
  display: flex;
  gap: 0.25rem;
}

.minical__navbtn {
  background: var(--bg);
  border: none;
  border-radius: 8px;
  width: 30px;
  height: 30px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
}

.minical__navbtn:hover {
  background: var(--border-soft);
}

.minical__grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.375rem;
}

.minical__dow {
  text-align: center;
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--faint);
  padding: 0.25rem 0;
}

.minical__day {
  position: relative;
  text-align: center;
  padding: 0.4375rem 0.25rem;
  border-radius: 8px;
  border: none;
  cursor: pointer;
  font-size: 0.8125rem;
  background: transparent;
  color: var(--text);
  font-family: var(--sans);
}

.minical__day--busy {
  background: var(--accent-soft);
}

.minical__day--today {
  color: var(--accent);
  font-weight: 700;
}

.minical__day--selected {
  background: var(--accent-solid);
  color: #fff;
  font-weight: 700;
}

.minical__dot {
  position: absolute;
  bottom: 3px;
  left: 50%;
  transform: translateX(-50%);
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent);
}

.minical__day--selected .minical__dot {
  background: #fff;
}

/* ===================== day-event list (appointments detail) ===================== */

.dayevent {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.dayevent:last-child {
  border-bottom: none;
}

.dayevent:hover {
  background: var(--surface-2);
}

.dayevent__bar {
  width: 4px;
  border-radius: 4px;
  align-self: stretch;
  flex-shrink: 0;
  min-height: 3.125rem;
}

.dayevent__head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0.5rem;
  margin-bottom: 0.375rem;
}

.dayevent__title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 0.1875rem;
}

.dayevent__time {
  font-size: 0.75rem;
  color: var(--muted);
}

.dayevent__attendees {
  display: flex;
  align-items: center;
  margin-top: 0.25rem;
}

.dayevent__attendees .avatar {
  width: 24px;
  height: 24px;
  flex: 0 0 24px;
  font-size: 0.625rem;
  border: 2px solid var(--surface);
  margin-left: -6px;
}

.dayevent__attendees .avatar:first-child {
  margin-left: 0;
}

.dayevent__names {
  font-size: 0.75rem;
  color: var(--muted);
  margin-left: 0.625rem;
}

/* ===================== requests master-detail split ===================== */

.split--req {
  /* Grows a little with the window instead of staying pinned at 23.75rem, and
     stops at 30rem so it never becomes the bigger half. The floor is the old
     fixed width, not something smaller: a first attempt at 21rem made the
     list narrower at 1440 than it had been, which is the opposite of the
     point. */
  grid-template-columns: clamp(23.75rem, 24%, 30rem) minmax(0, 1fr);
  align-items: stretch;
  /* Without a cap of its own, running the page wide would stretch a single
     request across a 2560px monitor. */
  max-width: 1760px;
}

@media (max-width: 980px) {
  .split--req {
    grid-template-columns: 1fr;
  }
}

/* The inbox shows a whole request beside the list, and the request page's
   two columns (a fixed 22rem side column) were decided by the window's
   width. At 1280px the pane is about 580px, so the details and the
   conversation, the part people read, got 210px and Assignment got 352px.
   Measured by the pane instead: below 50rem it is one column, in the same
   order as on a phone. The request page itself is not inside this
   container, so it is unaffected. */
.reqdetail {
  container: reqdetail / inline-size;
  min-width: 0;
}

@container reqdetail (max-width: 50rem) {
  .reclayout {
    grid-template-columns: minmax(0, 1fr);
  }
}

.reqlist {
  max-height: 37rem;
  overflow-y: auto;
}

.listmore {
  display: flex;
  justify-content: center;
  padding: 0.75rem 1.125rem 1rem;
}

.reqrow {
  display: block;
  width: 100%;
  text-align: left;
  font-family: var(--sans);
  padding: 0.875rem 1rem;
  border-bottom: 1px solid var(--border-soft);
  border-left: 3px solid transparent;
  background: var(--surface);
  cursor: pointer;
}

.reqrow:hover {
  background: var(--surface-2);
}

.reqrow--active {
  background: var(--surface-2);
  border-left-color: var(--accent);
}

.reqrow__top {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.375rem;
}

.reqrow__title {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text);
  line-height: 1.4;
}

.reqrow__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
}

.reqrow__meta {
  font-size: 0.6875rem;
  color: var(--faint);
}

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

.reqdetail {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.reqdetail__head {
  padding: 1.25rem 1.5rem;
  border-bottom: 1px solid var(--border-soft);
}

.reqdetail__badges {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 0.875rem;
}

.reqdetail__title {
  font-size: 1.125rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  margin-bottom: 0.625rem;
}

.reqdetail__who {
  display: flex;
  align-items: center;
  gap: 0.625rem;
}

.reqdetail__who span:first-of-type {
  font-size: 0.8125rem;
  font-weight: 600;
}

.reqdetail__who span.reqdetail__from {
  font-size: 0.8125rem;
  color: var(--muted);
}

.reqdetail__when {
  margin-left: auto;
  font-size: 0.75rem;
  color: var(--faint);
}

.reqdetail__body {
  padding: 1.375rem 1.5rem;
  flex: 1;
}

.reqdetail__text {
  font-size: 0.875rem;
  color: var(--text-2);
  line-height: 1.7;
  margin-bottom: 1.25rem;
  white-space: pre-wrap;
}

.reqdetail__actions {
  display: flex;
  gap: 0.625rem;
  margin-top: 1.5rem;
}

.reqdetail__actions .button,
.reqdetail__actions .button--ghost {
  flex: 1;
  text-align: center;
}

.reqdetail__empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  min-height: 20rem;
  color: var(--faint);
  font-size: 0.875rem;
}

.tag {
  font-size: 0.75rem;
  font-weight: 500;
  background: var(--bg);
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  padding: 0.25rem 0.75rem;
}

/* ===================== task dependencies ===================== */

.depitem {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.depitem:last-of-type {
  border-bottom: none;
}

.depitem__link {
  flex: 1;
  min-width: 0;
  text-align: left;
  font-family: var(--sans);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text);
  background: none;
  border: none;
  cursor: pointer;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.depitem__link:hover {
  color: var(--accent);
}

.deplabel {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--faint);
  padding: 0.75rem 1.25rem 0.25rem;
}

.deplabel:first-child {
  padding-top: 1rem;
}

.blockednotice {
  margin: 0 1.25rem 1rem;
  padding: 0.625rem 0.875rem;
  font-size: 0.8125rem;
  color: var(--warn);
  background: var(--warn-soft);
  border-left: 3px solid var(--warn);
  border-radius: var(--r-control);
}

/* ===================== project team ===================== */

.teamrow {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.teamrow:last-of-type {
  border-bottom: none;
}

.teamrow__name {
  flex: 1;
  min-width: 0;
  font-size: 0.8125rem;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.teamrow__lead {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
}

.teamrow__leadbtn {
  font-family: var(--sans);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
  background: none;
  border: none;
  padding: 0.25rem 0.375rem;
  cursor: pointer;
}

.teamrow__leadbtn:hover {
  text-decoration: underline;
}

/* ===================== CRM ===================== */

.crmrow {
  display: grid;
  grid-template-columns: 2.5rem minmax(0, 1fr) 10rem 8rem;
  gap: 0.75rem;
  align-items: center;
  padding: 0.8125rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.crmrow:last-child {
  border-bottom: none;
}

.crmrow:hover {
  background: var(--surface-2);
}

@media (max-width: 900px) {
  .crmrow {
    grid-template-columns: 2.5rem minmax(0, 1fr);
  }
  .crmrow > :nth-child(n + 3) {
    display: none;
  }
}

.pickresult {
  display: block;
  width: 100%;
  text-align: left;
  font-family: var(--sans);
  font-size: 0.8125rem;
  padding: 0.5rem 0.75rem;
  border: none;
  background: var(--surface);
  border-bottom: 1px solid var(--border-soft);
  cursor: pointer;
}

.pickresult:hover {
  background: var(--surface-2);
}

/* "Also reported by" under a request's details: the other people who
   reported the same thing. A divided list like the details above it, no
   boxes. */
.reporters {
  margin: 0 1.125rem 1.125rem;
  padding-top: 0.875rem;
  border-top: 1px solid var(--border);
  min-width: 0;
}

.reporters__title {
  margin: 0 0 0.5rem;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--muted);
}

.reporters__list {
  list-style: none;
  margin: 0 0 0.75rem;
  padding: 0;
}

.reporter {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem 0.75rem;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--border-soft);
  min-width: 0;
}

.reporter:last-child {
  border-bottom: none;
}

/* Name and how/when on one line, wrapping on a phone; the Remove button
   sits at the end of the first line. */
.reporter__top {
  flex: 1 1 12rem;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0 0.5rem;
  align-items: baseline;
}

.reporter__name {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text);
  overflow-wrap: anywhere;
}

.reporter__meta {
  font-size: 0.75rem;
  color: var(--muted);
}

.reporter .button--ghost {
  order: 2;
}

.reporter__reach,
.reporter__note {
  order: 3;
  flex: 1 1 100%;
  min-width: 0;
  margin: 0;
  font-size: 0.8125rem;
  overflow-wrap: anywhere;
}

.reporter__note {
  color: var(--text-2);
  white-space: pre-wrap;
}

.reporters__none {
  margin: 0 0 0.75rem;
  font-size: 0.8125rem;
  color: var(--muted);
}

.reporters__form {
  margin-top: 0.75rem;
}

.similar__add {
  margin-left: auto;
}

/* An appointment's "Linked to" panel: the task and request it is about,
   under its contact (10 October 2026). */
.linked__item + .linked__item,
.linkedcontact + .linked__item {
  margin-top: 0.875rem;
}

.linked__item .row__link {
  overflow-wrap: anywhere;
}

.linkedcontact {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.625rem 0.75rem;
  background: var(--surface-2);
  border-radius: var(--r-control);
}

.linkedcontact__name {
  flex: 1;
  min-width: 0;
  font-size: 0.8125rem;
  font-weight: 500;
}

.linkedcontact__sub {
  font-size: 0.75rem;
  color: var(--muted);
}

/* ===================== opportunity pipeline ===================== */

.oppcard {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--faint);
  border-radius: var(--r-control);
  box-shadow: var(--shadow-sm);
  padding: 0.625rem 0.6875rem;
  margin-bottom: 0.5rem;
  cursor: grab;
}

.oppcard--won { border-left-color: var(--ok); }
/* Grey, not red: red means Urgent only (4 October 2026). */
.oppcard--lost { border-left-color: var(--faint); }

.oppcard--dragging {
  opacity: 0.45;
}

/* A button, so the keyboard reaches it (it was a clickable div). */
.oppcard__title {
  display: block;
  width: 100%;
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text);
  text-align: left;
  overflow-wrap: anywhere;
  cursor: pointer;
  margin-bottom: 0.375rem;
}

.oppcard__title:hover {
  color: var(--accent);
}

.oppcard__likely {
  margin-left: 0.375rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
}

/* Owner at the left, close date at the right; they wrap on a narrow card. */
.oppcard__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.25rem 0.5rem;
  margin-top: 0.375rem;
  font-size: 0.75rem;
  color: var(--muted);
}

.oppcard__owner {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.oppcard__date {
  white-space: nowrap;
}

.column__sum {
  padding: 0 0.25rem 0.5rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.oppcard__value {
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--accent-dark);
  margin-bottom: 0.375rem;
}

.oppcard__meta {
  font-size: 0.75rem;
  color: var(--muted);
}

.pipelinetotal {
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 2rem;
}

.pipelinetotal__item {
  font-size: 0.8125rem;
  color: var(--muted);
}

.pipelinetotal__value {
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--text);
  margin-right: 0.375rem;
}

/* ===================== deals ===================== */

/* The last column fixed (Edit and Remove): "auto" was 0px in the heading
   row and the buttons' width in the others, so headings drifted. */
.lineitem {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 4rem 6rem 4.5rem 4.5rem 6.5rem 8.5rem;
  gap: 0.625rem;
  align-items: center;
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.lineitem:last-of-type {
  border-bottom: none;
}

.lineitemhead {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 4rem 6rem 4.5rem 4.5rem 6.5rem 8.5rem;
  gap: 0.625rem;
  padding: 0.625rem 1.25rem;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--faint);
  border-bottom: 1px solid var(--border-soft);
}

.lineitem__input {
  width: 100%;
  padding: 0.3125rem 0.5rem;
  font-family: var(--sans);
  font-size: 0.8125rem;
  border: 1px solid var(--border);
  border-radius: 6px;
}

.lineitem__total {
  font-size: 0.8125rem;
  font-weight: 600;
  text-align: right;
}

.revenuebox {
  padding: 1.125rem;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.75rem;
}

.revenuebox__item {
  text-align: center;
}

.revenuebox__value {
  font-size: 1.0625rem;
  font-weight: 700;
  color: var(--accent-dark);
}

.revenuebox__label {
  font-size: 0.6875rem;
  color: var(--muted);
  margin-top: 0.125rem;
}

/* Below 900px each item is its name over its figures, every figure with
   its label (data-label), then Edit and Remove. This hid every figure
   after the quantity, the total too, until 9 October 2026. */
@media (max-width: 900px) {
  .lineitemhead {
    display: none;
  }

  .lineitem {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.25rem 1rem;
  }

  .lineitem > :first-child {
    flex-basis: 100%;
    font-weight: 600;
  }

  /* Two classes: the plain .lineitem__acts rule comes later in the file. */
  .lineitem .lineitem__acts {
    flex-basis: 100%;
    justify-content: flex-start;
    margin-top: 0.25rem;
  }

  .lineitem [data-label]::before {
    content: attr(data-label) ' ';
    font-size: 0.75rem;
    font-weight: 400;
    color: var(--muted);
  }
}

/* ===================== milestones ===================== */

.milestonerow {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.milestonerow:last-of-type {
  border-bottom: none;
}

.milestonerow__name {
  flex: 1;
  min-width: 0;
  font-size: 0.875rem;
  font-weight: 500;
}

.milestonerow__name--done {
  text-decoration: line-through;
  color: var(--muted);
}

/* ===================== subtasks ===================== */

.subtaskrow {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.subtaskrow:last-of-type {
  border-bottom: none;
}

.subtaskrow__title {
  flex: 1;
  min-width: 0;
  font-size: 0.875rem;
  font-weight: 500;
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
  color: var(--text);
  font-family: var(--sans);
}

.subtaskrow__title:hover {
  color: var(--accent);
}

.subtaskrow__title--done {
  text-decoration: line-through;
  color: var(--muted);
}

/* Requests and the work that answers them (6 October 2026): the request
   page's "Project and tasks" panel and the project page's "Requests". */
.worklink {
  display: grid;
  gap: 0.5rem;
  padding: 0.875rem 1.125rem;
  border-bottom: 1px solid var(--border-soft);
}

.worklink__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.375rem;
}

.worklink__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem 0.625rem;
  min-width: 0;
}

.worklink__name {
  flex: 1 1 12rem;
  min-width: 0;
  overflow-wrap: anywhere;
  text-align: left;
  font: inherit;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--accent);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

span.worklink__name {
  color: var(--text);
  cursor: default;
}

.worklink__none {
  margin: 0;
  font-size: 0.875rem;
  color: var(--muted);
}

.workadd {
  display: grid;
  gap: 0.5rem;
  padding: 0.875rem 1.125rem;
}

.workdone {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  margin: 0.875rem 1.125rem 0;
  padding: 0.75rem 0.875rem;
  border-radius: var(--r-control);
  background: var(--ok-soft);
  color: var(--ok);
  font-size: 0.875rem;
}

.workdone p {
  margin: 0;
}

.parentnote {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1rem;
  font-size: 0.8125rem;
  color: var(--muted);
}

.parentnote__link {
  font-family: var(--sans);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--accent);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

/* ===================== comment attachments ===================== */

.commentfiles {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin-top: 0.5rem;
}

/* A comment's file (9 October 2026): thumbnail, then the name over its
   size; opens in the pop-up. Capped so a long name wraps rather than
   widening the comment. */
.commentfile {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  max-width: min(100%, 20rem);
  min-width: 0;
  padding: 0.375rem 0.75rem 0.375rem 0.375rem;
  border: 1px solid var(--border);
  border-radius: var(--r-control);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.commentfile:hover,
.commentfile:focus-visible {
  border-color: var(--accent);
}

.commentfile:disabled {
  cursor: progress;
}

.commentfile__thumb {
  width: 2.75rem;
  height: 2.75rem;
}

.commentfile__text {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  min-width: 0;
}

.commentfile__name {
  font-size: 0.8125rem;
  font-weight: 500;
  overflow-wrap: anywhere;
}

.commentfile__size {
  font-size: 0.75rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.filechip {
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 500;
  padding: 0.25rem 0.625rem;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
}

.filechip:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.pendingfile {
  display: none;
  align-items: center;
  gap: 0.625rem;
  margin-top: 0.5rem;
  padding: 0.375rem 0.625rem;
  background: var(--accent-soft);
  border-radius: var(--r-control);
  font-size: 0.8125rem;
  color: var(--accent-dark);
}

.taskpanelhead__open {
  background: none;
  border: none;
  padding: 0;
  font-family: var(--sans);
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--text);
  cursor: pointer;
}

.taskpanelhead__open:hover {
  color: var(--accent);
  text-decoration: underline;
}

/* ===================== mention notifications ===================== */

.bellwrap {
  position: relative;
}

.bellbtn {
  position: relative;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-control);
  cursor: pointer;
  color: var(--text-2);
}

.bellbtn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.bellbtn svg {
  width: 18px;
  height: 18px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.bellbadge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 16px;
  height: 16px;
  padding: 0 3px;
  border-radius: 999px;
  background: var(--warn);
  /* The surface colour: white in light, as it was; in dark --warn is a
     yellow and white on it measured 1.4:1. */
  color: var(--surface);
  font-size: 0.625rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.bellmenu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 40;
  width: 22rem;
  max-height: 26rem;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-pop);
}

.bellmenu__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border-soft);
}

.bellmenu__title {
  font-size: 0.875rem;
  font-weight: 700;
}

.mentionrow {
  display: flex;
  gap: 0.625rem;
  align-items: flex-start;
  width: 100%;
  padding: 0.75rem 1rem;
  border: none;
  border-bottom: 1px solid var(--border-soft);
  background: var(--surface);
  text-align: left;
  cursor: pointer;
  font-family: var(--sans);
}

.mentionrow:last-child {
  border-bottom: none;
}

.mentionrow:hover {
  background: var(--surface-2);
}

.mentionrow--unread {
  background: var(--accent-soft);
}

.mentionrow--unread:hover {
  background: var(--accent-soft);
  filter: brightness(0.97);
}

.mentionrow__body {
  flex: 1;
  min-width: 0;
}

.mentionrow__text {
  font-size: 0.8125rem;
  color: var(--text);
  line-height: 1.45;
}

.mentionrow__text b {
  font-weight: 600;
}

.mentionrow__snippet {
  font-size: 0.8125rem;
  color: var(--muted);
  margin-top: 0.1875rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mentionrow__when {
  font-size: 0.6875rem;
  color: var(--faint);
  margin-top: 0.25rem;
}

/* Both menus hang off the right edge of the button that opened them, which is
   right for a button on the right of a wide screen. On a phone the bell sits
   near the left edge, so a 22rem menu anchored to its right edge started at
   -300px: 300 of its 352 pixels were off the screen and all you could see was
   the tail of "Mark all read".

   Anchoring to the trigger cannot work at this width whichever side it uses,
   so on a phone they stop being drop-downs and become sheets pinned to the
   bottom of the screen: always fully visible, whatever opened them, and
   within reach of a thumb. Above the chat button, which would otherwise
   cover the last row. */
@media (max-width: 860px) {
  .bellmenu,
  .createmenu {
    position: fixed;
    inset: auto 0.75rem 0.75rem;
    width: auto;
    min-width: 0;
    max-height: 70vh;
    overflow-y: auto;
    z-index: 120;
  }
}

/* ===================== context-aware create split button ===================== */

.createsplit {
  display: flex;
  position: relative;
}

.createsplit__main {
  font-family: var(--sans);
  font-size: 0.8125rem;
  font-weight: 600;
  color: #ffffff;
  background: var(--accent-solid);
  border: none;
  border-radius: var(--r-pill) 0 0 var(--r-pill);
  padding: 0.5rem 0.9375rem;
  cursor: pointer;
  white-space: nowrap;
}

.createsplit__main:hover {
  background: var(--accent-solid-hover);
}

.createsplit__caret {
  font-family: var(--sans);
  color: #ffffff;
  background: var(--accent-solid);
  border: none;
  border-left: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 0 var(--r-pill) var(--r-pill) 0;
  padding: 0.5rem 0.625rem;
  cursor: pointer;
  display: flex;
  align-items: center;
}

.createsplit__caret:hover {
  background: var(--accent-solid-hover);
}

.createsplit__caret svg {
  width: 12px;
  height: 12px;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ===================== unlinked contact suggestion ===================== */

.suggestbox {
  border: 1px dashed var(--border-dashed);
  border-radius: 10px;
  background: var(--surface-2);
  padding: 0.875rem;
}

.suggestbox__label {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.625rem;
}

.suggestbox__text {
  font-size: 0.8125rem;
  color: var(--muted);
  margin: 0 0 0.625rem;
}

.suggestbox__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.25rem;
}

/* ===================== custom field definitions ===================== */

.cfrow {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.cfrow:last-of-type {
  border-bottom: none;
}

.cfrow__main {
  flex: 1;
  min-width: 0;
}

.cfrow__label {
  font-size: 0.875rem;
  font-weight: 600;
}

.cfrow__meta {
  font-size: 0.75rem;
  color: var(--muted);
  margin-top: 0.125rem;
}

.nameline {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* ===================== chat ===================== */

.chatwrap {
  display: grid;
  grid-template-columns: 15rem minmax(0, 1fr);
  gap: 1rem;
  align-items: start;
}

@media (max-width: 900px) {
  /* A 1fr track has a minimum of auto, so it grows to the widest thing in
     it. The conversation list needs about 466px before it will truncate, and
     that is what the whole Chat page was being sized to on a phone. */
  .chatwrap {
    grid-template-columns: minmax(0, 1fr);
  }
}

.chanlist {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

.chanlist__group {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 0.875rem 0.875rem 0.375rem;
}

.chanitem {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.5rem 0.875rem;
  border: none;
  background: transparent;
  font-family: var(--sans);
  font-size: 0.8125rem;
  color: var(--text-2);
  text-align: left;
  cursor: pointer;
}

.chanitem:hover {
  background: var(--surface-2);
}

.chanitem--active {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}

.chanitem__hash {
  color: var(--faint);
  font-weight: 600;
}

.chanitem--active .chanitem__hash {
  color: var(--accent);
}

.chanitem__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatpane {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
  /* The height of the screen below the page header, rather than a fixed
     32rem: at 1280x800 the conversation showed about five messages above
     157px of empty page (4 October 2026). Never shorter than it was. */
  height: max(32rem, calc(100vh - 12.5rem));
  height: max(32rem, calc(100dvh - 12.5rem));
}

/* On a phone the pane sits under the conversation list and is scrolled to
   when a conversation is chosen; it fits the screen above the bottom
   navigation bar (4rem), so the message box is not hidden behind it. */
@media (max-width: 900px) {
  .chatpane,
  .threadpane {
    height: max(24rem, calc(100vh - 6rem - env(safe-area-inset-bottom)));
    height: max(24rem, calc(100dvh - 6rem - env(safe-area-inset-bottom)));
  }
}

.chathead {
  padding: 0.875rem 1.125rem;
  border-bottom: 1px solid var(--border-soft);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.chathead__name {
  font-size: 0.9375rem;
  font-weight: 700;
}

.chathead__sub {
  font-size: 0.75rem;
  color: var(--muted);
}

.chatlog {
  flex: 1;
  overflow-y: auto;
  padding: 1rem 1.125rem;
  display: flex;
  flex-direction: column;
  gap: 0.875rem;
}

.msg {
  display: flex;
  gap: 0.625rem;
  align-items: flex-start;
}

.msg__body {
  flex: 1;
  min-width: 0;
}

.msg__head {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}

.msg__author {
  font-size: 0.8125rem;
  font-weight: 600;
}

.msg__when {
  font-size: 0.6875rem;
  color: var(--faint);
}

.msg__text {
  font-size: 0.875rem;
  color: var(--text-2);
  white-space: pre-wrap;
  word-break: break-word;
  margin-top: 0.0625rem;
}

.chatcompose {
  border-top: 1px solid var(--border-soft);
  padding: 0.75rem 1.125rem;
  display: flex;
  gap: 0.5rem;
  align-items: flex-end;
}

.chatcompose textarea {
  flex: 1;
  min-height: 2.5rem;
  max-height: 8rem;
  resize: vertical;
}

.livedot {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--muted);
}

.livedot::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--faint);
}

.livedot--on::before {
  background: #10b981;
}

/* ===================== chat: threads, reactions, unread ===================== */

.msg {
  position: relative;
}

.msg:hover {
  background: var(--surface-2);
  border-radius: 8px;
}

.msg__actions {
  display: none;
  gap: 0.25rem;
  position: absolute;
  top: -0.375rem;
  right: 0.25rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.125rem 0.25rem;
  box-shadow: var(--shadow-sm);
}

.msg:hover .msg__actions {
  display: flex;
}

.msgact {
  border: none;
  background: none;
  cursor: pointer;
  font-size: 0.875rem;
  line-height: 1;
  padding: 0.1875rem 0.25rem;
  border-radius: 6px;
  font-family: var(--sans);
}

.msgact:hover {
  background: var(--surface-2);
}

.msgact--text {
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--muted);
}

.reacts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin-top: 0.3125rem;
}

.react {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: 999px;
  padding: 0.0625rem 0.4375rem;
  font-size: 0.75rem;
  cursor: pointer;
  font-family: var(--sans);
}

.react--mine {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent-dark);
}

.react__n {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.threadline {
  margin-top: 0.3125rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--accent);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: var(--sans);
}

.threadline:hover {
  text-decoration: underline;
}

.threadpane {
  border-left: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  /* The same height as the conversation beside it (.chatpane). */
  height: max(32rem, calc(100vh - 12.5rem));
  height: max(32rem, calc(100dvh - 12.5rem));
  background: var(--surface);
}

.chatwrap--thread {
  grid-template-columns: 13rem minmax(0, 1fr) 20rem;
}

@media (max-width: 1200px) {
  .chatwrap--thread {
    grid-template-columns: 15rem minmax(0, 1fr);
  }
  .threadpane {
    display: none;
  }
}

/* This comes after the rule above on purpose: both selectors weigh the same,
   so without it the threaded view kept a 15rem sidebar on a phone, leaving
   about 130px for the conversation itself. */
@media (max-width: 900px) {
  .chatwrap--thread {
    grid-template-columns: minmax(0, 1fr);
  }
}

.unreadpill {
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--accent-solid);
  color: #fff;
  font-size: 0.625rem;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.newline {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0.25rem 0;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--danger);
}

.newline::before,
.newline::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--danger-soft);
}

/* ===================== chat: refined message list ===================== */

.chatlog {
  gap: 0;
  padding: 0.75rem 0.5rem;
}

.msg {
  padding: 0.3125rem 0.625rem;
  gap: 0.625rem;
  border-radius: 8px;
}

/* Consecutive messages from the same person lose the repeated avatar and
   name, so a back-and-forth reads as a conversation rather than a form. */
.msg--grouped {
  margin-top: 0;
}

.msg--grouped .msg__head {
  display: none;
}

.msg__gutter {
  width: 28px;
  flex: 0 0 28px;
  display: flex;
  justify-content: center;
  align-items: flex-start;
}

.msg__stamp {
  font-size: 0.6875rem;
  color: transparent;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
  user-select: none;
}

.msg:hover .msg__stamp {
  color: var(--faint);
}

.msg + .msg:not(.msg--grouped) {
  margin-top: 0.625rem;
}

.daysep {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  margin: 0.875rem 0.25rem 0.5rem;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--faint);
}

.daysep::before,
.daysep::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border-soft);
}

.mentionchip {
  background: var(--accent-soft);
  color: var(--accent-dark);
  border-radius: 4px;
  padding: 0 0.1875rem;
  font-weight: 600;
}

.msg--tagged {
  background: var(--warn-softer);
  border-left: 3px solid var(--warn);
  border-radius: 0 8px 8px 0;
}

.msgfiles {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin-top: 0.375rem;
}

/* Photos in chat (6 October 2026). A fixed frame from the start, so the
   log does not grow as each picture loads and push the newest message out
   of view; the picture is cropped to fill it and opens whole when tapped.
   The strip takes its own line above any file chips. */
.msgphotos {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  flex-basis: 100%;
  min-width: 0;
}

.msgphoto {
  width: 13.75rem;
  max-width: 100%;
  aspect-ratio: 4 / 3;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--r-control);
  background: var(--track);
  cursor: zoom-in;
}

/* The photo viewer: over everything, chat windows included (200). */
.photoview {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: max(1rem, env(safe-area-inset-top, 0px)) 1rem max(1rem, env(safe-area-inset-bottom, 0px));
  background: rgba(10, 10, 20, 0.86);
}

.photoview__frame {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  max-width: min(100%, 72rem);
  max-height: 100%;
  min-width: 0;
}

.photoview__img {
  display: block;
  max-width: 100%;
  max-height: calc(100vh - 6rem);
  max-height: calc(100dvh - 6rem);
  object-fit: contain;
  border-radius: var(--r-control);
  background: var(--surface);
}

.photoview__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  color: #ffffff;
  font-size: 0.875rem;
}

.photoview__name {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}

.photoview__link {
  color: #ffffff;
  text-decoration: underline;
}

.photoview__close {
  min-height: 44px;
  padding: 0 1.125rem;
  border: 1px solid rgba(255, 255, 255, 0.6);
  border-radius: var(--r-control);
  background: transparent;
  color: #ffffff;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.photoview__close:hover,
.photoview__close:focus-visible {
  background: rgba(255, 255, 255, 0.14);
}

/* Several photos sit two to a row where 220px each will not fit (a phone,
   a chat window), rather than one tall column. */
.msgphotos:has(> .msgphoto + .msgphoto) > .msgphoto {
  width: min(13.75rem, calc(50% - 0.1875rem));
}

.msgphoto img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.msgphoto:hover {
  border-color: var(--accent);
}

/* ---- composer ---- */

.chatcompose {
  flex-direction: column;
  align-items: stretch;
  gap: 0.5rem;
}

.chatcompose__row {
  display: flex;
  gap: 0.5rem;
  align-items: flex-end;
}

.chatcompose__tools {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  align-items: center;
}

.mentionpick {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}

.mentionbtn {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: 999px;
  padding: 0.125rem 0.5rem 0.125rem 0.125rem;
  font-size: 0.75rem;
  font-family: var(--sans);
  cursor: pointer;
}

.mentionbtn .avatar {
  width: 18px;
  height: 18px;
  flex: 0 0 18px;
  font-size: 0.5rem;
}

.mentionbtn--on {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent-dark);
  font-weight: 600;
}

/* ===================== docked chat ===================== */

/* ===================== @ mention autocomplete ===================== */

.chatcompose__row {
  position: relative;
}

.atmenu {
  position: absolute;
  left: 0;
  bottom: calc(100% + 6px);
  z-index: 60;
  width: 16rem;
  max-height: 13rem;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-pop);
  padding: 0.25rem;
}

.atitem {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.375rem 0.5rem;
  border: none;
  background: transparent;
  border-radius: var(--r-control);
  font-family: var(--sans);
  font-size: 0.8125rem;
  text-align: left;
  cursor: pointer;
  color: var(--text);
}

.atitem--active,
.atitem:hover {
  background: var(--accent-soft);
  color: var(--accent-dark);
}

.atitem__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.atitem .avatar {
  width: 22px;
  height: 22px;
  flex: 0 0 22px;
  font-size: 0.5625rem;
}

.atempty {
  padding: 0.5rem;
  font-size: 0.75rem;
  color: var(--muted);
}

/* ===================== message record links ===================== */

.msglinks {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin-top: 0.4375rem;
}

.recchip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: var(--r-control);
  padding: 0.25rem 0.5rem;
  font-size: 0.75rem;
  font-family: var(--sans);
  cursor: pointer;
  color: var(--text-2);
  max-width: 18rem;
}

.recchip:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.recchip__kind {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--faint);
}

.recchip:hover .recchip__kind {
  color: var(--accent);
}

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

/* share-to-chat dialog */

.sharebox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: 1rem;
  background: rgba(16, 24, 40, 0.4);
}

.sharecard {
  width: min(26rem, 100%);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-pop);
  padding: 1.25rem;
}

.sharecard h3 {
  margin: 0 0 0.25rem;
  font-size: 1rem;
  font-weight: 700;
}

/* ===================== overview stat cards (refined) ===================== */

/* Icons no longer carry a per-card colour set from JS. One calm accent
   tint for every card, so amber genuinely means "look at this" rather
   than competing with three other hues. */
.statcard__icon {
  background: var(--accent-soft);
  color: var(--accent);
  margin-bottom: 0.875rem;
}

.statcard__icon svg {
  stroke: currentColor;
  fill: none;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.statcard {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.statcard:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md);
}

.statcard--warn {
  border-color: var(--warn-line);
  background: var(--warn-softer);
}

.statcard--warn .statcard__icon {
  background: var(--warn-soft);
  color: var(--warn);
}

.statcard__note {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
  margin-top: 0.375rem;
}

.statcard--warn .statcard__note {
  color: var(--warn);
}

/* Grid items already stretch to the tallest in the row, so cards with and
   without a note line up without extra work. */

/* The comment textarea needs a positioned parent so the @ menu can anchor
   to it, matching how the chat composer is arranged. */
.composer__boxwrap {
  position: relative;
}

.composer__boxwrap textarea {
  width: 100%;
}

/* ===================== reports ===================== */

.reportbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: flex-end;
  padding: 1.125rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.reportbar .field {
  margin-bottom: 0;
}

.reportbar__spacer {
  flex: 1;
}

.bigfigs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  border-bottom: 1px solid var(--border-soft);
}

.bigfig {
  padding: 1.125rem 1.25rem;
  border-right: 1px solid var(--border-soft);
}

.bigfig:last-child {
  border-right: none;
}

.bigfig__value {
  font-size: 1.625rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.bigfig__label {
  font-size: 0.75rem;
  color: var(--muted);
  margin-top: 0.375rem;
}

.bigfig--warn .bigfig__value {
  color: var(--warn);
}

.breakdown {
  padding: 0.5rem 1.25rem 1.25rem;
}

.breakrow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 3.5rem 1fr;
  gap: 0.75rem;
  align-items: center;
  padding: 0.5rem 0;
}

.breakrow__label {
  font-size: 0.8125rem;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.breakrow__count {
  font-size: 0.8125rem;
  font-weight: 700;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.breakrow__bar {
  height: 8px;
  border-radius: 999px;
  background: var(--border-soft);
  overflow: hidden;
}

.breakrow__fill {
  height: 100%;
  border-radius: 999px;
  background: var(--accent);
}

/* ===================== dense record detail grid ===================== */

/* Two columns of label/value pairs, labels right-aligned against their
   values. Fits far more on screen than the tile layout, which is what a
   contact record needs: it is reference material, scanned not read. */
.detailgrid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 2.5rem;
  padding: 1.125rem 1.25rem;
}

.detailrow {
  display: grid;
  grid-template-columns: 9rem minmax(0, 1fr);
  gap: 0.75rem;
  align-items: baseline;
  padding: 0.4375rem 0;
  border-bottom: 1px solid var(--border-soft);
}

.detailrow__label {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
  text-align: right;
}

.detailrow__value {
  font-size: 0.8125rem;
  color: var(--text);
  min-width: 0;
  overflow-wrap: anywhere;
}

.detailrow__value a,
.detailrow__value .linkbutton {
  color: var(--accent);
}

.detailrow__value--muted {
  color: var(--faint);
}

@media (max-width: 900px) {
  .detailgrid {
    grid-template-columns: 1fr;
    column-gap: 0;
  }
}

/* ---- related lists ---- */

.relhead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.875rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.relhead__title {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  font-size: 0.9375rem;
  font-weight: 700;
}

.relhead__count {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
}

.relrow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 0.75rem;
  align-items: center;
  padding: 0.625rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.relrow:last-child {
  border-bottom: none;
}

.relrow:hover {
  background: var(--surface-2);
}

/* A destructive action should not look like an ordinary one. */
.button--danger {
  font-family: var(--sans);
  font-size: 0.8125rem;
  font-weight: 600;
  color: #ffffff;
  background: #b91c1c;
  border: none;
  border-radius: var(--r-pill);
  padding: 0.5rem 0.9375rem;
  cursor: pointer;
  margin-top: 0.75rem;
}

.button--danger:hover:not(:disabled) {
  background: #991b1b;
}

.button--danger:disabled {
  opacity: 0.6;
  cursor: default;
}

/* Member rows in the platform console need a name plus a secondary line
   for role and department. */
.teamrow__main {
  flex: 1;
  min-width: 0;
}

.teamrow__meta {
  font-size: 0.75rem;
  color: var(--muted);
  margin-top: 0.0625rem;
}

/* ===================== people by department ===================== */

.deptblock {
  margin-bottom: 1rem;
}

.deptblock__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.875rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.deptblock__name {
  font-size: 0.9375rem;
  font-weight: 700;
}

.deptblock__count {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
}

.peoplegrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 0.75rem;
  padding: 1rem 1.25rem;
}

.personcard {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.75rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-control);
  cursor: pointer;
  font-family: var(--sans);
  text-align: left;
  min-width: 0;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.personcard:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow-sm);
}

.personcard__body {
  flex: 1;
  min-width: 0;
}

.personcard__name {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.personcard__meta {
  font-size: 0.75rem;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-top: 0.0625rem;
}

/* Delete sits with the other message actions but should not read as an
   equal peer to Reply. */
.msgact--danger {
  color: var(--danger);
}

.msgact--danger:hover {
  background: var(--danger-soft);
}

/* ===================== group channel creation ===================== */

.groupdlg__people {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  max-height: 14rem;
  overflow-y: auto;
  padding: 0.125rem;
}

.grouppick {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: 999px;
  padding: 0.1875rem 0.625rem 0.1875rem 0.1875rem;
  font-size: 0.8125rem;
  font-family: var(--sans);
  cursor: pointer;
  color: var(--text-2);
}

.grouppick .avatar {
  width: 22px;
  height: 22px;
  flex: 0 0 22px;
  font-size: 0.5625rem;
}

.grouppick--on {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent-dark);
  font-weight: 600;
}

.grouppick__dept {
  font-size: 0.6875rem;
  color: var(--faint);
}

.grouppick--on .grouppick__dept {
  color: var(--accent);
}

/* ===================== chat launcher ===================== */

/* Sits where the panel opens, so the button and the thing it opens are
   obviously the same object. */
.chatfab {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  z-index: 110;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: none;
  background: var(--accent-solid);
  color: #ffffff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 10px 28px rgba(79, 70, 229, 0.42);
  transition: transform 0.14s ease, box-shadow 0.14s ease, background 0.14s ease;
}

.chatfab:hover {
  background: var(--accent-solid-hover);
  transform: translateY(-2px);
  box-shadow: 0 14px 34px rgba(79, 70, 229, 0.5);
}

.chatfab:active {
  transform: translateY(0);
}

.chatfab svg {
  width: 24px;
  height: 24px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.chatfab__badge {
  position: absolute;
  top: -2px;
  right: -2px;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  border-radius: 999px;
  background: #dc2626;
  color: #ffffff;
  font-size: 0.6875rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  border: 2px solid var(--surface);
}

@media (max-width: 600px) {
  .chatfab {
    right: 0.75rem;
    bottom: 0.75rem;
  }
}

/* ===================== comment editing and history ===================== */

.comment__edited {
  border: none;
  background: none;
  padding: 0;
  font-family: var(--sans);
  font-size: 0.6875rem;
  color: var(--faint);
  cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: 2px;
}

.comment__edited:hover {
  color: var(--accent);
}

.commentedit {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.375rem;
}

.commentedit__actions {
  display: flex;
  gap: 0.5rem;
}

.revisions {
  margin-top: 0.5rem;
  border-left: 2px solid var(--border);
  padding-left: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
}

.revision__meta {
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--faint);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.revision__body {
  font-size: 0.8125rem;
  color: var(--muted);
  white-space: pre-wrap;
  margin-top: 0.125rem;
}

/* Activity rows that lead to a record. Rows without a destination stay
   plain, so nothing looks clickable unless it is. */
/* Width less the card's side margins (1.25rem each): a button does not
   stretch to its container, and 100% plus the margins ran 40px past
   the panel's edge, cutting off "3h ago" (9 October 2026). */
.event--open {
  width: calc(100% - 2.5rem);
  text-align: left;
  font-family: var(--sans);
  border: none;
  cursor: pointer;
  transition: background 0.12s ease;
}

.event--open:hover {
  background: var(--surface-2);
}

/* ===================== assignment picker ===================== */

.assignpick {
  padding: 1.125rem;
}

.assignpick__current {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.625rem;
  border-radius: var(--r-control);
  background: var(--accent-soft);
}

.assignpick__current--empty {
  background: var(--surface-2);
  border: 1px dashed var(--border);
}

.assignpick__body {
  flex: 1;
  min-width: 0;
}

.assignpick__label {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
}

.assignpick__current--empty .assignpick__label {
  color: var(--muted);
}

.assignpick__name {
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.assignpick__quick {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin-top: 0.625rem;
}

.assignpick__search {
  margin-top: 0.625rem;
}

.assignpick__list {
  margin-top: 0.5rem;
  max-height: 15rem;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--r-control);
}

.assignoption {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.5rem 0.625rem;
  border: none;
  border-bottom: 1px solid var(--border-soft);
  background: var(--surface);
  font-family: var(--sans);
  text-align: left;
  cursor: pointer;
}

.assignoption:last-child {
  border-bottom: none;
}

.assignoption:hover {
  background: var(--accent-soft);
}

.assignoption--current {
  background: var(--accent-soft);
}

.assignoption__body {
  flex: 1;
  min-width: 0;
}

.assignoption__name {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.assignoption__dept {
  font-size: 0.6875rem;
  color: var(--muted);
}

.assignoption__tick {
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--accent);
}

/* "Add as a new client" in the contact picker: an action, not a result. */
.pickresult--create {
  color: var(--accent);
  font-weight: 600;
  border-top: 1px solid var(--border);
}

.pickresult--create:hover {
  background: var(--accent-soft);
}

/* ===================== module department scoping ===================== */

.modscope {
  padding: 1.125rem 1.25rem;
}

.modscope__row {
  display: grid;
  grid-template-columns: minmax(0, 12rem) minmax(0, 1fr);
  gap: 0.75rem;
  align-items: start;
  padding: 0.625rem 0;
  border-bottom: 1px solid var(--border-soft);
}

.modscope__row:last-child {
  border-bottom: none;
}

.modscope__name {
  font-size: 0.8125rem;
  font-weight: 600;
  padding-top: 0.25rem;
}

.modscope__depts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
}

.deptchip {
  display: inline-flex;
  align-items: center;
  gap: 0.3125rem;
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: 999px;
  padding: 0.25rem 0.625rem;
  font-family: var(--sans);
  font-size: 0.75rem;
  color: var(--text-2);
  cursor: pointer;
}

.deptchip--on {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent-dark);
  font-weight: 600;
}

.modscope__all {
  font-size: 0.75rem;
  color: var(--faint);
  padding-top: 0.3125rem;
}

/* A wider modal for forms, where 26rem is too cramped for paired fields. */
.sharecard--form {
  width: min(34rem, 100%);
  max-height: 88vh;
  overflow-y: auto;
  padding: 1.375rem;
}

.sharecard--form .field {
  margin-bottom: 0.75rem;
}

/* ===================== contacts list ===================== */

.listbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.625rem;
  align-items: center;
  padding: 0.875rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.listbar__search {
  flex: 1;
  min-width: 12rem;
  max-width: 22rem;
}

.listbar__count {
  font-size: 0.75rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* Whole row is the target, not just the name. */
.contactrow {
  display: grid;
  grid-template-columns: auto minmax(0, 1.4fr) minmax(0, 1fr) auto;
  gap: 0.75rem;
  align-items: center;
  width: 100%;
  padding: 0.625rem 1.25rem;
  border: none;
  border-bottom: 1px solid var(--border-soft);
  background: transparent;
  font-family: var(--sans);
  text-align: left;
  cursor: pointer;
}

.contactrow:last-child {
  border-bottom: none;
}

.contactrow:hover {
  background: var(--surface-2);
}

.contactrow__main {
  min-width: 0;
}

.contactrow__name {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.contactrow__sub {
  font-size: 0.75rem;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-top: 0.0625rem;
}

.contactrow__reach {
  min-width: 0;
  font-size: 0.75rem;
  color: var(--muted);
}

.contactrow__reach div {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.contactrow__tail {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  white-space: nowrap;
}

@media (max-width: 760px) {
  .contactrow {
    grid-template-columns: auto minmax(0, 1fr) auto;
  }
  .contactrow__reach {
    display: none;
  }
}

/* Address sits under the name, quieter than the job title above it. */
.contactrow__addr {
  font-size: 0.75rem;
  color: var(--faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-top: 0.0625rem;
}

/* ===================== chat windows ===================== */

/* The rail sits to the left of the launcher and grows leftwards.
   row-reverse means the first child renders rightmost, so a window
   opens nearest the button that opened it. */
.dockrail {
  position: fixed;
  right: 5rem;
  bottom: 1rem;
  z-index: 105;
  display: flex;
  flex-direction: row-reverse;
  align-items: flex-end;
  gap: 0.75rem;
  pointer-events: none;
}

.dockrail > * {
  pointer-events: auto;
}

.chatwin {
  width: 19rem;
  height: 26rem;
  max-height: calc(100vh - 6rem);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card) var(--r-card) 0 0;
  box-shadow: var(--shadow-pop);
  overflow: hidden;
}

/* Minimised collapses to the header bar alone, the way a chat window
   should: still visible, still one click from the conversation. */
.chatwin--min {
  height: auto;
}

.chatwin--min .chatwin__log,
.chatwin--min .chatwin__compose {
  display: none;
}

.chatwin__head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.625rem;
  background: var(--accent-solid);
  color: #ffffff;
  cursor: pointer;
  flex: 0 0 auto;
}

.chatwin__titlewrap {
  display: flex;
  align-items: center;
  gap: 0.4375rem;
  min-width: 0;
  flex: 1;
}

.chatwin__titlewrap .avatar {
  width: 22px;
  height: 22px;
  flex: 0 0 22px;
  font-size: 0.5625rem;
  border: 1px solid rgba(255, 255, 255, 0.5);
}

.chatwin__title {
  font-size: 0.8125rem;
  font-weight: 700;
  color: #ffffff;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatwin__acts {
  display: flex;
  align-items: center;
  gap: 0.125rem;
  flex: 0 0 auto;
}

.chatwin__btn {
  border: none;
  background: none;
  color: rgba(255, 255, 255, 0.85);
  font-size: 0.75rem;
  line-height: 1;
  /* At least 28px square on a laptop: they were 17 to 21px wide, under the
     24px minimum for a target, five in a row. Phones get 36px below. */
  min-width: 28px;
  min-height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 0.3125rem;
  border-radius: 4px;
  cursor: pointer;
  font-family: var(--sans);
}

.chatwin__btn:hover {
  background: rgba(255, 255, 255, 0.2);
  color: #ffffff;
}

.chatwin__log {
  flex: 1;
  overflow-y: auto;
  padding: 0.625rem;
  background: var(--surface-2);
  min-height: 0;
}

.chatwin__log .msg {
  padding: 0.3125rem 0;
}

.chatwin__log .msg__text {
  font-size: 0.8125rem;
}

.chatwin__compose {
  flex: 0 0 auto;
  display: flex;
  align-items: flex-end;
  gap: 0.375rem;
  padding: 0.5rem;
  border-top: 1px solid var(--border-soft);
  background: var(--surface);
}

.chatwin__compose textarea {
  flex: 1;
  min-height: 2.25rem;
  max-height: 6rem;
  font-size: 0.8125rem;
  padding: 0.4375rem 0.5rem;
}

/* ---- conversation list ---- */

.chatlist {
  position: fixed;
  right: 1rem;
  bottom: 4.75rem;
  z-index: 108;
  width: 17rem;
  max-height: min(26rem, calc(100vh - 7rem));
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-pop);
  overflow: hidden;
}

.chatlist__head {
  padding: 0.75rem 0.875rem;
  font-size: 0.875rem;
  font-weight: 700;
  border-bottom: 1px solid var(--border-soft);
  flex: 0 0 auto;
}

.chatlist__body {
  overflow-y: auto;
  min-height: 0;
}

.chatlist__row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.5rem 0.875rem;
  border: none;
  background: transparent;
  font-family: var(--sans);
  text-align: left;
  cursor: pointer;
}

.chatlist__row:hover {
  background: var(--accent-soft);
}

.chatlist__main {
  min-width: 0;
  flex: 1;
}

.chatlist__name {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatlist__kind {
  font-size: 0.6875rem;
  color: var(--muted);
}

.chatlist__sep {
  padding: 0.5rem 0.875rem 0.25rem;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--faint);
  border-top: 1px solid var(--border-soft);
  margin-top: 0.25rem;
}

/* On a phone one window fills the width rather than being a slab
   hanging off the right edge. */
@media (max-width: 600px) {
  /* On a wide screen the dock is held 5rem clear of the chat button. Here it
     spans the full width, so it runs underneath that button — and the button
     sat above it (110 against 105), covering the bottom-right corner of the
     window, which is exactly where Send is. The message could be typed and
     then not sent. With the window in front, the button it would have covered
     is behind it, and reappears the moment the window is minimised. */
  .dockrail {
    right: 0.5rem;
    left: 0.5rem;
    bottom: 0.5rem;
    z-index: 115;
  }

  .chatwin {
    width: 100%;
    /* 22rem left about six messages visible above the keyboard. */
    height: min(70vh, 32rem);
  }

  .chatlist {
    right: 0.5rem;
    left: 0.5rem;
    width: auto;
  }
}

/* A hook, not a style: the minimise arrow is found by this class so its
   glyph can be flipped without re-rendering the window header. */
.chatwin__min {
  /* intentionally no declarations */
}

/* ---- conversation list rows ---- */

.chatlist__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  min-width: 0;
}

.chatlist__when {
  font-size: 0.6875rem;
  color: var(--faint);
  flex: 0 0 auto;
}

.chatlist__preview {
  font-size: 0.6875rem;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-top: 0.0625rem;
}

/* An unread conversation carries the weight, so the eye lands on it
   before it lands on the badge. */
.chatlist__row--unread .chatlist__name {
  font-weight: 700;
}

.chatlist__row--unread .chatlist__preview {
  color: var(--text-2);
  font-weight: 600;
}

.chatlist__badge {
  flex: 0 0 auto;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: #dc2626;
  color: #ffffff;
  font-size: 0.625rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

/* ---- message editing ---------------------------------------------- */

.msg__edited {
  display: inline-block;
  margin-left: 0.4rem;
  font-size: 0.75rem;
  color: var(--muted);
  cursor: default;
}

.msgedit {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin: 0.15rem 0 0.25rem;
}

.msgedit__box {
  width: 100%;
  box-sizing: border-box;
  resize: vertical;
  padding: 0.45rem 0.55rem;
  font: inherit;
  line-height: 1.45;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
}

.msgedit__box:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.msgedit__acts {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}

.msgedit__note {
  font-size: 0.75rem;
  color: var(--muted);
}

/* Shown while a pane is loading its replacement content. The outgoing
   record stays visible and dims, rather than the pane going empty and
   flashing white for the length of a round trip. Pointer events are off
   so a button belonging to the outgoing record cannot be clicked. */
.is-loading {
  opacity: 0.45;
  pointer-events: none;
  transition: opacity 120ms ease-out;
}

/* ---- request categories and service standards ---------------------- */

/* Category, department, picked up by, first-reply target, resolve target,
   public form, actions. */
.row--cat {
  /* Shared out rather than fixed. Five fixed columns (42rem) left the
     category's own name 35px at 1280, inside Settings' narrower page, so
     "Roads and potholes" was cut to "Ro…". The name now has a floor and the
     largest share. The last column is fixed too: each row is its own
     grid, and "auto" made it 0px in the heading row (no buttons) and 107px
     in the others, so every heading sat over the wrong column. The two
     targets are 7rem: at 5rem "4 working hours" (100px) ran into the
     next column (seen 9 October 2026; working-time units are longer
     than "48 hours"). */
  grid-template-columns:
    minmax(9rem, 1.5fr) minmax(0, 1fr) minmax(0, 1fr) 7rem 7rem 8rem 7.5rem;
}

/* The public form column: the default button, with a note under it when
   people can also pick the category on the form themselves. */
.catpub {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.125rem;
  min-width: 0;
}

.catpub__note {
  font-size: 0.75rem;
  color: var(--muted);
}

/* A retired category still labels the requests filed under it, so it stays
   listed but reads as out of use. */
.row--muted {
  opacity: 0.55;
}

.row__acts {
  display: flex;
  gap: 0.375rem;
  justify-content: flex-end;
}

/* A missed service standard. Uses the same token as an overdue pill so
   lateness looks the same wherever it appears. */
.fact__value--flag {
  color: var(--warn);
}

/* Repeat controls on the appointment form. Indented and ruled so it reads
   as settings belonging to the tick box above, not as more of the form. */
.repeatbox {
  margin: 0.25rem 0 0.75rem 1.75rem;
  padding-left: 0.875rem;
  border-left: 2px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
}

@media (max-width: 640px) {
  .repeatbox {
    margin-left: 0.75rem;
  }
}

/* ---- project schedule ---------------------------------------------- */

.pschedule {
  padding: 1.125rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* The window the markers are placed in: project start, deadline, and the
   last dated thing, which may fall past the deadline. */
/* Name, track, date. The schedule reuses the timeline's row, which has
   two columns, and adds the date as a third item, so every date wrapped
   onto a line of its own under the name (4 October 2026). */
.pschedule .tlrow {
  grid-template-columns: minmax(0, 11rem) minmax(0, 1fr) auto;
}

@media (max-width: 620px) {
  .pschedule .tlrow {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .pschedule .tltrack {
    grid-column: 1 / -1;
    grid-row: 2;
  }
}

.pschedule__span {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  font-size: 0.75rem;
  color: var(--muted);
  padding-bottom: 0.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.tlname--plain {
  cursor: default;
  font-weight: 600;
}

.tlname--plain:hover {
  color: inherit;
}

/* A dated checkpoint is a moment, so it is a marker rather than a bar of
   invented length. Centred on its own position. */
.pmark {
  position: absolute;
  top: 5px;
  width: 12px;
  height: 12px;
  margin-left: -6px;
  border-radius: 50%;
  background: var(--accent);
}

.pmark--milestone {
  border-radius: 2px;
  transform: rotate(45deg);
}

.pmark--done { background: var(--ok); }
.pmark--late { background: var(--warn); }

.row__when--flag {
  color: var(--warn);
}

/* ---- project budget ------------------------------------------------ */

.budgethead {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2.5rem;
  padding: 1.125rem 1.125rem 0.75rem;
}

.budgetbar {
  height: 8px;
  margin: 0 1.125rem;
  background: var(--bg);
  border-radius: var(--r-pill);
  overflow: hidden;
}

.budgetbar__fill {
  height: 100%;
  background: var(--accent);
  border-radius: var(--r-pill);
  transition: width 200ms ease-out;
}

.budgetbar__fill--over {
  background: var(--warn);
}

/* What it was for (date, reference and milestone underneath), amount,
   and Edit and Remove. See fillProjectBudget for why not five columns. */
.row--spend {
  grid-template-columns: minmax(0, 1fr) auto auto;
}

.row__actions {
  display: flex;
  gap: 0.25rem;
}

/* An entry being corrected, in its place in the list. */
.inline-form.inline-form--row {
  margin: 0;
  padding: 0.75rem;
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  background: var(--surface-2);
}

/* A milestone being renamed or re-dated, in its place. */
.milestonerow--editing {
  flex-wrap: wrap;
  gap: 0.5rem;
  background: var(--surface-2);
}

.milestonerow--editing .field__input {
  flex: 1 1 12rem;
  width: auto;
}

.milestonerow--editing input[type='date'] {
  flex: 0 1 11rem;
}

/* On a phone the name takes the line beside the tick box and the date and
   buttons go underneath: with Edit added, a row of five left the name 14px
   wide at 375 (measured 4 October 2026). 17px + 0.75rem is the tick box
   and the gap, so the second line starts under the name. */
@media (max-width: 620px) {
  .milestonerow:not(.milestonerow--editing) {
    flex-wrap: wrap;
    row-gap: 0.375rem;
  }
  .milestonerow:not(.milestonerow--editing) .milestonerow__name {
    flex: 1 1 calc(100% - 17px - 0.75rem);
  }
  .milestonerow:not(.milestonerow--editing) > :nth-child(3) {
    margin-left: calc(17px + 0.75rem);
    margin-right: auto;
  }
}

.row__amount {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

/* ---- threads inside a chat window ---------------------------------- */

/* Threads stay in the window rather than opening a pane or a second window:
   a chat window is a small surface, and sending the conversation elsewhere
   loses the room it came from. */
.winthread {
  margin-top: 0.25rem;
}

.winthread__toggle {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: 0.75rem;
  color: var(--muted);
  cursor: pointer;
}

.winthread__toggle:hover {
  color: var(--accent);
  text-decoration: underline;
}

/* A thread that has replies is worth noticing; an empty one is just an
   affordance to reply and stays quiet. */
.winthread__toggle--has {
  color: var(--accent);
  font-weight: 600;
}

/* A thread holding something unread. Opening the channel clears the badge,
   so without a mark here the one new thing in the window is invisible.
   Weight and a dot carry it as well as colour, so it does not depend on
   seeing the difference between two similar blues. */
.winthread__toggle--new {
  color: var(--accent);
  font-weight: 700;
}

.winthread__toggle--new::before {
  content: '';
  display: inline-block;
  width: 0.4375rem;
  height: 0.4375rem;
  margin-right: 0.375rem;
  border-radius: 50%;
  background: var(--accent);
  vertical-align: 0.05em;
}

/* Ruled and indented so replies read as belonging to the message above
   rather than as more of the channel. */
.winthread__log {
  margin: 0.375rem 0 0.25rem;
  padding-left: 0.625rem;
  border-left: 2px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.msg--reply {
  font-size: 0.8125rem;
}

/* ---- reaching back through history ---------------------------------- */

.loadearlier {
  display: block;
  width: 100%;
  margin: 0 0 0.5rem;
  padding: 0.5rem;
  font: inherit;
  font-size: 0.8125rem;
  color: var(--accent);
  background: var(--surface-2);
  border: 1px dashed var(--border);
  border-radius: var(--r-control);
  cursor: pointer;
}

.loadearlier:hover:not(:disabled) {
  background: var(--accent-soft);
}

.loadearlier:disabled {
  color: var(--muted);
  cursor: default;
}

/* The beginning of a conversation is a statement, not a button. */
.loadearlier--done {
  color: var(--muted);
  background: none;
  border-style: solid;
  border-color: var(--border-soft);
  cursor: default;
  text-align: center;
}

/* ---- chat search ---------------------------------------------------- */

.chatsearch {
  display: flex;
  gap: 0.375rem;
  align-items: center;
  margin-left: auto;
  margin-right: 0.75rem;
}

.chatsearch__input {
  width: 13rem;
  min-width: 0;
  padding: 0.375rem 0.5rem;
  font: inherit;
  font-size: 0.8125rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-control);
}

.chatsearch__input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.chatsearch__scope {
  font-size: 0.75rem;
  padding: 0.375rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--r-control);
  background: var(--surface);
  color: var(--text-2);
}

/* The conversation header holds the name, a 13rem search box with a scope
   select, and the connection dot, all on one unwrapping row. That is about
   460px of content, so on a phone the Chat page was the one screen still
   scrolling sideways after everything else had been fixed.
   Raised to 1100px because the same header still ran 166px off the side of a
   1024px laptop screen, where the conversation list takes 15rem of the width
   before the header gets any. */
@media (max-width: 1100px) {
  .chathead {
    flex-wrap: wrap;
  }

  .chatsearch {
    order: 3;
    flex: 1 1 100%;
    margin-left: 0;
    margin-right: 0;
  }

  /* These two are declared after the general phone rule that lifts fields to
     16px, and carry the same specificity, so they were winning it back and
     still zooming the page on focus. */
  .chatsearch__input {
    flex: 1 1 auto;
    width: auto;
    font-size: 1rem;
  }

  .chatsearch__scope {
    font-size: 1rem;
  }

  /* Only the select: .chanitem is mostly buttons, which do not take focus the
     way a field does and so do not trigger the zoom. */
  select.chanitem {
    font-size: 1rem;
  }

  /* The message box in the chat popup was the one field the phone-wide 16px
     rule could not reach: ".chatwin__compose textarea" is a more specific
     selector than ".field__textarea", so it won wherever it sat in the file.
     At 13px, tapping it zoomed Safari in and left it there — and a zoomed
     page put the right end of the window's title bar, where the close button
     is, past the edge of the screen with no way to reach it. */
  .chatwin__compose textarea {
    font-size: 1rem;
  }

  /* Those title-bar buttons were 20px squares two pixels apart: five of them
     in about 106px. Even unzoomed, hitting close rather than minimise was
     luck. */
  .chatwin__btn {
    min-width: 36px;
    min-height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
  }

  .chatwin__acts {
    gap: 0.125rem;
  }
}

@media (max-width: 760px) {
  /* On a phone the header has no room for both; the box matters more. */
  .chatsearch__scope { display: none; }
  .chatsearch__input { width: 8rem; }
}

.chatsearch__count {
  padding: 0.5rem 0.25rem 0.75rem;
  font-size: 0.75rem;
  color: var(--muted);
}

.searchhit {
  display: flex;
  gap: 0.625rem;
  width: 100%;
  text-align: left;
  padding: 0.625rem 0.5rem;
  background: none;
  border: none;
  border-radius: var(--r-control);
  cursor: pointer;
  font: inherit;
}

.searchhit:hover {
  background: var(--surface-2);
}

.searchhit__body {
  min-width: 0;
  flex: 1;
}

.searchhit__top {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: baseline;
  margin-bottom: 0.1875rem;
}

.searchhit__who {
  font-weight: 600;
  font-size: 0.8125rem;
}

.searchhit__where {
  font-size: 0.75rem;
  color: var(--accent);
}

.searchhit__when {
  font-size: 0.75rem;
  color: var(--muted);
}

/* Two lines of the message is enough to recognise it; the conversation is
   one click away for the rest. */
.searchhit__text {
  font-size: 0.8125rem;
  color: var(--text-2);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.searchhit__note {
  margin-top: 0.1875rem;
  font-size: 0.75rem;
  color: var(--muted);
}

/* Results sit where the log was, so the pane keeps its height and the page
   does not jump between searching and reading. */
.chatsearch__results {
  padding: 0.5rem 0.75rem;
}

/* A person the viewer may not add or remove: shown so the membership is
   still legible, but plainly not something they can change. */
.grouppick:disabled {
  cursor: default;
  opacity: 0.6;
}

.grouppick:disabled:hover {
  background: var(--surface);
}

/* ---- what the chat window's one composer is aimed at ---------------- */

/* A window has a single place to type, which answers either the channel or
   an open thread. This bar is how the writer knows which, and how they get
   back out. */
.chatwin__aim {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.3125rem 0.625rem;
  background: var(--accent-soft);
  border-top: 1px solid var(--border-soft);
  font-size: 0.75rem;
}

.chatwin__aimtext {
  color: var(--accent-dark);
  font-weight: 600;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatwin__aimcancel {
  flex: none;
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: 0.75rem;
  color: var(--muted);
  cursor: pointer;
  text-decoration: underline;
}

.chatwin__aimcancel:hover {
  color: var(--text);
}

/* A person shown for information rather than as something to click: the
   membership of a department, project, organisation or direct channel is a
   consequence of something else and is not edited here. */
.grouppick--static {
  cursor: default;
  background: var(--surface-2);
}

/* Search above a list of people. Sits tight to the list it filters, with the
   match count beside it so a short result does not look like an empty one. */
.peoplefilter {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0.25rem 0 0.375rem;
}

.peoplefilter .field__input {
  flex: 1;
  min-width: 0;
  padding: 0.375rem 0.5rem;
  font-size: 0.8125rem;
}

.peoplefilter__count {
  flex: none;
  font-size: 0.75rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* The title of a window that is still loading. Dimmed so it reads as a
   placeholder rather than as a conversation called "Opening…". */
.chatwin__title--loading {
  color: var(--muted);
  font-weight: 500;
}

/* The skeleton inside a loading window needs room to read as content rather
   than sitting flush against the header. */
.chatwin__log > .skeleton {
  padding: 0.75rem 0.625rem;
}

/* ---- searching inside a chat window -------------------------------- */

.chatwin__find {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.375rem 0.5rem;
  border-bottom: 1px solid var(--border-soft);
  background: var(--surface-2);
}

.chatwin__findbox {
  flex: 1;
  min-width: 0;
  padding: 0.3125rem 0.5rem;
  font: inherit;
  font-size: 0.8125rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-control);
}

.chatwin__findbox:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}

.chatwin__findclose {
  flex: none;
  background: none;
  border: none;
  padding: 0.125rem 0.25rem;
  font-size: 0.8125rem;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
}

.chatwin__findclose:hover { color: var(--text); }

/* Results sit exactly where the messages were, so the window keeps its
   height and nothing below it moves. */
.chatwin__results {
  padding: 0.25rem;
}

.winhit {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0.4375rem 0.5rem;
  margin-bottom: 0.125rem;
  background: none;
  border: none;
  border-radius: var(--r-control);
  cursor: pointer;
  font: inherit;
}

.winhit:hover { background: var(--surface-2); }

.winhit__top {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  align-items: baseline;
}

.winhit__who {
  font-weight: 600;
  font-size: 0.8125rem;
}

.winhit__when {
  flex: none;
  font-size: 0.75rem;
  color: var(--muted);
}

/* Two lines is enough to recognise the message; clicking opens it in the
   conversation around it. */
.winhit__text {
  font-size: 0.8125rem;
  color: var(--text-2);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.winhit__note {
  font-size: 0.75rem;
  color: var(--muted);
  margin-top: 0.125rem;
}

/* The message a search result led to, so the eye lands on it among its
   neighbours. */
.msg--found {
  background: var(--accent-soft);
  border-radius: var(--r-control);
  scroll-margin: 4rem;
}

/* A document the member of the public sent, as opposed to one a colleague
   uploaded. On a disputed claim that distinction is the whole point. */
.file__from {
  font-size: 0.75rem;
  color: var(--accent);
  background: var(--accent-soft);
  padding: 0.0625rem 0.375rem;
  border-radius: var(--r-pill);
  white-space: nowrap;
}

/* ===================== tasks grouped by milestone ===================== */

/* A heading over each run of tasks, so a milestone has visible work under it
   rather than being a checkpoint on its own in a separate panel. */
.taskgroup {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 0.75rem;
  padding: 1rem 1.125rem 0.5rem;
}

.taskgroup__name {
  font-size: 0.8125rem;
  font-weight: 700;
  color: var(--text);
}

.taskgroup__count {
  font-size: 0.75rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.taskgroup__when {
  font-size: 0.75rem;
  color: var(--faint);
  margin-left: auto;
}

/* The add row carries a title, an owner, a date and a milestone now, which is
   more than fits on one line. Title first, the rest underneath it. */
.taskadd {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.875rem 1.125rem;
  border-top: 1px solid var(--border-soft);
  background: var(--surface-2);
}

.taskadd__row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
}

.taskadd__row .field__select,
.taskadd__row .field__input {
  flex: 1 1 8rem;
  width: auto;
  min-width: 0;
}

.taskadd__row .button {
  flex: 0 0 auto;
  margin-left: auto;
}

/* ====================================================================
   Phone layout
   --------------------------------------------------------------------
   Everything above this point was drawn for a wide screen and then made
   to survive a narrow one. This block is the narrow screen on its own
   terms. It is last in the file on purpose: these selectors weigh the
   same as the ones they correct, so order is what decides.

   The audit that produced it, at 390px across every screen: no
   horizontal overflow left, but 384px of the 844px screen was spent
   before the first row of content, seventeen kinds of control were
   under the 44px a finger needs, and thirty-two kinds of text were
   under 13px — eleven of them at 10 or 11.
   ==================================================================== */

@media (max-width: 860px) {
  /* ---- 1. the page header ----
     The bell, the search box and the create button each took a line of
     their own: 116px of stacked controls that read as three unrelated
     things. One row, with search taking whatever is left over. */
  .topbar {
    padding: 0.75rem 1rem 0.875rem;
    gap: 0.625rem;
  }

  .topbar__left {
    flex: 1 1 100%;
  }

  .topbar__actions {
    flex: 1 1 100%;
    flex-wrap: nowrap;
    gap: 0.5rem;
    /* Without this the row cannot shrink below its contents and the create
       button's caret hangs 20px off the right of the screen. */
    min-width: 0;
  }

  /* The bell and the create button are fixed sizes; search takes whatever
     is left, however little that is. */
  .topbar__actions .searchtrigger {
    flex: 1 1 0;
    min-width: 0;
  }

  .topbar__actions .createsplit,
  .topbar__actions .bellwrap {
    flex: 0 0 auto;
  }

  /* Squeezed between the bell and the create button, "Search or jump to…"
     broke onto a second line and pushed the whole bar taller. */
  .searchtrigger,
  .searchtrigger * {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* A sentence you read once on your first visit, on every screen, for
     45px each time. */
  .pagelede {
    display: none;
  }

  /* There is no Ctrl key on a phone. */
  .searchtrigger__hint {
    display: none;
  }

  .searchtrigger__long {
    display: none;
  }

  .searchtrigger__short {
    display: inline;
  }

  .topbar__title {
    font-size: 1.375rem;
  }

  /* ---- 2. a floor under the type ----
     Eleven pixels is a size you squint at. Nothing on a phone goes below
     twelve, and the things that carry meaning — status pills, row
     titles — come up further than that. */
  .eyebrow,
  .panel__eyebrow,
  .fact__label,
  .scopelabel,
  .assignbox__label,
  .assignpick__label,
  .chanlist__group,
  .msg__when,
  .daysep,
  .reqrow__meta,
  .rechead__ref,
  .tile__label,
  .livedot,
  .statcard__note,
  .statcard__change,
  .agendaitem__sub,
  .agendaitem__time,
  .navitem__count,
  .personcard__meta,
  .taskpanelhead__sub,
  .bigfig__label,
  .chathead__sub,
  .deptblock__count,
  .deptchip,
  .modscope__all,
  .unreadpill,
  .bellbadge,
  .chatfab__badge,
  .healthcell__label,
  .projectcard__meta,
  .avatar,
  .crumbs {
    font-size: 0.75rem;
  }

  /* A task title cut off mid-word tells you nothing: 127px of "Draft
     memorandum for the Sangguniang Panlalawigan" was being hidden behind
     an ellipsis. Two lines on a phone rather than one. */
  .taskrow__title,
  .taskrow__title > span {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  /* A status is the second thing you read on any row. */
  .pill {
    font-size: 0.75rem;
    padding: 0.1875rem 0.625rem;
  }

  /* Row titles are what the whole list is for. */
  .reqrow__title,
  .row__link,
  .chanitem__name {
    font-size: 0.9375rem;
  }

  .reqrow__bottom {
    gap: 0.375rem 0.5rem;
  }

  /* ---- 3. targets a finger can hit ----
     Seventeen classes were under 44px; the row link — the way you open
     any record anywhere in the app — was 16. */
  .row__link,
  .crumbs__link {
    min-height: 44px;
    display: flex;
    align-items: center;
    text-align: left;
  }

  /* "Open in map" on a request's location was 17px tall. It is on a line
     of its own, so it can take the height without pushing anything. */
  .tile__maplink {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  .button,
  .button--ghost,
  .linkbutton {
    min-height: 40px;
  }

  .button--small {
    min-height: 36px;
  }

  /* The controls you reach for constantly get the full 44px. The rest get
     40, which is the compromise between a target you can hit and a toolbar
     that does not become a wall. */
  .navitem,
  .searchtrigger,
  .filters__select,
  .createsplit__main,
  .createsplit__caret,
  .chanitem {
    min-height: 44px;
  }

  .taskpanelhead__open,
  .deptchip {
    min-height: 40px;
  }

  .bellbtn {
    min-width: 44px;
    min-height: 44px;
  }

  .field__input,
  .field__select,
  .field__textarea {
    min-height: 44px;
  }

  /* The box itself stays a box; what grows is the area around it, so the
     whole line is the target rather than a 20px square. */
  .checkbox,
  input[type='checkbox'] {
    width: 20px;
    height: 20px;
  }

  .checkline {
    min-height: 44px;
    align-items: center;
    padding: 0.25rem 0;
  }

  .checkline input {
    margin-top: 0;
  }

  /* A 12rem label column beside the chips leaves about 100px for chips that
     are 94px wide before their border: on a 320px screen they ran off the
     edge. The label goes above them instead. */
  .modscope__row {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.375rem;
  }

  .deptchip {
    max-width: 100%;
  }

  /* ---- 4. one rhythm per panel ----
     The panel's name and its view switcher were fighting over one line,
     and the filter chips wrapped into a ragged second row that read as
     an accident. Each gets its own full-width line, and a strip of
     chips scrolls rather than wrapping. */
  .panel__head {
    padding: 1rem 1rem 0.75rem;
    gap: 0.625rem;
  }

  .panel__head > * {
    flex: 1 1 100%;
    min-width: 0;
  }

  /* Three things — the scope chips, the department picker and the count —
     do not fit on one line, and squeezing them onto one collapsed the chips
     to nothing. Two lines, each with a job: the chips, then the picker with
     the count at the end of it. */
  .filters {
    padding: 0.625rem 1rem;
    gap: 0.5rem;
    flex-wrap: wrap;
    align-items: center;
  }

  .filters > .segmented {
    flex: 1 1 100%;
  }

  .segmented::-webkit-scrollbar {
    display: none;
  }

  .segmented {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    min-width: 0;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    /* Says there is more to the right without needing a scrollbar. */
    mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
  }

  .segmented > * {
    flex: 0 0 auto;
  }

  /* Two to a row (department and category, then sort beside the count),
     rather than one each: four full-width rows pushed the first request
     below the fold. */
  .filters__select {
    flex: 1 1 calc(50% - 0.375rem);
    min-width: 0;
    /* iOS Safari zooms into a select under 16px too, not only inputs. */
    font-size: 1rem;
  }

  /* The search box gets a row of its own on a phone. */
  .filters__search {
    flex-basis: 100%;
  }

  .filters__count {
    flex: 0 0 auto;
    margin-left: auto;
    font-size: 0.8125rem;
  }

  /* The priority pill sat in a flex row that stretched it to the height of
     a title wrapping onto three lines, turning a small label into a large
     oval blob. */
  .reqrow__top {
    align-items: flex-start;
  }

  .reqrow__top > .pill {
    flex: 0 0 auto;
    align-self: flex-start;
  }

  /* The view bar on Projects holds a .segmented of its own. A scroller can
     only scroll if its container lets it shrink; without this the strip
     pushed the bar out to 466px and the panel, which clips rather than
     scrolls, cut the end off it. */
  .viewbar,
  .viewbar__left,
  .viewbar__right {
    min-width: 0;
    padding-left: 1rem;
    padding-right: 1rem;
  }

  .viewbar__left,
  .viewbar__right {
    flex: 1 1 100%;
  }

  .viewbar__left > .segmented,
  .viewbar__right > .segmented {
    flex: 1 1 auto;
    min-width: 0;
  }

  /* ---- 5. room to breathe ----
     Panels ran edge to edge with the content padding, so the page was a
     single grey seam from top to bottom. */
  /* 5.5rem at the foot: room for the bottom navigation bar (4rem), which
     now covers the last 4rem of the screen. It was for the chat button. */
  .content {
    padding: 1rem 0.875rem calc(5.5rem + env(safe-area-inset-bottom));
  }

  .panel + .panel,
  .panel + .split,
  .split + .panel {
    margin-top: 0.875rem;
  }

  .panel__body {
    padding-bottom: 0.25rem;
  }

  /* The chat button floats over the bottom-right corner of whatever is
     last on the page. The extra bottom padding above keeps the final row
     clear of it. */
}

@media (max-width: 620px) {
  /* Two figures side by side is the most that stays readable; four
     across turned every number into a column of single digits. */
  .statgrid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.625rem;
  }

  /* Compact figures: the four cards were about 170px tall each, two rows
     of them a full screen before My work appeared (4 October 2026). The
     icon goes and the padding tightens; number, label and note stay. */
  .statcard {
    padding: 0.75rem 0.875rem;
  }

  .statcard .statcard__icon {
    display: none;
  }

  .statcard .statcard__value {
    font-size: 1.5rem;
  }

  .healthrow {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* A two-up split is a stack. */
  .split,
  .split--dash {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Two columns of read-only tiles on a 358px screen meant a field's value
     decided the column width; "Farm-to-market road, Valencia" pushed the
     grid past the edge of the page. One column, and each track capped. */
  .tiles {
    grid-template-columns: minmax(0, 1fr);
  }

  /* These rows hold a date, a title and a status, in that order, and every
     row is its own grid — so each one sized its columns to its own content
     and no two agreed. On the meetings list that left one date squeezed to
     nothing and printed across the title next to it. One column: the three
     parts stack in reading order and every row in the list matches. */
  .row,
  .row--plain,
  .row--when {
    grid-template-columns: minmax(0, 1fr);
    justify-items: start;
    gap: 0.25rem;
    padding: 0.75rem 0.875rem;
  }

  /* The text block fills the column, so a long line under the title ends
     in "…": with justify-items: start it took its own width instead, and a
     ready reply's preview ran to 732px inside a 305px row, chopped by the
     panel edge with no ellipsis (found 4 October 2026). */
  .row > .row__main {
    justify-self: stretch;
  }

  .row__when,
  .row__where {
    white-space: normal;
  }

  /* On its own line, so it should be the width of that line: a target the
     width of its own text is a target you have to aim at. */
  .row .row__link {
    min-height: 40px;
    width: 100%;
    padding: 0.25rem 0;
  }

  .row {
    min-height: 44px;
  }

  /* Stacked, the categories table's heading row was six labels in a
     column above the first category, matched to nothing. Each value
     carries its heading instead. */
  .row--cat.rowhead {
    display: none;
  }

  .row--cat [data-label]::before {
    content: attr(data-label) ': ';
    color: var(--muted);
    font-weight: 500;
  }

  .row--cat .catpub[data-label]::before {
    content: attr(data-label);
    font-size: 0.75rem;
  }
}

/* ---- replies the requester can see ----
   Marked in the conversation, because everything else there is internal,
   and the composer changes colour in reply mode so nobody sends a note to
   the public by mistake. */
.comment__public {
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 999px;
  padding: 0.0625rem 0.5rem;
}

/* Three classes, because `.thread .comment` (two) removes every side border
   and silently won over a plain `.comment--public`. The padding gives back
   the border's 3px so the text stays aligned with its neighbours. */
.thread .comment.comment--public {
  border-left: 3px solid var(--accent);
  padding-left: calc(1.125rem - 3px);
}

.composer__mode {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
  margin-bottom: 0.5rem;
  min-width: 0;
}

.composer--public .field__textarea {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* ===================== password box ===================== */

/* Show / Hide sits inside the box, on the right; the input keeps room for
   it so a long password never runs underneath the word. */
.pwbox {
  position: relative;
  display: block;
}

.pwbox__input {
  padding-right: 4.25rem;
}

.pwbox__toggle {
  /* Top and bottom rather than a fixed height: the box is 35px on a
     laptop and 44px on a phone, and a fixed 36px stuck out of the first. */
  position: absolute;
  top: 3px;
  bottom: 3px;
  right: 3px;
  min-width: 44px;
  padding: 0 0.625rem;
  font-family: var(--sans);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--accent);
  background: none;
  border: none;
  border-radius: var(--r-control);
  cursor: pointer;
}

.pwbox__toggle:hover {
  background: var(--accent-soft, rgba(79, 70, 229, 0.08));
}

/* ===================== ready-made replies ===================== */

/* The menu opens upwards from the button under the reply box, like the
   @ menu, so it does not run off the foot of the panel. */
.replypick {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

.replymenu {
  position: absolute;
  left: 0;
  bottom: calc(100% + 6px);
  z-index: 60;
  width: min(22rem, calc(100vw - 2rem));
  max-height: 18rem;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-pop);
  padding: 0.25rem;
}

.replymenu__item {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  width: 100%;
  min-height: 2.75rem;
  padding: 0.5rem 0.625rem;
  font-family: var(--sans);
  text-align: left;
  background: none;
  border: none;
  border-radius: var(--r-control);
  cursor: pointer;
}

.replymenu__item:hover,
.replymenu__item:focus-visible {
  background: var(--bg);
}

.replymenu__title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text);
}

.replymenu__preview {
  font-size: 0.8125rem;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

.replymenu__empty {
  padding: 0.75rem;
  font-size: 0.8125rem;
  color: var(--muted);
}

.replymenu__foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.25rem 1rem;
  padding: 0.5rem 0.625rem 0.375rem;
  margin-top: 0.25rem;
  border-top: 1px solid var(--border-soft);
}

/* Settings: a reply's name, then its text, then the buttons. */
.inline-form.inline-form--stack {
  flex-direction: column;
  align-items: stretch;
}

.inline-form--stack .field__textarea {
  min-height: 6rem;
}

.row__link--static {
  cursor: default;
}

.row__link--static:hover {
  color: var(--text);
}

.linkbutton:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  text-decoration: none;
}

/* On a phone the menu opened from wherever the button had wrapped to and
   ran 3px past the right edge at 375. It spans the screen instead, just
   above the bottom bar. */
@media (max-width: 620px) {
  .replymenu {
    position: fixed;
    left: 0.75rem;
    right: 0.75rem;
    bottom: calc(4.75rem + env(safe-area-inset-bottom));
    width: auto;
    max-height: 50vh;
  }
}

/* ===================== similar open requests ===================== */

/* Under the location on a new request: open requests that look like the
   same thing (similarRequests). Indigo-edged, not amber: it asks the
   person to check, it does not say anything is wrong. */
.similar {
  margin: 0 0 1rem;
  padding: 0.75rem 0.875rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--r-control);
}

.similar[hidden] {
  display: none;
}

.similar__head {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 0.375rem;
}

.similar__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
}

.similar__item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.5rem;
  min-width: 0;
}

.similar__link {
  flex: 1 1 100%;
  min-width: 0;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--accent);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.similar__link:hover {
  text-decoration: underline;
}

.similar__meta {
  font-size: 0.75rem;
  color: var(--muted);
  min-width: 0;
  overflow-wrap: anywhere;
}

.similar .field__hint {
  margin: 0.5rem 0 0;
}

/* ===================== working hours and holidays ===================== */

/* A target's amount beside its unit: "3 [working days]". The number is
   short, the unit takes the rest. */
.amountunit {
  display: grid;
  grid-template-columns: 6rem minmax(0, 1fr);
  gap: 0.5rem;
}

.workhours__intro {
  margin: 0 0 1rem;
}

.workdays__set {
  border: none;
  margin: 0 0 1rem;
  padding: 0;
  min-width: 0;
}

/* Seven day toggles that wrap on a phone; each is a full label, so the
   word is part of the target. */
.workdays {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.375rem;
}

.workdays__day {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 2.25rem;
  padding: 0 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--r-control);
  background: var(--surface);
  font-size: 0.875rem;
  color: var(--text);
  cursor: pointer;
}

.workdays__day:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.holidays {
  margin-top: 1.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--border);
}

.holidays__list {
  margin: 0.5rem 0 1rem;
}

/* Date, name, Remove. .row.row--holiday so it outranks the general phone
   rule that stacks every .row into one column (CLAUDE.md). */
.row.row--holiday {
  display: grid;
  grid-template-columns: 8.5rem minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.75rem;
}

.holiday__date {
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  font-size: 0.875rem;
}

.holiday__name {
  min-width: 0;
  overflow-wrap: anywhere;
}

@media (max-width: 620px) {
  .row.row--holiday {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .row.row--holiday .holiday__date {
    grid-column: 1 / -1;
  }
}

/* ====================== CRM log (calls, visits, notes) ====================== */

/* The log on a contact's or company's page (fillActivityLog, 8 October
   2026): a short form, then the entries newest first. */
.crmlog__form {
  display: grid;
  gap: 0.625rem;
  padding: 0.875rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.crmlog__form .actions {
  margin-top: 0;
}

.crmlog__types {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
}

.crmlog__row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.crmlog__row > * {
  flex: 1 1 12rem;
  min-width: 0;
}

/* The outcome list shows for calls only; a class with display would
   otherwise beat the hidden attribute. */
.crmlog__row > [hidden] {
  display: none;
}

.crmlog__entry {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto;
  gap: 0.75rem;
  align-items: start;
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
}

.crmlog__entry:last-child {
  border-bottom: none;
}

.crmlog__line {
  font-size: 0.875rem;
  line-height: 1.45;
  color: var(--text-2);
}

.crmlog__subject {
  margin-top: 0.125rem;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text);
}

/* Words as typed: line breaks kept, and a long address or link wraps
   instead of widening the page. */
.crmlog__body {
  margin: 0.25rem 0 0;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--text);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.crmlog__actions {
  display: flex;
  gap: 0.875rem;
  margin-top: 0.375rem;
}

/* On a phone the time goes under the words rather than squeezing them;
   boxes at 16px so iOS does not zoom in on them. */
@media (max-width: 620px) {
  .crmlog__entry {
    grid-template-columns: 28px minmax(0, 1fr);
  }

  .crmlog__entry > .event__when {
    grid-column: 2;
  }

  .crmlog__form .field__textarea,
  .crmlog__form .field__input,
  .crmlog__form select {
    font-size: 1rem;
  }
}

/* ============ settings pages in groups (9 October 2026) ============
   Settings and Account: the groups in a list down the side, one group
   on the page at a time. Settings was one column of fifteen panels. The
   group's panels stop at 64rem: a form across a 1,900px page is hard to
   read. On a phone the list is a row of rounded choices above. */
.setlayout {
  display: grid;
  grid-template-columns: 13.5rem minmax(0, 1fr);
  gap: 1.5rem;
  align-items: start;
}

.setlayout__side {
  position: sticky;
  top: 0.75rem;
  display: grid;
  gap: 1rem;
  min-width: 0;
}

.setlayout__nav {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  padding: 0.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-sm);
}

.setlayout__link {
  min-height: 2.25rem;
  padding: 0.5rem 0.75rem;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--text-2);
  font-family: var(--sans);
  font-size: 0.875rem;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}

.setlayout__link:hover {
  background: var(--neutral-soft);
  color: var(--text);
}

.setlayout__link--on,
.setlayout__link--on:hover {
  background: var(--accent-soft);
  color: var(--accent-dark);
  font-weight: 600;
}

.setlayout__main {
  min-width: 0;
  max-width: 64rem;
}

/* The pointer panel under the list is narrow: its text wraps. */
.setlayout__side .panel {
  margin: 0;
}

/* Across the top below 1180px as well as on a phone: beside the list,
   at 1024 the request categories table had 0px for its department and
   "picked up by" columns. */
@media (max-width: 1180px) {
  .setlayout {
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
  }

  .setlayout__side {
    position: static;
    display: contents;
  }

  .setlayout__nav {
    flex-direction: row;
    overflow-x: auto;
    padding: 0.25rem;
    border-radius: var(--r-pill);
    scrollbar-width: thin;
  }

  .setlayout__link {
    flex: none;
    white-space: nowrap;
    border-radius: var(--r-pill);
  }

  /* The pointer panel after the group's panels, not between the list
     and them. */
  .setlayout__side > .panel {
    order: 2;
  }
}

/* Account, Display, Sections: one row per section, its place, its name,
   and Up and Down. */
.navorder {
  list-style: none;
  margin: 0.75rem 0;
  padding: 0;
  max-width: 28rem;
}

.navorder__item {
  display: grid;
  grid-template-columns: 1.75rem minmax(0, 1fr) auto auto;
  gap: 0.5rem;
  align-items: center;
  padding: 0.375rem 0;
  border-bottom: 1px solid var(--border-soft);
}

.navorder__item:last-child {
  border-bottom: none;
}

.navorder__num {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
  text-align: right;
}

.navorder__name {
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--text);
}

/* The bottom bar's four, set apart on the list by a firmer line. */
.navorder__item:nth-child(4) {
  border-bottom-color: var(--border-strong);
}

/* Account's side list: "You", then "Organisation" for those who look
   after its settings. */
.setlayout__heading {
  padding: 0.625rem 0.75rem 0.25rem;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.setlayout__heading:first-child {
  padding-top: 0.25rem;
}

@media (max-width: 1180px) {
  /* In the row across the top the headings would be orphan words: the
     choices read in order without them. */
  .setlayout__heading {
    display: none;
  }
}

/* The deals list: deal, status, contract value, monthly, renews. */
.row.row--deal {
  grid-template-columns: minmax(0, 1fr) 8.5rem 8rem 7.5rem 7rem;
}

/* The pill its own width, not its column's. */
.row.row--deal > .pill {
  justify-self: start;
}

/* On a phone: the name across the top, then status and value, then
   monthly and renewal. Two classes and a third to outrank the general
   phone rule that stacks every .row (see the landmine). */
@media (max-width: 620px) {
  .rows .row.row--deal {
    grid-template-columns: minmax(0, 1fr) auto;
    justify-items: stretch;
  }

  .rows .row.row--deal > .row__link {
    grid-column: 1 / -1;
  }

  .rows .row.row--deal.rowhead {
    display: none;
  }
}

/* Boards (9 October 2026): the whole card opens its record, and the
   title is a button for the keyboard. Pointer, not grab: a click is what
   most people do with a card, and it still drags. */
.card--opens,
.oppcard.card--opens {
  cursor: pointer;
}

button.card__title {
  width: 100%;
  padding: 0;
  border: none;
  background: none;
  font-family: var(--sans);
  color: var(--text);
  text-align: left;
}

.card--opens:hover .card__title,
.card--opens:hover .oppcard__title {
  color: var(--accent);
}

/* Saving after a move: the card is already where it was dropped. */
.card--saving {
  opacity: 0.7;
}

/* Paused (waiting on the requester, on hold): reached, so the line into
   it is green, but grey with pause bars, not indigo, which means work
   is moving (the colour rules). */
.stagetrack__step--paused::before {
  background: var(--ok);
}

.stagetrack__step--paused .stagetrack__dot {
  border-color: var(--muted);
  background: var(--surface);
  color: var(--muted);
  box-shadow: 0 0 0 4px var(--neutral-soft);
}

.stagetrack__step--paused .stagetrack__name {
  color: var(--text);
}

/* List rows that open their record anywhere (rowOpens). */
.row--opens {
  cursor: pointer;
}

.row--opens:hover .row__link {
  color: var(--accent);
}

/* ============ start-up screen (index.html, 9 October 2026) ============
   The mark in the middle of the screen, "Loading…" under it. The full
   height of the screen on a phone too (dvh: the visible height, without
   the browser's own bars). A slow breath on the mark says it is working;
   not for anyone who has asked for less motion. */
.bootscreen {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 1rem;
  background: var(--bg);
  box-sizing: border-box;
}

.bootscreen__mark {
  display: block;
  border-radius: 16px;
  box-shadow: var(--shadow-md);
  animation: bootscreen-breathe 1.6s ease-in-out infinite;
}

.bootscreen__text {
  margin: 0;
  font-family: var(--sans);
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--muted);
}

@keyframes bootscreen-breathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(0.94); }
}

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

/* ============ importing contacts (9 October 2026) ============ */
.importfile {
  display: block;
  margin: 0.75rem 0 0.5rem;
  font-family: var(--sans);
  font-size: 1rem;
  max-width: 100%;
}

.importmap {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
  gap: 0 1.25rem;
  padding: 1.125rem 1.125rem 0;
}

.importmap__note {
  padding: 0 1.125rem 1.125rem;
}

.importsum {
  margin: 0 0 1rem;
  padding-left: 1.125rem;
  font-size: 0.9375rem;
  color: var(--text-2);
  line-height: 1.6;
}

.importsum__add {
  font-weight: 600;
  color: var(--text);
}

.importprev {
  margin: 0.375rem 0 1rem;
}

.importdone {
  margin-top: 1rem;
  padding: 1rem 1.125rem;
  border: 1px solid var(--border);
  border-left: 3px solid var(--ok);
  border-radius: var(--r-control);
  background: var(--surface-2);
}

.importdone__title {
  margin: 0 0 0.75rem;
  font-weight: 600;
  color: var(--text);
}

/* "Times are Manila time." beside the calendar's views, when the viewer
   is in another zone. */
.viewbar__note {
  margin: 0 0 0 auto;
  align-self: center;
}

/* ============ tags (9 October 2026) ============
   A row under a contact's or company's summary: the tags as chips, each
   with a cross, and a box to add one. Neutral chips: a tag is a label,
   not a status, so it takes none of the status colours. */
.tagrow {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--border-soft);
}

.tagrow__label {
  font-size: 0.75rem;
  color: var(--muted);
  margin-right: 0.25rem;
}

.tagrow__none {
  font-size: 0.875rem;
  color: var(--muted);
}

.tagchip {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  max-width: 100%;
  padding: 0.1875rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--neutral-soft);
  color: var(--text);
  font-size: 0.8125rem;
  font-weight: 500;
  overflow-wrap: anywhere;
}

.tagchip--small {
  padding: 0.0625rem 0.4375rem;
  font-size: 0.75rem;
}

.tagchip__x {
  display: inline-flex;
  width: 1.125rem;
  height: 1.125rem;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}

.tagchip__x:hover {
  background: var(--surface);
  color: var(--text);
}

.tagchip__x svg {
  width: 100%;
  height: 100%;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.5;
  stroke-linecap: round;
}

.tagrow__input {
  width: 9rem;
  min-width: 0;
  padding: 0.25rem 0.5rem;
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--text);
  font-family: var(--sans);
  font-size: 0.8125rem;
}

.tagrow__msg {
  flex-basis: 100%;
  font-size: 0.8125rem;
  color: var(--text-2);
}

.tagchips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin-top: 0.25rem;
}

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


/* 16px on a phone: smaller, iPhone Safari zooms in on the box. */
@media (max-width: 860px) {
  .tagrow__input {
    font-size: 1rem;
  }
}

/* Deal line items (9 October 2026): Edit and Remove side by side, the
   editor as a small form in the list. On a phone each item is its
   name over its figures. */
.lineitem__acts {
  display: flex;
  gap: 0.375rem;
  justify-content: flex-end;
}

.lineedit {
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--border-soft);
  background: var(--surface-2);
}


/* ============ attachments: thumbnails and the pop-up (9 October 2026) ====
   Each file row starts with a thumbnail: the photo itself, or a tile with
   the file's kind. The thumbnail and the name open the file over the page
   (showFile), as Open does. */
.file__thumb {
  flex: none;
  width: 3rem;
  height: 3rem;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-control);
  background: var(--surface-2);
  overflow: hidden;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.file__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.file__thumb:hover,
.file__thumb:focus-visible {
  border-color: var(--accent);
}

/* The name as a button: the plain .file__name rule (flex 1, ellipsis)
   still applies. */
.file__namebtn {
  padding: 0;
  border: none;
  background: none;
  color: var(--text);
  font: inherit;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}

.file__namebtn:hover {
  color: var(--accent);
  text-decoration: underline;
}

/* A file's kind in letters, for files that are not pictures. Neutral for
   every kind: each colour means one thing in Macsen (red is Urgent, green
   is done), and a file's kind is neither. */
.filebadge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.25rem;
  padding: 0.125rem 0.25rem;
  border-radius: 4px;
  background: var(--neutral-soft);
  color: var(--text-2);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

/* A PDF in the pop-up: as large as the screen allows. */
.photoview__frame--doc {
  width: min(100%, 60rem);
  height: 100%;
}

.photoview__doc {
  flex: 1;
  width: 100%;
  min-height: 0;
  border: none;
  border-radius: var(--r-control);
  background: var(--surface);
}

/* Any other file: its tile, name and size, and why it is not shown. */
.photoview__card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  width: min(100%, 24rem);
  padding: 2rem 1.5rem;
  border-radius: var(--r-card);
  background: var(--surface);
  color: var(--text);
  text-align: center;
}

.photoview__card .filebadge {
  min-width: 3.5rem;
  padding: 0.5rem;
  font-size: 0.9375rem;
}

.photoview__cardname {
  font-weight: 600;
  overflow-wrap: anywhere;
}

.photoview__cardmeta,
.photoview__cardnote {
  margin: 0;
  font-size: 0.875rem;
  color: var(--text-2);
}

/* A file row: thumbnail, the name over its size, then Open and Remove. */
.file:has(> .file__main) {
  display: grid;
  grid-template-columns: 3rem minmax(0, 1fr) auto;
  gap: 0.75rem;
  flex-wrap: nowrap;
}

.file__main {
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.25rem;
}

.file__main .file__name {
  max-width: 100%;
  /* Wrapped rather than cut: "inspection-repo…" said too little. */
  white-space: normal;
  overflow-wrap: anywhere;
}

.file__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.5rem;
}

.file__acts {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  align-items: stretch;
}

/* ============ chat: "Seen", typing and pins (9 October 2026) ============
   conversationExtras in app.js. "Seen" sits under the latest message when
   it is your own; the typing line above the message box; the pinned bar
   above the conversation. Grey text throughout: none of these is a
   status in the colour rules. */
.seen {
  padding: 0.125rem 0.75rem 0.375rem;
  text-align: right;
  font-size: 0.75rem;
  color: var(--muted);
}

.seen__btn {
  padding: 0;
  border: none;
  background: none;
  color: var(--muted);
  font: inherit;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.seen__btn:hover {
  color: var(--accent);
}

.seen__list {
  margin-top: 0.25rem;
  overflow-wrap: anywhere;
}

.typing {
  min-height: 1.25rem;
  padding: 0 0.75rem;
  font-size: 0.75rem;
  font-style: italic;
  color: var(--muted);
}

.typing:empty {
  min-height: 0;
}

.pinbar {
  border-bottom: 1px solid var(--border-soft);
  background: var(--surface-2);
  font-size: 0.8125rem;
}

.pinbar__toggle {
  display: block;
  width: 100%;
  padding: 0.5rem 0.75rem;
  border: none;
  background: none;
  color: var(--text);
  font: inherit;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}

.pinbar__toggle:hover {
  color: var(--accent);
}

.pinbar__list {
  max-height: 14rem;
  overflow-y: auto;
  padding: 0 0.5rem 0.5rem;
}

.pinbar__note {
  margin: 0;
  padding: 0 0.75rem 0.5rem;
  font-size: 0.75rem;
  color: var(--muted);
}

.pinitem {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.5rem;
  align-items: start;
  padding: 0.375rem 0.25rem;
  border-top: 1px solid var(--border-soft);
}

.pinitem__show {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  min-width: 0;
  padding: 0;
  border: none;
  background: none;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.pinitem__who {
  font-size: 0.75rem;
  color: var(--muted);
}

.pinitem__text {
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow-wrap: anywhere;
}

.pinitem__show:hover .pinitem__text {
  color: var(--accent);
}

.pinitem__unpin {
  padding: 0.125rem 0.375rem;
  border: 1px solid var(--border);
  border-radius: var(--r-control);
  background: var(--surface);
  color: var(--text-2);
  font: inherit;
  font-size: 0.75rem;
  cursor: pointer;
}

/* A pinned message carries a mark beside its time; a window's grouped
   message has no head, so the mark goes above its text. */
.msg--pinned .msg__body > .msg__head::after,
.msg--pinned .msg__body:not(:has(> .msg__head))::before {
  content: '\1F4CC  Pinned';
  margin-left: 0.5rem;
  font-size: 0.6875rem;
  color: var(--muted);
}

.msg--pinned .msg__body:not(:has(> .msg__head))::before {
  display: block;
  margin-left: 0;
}

/* ============ saved list views (9 October 2026) ============
   savedViewsRow in app.js: a row of their own under the built-in views,
   shown once there are any; Save view is in the filter bar; under the
   rows, what can be done with the view in use. */
.listviews--saved {
  align-items: center;
  padding-top: 0.5rem;
}

.listviews__label {
  flex: none;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
}

.listview__shared {
  padding: 0.0625rem 0.375rem;
  border-radius: var(--r-pill);
  background: var(--neutral-soft);
  color: var(--text-2);
  font-size: 0.6875rem;
  font-weight: 600;
}

.savedbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 1rem;
  padding: 0.5rem 1.25rem 0;
  font-size: 0.8125rem;
}

.savedbar__label {
  min-width: 0;
  color: var(--text-2);
  overflow-wrap: anywhere;
}

.savedbar .notice {
  flex-basis: 100%;
  margin: 0.25rem 0 0;
}

.savedform {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.5rem 1rem;
  width: 100%;
}

.savedform .field {
  flex: 1 1 16rem;
  min-width: 0;
  margin: 0;
}

.savedform__share {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 2.25rem;
  color: var(--text-2);
}

.savedform__actions {
  display: flex;
  gap: 0.5rem;
}

.savedform__note {
  flex-basis: 100%;
  margin: 0;
  color: var(--text-2);
  font-size: 0.8125rem;
}

.savedform__note:empty {
  display: none;
}
