/* ============================================================================
   Ridgeline — one visual language.

   The four source apps each had their own: KnockMap's near-black slate,
   KnockReport's shingle-and-chalk, Knock Board's cream-on-grey, KnockLedger's
   own again. Keeping four would make one product feel like four bookmarks.

   This takes KnockMap's dark ground (it has to survive direct sunlight on a
   roof) and Knock Board's condensed display type (numbers need to read at a
   glance from a truck seat), and applies them everywhere.
   ========================================================================= */

:root {
  /* colour — every colour in the app is one of these */
  --bg:        #0B0F14;
  --surface:   #141A21;
  --surface-2: #1B222B;
  --line:      rgba(233,238,244,.11);   /* dividers only — decorative */
  --line-strong: rgba(233,238,244,.38); /* the edge of a control: 3.25:1 on both surfaces */
  --track:     rgba(233,238,244,.08);   /* progress and funnel tracks */

  --text:      #E9EEF4;
  --dim:       #8A97A6;                 /* 5.9:1 on --surface: meta, secondary text */
  --faint:     #758495;                 /* 4.6:1 on --surface: labels, eyebrows. Was #5A6675 (3.0:1) */

  --accent:    #38BDF8;
  --accent-soft: rgba(56,189,248,.14);  /* selected nav, row hover */
  --ink-on-accent: #06202C;
  --gold:      #E0AE4B;
  --ink-on-gold: #241A06;
  --good:      #4ADE80;
  --bad:       #F26464;                 /* 5.2:1 on --surface-2 (a menu's Delete). Was #EF4444 (4.3:1) */
  --ink-on-bad: #1A0606;                /* 6.3:1 on --bad: an armed Discard's words */
  --warn:      #FBBF24;
  --pin-ink:   #000;
  --paper:     #fff;
  --scrim:     rgba(0,0,0,.55);
  --focus:     var(--accent);
  --good-soft: rgba(74,222,128,.4);
  --shadow-2:  -8px 0 30px rgba(0,0,0,.35);
  --text-shadow: 0 0 2px rgba(0,0,0,.9), 0 0 4px rgba(0,0,0,.75), 0 1px 2px rgba(0,0,0,.9);
  --stamp-ink: #12305c;               /* value ink on the printed contract page */
  /* --stage-<id> and --prio-<n> are written here at boot by app.js from model.js */

  /* type */
  --disp: 'Oswald', system-ui, sans-serif;
  --body: 'IBM Plex Sans', system-ui, -apple-system, sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, Menlo, monospace;
  --fs-xs: 11px; --fs-sm: 12px; --fs-md: 13.5px; --fs-base: 15px; --fs-lg: 17px; --fs-xl: 20px;
  --fs-hero: 34px; --fs-hero-lg: 40px;

  /* space, shape, motion, size */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px;
  --r-sm: 8px; --r-md: 12px; --r-lg: 16px; --r-pill: 999px;
  --shadow-1: 0 2px 7px rgba(0,0,0,.6);
  --t-fast: .12s; --t-base: .2s; --t-slow: .3s;
  --hit: 44px;                          /* minimum touch target on coarse pointers */
  --rail: 78px;                         /* wide enough for the longest nav label */
  /* the lead page and the Board */
  --rail-bg:   var(--surface);
  --rail-ink:  var(--faint);
  --rail-on-bg: var(--accent-soft);
  --rail-on-ink: var(--accent);
  --rail-edge: var(--line);
  --panel-rule: rgba(56,189,248,.55);   /* the coloured top edge of a panel */
  --figure:    var(--gold);             /* counts and money on the Board: AccuLynx's orange numbers */
  --sc-off:    #334150;                 /* a milestone not reached yet */
  --sc-off-ink:#A9B4C1;                 /* 5.0:1 on --sc-off. Was #8A97A6 (3.5:1) */
  --conn:      rgba(233,238,244,.16);
  --conn-on:   rgba(233,238,244,.55);
  --go:        #2E7D32;                 /* Advance Job: white on it is 5.1:1 */
  --ink-on-go: #FFFFFF;
  --shadow-fab: 0 4px 14px rgba(0,0,0,.28);
  /* a priority as a WORD; the dot uses --prio-<n> itself */
  --prio-word-1: var(--prio-1); --prio-word-2: var(--prio-2); --prio-word-3: var(--prio-3);
  /* communications: a search hit's ground (--text on it at AA), the rail's
     unread pill, a mention, and the eight tag dots (3:1 on the surface, and
     always beside the tag's name) */
  --hl:        rgba(251,191,36,.34);
  --badge-bg:  var(--accent);
  --badge-ink: var(--ink-on-accent);
  --mention-bg: var(--accent-soft);
  --tag-slate: #94A3B8; --tag-blue: #60A5FA; --tag-green: #4ADE80; --tag-amber: #FBBF24;
  --tag-red:   #F87171; --tag-violet: #A78BFA; --tag-teal: #2DD4BF; --tag-rose: #FB7185;
  color-scheme: dark;
}

/* Light — the default. Office software is light, and so is AccuLynx; the
   dark palette above stays one switch away in Setup. Every value is a
   token swap: no rule below knows which theme it is in. */
:root[data-theme="light"] {
  --bg:        #EEF1F5;
  --surface:   #FFFFFF;
  --surface-2: #F4F6F9;
  --line:      rgba(15,23,42,.11);
  --line-strong: rgba(15,23,42,.46);    /* 3:1 against white — the edge of a control */
  --track:     rgba(15,23,42,.08);
  --text:      #1D2733;
  --dim:       #52606E;                 /* 6.4:1 on white */
  --faint:     #5F6C79;                 /* 5.4:1 on white, 4.9:1 on --surface-2 */
  --accent:    #1F68AE;                 /* 5.5:1 on white, as text and as a fill under white */
  --accent-soft: rgba(31,104,174,.10);
  --ink-on-accent: #FFFFFF;
  --gold:      #9A5B00;                 /* 5.3:1 on white */
  --ink-on-gold: #FFFFFF;
  --good:      #2B7A3B;                 /* 5.2:1 */
  --bad:       #C0262D;                 /* 5.9:1 */
  --ink-on-bad: #fff;
  --warn:      #9A5B00;
  --scrim:     rgba(15,23,42,.45);
  --good-soft: rgba(43,122,59,.25);
  --shadow-1:  0 1px 3px rgba(15,23,42,.16);
  --shadow-2:  -8px 0 30px rgba(15,23,42,.12);
  --rail-bg:   #2A5A98;                 /* AccuLynx's blue bar, down the side */
  --rail-ink:  rgba(255,255,255,.86);   /* 5.6:1 on the rail */
  --rail-on-bg: rgba(255,255,255,.18);
  --rail-on-ink: #FFFFFF;
  --rail-edge: transparent;
  --panel-rule: #2A5A98;
  --figure:    #B4530A;                 /* AccuLynx orange, darkened to 4.6:1 on white */
  --sc-off:    #D5DAE1;
  --sc-off-ink:#52606E;                 /* 4.6:1 — an unreached letter still reads */
  --conn:      #D5DAE1;
  --conn-on:   #6B7684;
  /* the priority hues are dots first; as words on white they must be darker
     (Cold was 2.5:1, Lukewarm 2.3:1) */
  --prio-word-1: #1D5FAF; --prio-word-2: #A3510A; --prio-word-3: #B42318;
  --hl:        #FFE27A;
  /* the rail is blue here: an accent pill would vanish into it */
  --badge-bg:  #FFFFFF;
  --badge-ink: #1F4E86;
  --tag-slate: #64748B; --tag-blue: #2563EB; --tag-green: #15803D; --tag-amber: #B45309;
  --tag-red:   #DC2626; --tag-violet: #7C3AED; --tag-teal: #0F766E; --tag-rose: #E11D48;
  color-scheme: light;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
/* `hidden` always wins: a class that sets display (.navbtn, .cctx, .tnew)
   would otherwise show what the markup says is hidden */
[hidden] { display: none !important; }
html, body { margin: 0; padding: 0; height: 100%; }
/* An app, not a document: no pinch or double-tap zoom on the page. The map
   still zooms — Leaflet handles its own gestures (touch-action: none). */
html { touch-action: pan-x pan-y; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
  background: var(--bg); color: var(--text);
  font-family: var(--body); font-size: 15px; line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  overscroll-behavior-y: contain;
}
button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }
button { cursor: pointer; }
a { color: var(--accent); }

/* ------------------------------------------------------------------ layout */

#app { display: flex; min-height: 100vh; min-height: 100dvh; }

/* Desktop: a rail on the left. Mobile: a bar along the bottom, because a rep
   is holding the phone one-handed and the thumb does not reach the top. */
#rail {
  width: var(--rail); flex: none; background: var(--rail-bg);
  border-right: 1px solid var(--rail-edge);
  display: flex; flex-direction: column; align-items: center;
  padding: 12px 0; gap: 4px; position: sticky; top: 0; height: 100vh; height: 100dvh;
}
#rail .logo {
  font-family: var(--disp); font-weight: 700; font-size: 17px; letter-spacing: .02em;
  color: var(--rail-on-ink); margin-bottom: 10px; line-height: 1;
  /* centred on the rail by its ink, measured: the letter-spacing after the L
     and Oswald's side bearings leave the letters 0.25px right of centre */
  margin-left: -.03em;
}
.navbtn {
  width: 68px; height: 48px; border: 0; background: none; border-radius: 10px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; color: var(--rail-ink); transition: background .15s, color .15s;
}
.navbtn svg { width: 19px; height: 19px; display: block; }
.navbtn span { font-size: 10px; letter-spacing: .04em; text-transform: uppercase; font-weight: 600; }
.navbtn:hover { color: var(--rail-on-ink); }
#rail .spacer { flex: 1; }
.navbtn[aria-current="page"], .navbtn.on { background: var(--rail-on-bg); color: var(--rail-on-ink); }

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

.topbar {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 18px; border-bottom: 1px solid var(--line);
  background: var(--bg); position: sticky; top: 0; z-index: 30;
}
.topbar h1 {
  font-family: var(--disp); font-weight: 600; font-size: 20px;
  letter-spacing: .04em; text-transform: uppercase; margin: 0; white-space: nowrap;
}
.topbar #syncnote { white-space: nowrap; }

/* A flex column, so a full-bleed child like the map can claim the remaining
   height. Without this #mapview's flex:1 resolves against nothing, and because
   #map is absolutely positioned the container collapses to zero height - the
   map initialises and even fetches tiles, but paints into a box with no height. */
.view { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; }
.pad { padding: 18px; max-width: 1100px; flex: 0 0 auto; width: 100%; }

/* ------------------------------------------------------------------ pieces */

.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; padding: 16px; margin-bottom: 14px;
}
.card-head {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 10px; margin-bottom: 12px;
}
.card h2, .card-head h2 {
  font-family: var(--disp); font-weight: 500; font-size: 13px;
  letter-spacing: .16em; text-transform: uppercase; margin: 0; color: var(--text);
}
.micro { font-size: 12px; color: var(--dim); margin: 0; }
.eyebrow {
  font-family: var(--disp); font-size: 11px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--faint); margin: 0 0 8px;
}

.hero {
  font-family: var(--disp); font-weight: 700; font-size: 40px; line-height: 1;
  margin: 0 0 10px; display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
}
.hero .unit { font-family: var(--body); font-weight: 400; font-size: 13px; color: var(--dim); letter-spacing: 0; }
.hero.gold { color: var(--gold); }
.hero.good { color: var(--good); }
.hero.bad  { color: var(--bad); }

.bar { height: 6px; background: var(--track); border-radius: 3px; overflow: hidden; margin-bottom: 8px; }
.bar > span { display: block; height: 100%; transition: width .3s ease; }
.fill-accent { background: var(--accent); }
.fill-gold   { background: var(--gold); }
.fill-good   { background: var(--good); }

.grid { display: grid; gap: 14px; }
.grid.c2 { grid-template-columns: repeat(2, 1fr); }
.grid.c3 { grid-template-columns: repeat(3, 1fr); }
.grid.c4 { grid-template-columns: repeat(4, 1fr); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  background: var(--accent); color: var(--ink-on-accent); border: 0; border-radius: 9px;
  font-family: var(--disp); font-size: 15px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; padding: 12px 16px;
}
.btn { min-height: 46px; transition: filter var(--t-fast), transform var(--t-fast), background var(--t-fast); }
/* Four intents. `.ghost` is today's outlined secondary and keeps that look until every
   call site has moved to `.secondary` (Phase 3); it then becomes the borderless one. */
.btn.secondary, .btn.ghost { background: transparent; border: 1px solid var(--line-strong); color: var(--dim); }
.btn.quiet { background: transparent; border: 1px solid transparent; color: var(--dim); }
.btn.danger { background: transparent; border: 1px solid var(--bad); color: var(--bad); }
.btn.danger:hover, .btn.danger.armed { background: var(--bad); color: var(--ink-on-bad); }
.btn.sm    { padding: 7px 11px; font-size: 12.5px; min-height: 38px; }
.btn.wide  { width: 100%; }
.btn.icon  { width: var(--hit); height: var(--hit); min-height: var(--hit); padding: 0; flex: none; position: relative; }
.btn.icon .i, .i { width: 20px; height: 20px; display: block; }
/* Disabled is readable but inert. Never opacity .4: that dims the label that explains why. */
.btn:disabled, .btn[aria-disabled="true"] { opacity: .65; cursor: not-allowed; filter: none; transform: none; }   /* --dim at .65 = 3.2:1 */
.btn.secondary:disabled, .btn.ghost:disabled, .btn.quiet:disabled { color: var(--dim); border-color: var(--line); }
.btn.is-loading { pointer-events: none; color: transparent; }
.btn.is-loading::after {
  content: ''; position: absolute; width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent; color: var(--ink-on-accent);
  animation: spin .8s linear infinite;
}
.btn.secondary.is-loading::after, .btn.ghost.is-loading::after { color: var(--dim); }
@keyframes spin { to { transform: rotate(360deg); } }

.chip {
  background: none; border: 1px solid var(--line-strong); color: var(--dim);
  border-radius: var(--r-pill); padding: 6px 11px; font-size: var(--fs-sm); font-weight: 600;
  display: inline-flex; align-items: center; gap: 6px; min-height: 36px;
  transition: filter var(--t-fast), transform var(--t-fast), background var(--t-fast);
}
.chip.on, .chip[aria-pressed="true"], .chip[aria-selected="true"] { background: var(--text); color: var(--bg); border-color: var(--text); }
.chip:disabled { opacity: .65; cursor: not-allowed; }
.chip .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.chips { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }

label.f { display: block; font-family: var(--mono); font-size: 10px; text-transform: uppercase;
  letter-spacing: .1em; color: var(--faint); margin-bottom: 5px; }
input, select, textarea {
  width: 100%; background: var(--surface-2); border: 1px solid var(--line-strong);
  border-radius: 8px; padding: 10px 11px;
}
input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
textarea { resize: vertical; min-height: 72px; line-height: 1.5; }
.field { margin-bottom: 12px; }

table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
th { text-align: left; font-weight: 500; color: var(--dim); padding: 8px 0; border-bottom: 1px solid var(--line); font-size: 12px; }
td { padding: 9px 0; border-bottom: 1px solid var(--line); }
td.n { text-align: right; font-family: var(--disp); font-size: 16px; }
/* Row separators divide rows; after the last one there is nothing to divide,
   so it reads as a stray rule floating under the list. */
tbody tr:last-child > td,
tbody tr:last-child > th { border-bottom: 0; }

/* The knob is centred rather than pinned to the top, and the track is a pill at
   any height: a phone stretches this to the 44px touch target below, and a
   top-pinned knob turned it into a rounded square with a dot in the corner. */
.tgl { width: 44px; height: 26px; border-radius: 999px; background: var(--surface-2);
  border: 1px solid var(--line-2); position: relative; flex: none; transition: background .18s; }
.tgl::after { content: ''; position: absolute; top: 50%; left: 3px; width: 20px; height: 20px;
  border-radius: 50%; background: var(--faint); transform: translateY(-50%);
  transition: transform .18s, background .18s; }
.tgl.on { background: var(--accent); border-color: var(--accent); }
.tgl.on::after { transform: translate(18px, -50%); background: var(--paper); }
.setrow { display: flex; align-items: center; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--line); }
/* Belt and braces: :last-child misses when a hidden input trails the list, and
   a rule under the final row is the "weird line" that keeps reappearing. */
.setrow:last-child, .setrow:last-of-type { border-bottom: 0; }
.setrow .lbl { flex: 1; min-width: 0; }
.setrow .lbl small { display: block; color: var(--dim); font-size: 12px; margin-top: 2px; }

.empty { color: var(--dim); font-size: 13.5px; padding: 22px 0; text-align: center; }

/* ------------------------------------------------------------- stage pills */

.stage {
  display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px;
  font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  padding: 3px 9px; border-radius: 999px; background: var(--surface-2); color: var(--dim);
}
.stage .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--stage-color, var(--dim)); }

/* --------------------------------------------------------------------- map */

/* isolation: the map's own stacking context, so Leaflet's panes (z 400+) can
   never rise above the menus (z 80) or a dialog (z 300) - which they did. */
#mapview { position: relative; flex: 1 1 auto; min-height: 340px; display: flex; flex-direction: column; isolation: isolate; }
#leafmap { position: relative; flex: 1; min-height: 0; background: var(--bg); }
.mapbar { display: flex; gap: var(--s2); padding: 10px 12px; background: var(--surface); border-top: 1px solid var(--line); flex: none; }
.mapbar .btn:first-child { flex: 1; }
/* the centre the button drops on, marked */
.reticle { position: absolute; left: 50%; top: calc(50% - 33px); width: 22px; height: 22px; transform: translate(-50%, -50%);
  pointer-events: none; z-index: 1; opacity: .8; }
.reticle::before, .reticle::after { content: ''; position: absolute; background: var(--paper); box-shadow: 0 0 2px var(--bg); }
.reticle::before { left: 50%; top: 0; width: 2px; height: 100%; transform: translateX(-50%); }
.reticle::after { top: 50%; left: 0; height: 2px; width: 100%; transform: translateY(-50%); }
.maphint { position: absolute; left: 12px; right: 12px; top: 12px; z-index: 1; margin: 0; padding: 10px 12px;
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-md); font-size: var(--fs-md); color: var(--text); }
.leaflet-container { background: var(--bg) !important; font-family: var(--body); }
.anum {
  font: 500 12px var(--body); color: var(--paper); text-align: center; white-space: nowrap;
  text-shadow: var(--text-shadow);
  pointer-events: none;
}
/* You are here: Google Maps' blue dot, white rim, pale accuracy circle. The
   blue is Google's, not the theme's — it is the one everybody already reads. */
.medot { position: relative; width: 22px; height: 22px; }
.medot span {
  position: absolute; inset: 3px; border-radius: 50%; background: #1A73E8;
  border: 3px solid #FFFFFF; box-shadow: 0 1px 4px rgba(0,0,0,.45);
}
.medot::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%; background: rgba(26,115,232,.35);
  animation: mepulse 2s ease-out infinite;
}
@keyframes mepulse { from { transform: scale(.6); opacity: .9; } to { transform: scale(2.2); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .medot::before { animation: none; opacity: 0; } }
path.mering { fill: rgba(26,115,232,.14); stroke: rgba(26,115,232,.45); }
.leaflet-addr-pane { transition: opacity .16s ease; }
.leaflet-addr-pane.afade { opacity: 0; }
.pinwrap { position: relative; width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; }
.leaflet-marker-icon:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; border-radius: 50%; }
.pin {
  width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center;
  justify-content: center; font-family: var(--body); font-weight: 600; font-size: 14px;
  color: var(--pin-ink); box-shadow: var(--shadow-1); background: var(--stage-color, var(--dim));
}
.pin.stage-lead { --stage-color: var(--stage-lead); color: var(--stage-ink-lead); }
.pin.stage-prospect { --stage-color: var(--stage-prospect); color: var(--stage-ink-prospect); }
.pin.stage-approved { --stage-color: var(--stage-approved); color: var(--stage-ink-approved); }
.pin.stage-completed { --stage-color: var(--stage-completed); color: var(--stage-ink-completed); }
.pin.stage-invoiced { --stage-color: var(--stage-invoiced); color: var(--stage-ink-invoiced); }
.pin.stage-closed { --stage-color: var(--stage-closed); color: var(--stage-ink-closed); }
.pin.stage-dead { --stage-color: var(--stage-dead); color: var(--stage-ink-dead); }
.pin .lbl { pointer-events: none; }
.padr {
  position: absolute; top: 38px; left: 50%; transform: translateX(-50%);
  font: 700 9.5px var(--mono); color: var(--paper); white-space: nowrap;
  text-shadow: var(--text-shadow); pointer-events: none;
}

/* z-index 400: above .sigpad and .dialog (both 300). "Could not save the
   signature - do not treat this as signed" was painting UNDER the pad's scrim
   with its Dismiss button unclickable. openDialog deliberately leaves #toast
   out of its inerting loop, so the toast is meant to be usable over a dialog. */
#toast {
  position: fixed; left: 50%; bottom: 92px; transform: translate(-50%, 12px);
  background: var(--text); color: var(--bg); padding: 10px 16px; border-radius: 999px;
  font-size: 13.5px; font-weight: 600; opacity: 0; pointer-events: none;
  transition: opacity .2s, transform .2s; z-index: 400; max-width: 88vw; text-align: center;
}
#toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ------------------------------------------------------------------ mobile */

@media (max-width: 780px) {
  #app { flex-direction: column; }
  #rail {
    /* top:auto matters: the desktop rule pins top:0 for the sticky sidebar, and
       a fixed element with both top:0 and bottom:0 stretches to fill the screen
       no matter what height says - which turns the nav into an invisible
       full-screen overlay that eats every tap. */
    order: 2; width: 100%; height: auto; flex-direction: row; position: fixed;
    top: auto; bottom: 0; left: 0; right: 0; border-right: 0; border-top: 1px solid var(--line);
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom)); justify-content: space-around;
    z-index: 50;
  }
  #rail .logo, #rail .spacer { display: none; }
  /* Six equal cells: the whole bar is tappable, not six islands with gaps.
     The label sizes off the viewport because the longest of them is nine
     characters and a truncated "CONTRA…" is a section nobody can name. */
  .navbtn { flex: 1; width: auto; min-width: 0; height: 46px; padding: 0 1px; }
  .navbtn span { max-width: 100%; overflow: hidden; text-overflow: ellipsis;
    font-size: min(10px, 2.45vw); letter-spacing: .01em; }
  /* The rail is fixed over the content, so the map has to stop short of it or
     its own controls sit underneath the nav. */
  #main { padding-bottom: 74px; }
  #mapview { margin-bottom: 0; min-height: 0; }
  #main > .view { padding-bottom: 0; }
  .pad { padding: 14px; }
  .grid.c3, .grid.c4 { grid-template-columns: repeat(2, 1fr); }
  .hero { font-size: 34px; }
  /* The subtitle wrapped alongside the heading and collided with it. */
  .card-head { flex-direction: column; align-items: flex-start; gap: 2px; }
  /* Label above control: side by side, "Callback number" wrapped onto two
     lines and squeezed its input. */
  .setrow { flex-wrap: wrap; }
  .setrow .lbl { flex: 1 1 100%; }
  .setrow input[type="number"], .setrow input[type="text"], .setrow input[type="tel"], .setrow input[type="email"], .setrow select {
    width: 100% !important; text-align: left !important;
  }
  .setrow .tgl { margin-left: auto; }
  .setrow:has(.tgl) .lbl { flex: 1 1 auto; max-width: calc(100% - 60px); }
  #toast { bottom: 96px; }
  /* a thread on a phone: the composer owns the bottom, so the toast goes to the top */
  body:has(.inbox.open) #toast { bottom: auto; top: calc(var(--topbar-h, 66px) + 8px); transform: translate(-50%, -12px); }
  body:has(.inbox.open) #toast.show { transform: translate(-50%, 0); }
}

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

/* ------------------------------------------------------------- e-signature */

/* Page render with a value overlay. Percentages, so one set of coordinates
   places correctly on a 375px phone and on paper. */
.cpage {
  position: relative; margin: 0 0 12px; background: var(--paper); border-radius: 6px;
  overflow: hidden;
  /* Type is sized off the PAGE, not the viewport. vw was wrong: the same phone
     width renders a different page width depending on the surrounding chrome. */
  container-type: inline-size;
}
.cpage img { width: 100%; display: block; }
.colay { position: absolute; inset: 0; }   /* 13px at the 820px design width */

/* A notice is read, not skimmed past: fixed height forces the scroll that the
   acknowledgement records. */

.notice.acked { border-color: var(--good-soft); }

.sigpad {
  position: fixed; inset: 0; z-index: 300; background: var(--scrim);
  display: flex; align-items: center; justify-content: center; padding: 18px;
}
#sigcanvas {
  display: block; margin: 12px auto 0; background: var(--paper); border-radius: 8px;
  border: 1px solid var(--line-2); touch-action: none; cursor: crosshair;
  /* a baseline to sign on, drawn by CSS so it never lands in the captured ink */
  background-image: linear-gradient(#c9ccd1, #c9ccd1); background-size: calc(100% - 40px) 1px;
  background-position: 20px 74%; background-repeat: no-repeat;
}
.sigpad { overflow-y: auto; }                 /* a phone on its side still reaches Adopt */

/* A value that will not fit its printed line. Said at fill time, because after
   execution the only options are a cut-off value or a re-signed contract. */
.toolong {
  margin: 5px 0 0; font-size: 11.5px; line-height: 1.4;
  color: var(--warn);
}
.field input.over, .field textarea.over { border-color: var(--warn); }

/* ============================================================================
   Design system — one set of controls, states and layouts for every screen.

   Rules of the road (docs/ui-conventions.md):
     - a clickable thing is a <button> or an <a>; every one has hover,
       focus-visible, active and disabled states — defined once, here;
     - literal colours, sizes, radii and durations live in :root only;
     - views compose these classes; the only inline styles left are data
       (a bar's width, a stamp's rect, a stage's colour variable).
   ========================================================================= */

/* ---------------------------------------------------------- global states */

:where(button, [role="button"], a, .chip, .tgl, .navbtn, summary):focus-visible {
  outline: 2px solid var(--focus); outline-offset: 2px;
}
.btn:hover, .chip:hover, .tgl:hover, .navbtn:hover { filter: brightness(1.12); }
.btn:active, .chip:active, .tgl:active, .navbtn:active { transform: translateY(1px); filter: brightness(.92); }
.tgl:focus-visible { outline-offset: 3px; }

/* A phone gets 44px targets; a mouse keeps the density. */
@media (pointer: coarse), (max-width: 780px) {
  .btn, .btn.sm, .tgl, .navbtn, .btn.icon, details > summary, .link.icon { min-height: var(--hit); }
  input:not([type="checkbox"]):not([type="radio"]):not([type="file"]), select { min-height: var(--hit); }
  .chip { min-height: var(--hit); padding-top: 8px; padding-bottom: 8px; }
  /* The TARGET is 44px tall, but the painted track stays 30px: stretching the
     track itself turned the switch into a lozenge with a dot floating in it.
     So the button goes transparent and ::before draws the track. */
  .tgl { height: 44px; width: 52px; background: none; border-color: transparent; }
  .tgl::before { content: ''; position: absolute; left: 0; right: 0; top: 50%; height: 30px;
    transform: translateY(-50%); border-radius: 999px; background: var(--surface-2);
    border: 1px solid var(--line-2); transition: background .18s, border-color .18s; }
  .tgl.on { background: none; }
  .tgl.on::before { background: var(--accent); border-color: var(--accent); }
  .tgl::after { width: 22px; height: 22px; left: 4px; }
  .tgl.on::after { transform: translate(22px, -50%); }
}

/* ----------------------------------------------------------------- icons */

.i { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round; flex: none; }
.i.sm { width: 16px; height: 16px; }
/* Icon-only buttons carry their label as a tooltip on hover and focus. */
.btn.icon[aria-label]:is(:hover, :focus-visible)::before {
  content: attr(aria-label); position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%);
  background: var(--text); color: var(--bg); font: 600 var(--fs-sm)/1.2 var(--body); letter-spacing: 0;
  text-transform: none; padding: 5px 8px; border-radius: var(--r-sm); white-space: nowrap; pointer-events: none; z-index: 5;
}

/* ---------------------------------------------------------------- links */

a.link, .link { color: var(--accent); text-decoration: none; font-weight: 600; display: inline-flex;
  align-items: center; gap: 4px; min-height: 28px; }
a.link:hover, .link:hover { text-decoration: underline; }
button.link { background: none; border: 0; padding: 0; font: inherit; font-weight: 600; cursor: pointer; }
button.link:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 4px; }

/* ---------------------------------------------------------------- fields */

.field .hint { margin: 5px 0 0; font-size: var(--fs-xs); color: var(--dim); line-height: 1.4; }
/* "Edit the written version", under a report text field (D-092) */

.field .err  { margin: 5px 0 0; font-size: var(--fs-xs); color: var(--warn); line-height: 1.4; }
.field.invalid input, .field.invalid select, .field.invalid textarea { border-color: var(--warn); }
/* A money or percent input: right-aligned digits with the unit fixed at the edge. */
.affix { position: relative; }
.affix input { text-align: right; padding-right: 30px; font-variant-numeric: tabular-nums; }
.affix[data-affix="$"] input { padding-left: 24px; padding-right: 11px; }
.affix::before { content: attr(data-affix); position: absolute; top: 50%; transform: translateY(-50%);
  right: 11px; color: var(--dim); font-size: var(--fs-md); pointer-events: none; }
.affix[data-affix="$"]::before { right: auto; left: 11px; }
input[type="search"] { -webkit-appearance: none; appearance: none; }
input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; height: 14px; width: 14px;
  background: var(--dim); mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E") center/contain no-repeat;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E") center/contain no-repeat; cursor: pointer; }
.field .req { color: var(--warn); margin-left: 2px; }
/* Setup rows: control widths come from here, not from inline styles. */
.setrow input[type="text"], .setrow input[type="number"], .setrow input[type="tel"], .setrow input[type="email"], .setrow select { width: 220px; flex: none; }
/* the agenda's time sits beside its switch, on a phone too */
.setrow .nphour { width: 120px !important; flex: none; }
.setrow input[type="number"] { text-align: right; }

/* ----------------------------------------------------------------- rows */

/* A list row: title with a meta line, a number over a badge on the right.
   Rows that open something are buttons in every sense: focusable, keyboard
   operable, and visibly hoverable. */
.rows th { font-weight: 600; color: var(--text); text-align: left; padding-right: 10px; font-size: var(--fs-md); }
.rows th small, .rows .meta { display: block; color: var(--dim); font-weight: 400; font-size: var(--fs-sm); margin-top: 2px; }
.rows td.r { text-align: right; white-space: nowrap; }
td.n, .rows .num { text-align: right; font-family: var(--disp); font-size: 16px; font-variant-numeric: tabular-nums; }
.n.good, .num.good { color: var(--good); }
.n.bad,  .num.bad  { color: var(--bad); }
.n.gold, .num.gold { color: var(--gold); }
.n.dim,  .num.dim  { color: var(--dim); }
.rows tr[data-open] { cursor: pointer; transition: background var(--t-fast); }
.rows tr[data-open]:hover, .rows tr[data-open]:focus-within { background: var(--accent-soft); }
.rows tr[data-open]:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.rows tr[data-open] > td:last-child { padding-right: 22px; position: relative; }
.rows tr[data-open] > td:last-child::after {
  content: ''; position: absolute; right: 4px; top: 50%; width: 8px; height: 8px;
  border-right: 2px solid var(--faint); border-top: 2px solid var(--faint); transform: translateY(-50%) rotate(45deg);
}
.rows th, .rows td { padding-left: 6px; }
.rows tr[data-open] > th:first-child { border-radius: var(--r-sm) 0 0 var(--r-sm); }
.rows tr[data-open] > td:last-child { border-radius: 0 var(--r-sm) var(--r-sm) 0; }

/* ---------------------------------------------------------- cards, tiles */

.card.flush { margin: 0; }
.card.tight { padding: 4px 16px; }
.tile .eyebrow { margin-bottom: 4px; }
.hero.tile { font-size: 32px; margin: 0; }
.hero.md { font-size: 26px; }
.eyebrow.accent { color: var(--accent); }
.eyebrow.good { color: var(--good); }
.eyebrow.gold { color: var(--gold); }

/* ---------------------------------------------------- layout utilities */

.actions { display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center; }
.actions .grow { flex: 1; }
.section { margin-top: var(--s4); }
.stack { display: flex; flex-direction: column; gap: var(--s3); }
.grid.tight { gap: var(--s2); }
.mt1 { margin-top: var(--s1); } .mt2 { margin-top: var(--s2); } .mt3 { margin-top: var(--s3); } .mt4 { margin-top: var(--s4); }
.mb2 { margin-bottom: var(--s2); } .mb3 { margin-bottom: var(--s3); }
.right { text-align: right; }

/* ----------------------------------------------------------- stage badge */

.stage.stage-lead { --stage-color: var(--stage-lead); }
.stage.stage-prospect { --stage-color: var(--stage-prospect); }
.stage.stage-approved { --stage-color: var(--stage-approved); }
.stage.stage-completed { --stage-color: var(--stage-completed); }
.stage.stage-invoiced { --stage-color: var(--stage-invoiced); }
.stage.stage-closed { --stage-color: var(--stage-closed); }
.stage.stage-dead { --stage-color: var(--stage-dead); }
.chip .dot.stage-lead { background: var(--stage-lead); }
.chip .dot.stage-prospect { background: var(--stage-prospect); }
.chip .dot.stage-approved { background: var(--stage-approved); }
.chip .dot.stage-completed { background: var(--stage-completed); }
.chip .dot.stage-invoiced { background: var(--stage-invoiced); }
.chip .dot.stage-closed { background: var(--stage-closed); }
.chip .dot.stage-dead { background: var(--stage-dead); }
.dot.prio-0 { background: var(--prio-0); } .dot.prio-1 { background: var(--prio-1); }
.dot.prio-2 { background: var(--prio-2); } .dot.prio-3 { background: var(--prio-3); }
.prio-1 { color: var(--prio-word-1); } .prio-2 { color: var(--prio-word-2); } .prio-3 { color: var(--prio-word-3); }
.badge { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase; padding: 3px 9px; border-radius: var(--r-pill);
  background: var(--surface-2); color: var(--dim); }

/* ------------------------------------------------------- tabs, segments */

.tabs { display: flex; gap: 6px; flex-wrap: wrap; }

[inert] { pointer-events: none; }

/* --------------------------------------------------------------- menu */

.menu { position: absolute; z-index: 80; min-width: 200px; background: var(--surface-2); border: 1px solid var(--line-strong);
  border-radius: var(--r-md); padding: 6px; box-shadow: var(--shadow-1); display: flex; flex-direction: column; }
.menu button { display: flex; align-items: center; gap: 10px; width: 100%; background: none; border: 0; color: var(--text);
  text-align: left; padding: 10px 12px; border-radius: var(--r-sm); font-size: var(--fs-md); min-height: 40px; }
.menu button:hover, .menu button:focus-visible { background: var(--accent-soft); outline: none; }
.menu button.danger { color: var(--bad); }
.menu hr { border: 0; border-top: 1px solid var(--line); margin: 4px 0; }

/* --------------------------------------------------------------- toast */

#toast { display: flex; align-items: center; gap: 12px; border: 1px solid transparent; }
#toast .dis { background: none; border: 0; color: inherit; font: inherit; opacity: .7; padding: 4px 6px; border-radius: var(--r-sm); cursor: pointer; min-height: 28px; }
#toast .dis:hover { opacity: 1; }
#toast.err { background: var(--surface-2); color: var(--text); border-color: var(--bad); pointer-events: auto; }
#toast .act { background: none; border: 0; color: var(--accent); font: inherit; font-weight: 700; padding: 4px 6px;
  border-radius: var(--r-sm); cursor: pointer; min-height: 28px; }
#toast.err .act { color: var(--text); }
#toast.show { pointer-events: auto; }

/* ------------------------------------------------ empty, loading, error */

.empty .btn { margin-top: 12px; }
.empty.error { color: var(--warn); }
.empty.loading { color: var(--dim); }
.skel { display: block; height: 14px; border-radius: 6px; background: linear-gradient(90deg, var(--track) 25%, var(--surface-2) 50%, var(--track) 75%);
  background-size: 200% 100%; animation: shimmer 1.2s linear infinite; }
.skel + .skel { margin-top: 8px; }
.skel.w60 { width: 60%; } .skel.w40 { width: 40%; } .skel.sq { width: 76px; height: 76px; border-radius: var(--r-sm); }
@keyframes shimmer { to { background-position: -200% 0; } }

/* -------------------------------------------------------------- dialog */

.dialog { position: fixed; inset: 0; z-index: 300; background: var(--scrim); display: flex; align-items: center;
  justify-content: center; padding: 18px; }
.dialog-card { background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-lg); padding: 18px;
  width: min(440px, 100%); }
.dialog-card h3 { font-family: var(--disp); font-size: var(--fs-lg); letter-spacing: .06em; text-transform: uppercase; margin: 0 0 6px; }
.dialog-card p { margin: 0 0 14px; color: var(--dim); font-size: var(--fs-md); }

/* ------------------------------------------------------ record pieces */

/* A field with an action beside it: the phone's call/text, the address's directions. */
.field-row { display: flex; gap: var(--s2); align-items: flex-end; }
.field-row .field { flex: 1; min-width: 0; }
.field-row .link.icon { width: var(--hit); height: var(--hit); justify-content: center; border: 1px solid var(--line-strong);
  border-radius: var(--r-sm); margin-bottom: 12px; flex: none; }
.field.flagged input { border-color: var(--warn); }
.field.flagged label.f::after { content: ' · flagged'; color: var(--warn); text-transform: none; letter-spacing: 0; }
.card.photo { display: flex; gap: 10px; align-items: flex-start; margin-bottom: var(--s2); padding: 10px; }
.photo .thumb { width: 76px; height: 76px; flex: none; }
.photo .thumb img { width: 76px; height: 76px; object-fit: cover; border-radius: 6px; background: var(--bg); display: block; }
.photo .field { margin-bottom: 6px; }
.photo > .grow { flex: 1; min-width: 0; }                  /* the fields take the card's width, not half of it */
.photo .grid.c2 { grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); }
@media (max-width: 520px) { .photo .grid.c2 { grid-template-columns: 1fr; } }
.stack.tight { gap: 6px; }
details > summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 8px; min-height: 32px; }
details > summary::-webkit-details-marker { display: none; }
details > summary::before { content: ''; width: 7px; height: 7px; border-right: 2px solid var(--faint); border-bottom: 2px solid var(--faint);
  transform: rotate(-45deg); transition: transform var(--t-fast); }
details[open] > summary::before { transform: rotate(45deg); }

/* ------------------------------------------------------------ jobs list */

/* The stage pill on a row is a menu button: same look as the badge, plus the
   states every control has. */
button.stage { cursor: pointer; border: 1px solid transparent; font-family: var(--body); min-height: 32px; padding: 4px 10px;
  transition: filter var(--t-fast), border-color var(--t-fast); }
/* The call link is a secondary target inside a 53px+ row; 36px keeps the meta
   line on one line (D-015). */
@media (pointer: coarse), (max-width: 780px) { button.stage { min-height: var(--hit); } .rows .call { min-width: 36px; height: 36px; min-height: 36px; justify-content: center; align-items: center; } }
button.stage:hover, button.stage[aria-expanded="true"] { border-color: var(--line-strong); filter: brightness(1.15); }
button.stage:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.rows .call { display: inline-flex; vertical-align: middle; margin-left: 6px; min-height: 0; padding: 4px; border-radius: var(--r-sm); }
.rows .call:hover { background: var(--accent-soft); text-decoration: none; }
.actions .field.grow { flex: 1; min-width: 200px; }

/* ---------------------------------------------------------------- board */

/* ================================================================ jobs page

   The Board's companion: one panel with the same top edge and header band,
   the pipeline's circles (count in the Board's orange, value under it) as the
   stage filter, and rows led by the same circle as the activity feed. */
.pad.jobs { max-width: 1480px; }
.jpanel { overflow: hidden; margin: 0; }

.jtabs { display: flex; overflow-x: auto; border-bottom: 1px solid var(--line); scrollbar-width: none; }
.jtabs::-webkit-scrollbar { display: none; }
.jtab {
  flex: 1 0 auto; display: flex; align-items: center; gap: 10px; min-width: 124px;
  padding: 12px 14px 9px; background: none; border: 0; border-right: 1px solid var(--line);
  border-bottom: 3px solid transparent; color: var(--text); font: inherit; text-align: left;
  cursor: pointer; transition: background var(--t-fast);
}
.jtab:last-child { border-right: 0; }
.jtab .sc { width: 34px; height: 34px; font-size: 16px; }
.jtab .sc.glyph .i { width: 16px; height: 16px; }
.jtt { display: flex; flex-direction: column; min-width: 0; }
.jtl { font-size: 12px; color: var(--dim); white-space: nowrap; }
.jtn { font: 600 20px/1.15 var(--body); color: var(--figure); }
.jtv { font-size: 12px; color: var(--text); white-space: nowrap; }
.jtab:hover { background: var(--surface-2); }
.jtab:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.jtab.on { background: var(--accent-soft); border-bottom-color: var(--accent); }
.jtab.on .jtl { color: var(--text); font-weight: 600; }
.jtab.zero .jtn, .jtab.zero .jtl { color: var(--faint); }
.jtab.zero .sc { opacity: .5; }

.jtools { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--line); }
.jfind { position: relative; flex: 1 1 260px; min-width: 0; }
.jfind .i { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--faint); pointer-events: none; }
.jfind input { min-height: 38px; padding: 7px 10px 7px 34px; background: var(--surface); border-radius: var(--r-sm); font-size: 14px; }
.jtools .viewas { min-width: 170px; }
.jwork { display: flex; align-items: center; gap: 12px; padding: 9px 12px 9px 16px; background: var(--accent-soft); border-bottom: 1px solid var(--line); font-size: 14px; }

.jhead, .jrow {
  display: grid; column-gap: 14px; align-items: center; padding: 0 16px;
  grid-template-columns: 30px minmax(0, 2.2fr) minmax(0, 1.4fr) 104px 104px 96px 176px;
}
.jhead.who, .jrows.who .jrow { grid-template-columns: 30px minmax(0, 2fr) minmax(0, 1.3fr) minmax(0, 1fr) 104px 104px 96px 176px; }
.jhead { padding-top: 7px; padding-bottom: 7px; background: var(--surface-2); border-bottom: 1px solid var(--line);
  font-size: 12px; font-weight: 600; color: var(--dim); }
.jhead .r, .jval, .jwhen, .jcreated { text-align: right; }
/* the Stage heading sits over the stage buttons, past the call column */
.jhead .st { padding-left: 40px; }
/* a heading is a button: its arrow says which way the list runs; the faint
   double arrow on the others says they sort too */
.jsort {
  display: inline-flex; align-items: center; gap: 3px; margin: -4px -6px; padding: 4px 6px;
  background: none; border: 0; border-radius: var(--r-sm); color: var(--dim);
  font: inherit; cursor: pointer; transition: background var(--t-fast), color var(--t-fast);
}
.jsort .i { width: 14px; height: 14px; opacity: .45; }
.jsort:hover { background: var(--surface); color: var(--text); }
.jsort:hover .i { opacity: .8; }
.jsort.on { color: var(--text); }
.jsort.on .i { opacity: 1; color: var(--accent); stroke-width: 2.2; }
.jsort:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.jcreated { font-size: 13.5px; color: var(--text); white-space: nowrap; }
.jcreated small { display: block; font-size: 12px; color: var(--dim); margin-top: 1px; }
.jrows { list-style: none; margin: 0; padding: 0; }
.jrow { padding-top: 11px; padding-bottom: 11px; border-bottom: 1px solid var(--line); cursor: pointer; transition: background var(--t-fast); }
.jrow:last-child { border-bottom: 0; }
.jrow:hover { background: var(--surface-2); }
.jrow:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.jcirc { width: 30px; height: 30px; font-size: 14px; }
.jmain { display: flex; flex-direction: column; min-width: 0; }
.jtitle, .jaddr, .jwho { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jtitle { font-size: 14.5px; font-weight: 600; color: var(--text); }
.jno { color: var(--accent); }
.jaddr { font-size: 13px; color: var(--dim); margin-top: 1px; }
.jmeta { display: none; }
.jstatus { min-width: 0; font-size: 13.5px; color: var(--text); }
.jstatus small { display: block; font-size: 12px; color: var(--dim); margin-top: 1px; }
.jwho { font-size: 13px; color: var(--text); }
.jval { font: 600 15px var(--body); color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap; }
.jwhen { font-size: 12.5px; color: var(--dim); white-space: nowrap; }
.jrowact { display: flex; align-items: center; gap: 4px; }
.jrow .call { display: inline-flex; align-items: center; justify-content: center; width: 36px; padding: 6px; border-radius: var(--r-sm); flex: none; }
.callgap { width: 36px; flex: none; }
.jrow .call:hover { background: var(--accent-soft); text-decoration: none; }
.jstage {
  display: inline-flex; align-items: center; gap: 4px; min-height: 32px; padding: 4px 6px 4px 12px;
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  color: var(--text); font: 600 13px var(--body); white-space: nowrap; cursor: pointer; transition: background var(--t-fast);
}
.jstage .i { width: 14px; height: 14px; color: var(--dim); transform: rotate(90deg); }
.jstage:hover, .jstage[aria-expanded="true"] { background: var(--surface-2); }
.jstage:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
@media (pointer: coarse), (max-width: 780px) {
  .jstage { min-height: var(--hit); }
  .jrow .call { min-width: 40px; min-height: 40px; }
}
/* a phone or a narrow window: circle, the job and its one meta line, then
   value over the stage. Sorting moves to the Sort menu. */
@media (max-width: 1100px) {
  .jhead { display: none; }
  .jrow, .jrows.who .jrow {
    grid-template-columns: 30px minmax(0, 1fr) auto; grid-template-areas: "circ main val" "circ main act";
    row-gap: 4px; align-items: start; padding: 12px 14px;
  }
  .jcirc { grid-area: circ; margin-top: 1px; }
  .jmain { grid-area: main; }
  .jval { grid-area: val; }
  .jrowact { grid-area: act; }
  .jstatus, .jwho, .jwhen, .jcreated, .jval.none, .callgap { display: none; }
  .jrowact { justify-content: flex-end; }
  .jmeta { display: block; font-size: 12.5px; color: var(--dim); margin-top: 3px; }
  .jtitle, .jaddr { white-space: normal; }
  .jtools { padding: 10px 14px; }
  .jfind { flex-basis: 100%; }
  .jtools .viewas { flex: 1 1 140px; min-width: 0; }
  .jtab { min-width: 0; padding: 10px 12px 8px; gap: 8px; }
  .jtab .sc { width: 28px; height: 28px; font-size: 13px; }
  .jtn { font-size: 18px; }
}

/* ---------------------------------------------------------- ceremony */

/* A stepper, not tabs: numbered, ticked when done, the current one lit; only
   finished steps are buttons you can go back to. */

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

/* review: the values as a checkable list, then the pages, pannable at a readable size */
.kv { display: grid; grid-template-columns: minmax(120px, auto) 1fr; gap: 4px 14px; font-size: var(--fs-md); margin: 0 0 12px; }
.kv dt { color: var(--dim); font-size: var(--fs-sm); padding-top: 2px; }
.kv dd { margin: 0; font-weight: 600; word-break: break-word; }
.cpages { overflow-x: auto; -webkit-overflow-scrolling: touch; border-radius: 6px; }
.cpages:focus-visible { outline: 2px solid var(--focus); }
.cpages-inner { min-width: 640px; }

/* a notice pane that has more below the fold says so */

.notice.acked .card-head .micro { color: var(--good); }

/* ------------------------------------------------------------- contracts */

/* The contract as the signer sees it, inside the app: white paper on the dark
   ground, scrollable, with the agreement docked below it. */

/* On screen the document is read, not printed: the 6pt print sizes that keep
   the paper to two sheets are unreadable on a phone. Print is untouched. */

/* prepare: the folded groups and one column on a phone */

/* The in-app document reflows to the width it actually HAS — a container query,
   not a viewport one, because this box is 52vh of a column whose width the
   viewport does not predict. The PRINTED sheet keeps its declared columns:
   pagination is fixed for ever, legibility on a phone is not. Three columns of
   material fields at 374px cut "Additional roof system" in half. */

/* Docked, so the agreement is reachable without scrolling past the prose -
   the Sign button sat 1,300px below the fold when it followed the text. */
/* FIXED, not sticky. `.view` is overflow-y:auto, which makes it the sticky
   scrollport — but the window is what actually scrolls, at every width, so a
   sticky bar inside it never docked: the agreement sat 1,251px down the page,
   the exact failure this bar exists to prevent. Fixed spans the content column,
   and the step leaves room so nothing hides behind it. */

/* A switch with its sentence beside it. Used by the sign bar and by the
   template builder — it was scoped to the sign bar and the builder's copy
   rendered as a stacked block. */
.agree { display: flex; align-items: center; gap: 12px; font-size: var(--fs-md); line-height: 1.35; }
.agree .tgl { flex: none; }

/* Picking which property a new contract is for. */
.picklist { max-height: 46vh; overflow-y: auto; margin-top: 8px; }
.pickrow {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  border-bottom: 1px solid var(--line); color: var(--text); padding: 10px 8px;
  border-radius: var(--r-sm); cursor: pointer; min-height: var(--hit);
}
.pickrow:hover, .pickrow:focus-visible { background: var(--accent-soft); outline: none; }
.pickrow .a { display: block; font-weight: 600; }
.pickrow small { color: var(--dim); font-size: var(--fs-sm); }
.badge.ok { color: var(--good); }

/* -------------------------------------------------------- template builder */

/* The uploaded page, with proposed blanks and placed fields drawn over it. */

/* A proposal, not a field: dashed, and it never becomes one on its own. */
.tfield {
  position: absolute; padding: 0; border-radius: 3px; cursor: pointer;
  font: 600 10px/1 var(--body); display: flex; align-items: center;
  min-height: 0; min-width: 0;          /* these are page geometry, not touch targets */
}
.tfield { background: rgba(74,222,128,.2); border: 1px solid var(--good); color: #06202C; }
.tfield.on { background: var(--accent); border-color: var(--accent); outline: 2px solid var(--paper); }
.tfield span { padding: 0 3px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
/* who signs it, in shape as well as colour */
.tfield.p-owner1 { border-style: solid; }
.tfield.p-owner2 { border-style: dashed; }
.tfield.p-rep    { border-style: dotted; }

/* Exact placement without dragging: a real contract's row pitch is ~13px at
   phone width, which no thumb can work. */
.nudge { display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--s2); }
.nudge .btn { min-width: 0; }
/* One chevron, turned four ways — four different glyphs would have to be read;
   a rotation is understood at a glance. */
.nudge [data-nudge="up"] .i { transform: rotate(-90deg); }
.nudge [data-nudge="down"] .i { transform: rotate(90deg); }
.nudge [data-nudge="left"] .i { transform: rotate(180deg); }
.sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* =============================================================== stage circles

   AccuLynx's lettered circles: L P A C I ✓. One component everywhere — the
   Board, the lead page's milestones, the feed, the search results, the pins. */
.sc {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 28px; height: 28px; border-radius: 50%;
  font: 600 14px/1 var(--body);
  background: var(--sc-bg, var(--surface-2)); color: var(--sc-ink, var(--dim));
}
.sc.lg { width: 52px; height: 52px; font-size: 26px; }
.sc.sm { width: 22px; height: 22px; font-size: 11.5px; }
.sc.off { --sc-bg: var(--sc-off); --sc-ink: var(--sc-off-ink); }
.sc.glyph { --sc-bg: var(--surface-2); --sc-ink: var(--dim); border: 1px solid var(--line); }
.sc.glyph .i { width: 12px; height: 12px; }
.stage-bg-lead      { --sc-bg: var(--stage-lead);      --sc-ink: var(--stage-ink-lead); }
.stage-bg-prospect  { --sc-bg: var(--stage-prospect);  --sc-ink: var(--stage-ink-prospect); }
.stage-bg-approved  { --sc-bg: var(--stage-approved);  --sc-ink: var(--stage-ink-approved); }
.stage-bg-completed { --sc-bg: var(--stage-completed); --sc-ink: var(--stage-ink-completed); }
.stage-bg-invoiced  { --sc-bg: var(--stage-invoiced);  --sc-ink: var(--stage-ink-invoiced); }
.stage-bg-closed    { --sc-bg: var(--stage-closed);    --sc-ink: var(--stage-ink-closed); }
.stage-bg-dead      { --sc-bg: var(--stage-dead);      --sc-ink: var(--stage-ink-dead); }

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

   AccuLynx's card: a coloured top edge, a tinted header band, a sentence-case
   title. Used by the Board and the lead page — the two screens modelled on it. */
.panel {
  position: relative; background: var(--surface); border: 1px solid var(--line);
  border-top: 2px solid var(--panel-rule); border-radius: var(--r-sm); margin-bottom: var(--s4);
}
.panel-head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 11px 16px; background: var(--surface-2); border-bottom: 1px solid var(--line);
}
.panel-head h2 {
  display: flex; align-items: center; gap: 8px; margin: 0 auto 0 0;
  font: 500 18px/1.25 var(--body); letter-spacing: 0; text-transform: none; color: var(--text);
}
.panel-head .micro { margin: 0; }
.panel-head b { color: var(--text); }
.panel-body { padding: 14px 16px; }
.panel-body:has(> .pencil) { padding-bottom: 50px; }
/* .btn.icon.ghost outranks a single class, so these carry the full chain */
.btn.icon.pencil { position: absolute; right: 8px; bottom: 8px; }
/* icon buttons that sit on a panel read as AccuLynx's bare glyphs, not boxed controls */
.btn.icon.pencil, .btn.icon.lback, .panel-head .btn.icon.ghost, .notes .btn.icon.ghost { border-color: transparent; color: var(--accent); }
.btn.icon.pencil:hover, .btn.icon.lback:hover, .panel-head .btn.icon.ghost:hover, .notes .btn.icon.ghost:hover { background: var(--accent-soft); }
.dim { color: var(--dim); }

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

.board {
  display: grid; gap: var(--s4); align-items: start; max-width: 1480px;
  grid-template-columns: minmax(0, 2fr) minmax(300px, 1fr);
  /* the feed is tall and spans both rows; without `auto 1fr` its height is
     shared between them and a gap opens under the pipeline */
  grid-template-rows: auto 1fr;
  grid-template-areas: "pipe feed" "acts feed";
}
.board .panel { margin: 0; }
.bpipe { grid-area: pipe; } .bacts { grid-area: acts; } .bfeed { grid-area: feed; }
@media (max-width: 1000px) {
  .board { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto; grid-template-areas: "pipe" "acts" "feed"; }
}

/* ---- current pipeline */
.pipe { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); padding: 14px 8px 8px; }
.pstage {
  display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 0;
  background: none; border: 0; border-radius: var(--r-md); padding: 10px 4px 12px;
  color: inherit; font: inherit; cursor: pointer; transition: background var(--t-fast);
}
.pstage:hover { background: var(--surface-2); }
.pstage:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.pcount { font: 600 26px/1.1 var(--body); color: var(--figure); margin-top: 10px; }
.pval { font-size: 14px; color: var(--text); white-space: nowrap; }
.plabel { font-size: 12px; color: var(--dim); }
.pipe-foot { display: flex; flex-wrap: wrap; gap: 6px 22px; padding: 10px 16px 12px; border-top: 1px solid var(--line); }
.pipe-foot .link { display: inline-flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--text); }
.pipe-foot .link b { color: var(--figure); }
@media (max-width: 560px) {
  .pipe { padding: 10px 2px 4px; }
  .pstage .sc.lg { width: 40px; height: 40px; font-size: 19px; }
  .pcount { font-size: 21px; margin-top: 6px; }
  .pval { font-size: 11px; }
}

/* ---- action items: a grid of questions, each count a door */
.bacts, .jact-panel { overflow: hidden; }
/* Lines are each cell's own right and bottom borders, and the grid is pulled
   1px past the panel's edge to hide the outermost ones. A background showing
   through a 1px gap filled any EMPTY cells in the last row with a grey block. */
.agrid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin: 0 -1px -1px 0; }
.aitem {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 10px;
  min-height: 68px; padding: 10px 14px; background: var(--surface); border: 0;
  border-right: 1px solid var(--line); border-bottom: 1px solid var(--line);
  color: var(--text); font: inherit; text-align: left; cursor: pointer; transition: background var(--t-fast);
}
.aitem:hover { background: var(--surface-2); }
.aitem:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.acount { font: 600 21px/1 var(--body); color: var(--figure); min-width: 1.3em; text-align: center; }
.alabel { font-size: 13px; line-height: 1.3; }
.aicon.glyph { color: var(--faint); display: inline-flex; }
.aicon.glyph .i { width: 22px; height: 22px; }
.aitem.zero .acount, .aitem.zero .alabel { color: var(--faint); }
.aitem.zero .aicon { opacity: .5; }
@media (max-width: 1280px) { .agrid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 700px)  { .agrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .aitem { gap: 8px; padding: 10px; } }

/* ---- activity feed */
.feedlist { list-style: none; margin: 0; padding: 0; }
@media (min-width: 1001px) { .bfeed .feedlist { max-height: calc(100dvh - 190px); overflow-y: auto; } }
.feedlist li + li { border-top: 1px solid var(--line); }
.feedmore { display: none; padding: 10px 14px 14px; border-top: 1px solid var(--line); }
@media (max-width: 1000px) {
  .feedlist:not(.all) li:nth-child(n+11) { display: none; }
  .feedmore { display: block; }
}
.frow2 {
  display: grid; grid-template-columns: 46px minmax(0, 1fr); gap: 10px; width: 100%;
  padding: 10px 14px; background: none; border: 0; color: inherit; font: inherit;
  text-align: left; cursor: pointer; transition: background var(--t-fast);
}
.frow2:hover { background: var(--surface-2); }
.frow2:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.fbadge { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.fwhen { font-size: 11px; color: var(--faint); white-space: nowrap; }
.ftitle { display: block; font-size: 13.5px; color: var(--accent); overflow-wrap: anywhere; }
.ftitle b { color: var(--text); font-weight: 600; }
.faddr, .ftext { display: block; font-size: 12.5px; color: var(--dim); overflow-wrap: anywhere; }

/* ---- jobs list banner, when an action item opened it */
.banner { display: flex; align-items: center; gap: 12px; padding: 8px 8px 8px 14px; border-radius: var(--r-sm);
  background: var(--accent-soft); border: 1px solid var(--line); }

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

.gsearch { position: relative; flex: 1; max-width: 520px; margin: 0 auto 0 12px; min-width: 0; }
.gsearch input {
  width: 100%; height: 38px; padding: 0 12px 0 36px; border-radius: var(--r-sm);
  border: 1px solid var(--line-strong); background: var(--surface); color: var(--text); font-size: 14px;
}
.gsearch input:focus { outline: 2px solid var(--focus); outline-offset: 1px; }
.gicon { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--faint); pointer-events: none; }
.gres {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 85;
  list-style: none; margin: 0; padding: 4px; max-height: 60vh; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-sm); box-shadow: var(--shadow-1);
}
.gres li[role="option"] { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 6px; cursor: pointer; min-height: var(--hit); }
.gres li[aria-selected="true"], .gres li[role="option"]:hover { background: var(--accent-soft); }
.gtext { display: flex; flex-direction: column; min-width: 0; }
.gtext b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gtext small { color: var(--dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gnone { padding: 10px; color: var(--dim); }
@media (max-width: 780px) {
  .gsearch { margin-left: 8px; }
  .gsearch input { height: var(--hit); font-size: 16px; }   /* 16px: iOS zooms into anything smaller */
  .topbar #syncnote:not(.err) { display: none; }            /* the count is on the Board; an error still shows */
}

/* ================================================================ lead page */

/* width: 100% — a block with auto margins inside the flex column .view would
   otherwise shrink to its content, so tabs with one panel came out narrower */
.lead { width: 100%; max-width: 1400px; margin: 0 auto; padding-bottom: 96px; }
.lead #lbody { padding: 0 16px; }

/* ---- header */
.lhead {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 14px 18px; background: var(--surface); border-bottom: 1px solid var(--line);
}
.lback { color: var(--accent); }
.lwho { flex: 1 1 240px; min-width: 0; }
.lwho h2 { margin: 0; font: 500 24px/1.2 var(--body); overflow-wrap: anywhere; }
.lwho a { display: inline-flex; align-items: center; gap: 4px; font-size: 15px; margin-top: 2px; }
.lmeta { display: flex; flex-wrap: wrap; align-items: stretch; }
.lcell { display: flex; flex-direction: column; justify-content: center; gap: 4px; padding: 2px 18px; border-left: 1px solid var(--line); }
.lk { font-size: 12.5px; color: var(--dim); }
.rank, .jprio {
  display: inline-flex; align-items: center; gap: 3px; background: none; border: 0; padding: 4px 0;
  color: var(--text); font: 500 15px var(--body); cursor: pointer; min-height: 32px;
}
.rank span:not(.rlabel) { width: 17px; height: 14px; border-radius: 2px; background: var(--track); border: 1px solid var(--line); }
.rank span.on { background: var(--good); border-color: var(--good); }
.rlabel { margin-left: 6px; font-size: 13px; color: var(--dim); }
.jprio { gap: 7px; }
.jprio .ring { width: 15px; height: 15px; border-radius: 50%; border: 3px solid var(--good); }
.jprio.p-high .ring { border-color: var(--warn); }
.jprio.p-urgent .ring { border-color: var(--bad); }
.jprio .i { width: 14px; height: 14px; transform: rotate(90deg); color: var(--dim); }
.rank:focus-visible, .jprio:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 4px; }
.lrep { flex-direction: row; align-items: center; gap: 8px; font-size: 13.5px; color: var(--accent); }
.avatar {
  width: 34px; height: 34px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-2); border: 1px solid var(--line-strong); color: var(--dim); font-size: 12px; font-weight: 600;
}
@media (max-width: 780px) {
  .lhead { padding: 12px 14px; gap: 10px; }
  .lwho h2 { font-size: 20px; }
  .lmeta { width: 100%; }
  .lcell { border-left: 0; padding: 0 18px 0 0; }
  .lhead .sc.lg { width: 40px; height: 40px; font-size: 20px; }
}

/* ---- the tab bar */
.ltabs {
  display: flex; align-items: center; gap: 6px; margin-bottom: var(--s4);
  padding: 0 10px; background: var(--surface); border-bottom: 1px solid var(--line);
}
.ltablist { display: flex; overflow-x: auto; min-width: 0; }
#ljobmenu { flex: none; }
@media (max-width: 560px) {
  .jmlabel { display: none; }                  /* the icon and its aria-label carry it */
  .ltabs { padding: 0 4px; }
  .ltab { padding: 12px 10px 10px; font-size: 14.5px; }
  .panel-head { flex-wrap: nowrap; padding: 10px 12px; }
  .panel-head h2 { font-size: 16px; min-width: 0; }
  .panel-head .link { font-size: 13.5px; white-space: nowrap; }
}
.ltab {
  background: none; border: 0; border-bottom: 3px solid transparent; padding: 12px 14px 10px;
  color: var(--dim); font: 500 15px var(--body); cursor: pointer; white-space: nowrap; min-height: var(--hit);
}
.ltab:hover { color: var(--text); }
.ltab.on { color: var(--text); border-bottom-color: var(--accent); }
.ltab:focus-visible { outline: 2px solid var(--focus); outline-offset: -3px; }

/* ---- milestones */
.ms { display: grid; grid-template-columns: minmax(240px, 1fr) minmax(0, 2.2fr); gap: 24px; align-items: center; padding: 18px 20px; }
.mstatus { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; min-width: 0; }
.mrow { display: flex; align-items: center; gap: 6px; width: 100%; }
.mk { font-weight: 600; font-size: 14px; letter-spacing: .02em; text-transform: uppercase; white-space: nowrap; }
.mk.good { color: var(--good); }
.mk.warn { color: var(--figure); }
select.inline, input.inline {
  flex: 1; min-width: 0; min-height: 36px; padding: 5px 8px; border-radius: var(--r-sm);
  border: 1px solid transparent; background: transparent; color: var(--text); font: inherit; font-size: 15px;
}
select.inline:hover, input.inline:hover { border-color: var(--line-strong); }
select.inline:focus, input.inline:focus { border-color: var(--accent); outline: 2px solid var(--focus); outline-offset: 0; background: var(--surface); }
.btn.go { background: var(--go); border-color: var(--go); color: var(--ink-on-go); margin-top: 6px; }
.stepper-lx { list-style: none; margin: 0; padding: 22px 0 0; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); }
.stepper-lx li { position: relative; display: flex; justify-content: center; min-width: 0; }
.conn { position: absolute; top: 26px; right: 50%; width: 100%; height: 3px; background: var(--conn); }
.conn.on { background: var(--conn-on); }
.conn small {
  position: absolute; left: 50%; bottom: 6px; transform: translateX(-50%);
  font-size: 12px; color: var(--dim); white-space: nowrap; background: var(--surface); padding: 0 3px;
}
.mstep {
  position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; gap: 3px;
  background: none; border: 0; padding: 0 2px; color: inherit; font: inherit; cursor: pointer; min-width: 0;
}
.mstep .sc { box-shadow: 0 0 0 4px var(--surface); }
.stepper-lx li.current .mstep .sc { box-shadow: 0 0 0 3px var(--surface), 0 0 0 5px var(--text); }
.mstep.armed .sc { box-shadow: 0 0 0 3px var(--surface), 0 0 0 5px var(--warn); }
.mstep:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 6px; }
.ml { font-size: 14px; margin-top: 4px; }
.md { font-size: 12.5px; color: var(--dim); }
@media (max-width: 960px) { .ms { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 560px) {
  .ms { padding: 14px; }
  .mstep .sc.lg { width: 36px; height: 36px; font-size: 17px; }
  .conn { top: 18px; }
  .conn small { display: none; }
  .ml { font-size: 11.5px; }
  .md { font-size: 10.5px; }
}
@media (max-width: 420px) { .ml { font-size: 10.5px; letter-spacing: -.01em; } }

/* ---- job activity: counters that are doors */
.jact { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin: 0 -1px -1px 0; }
.jcell {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 60px;
  padding: 12px 16px; background: var(--surface); border: 0; color: var(--accent);
  border-right: 1px solid var(--line); border-bottom: 1px solid var(--line);
  font: inherit; font-size: 15px; text-align: left; cursor: pointer; transition: background var(--t-fast);
}
.jcell:hover { background: var(--surface-2); }
.jcell:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.jcell .n { font: 600 22px/1 var(--body); color: var(--figure); }
.jcell .ok { color: var(--good); } .jcell .no { color: var(--bad); }
.jcell .ok .i, .jcell .no .i { width: 26px; height: 26px; stroke-width: 3; }
.pinned { display: inline-flex; align-items: center; gap: 3px; margin-right: 10px; color: var(--dim); }
/* the job's Drive folder link, under the counters (D-091) */
.drive { display: flex; align-items: center; gap: 8px; min-height: 52px; padding: 8px 16px; border-top: 1px solid var(--line); }
.drive-open { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; white-space: nowrap; }
.drive-host { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dim); }
.drive input { flex: 1; min-width: 0; }
@media (max-width: 560px) { .drive { flex-wrap: wrap; padding: 8px 12px; } .drive input { flex-basis: 100%; } }
@media (max-width: 1100px) { .jact { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .jact { grid-template-columns: repeat(2, minmax(0, 1fr)); } .jcell { padding: 12px; font-size: 14px; } }

/* ---- contact and location */
.lcols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--s4); align-items: start; }
@media (max-width: 960px) { .lcols { grid-template-columns: minmax(0, 1fr); } }
.kv2 { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 12px 26px; margin: 0; font-size: 15px; }
.kv2 dt { font-weight: 600; color: var(--text); }
.kv2 dd { margin: 0; color: var(--text); overflow-wrap: anywhere; }
.kv2 dd .link.icon { display: inline-flex; vertical-align: middle; padding: 2px; }
.kv2 dd a:not(.link) { display: inline-flex; align-items: center; gap: 4px; }
@media (max-width: 420px) { .kv2 { grid-template-columns: minmax(0, 1fr); gap: 2px; } .kv2 dd { margin-bottom: 10px; } }
.ptabs { display: flex; background: var(--surface-2); border-bottom: 1px solid var(--line); }
.ptab {
  flex: 1; padding: 12px 8px 10px; background: none; border: 0; border-bottom: 3px solid transparent;
  color: var(--accent); font: 500 15.5px var(--body); cursor: pointer; min-height: var(--hit);
}
.ptab.on { background: var(--surface); color: var(--text); border-bottom-color: var(--accent); }
.ptab:focus-visible { outline: 2px solid var(--focus); outline-offset: -3px; }
.others { border-top: 1px solid var(--line); margin-top: 14px; padding-top: 12px; }
.other + .other { border-top: 1px dashed var(--line); margin-top: 12px; padding-top: 12px; }

/* ---- communications */
.notes { list-style: none; margin: 14px 0 0; padding: 0; }
.notes li { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 10px; padding: 10px 0; border-top: 1px solid var(--line); }
.notes p { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }

/* ---- the floating add button */
.fab {
  position: fixed; right: 26px; bottom: 26px; z-index: 40; width: 60px; height: 60px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; border: 0; cursor: pointer;
  background: var(--accent); color: var(--ink-on-accent); box-shadow: var(--shadow-fab);
}
.fab .i { width: 28px; height: 28px; }
.fab:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
@media (max-width: 780px) { .fab { right: 16px; bottom: calc(58px + 16px + env(safe-area-inset-bottom)); width: 56px; height: 56px; } }

/* ============================================================ sign-in screens

   Drawn over the app, which is inert behind it. One card, centred, the
   AccuLynx way: brand, title, the few fields, one primary action. */
.gate {
  position: fixed; inset: 0; z-index: 250; overflow-y: auto;
  display: flex; align-items: flex-start; justify-content: center;
  padding: max(6vh, 24px) 16px calc(24px + env(safe-area-inset-bottom));
  background: var(--bg);
}
.gate-card {
  width: min(440px, 100%); background: var(--surface); border: 1px solid var(--line);
  border-top: 3px solid var(--panel-rule); border-radius: var(--r-md); padding: 26px 26px 22px;
  box-shadow: var(--shadow-1);
}
.gate-brand { display: flex; align-items: center; gap: 10px; margin-bottom: 18px;
  font: 600 15px var(--body); color: var(--dim); }
/* the app icon itself (ipad/scripts/icons.mjs centres the letters on their
   ink), not text: typed text sat 1.5px low, a font's line box leaving room for
   accents and descenders that RL does not have */
.gate-logo { display: block; width: 34px; height: 34px; flex: none; border-radius: 8px; }
.gate h1 { margin: 0 0 6px; font: 600 24px/1.2 var(--body); color: var(--text); }
.gate-sub, .gate-body { margin: 0 0 18px; color: var(--dim); font-size: 14.5px; line-height: 1.5; }
.gate-fine { margin: 10px 0 0; color: var(--faint); font-size: 12.5px; line-height: 1.45; }
.gate .field input { width: 100%; }
.gate form .btn.wide { margin-top: 6px; }
.gate-links { display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-top: 14px; }
.gate-or { display: flex; align-items: center; gap: 12px; margin: 20px 0 14px; color: var(--faint); font-size: 12.5px; }
.gate-or::before, .gate-or::after { content: ''; flex: 1; height: 1px; background: var(--line); }
.gate-msg { margin: 0 0 14px; padding: 10px 12px; border-radius: var(--r-sm); font-size: 14px; line-height: 1.4; }
.gate-msg.err { background: color-mix(in srgb, var(--bad) 10%, transparent); color: var(--bad); border: 1px solid color-mix(in srgb, var(--bad) 35%, transparent); }
.gate-msg.note { background: var(--accent-soft); color: var(--text); border: 1px solid var(--line); }
.gate-bring { margin: 6px 0 12px; align-items: flex-start; }
.gate-bring small { display: block; color: var(--dim); font-size: 12.5px; margin-top: 2px; }
.gate-step { margin-left: auto; font-size: 12px; font-weight: 600; color: var(--faint); letter-spacing: .02em; }
.gate-links .gate-fine { margin: 0; align-self: center; }
.gate-acts { display: inline-flex; gap: 16px; flex-wrap: wrap; }
.gate .link.quiet { color: var(--dim); font-weight: 500; }
.gate-stack { display: flex; flex-direction: column; gap: 10px; margin-top: 16px; }
.gate-stack .link { align-self: center; margin-top: 4px; }
/* password: the eye sits inside the field, the text never overlaps it */
.pw { position: relative; }
.pw input { width: 100%; padding-right: 64px; }
.pw-eye { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); min-height: 32px; padding: 0 8px;
  font-size: 12.5px; color: var(--dim); border-radius: var(--r-sm); }
.pw-eye:hover, .pw-eye:focus-visible { color: var(--accent); text-decoration: none; }
/* the two doors after sign-up */
.gate-choice { display: grid; gap: 10px; margin: 4px 0 6px; }
.gate-opt { display: block; width: 100%; text-align: left; padding: 14px 16px; border: 1px solid var(--line-strong);
  border-radius: var(--r-md); background: var(--surface); color: var(--text); cursor: pointer; font: inherit; }
.gate-opt:hover, .gate-opt:focus-visible { border-color: var(--accent); background: var(--accent-soft); }
.gate-opt:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.gate-opt-t { display: block; font-weight: 600; font-size: 16px; margin-bottom: 3px; }
.gate-opt-s { display: block; color: var(--dim); font-size: 13.5px; line-height: 1.4; }
/* the crew code: big enough to read out over the phone */
.gate-code, .crew-code { display: grid; grid-template-columns: 1fr auto; column-gap: 12px; align-items: center;
  padding: 12px 14px; border: 1px dashed var(--line-strong); border-radius: var(--r-md); background: var(--surface-2); }
.gate-code-l, .crew-code .f { grid-column: 1; margin: 0; font-size: 11.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--dim); }
.gate-code-v, .crew-code > b { grid-column: 1; font: 700 26px/1.2 var(--disp); letter-spacing: .12em; color: var(--text); }
.gate-code .btn, .crew-code .btn { grid-column: 2; grid-row: 1 / span 2; }
.gate-code-s, .crew-code .micro { grid-column: 1 / -1; margin: 8px 0 0; color: var(--dim); font-size: 12.5px; line-height: 1.45; }
.gate-codein { font: 700 22px/1.2 var(--disp); letter-spacing: .12em; text-transform: uppercase; text-align: center; }
.gate-inv { display: grid; gap: 4px; }
.gate-invrow { display: grid; grid-template-columns: 1fr 120px; gap: 8px; }
.gate-invrow .field { margin-bottom: 4px; }
.gate-invrow input, .gate-invrow select { width: 100%; }
.gate #gmore { margin: 2px 0 10px; }
.crew { display: grid; gap: 14px; margin: 4px 0 14px; }
@media (min-width: 900px) { .crew { grid-template-columns: 1fr 1fr; align-items: start; } .crew .field { margin-bottom: 0; } }
@media (max-width: 480px) { .gate-card { padding: 20px 18px 18px; } .gate h1 { font-size: 21px; } }

/* ================================================================ job numbers */

/* AccuLynx prints the job number before the name everywhere: "RC-3190: …" */
.jobno {
  display: inline-block; margin-right: 8px; padding: 1px 7px; border-radius: 5px; vertical-align: 2px;
  font: 600 12px/1.5 var(--mono); letter-spacing: .02em; white-space: nowrap;
  background: var(--accent-soft); color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
}
.jobno.pending { color: var(--dim); background: var(--surface-2); border-color: var(--line); font-family: var(--body); }
.lwho h2 .jobno { font-size: 13px; vertical-align: 4px; }
.gtext .jobno { font-size: 11px; margin-right: 6px; }

/* ================================================================== the team */

.assignees { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; min-height: 32px; }
.assignee { display: inline-flex; align-items: center; gap: 6px; font-size: 13.5px; color: var(--text); }
.assignee .avatar { width: 26px; height: 26px; font-size: 10.5px; }
.lrep { flex-direction: column; align-items: flex-start; }
.avatar.lg { width: 48px; height: 48px; font-size: 16px; flex: none; }
.acct { display: flex; gap: 14px; align-items: flex-start; }
.acct .field { margin-bottom: 4px; }
.people .who { display: flex; align-items: center; gap: 10px; }
.people .who small { display: block; }
.people td.r { white-space: nowrap; }
.rolesel { min-height: 36px; padding: 4px 8px; border-radius: var(--r-sm); border: 1px solid var(--line-strong);
  background: var(--surface); color: var(--text); font: inherit; font-size: 14px; }
.invite { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) auto; gap: 10px; align-items: end; }
.invite .btn { margin-bottom: 12px; }
@media (max-width: 560px) { .invite { grid-template-columns: minmax(0, 1fr); } .invite .btn { margin-bottom: 0; } }
.roles summary { cursor: pointer; }

/* "Viewing: one rep" — the Board and the Jobs list, for managers */
.viewas { display: flex; flex-direction: column; min-width: 190px; }
.viewas .f { margin-bottom: 4px; }
.viewas select { min-height: 38px; padding: 4px 8px; border-radius: var(--r-sm); border: 1px solid var(--line-strong);
  background: var(--surface); color: var(--text); font: inherit; font-size: 14px; }
/* its own row, only when it is there — an empty row would still cost a gap */
.board:has(.bscope) { grid-template-rows: auto auto 1fr; grid-template-areas: "scope scope" "pipe feed" "acts feed"; }
.bscope { grid-area: scope; display: flex; justify-content: flex-end; }
@media (max-width: 1000px) {
  .board:has(.bscope) { grid-template-rows: auto; grid-template-areas: "scope" "pipe" "acts" "feed"; }
}
.bscope .viewas { width: min(320px, 100%); }

#syncnote.warn { color: var(--warn); }
#syncnote.err { color: var(--bad); font-weight: 600; }      /* was never styled: "Not saved" read as quiet grey */
@media (max-width: 780px) { .topbar #syncnote.warn { display: inline; } }

/* ===================================================================== inbox

   Job communications: the Inbox (list and thread side by side at 1100 px and
   up, one screen at a time below), the thread and its composer, the lead
   page's compact thread, tasks. The Board's language throughout — panels,
   stage circles, job lines, counts in --figure. Tokens only. */

/* the rail's Inbox button and its count */
.navbtn { position: relative; }
.navbtn .nbadge {
  position: absolute; top: 3px; left: calc(50% + 3px); min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: var(--r-pill); background: var(--badge-bg); color: var(--badge-ink);
  font: 700 11px/18px var(--body); letter-spacing: 0; text-align: center; font-variant-numeric: tabular-nums;
  box-shadow: 0 0 0 2px var(--rail-bg);
}
@media (max-width: 780px) {
  /* seven cells in a team: CONTRACTS needs a hair less, and the bar's own
     side padding back (measured at 390 px: no label clips) */
  #rail.team { padding-left: 1px; padding-right: 1px; }
  #rail.team .navbtn { padding: 0; }
  #rail.team .navbtn span { font-size: min(10px, 2.2vw); letter-spacing: 0; }
  body.typing #rail { display: none; }
  body.typing #main { padding-bottom: 0; }
}

.pad.inbox { max-width: 1480px; }
.inbox .panel { margin-bottom: 0; }
.itabs { margin: 0; padding: 0 6px; border-radius: var(--r-sm) var(--r-sm) 0 0; }
.itabs .ltablist { width: 100%; }
.itabs .ltab { flex: 1 0 auto; display: inline-flex; align-items: center; justify-content: center; gap: 6px; }

/* unread pills: the list's, the tabs' */
.upill {
  display: inline-flex; align-items: center; justify-content: center; min-width: 22px; height: 22px; padding: 0 7px;
  border-radius: var(--r-pill); background: var(--accent); color: var(--ink-on-accent);
  font: 700 12px/1 var(--body); font-variant-numeric: tabular-nums; flex: none; align-self: center;
}
.upill.at { background: var(--figure); color: var(--ink-on-gold); }
.upill.muted, .upill.plain { background: var(--surface-2); color: var(--dim); border: 1px solid var(--line); }
.upill.bad { background: transparent; color: var(--bad); border: 1px solid var(--bad); }

/* wide: two panes, each scrolling on its own */
.inbox.wide { display: grid; grid-template-columns: 400px minmax(0, 1fr); gap: var(--s4); align-items: stretch;
  height: calc(100dvh - var(--topbar-h, 66px)); }
.inbox.wide .ilist { display: flex; flex-direction: column; min-height: 0; }
.inbox.wide .ilist > [data-ibody] { flex: 1; min-height: 0; overflow-y: auto; }
.inbox.wide .ipane { display: flex; min-height: 0; }
.inbox.wide .ipane > .panel { flex: 1; }
.inbox.wide .tback { display: none; }
.ipick { display: flex; align-items: center; justify-content: center; }

/* narrower: a thread is a screen of its own, between the top bar and the nav */
@media (max-width: 1099px) {
  .inbox.open .ipane {
    position: fixed; z-index: 20; top: var(--topbar-h, 66px); left: var(--rail); right: 0; bottom: 0;
    display: flex; background: var(--bg);
  }
  .inbox.open .ipane > .panel { flex: 1; border-radius: 0; border-left: 0; border-right: 0; }
}
@media (max-width: 780px) {
  .pad.inbox { padding: 0 0 14px; }
  .inbox .ilist { border-radius: 0; border-left: 0; border-right: 0; }
  .inbox.open .ipane { left: 0; bottom: calc(58px + env(safe-area-inset-bottom)); }
  /* the keyboard is up: the thread rides on it (visualViewport sets --kb) */
  body.typing .inbox.open .ipane { bottom: var(--kb, 0px); }
}

/* the list */
.itools { padding: 10px 12px; }
.ifilters { display: none; }
.idates { display: flex; gap: 10px; width: 100%; }
.idates .field { flex: 1; margin: 0; }
@media (max-width: 780px) {
  .ifilters { display: inline-flex; }
  .ifchips { display: none; width: 100%; }
  .ifchips.show { display: flex; }
  .itools .jfind { flex-basis: calc(100% - 120px); }
}
.ilocal { padding: 8px 14px; border-bottom: 1px solid var(--line); }
.istranded { margin: 10px 12px; flex-wrap: wrap; }
.ilist-rows { list-style: none; margin: 0; padding: 0; }
.iskel { padding: 16px; }
.icount { padding: 8px 14px; border-bottom: 1px solid var(--line); }
.imore { padding: 12px 14px; text-align: center; }
.trow {
  display: grid; grid-template-columns: 46px minmax(0, 1fr) auto; gap: 10px; align-items: start;
  padding: 11px 14px; border-bottom: 1px solid var(--line); cursor: pointer; transition: background var(--t-fast);
}
.trow:hover { background: var(--surface-2); }
.trow:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.trow.on, .trow.on:hover { background: var(--accent-soft); }
.trow.on .twhen { color: var(--dim); }     /* --faint is 3.5:1 on the tinted row in dark */
.trow.unread { box-shadow: inset 3px 0 0 var(--accent); }
.tlead { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.twhen { font-size: 11px; color: var(--faint); white-space: nowrap; }
.tmid { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.t1 { font-size: 14px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.trow.unread .t1 { font-weight: 600; }
.t2 { font-size: 13px; color: var(--dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.t2 b { color: var(--text); font-weight: 600; }
.t2.snip { white-space: normal; display: -webkit-box; -webkit-line-clamp: 3; line-clamp: 3; -webkit-box-orient: vertical; }
.t3 { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; font-size: 12px; color: var(--dim); }
.t3 .i { width: 14px; height: 14px; }
.tmeta2 { font-size: 12px; color: var(--dim); }
.trow .btn.icon.ghost { border-color: transparent; color: var(--accent); align-self: center; }
@media (max-width: 780px) {
  .t2 { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; }
}

/* the thread */
.thread { display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.thead { flex-wrap: nowrap; gap: 8px; }
.thead .sc { flex: none; }
.twho { flex: 1; min-width: 0; }
.twho h2 { font-size: 16px; margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.twho .micro { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tjob { color: var(--text); text-decoration: none; }
.tjob:hover { text-decoration: underline; }
.thead .btn.icon.on { background: var(--accent-soft); }
.tpeople { display: flex; align-items: center; gap: 6px; flex: none; }
.tavatars { display: flex; align-items: center; padding-left: 6px; }
.tavatars .avatar { width: 28px; height: 28px; font-size: 10.5px; margin-left: -6px; border: 2px solid var(--surface-2); position: relative; }
.avatar.muted .i { position: absolute; right: -5px; bottom: -5px; width: 15px; height: 15px; padding: 1px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 50%; color: var(--dim); }
.tcount { display: none; }
@media (max-width: 780px) { .tavatars { display: none; } .tcount { display: inline; white-space: nowrap; } }
[data-tbanner] .banner { margin: 8px 12px; }
.tlost { margin: 8px 12px; flex-wrap: wrap; }
.strlist { list-style: none; margin: 0; padding: 0; width: 100%; display: flex; flex-direction: column; gap: 6px; }
.strlist li { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 8px; padding-top: 6px; border-top: 1px solid var(--line); }
.strlist li .grow { min-width: 12em; overflow-wrap: anywhere; }
.tmuted, .toffline { margin: 0; padding: 6px 16px; border-bottom: 1px solid var(--line); }
.hlbar { display: flex; align-items: center; gap: 2px; margin: 8px 12px; padding: 2px 4px 2px 12px;
  border-radius: var(--r-sm); background: var(--accent-soft); border: 1px solid var(--line); font-size: 13.5px; }
.tmsgs { flex: 1; min-height: 0; overflow-y: auto; padding: 8px 12px 14px; overscroll-behavior: contain; }
.tmsgs:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.tmsgs.embedded { flex: none; overflow: visible; padding: 0; }
.tolder { display: flex; justify-content: center; padding: 6px 0 10px; }
.tearlier { margin: 0 0 6px 6px; }
.tnew { align-self: center; position: relative; z-index: 2; margin-top: -48px; margin-bottom: 8px; box-shadow: var(--shadow-1); }
.daysep, .newsep { display: flex; align-items: center; gap: 10px; margin: 12px 0 6px; font-size: 12px; color: var(--dim); }
.daysep::before, .daysep::after, .newsep::before, .newsep::after { content: ''; flex: 1; height: 1px; background: var(--line); }
.newsep { color: var(--accent); font-weight: 600; }
.newsep::before, .newsep::after { background: var(--accent); }

/* a message */
.msg { position: relative; display: grid; grid-template-columns: 32px minmax(0, 1fr) auto; gap: 0 10px;
  padding: 7px 6px; border-radius: var(--r-sm); transition: background var(--t-fast); }
.msg:hover { background: var(--surface-2); }
.msg:focus { outline: none; }
.msg.flash { background: var(--accent-soft); }
/* on a touch screen a long press opens the message menu (which has Copy text),
   so iOS must not also start a selection and its callout */
@media (pointer: coarse) { .tmsgs .msg { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; } }
.avatar.sm { width: 32px; height: 32px; font-size: 11.5px; }
.avatar.glyph { color: var(--faint); }
.avatar.glyph .i { width: 16px; height: 16px; }
.msg.cont { padding-top: 1px; }
.msg.cont > .avatar { visibility: hidden; height: 0; }
.msg.cont .mhead { display: none; }
.mbody { min-width: 0; }
.mhead { display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 8px; }
.mname { font-weight: 600; font-size: 14px; }
.mtime { font-size: 12px; color: var(--dim); }
.medited { font-size: 12px; min-height: 0; }
.mtext { white-space: pre-wrap; overflow-wrap: anywhere; font-size: 15px; line-height: 1.5; margin-top: 1px; }
.mtext.clamp { max-height: 18em; overflow: hidden; }
.mmore { font-size: 13px; }
.mtags { display: flex; flex-wrap: wrap; gap: 4px; margin: 3px 0 2px; }
.mversions { margin: 6px 0 0; padding-left: 18px; font-size: 13.5px; color: var(--dim); }
.mversions s { color: var(--dim); }
.mention { padding: 0 3px; border-radius: 4px; background: var(--mention-bg); color: var(--accent); font-weight: 600; }
.mention.me { box-shadow: inset 0 0 0 1px var(--figure); color: var(--text); }
mark.hl { background: var(--hl); color: var(--text); border-radius: 2px; padding: 0 1px; }
.msg .mact { align-self: start; }
@media (pointer: fine) {
  .msg .mact { opacity: 0; }
  .msg:hover .mact, .msg:focus-within .mact, .msg .mact[aria-expanded="true"] { opacity: 1; }
}
.msg .btn.icon.ghost { border-color: transparent; color: var(--dim); }
.msg.failed { box-shadow: inset 3px 0 0 var(--bad); }
.msg.deleted { border: 1px dashed var(--line-strong); margin: 4px 0; }
.msg.deleted .mtext { color: var(--dim); }
.msg.note .mname { color: var(--dim); }
.mstate { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-top: 4px; font-size: 12.5px; color: var(--dim); }
.mstate .i { width: 14px; height: 14px; }
.mstate.bad { color: var(--text); }
.mstate .actions { gap: 6px; }

/* files on a message */
.attgrid { display: grid; grid-template-columns: repeat(auto-fill, 96px); gap: 6px; margin-top: 6px; }
.att { position: relative; width: 96px; height: 96px; padding: 0; border: 1px solid var(--line); border-radius: var(--r-sm);
  overflow: hidden; background: var(--surface-2); cursor: zoom-in; }
.att img { width: 100%; height: 100%; object-fit: cover; display: block; }
.attmore { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: var(--scrim); color: var(--paper); font: 600 18px var(--body); }
.attfiles, .reacts, .tchips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.attfile, .tchip {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%; min-height: 34px; padding: 5px 10px;
  border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: var(--surface); color: var(--text);
  font: 500 13px var(--body); text-align: left; cursor: pointer;
}
.attfile .afn { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.attfile:hover, .tchip:hover { background: var(--surface-2); }
.tchip.done span { text-decoration: line-through; color: var(--dim); }
.react { display: inline-flex; align-items: center; gap: 4px; min-height: 30px; padding: 2px 9px; border-radius: var(--r-pill);
  border: 1px solid var(--line-strong); background: var(--surface); color: var(--text); font-size: 13px; cursor: pointer; }
.react[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); }
.react:hover { filter: brightness(1.08); }
@media (pointer: coarse), (max-width: 780px) {
  .react, .attfile, .tchip, .medited, .mmore, .tearlier { min-height: var(--hit); }
}

/* the reactions row at the top of a message's menu */
.menu .mrow { display: flex; gap: 2px; padding: 2px 2px 6px; margin-bottom: 4px; border-bottom: 1px solid var(--line); }
.menu .mrow .mrbtn { flex: 1; justify-content: center; min-width: var(--hit); min-height: var(--hit); padding: 0; font-size: 20px; }
.menu .mrow .mrbtn[aria-checked="true"] { background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent); }

/* tags */
.mtag { display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px; border-radius: var(--r-pill);
  background: var(--surface-2); border: 1px solid var(--line); color: var(--text); font-size: 12px; font-weight: 500; }
.mtag .btn.icon { width: 26px; height: 26px; min-height: 26px; margin: -3px -6px -3px 0; border-color: transparent; }
.tdot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--tag-slate); }
.tdot.tag-slate { background: var(--tag-slate); } .tdot.tag-blue { background: var(--tag-blue); }
.tdot.tag-green { background: var(--tag-green); } .tdot.tag-amber { background: var(--tag-amber); }
.tdot.tag-red { background: var(--tag-red); } .tdot.tag-violet { background: var(--tag-violet); }
.tdot.tag-teal { background: var(--tag-teal); } .tdot.tag-rose { background: var(--tag-rose); }

/* the composer: never repainted, only its strips */
.composer { position: relative; display: flex; flex-direction: column; gap: 8px; padding: 10px 12px;
  border-top: 1px solid var(--line); background: var(--surface); }
.tembed .composer { margin-top: 12px; border: 1px solid var(--line-strong); border-radius: var(--r-md); }
.composer textarea { min-height: 44px; resize: none; padding: 10px 12px; font-size: 15px; line-height: 1.45; }
.cctx { display: flex; align-items: center; gap: 8px; padding: 0 0 0 10px; border-radius: var(--r-sm);
  background: var(--accent-soft); font-size: 13.5px; }
.cctx .grow { display: inline-flex; align-items: center; gap: 6px; }
.cfiles, .ctags, .ctagpick { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.cfiles:empty, .ctags:empty { display: none; }
.cfile { display: inline-flex; align-items: center; gap: 2px; height: 56px; padding: 0 2px 0 8px; max-width: 220px;
  border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: var(--surface-2); font-size: 12.5px; }
.cfile img { width: 54px; height: 54px; margin-left: -8px; object-fit: cover; border-radius: var(--r-sm) 0 0 var(--r-sm); }
.cfile .cfname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.cfile.adding { padding: 0 12px; color: var(--dim); }
.cfile .btn.icon { border-color: transparent; }
.ctagpick { padding: 4px 0; }
.ctagpick .chip { min-height: 34px; }
@media (pointer: coarse), (max-width: 780px) {
  .mtag .btn.icon { width: var(--hit); height: var(--hit); min-height: var(--hit); margin: -10px -12px -10px -4px; }
  .ctagpick .chip { min-height: var(--hit); }
}
.cbar { display: flex; align-items: center; gap: 2px; }
.cbar .btn.icon.ghost { border-color: transparent; color: var(--dim); }
/* a ghost icon that is a toggle (tag, mute) shows when it is on */
.btn.icon.ghost[aria-pressed="true"] { color: var(--accent); background: var(--accent-soft); }
.cbar .ccount { margin-left: 6px; }
.csend { min-height: 44px; padding: 8px 16px; }
.composer.editing .csend { background: var(--go); color: var(--ink-on-go); }
.cnote { margin: 0; }
.cmention { position: absolute; left: 10px; right: 10px; bottom: calc(100% - 4px); z-index: 6; max-height: 280px; overflow-y: auto;
  padding: 4px; background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-sm); box-shadow: var(--shadow-1); }
.cmopt { display: flex; align-items: center; gap: 10px; min-height: var(--hit); padding: 6px 10px; border-radius: 6px; cursor: pointer; }
.cmopt[aria-selected="true"], .cmopt:hover { background: var(--accent-soft); }
.cmopt.out b { color: var(--dim); font-weight: 500; }
.cmtext { display: flex; flex-direction: column; min-width: 0; }
.cmtext small { color: var(--dim); font-size: 12px; }
.cmhead { padding: 8px 10px 4px; font: 500 11px var(--disp); letter-spacing: .14em; text-transform: uppercase; color: var(--faint); }
.cmconfirm { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px; font-size: 14px; }
@media (max-width: 780px) {
  .composer textarea { font-size: 16px; }     /* iOS zooms into anything smaller */
  .cslabel { display: none; }
  .csend { width: var(--hit); padding: 0; }
}

/* the lead page: the thread, compact */
.tembed { margin-top: 4px; }
/* the lead page's Communications tab is the Inbox, one job: its tabs, search
   and lists where the Inbox's are, its thread beside them (D-084) */
.lcomms.inbox.wide { padding: 0; max-width: none; height: min(76vh, 820px); }
.jnote { padding: 6px 14px 12px; border-bottom: 1px solid var(--line); }
.jnote textarea { margin-top: 4px; }
.ltab .udot { display: inline-block; width: 8px; height: 8px; margin-left: 6px; border-radius: 50%; background: var(--accent); vertical-align: middle; }
@media (max-width: 1099px) {
  .lcomms.inbox.wide { display: flex; flex-direction: column; height: auto; }
  .lcomms .ilist { flex: none; }
  .lcomms .ipane { height: calc(100dvh - var(--topbar-h, 66px) - 120px); min-height: 420px; margin-top: var(--s4); }
}
/* the Tasks tab's toolbar in the list column */
.inbox.wide .ttools { flex-wrap: wrap; gap: 8px; }
.jcell .udot { width: 9px; height: 9px; border-radius: 50%; background: var(--accent); margin-left: auto; margin-right: 6px; }

/* skeleton messages */
.skmsg { display: grid; grid-template-columns: 32px minmax(0, 1fr); gap: 10px; padding: 8px 6px; }
.skel.sq.sm { width: 32px; height: 32px; border-radius: 50%; }
.skbody { display: flex; flex-direction: column; }
.empty > p { margin: 0; }
.empty > .micro { margin-top: 4px; }

/* tasks */
.ttools { padding: 10px 14px; }
.ttools .chips { margin: 0; }
.tbody { padding-bottom: 8px; }
.tasklist { list-style: none; margin: 0; padding: 0; }
.taskrow { display: grid; grid-template-columns: var(--hit) minmax(0, 1fr) auto; gap: 8px; align-items: center;
  padding: 6px 14px 6px 8px; border-bottom: 1px solid var(--line); cursor: pointer; transition: background var(--t-fast); }
.taskrow:last-child { border-bottom: 0; }
.taskrow:hover { background: var(--surface-2); }
.taskrow:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.tcheck { width: var(--hit); height: var(--hit); padding: 0; border: 0; background: none; display: inline-flex;
  align-items: center; justify-content: center; border-radius: 50%; cursor: pointer; }
.tcheck .i { width: 26px; height: 26px; padding: 3px; border: 2px solid var(--line-strong); border-radius: 50%; color: transparent; stroke-width: 3; }
.tcheck:hover .i { border-color: var(--good); color: var(--good); }
.tcheck[aria-pressed="true"] .i { background: var(--good); border-color: var(--good); color: var(--paper); }
.tcheck:disabled { cursor: not-allowed; }
.tcheck:focus-visible { outline: 2px solid var(--focus); outline-offset: 0; }
.tmain { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.ttitle { font-size: 14.5px; font-weight: 600; overflow-wrap: anywhere; }
.taskrow.done .ttitle { text-decoration: line-through; color: var(--dim); }
.tmeta { font-size: 12.5px; color: var(--dim); }
.tmeta .bad, .tmeta.bad { color: var(--bad); }
.tfrom { font-size: 12.5px; min-height: 0; }
.p-word.p-high { color: var(--warn); } .p-word.p-urgent { color: var(--bad); }
.tghead { display: flex; align-items: center; gap: 8px; margin: 0; padding: 14px 14px 6px; font: 600 13px var(--body); color: var(--dim); }
.tghead .num { color: var(--figure); font: 600 14px var(--body); }
.tgroup.overdue .tghead { color: var(--bad); }
.tstrip { margin-bottom: 12px; }
.tstrip .eyebrow { margin-bottom: 2px; }
.tstrip .taskrow { padding-left: 0; }
.tlocked { margin: 0 0 10px; }

/* the task dialog: a card on a desk, a sheet on a phone */
.taskcard { width: min(480px, 100%); max-height: calc(100dvh - 36px); overflow-y: auto; }
.tjobline { margin: -2px 0 12px; }
.tquote { margin: 0 0 12px; padding: 8px 12px; border-left: 3px solid var(--line-strong); border-radius: 0 var(--r-sm) var(--r-sm) 0; background: var(--surface-2); }
.tquote p { margin: 4px 0; color: var(--text); font-size: 14px; white-space: pre-wrap; overflow-wrap: anywhere; }
.tdue { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.tdue input { width: auto; flex: 1 1 150px; }
.tdue .chips { margin: 0; }
.tprio .ring { width: 13px; height: 13px; border-radius: 50%; border: 3px solid var(--good); }
.tprio.p-high .ring { border-color: var(--warn); }
.tprio.p-urgent .ring { border-color: var(--bad); }
.dialog.sheet { align-items: flex-end; padding: 0; }
.dialog.sheet .dialog-card { width: 100%; max-height: 92dvh; border-radius: var(--r-lg) var(--r-lg) 0 0; border-bottom: 0;
  padding-bottom: calc(14px + env(safe-area-inset-bottom)); }
.dialog.sheet .tkactions { position: sticky; bottom: calc(-14px - env(safe-area-inset-bottom)); margin: 0 -18px; padding: 12px 18px;
  background: var(--surface); border-top: 1px solid var(--line); }

/* Setup → Message tags */
.tagrows { margin: 0 0 12px; }
.tagrow { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--line); }
.tagrow:last-child { border-bottom: 0; }
.tagrow input { flex: 1; min-width: 0; min-height: 38px; padding: 6px 10px; }
.tagrow .micro { white-space: nowrap; }
.tagrow.archived input { color: var(--dim); }
.swatches { display: flex; flex-wrap: wrap; gap: 4px; }
.swatch { width: 36px; height: 36px; padding: 0; border-radius: 50%; border: 1px solid var(--line-strong); background: var(--surface);
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
.swatch .tdot { width: 16px; height: 16px; }
.swatch[aria-pressed="true"] { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--text); }
@media (pointer: coarse), (max-width: 780px) { .swatch { width: var(--hit); height: var(--hit); } }
.tagadd { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; align-items: end; }
.tagadd .field { margin: 0; }
@media (max-width: 560px) { .tagadd { grid-template-columns: minmax(0, 1fr); } }

/* ================================================== phone targets, last word
   The 44 px rule again for the controls whose own rules come later in this
   file and would otherwise win: the lead page's rank, priority and status,
   list sorts and scopes, text links, and the toast's buttons. */
@media (pointer: coarse), (max-width: 780px) {
  select:not([multiple]), select.inline, .rolesel { min-height: var(--hit); }
  .rank, .jprio, button.link, .link, .pipe-foot .link, #toast .act, #toast .dis { min-height: var(--hit); display: inline-flex; align-items: center; }
  .lwho a, .kv2 dd a, .tjob { display: inline-flex; align-items: center; min-height: var(--hit); }
}

/* a contract the server refused (D-089) */

.eyebrow.bad { color: var(--bad); }
.rows small.refused { color: var(--bad); }
.badge.bad { background: color-mix(in srgb, var(--bad) 14%, transparent); color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, transparent); }

/* the Jobs list, drawn 300 rows at a time (D-089) */
.listmore { display: flex; justify-content: center; padding: 12px 0 16px; }
.listmore .micro { margin-left: 6px; text-transform: none; letter-spacing: 0; }

/* ---- the iPad app (ipad/, D-094) */
/* a report or contract opens over the app, where a browser would open a tab */
.docwin { position: fixed; inset: 0; z-index: 10000; display: flex; background: #f2f3f5;
  padding-top: env(safe-area-inset-top); }
.docwin iframe { flex: 1; width: 100%; height: 100%; border: 0; background: #f2f3f5; }
/* the privacy policy, terms and help, over the iPad app (ui.openPage) */
.pagewin { flex-direction: column; background: var(--surface); }
.pagewin .pagebar { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 8px 16px; border-bottom: 1px solid var(--line); color: var(--text); }
.pagewin .pagebar b { font-weight: 600; }
.pagewin iframe { background: var(--bg); min-height: 0; }
a.btn { text-decoration: none; }
/* under the status bar: in a browser the address bar sits above the page */
/* the strip of the rail under the status bar takes the page's colour, so the
   whole status bar sits on one background and its text reads */
@media (min-width: 781px) { html.native #rail { border-top: env(safe-area-inset-top) solid var(--bg); } }
html.native .topbar { padding-top: calc(14px + env(safe-area-inset-top)); }
