/* DoorFlow design system — tokens lifted directly from crm-mockup.html */
/* ⭐ THE STANDARD TYPE (Stephen, 2026-10-18): Manrope headings, Inter for everything
   else, numbers included. IBM Plex Mono stays for keys, shortcuts and the
   'Technical' heading choice; Caveat for the handwritten notes. */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400..700&family=Manrope:wght@500..800&family=IBM+Plex+Mono:wght@400;500&family=Caveat:wght@500;600&display=swap');

:root {
  /* ⚠️ THE TOPBAR'S REAL HEIGHT, IN ONE PLACE. It was hardcoded as 49px in
     two sticky rules and as top:0 in a third, which is how the job header
     ended up pinned over the bar instead of under it. The bar grows with
     the notch in the installed app, so the offset has to as well. */
  --topbar-h: calc(49px + env(safe-area-inset-top, 0px));
  --navy: #0F1C2E;
  --navy-soft: #16273D;
  --navy-line: #26364C;
  --navy-text: #9AA7BD;
  --canvas: #F5F6F3;
  --ink: #1A2333;
  /* --text was never defined, so every `color: var(--text)` (the New menu,
     the profile menu, the nav menus) inherited whatever its parent wore;
     under a dark top bar that was white on a white menu (11/6). */
  --text: var(--ink);
  /* ⚠️ S11, Josh 2026-09-28: "Fonts need to be more pronounced." The grey
     secondary text is most of the words on a screen; it darkens a step
     (#666D79 → #525A67, #67707F → #5A6371) and so does its dark-mode twin. */
  --slate: #525A67;        /* was #666D79; #6B7280 before that */
  /* ⚠️ Was #98A2B3, which is 2.58:1 on white — well under AA, on the 12px
     labels and table headings used across every screen. A browser contrast
     audit run over the new billing panel turned it up app-wide. */
  --slate-light: #5A6371;
  --border: #E3E5E1;
  --blue: #2B6CB0;
  --blue-light: #EAF2FB;
  /* The brand tone ladder. One hue, nine designed stops: whisper tints for
     washes and hovers, a disciplined middle for actions, deep inks for text
     on tint. These defaults are the house blue; theme.js re-derives all of
     them from the company's accent so ANY brand color lands on these same
     lightness curves — that discipline, not the hue, is what looks designed. */
  --b50: #EFF5FB;
  --b100: #E0EBF7;
  --b200: #C6DBEE;
  --b300: #9DBEE0;
  --b400: #5E92C9;
  --b500: #3D7CBC;
  --b600: #2B6CB0;
  --b700: #245A94;
  --b800: #1C4776;
  --b900: #142F4E;
  --brand-wash: #F1F6FB;      /* the atmosphere: brand hue at 4% strength */
  --brand-glow: rgba(111, 168, 223, .45);
  --orange: #C2410C;       /* was #E8590C: 3.58:1 on white */
  --orange-light: #FDEEE5;
  --green: #177A41;        /* was #1F9D55: 3.49:1 on white, and it is
                              what every dollar figure is printed in */
  --green-deep: #177A41;   /* readable on --green-light */
  --green-light: #E8F6ED;
  --amber: #9A5B00;
  --amber-light: #FEF3E2;
  --red: #B3122F;
  --red-light: #FDECEE;

  --display: 'Manrope', system-ui, sans-serif;
  /* Numbers and counts used to be a typewriter face; Inter's own figures,
     set tabular on body, line up in columns without it. --code is the real
     monospace for API keys and keyboard shortcuts. */
  --mono: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --code: 'IBM Plex Mono', ui-monospace, Menlo, monospace;
  --body: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --radius: 10px;
  --radius-sm: 6px;
  /* Layered, not single-source: a tight contact shadow plus a soft ambient
     one is what makes a card sit ON the page instead of printing on it. */
  --shadow: 0 1px 2px rgba(15, 28, 46, .06), 0 4px 14px rgba(15, 28, 46, .05);
  --shadow-pop: 0 8px 28px rgba(15, 28, 46, .16);
  --shadow-lift: 0 2px 4px rgba(15, 28, 46, .06), 0 14px 30px rgba(15, 28, 46, .13);
  --surface-glass: rgba(255, 255, 255, .72);

  /* Cards, bars, modals — everything that used to be hard #fff. One token
     so dark mode is a re-mapping, not a rewrite. */
  --surface: #ffffff;
  /* ⚠️ --raise WAS NEVER DEFINED. Four rules already asked for it — the
     avatar menu's hover, the leaderboard's "this row is you" highlight, the
     photo tile's placeholder — and every one of them resolved to nothing
     and rendered as no change at all. One step up off the surface: hover
     states, menu rows, the ground under a thumbnail. */
  --raise: #F0F2F6;
  --ai-wash: #FCFDFF;
  --sk-base: #ECEDE9;
  --sk-shine: rgba(255, 255, 255, .55);
  color-scheme: light;
}

/* Dark mode — the rail's navy family extended to the whole app. Applied by
   data-theme on <html> (set from Settings; "auto" follows the OS). The tint
   pairs (--blue-light etc.) flip from pastel-on-white to deep-on-dark: same
   token, same meaning, readable ink either way. */
:root[data-theme="dark"] {
  --canvas: #0C1420;
  --surface: #16202F;
  --raise: #1F2A3C;
  --ink: #E8EDF5;
  --slate: #B3BDCC;
  --slate-light: #A2ADBF;
  --border: #283449;
  --navy: #0A111C;
  --navy-soft: #1B2A40;
  --navy-line: #223045;
  --navy-text: #93A1B8;
  --blue: #6FA8DF;
  --blue-light: #1C2E45;
  /* dark ladder: same meanings, flipped values — tints go deep, inks go light,
     so "b50 background + b700 text" reads correctly in both themes */
  --b50: #1C2E45;
  --b100: #223850;
  --b200: #2C4560;
  --b300: #3D5B7E;
  --b400: #5885B3;
  --b500: #6FA8DF;
  --b600: #6FA8DF;
  --b700: #8FBCE8;
  --b800: #B0D0F0;
  --b900: #D2E4F7;
  --brand-wash: #101B2B;
  --brand-glow: rgba(111, 168, 223, .30);
  --orange: #F09A6A;
  --orange-light: #3A2417;
  --green: #5FC389;
  --green-deep: #5FC389;
  --green-light: #14301F;
  --amber: #E0A94F;
  --amber-light: #33270F;
  --red: #F07E90;
  --red-light: #3A1620;
  --shadow: 0 1px 2px rgba(0, 0, 0, .35), 0 5px 16px rgba(0, 0, 0, .25);
  --shadow-pop: 0 8px 28px rgba(0, 0, 0, .55);
  --shadow-lift: 0 2px 4px rgba(0, 0, 0, .4), 0 14px 30px rgba(0, 0, 0, .45);
  --surface-glass: rgba(22, 32, 47, .72);
  --ai-wash: #172133;
  --sk-base: #1F2A3C;
  --sk-shine: rgba(255, 255, 255, .07);
  color-scheme: dark;
}

/* ------------------------------------------------- ask the stack */
.ask-panel { position: fixed; inset: 0; z-index: 110; pointer-events: none; }
.ask-scrim {
  position: absolute; inset: 0; background: rgba(10, 16, 26, .35);
  opacity: 0; transition: opacity .22s; pointer-events: auto;
}
.ask-sheet {
  position: absolute; top: 0; right: 0; bottom: 0; width: min(430px, 100vw);
  background: var(--surface); border-left: 1px solid var(--border);
  display: flex; flex-direction: column; pointer-events: auto;
  transform: translateX(100%); transition: transform .24s cubic-bezier(.4, 0, .2, 1);
  box-shadow: -12px 0 40px rgba(10, 16, 26, .18);
  /* iOS: 100% of the LAYOUT viewport can run under Safari's bottom bar and
     the home indicator, which is exactly how Joshua's screenshot lost the
     composer. dvh tracks what is actually visible. */
  height: 100dvh; max-height: 100dvh;
}
.ask-panel.open .ask-scrim { opacity: 1; }
.ask-panel.open .ask-sheet { transform: none; }
.ask-head {
  display: flex; align-items: center; gap: 10px; padding: 14px 16px;
  padding-top: calc(14px + env(safe-area-inset-top, 0px));
  border-bottom: 1px solid var(--border);
}
.ask-head h3 { font-size: 15px; margin: 0; }
.ask-thread { flex: 1; overflow-y: auto; padding: 16px; display: flex;
  flex-direction: column; gap: 10px; }
/* the conversation lives DOWN by the composer, like every messaging app —
   an empty panel is a greeting above the input, not a bubble floating over
   a screenful of nothing (Joshua's screenshot, 8/30) */
.ask-thread > :first-child { margin-top: auto; }
.ask-q {
  align-self: flex-end; max-width: 82%; background: var(--blue); color: #fff;
  border-radius: 14px 14px 4px 14px; padding: 9px 13px; font-size: 13.5px;
}
.ask-a { align-self: flex-start; max-width: 88%; }
.ask-a-text {
  background: var(--canvas); border-radius: 14px 14px 14px 4px;
  padding: 10px 13px; font-size: 13.5px; line-height: 1.55; white-space: pre-wrap;
}
.ask-a-text.thinking { color: var(--slate); font-style: italic; }
.ask-jobs { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.ask-docs { font-size: 12px; margin: 6px 0 0; }
.ask-docs a { color: inherit; text-decoration: underline; }
.ask-report { margin-top: 9px; border: 1px solid var(--border); border-radius: 10px; padding: 8px 10px; background: var(--card, transparent); }
.ask-report-h { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; margin-bottom: 6px; }
.ask-bars { display: grid; gap: 4px; }
.ask-bar { display: grid; grid-template-columns: minmax(60px, 34%) 1fr auto; align-items: center; gap: 8px; font-size: 12px; }
.ask-bar-l { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ask-bar-t { height: 10px; background: var(--border); border-radius: 5px; overflow: hidden; }
.ask-bar-t i { display: block; height: 100%; background: var(--accent, #2f6fed); border-radius: 5px; }
.ask-bar-v { font-variant-numeric: tabular-nums; white-space: nowrap; }
.ask-stats { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 12.5px; }
.ask-stat b { font-size: 15px; font-variant-numeric: tabular-nums; }
.ask-table-wrap { overflow-x: auto; margin-top: 6px; }
.ask-table { border-collapse: collapse; font-size: 11.5px; width: 100%; }
.ask-table th, .ask-table td { text-align: left; padding: 3px 6px; border-bottom: 1px solid var(--border); white-space: nowrap; }
.ask-table td { font-variant-numeric: tabular-nums; }
.ask-job {
  display: inline-flex; align-items: center; gap: 5px; font-size: 12px;
  font-weight: 600; color: var(--b700); background: var(--b50);
  border: 1px solid var(--b200); border-radius: 99px; padding: 4px 11px;
  text-decoration: none;
}
.ask-job:hover { border-color: var(--b400); }
.ask-foot {
  border-top: 1px solid var(--border);
  /* the home-indicator strip must never sit ON the input row */
  padding: 10px 14px calc(14px + env(safe-area-inset-bottom, 0px));
}
.ask-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.ask-chip {
  border: 1px solid var(--border); background: var(--surface); color: var(--slate);
  border-radius: 99px; padding: 5px 12px; font-size: 12px; cursor: pointer;
  font-family: var(--body); transition: border-color .15s, color .15s;
}
.ask-chip:hover { border-color: var(--b300); color: var(--ink); }
.ask-inrow { display: flex; gap: 8px; }
.ask-inrow input { flex: 1; }
@media (max-width: 760px) {
  .ask-sheet { width: 100vw; border-left: 0; }
}

/* action confirm cards: the model proposed, the person decides */
.ask-acts { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.ask-act {
  background: var(--surface); border: 1px solid var(--b200);
  border-left: 3px solid var(--b500); border-radius: 11px; padding: 11px 13px;
  box-shadow: var(--shadow);
}
.ask-act-head { display: flex; align-items: center; gap: 7px; font-size: 12.5px; }
.ask-act-head svg { color: var(--b600); }
.ask-act-why { font-size: 12px; color: var(--slate); margin: 5px 0 0; }
.ask-act-fields { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 9px; }
.ask-act-fields input, .ask-act-fields select, .ask-act-fields textarea {
  font-size: 12.5px; padding: 6px 9px; flex: 1; min-width: 120px;
}
.ask-act-fields textarea { width: 100%; flex-basis: 100%; }
.ask-act-btns { display: flex; justify-content: flex-end; gap: 7px; margin-top: 9px; }
.ask-act-done { font-size: 13px; color: var(--green); font-weight: 600;
  display: flex; align-items: center; flex-wrap: wrap; }
.ask-act-err { font-size: 12px; color: var(--red); margin: 7px 0 0; }

/* storm day: the one banner allowed to shout */
.storm-banner {
  border-left: 4px solid var(--amber);
  background: linear-gradient(100deg, var(--amber-light), var(--surface) 65%);
}
.storm-flash { font-size: 22px; animation: storm-flash 2.4s ease-in-out infinite; }
@keyframes storm-flash { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) { .storm-flash { animation: none; } }

/* the stack noticed — the proactive card */
.nudge-row { padding: 9px 0; border-top: 1px solid var(--border); }
.nudge-row:first-of-type { border-top: 0; }

/* the brief, talking back */
.brief-job { font-weight: 700; color: var(--b700); text-decoration: none;
  border-bottom: 1px dashed var(--b300); }
.brief-job:hover { color: var(--b500); }
.brief-in { opacity: 0; transform: translateY(8px);
  animation: brief-rise .5s cubic-bezier(.2, .7, .3, 1) forwards; }
@keyframes brief-rise { to { opacity: 1; transform: none; } }
.brief-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
@media (prefers-reduced-motion: reduce) {
  .brief-in { animation: none; opacity: 1; transform: none; }
  .ask-sheet, .ask-scrim { transition: none; }
}

/* night polish: in the dark theme the trend lines and goal bars GLOW in the
   company's hue — the command-center look. Light theme stays matte. */
:root[data-theme="dark"] .spark polyline,
:root[data-theme="dark"] .spark path {
  filter: drop-shadow(0 0 5px var(--brand-glow));
}
:root[data-theme="dark"] .goal-bar i {
  box-shadow: 0 0 10px var(--brand-glow);
}

/* the first win: ring draws, check lands, the light passes over — once */
.win-moment { text-align: center; padding: 10px 6px 4px; position: relative; overflow: hidden; }
.win-moment h2 { font-size: 21px; margin: 4px 0 2px; }
.win-moment .win-amt {
  font-family: var(--display); font-size: 30px; font-weight: 700;
  color: var(--b700); margin: 6px 0 2px; font-variant-numeric: tabular-nums;
}
.win-ring { width: 72px; height: 72px; display: block; margin: 0 auto 10px; }
.win-ring circle { fill: none; stroke: var(--b100); stroke-width: 5; }
.win-ring .arc {
  stroke: var(--b500); stroke-dasharray: 214; stroke-dashoffset: 214;
  stroke-linecap: round; transform: rotate(-90deg); transform-origin: center;
}
.win-moment.play .arc { animation: win-draw .9s .15s cubic-bezier(.4, 0, .2, 1) forwards; }
.win-ring .chk {
  fill: none; stroke: var(--b600); stroke-width: 5.5; stroke-linecap: round;
  stroke-linejoin: round; stroke-dasharray: 60; stroke-dashoffset: 60;
}
.win-moment.play .chk { animation: win-draw .5s .95s cubic-bezier(.4, 0, .2, 1) forwards; }
@keyframes win-draw { to { stroke-dashoffset: 0; } }
.win-moment::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(115deg, transparent 42%, var(--sk-shine) 50%, transparent 58%);
  transform: translateX(-120%);
}
.win-moment.play::before { animation: win-shine 1.3s 1.4s ease forwards; }
@keyframes win-shine { to { transform: translateX(120%); } }
@media (prefers-reduced-motion: reduce) {
  .win-moment .arc, .win-moment .chk { stroke-dashoffset: 0; animation: none; }
  .win-moment::before { display: none; }
}

/* the crew walks in: roster avatars arrive with a small spring, staggered —
   the owner watches the team fill up instead of reading that it did */
tr[data-person] .avatar { animation: crew-pop .45s cubic-bezier(.2, 1.4, .4, 1) backwards; }
tr[data-person]:nth-child(2) .avatar { animation-delay: .07s; }
tr[data-person]:nth-child(3) .avatar { animation-delay: .14s; }
tr[data-person]:nth-child(4) .avatar { animation-delay: .21s; }
tr[data-person]:nth-child(5) .avatar { animation-delay: .28s; }
tr[data-person]:nth-child(6) .avatar { animation-delay: .35s; }
tr[data-person]:nth-child(n+7) .avatar { animation-delay: .4s; }
@keyframes crew-pop { from { transform: scale(0); } }
@media (prefers-reduced-motion: reduce) { tr[data-person] .avatar { animation: none; } }

/* the lit runway: setup progress in the company's own color */
.rw-track {
  height: 5px; border-radius: 99px; background: var(--b100);
  overflow: hidden; margin-bottom: 6px;
}
.rw-track i {
  display: block; height: 100%; border-radius: 99px; background: var(--b500);
  transition: width .6s cubic-bezier(.4, 0, .2, 1);
}
.rw-tick {
  flex: none; width: 18px; height: 18px; border-radius: 50%;
  border: 1.5px solid var(--border); display: inline-flex;
  align-items: center; justify-content: center;
  font-size: 10px; color: #fff; transition: background .35s, border-color .35s;
}
.rw-tick.done { background: var(--b500); border-color: var(--b500); }
.rw-tick.done::after { content: '✓'; }
.rw-row.done > span:nth-child(2) { color: var(--slate); text-decoration: line-through;
  text-decoration-thickness: 1px; text-decoration-color: var(--slate-light); }

/* the brand-reveal sweep: their new color as light passing over the app */
.brand-reveal {
  position: fixed; inset: 0; z-index: 200; pointer-events: none;
  background: radial-gradient(circle at 28px 28px,
    var(--b500) 0%, var(--b300) 45%, transparent 72%);
  opacity: 0; clip-path: circle(0% at 28px 28px);
}
.brand-reveal.go { animation: brand-sweep 1.7s cubic-bezier(.4, 0, .2, 1) forwards; }
@keyframes brand-sweep {
  0% { clip-path: circle(0% at 28px 28px); opacity: .5; }
  55% { opacity: .28; }
  100% { clip-path: circle(165% at 28px 28px); opacity: 0; }
}

/* the brand-from-website stage: the scan, then the arrival */
.brand-stage { position: fixed; inset: 0; z-index: 210; display: flex; align-items: center; justify-content: center;
  opacity: 0; transition: opacity .35s ease; pointer-events: none; }
.brand-stage.on { opacity: 1; pointer-events: auto; }
.brand-stage.leave { opacity: 0; transition: opacity .8s ease; }
.bs-back { position: absolute; inset: 0; background: rgba(8, 11, 18, .78); backdrop-filter: blur(10px) saturate(1.2); -webkit-backdrop-filter: blur(10px) saturate(1.2); }
.bs-scan { position: relative; text-align: center; color: #fff; width: min(560px, 92vw); }
.bs-aurora { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.bs-aurora i { position: absolute; width: 46vmax; height: 46vmax; border-radius: 50%; filter: blur(70px); opacity: .55; mix-blend-mode: screen;
               transition: background 1.2s ease; animation: bs-drift 14s ease-in-out infinite alternate; }
.bs-aurora i:nth-child(1) { left: -10vmax; top: -12vmax; background: #2b6cb0; }
.bs-aurora i:nth-child(2) { right: -12vmax; top: 10vmax; background: #7c3aed; animation-delay: -5s; }
.bs-aurora i:nth-child(3) { left: 20vmax; bottom: -18vmax; background: #0ea5a4; animation-delay: -9s; }
@keyframes bs-drift { from { transform: translate(0, 0) scale(1); } to { transform: translate(6vmax, -4vmax) scale(1.15); } }
.bs-card { margin: 0 auto; padding: 34px 34px 28px; border-radius: 22px; background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.18);
           backdrop-filter: blur(18px) saturate(1.4); -webkit-backdrop-filter: blur(18px) saturate(1.4); box-shadow: 0 30px 80px rgba(0,0,0,.45); }
.bs-eyebrow { font-size: 11.5px; letter-spacing: .14em; text-transform: uppercase; color: rgba(255,255,255,.7); margin-bottom: 8px; }
.bs-host { font: 700 40px/1.1 var(--display, system-ui, sans-serif); letter-spacing: -.01em; color: #fff; white-space: nowrap; overflow: hidden; min-height: 1.1em; }
.bs-caret { display: inline-block; width: 3px; height: .9em; background: #fff; margin-left: 3px; vertical-align: -.1em; animation: bs-caret 1s steps(2) infinite; }
@keyframes bs-caret { 50% { opacity: 0 } }
.bs-wipe { position: absolute; inset: -20%; pointer-events: none; opacity: 0; transform: scale(.2); transition: opacity 1.4s ease, transform 1.6s cubic-bezier(.2, .8, .2, 1); mix-blend-mode: screen; }
.bs-wipe.go { opacity: .55; transform: scale(1.3); }
.bs-mark { position: relative; }
.bs-ring { position: absolute; inset: -14px; width: calc(100% + 28px); height: calc(100% + 28px); transform: rotate(-90deg); }
.bs-ring circle { stroke-dasharray: 295; stroke-dashoffset: 295; animation: bs-draw 1.1s cubic-bezier(.4, 0, .2, 1) .35s forwards; opacity: .9; }
@keyframes bs-draw { to { stroke-dashoffset: 0; } }
.bs-swatches span { position: relative; }
.bs-swatches span i { position: absolute; left: 50%; top: calc(100% + 6px); transform: translateX(-50%); font: 600 10px/1 ui-monospace, Menlo, monospace; color: rgba(255,255,255,.7); font-style: normal; letter-spacing: .03em; white-space: nowrap; }
.bs-name span { background: linear-gradient(100deg, #fff 30%, #ffe8b3 50%, #fff 70%); background-size: 200% 100%; -webkit-background-clip: text; background-clip: text; color: transparent; animation: bs-sheen 2.4s ease 1.2s 1; }
@keyframes bs-sheen { from { background-position: 100% 0 } to { background-position: -100% 0 } }
.bs-bar { height: 3px; border-radius: 2px; background: rgba(255,255,255,.18); margin: 22px auto 0; width: 72%; overflow: hidden; }
.bs-bar i { display: block; height: 100%; width: 10%; border-radius: 2px; background: linear-gradient(90deg, #8fc1ff, #fff); transition: width 1.3s cubic-bezier(.4, 0, .2, 1); box-shadow: 0 0 18px rgba(255,255,255,.7); }
.bs-step { margin: 16px 0 0; font-size: 15px; color: #e6eaf2; transition: opacity .18s, transform .18s; }
.bs-step.swap { opacity: 0; transform: translateY(6px); }
/* the arrival */
.brand-stage.arrive .bs-scan { animation: none; }
.bs-mark { width: min(148px, 24vh); height: min(148px, 24vh); margin: 0 auto; border-radius: min(32px, 5vh); background: #fff; display: flex; align-items: center; justify-content: center;
  box-shadow: 0 30px 80px rgba(0,0,0,.55), 0 0 0 10px rgba(255,255,255,.06); overflow: hidden;
  animation: bs-spring .9s cubic-bezier(.2, 1.4, .4, 1) both; }
.bs-mark img { max-width: 78%; max-height: 78%; object-fit: contain; }
.bs-initials { font: 700 46px/1 var(--display, system-ui, sans-serif); color: var(--b500, #2563eb); }
.bs-swatches { display: flex; justify-content: center; gap: 10px; margin: 26px 0 0; }
.bs-swatches span { width: min(44px, 9vw); height: min(44px, 9vw); border-radius: 12px; box-shadow: 0 10px 24px rgba(0,0,0,.4), inset 0 0 0 1px rgba(255,255,255,.18);
  opacity: 0; transform: translateY(18px) scale(.6); animation: bs-pop .55s cubic-bezier(.2, 1.3, .4, 1) forwards; }
.bs-name { margin: 26px 0 0; font: 700 clamp(26px, 5vw, 40px)/1.1 var(--display, system-ui, sans-serif); letter-spacing: -.01em;
  opacity: 0; animation: bs-rise .6s ease forwards; animation-delay: .9s; }
.bs-sub { margin: 10px auto 0; max-width: 46ch; font-size: 14px; color: #b7c0cf; opacity: 0; animation: bs-rise .6s ease forwards; animation-delay: 1.15s; }
.bs-sweep { position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: radial-gradient(circle at 50% 42%, var(--b500) 0%, var(--b300) 40%, transparent 70%);
  clip-path: circle(0% at 50% 42%); }
.bs-sweep.go { animation: bs-sweep 1.5s cubic-bezier(.4, 0, .2, 1) forwards; }
@keyframes bs-spring { 0% { opacity: 0; transform: perspective(600px) rotateY(-70deg) scale(.6); } 60% { opacity: 1; transform: perspective(600px) rotateY(12deg) scale(1.04); } 100% { opacity: 1; transform: perspective(600px) rotateY(0) scale(1); } }
@keyframes bs-pop { to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes bs-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
@keyframes bs-sweep { 0% { clip-path: circle(0% at 50% 42%); opacity: .75; } 60% { opacity: .35; } 100% { clip-path: circle(160% at 50% 42%); opacity: 0; } }
.bs-use { margin: 22px auto 0; display: inline-flex; background: #fff; color: #17202d; font-weight: 700; padding: 10px 18px; border-radius: 12px; border: 0; box-shadow: 0 10px 30px rgba(0,0,0,.35); opacity: 0; animation: bs-rise .6s ease forwards; animation-delay: 1.4s; }
@media (prefers-reduced-motion: reduce) { .bs-aurora i, .bs-mark, .bs-swatches span, .bs-name, .bs-sub, .bs-use { animation: none !important; opacity: 1 !important; transform: none !important; } }

/* shimmer placeholders while a screen's data is on the wire */
.sk {
  position: relative; overflow: hidden; border-radius: 6px;
  background: var(--sk-base);
}
.sk::after {
  content: ''; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, var(--sk-shine), transparent);
  animation: sk-shine 1.3s infinite;
}
@keyframes sk-shine { to { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .sk::after { animation: none; } }

/* stat-card trims: the trend line and the vs-last-period chip */
.stat .spark { display: block; margin-top: 8px; width: 100%; max-width: 150px; }
.delta {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0;
  text-transform: none; margin-left: 7px; border-radius: 4px; padding: 1px 5px;
}
.delta.up { color: var(--green); background: var(--green-light); }
.delta.down { color: var(--red); background: var(--red-light); }

/* chart bars grow in from the floor */
.bars .bar {
  animation: bar-grow .55s cubic-bezier(.2, .8, .3, 1) backwards;
  transform-origin: bottom;
}
@keyframes bar-grow { from { transform: scaleY(0); } }
@media (prefers-reduced-motion: reduce) { .bars .bar { animation: none; } }

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--body);
  font-variant-numeric: tabular-nums;
  /* Stephen, 2026-09-06: "I wouldn't mind using slightly larger fonts as
     well throughout." 14 → 15. Everything sized in rem/em follows; the
     handful of hard-coded 12-13px labels are lifted a point with it so the
     ladder keeps its shape rather than flattening. */
  font-size: 15px;
  /* S11: body copy a touch heavier; variable system fonts render 450 as a
     real weight, others round it to regular. */
  font-weight: 450;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { font-family: var(--display); font-weight: 600; margin: 0; }
a { color: var(--blue); text-decoration: none; }
button { font-family: inherit; }

.display { font-family: var(--display); font-weight: 600; }
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.micro {
  font-size: 12px; color: var(--slate); text-transform: uppercase; font-weight: 600;
  letter-spacing: .04em; margin: 0;
}
.muted { color: var(--slate); }
.dim { color: var(--slate-light); }
.right { text-align: right; }
.grow { flex: 1; }
.row { display: flex; align-items: center; gap: 10px; }
/* ⚠️ THE HIDDEN ATTRIBUTE ALWAYS HIDES (phone walk, 2026-11-06). Any class
   that sets `display` beats the browser's own [hidden] { display: none }.
   It was fixed one class at a time (.avatar-menu, .newmenu, .topnav-menu,
   .field) until the Jobs and Leads bulk bar (.row) showed "Reassign to"
   with nothing ticked. One rule for every element now. */
[hidden] { display: none !important; }
.wrap { flex-wrap: wrap; }
.hide { display: none !important; }

/* ------------------------------------------------------------------ shell */
#app { display: flex; flex-direction: column; min-height: 100vh; }

/* Frosted glass: the page scrolls UNDER the topbar, softly visible through
   it, with a whisper of the brand hue as a hairline along its bottom edge.
   The solid --surface fallback keeps old WebViews readable. */
.topbar {
  display: flex; align-items: center; gap: 14px;
  padding: 11px 20px; background: var(--surface);
  /* viewport-fit=cover: in the installed app the sheet reaches the notch,
     so the bar wears the status area rather than hiding under it */
  padding-top: calc(11px + env(safe-area-inset-top, 0px));
  background: var(--surface-glass);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  backdrop-filter: blur(14px) saturate(1.4);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 40;
}
.topbar::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: linear-gradient(90deg, transparent, var(--b300), transparent);
  opacity: .5; pointer-events: none;
}

/* A button now, because it is the way home from anywhere. It must not
   look like one — the mark and the company name ARE the affordance. */
.brand { display: flex; align-items: center; gap: 9px; flex: 0 0 auto;
  border: 0; background: transparent; padding: 0; cursor: pointer;
  font: inherit; color: inherit; border-radius: var(--radius-sm); }
.brand:hover { opacity: .82; }
.brand:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
.brand-mark {
  width: 26px; height: 26px; border-radius: var(--radius-sm);
  background: var(--navy); color: #fff;
  display: flex; align-items: center; justify-content: center;
}
.brand-name { font-family: var(--display); font-weight: 700; font-size: 15px; white-space: nowrap; }
.brand-co {
  font-size: 12px; color: var(--slate); padding-left: 10px; margin-left: 2px;
  border-left: 1px solid var(--border);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* the company's own logo, worn in the topbar next to the product name */
.brand-logo {
  height: 22px; max-width: 96px; object-fit: contain;
  margin-left: 10px; padding-left: 10px; border-left: 1px solid var(--border);
}
@media (max-width: 760px) { .brand-logo { display: none; } }
/* With a mark on file the company IS the identity: their logo leads, their
   name beside it, and the product demotes to a quiet tag. Their app. */
.brand-logo.lead {
  height: 28px; max-width: 140px; margin-left: 0; padding-left: 0;
  border-left: 0;
}
@media (max-width: 760px) { .brand-logo.lead { display: block; } }
.brand-co.lead {
  font-family: var(--display); font-weight: 700; font-size: 15px;
  color: inherit; white-space: nowrap;
}
.brand-product {
  font-size: 10.5px; color: var(--slate-light); white-space: nowrap;
  margin-left: 10px; padding-left: 10px; border-left: 1px solid var(--border);
}
@media (max-width: 900px) { .brand-product { display: none; } }

/* Moved out of the middle and in beside Feedback and Ask, where he wanted
   it. Narrower there, and it gives way first when the nav needs the room. */
.searchbox {
  display: flex; align-items: center; gap: 7px; margin-left: 0;
  background: var(--canvas); border: 1px solid transparent;
  border-radius: var(--radius-sm); padding: 6px 10px;
  /* 210, not 240: those 30px are the difference between nine nav groups
     fitting a 1440 laptop and one of them dropping into More. */
  width: clamp(150px, 15vw, 210px); flex: 0 1 auto; min-width: 0;
}
/* ⚠️ Between the phone breakpoint and 1100px the box used to vanish and the
   toggle had not arrived yet: no search at all on a tablet or a narrow
   window (the self-test caught it at 1024px, 2026-09-11). The box now
   stays (the ≤1180px rule below already narrows it to 160px) until the
   phone toggle takes over at 760px. */
.searchbox:focus-within { border-color: var(--blue); background: var(--surface); }
/* The top search's drop list (11/3): customers by any part of the name. */
.searchbox { position: relative; }
.topsearch {
  position: absolute; top: calc(100% + 6px); right: 0; width: min(420px, 92vw);
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: var(--shadow-pop); padding: 6px; z-index: 80; max-height: 60vh; overflow-y: auto;
}
.topsearch-row {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 8px;
  cursor: pointer; color: var(--ink); font-size: 13.5px; flex-wrap: wrap;
}
.topsearch-row svg { color: var(--slate); flex: 0 0 auto; }
.topsearch-row.on { background: var(--blue-light); }
.topsearch-text { flex: 1; min-width: 0; }
.topsearch-name { font-weight: 500; }
.topsearch-detail { color: var(--slate); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topsearch-jobs { display: flex; gap: 4px; flex-wrap: wrap; }
.topsearch-empty { margin: 6px 10px; font-size: 12.5px; }
@media (max-width: 760px) { .topsearch { left: 0; right: 0; width: auto; } }
.searchbox input {
  border: 0; background: transparent; outline: none; width: 100%;
  font-size: 13px; color: var(--ink); font-family: var(--body);
}

.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 14px; }
/* Gap thirty-two: a sub's seat keeps Feedback and the avatar, nothing that
   searches, tags, notes, asks or creates across the company. */
.topbar-right.sub-seat .searchbox, .topbar-right.sub-seat #tagsWrap, .topbar-right.sub-seat #stickyNew,
.topbar-right.sub-seat #stickyMore, .topbar-right.sub-seat #stickyMenu, .topbar-right.sub-seat #needHelp,
.topbar-right.sub-seat #quickNew, .topbar-right.sub-seat #quickNewMenu { display: none !important; }

.avatar {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--blue-light); color: var(--blue);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 600; flex: 0 0 auto;
}
.avatar.lg { width: 36px; height: 36px; font-size: 13px; }
.avatar.sm { width: 22px; height: 22px; font-size: 9.5px; }
/* ⚠️ THE INITIALS SIT UNDERNEATH, ALWAYS. The photo is layered over them
   rather than replacing them, so a face that fails to load — a dropped
   request, an offline phone, a deleted file — leaves the person's initials
   showing instead of an empty blue circle. No onerror handler: a name with
   an apostrophe in it would end the attribute early and take the fallback
   with it, which is exactly how the last one broke. */
.avatar { position: relative; overflow: hidden; }
.avatar img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; border-radius: 50%;
}

/* The avatar is where everybody looks to sign out. It used to be a plain
   div that did nothing, so the only Sign out in the product sat inside
   Settings → Company, below a seat-code box — somewhere nobody would think
   to look, and impossible to find when what you want is to leave. */
.avatar-wrap { position: relative; flex: 0 0 auto; }
button.avatar { border: 0; cursor: pointer; font-family: inherit; }
.avatar-menu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 400;
  min-width: 208px; padding: 6px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.28);
}
.avatar-menu[hidden] { display: none; }
.avatar-menu .who {
  padding: 8px 10px 10px; border-bottom: 1px solid var(--line);
  margin-bottom: 6px; line-height: 1.4;
}
.avatar-menu .who b { display: block; font-size: 13px; }
.avatar-menu .who span { font-size: 12px; color: var(--muted);
                         word-break: break-all; }
.avatar-menu button, .avatar-menu a[role="menuitem"] {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 8px 10px; border: 0; border-radius: 7px; cursor: pointer;
  background: transparent; color: var(--text); font: inherit;
  font-size: 13px; text-align: left;
}
.avatar-menu button:hover, .avatar-menu a[role="menuitem"]:hover { background: var(--raise); }
.avatar-menu button.danger { color: var(--red); }

/* Josh's plus button (@9:13): "to have the same thing… a very similar
   setup." Same furniture as the avatar menu, and ⚠️ the same [hidden] rule
   with it — a class that sets `display` beats the UA's [hidden]{display:none}
   and the menu renders permanently. That exact omission is what made all
   five nav dropdowns sit open on screen for a day. */
.newmenu-wrap { position: relative; }
.newmenu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 400;
  min-width: 190px; padding: 6px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.28);
}
.newmenu[hidden] { display: none; }
.newmenu button {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 8px 10px; border: 0; border-radius: 7px; cursor: pointer;
  background: transparent; color: var(--text); font: inherit;
  font-size: 13px; text-align: left;
}
.newmenu button:hover { background: var(--raise); }

/* The job picker the plus menu opens when what you are starting has to
   belong to a job. Scrolls inside itself — a shop with 400 open jobs must
   not push the search box off the top of the modal. */
.pick-list { max-height: 46vh; overflow-y: auto; margin-top: 6px; }
.pick-row {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: 9px 10px; border: 0; border-radius: 8px; background: transparent;
  color: var(--text); font: inherit;
}
.pick-row:hover { background: var(--raise); }
.pick-row b { display: block; font-size: 13.5px; }
.pick-row span { font-size: 12px; color: var(--muted); }

.shell { display: flex; flex: 1; min-height: 0; }

/* ------------------------------------------------------------- top nav
   Josh's review, 2026-09-04: the sidebar goes and the groupings become
   dropdowns along the top. "That gets rid of these really awful-looking
   whatevers… it kind of opens it up a little bit better."
   ⚠️ DESKTOP ONLY — under 760px this strip is gone and the tabbar plus its
   More pop-out take over unchanged, because he was explicit that a
   dropdown is miserable to hit with a thumb. */
/* ⚠️ overflow-x MUST STAY VISIBLE, and this is the whole bug behind "the
   dropdowns don't go to anything". The strip is 29px tall; every menu is
   absolutely positioned BELOW it, from y=54 down. `overflow-x: auto` here
   computes to `overflow-y: auto` too — the spec forbids one axis being
   visible while the other scrolls — so every dropdown was CLIPPED away
   entirely: not painted, not hit-testable, while getBoundingClientRect()
   happily reported its full height, because rects ignore clipping. That is
   why it survived a self test that measured height.
   Nothing is lost by removing it: renderTopNav() already measures the strip
   and moves what does not fit into More, which is the deliberate answer to
   this exact problem — see the note there about a scrollbar nobody knows is
   there. scrollWidth still reports overflow with visible, so the fitting
   loop is unaffected. */
.topnav { display: flex; align-items: center; gap: 2px; flex: 1;
  min-width: 0; overflow: visible; }
.topnav-link {
  border: 0; background: transparent; cursor: pointer; white-space: nowrap;
  font: inherit; font-size: 13px; color: var(--slate);
  /* 10px, not 12: nine groups at 12px overflow a 1440 laptop by a hair and
     one of them drops into More for no reason a user could see. */
  padding: 7px 10px; border-radius: var(--radius-sm);
  display: inline-flex; align-items: center; gap: 5px; text-decoration: none;
}
.topnav-link:hover { color: var(--ink); background: var(--raise); }
.topnav-link.on { color: var(--ink); background: var(--raise); font-weight: 600; }
.topnav-link:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
.topnav-group { position: relative; }
.topnav-menu {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 60;
  min-width: 232px; padding: 8px; border-radius: var(--radius);
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: 0 10px 30px rgba(15, 19, 26, .16);
  display: flex; flex-direction: column; gap: 1px;
}
/* ⚠️ WITHOUT THIS THE NAV IS DECORATION. `display: flex` above beats the
   browser's own [hidden] { display: none }, so every dropdown rendered at
   full size on top of the page permanently, and clicking a group toggled an
   attribute that changed nothing anybody could see. Reported from the live
   site as "these don't go to anything", which is exactly right.
   Same trap as .field[hidden]: in this file, any class that sets `display`
   and is toggled by the hidden ATTRIBUTE must say so itself. */
.topnav-menu[hidden] { display: none; }
.topnav-blurb {
  margin: 2px 6px 7px; font-size: 11.5px; line-height: 1.4;
  color: var(--slate);
}
.topnav-menu a, .topnav-menu button {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 8px 9px; border: 0; background: transparent; cursor: pointer;
  font: inherit; font-size: 13.5px; color: var(--ink);
  border-radius: var(--radius-sm); text-align: left; text-decoration: none;
}
.topnav-menu a:hover, .topnav-menu button:hover { background: var(--raise); }
/* The overflow catch-all. Groups flatten into it under their own heading
   rather than nesting a second menu inside the first. Its panel hangs from
   the button's RIGHT edge — More is always the last thing in the strip, so
   anchoring left would push the panel off the window on a narrow one. */
.topnav-spill .topnav-menu { left: auto; right: 0; }
.topnav-menu .spill-head {
  margin: 9px 6px 3px; font-size: 10.5px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--slate);
}
.topnav-menu .spill-head:first-child { margin-top: 2px; }
@media (max-width: 760px) { .topnav { display: none; } }

/* ---- the two-row header (2026-09-16, "Five ways to find things" option 3).
   Row one is the tools, row two is the sections with nothing competing for
   the room, and the pages of the section you are in sit as chips at the top
   of the page. The sticky thing is the whole header now; syncTopbarHeight
   measures it, so --topbar-h already means both rows. */
.appbar { position: sticky; top: 0; z-index: 40; }
.appbar .topbar { position: relative; }
.secbar {
  display: flex; align-items: stretch; height: 42px; padding: 0 20px;
  background: var(--surface-glass);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  backdrop-filter: blur(14px) saturate(1.4);
  border-bottom: 1px solid var(--border);
}
.secbar .topnav { align-items: stretch; gap: 4px; }
.secbar .topnav-link {
  border-radius: 0; padding: 0 12px; font-size: 13.5px;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.secbar .topnav-link:hover { background: transparent; color: var(--ink); }
.secbar .topnav-link.on {
  background: transparent; color: var(--ink); font-weight: 600;
  border-bottom-color: var(--blue);
}
.secbar .topnav-group { display: flex; }
.secbar .topnav-menu { top: calc(100% + 2px); }
@media (min-width: 1181px) {
  .appbar .searchbox { width: clamp(200px, 22vw, 340px); }
}
.secpages { display: flex; flex-wrap: wrap; gap: 6px; margin: -6px 0 16px; }
.secpages[hidden] { display: none; }
.secpage {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px;
  border: 1px solid var(--border); border-radius: 999px;
  background: var(--surface); color: var(--ink); cursor: pointer;
  font: inherit; font-size: 13px; text-decoration: none; white-space: nowrap;
}
.secpage:hover { background: var(--raise); }
.secpage.on { border-color: var(--blue); background: var(--b50); color: var(--b800); font-weight: 600; }
.secpage:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
/* Tags reads like a missed-text badge on a phone: red, round, only when
   something is unread (Stephen, 2026-09-16). */
#tagsCount:not(:empty) {
  display: inline-block; min-width: 18px; height: 18px; padding: 0 5px;
  margin-left: 6px; border-radius: 999px; background: #D92D20; color: #fff;
  font-size: 11px; font-weight: 700; line-height: 18px; text-align: center;
}
@media (max-width: 760px) {
  .secbar, .secpages { display: none !important; }
}

/* The "what's next" line on a job — computed from the flow, not written by
   a model, so it reads as fact rather than as a suggestion. */
.next-line {
  margin: 0 0 4px; font-size: 13.5px; line-height: 1.5; color: var(--ink);
}
.next-stop {
  margin: 0 0 6px; font-size: 12.5px; color: var(--amber);
}

/* ---- the calendar (Josh's item 17) --------------------------------------
   A month is six rows of seven, always, so the grid does not change height
   as you page through and the "next" button stays under the cursor. */
.cal-grid {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 1px; background: var(--border); border: 1px solid var(--border);
  border-radius: 10px; overflow: hidden;
}
.cal-dow {
  background: var(--surface); padding: 7px 8px; font-size: 11.5px;
  text-transform: uppercase; letter-spacing: .05em; color: var(--slate);
  font-weight: 600;
}
.cal-cell {
  background: var(--surface); min-height: 96px; padding: 6px 6px 8px;
  display: flex; flex-direction: column; gap: 3px;
}
/* Days either side of the month are context, not content. */
.cal-out { opacity: .45; }
.cal-today { box-shadow: inset 0 0 0 2px var(--blue); }
.cal-num { font-size: 12px; font-weight: 600; color: var(--slate); }
.cal-week {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 1px; background: var(--border); border: 1px solid var(--border);
  border-radius: 10px; overflow: hidden;
}
.cal-col {
  background: var(--surface); min-height: 220px; padding: 8px;
  display: flex; flex-direction: column; gap: 4px;
}
.cal-colhead {
  font-size: 12px; color: var(--slate); margin-bottom: 2px;
}
/* The left edge carries whose it is. A chip has to survive a narrow column,
   so the title truncates and the full line lives in the tooltip. */
.cal-chip {
  display: block; font-size: 11.5px; line-height: 1.35; text-decoration: none;
  color: var(--ink); background: var(--b50);
  border-left: 3px solid var(--slate); border-radius: 4px;
  padding: 2px 5px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}
.cal-chip:hover { background: var(--b100); }
.cal-chip-t { font-weight: 600; margin-right: 4px; }
.cal-more {
  background: none; border: 0; padding: 1px 5px; cursor: pointer;
  font-size: 11px; color: var(--blue); text-align: left; width: auto;
}
.cal-dot {
  width: 9px; height: 9px; border-radius: 50%; display: inline-block;
  flex: 0 0 auto;
}
.cal-legend { font-size: 12.5px; align-items: center; cursor: pointer; }

/* The Apps tiles (Josh's item 21: "it's just very plain"). A tile is a
   card that ends in a row of doors, so the foot pins to the bottom however
   long the description above it runs — otherwise a two-line tile and a
   four-line tile put their buttons at different heights and the grid reads
   as broken. */
.app-tile { display: flex; flex-direction: column; }
.app-tile-foot {
  gap: 8px; align-items: center; margin-top: auto; padding-top: 14px;
}
.app-stat {
  display: flex; align-items: center; gap: 6px;
  margin: 12px 0 0; font-size: 12.5px; font-weight: 500;
  color: var(--green);
}

/* Their points, answered one at a time (Josh's item 13). */
.reply-point {
  padding: 8px 0; border-top: 1px solid var(--border);
}
.reply-point:first-of-type { border-top: 0; }

/* Drop the carrier's estimate in (Josh's item 12). */
.scope-drop {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  text-align: center; cursor: pointer; padding: 22px 16px;
  border: 2px dashed var(--border); border-radius: var(--radius);
  background: var(--raise); color: var(--slate); font-size: 13.5px;
  transition: border-color .15s, background .15s;
}
.scope-drop:hover, .scope-drop.over { border-color: var(--blue); background: var(--b50); }
.scope-drop.over { border-style: solid; }
.scope-drop.busy { opacity: .6; pointer-events: none; }
.scope-drop svg { color: var(--slate-light); }
.scope-drop b { color: var(--ink); }
/* The summary page's figures, every deduction its own box (11/6). */
.scope-totals { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 0 12px; }
/* Who pays which part of an approved price contract. */
.claim-split { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 14px; }
.claim-split > div { padding: 10px 12px; border-radius: var(--radius); background: var(--raise);
  display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.claim-split span { font-size: 12px; color: var(--slate); }
.claim-split b { font-size: 20px; font-family: var(--display); font-variant-numeric: tabular-nums; }
.claim-split small { font-size: 11.5px; color: var(--slate); line-height: 1.35; }
@media (max-width: 520px) { .claim-split { grid-template-columns: 1fr; } }
/* The scope into the estimate (11/6). */
.ins-make { border-color: #2B6CB033; }
.ins-make-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.ins-make-tiles > div, .ins-est-tiles > div { padding: 9px 11px; border-radius: var(--radius); background: var(--raise);
  display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.ins-make-tiles span, .ins-est-tiles span { font-size: 12px; color: var(--slate); }
.ins-make-tiles b, .ins-est-tiles b { font-size: 18px; font-family: var(--display); font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ins-make-tiles small, .ins-est-tiles small { font-size: 11.5px; color: var(--slate); line-height: 1.35; }
.ins-made { display: flex; flex-direction: column; gap: 6px; margin: 0 0 12px; }
.ins-made-row { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border: 1px solid var(--border);
  border-radius: var(--radius); font-size: 13px; }
@media (max-width: 720px) { .ins-make-tiles { grid-template-columns: 1fr 1fr; } }
/* An insurance estimate on the Estimate tab: the claim, who pays what, the
   carrier's lines under their sections. */
.ins-est { margin: 0 0 12px; }
.ins-est-claim { font-size: 13px; color: var(--slate); margin: 0 0 8px; }
.ins-est-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.ins-est-tiles > div.you { background: var(--blue-light); }
.opt-lines tr.ins-sec td { padding-top: 12px; font-size: 12px; font-weight: 700; color: var(--slate);
  text-transform: uppercase; letter-spacing: .04em; }
.opt-lines tr.ins-sub td { font-size: 12.5px; color: var(--slate); border-top: 1px dashed var(--border); }
.ins-flag { display: inline-block; margin-left: 6px; font-size: 11px; font-weight: 600; padding: 1px 6px;
  border-radius: 999px; vertical-align: 1px; }
.ins-flag.below { background: var(--amber-light); color: var(--amber); }
.ins-flag.nocost { background: var(--raise); color: var(--slate); }
.ins-margin { margin: 10px 0 0; font-size: 12.5px; color: var(--slate); }
@media (max-width: 560px) { .ins-est-tiles { grid-template-columns: 1fr; } }

/* ---- the company's mark, behind the work (Josh's item 2). "You just
   kind of know it's there." ⚠️ NOT see-through content: it is a layer
   BEHIND the cards, every one of which keeps its own opaque surface, so
   nothing on the page loses a point of contrast to it.
   ⚠️ THE BOX IS MEASURED, NOT DECLARED (2026-09-20). Stephen, on a screenshot
   of the Team page: "This shouldn't sit here like this" — the mark was sized
   in vh while a page head is sized in text, so it hung below the head and
   over the cards, and it was cut off where it ran into the page title. Every
   number that decides where it goes now comes from the head's own box in
   watermark.js; the rules here are the ones that hold whatever it measures:
   never painted at all until it has been placed, never on top of anything,
   never cropped. */
.brand-mark-wash {
  /* ⚠️ right: 0, NOT a negative offset. .main reports its scrollWidth even
     with overflow-x: clip, so a decorative layer hanging 60px past the edge
     makes the page's own width audit fail — a watermark is not worth a
     false "this page scrolls sideways" on every screen. */
  /* ⚠️ IT USED TO SIT BEHIND THE CARDS, AND THE CARDS ARE OPAQUE. Measured
     on the live dashboard: only 13% of the mark was unoccluded — the other
     87% was underneath .card backgrounds, so raising the opacity did
     nothing a person could see. That is the whole reason "the logo in the
     background" read as missing rather than subtle.
     The page head is genuinely empty ground on every screen, with the
     heading text ending a little way across. The mark lives THERE: still
     behind the work, still a watermark, but on ground where it can
     actually be seen — and only as much of that ground as the head has
     to spare. */
  position: absolute; top: 0; right: 0;
  /* ⚠️ HIDDEN UNTIL PLACED. A watermark that paints before it has been
     measured is a watermark in the wrong place for one frame, which on a
     slow phone is a frame somebody screenshots. placeWatermark() adds
     .is-placed, and only then. */
  display: none;
  width: 260px; height: 52px;
  background-repeat: no-repeat; background-position: center right;
  /* contain, so a wide wordmark scales to fit its box. It is never cropped:
     a mark cut off mid-word reads as a broken page, not as a brand. */
  background-size: contain;
  /* ⚠️ .045 WAS TOO QUIET TO COUNT AS A FEATURE. Stephen, 2026-09-05,
     looking at the live app: "Did you not hear Josh talk about the logo
     being in the background?" — it was there and nobody could see it.
     Josh's bar is "you just kind of know it's there", which is a mark you
     notice, not one you have to be told about; his only hard limit was
     that content must never look see-through. These values clear that bar
     from both sides. */
  opacity: .16; pointer-events: none; user-select: none; z-index: 0;
  will-change: transform;
}
.brand-mark-wash.is-placed { display: block; }
/* ⚠️ THE DARK VALUE NEEDS THE MEDIA QUERY AS WELL AS THE STAMP. Written as
   :root:not([data-theme="light"]) alone it matches the UNSTAMPED root — the
   default "follow the system" state — so every light-mode viewer got the
   dark opacity. Same shape as every other themed rule in this file. */
:root[data-theme="dark"] .brand-mark-wash { opacity: .20; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .brand-mark-wash { opacity: .20; }
}
@media (prefers-reduced-motion: reduce) {
  .brand-mark-wash { transform: none !important; }
}
/* The monogram flavour, for a company that has not uploaded a mark yet.
   Same box, same opacity ladder, same stacking — only the paint differs, so
   nothing about the layout changes when they DO upload one.
   ⚠️ NO font-size HERE. Type sized in vh inside a box sized in pixels is
   how two letters end up taller than the box holding them, which crops them
   mid-letter; watermark.js sizes them from the box it measured. */
.brand-mark-mono {
  font-family: var(--display, inherit);
  font-weight: 800; letter-spacing: -.04em;
  font-size: 40px; line-height: 1;
  color: var(--blue); user-select: none;
}
.brand-mark-mono.is-placed { display: flex; align-items: center; justify-content: flex-end; }

/* ⚠️ SCOPED TO #main, NOT .main. The view renders INTO #main, so that is
   where the watermark lands and that is the element that must be the
   containing block. Putting the stacking on .main instead would give the
   #main wrapper a z-index of its own and bury the watermark under the very
   children it is supposed to sit behind. */
#main { position: relative; }
#main > *:not(.brand-mark-wash) { position: relative; z-index: 1; }
@media (max-width: 760px) {
  /* On a phone the page head is worked ground, not spare ground: the title,
     the count and the one button fill it. watermark.js stands the mark down
     below 820px on its own; this is the backstop, so a phone can never paint
     it however the measuring goes. */
  .brand-mark-wash { display: none !important; }
}

/* ---- HOW MUCH BRAND (2026-09-20). Stephen: "when a team adds their URL, I
   want the colors and logos more prominent throughout the CRM and app."
   One stored word, two looks:
     light  nothing here applies. This is the app exactly as it has always
            been, and it is what a company with no website still gets.
     full   their color carries the page kickers, the empty states and the
            ground the work sits on, and their mark opens the day.
   ⚠️ EVERY BRAND-COLOURED WORD USES --brand-ink, WHICH IS DERIVED SERVER
   SIDE. It is brandkit's `deep` on a light theme and `light` on a dark one,
   each lifted until it clears 4.5:1 against the ground it is printed on, and
   tools/check_contrast sweeps 4096 colors through both. A raw accent must
   never become text: that is how a pale brand turns a sentence into a rumour.
   The fallback in every rule is the token the app used before, so a company
   whose palette has not loaded yet reads exactly as it did. */
/* ⚠️ THE GROUND TINT IS SET FROM theme.js, NOT HERE. Cancelling a custom
   property in a media query (--canvas: initial) does not put the stylesheet's
   value back — it leaves the property guaranteed-invalid, and every rule
   reading var(--canvas) then paints transparent. Writing the tint as an
   inline value and REMOVING it for the dark theme restores the cascade
   properly, so the same company is tinted paper by day and plain navy at
   night. A company that also chose a tone under the look dials keeps their
   tone: a named choice beats a derived one. */
/* The line above every page title. It is the one piece of type on a page
   that says nothing operational, which makes it the right place for a
   company to be. */
:root[data-brand-depth="full"] .page-head p {
  color: var(--brand-ink, var(--slate));
}
/* An empty state is where a company is most obviously looking at software
   rather than at their work, so it is worth wearing their color. */
:root[data-brand-depth="full"] .empty-bubble {
  background: var(--brand-paper, var(--blue-light));
  color: var(--brand-ink, var(--blue));
}
:root[data-brand-depth="full"] .empty-state b,
:root[data-brand-depth="full"] .empty-state h3 { color: var(--brand-ink, inherit); }
/* Their mark on the way in and on the way back. */
.auth-logo { height: 30px; max-width: 170px; object-fit: contain; }
.boot-logo { height: 34px; max-width: 200px; object-fit: contain; margin-bottom: 10px; }
:root[data-brand-depth="full"] .auth-card {
  border-top: 3px solid var(--brand-deep, var(--blue));
}

/* The picture under the brand switch: one tile per surface the answer
   touches, drawn in the company's own colors so a manager can see what
   "everywhere" means before they choose it rather than after. */
.bp-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
  gap: 8px; margin-top: 10px;
}
.bp-tile { display: flex; flex-direction: column; gap: 4px; }
.bp-cap { font-size: 11px; color: var(--slate); }
.bp-art { border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
.bp-card {
  background: var(--surface); padding: 8px; display: flex; flex-direction: column;
  align-items: flex-start; gap: 4px; min-height: 66px; font-size: 10px;
}
.bp-card b { font-size: 11px; }
.bp-card.bp-dark { background: #0e1116; }
.bp-band { height: 5px; width: 100%; border-radius: 2px; }
.bp-btn { color: #fff; font-size: 9px; padding: 2px 7px; border-radius: 99px; }
.bp-logo { height: 15px; max-width: 86px; object-fit: contain; }
.bp-mono { font-weight: 800; font-size: 13px; letter-spacing: -.03em; }
.bp-bubble {
  width: 20px; height: 20px; border-radius: 50%; display: flex;
  align-items: center; justify-content: center; font-weight: 700;
}

/* ---- the guided build checklist (Josh's item 14). The camera is the
   control that matters: one tap, no picker, and the count of what it has
   already got sitting on it. */
.cl-prompt {
  margin: 2px 0 0; font-size: 12px; line-height: 1.45; color: var(--slate);
  max-width: 58ch;
}
.cl-cam {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  padding: 5px 10px; border-radius: var(--radius-sm); font-size: 12px;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--slate); font-weight: 600;
}
.cl-cam:hover { border-color: var(--blue); color: var(--blue); }
.cl-cam span { font-variant-numeric: tabular-nums; }
.cl-cam span:empty { display: none; }
.cl-yesno { display: inline-flex; gap: 4px; }
.cl-primary { display: flex; gap: 6px; flex: 0 0 auto; align-items: center; }

/* A stage's triggers, each with its own strength (Josh's item 7). */
.req-pill {
  display: inline-flex; align-items: center; gap: 4px; margin: 0 4px 4px 0;
  padding: 2px 4px 2px 8px; border-radius: 99px; font-size: 11.5px;
  background: var(--raise); border: 1px solid var(--border);
}
.req-pill select { border: 0; background: transparent; padding: 0 2px; }
.req-x {
  border: 0; background: transparent; cursor: pointer; color: var(--slate);
  font-size: 14px; line-height: 1; padding: 0 3px;
}
.req-x:hover { color: var(--red); }

/* ---- the estimator's scope row (Josh's review, 2026-09-04) */
.scope-row {
  padding: 10px 12px; margin-bottom: 10px; border-radius: var(--radius);
  background: var(--raise); border: 1px solid var(--border);
}
.scope-tick {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  font-size: 13px; color: var(--ink);
}
.scope-tick input { width: auto; }
/* What the county requires here. Amber, not red: this is a heads-up a rep
   acts on, not an error they made. */
.code-note {
  display: flex; gap: 8px; margin-top: 10px; padding: 9px 11px;
  border-radius: var(--radius-sm); font-size: 12.5px; line-height: 1.5;
  background: var(--amber-light); color: var(--ink);
  border: 1px solid var(--amber);
}
.code-note svg { flex: 0 0 auto; color: var(--amber); margin-top: 2px; }
.code-note p { margin: 3px 0 0; }
.req-chip {
  display: inline-flex; align-items: center; gap: 3px; margin-left: 6px;
  padding: 1px 6px; border-radius: 99px; font-size: 10px; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
  background: var(--amber-light); color: var(--amber);
  border: 1px solid var(--amber); vertical-align: middle;
}
tr.req-line td:first-child { position: relative; }
/* An armed delete says so in words. An icon that changes color is not a
   confirmation; "Remove?" is. */
.btn.danger[data-del] {
  color: var(--red); border-color: var(--red); font-weight: 600;
}

/* ---- job messages: the list on the left, the one you picked on the right
   (Josh's review, 2026-09-04). One column on a phone, where the list and the
   reading pane swap places instead of squeezing side by side. */
.thread-split {
  display: grid; gap: 14px; align-items: start;
  grid-template-columns: minmax(240px, 320px) 1fr;
}
.thread-list { display: grid; gap: 8px; align-content: start; }
.thread-row {
  display: grid; gap: 4px; text-align: left; cursor: pointer; width: 100%;
  padding: 10px 12px; border-radius: var(--radius); font: inherit;
  border: 1px solid var(--border); background: var(--surface);
  color: inherit; box-shadow: var(--shadow);
}
.thread-row:hover { border-color: var(--b300); }
.thread-row.on { border-color: var(--blue); background: var(--b50); }
.thread-who {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; font-weight: 600; color: var(--ink);
  background: var(--raise); border-radius: 99px; padding: 2px 8px 2px 2px;
  max-width: 100%; overflow: hidden; white-space: nowrap;
}
.thread-last {
  margin: 0; font-size: 12.5px; color: var(--slate);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.thread-when { margin: 0; font-size: 11px; color: var(--slate-light); }
.thread-pane { margin: 0; }
.empty-pane { display: flex; align-items: center; justify-content: center; }
.msg-list { display: grid; gap: 14px; }
.msg { display: flex; gap: 10px; align-items: flex-start; }
/* A message that names you gets a rail, not a highlight — a whole tinted
   block is loud in a list where half of them may be yours. */
.msg.tagged { border-left: 3px solid var(--blue); padding-left: 9px; margin-left: -12px; }
.msg-body { min-width: 0; flex: 1; }
.msg-meta { margin: 0 0 2px; font-size: 11.5px; color: var(--slate-light); }
.msg-text { margin: 0; font-size: 13.5px; line-height: 1.5; white-space: pre-wrap; }
.msg-files { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
/* Gap seventeen: the original under a translated message, folded. */
.msg-orig { margin-top: 4px; }
.msg-orig summary { cursor: pointer; font-size: 11.5px; color: var(--slate-light); list-style: none; }
.msg-orig summary::before { content: '▸ '; }
.msg-orig[open] summary::before { content: '▾ '; }
.msg-orig .msg-text { margin-top: 4px; font-size: 12.5px; }
.lb-translated { background: var(--raise); border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; color: var(--ink); }
.lb-translated-text { white-space: pre-wrap; font: inherit; font-size: 13px; line-height: 1.5; margin: 0; max-height: 320px; overflow: auto; }
.msg-file {
  display: inline-flex; align-items: center; gap: 6px; max-width: 220px;
  padding: 4px 8px 4px 4px; border-radius: 8px; text-decoration: none;
  border: 1px solid var(--border); background: var(--raise); color: var(--ink);
  font-size: 12px;
}
.msg-file:hover { border-color: var(--b300); }
.msg-file img { width: 26px; height: 26px; border-radius: 5px; object-fit: cover; }
.msg-file-doc {
  width: 26px; height: 26px; border-radius: 5px; display: flex;
  align-items: center; justify-content: center; color: var(--slate);
  background: var(--surface);
}
.msg-file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-file-x {
  border: 0; background: transparent; cursor: pointer; color: var(--slate);
  display: flex; padding: 0 2px;
}
.pick-grid {
  display: grid; gap: 8px; max-height: 46vh; overflow-y: auto;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.pick-file {
  display: flex; align-items: center; gap: 8px; text-align: left; width: 100%;
  padding: 6px; border-radius: 8px; cursor: pointer; font: inherit;
  border: 1px solid var(--border); background: var(--surface); color: inherit;
  font-size: 12px; overflow: hidden;
}
.pick-file.on { border-color: var(--blue); background: var(--b50); }
.pick-file img { width: 34px; height: 34px; border-radius: 5px; object-fit: cover; }
@media (max-width: 900px) {
  /* ⚠️ ONE COLUMN, AND ONLY ONE OF THE TWO SHOWING. Side by side at phone
     width would give each half about 160px, which is not a reading pane, it
     is two broken ones. Picking a thread hides the list; the ✕ brings it
     back. */
  .thread-split { grid-template-columns: 1fr; }
  .thread-split.reading .thread-list { display: none; }
}

/* the group overlay — the page stays visible behind a dim blur; the group's
   screens sit on top as big labeled tiles. Enter blooms up, close drops
   back down. */
.nav-overlay {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(13, 22, 38, .48);
  -webkit-backdrop-filter: blur(7px) saturate(1.15);
  backdrop-filter: blur(7px) saturate(1.15);
  animation: overlay-in .18s ease-out;
}
/* The Everything grid is taller than a phone, so an inner layer scrolls.
   ⚠️ The scrolling cannot live on .nav-overlay itself: its backdrop-filter
   makes it the containing block for fixed descendants, so a "fixed" ✕
   would ride the scroll right off the screen. */
.nav-overlay-scroll {
  position: absolute; inset: 0;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  display: flex;
}
.nav-overlay.closing { animation: overlay-out .18s ease-in forwards; pointer-events: none; }
@keyframes overlay-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes overlay-out { from { opacity: 1; } to { opacity: 0; } }
.nav-overlay-box {
  text-align: center; padding: 24px; max-width: 640px;
  /* auto margins center a short group and let a tall one start at the
     top and scroll — flex centering alone clips a too-tall box at BOTH
     ends with no way to reach either. */
  margin: auto;
  animation: bloom-up .22s cubic-bezier(.2, .9, .3, 1.15);
}
@media (max-width: 700px) {
  /* Clear the ✕ up top and the home indicator down below. */
  .nav-overlay-box {
    padding: 70px 14px calc(30px + env(safe-area-inset-bottom, 0px));
  }
}
.nav-overlay.closing .nav-overlay-box { animation: bloom-down .18s ease-in forwards; }
@keyframes bloom-up {
  from { transform: translateY(26px) scale(.86); opacity: 0; }
  to { transform: none; opacity: 1; }
}
@keyframes bloom-down {
  from { transform: none; opacity: 1; }
  to { transform: translateY(26px) scale(.88); opacity: 0; }
}
.nav-overlay-box h2 {
  color: #fff; font-family: var(--display); font-size: 27px; font-weight: 600;
  margin: 0; text-shadow: 0 2px 14px rgba(0, 0, 0, .35);
}
.nav-overlay-box p {
  color: rgba(255, 255, 255, .78); font-size: 13.5px; margin: 6px 0 0;
  text-shadow: 0 1px 8px rgba(0, 0, 0, .3);
}
.nav-overlay-grid {
  display: flex; flex-wrap: wrap; gap: 14px; justify-content: center;
  margin-top: 22px;
}
.overlay-tile {
  width: 112px; padding: 18px 8px 15px;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  background: rgba(255, 255, 255, .11); border: 1px solid rgba(255, 255, 255, .24);
  border-radius: 14px; color: #fff; cursor: pointer;
  font-family: inherit; font-size: 12.5px; text-decoration: none;
  transition: transform .12s ease, background .12s ease;
}
.overlay-tile:hover, .overlay-tile:focus-visible {
  transform: translateY(-3px) scale(1.04);
  background: rgba(255, 255, 255, .2); outline: none;
}
.overlay-tile.on { border-color: #fff; background: rgba(255, 255, 255, .22); }
.overlay-tile svg { display: block; }
.nav-overlay-x {
  position: absolute; top: max(14px, env(safe-area-inset-top, 0px));
  right: 16px;
  width: 38px; height: 38px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(13, 22, 38, .55); border: 1px solid rgba(255, 255, 255, .35);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  color: #fff; cursor: pointer;
  /* Above the tiles — the grid scrolls underneath and the ✕ stays. */
  z-index: 5;
}
.nav-overlay-x:hover { background: rgba(255, 255, 255, .24); }

/* ------------------------------------------------- the command palette */
.kbd-chip {
  font-family: var(--mono); font-size: 10.5px; color: var(--slate-light);
  border: 1px solid var(--border); border-radius: 5px; padding: 2px 6px;
  background: var(--surface); cursor: pointer; flex: 0 0 auto;
}
.cmdk {
  position: fixed; inset: 0; z-index: 210;
  background: rgba(13, 22, 38, .42);
  -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px);
  display: flex; justify-content: center; align-items: flex-start;
  padding: 12vh 16px 0;
  animation: overlay-in .14s ease-out;
}
.cmdk.closing { animation: overlay-out .14s ease-in forwards; pointer-events: none; }
.cmdk-panel {
  width: 100%; max-width: 560px; background: var(--surface);
  border: 1px solid var(--border); border-radius: 14px;
  box-shadow: var(--shadow-pop); overflow: hidden;
  animation: bloom-up .18s cubic-bezier(.2, .9, .3, 1.12);
}
.cmdk.closing .cmdk-panel { animation: bloom-down .14s ease-in forwards; }
.cmdk-input {
  display: flex; align-items: center; gap: 9px;
  padding: 13px 16px; border-bottom: 1px solid var(--border);
}
.cmdk-input input {
  flex: 1; border: 0; outline: none; background: transparent;
  font-size: 14.5px; color: var(--ink); font-family: var(--body);
}
.cmdk-hint {
  font-family: var(--mono); font-size: 10.5px; color: var(--slate-light);
  border: 1px solid var(--border); border-radius: 5px; padding: 2px 6px;
}
.cmdk-results { max-height: 46vh; overflow-y: auto; padding: 6px; }
.cmdk-kind { padding: 8px 10px 3px; }
.cmdk-row {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: 8px; cursor: pointer;
  color: var(--ink); font-size: 13.5px;
}
.cmdk-row svg { color: var(--slate); flex: 0 0 auto; }
.cmdk-row.on { background: var(--blue-light); }
.cmdk-row.on svg { color: var(--blue); }
.cmdk-primary { font-weight: 500; white-space: nowrap; }
.cmdk-detail {
  color: var(--slate); font-size: 12.5px; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cmdk-right {
  margin-left: auto; font-family: var(--mono); font-size: 12px;
  color: var(--green); flex: 0 0 auto;
}
.cmdk-none { padding: 22px 14px; color: var(--slate); font-size: 13px; }
@media (max-width: 760px) {
  .kbd-chip { display: none; }
  .cmdk { padding-top: 8vh; }
}
@media (prefers-reduced-motion: reduce) {
  .nav-overlay, .nav-overlay-box,
  .nav-overlay.closing, .nav-overlay.closing .nav-overlay-box { animation: none; }
}
@media (max-width: 760px) {
  .overlay-tile { width: 96px; padding: 15px 6px 12px; }
  .nav-overlay-grid { gap: 10px; padding: 0 6px; }
}
/* The tab bar's own count, on navy. */
.nav-badge {
  margin-left: auto; font-family: var(--mono); font-size: 11px;
  color: var(--navy-text);
}
/* ⚠️ AND ON THE TOP STRIP, which is a light surface — the navy color above
   would all but vanish there. The count rides the closed dropdown that
   holds Follow-ups as well as the entry inside it, because a number nobody
   can see is the same as no number at all. */
.topnav .nav-badge {
  margin-left: 5px; flex: 0 0 auto; min-width: 17px; padding: 0 5px;
  border-radius: 999px; background: var(--raise); color: var(--slate);
  font-size: 10.5px; line-height: 17px; text-align: center;
  font-variant-numeric: tabular-nums;
}
.topnav-menu a .nav-badge, .topnav-menu button .nav-badge { margin-left: auto; }

.main { flex: 1; min-width: 0; padding: 20px 24px 48px;
  /* The page NEVER scrolls sideways; anything wide scrolls inside its own
     box (.table-scroll, the board). clip, not hidden — clip cannot become
     a scroll container, so nothing inside loses position:sticky. */
  overflow-x: clip; }
/* The atmosphere wash: the company's hue at 4% strength pouring in from the
   top of the dashboard, like light through a window. Felt, not seen. */
body[data-route="dashboard"] .main,
body[data-route="week"] .main {
  background:
    radial-gradient(110% 34% at 30% 0%, var(--brand-wash) 0%, transparent 70%),
    radial-gradient(80% 26% at 90% 0%, var(--brand-wash) 0%, transparent 60%);
}
.page-head { margin-bottom: 18px; }
.page-head p { font-size: 13px; color: var(--slate); margin: 0 0 2px; }
.page-head h1 { font-size: 22px; }

/* ------------------------------------------------------------------ cards */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 14px 16px; box-shadow: var(--shadow);
}
.card + .card { margin-top: 16px; }
/* ⚠️ That stacking rule leaks into grids: every card after the first sagged
   16px (the dashboard KPI stagger on the punch list — measured, card 2 sat
   top+16 with 16px less height at every width). Grids space with gap. */
.grid > .card + .card { margin-top: 0; }
.card-head {
  display: flex; align-items: center; gap: 8px; margin-bottom: 10px;
}
.card-head h3 { font-size: 15px; }

/* The job Overview's two fact cards (Josh 2026-10-12, from AccuLynx):
   a shaded header band, bold labels in a column, answers beside them in the
   link blue, and a pencil sitting in the bottom right corner. */
/* Josh 2026-10-12, second pass: "too much space and looks clunky." The
   pencil sits in the header instead of reserving a strip at the bottom,
   labels take only the room they need, and rows sit closer. Third pass,
   same day: the two boxes must be the same size ("or it's an eye sore"),
   so the pair stretches to the taller card again; with the pencil gone from
   the bottom, that leaves a little air under the shorter card, not a hole. */
.ov-pair { align-items: stretch; }
/* Under the pair: two even columns. (The claim sat between them for a
   moment on 2026-10-12; it has its own tab now.) */
.ov-cols { margin-top: 16px; align-items: start; }
.ov-card { padding: 12px 14px; }
.ov-card .card-head {
  margin: -12px -14px 10px; padding: 8px 10px 8px 14px; gap: 8px;
  background: var(--canvas); border-bottom: 1px solid var(--border);
  border-radius: var(--radius) var(--radius) 0 0;
}
.ov-card .card-head h3 { font-size: 15.5px; font-weight: 600; }
.ov-card .card-head svg { color: var(--blue); }
/* Fourth pass, same day: "give name, email and phone number some room, it's
   too bunched up." The equal-height pair has the space, so the rows spread
   out and the type steps up a size. */
.ov-facts {
  display: grid; grid-template-columns: minmax(100px, max-content) 1fr;
  column-gap: 28px; row-gap: 14px; margin: 4px 0 2px; font-size: 15px; line-height: 1.45;
}
.ov-facts dt { font-weight: 600; color: var(--slate); }
.ov-facts dd { margin: 0; color: var(--ink); min-width: 0; overflow-wrap: anywhere; }
.ov-facts dd a, .ov-facts .ov-strong { color: var(--blue); text-decoration: none; }
.ov-facts dd a:hover { text-decoration: underline; }
.ov-facts .ov-out { display: inline-flex; vertical-align: -2px; margin-left: 4px; }
.ov-phone { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; }
.ov-mini {
  all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: 4px;
  font-size: 12px; line-height: 1; padding: 3px 7px; border-radius: 999px;
  color: var(--slate); border: 1px solid var(--border);
}
.ov-mini:hover { color: var(--blue); border-color: var(--blue); }
/* Other buildings: one pill each, an x to take it off, Add at the end. */
.ov-structs { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.ov-struct {
  display: inline-flex; align-items: center; gap: 4px; font-size: 13px;
  padding: 2px 4px 2px 9px; border-radius: 999px;
  background: var(--blue-light); color: var(--ink);
}
.ov-struct button {
  all: unset; cursor: pointer; width: 18px; height: 18px; border-radius: 50%;
  display: inline-grid; place-items: center; color: var(--slate); font-size: 14px;
}
.ov-struct button:hover { background: var(--surface); color: var(--red); }
.ov-edit {
  background: none; border: 0; padding: 4px; cursor: pointer; display: inline-flex;
  color: var(--blue); border-radius: 6px;
}
.ov-edit:hover { background: var(--blue-light); }

/* ------------------------------------------------------------- folds
   The collapsed sections of the overview. Same furniture as a card, so a
   closed fold and an open one sit in the same rhythm as everything else. */
.fold {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; margin: 0 0 12px; overflow: hidden;
}
.fold-head {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 16px; cursor: pointer; list-style: none; user-select: none;
}
.fold-head::-webkit-details-marker { display: none; }
/* The chevron, drawn rather than an icon so it can rotate. */
.fold-head::before {
  content: ''; width: 7px; height: 7px; flex: none;
  border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted);
  transform: rotate(45deg); transition: transform .16s ease;
  margin-top: -3px;
}
.fold:not([open]) > .fold-head::before { transform: rotate(-45deg); }
.fold-head:hover { background: var(--raise); }
.fold-title { font-weight: 600; font-size: 15px; }
/* ⚠️ THE META IS WHY A FOLD IS OPENABLE AT ALL. A closed section that
   says only its name tells you nothing about whether to open it; the
   count or the headline number is the answer most days. */
.fold-meta {
  margin-left: auto; color: var(--muted); font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.fold-body { padding: 0 16px 16px; }
/* A card nested straight inside a fold would draw a second border around
   the same content. */
.fold-body > .card:only-child {
  border: 0; padding: 0; background: none; border-radius: 0;
}
@media (prefers-reduced-motion: reduce) {
  .fold-head::before { transition: none; }
}

.grid { display: grid; gap: 12px; }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
.grid-2 { grid-template-columns: 1fr 1fr; }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
/* A number worth reading across the room — the wallet balance, the line. */
.stat-lg { font-size: 26px; font-weight: 650; margin: 2px 0 6px;
  font-variant-numeric: tabular-nums; }
.grid-14 { grid-template-columns: 1.4fr 1fr; }
.gap-16 { gap: 16px; }
.mt-22 { margin-top: 22px; }
.mb-12 { margin-bottom: 12px; }

.stat p:first-child { margin: 0; }
.stat .value {
  font-family: var(--display); font-size: 24px; font-weight: 600;
  margin: 4px 0 0; font-variant-numeric: tabular-nums;
}
.stat .sub { font-size: 12px; color: var(--slate-light); margin: 2px 0 0; }

/* --------------------------------------------------------------- pipeline */
.board { display: grid; gap: 10px; position: relative; align-items: start; }
.board-col { position: relative; min-width: 0; }
.board-col.drop {
  border-radius: 8px;
  box-shadow: 0 0 0 2px var(--blue), 0 0 18px 2px var(--blue-light);
  background: var(--blue-light);
}
/* dropping on Sold gets the money color — a quiet celebration, not confetti */
.board-col.drop[data-stage="sold"] {
  box-shadow: 0 0 0 2px var(--green), 0 0 18px 2px var(--green-light);
  background: var(--green-light);
}
.col-head { display: flex; align-items: center; gap: 6px; margin-bottom: 10px; }
.col-dot { width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto; }
.col-head p { font-size: 12px; font-weight: 600; margin: 0; }
.col-count { font-family: var(--mono); font-size: 11px; color: var(--slate-light); margin-left: auto; }
.col-total {
  font-family: var(--mono); font-size: 11px; color: var(--green);
  margin-bottom: 8px;
}

.lead-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
  padding: 10px 12px; margin-bottom: 8px; cursor: grab;
  box-shadow: var(--shadow);
  transition: transform .14s ease, box-shadow .14s ease, border-color .14s;
}
.lead-card:hover {
  border-color: var(--b300);
  transform: translateY(-3px);
  box-shadow: var(--shadow-lift);
}
.lead-card:active { cursor: grabbing; }
.lead-card.aging { border-left: 3px solid var(--amber); }
/* the text inbox: threads left, the conversation right */
.txt-split { display: grid; grid-template-columns: 280px minmax(0, 1fr); gap: 16px; }
@media (max-width: 760px) { .txt-split { grid-template-columns: 1fr; } }
.txt-list { display: flex; flex-direction: column; gap: 6px; }
.txt-row {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; padding: 10px 12px; cursor: pointer; position: relative;
}
.txt-row.on { border-color: var(--blue); }
.txt-row .t { font-size: 13.5px; font-weight: 600; margin: 0; }
.txt-row .d { font-size: 12px; color: var(--slate); margin: 2px 0 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.txt-row .w { position: absolute; top: 10px; right: 12px; font-size: 11px;
  color: var(--slate-light); margin: 0; }
.txt-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--blue); margin-left: 6px; }
.txt-pane { display: flex; flex-direction: column; }
.txt-talk { display: flex; flex-direction: column; gap: 8px;
  max-height: 52vh; overflow-y: auto; padding: 4px 2px; }
.txt-msg { max-width: 78%; }
.txt-msg p { margin: 0; padding: 8px 12px; border-radius: 14px; font-size: 14px; }
.txt-msg span { display: block; font-size: 10.5px; color: var(--slate-light);
  margin: 2px 6px 0; }
.txt-msg.in { align-self: flex-start; }
.txt-msg.in p { background: var(--canvas); border-bottom-left-radius: 4px; }
.txt-msg.out { align-self: flex-end; text-align: right; }
.txt-msg.out p { background: var(--blue); color: #fff;
  border-bottom-right-radius: 4px; }
.txt-stop { font-size: 12px; color: var(--amber); background: var(--amber-light);
  border-radius: 8px; padding: 7px 10px; margin: 2px 0; align-self: center; }

/* the markup studio: toolbar over canvas, pointer-first (a thumb on a
   phone draws the same arrow a mouse does) */
.anno-bar {
  display: flex; align-items: center; gap: 8px; margin-bottom: 10px;
  flex-wrap: wrap;
}
.anno-color {
  width: 22px; height: 22px; border-radius: 50%; border: 2px solid transparent;
  cursor: pointer; padding: 0;
}
.anno-color.on { border-color: var(--ink); box-shadow: 0 0 0 2px var(--surface); }
.anno-stage {
  overflow: auto; max-height: 62vh; border-radius: 10px;
  border: 1px solid var(--border); background: #000;
  display: flex; justify-content: center;
}
.anno-stage canvas {
  max-width: 100%; height: auto; display: block; cursor: crosshair;
  touch-action: none;
}

/* the phone FAB (queue item 3): one thumb verb, floating above the tab
   bar. Desktop never shows it — the labeled buttons are the desktop way. */
.fab, .fab-sheet { display: none; }
@media (max-width: 760px) {
  .fab {
    display: flex; position: fixed; right: 16px;
    bottom: calc(84px + env(safe-area-inset-bottom, 0px)); z-index: 95;
    width: 54px; height: 54px; border-radius: 50%; border: 0;
    background: var(--blue); color: #fff; cursor: pointer;
    align-items: center; justify-content: center;
    box-shadow: 0 8px 24px var(--brand-glow);
  }
  .fab[hidden] { display: none; }
  .fab:active { transform: scale(.94); }
  .fab-sheet {
    display: flex; flex-direction: column; gap: 4px;
    position: fixed; right: 16px;
    bottom: calc(148px + env(safe-area-inset-bottom, 0px)); z-index: 95;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: 14px; padding: 8px; box-shadow: var(--shadow-pop);
  }
  .fab-sheet[hidden] { display: none; }
  .fab-sheet button {
    display: flex; align-items: center; gap: 9px;
    border: 0; background: transparent; color: var(--ink);
    font: inherit; font-size: 14px; padding: 10px 14px;
    border-radius: 9px; cursor: pointer; text-align: left;
  }
  .fab-sheet button:active { background: var(--canvas); }
}

.tl-day {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--slate-light);
  margin: 14px 0 6px; padding-bottom: 4px;
  border-bottom: 1px solid var(--border);
}
.tl-day:first-child { margin-top: 0; }
/* The day heading is a <summary> now (collapsible timeline, Josh 2026-09-04).
   list-style:none kills the default triangle in Firefox; ::-webkit-details-
   marker does the same in Safari and Chrome — one without the other leaves
   a stray arrow in half the browsers. */
summary.tl-day { cursor: pointer; list-style: none; user-select: none; }
summary.tl-day::-webkit-details-marker { display: none; }
summary.tl-day::before {
  content: '▾'; display: inline-block; margin-right: 6px;
  font-size: 9px; transition: transform .15s; color: var(--slate-light);
}
.tl-day-group:not([open]) > summary.tl-day::before { transform: rotate(-90deg); }
.tl-day-group:first-child > summary.tl-day { margin-top: 0; }

.info-dot {
  font: 600 10px/1 var(--mono); color: var(--slate);
  border: 1px solid var(--border); background: transparent;
  border-radius: 50%; width: 17px; height: 17px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.info-dot:hover { color: var(--ink); border-color: var(--slate); }

.fldcol { display: flex; flex-direction: column; gap: 4px; }
.fldcol span {
  font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--slate);
}
.goal-bar {
  position: relative; background: var(--canvas); border-radius: 99px;
  height: 8px; overflow: visible;
}
.goal-bar i {
  display: block; height: 8px; border-radius: 99px;
  transition: width .4s ease;
}
.goal-bar b {
  position: absolute; top: -3px; width: 2px; height: 14px;
  background: var(--slate); border-radius: 1px;
}
.card-age {
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  color: var(--amber); background: var(--amber-light);
  border-radius: 99px; padding: 1px 7px; white-space: nowrap;
}
.lead-card.dragging { opacity: .35; transform: rotate(1.5deg) scale(1.02); }
.lead-card.landed { animation: card-land .32s cubic-bezier(.2, .9, .3, 1.2); }
@keyframes card-land {
  from { transform: translateY(-7px) scale(1.04); box-shadow: 0 10px 22px rgba(15, 28, 46, .2); }
  to { transform: none; }
}
@media (prefers-reduced-motion: reduce) { .lead-card.landed { animation: none; } }
.lead-card .name { font-size: 13.5px; font-weight: 600; margin: 0; }
.lead-card .addr {
  font-family: var(--mono); font-size: 11.5px; color: var(--slate);
  margin: 2px 0 0; display: flex; align-items: center; gap: 4px;
}
.lead-card .val { font-family: var(--mono); font-size: 12.5px; color: var(--green); font-weight: 500; }
.lead-foot { display: flex; justify-content: space-between; align-items: center; margin-top: 8px; }
.chip {
  font-size: 11px; color: var(--slate); background: var(--canvas);
  border-radius: 4px; padding: 2px 6px; white-space: nowrap;
}
/* Report builder column toggles ride the base chip with a lit state. */
button.chip { cursor: pointer; border: 1px solid var(--border);
  padding: 4px 9px; font-size: 12px; }
button.chip.on { background: var(--blue); border-color: var(--blue);
  color: #fff; }
.col-empty {
  border: 1px dashed var(--border); border-radius: 8px; padding: 14px 10px;
  text-align: center; font-size: 11.5px; color: var(--slate-light);
}
.col-compact {
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
  padding: 16px 10px; text-align: center;
}
.col-compact .n { font-family: var(--display); font-size: 22px; font-weight: 600; margin: 0; }
.col-compact .l { font-size: 11px; color: var(--slate-light); margin: 2px 0 0; }

.badge {
  font-family: var(--mono); font-size: 11px; border-radius: 4px;
  padding: 2px 6px; border: 1px solid; white-space: nowrap;
}
.badge.slate { color: var(--slate); border-color: #6B728055; }
.badge.blue { color: var(--blue); border-color: var(--b200); }
.badge.amber { color: var(--amber); border-color: #B36B0055; }
.badge.green { color: var(--green); border-color: #1F9D5555; }
.badge.red { color: var(--red); border-color: #B3122F55; }

/* ---------------------------------------------------------------- tables */
table.data { width: 100%; font-size: 12.5px; border-collapse: collapse; }
/* seat picker — first-login modal and the Settings card share these */
.seat-row { display: flex; align-items: center; gap: 14px;
  padding: 12px 0; border-top: 1px solid var(--border); }
.seat-row:first-of-type { border-top: 0; }
.seat-row > div:first-child { min-width: 0; flex: 1; }
.seat-count { display: flex; align-items: center; gap: 6px; flex: none; }
.seat-count input { width: 52px; text-align: center; padding: 6px 4px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  font-size: 14px; }

/* An explicit scroll box for any table not sitting as .card's direct child
   (the automatic boxWideTables rule can't reach those) — mail billing was
   shipping this class with no definition and scrolled the page sideways. */
.tablewrap { overflow-x: auto; }
table.data th {
  text-align: left; font-weight: 500; color: var(--slate-light);
  padding-bottom: 6px; font-size: 12px; white-space: nowrap;
}
table.data td { padding: 8px 0; border-top: 1px solid var(--border); }
table.data tbody tr.clickable { cursor: pointer; }
table.data tbody tr.clickable:hover td { background: var(--canvas); }
table.data td.num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

.list-row { padding: 8px 0; border-top: 1px solid var(--border); }
.list-row:first-child { border-top: 0; }
.list-row .t { font-size: 12.5px; font-weight: 500; margin: 0; }
.list-row .d { font-size: 11.5px; color: var(--slate); margin: 2px 0 0; }

/* --------------------------------------------------------------- controls */
.btn {
  border: 1px solid var(--border); background: var(--surface); color: var(--ink);
  border-radius: var(--radius-sm); padding: 7px 13px; font-size: 13px;
  cursor: pointer; display: inline-flex; align-items: center; gap: 6px;
}
.btn:hover { border-color: var(--slate-light); }
.btn.primary { background: var(--blue); border-color: var(--blue); color: var(--on-accent, #fff); }
.btn.primary:hover { background: var(--b700); border-color: var(--b700); }
/* dark's ladder runs the other way — hover must deepen, not lift, or the
   white label washes out */
:root[data-theme="dark"] .btn.primary:hover { background: var(--b400); border-color: var(--b400); }
.btn.ghost { border-color: transparent; background: transparent; color: var(--slate); }
.btn.sm { padding: 4px 9px; font-size: 12px; }
.btn.danger { color: var(--red); border-color: #B3122F44; }
.btn:disabled { opacity: .5; cursor: not-allowed; }

.seg { display: flex; background: var(--canvas); border-radius: 8px; padding: 3px; }
.seg button {
  border: 0; cursor: pointer; font-size: 12.5px; font-weight: 500;
  padding: 6px 14px; border-radius: var(--radius-sm);
  background: transparent; color: var(--slate);
}
.seg button.on { background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px rgba(0,0,0,.08); }
.seg button svg { vertical-align: -2px; margin-right: 5px; }

.field { display: block; margin-bottom: 12px; }
.field > span {
  display: block; font-size: 12px; color: var(--slate); font-weight: 600;
  text-transform: uppercase; letter-spacing: .04em; margin-bottom: 5px;
}
input, select, textarea {
  width: 100%; font-family: var(--body); font-size: 13.5px; color: var(--ink);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 8px 10px; outline: none;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-light);
}
textarea { resize: vertical; min-height: 70px; }

/* ⚠️ CHECKBOXES AND RADIOS ARE NEVER TEXT FIELDS (Josh, 2026-09-15: "anything
   that has a check box" looked bad). The rule above gave them width:100%, a
   text field's padding and border, so inside a flex label the box sat alone
   in a wide slot and its words squeezed into a narrow column. This undoes
   that for every one of them, and the :has() rule fixes the ~50 existing
   <label class="row"><input type=checkbox> words</label> without touching
   their markup (the !important beats their inline align-items:center). */
input[type=checkbox], input[type=radio] {
  width: 16px; height: 16px; flex: none; margin: 0; padding: 0;
  border: 0; border-radius: 0; background: none; box-shadow: none;
  accent-color: var(--blue); cursor: pointer;
}
input[type=checkbox]:focus, input[type=radio]:focus { box-shadow: none; }
input[type=checkbox]:focus-visible, input[type=radio]:focus-visible {
  outline: 2px solid var(--blue); outline-offset: 2px;
}
:root[data-theme="dark"] input[type=checkbox], :root[data-theme="dark"] input[type=radio] { color-scheme: dark; }
label.row:has(> input[type=checkbox]), label.row:has(> input[type=radio]) {
  align-items: flex-start !important; flex-wrap: nowrap !important;
  gap: 8px; cursor: pointer; line-height: 1.4;
}
label.row:has(> input[type=checkbox]) > input, label.row:has(> input[type=radio]) > input { margin-top: 2px; }
.check { display: inline-flex; align-items: flex-start; gap: 8px; cursor: pointer; line-height: 1.4; }
.check > input { margin-top: 2px; }
/* A person in or out of something, as a pill: the lead-routing rotation. */
label.chip-toggle {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 11px;
  border: 1px solid var(--border); border-radius: 999px; cursor: pointer;
  font-size: 13px; user-select: none;
}
label.chip-toggle:has(input:checked) { border-color: var(--blue); background: var(--blue-light); }
/* On / Paused, per automation rule. */
.au-switch {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  border: 1px solid var(--border); border-radius: 999px; background: var(--surface);
  padding: 3px 10px 3px 4px; font: inherit; font-size: 12px; color: var(--ink);
}
.au-switch i { width: 24px; height: 14px; border-radius: 7px; background: var(--border); position: relative; flex: none; }
.au-switch i::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 10px; height: 10px;
  border-radius: 50%; background: #fff; transition: left .15s;
}
.au-switch.on i { background: var(--green); }
.au-switch.on i::after { left: 12px; }
/* Mount points stacked on a tab: space between the ones that rendered,
   none for the empty ones (so no double gaps). */
.tab-stack > div:not(:empty) ~ div:not(:empty) { margin-top: 18px; }

/* ⚠️ 16px OR iOS ZOOMS. Safari auto-zooms the whole page the moment a field
   under 16px is focused, and never zooms back — the page then pans sideways
   forever (Joshua's screenshots, 8/30). The viewport meta's maximum-scale
   stops it in Safari proper; this stops it in every webview that ignores the
   meta. The !important is the point: several controls carry their own
   smaller sizes (.searchbox input at 13px and friends), and every one of
   them is an iOS zoom trigger this rule exists to outrank. */
@media (max-width: 760px) {
  body :is(input, select, textarea) { font-size: 16px !important; }
}

/* ⚠️ `.field { display: block }` beats a bare [hidden], so a field that
   hides itself needs saying explicitly — the same shape as the six
   other [hidden] rules in this file. Without it the password box on
   the profile card would sit there asking for a password nobody
   needs to type. */
.field[hidden] { display: none; }

.field-row { display: flex; gap: 12px; }
.field-row > * { flex: 1; }

/* ----------------------------------------------------------------- modal */
.scrim {
  position: fixed; inset: 0; background: rgba(15, 28, 46, .45);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 60px 20px; z-index: 100; overflow: auto;
}
.modal {
  background: var(--surface); border-radius: 12px; width: 100%; max-width: 520px;
  box-shadow: var(--shadow-pop); padding: 20px 22px;
}
.modal.wide { max-width: 760px; }
/* The hand tracer wants the room a drawing surface needs; side panel drops
   under the canvas on a phone rather than squeezing it. */
.modal.tracer-modal { max-width: min(1150px, calc(100vw - 24px)); }
.tracer-body { display: flex; gap: 12px; align-items: flex-start; }
.tracer-side { width: 280px; flex: 0 0 280px; display: flex; flex-direction: column; gap: 10px; }
@media (max-width: 860px) {
  .tracer-body { flex-direction: column; }
  .tracer-side { width: 100%; flex: 1 1 auto; }
}
.modal-head { display: flex; align-items: flex-start; margin-bottom: 16px; }
.modal-head h2 { font-size: 17px; }
.modal-foot {
  display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px;
  padding-top: 14px; border-top: 1px solid var(--border);
}

/* ----------------------------------------------------------------- charts */
.bars {
  display: flex; align-items: flex-end; justify-content: center;
  gap: 14px; height: 170px; padding-top: 8px;
}
.bar-col {
  flex: 1 1 0; max-width: 108px; display: flex; flex-direction: column;
  justify-content: flex-end; height: 100%;
}
.bar {
  border-radius: 3px 3px 0 0; min-height: 2px; width: 100%;
  transition: height .3s ease;
}
.bar-label { font-size: 11px; color: var(--slate); text-align: center; margin-top: 6px; }
.bar-value {
  font-family: var(--mono); font-size: 10.5px; color: var(--slate);
  text-align: center; margin-bottom: 4px;
}
.chart-grid { border-top: 1px solid var(--border); }

.funnel { display: grid; gap: 8px; position: relative; }
.funnel-step { text-align: center; position: relative; }
.funnel-dot {
  width: 10px; height: 10px; border-radius: 50%; margin: 12px auto 10px;
  background: var(--blue);
}
.funnel-step .n { font-family: var(--display); font-size: 20px; font-weight: 600; margin: 0; }
.funnel-step .s { font-size: 11.5px; color: var(--slate); margin: 2px 0 0; }
.funnel-step .c { font-family: var(--mono); font-size: 10.5px; color: var(--slate-light); margin: 3px 0 0; }
.funnel-rule {
  position: absolute; top: 17px; left: 8%; right: 8%; height: 1px;
  border-top: 1px dashed var(--border);
}

/* ------------------------------------------------------------- job detail */
.job-head { display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
/* Eight tabs do not fit in 375px, and the honest answer is to let the strip
   scroll rather than let it drag the whole page sideways with it. */
.tabs {
  display: flex; gap: 2px; border-bottom: 1px solid var(--border);
  margin: 18px 0 16px; overflow-x: auto; scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  border: 0; background: transparent; cursor: pointer; font-size: 13px;
  color: var(--slate); padding: 9px 14px; border-bottom: 2px solid transparent;
  margin-bottom: -1px; white-space: nowrap; flex: 0 0 auto;
}
.tab.on { color: var(--ink); border-bottom-color: var(--blue); font-weight: 500; }

.timeline { position: relative; }
.tl-item { display: flex; gap: 10px; padding: 10px 0; border-top: 1px solid var(--border); }
.tl-item:first-child { border-top: 0; }
.tl-icon {
  width: 26px; height: 26px; border-radius: 50%; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  background: var(--canvas); color: var(--slate);
}
.tl-body { flex: 1; min-width: 0; }
.tl-body .b { font-size: 13px; margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.tl-body .m { font-size: 11.5px; color: var(--slate-light); margin: 3px 0 0; }

/* the stage journey: filled line and checks behind, pulsing dot at the
   current stage, hollow steps ahead. Scrolls in its own box on phones. */
.stage-rail {
  display: flex; align-items: center; gap: 4px;
  overflow-x: auto; padding-bottom: 2px;
}
.stage-pip {
  font-size: 11.5px; padding: 5px 10px; border-radius: 99px; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface); color: var(--slate);
  display: inline-flex; align-items: center; gap: 5px;
  white-space: nowrap; flex: 0 0 auto; transition: border-color .15s, color .15s;
}
.stage-pip:hover { border-color: var(--slate-light); color: var(--ink); }
.stage-pip.on { background: var(--navy); border-color: var(--navy); color: #fff; }
.stage-pip.done { border-color: var(--green); color: var(--green); background: var(--green-light); }
.stage-pip.lost { color: var(--red); margin-left: 10px; }
.pip-mark { font-size: 10px; font-weight: 700; }
.pip-dot {
  width: 6px; height: 6px; border-radius: 50%; background: #7FB2E5;
  animation: pip-pulse 1.6s ease-in-out infinite;
}
@keyframes pip-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(127, 178, 229, .55); }
  55% { box-shadow: 0 0 0 5px rgba(127, 178, 229, 0); }
}
@media (prefers-reduced-motion: reduce) { .pip-dot { animation: none; } }
.stage-line {
  width: 16px; height: 2px; border-radius: 1px; flex: 0 0 auto;
  background: var(--border);
}
.stage-line.fill { background: var(--green); }

/* ⚠️ THE PIPS ARE SPANS NOW, NOT BUTTONS. The rail shows the five BUCKETS a
   job walks (Josh's review, 2026-09-04) and a bucket is not somewhere you
   can click a job into — the moves live in the row underneath, which offers
   only what the flow allows. A clickable bucket was the skipping he asked
   us to stop, wearing a nicer hat. */
span.stage-pip { cursor: default; }
span.stage-pip:hover { border-color: var(--border); color: var(--slate); }
span.stage-pip.on:hover { border-color: var(--navy); color: #fff; }
span.stage-pip.done:hover { border-color: var(--green); color: var(--green); }
.flow-here {
  font-family: var(--display); font-size: 15px; font-weight: 600;
  color: var(--ink);
}
/* A next step that is not ready still shows, and says so rather than
   quietly refusing when it is pressed. */
.btn.blocked { border-style: dashed; color: var(--amber); }
.btn.blocked:hover { border-color: var(--amber); color: var(--amber); }

/* ---- the Pipeline page's buckets. Five cards, one per bucket, each a
   filter for the list beneath it. */
.bucket-strip {
  display: grid; gap: 10px; margin-bottom: 14px;
  grid-template-columns: repeat(auto-fit, minmax(128px, 1fr));
}
.bucket-card {
  display: grid; gap: 2px; text-align: left; cursor: pointer;
  padding: 12px 14px; border-radius: var(--radius);
  border: 1px solid var(--border); background: var(--surface);
  font: inherit; color: inherit; box-shadow: var(--shadow);
  transition: border-color .15s, box-shadow .15s;
}
.bucket-card:hover { border-color: var(--b300); box-shadow: var(--shadow-lift); }
.bucket-card.on { border-color: var(--blue); box-shadow: var(--shadow-lift); }
.bucket-card.on .bucket-l { color: var(--blue); }
.bucket-n {
  font-family: var(--display); font-size: 24px; font-weight: 600;
  line-height: 1.1; color: var(--ink); font-variant-numeric: tabular-nums;
}
.bucket-l { font-size: 12.5px; font-weight: 600; color: var(--slate); }
.bucket-v {
  font-family: var(--mono); font-size: 11.5px; color: var(--slate-light);
}

/* time-in-stage, colored by how stale the job is going */
.age-chip {
  font-size: 11.5px; font-weight: 600; border-radius: 99px; padding: 3px 9px;
  color: var(--green); background: var(--green-light);
}
.age-chip.aging { color: var(--amber); background: var(--amber-light); }
.age-chip.late { color: var(--red); background: var(--red-light); }

/* the hover-peek card — same bloom language as the nav overlay, sized down */
.peek {
  position: fixed; z-index: 190; width: 252px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 12px; padding: 13px 14px; box-shadow: var(--shadow-pop);
  animation: bloom-up .16s cubic-bezier(.2, .9, .3, 1.12);
  pointer-events: none;
}
.peek-name { margin: 0; font-weight: 600; font-size: 13.5px; }
.peek-addr {
  margin: 2px 0 0; color: var(--slate); font-size: 12px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.peek-val { margin-left: auto; font-family: var(--mono); font-size: 13px;
  color: var(--green); font-weight: 500; flex: 0 0 auto; }
.peek-foot { margin: 8px 0 0; font-size: 11px; color: var(--slate-light);
  font-family: var(--mono); }

/* ---- narrow screens --------------------------------------------------- */
/* The rule everything below serves: WIDE CONTENT SCROLLS INSIDE ITS OWN BOX,
   and the page itself never scrolls sideways. A page that slides horizontally
   under your thumb while you are trying to scroll down is the difference
   between an app a rep uses on a roof and one they give up on.
   Ten of thirteen pages did exactly that; the culprit was always a data table
   sitting in a card that could not clip it. */
/* ⚠️ The scroll goes on a BOX AROUND the table, never on the table itself.
   Making `table.data` a block and its thead/tbody `display:table` did make the
   overflow behave — and silently broke every data table in the app, at every
   width: two independent tables each size their own columns, so the headers
   stopped lining up with the numbers underneath. On the coaching report that
   put revenue under "Close rate". The mobile audit never caught it because it
   measured horizontal overflow, which was genuinely fixed, and nothing was
   measuring alignment. app.js puts the box in place so no render site has to
   remember. */
.table-scroll {
  display: block; overflow-x: auto; -webkit-overflow-scrolling: touch;
}

@media (max-width: 760px) {
  /* Below this, a table stops trying to squeeze and starts scrolling. The
     minimum keeps columns legible rather than crushing six of them into
     375px and making all six unreadable. */
  .table-scroll > table.data { min-width: 460px; }

  /* Cards and the shell get their padding back. */
  .main { padding: 14px 12px 40px; }
  .card { padding: 14px; }
  .page-head h1 { font-size: 22px; }

  /* A job's header stacks: the money should not be squeezed against the name. */
  .job-head { flex-wrap: wrap; }
  /* ⚠️ WRAP. This became a single non-wrapping flex row when the header
     was rebuilt on 2026-09-04, and the AR line and its button then ran
     110px past the right edge and dragged the whole job page sideways on
     every phone. It hid because the width audit walks the job LIST and
     never the job itself — now fixed in the self test too. */
  .job-head .right { width: 100%; display: flex; align-items: center;
                     flex-wrap: wrap; gap: 6px 10px; margin-top: 6px;
                     text-align: left; }
  .job-head .right .display { margin: 0 !important; }
  .job-head .right .micro { margin: 0 !important; }
  .job-head .right .btn { margin-top: 0 !important; }

  /* Two-up grids become one-up. */
  .grid-2, .grid-14, .grid-3 { grid-template-columns: 1fr !important; }

  /* A grid or flex item defaults to min-width:auto, so it refuses to shrink
     below its contents — one wide table inside a card pushed the card past
     its own track and took the page with it. This is the line that actually
     lets the scroll containers above do their job. */
  .grid > *, .row > * { min-width: 0; }

  /* Filters and toolbars wrap instead of pushing the page wide. A card header
     with a title, a spacer and two buttons is 400px of content in a 375px
     screen, so the buttons drop to their own line rather than hang off it. */
  .row, .searchbox, .seg, .card-head { flex-wrap: wrap; }
  .card-head .grow { flex-basis: 100%; height: 0; }

  /* The pipeline board is columns side by side — that IS its shape, so it
     scrolls as a board rather than pretending to be a list. The template is
     set inline per stage count, so it has to be overridden outright, or five
     columns just crush to 60px each. */
  .board {
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    grid-template-columns: none !important;
    grid-auto-flow: column; grid-auto-columns: 78vw;
    padding-bottom: 6px;
  }
  .board-col { min-width: 0; }

  /* Modals were sized for a desktop dialog. */
  .modal { width: calc(100vw - 20px); max-width: none; padding: 16px; }
  .modal-foot { flex-wrap: wrap; gap: 8px; }
  .modal-foot .btn { flex: 1 1 auto; justify-content: center; }
  .field-row { flex-direction: column; gap: 0; }
}

/* -------------------------------------------------------------- postcards */
.pc-grid {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
}
.pc-card {
  display: flex; flex-direction: column; gap: 5px; text-align: left;
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
  padding: 12px; cursor: pointer; font: inherit; color: inherit;
}
.pc-card:hover { border-color: var(--blue); }
.pc-card.on { border-color: var(--blue); border-width: 2px; padding: 11px; background: var(--blue-light); }
.pc-name {
  font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--slate);
}
.pc-headline { font-family: var(--display); font-weight: 600; font-size: 14px; }
.pc-body { font-size: 12px; color: var(--slate); line-height: 1.45; }
.pc-cta { font-size: 11.5px; color: var(--blue); font-weight: 500; margin-top: 2px; }

.pc-row {
  display: flex; align-items: center; gap: 10px; padding: 9px 0;
  border-top: 1px solid var(--border); font-size: 13px; cursor: pointer;
}
.pc-row:first-of-type { border-top: 0; }
.pc-row.blocked { opacity: .55; cursor: not-allowed; }
.pc-row input { width: auto; }

/* --------------------------------------------------------------- activity */
.act-scale {
  position: relative; height: 18px; margin: 0 0 6px 190px;
  border-bottom: 1px solid var(--border);
}
.act-tick {
  position: absolute; transform: translateX(-50%); font-size: 10.5px;
  color: var(--slate-light); font-family: var(--mono);
}
.act-row {
  display: flex; gap: 14px; align-items: center;
  padding: 10px 0; border-top: 1px solid var(--border);
}
.act-who { display: flex; align-items: center; gap: 9px; width: 176px; flex: 0 0 176px; }
.act-track { flex: 1; min-width: 0; }
.tl-bar {
  position: relative; height: 20px; border-radius: 4px;
  background: var(--canvas); overflow: hidden;
}
.tl-stint { position: absolute; top: 3px; height: 14px; border-radius: 3px; background: var(--blue); }
.tl-gap { position: absolute; top: 3px; height: 14px; border-radius: 3px; background: #E7E9E4; }
.tl-gap.long { background: var(--orange-light); border: 1px solid var(--orange); }
.act-meta {
  display: flex; gap: 14px; flex-wrap: wrap; margin-top: 5px; font-size: 11.5px;
}
.act-legend {
  display: flex; gap: 18px; flex-wrap: wrap; margin-top: 14px;
  padding-top: 12px; border-top: 1px solid var(--border);
  font-size: 11.5px; color: var(--slate);
}
.act-legend i { display: inline-block; width: 14px; height: 10px; border-radius: 2px; margin-right: 5px; }
.sw-stint { background: var(--blue); }
.sw-gap { background: #E7E9E4; }
.sw-long { background: var(--orange-light); border: 1px solid var(--orange); }

@media (max-width: 760px) {
  .act-row { flex-direction: column; align-items: stretch; gap: 6px; }
  .act-who { width: auto; flex: none; }
  .act-scale { margin-left: 0; }
}

/* ------------------------------------------------------------------ toast */
#toast {
  position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%);
  background: var(--navy); color: #fff; padding: 10px 16px;
  border-radius: 8px; font-size: 13px; box-shadow: var(--shadow-pop);
  z-index: 200; max-width: 80vw;
  display: flex; align-items: center; gap: 12px; overflow: hidden;
}
/* an undo-style toast: the button, and a fuse burning down its lifetime */
.toast-act {
  border: 1px solid rgba(255, 255, 255, .4); background: transparent;
  color: #fff; font-size: 12px; font-weight: 700; border-radius: 6px;
  padding: 3px 10px; cursor: pointer; flex: 0 0 auto;
}
.toast-act:hover { background: rgba(255, 255, 255, .14); }
.toast-fuse {
  position: absolute; left: 0; bottom: 0; height: 2px; width: 100%;
  background: rgba(255, 255, 255, .45);
  animation: fuse linear forwards;
  transform-origin: left;
}
@keyframes fuse { to { transform: scaleX(0); } }
#toast.err { border-left: 4px solid #FF8B8B; padding-left: 14px; }
#toast.ok { border-left: 4px solid #6EE7A8; padding-left: 14px; }
/* Something happened, but not the whole thing — e.g. the estimate sent
   while the email sat in an outbox because no provider is configured. */
#toast.warn { border-left: 4px solid #F0B357; padding-left: 14px; }

/* ------------------------------------------------------------------ login */
/* ⭐ THE SEAM BETWEEN THE WEBSITE AND THE APP (2026-09-26). A visitor
   presses Start free on a Blueprint page and lands here, so this one
   screen wears the website's ground rather than the app's. It is a hard
   value on purpose: there is no company yet, so there is no company theme
   to honor, and this has to match landing.html's --bg exactly.
   ⚠️ SCOPED TO .auth-wrap DELIBERATELY. The app itself keeps its own
   palette and its Appearance presets; this is a doorway, not a repaint. */
.auth-wrap {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: 24px; background: #0B131B;
}
.auth-card {
  background: var(--surface); border-radius: 14px; padding: 28px; width: 100%;
  max-width: 420px; box-shadow: var(--shadow-pop);
}
.auth-card h1 { font-family: "Instrument Serif", Georgia, serif;
  font-weight: 400; font-size: 30px; line-height: 1.08; letter-spacing: -.015em;
  margin-bottom: 6px; }
.auth-card .sub { font-size: 13px; color: var(--slate); margin: 0 0 20px; }
.auth-switch { font-size: 12.5px; color: var(--slate); margin-top: 14px; text-align: center; }

.empty {
  text-align: center; padding: 40px 20px; color: var(--slate-light);
  font-size: 13px;
}

/* the designed empty state: icon bubble, one honest line, one way forward */
.empty-state {
  text-align: center; padding: 42px 20px 38px;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
}
.empty-bubble {
  width: 52px; height: 52px; border-radius: 50%;
  background: var(--blue-light); color: var(--blue);
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 6px;
}
.empty-state.good .empty-bubble { background: var(--green-light); color: var(--green); }
.empty-title { margin: 0; font-weight: 600; font-size: 14px; color: var(--ink); }
.empty-note { margin: 0 0 8px; font-size: 12.5px; color: var(--slate); max-width: 40ch; }
.empty-state .btn { margin-top: 6px; }

/* --------------------------------------------------------------- responsive */
@media (max-width: 1000px) {
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .grid-2, .grid-14 { grid-template-columns: 1fr; }
  .searchbox { width: 160px; }
}

/* ⚠️ THE NAV IS THE PRIORITY IN THE TOP BAR, and on a narrow window
   everything beside it yields first. This is not cosmetic tidying: the bar
   is a fixed budget shared by the brand, the nav and the right-hand
   cluster, and at 800px the cluster was taking 312px of it — the strip got
   241 and spilled the entire app into More behind one button. Give those
   pixels back and the same window keeps its groups on the bar. */
@media (max-width: 1180px) {
  #needHelp .btn-label, #reportProblem .btn-label, #settingsBtn .btn-label { display: none; }
  /* ⚠️ THE TOP BAR IS A FIXED BUDGET AND I SPENT 126px OF IT. The sticky
     split button kept its full "Sticky notes" label plus a caret while
     Feedback and Ask had already collapsed to icons — it became the widest
     thing on the bar and pushed the whole cluster past the edge on a
     phone. Caught by the browser self test dropping one route, not by
     looking at it. */
  #stickyNew .btn-label { display: none; }
}
@media (max-width: 760px) {
  /* The drawer is a desk convenience; on a phone the one-tap note is the
     whole feature and the caret is just width. */
  #stickyMore { display: none; }
  .splitbtn > .btn:first-child {
    border-top-right-radius: var(--r); border-bottom-right-radius: var(--r);
  }
}
@media (max-width: 1040px) {
  .brand-co { display: none; }        /* the page head names the company */
  #quickNew .btn-label { display: none; }        /* "+ New" still reads */
  .topbar { gap: 10px; }
  .topbar-right { gap: 8px; }
}
@media (max-width: 760px) {
  /* ⚠️ One of the two mobile defects that lived here still applies
     (MOBILE-PUNCHLIST.md): `.searchbox { display:none }` deleted search
     from phones entirely. It now collapses to a tap-to-expand icon and is
     never removed. The other — `.navlink span { display:none }`, which
     turned 18 features into mystery glyphs — died with the rail itself;
     the tabbar below names every door it shows. */
  .main { padding: 16px 14px 40px; }
  .board { overflow-x: auto; }
  .searchbox {
    display: none;                    /* until the icon opens it */
    position: absolute; left: 8px; right: 8px; top: 100%; margin: 6px 0 0;
    width: auto; background: var(--surface); border-color: var(--border);
    box-shadow: var(--shadow-pop); z-index: 60;
  }
  .topbar.search-open .searchbox { display: flex; }
  #searchToggle { display: flex; }
  .brand-co { display: none; }
  /* ⚠️ The topbar is sticky, so ITS overflow widens every route: at 375px
     the right cluster ran 69px past the screen and the whole app scrolled
     sideways. Phone width: tighter gaps, icon-only Need help. */
  .topbar { gap: 8px; padding-left: 10px; padding-right: 10px; }
  .topbar-right { gap: 8px; min-width: 0; flex-wrap: nowrap; }
  .topbar-right .btn { padding-left: 8px; padding-right: 8px; }
  /* Stephen, 2026-09-11 (a phone screenshot): Owner, Tags and New still
     wore their words at phone width and the cluster ran 20px past the
     edge again. Every bar button is its icon on a phone; the badge on
     Tags still counts, and the words come back at tablet width. */
  #needHelp .btn-label, #reportProblem .btn-label, #tagsWrap .btn-label,
  .topbar-right a.btn .btn-label { display: none; }
  /* the phone-width topbar keeps the mark and drops the words — the page
     head says the company's name two lines lower anyway */
  .brand-name, .brand-company { display: none; }
  /* KPI cards: same height per row, whatever their sub-lines do */
  .grid-4 { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 1fr; }
  .stat .value { font-size: 20px; }
}

@media (max-width: 480px) {
  /* A small phone: tighter still, and Feedback moves into the avatar
     menu (it is there at every width) so the bar never scrolls the app. */
  .topbar { gap: 6px; padding-left: 8px; padding-right: 8px; }
  .topbar-right { gap: 6px; }
  .topbar-right .btn { padding-left: 7px; padding-right: 7px; }
  #reportProblem, #ownerLink { display: none; }
}

/* The search icon lives in the topbar always, shown only at phone width.
   ⚠️ The media override must FOLLOW this base rule — same specificity, so
   source order decides, and a base display:none written later silently
   wins at every width. That exact bug shipped for five minutes. */
#searchToggle {
  display: none; align-items: center; justify-content: center;
  width: 32px; height: 32px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: var(--surface); cursor: pointer;
  color: var(--slate); flex: 0 0 auto;
}
@media (max-width: 760px) {
  #searchToggle { display: flex; }
}

/* --------------------------------------------------------------------- AI */
/* A draft should never look like a saved record. */
.ai-card { border-left: 3px solid var(--blue); background: var(--ai-wash); }
.ai-headline { font-family: var(--display); font-weight: 600; font-size: 15px; margin: 0 0 6px; }
.ai-status { font-size: 13.5px; margin: 0 0 12px; color: var(--ink); }
.ai-list { margin: 4px 0 12px; padding-left: 18px; font-size: 13px; color: var(--slate); }
.ai-list li { margin-bottom: 3px; }
.ai-list li b { color: var(--ink); font-weight: 500; }
.ai-concern {
  display: flex; align-items: flex-start; gap: 6px; font-size: 13px;
  color: var(--amber); background: var(--amber-light);
  border-radius: 6px; padding: 8px 10px; margin: 0 0 10px;
}
.ai-error { font-size: 12.5px; color: var(--red); margin: 10px 0 0; }
.ai-prov {
  font-family: var(--mono); font-size: 11px; color: var(--slate-light);
  margin: 10px 0 0; border-top: 1px solid var(--border); padding-top: 8px;
}

/* ------------------------------------------------------------- checklists */
.cl-bar {
  height: 8px; border-radius: 4px; background: var(--canvas);
  overflow: hidden; border: 1px solid var(--border);
}
.cl-bar.sm { height: 6px; }
.cl-bar span { display: block; height: 100%; transition: width .25s ease; }

.cl-item {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 9px 0; border-top: 1px solid var(--border);
}
.cl-item:first-of-type { border-top: 0; }
.cl-item.done .cl-label { color: var(--slate); text-decoration: line-through; }
.cl-item.na .cl-label { color: var(--slate-light); }
.cl-item.blocked { background: var(--amber-light); border-radius: 6px; padding-left: 8px; padding-right: 8px; }
.cl-label { font-size: 13.5px; margin: 0; }
.cl-meta { font-size: 11.5px; color: var(--slate-light); margin: 2px 0 0; }
.cl-blocked {
  display: flex; align-items: center; gap: 5px;
  font-size: 12px; color: var(--amber); margin: 3px 0 0;
}
.cl-tick {
  flex: 0 0 auto; width: 24px; height: 24px; border-radius: 6px;
  border: 1px solid var(--border); background: var(--surface); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  color: var(--green); padding: 0;
}
.cl-tick:hover { border-color: var(--green); }
.cl-item.done .cl-tick { background: var(--green-light); border-color: var(--green); }
.cl-empty { width: 10px; height: 10px; }
.cl-actions { display: flex; gap: 2px; flex: 0 0 auto; opacity: 0; }
.cl-item:hover .cl-actions, .cl-item.blocked .cl-actions, .cl-item.na .cl-actions { opacity: 1; }
/* ⚠️ AND ON A PHONE THEY ARE ALWAYS THERE. opacity:0 until hover means
   never on a touch screen — Block and N/A have been unreachable on the
   device this checklist is actually used on. ⚠️ THIS MUST FOLLOW the base
   rule above: same specificity, so source order decides, and the same
   mistake is already documented on .searchbox further down. */
@media (max-width: 760px) {
  .cl-actions { opacity: 1; }
  /* ⚠️ AND THE ROW WRAPS. Beside a tick, a camera, a yes/no and three
     buttons, the label column on a 375px phone was about eight characters
     wide — "Anything already broken" came out one word per line. The
     controls drop under the text instead, which is the only arrangement
     that leaves the words readable on the device a crew is holding. */
  .cl-item { flex-wrap: wrap; }
  .cl-item > .grow { flex: 1 1 100%; order: 1; }
  .cl-tick { order: 0; }
  .cl-primary, .cl-actions { order: 2; margin-left: 26px; }
  .cl-actions { flex-wrap: wrap; gap: 4px; }
}

/* A key or URL you need to read in full and copy. Not an <input>: a long
   value in a one-line field is exactly what made this painful. */
.keybox {
  font-family: var(--mono); font-size: 12.5px; line-height: 1.5;
  background: var(--canvas); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 10px 12px;
  word-break: break-all; user-select: all; -webkit-user-select: all;
  color: var(--ink);
}

/* A line the AI scoped but nobody has measured. Zero is not a price. */
input.needs-qty {
  border-color: var(--amber); background: var(--amber-light);
}

/* Same warning in a read-only table — a supplement item with no quantity
   cannot be sent, so it should be impossible to miss on the way past. */
td.needs-qty {
  color: var(--amber); font-weight: 600;
}

/* The "and this is what it all adds up to" row on a carrier scope. */
table.data tfoot td {
  border-top: 2px solid var(--border); padding-top: 10px;
}

/* Compose, on the Communications tab. Sized for a thumb: the textarea is big
   enough to see what you wrote and the button is full width on a phone. */
.compose { display: flex; flex-direction: column; gap: 10px; }
.kind-row { display: flex; flex-wrap: wrap; gap: 6px; }
.compose textarea { width: 100%; font-size: 15px; }
@media (max-width: 620px) {
  .compose .btn { width: 100%; justify-content: center; }
}

/* ---- rep diagnosis ---------------------------------------------------- */
/* The sentence leads. The table exists to back it up, not to be stared at. */
.diagnosis {
  border-left: 3px solid var(--blue); background: var(--blue-light);
  padding: 11px 14px; border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  margin: 0 0 14px;
}
.diagnosis.muted-diag {
  border-left-color: var(--slate-light); background: var(--canvas);
}
.diag-head {
  margin: 0; font-weight: 600; font-size: 14px; display: flex;
  align-items: center; gap: 7px; color: var(--ink);
}
.diag-detail { margin: 5px 0 0; font-size: 13px; color: var(--slate); }
.diag-fix {
  margin: 7px 0 0; font-size: 12.5px; color: var(--slate);
  display: flex; align-items: baseline; gap: 6px;
}

/* Pitch sections, worst first — the shape of the bar is the message. */
.sections { display: flex; flex-direction: column; gap: 5px; }
.sec-row { display: flex; align-items: center; gap: 10px; font-size: 12.5px; }
.sec-label { width: 150px; flex: 0 0 auto; color: var(--slate); }
.sec-track {
  flex: 1; height: 7px; background: var(--canvas);
  border-radius: 4px; overflow: hidden;
}
.sec-fill { display: block; height: 100%; border-radius: 4px; }
.sec-val { width: 28px; text-align: right; flex: 0 0 auto; }

/* ---- photos and documents -------------------------------------------- */
/* Capture. Designed for someone standing on a roof holding a phone in one
   hand, so the targets are big and there are only two of them. */
.capture {
  border: 2px dashed var(--border); border-radius: var(--radius);
  padding: 16px; background: var(--canvas);
  transition: border-color .12s, background .12s;
}
.capture.over { border-color: var(--blue); background: var(--blue-light); }

.phase-row { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 14px; }
.phase {
  border: 1px solid var(--border); background: var(--surface); color: var(--slate);
  border-radius: 999px; padding: 7px 14px; font-size: 13px; cursor: pointer;
  font-weight: 500;
}
.phase.on {
  background: var(--ink); color: #fff; border-color: var(--ink);
}
.capture-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.btn.big { padding: 12px 18px; font-size: 14.5px; }

/* Batch progress. A bar plus a count, because "uploading…" for four minutes
   with no number is indistinguishable from a hang. */
.upload-status { margin-top: 12px; }
.up-track {
  height: 8px; background: var(--canvas); border: 1px solid var(--border);
  border-radius: 5px; overflow: hidden;
}
.up-fill {
  display: block; height: 100%; background: var(--blue);
  transition: width .2s ease;
}

@media (max-width: 620px) {
  .capture-actions { flex-direction: column; }
  .capture-actions .btn { width: 100%; justify-content: center; }
}

/* Photo reading. The picture sits next to what was said about it, because a
   description you cannot check against the image is worth nothing. */
.triage-grid {
  display: flex; flex-direction: column; gap: 10px; margin-top: 12px;
  max-height: 420px; overflow-y: auto;
}
.triage-row { display: flex; gap: 11px; align-items: flex-start; }
.triage-row img {
  width: 74px; height: 56px; object-fit: cover; border-radius: 5px;
  flex: 0 0 auto; background: var(--canvas);
}
.triage-row .b { margin: 0; font-size: 13px; line-height: 1.4; }
.triage-row .micro { margin: 3px 0 0; }
.cond-dmg { color: var(--orange); font-weight: 600; }
.cond-unclear { color: var(--slate-light); }

.file-grid {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
/* Gap sixteen: how many people have said something about this picture. */
.tile-comments{position:absolute;top:8px;right:8px;display:inline-flex;align-items:center;gap:4px;
  padding:2px 7px;border-radius:999px;background:rgba(15,19,26,.72);color:#fff;font:600 11px var(--mono,monospace);
  backdrop-filter:blur(4px);pointer-events:none}
.lb-comments{border-top:1px solid var(--border);margin-top:10px;padding-top:6px}
.lb-comments .msg-list .msg{padding:6px 0}
/* Pick 23: live listen-in */
.live-visit { border-top: 1px solid var(--border); padding: 10px 0; }
.live-text { font-size: 13px; margin: 6px 0 0; max-height: 120px; overflow: auto; white-space: pre-wrap; color: var(--text); }
/* Pick 10: the coach */
.coach-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 10px; margin-top: 10px; }
.coach-item { border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; background: var(--surface); font-size: 13px; }
.coach-item b { display: block; margin: 6px 0 4px; }
.coach-item p { margin: 0 0 4px; }
.coach-item .micro { margin: 0 4px 0 0; }
/* Gap pick 1: the sparkle on a customer-facing field */
.rw-btn { display: inline-flex; align-items: center; gap: 5px; margin: 6px 0 0; padding: 3px 9px; font: inherit; font-size: 12px;
  border: 1px solid var(--border); border-radius: 999px; background: var(--surface); color: var(--slate); cursor: pointer; }
.rw-btn:hover { color: var(--text); border-color: var(--blue); }
.rw-pop { display: inline-flex; flex-wrap: wrap; gap: 4px; margin: 6px 0 0 6px; padding: 6px; border: 1px solid var(--border);
  border-radius: 10px; background: var(--surface); box-shadow: var(--shadow-pop); vertical-align: middle; }
.rw-pop button { font: inherit; font-size: 12.5px; padding: 5px 10px; border-radius: 7px; border: 0; background: transparent; color: var(--text); cursor: pointer; }
.rw-pop button:hover { background: var(--raise); }
.rw-pop.busy { opacity: .5; pointer-events: none; }
/* Gap sixty-four: the projects on a job */
.proj-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 10px; }
.proj { border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; background: var(--surface); }
.proj-nums { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 6px; font-size: 12px; color: var(--slate); }
.proj-nums b { color: var(--text); }
/* Gap sixty-three: the field designer over rendered pages */
.fd-palette { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin: 0 0 10px; }
.fd-palette .btn.on { outline: 2px solid var(--blue); }
.fd-pages { max-height: 62vh; overflow: auto; background: var(--raise); padding: 10px; border-radius: 8px; }
.fd-page { position: relative; margin: 0 auto 10px; max-width: 760px; background: #fff;
  box-shadow: 0 1px 4px rgba(0,0,0,.3); touch-action: none; }
.fd-page.placing { cursor: crosshair; }
.fd-field { position: absolute; box-sizing: border-box; border: 1.5px dashed var(--blue);
  background: rgba(59,130,246,.18); color: var(--blue); font-size: 11px; display: flex;
  align-items: center; gap: 4px; padding: 0 4px; cursor: move; user-select: none;
  overflow: visible; white-space: nowrap; }
.fd-field .fd-lbl { overflow: hidden; text-overflow: ellipsis; }
.fd-x { position: absolute; top: -9px; right: -9px; width: 18px; height: 18px; border-radius: 50%;
  background: var(--red); color: #fff; font-size: 13px; line-height: 17px; text-align: center; cursor: pointer; }
.fd-rs { position: absolute; right: -5px; bottom: -5px; width: 12px; height: 12px; background: var(--blue);
  border-radius: 2px; cursor: nwse-resize; }
.fd-req { margin-left: auto; font-size: 9px; padding: 0 4px; border-radius: 6px; background: var(--blue);
  color: #fff; cursor: pointer; opacity: .45; }
.fd-req.on { opacity: 1; }
/* Gap sixty-two: the pages on a proposal */
.page-chip { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; padding: 3px 9px;
  border-radius: 999px; background: var(--surface, #fff); border: 1px solid var(--border); }
.page-chip button { background: none; border: 0; color: var(--slate); cursor: pointer; font-size: 15px;
  line-height: 1; padding: 0; }
.page-chip button:hover { color: var(--red, #B3122F); }
/* Gap sixty-one: pictures on estimate lines, the picker, the book column */
.line-photos { display: inline-flex; align-items: center; gap: 4px; margin-left: 6px; vertical-align: middle; }
.line-thumb { width: 34px; height: 26px; object-fit: cover; border-radius: 4px;
  box-shadow: 0 1px 2px rgba(0,0,0,.25); display: inline-block; vertical-align: middle; }
.pick-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));
  gap: 8px; max-height: 52vh; overflow: auto; padding: 2px; }
.pick-tile { position: relative; margin: 0; border: 2px solid var(--border); border-radius: 10px;
  overflow: hidden; cursor: pointer; background: var(--surface, #fff); }
.pick-tile img { display: block; width: 100%; height: 88px; object-fit: cover; }
.pick-tile figcaption { font-size: 11px; padding: 4px 6px; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; color: var(--slate); }
.pick-tile .pick-mark { position: absolute; top: 6px; right: 6px; width: 20px; height: 20px;
  border-radius: 50%; background: var(--blue); color: #fff; display: none; align-items: center;
  justify-content: center; }
.pick-tile.on { border-color: var(--blue); }
.pick-tile.on .pick-mark { display: inline-flex; }
.pb-img { width: 36px; height: 30px; border: 1px dashed var(--border); border-radius: 6px;
  background: transparent; color: var(--slate); display: inline-flex; align-items: center;
  justify-content: center; cursor: pointer; padding: 0; overflow: hidden; }
.pb-img.has { border-style: solid; }
.pb-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.file-tile { position: relative;
  margin: 0; cursor: pointer; border: 1px solid var(--border);
  border-radius: var(--radius-sm); overflow: hidden; background: var(--surface);
  transition: border-color .12s, transform .12s;
}
.file-tile:hover { border-color: var(--blue); transform: translateY(-1px); }
.file-tile img {
  width: 100%; height: 118px; object-fit: cover; display: block;
  background: var(--canvas);
}
.file-tile figcaption {
  padding: 8px 9px; display: flex; flex-direction: column; gap: 3px;
  font-size: 12px; line-height: 1.35;
}
.file-tile figcaption b {
  font-weight: 500; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}
.doc-tile {
  height: 118px; display: flex; flex-direction: column; gap: 6px;
  align-items: center; justify-content: center; background: var(--canvas);
  color: var(--slate); font-family: var(--mono); font-size: 11px;
}

/* A document as a small sheet in its kind's color (11/10). */
.doc-tile.doc-sheet { background: var(--canvas); align-items: stretch; justify-content: flex-start; gap: 0; padding: 10px 14px 0; font-family: inherit; }
.doc-sheet > .doc-band, .doc-sheet > .doc-lines { background: #fff; }
.doc-sheet .doc-band { display: flex; align-items: center; gap: 6px; padding: 7px 9px; border-radius: 6px 6px 0 0;
  border-top: 4px solid var(--doc); color: var(--doc); font-size: 11.5px; box-shadow: 0 1px 3px rgba(0,0,0,.12); }
.doc-sheet .doc-band b { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.doc-sheet .doc-lines { flex: 1; display: flex; flex-direction: column; gap: 5px; padding: 4px 9px 0; box-shadow: 0 1px 3px rgba(0,0,0,.12); }
.doc-sheet .doc-lines span { font-size: 10.5px; color: #4a5568; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.doc-sheet .doc-lines i { display: block; height: 4px; border-radius: 2px; background: #e2e8f0; }
.doc-sheet .doc-lines i:nth-child(3) { width: 80%; } .doc-sheet .doc-lines i:nth-child(4) { width: 55%; }

/* Lightbox. The image gets the room; the chrome stays out of the way. */
.lb-stage {
  position: relative; display: flex; align-items: center;
  justify-content: center; background: var(--ink);
  border-radius: var(--radius-sm); min-height: 260px; margin: 10px 0;
}
.lb-stage img { max-width: 100%; max-height: 62vh; display: block; }
.lb-doc {
  /* The stage is painted --ink, so the words on it take the page ground:
     white text vanished on the light stage of the dark theme. */
  color: var(--surface, #fff); text-align: center; padding: 40px 20px;
  display: flex; flex-direction: column; gap: 10px; align-items: center;
}
.lb-nav {
  position: absolute; left: 6px; top: 50%; transform: translateY(-50%);
  width: 38px; height: 38px; border-radius: 50%; border: 0; cursor: pointer;
  background: #0009; color: #fff; font-size: 22px; line-height: 1;
}
.lb-nav.right { left: auto; right: 6px; }
.lb-nav:hover { background: #000c; }

/* Evidence attached to a supplement item — small, inline, and clearly
   different from the item's own text. */
.evidence-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.evidence-chip {
  display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px;
  border: 1px solid var(--border); border-radius: 999px; padding: 2px 4px 2px 2px;
  background: var(--surface);
}
.evidence-chip img {
  width: 22px; height: 22px; object-fit: cover; border-radius: 50%;
}
.evidence-chip button {
  border: 0; background: none; cursor: pointer; color: var(--slate);
  font-size: 13px; line-height: 1; padding: 0 3px;
}
.evidence-chip button:hover { color: var(--red); }

/* The letter to the carrier: plain text, but long, so it scrolls in place
   rather than stretching the card. */
pre.keybox {
  font-family: var(--code);
  max-height: 380px; overflow: auto; word-break: normal;
  user-select: text; -webkit-user-select: text;
}

/* ------------------------------------------------------------ plan cards */
.plans { display: grid; gap: 12px; grid-template-columns: repeat(3, 1fr); }
.plan {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 12px 14px; background: var(--surface);
}
.plan.on { border-color: var(--blue); box-shadow: 0 0 0 1px var(--blue); }
.pill {
  font-size: 12px; padding: 3px 9px; border-radius: 999px;
  background: var(--canvas); color: var(--slate); white-space: nowrap;
}
.pill.ok { background: var(--green-light); color: var(--green-deep); }
.pill.warn { background: var(--amber-light); color: var(--amber); }
.pill.bad { background: var(--red-light); color: var(--red); }
@media (max-width: 760px) { .plans { grid-template-columns: 1fr; } }

/* ---- phone cards for the list tables (phone walk, 2026-11-06) ----------
   On a phone the Jobs, Leads, Properties and Production tables were a
   table crushed into 390px: "J-" over "2203", names and streets wrapped
   three lines deep, Stage and Source pushed off the edge. Under 760px each
   row of a `.phone-cards` table is a card instead, laid out by grid areas
   on the SAME cells (no second markup to keep in step), and the table drops
   the 460px minimum the other tables keep, so nothing scrolls sideways.
   The cells are picked by position, so a column added to one of these
   tables must be placed here too. `.novalue` hides an empty value's dash. */
@media (max-width: 760px) {
  .table-scroll > table.data.phone-cards, table.data.phone-cards {
    display: block; width: 100%; min-width: 0;
  }
  table.data.phone-cards thead { display: none; }
  table.data.phone-cards tbody { display: block; }
  table.data.phone-cards tbody tr {
    display: grid; gap: 3px 8px; padding: 12px 2px; align-items: center;
    border-bottom: 1px solid var(--border);
  }
  table.data.phone-cards tbody tr:last-child { border-bottom: 0; }
  table.data.phone-cards tbody td {
    display: block; padding: 0; border: 0; min-width: 0 !important;
    max-width: none !important; white-space: normal;
  }
  table.data.phone-cards tbody tr.clickable:hover td { background: none; }
  table.data.phone-cards tbody tr:has(> td[colspan]) { display: block; }
  table.data.phone-cards tbody td.novalue { display: none; }

  /* Jobs and Leads: 1 pick 2 number 3 customer 4 address 5 stage 6 source
     7 trade 8 segment 9 value 10 owner 11 updated */
  table.data.cards-jobs tbody tr {
    grid-template-columns: 22px auto auto 1fr;
    grid-template-areas:
      "pick name  name  value"
      ".    addr  addr  addr"
      ".    stage num   upd"
      ".    owner owner src";
  }
  table.data.cards-jobs tbody td:nth-child(1) { grid-area: pick; }
  table.data.cards-jobs tbody td:nth-child(2) { grid-area: num; font-size: 12px; }
  table.data.cards-jobs tbody td:nth-child(3) { grid-area: name; font-size: 15px; line-height: 1.3; }
  table.data.cards-jobs tbody td:nth-child(4) { grid-area: addr; font-size: 13px; }
  table.data.cards-jobs tbody td:nth-child(5) { grid-area: stage; }
  table.data.cards-jobs tbody td:nth-child(6) { grid-area: src; font-size: 12px; text-align: right; }
  table.data.cards-jobs tbody td:nth-child(7),
  table.data.cards-jobs tbody td:nth-child(8) { display: none; }
  table.data.cards-jobs tbody td:nth-child(9) { grid-area: value; font-weight: 600; text-align: right; }
  table.data.cards-jobs tbody td:nth-child(10) { grid-area: owner; font-size: 12px; }
  table.data.cards-jobs tbody td:nth-child(11) { grid-area: upd; font-size: 12px; text-align: right; }

  /* Properties: 1 address 2 city 3 type 4 trades 5 jobs 6 open 7 lifetime
     8 last activity */
  table.data.cards-props tbody tr {
    grid-template-columns: auto auto 1fr auto;
    grid-template-areas:
      "addr addr   addr life"
      "city city   city last"
      "type trades jobs open";
  }
  table.data.cards-props tbody td:nth-child(1) { grid-area: addr; font-size: 15px; }
  table.data.cards-props tbody td:nth-child(2) { grid-area: city; font-size: 13px; }
  table.data.cards-props tbody td:nth-child(3) { grid-area: type; }
  table.data.cards-props tbody td:nth-child(4) { grid-area: trades; }
  table.data.cards-props tbody td:nth-child(5) { grid-area: jobs; font-size: 12px; text-align: right; }
  table.data.cards-props tbody td:nth-child(5)::before { content: "Jobs "; color: var(--slate-light); }
  table.data.cards-props tbody td:nth-child(6) { grid-area: open; font-size: 12px; text-align: right; }
  table.data.cards-props tbody td:nth-child(6)::before { content: "Open "; color: var(--slate-light); }
  table.data.cards-props tbody td:nth-child(7) { grid-area: life; font-weight: 600; text-align: right; }
  table.data.cards-props tbody td:nth-child(8) { grid-area: last; font-size: 12px; text-align: right; }

  /* The job's invoices, by cell class (a Project column comes and goes). */
  table.data.cards-inv tbody tr {
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "num  bal"
      "for  when"
      "proj proj"
      "amt  paid"
      "act  act";
  }
  table.data.cards-inv td.inv-num { grid-area: num; font-weight: 600; }
  table.data.cards-inv td.inv-for { grid-area: for; font-size: 13px; }
  table.data.cards-inv td.inv-proj { grid-area: proj; font-size: 12px; }
  table.data.cards-inv td.inv-amt { grid-area: amt; font-size: 12px; }
  table.data.cards-inv td.inv-amt::before { content: "Amount "; color: var(--slate-light); font-family: inherit; }
  table.data.cards-inv td.inv-paid { grid-area: paid; font-size: 12px; text-align: right; }
  table.data.cards-inv td.inv-paid::before { content: "Paid "; color: var(--slate-light); font-family: inherit; }
  table.data.cards-inv td.inv-bal { grid-area: bal; font-weight: 600; text-align: right; }
  table.data.cards-inv td.inv-when { grid-area: when; font-size: 12px; text-align: right; }
  table.data.cards-inv td.inv-act { grid-area: act; white-space: normal !important; margin-top: 6px; }
  table.data.cards-inv td.inv-act .btn { margin: 0 6px 6px 0; }

  /* Production: 1 number 2 customer 3 address 4 trade 5 progress
     6 outstanding 7 owner 8 value */
  table.data.cards-prod tbody tr {
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "name  value"
      "addr  addr"
      "prog  prog"
      "out   num"
      "owner trade";
  }
  table.data.cards-prod tbody td:nth-child(1) { grid-area: num; font-size: 12px; text-align: right; }
  table.data.cards-prod tbody td:nth-child(2) { grid-area: name; font-size: 15px; }
  table.data.cards-prod tbody td:nth-child(3) { grid-area: addr; font-size: 13px; }
  table.data.cards-prod tbody td:nth-child(4) { grid-area: trade; text-align: right; }
  table.data.cards-prod tbody td:nth-child(5) { grid-area: prog; }
  table.data.cards-prod tbody td:nth-child(6) { grid-area: out; font-size: 12.5px; }
  table.data.cards-prod tbody td:nth-child(7) { grid-area: owner; font-size: 12px; }
  table.data.cards-prod tbody td:nth-child(8) { grid-area: value; font-weight: 600; text-align: right; }
}

/* ------------------------------------------------- the follow-up worklist
   ⚠️ THIS LIST IS WORKED FROM A PHONE, standing on a driveway between two
   calls — which is exactly where the rest of the app's tables get away with
   scrolling sideways inside their card and this one does not. Every row here
   ends in a decision (ring them, send it, push it back), and a button you
   have to scroll horizontally to reach is a button nobody presses.
   So on a narrow screen each row stops being a table row and becomes a card:
   date and customer on one line, the task, then the actions full width. */
@media (max-width: 760px) {
  .worklist, .worklist tbody, .worklist tr, .worklist td { display: block; }
  .worklist { min-width: 0 !important; table-layout: auto !important; }
  .worklist colgroup { display: none; }
  .worklist tr {
    padding: 12px 0; border-bottom: 1px solid var(--border);
  }
  .worklist tr:last-child { border-bottom: 0; }
  table.data.worklist td { border-top: 0; padding: 0 2px; }
  table.data.worklist td + td { margin-top: 6px; }
  table.data.worklist td.num {
    text-align: left; white-space: normal; margin-top: 10px;
    font-family: inherit;
  }
  .worklist td.num .btn { margin: 0 6px 6px 0; }
}

/* ---- the field mode (knock view) ---------------------------------- */
.knock-view { display: flex; flex-direction: column; gap: 10px;
  height: calc(100vh - var(--topbar-h, 49px) - 48px); }
.knock-top { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.knock-top .page-kicker { margin: 0; }
.knock-stats { display: flex; gap: 14px; margin-left: auto; font-size: 13px;
  color: var(--slate); }
.knock-stats b { color: var(--ink); font-family: var(--display); }
.knock-gps { align-self: flex-start; display: inline-flex; align-items: center;
  gap: 6px; font-size: 12px; color: var(--slate); background: var(--surface);
  border: 1px solid var(--border); border-radius: 999px; padding: 3px 10px; }
.knock-gps.ok { color: var(--green); border-color: var(--green-light); }
/* The Knock gateway — the page that replaced the in-shell map. */
.knock-gate { max-width: 640px; }
.knock-gate h3 { margin: 0 0 6px; }
.knock-gate p { font-size: 13.5px; line-height: 1.55; margin: 0 0 10px; }
.knock-gate .row-gap { display: flex; gap: 9px; flex-wrap: wrap;
  align-items: center; margin-top: 4px; }
.gate-out { display: none; margin-top: 12px; font-size: 13px; line-height: 1.55;
  border-radius: var(--radius); padding: 10px 12px; }
.gate-out.ok { display: block; background: var(--green-light); color: var(--green); }
.gate-out.err { display: block; background: var(--amber-light); color: var(--amber); }
.knock-gate .knock-unfiled { margin-top: 14px; }
.knock-unfiled { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-size: 13px; color: var(--amber); background: var(--amber-light);
  border-radius: var(--radius); padding: 8px 12px; }
.knock-unfiled[hidden] { display: none; }
.knock-map { flex: 1; min-height: 320px; border-radius: var(--radius);
  border: 1px solid var(--border); overflow: hidden; background: #E9ECE6;
  z-index: 0; }
.knock-sheet[hidden] { display: none; }
.knock-sheet { position: absolute; right: 24px; bottom: 24px; width: 340px;
  max-width: calc(100vw - 48px); background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-pop); padding: 14px;
  display: flex; flex-direction: column; gap: 10px; z-index: 1000; }
.knock-sheet-head { display: flex; align-items: center; justify-content: space-between; }
.knock-sheet input, .knock-sheet textarea { width: 100%; box-sizing: border-box;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 8px 10px; font: inherit; }
.dispo-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.dispo-chip { border: 1px solid var(--border); background: var(--surface); color: var(--ink);
  border-radius: var(--radius-sm); padding: 8px 6px; font-size: 12.5px;
  cursor: pointer; border-left: 3px solid var(--chip); }
.dispo-chip.on { background: var(--chip); border-color: var(--chip); color: #fff; }
#apptFields { display: flex; flex-direction: column; gap: 6px; }
#apptFields[hidden] { display: none; }
.pin-pop p { margin: 2px 0; font-size: 12.5px; }
.knock-view .main, .knock-view { position: relative; }
@media (max-width: 760px) {
  .knock-view { height: calc(100vh - var(--topbar-h, 49px) - 24px); }
  .knock-sheet { position: fixed; left: 12px; right: 12px; width: auto;
    bottom: 12px; }
}

/* ------------------------------------------------------------------ mail */
.note { background: var(--canvas); border-radius: var(--radius-sm);
  padding: 10px 14px; font-size: 13px; margin-top: 10px; }
.mailcard { position: relative; width: 100%; overflow: hidden;
  /* Its own width is the unit every length inside is a fraction of
     (100cqw in mail.js units()) — without this a tile drew a 436px card. */
  container-type: inline-size;
  border: 1px solid var(--border); border-radius: 6px; background: var(--surface);
  box-shadow: 0 1px 3px rgba(0,0,0,.08); }
.mailtile-grid { display: grid; gap: 18px;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.mailtile { min-width: 0; }
.scheme-chip { width: 26px; height: 26px; border-radius: 50%;
  border: 2px solid var(--border); cursor: pointer; padding: 0; }
.scheme-chip.on { border-color: var(--ink); box-shadow: 0 0 0 2px #fff inset; }
.designer { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.designer-preview { min-width: 0; }
.designer-form { min-width: 0; }
@media (max-width: 760px) {
  .designer { grid-template-columns: 1fr; }
}


/* ---- one-tap stage advance on pipeline cards */
.card-adv { margin-left: auto; border: 1px solid var(--border);
  background: var(--surface); border-radius: 6px; width: 26px; height: 22px;
  display: grid; place-items: center; cursor: pointer; color: var(--blue);
  opacity: .55; transition: opacity .12s; }
.lead-card:hover .card-adv, .card-adv:focus-visible { opacity: 1; }

/* ---- settings tab panes */
.set-pane.hidden { display: none; }


/* ---- tap-to-act contact chips */
a.chip { text-decoration: none; display: inline-flex; align-items: center;
  gap: 5px; cursor: pointer; }
a.chip:hover { border-color: var(--blue); color: var(--blue); }

/* ---- the phone tab bar (motion study 01). Hidden above 760px; below it,
   the rail hides and these five thumb doors take over. Blurred like iOS,
   safe-area aware, and the .on state inherits renderRoute's document-wide
   data-nav highlighting. */
.tabbar { display: none; }
body.page-owns-new #quickNew { display: none; }  /* motion study 05 */
@media (max-width: 760px) {
  .tabbar {
    display: flex; position: fixed; left: 10px; right: 10px;
    bottom: calc(10px + env(safe-area-inset-bottom, 0px)); z-index: 90;
    background: var(--navy);
    background: color-mix(in srgb, var(--navy) 88%, transparent);
    -webkit-backdrop-filter: blur(10px) saturate(1.2);
    backdrop-filter: blur(10px) saturate(1.2);
    border: 1px solid var(--navy-line); border-radius: 18px;
    padding: 6px 4px calc(6px);
    justify-content: space-around; align-items: center;
    box-shadow: 0 10px 30px rgba(0, 0, 0, .35);
  }
  .tab-item {
    display: flex; flex-direction: column; align-items: center; gap: 3px;
    border: 0; background: transparent; color: var(--navy-text);
    font-size: 9.5px; padding: 5px 10px; border-radius: 12px; cursor: pointer;
    min-width: 54px;
  }
  .tab-item.on { color: #fff; }
  .tab-item.on svg { color: var(--blue); filter: drop-shadow(0 0 7px var(--blue)); }
  .main { padding-bottom: calc(86px + env(safe-area-inset-bottom, 0px)); }
}

/* stage chips over the phone board (motion study 04): name the whole
   pipeline up front, tap to slide there. Desktop sees all columns anyway. */
.board-chips { display: none; }
@media (max-width: 760px) {
  .board-chips {
    display: flex; gap: 6px; overflow-x: auto; margin: 0 0 10px;
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
  }
  .board-chips::-webkit-scrollbar { display: none; }
  .board-chip {
    font-family: var(--mono); font-size: 11px; font-weight: 600;
    color: var(--slate); background: var(--canvas);
    border: 1px solid var(--border); border-radius: 99px;
    padding: 6px 11px; white-space: nowrap; cursor: pointer; flex: 0 0 auto;
  }
  .board-chip.on { color: #fff; background: var(--blue); border-color: var(--blue); }
  /* phone columns are real columns you slide between, not five slivers */
  .board {
    display: flex; overflow-x: auto; scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
  }
  .board-col { flex: 0 0 84%; scroll-snap-align: start; }
}

/* ---------------------------------------------------------- the AI orb
   Ember orbit: the one mark that says "this part is intelligent", on every
   bar the AI owns. A glowing band circles one way, two sparks drift the
   other, the core breathes. Pure CSS, screen-blended, sized by --orb.
   .busy makes it think faster; prefers-reduced-motion stills it. */
/* THE ORB IS TIDE — Stephen's settled pick (8/31): the original from the
   gallery, small. A glass sphere of ocean-blue water, one wave turning,
   the fill breathing up and down. Ocean on purpose: the AI never wears
   the company brand — one recognisable creature across every company.
   24px standard, 34 in the large slots. Thinking stirs the water a
   little quicker — a swell, never a boil. */
/* An orb with a topic is a door — say so on hover, and to keyboards. */
.ai-orb[data-ask-topic]{cursor:pointer;transition:transform .15s ease}
.ai-orb[data-ask-topic]:hover{transform:scale(1.18)}
.ai-orb[data-ask-topic]:focus-visible{outline:2px solid var(--blue);
  outline-offset:3px;border-radius:50%}
.ai-orb{--orb:24px;width:var(--orb);height:var(--orb);position:relative;
  display:inline-block;vertical-align:-6px;flex:none;border-radius:50%;
  overflow:hidden;
  filter:drop-shadow(0 0 5px hsl(202 75% 55% / .45))}
.ai-orb::before{content:'';position:absolute;width:200%;height:200%;
  left:-50%;top:56%;border-radius:42%;
  background:linear-gradient(hsl(202 78% 58% / .92),hsl(210 72% 44%));
  animation:tide-spin 6s linear infinite,tide-rise 9s ease-in-out infinite}
.ai-orb::after{content:'';position:absolute;inset:0;border-radius:50%;
  background:radial-gradient(circle at 32% 26%,rgba(255,255,255,.5),transparent 45%)}
.ai-orb i{display:none}
.ai-orb.lg{--orb:34px;vertical-align:-9px}
@keyframes tide-spin{to{transform:rotate(360deg)}}
@keyframes tide-rise{0%,100%{top:60%}50%{top:36%}}
/* thinking: the water stirs, it does not boil */
.ai-orb.busy::before{animation-duration:3.8s,6s}
/* No box around the water (Stephen, 8/31): the orb floats bare in the
   topbar — no border, no ring, no button chrome. The sphere's own glow
   is the affordance, and hover deepens it so it still reads as a button. */
#needHelp {
  position: relative;
  border: 0; background: transparent; box-shadow: none; padding: 4px 6px;
}
#needHelp:hover { border: 0; background: transparent; }
#needHelp:hover .ai-orb { filter: drop-shadow(0 0 9px hsl(202 80% 58% / .7)); }
/* Riley, offered where she would make a call (2026-10-02): one quiet line
   with her orb beside the thing she would call about. */
.riley-ask{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0;
  padding:7px 10px;border:1px solid var(--border);border-radius:10px;
  background:var(--brand-wash, transparent);font-size:13px}
.riley-ask .ai-orb{--orb:18px;flex:none}
.riley-ask-text{flex:0 1 auto;min-width:0}
.riley-ask .btn{margin-left:auto}
.riley-ask-pick{width:auto;padding:2px 6px;font-size:12.5px}
.riley-ask-muted{background:transparent;border-style:dashed;color:var(--muted)}
.riley-ask-chip .ai-orb{--orb:14px;vertical-align:-2px}
@media (prefers-reduced-motion:reduce){
  .ai-orb::before,.ai-orb::after,.ai-orb i{animation:none}}
.tile-orb{display:grid;place-items:center;height:34px}

/* Polish batch: lift on hover, breath between screens, sticky job header */
.card{transition:transform .15s ease,box-shadow .15s ease}
.card:hover{transform:translateY(-2px);box-shadow:0 6px 18px rgba(0,0,0,.28)}
#main.view-in{animation:viewfade .12s ease}
@keyframes viewfade{from{opacity:.3;transform:translateY(3px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  .card{transition:none}.card:hover{transform:none}
  #main.view-in{animation:none}}
/* ⚠️ TWO OF JOSH'S BUGS WERE THIS ONE RULE (review 2026-09-04).
   --bg and --line are not defined anywhere in the app — only in the
   marketing pages — so both fell back to values written for a dark theme
   that no longer exists. The header painted itself #0d1420 while its text
   went on inheriting the light theme's dark ink, which is why the job
   value read as "blacked out" on every single job.
   And top:0 with z-index:40 are the topbar's OWN values, so this pinned
   itself over the app's chrome instead of under it: "it keeps staying up
   there and it makes it look weird."
   Tokens that exist, a top offset that clears the bar, and a layer below
   it. */
/* ⚠️ #main > * pins every child to position:relative (the brand wash's
   stacking rule, item 2), and an id beats a class — so this bar was never
   sticky and its top offset shoved it 68px down over the header. The
   selector carries the id so sticky actually wins. */
/* ⚠️ AND IT NEEDS AIR UNDER THE BAR. Stephen's photo, 2026-09-17: the row
   reading "No value yet · Josh" sat tucked into the header on the job
   screen. Two causes, both fixed: --topbar-h is now re-measured whenever the
   header changes shape (app.js), and this bar stops one notch BELOW it
   instead of trying to touch it, so a pixel of rounding never reads as an
   overlap. The padding is the same two pixels at the top, so nothing under
   it moves. */
/* ⚠️ NO LONGER PINNED. Josh, 2026-10-12: "this does not need to move as I
   scroll down." The bar (stage, owner) now scrolls away with the page; the
   class name stays so the split pane and the header observer keep working. */
#main > .job-sticky,
.job-sticky{position:static;
  background:var(--surface);padding:8px 0;margin-bottom:10px;
  border-bottom:1px solid var(--border)}
/* Josh, 2026-09-08: one compact bar stays pinned — number, name, stage,
   value, owner — and the Back button is gone. Everything else scrolls. */
.job-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-height:32px}
/* ⚠️ ONE COPY OF THE CUSTOMER AT A TIME. Josh, 2026-09-28: "Customer info
   needs to be fixed at the top and it's doubled up". While the full header is
   on screen the bar carries only what the header lacks (stage, owner); the
   number, name and value join it once the header has scrolled away. */
/* The bar's money and owner (Josh 2026-10-12, from AccuLynx): value over
   balance due over an A/R link, a ring for the share collected, then the
   owner, whose name opens a card with a pencil to hand the job on. */
.jb-money{display:flex;flex-direction:column;align-items:flex-start;line-height:1.25}
.jb-value{font-size:18px;font-weight:700}
/* The value is its own edit button: the number, and a pencil that is quiet
   until you reach for it. */
.jb-valbtn{all:unset;cursor:pointer;display:inline-flex;align-items:center;gap:6px;
  margin:-2px -6px;padding:2px 6px;border-radius:6px}
.jb-valbtn:hover,.jb-valbtn:focus-visible{background:var(--blue-light)}
.jb-pen{display:inline-flex;color:var(--slate-light)}
.jb-valbtn:hover .jb-pen,.jb-valbtn:focus-visible .jb-pen{color:var(--blue)}
.jb-due{font-size:13px;color:var(--green)}
.jb-due.owed{color:var(--red)}
/* Balance left on the job with nothing billed yet: neither paid (green)
   nor owed (red), just still to come. */
.jb-due.open{color:var(--slate)}
.jb-invoiced{font-size:12px;color:var(--red)}
/* The Invoices tab's contract line (Josh 2026-10-14): contract, invoiced,
   scheduled and paid in a row, and what is neither invoiced nor scheduled. */
.inv-recon{display:flex;flex-wrap:wrap;align-items:center;gap:6px 18px;margin:0 0 12px;
  padding:10px 12px;border-radius:var(--radius);border:1px solid var(--border);
  background:var(--canvas);font-size:13.5px}
.inv-recon b{font-weight:600;color:var(--slate);margin-right:4px}
.inv-recon.short{border-color:var(--amber);background:var(--amber-light)}
.inv-recon.over{border-color:var(--red);background:var(--red-light)}
.inv-recon .inv-gap{font-weight:600;color:var(--amber)}
.inv-recon.over .inv-gap{color:var(--red)}
.inv-recon .inv-even{color:var(--green);font-weight:600}
.jb-link{all:unset;cursor:pointer;font-size:12px;color:var(--blue);
  text-transform:uppercase;letter-spacing:.02em}
.jb-link:hover{text-decoration:underline}
.jb-ring{--ring:var(--red);width:52px;height:52px;border-radius:50%;flex:none;
  display:grid;place-items:center;
  background:conic-gradient(var(--ring) calc(var(--pct,0) * 1%), var(--border) 0)}
.jb-ring.part{--ring:var(--amber)}
.jb-ring.paid{--ring:var(--green)}
.jb-ring::before{content:"";grid-area:1/1;width:40px;height:40px;border-radius:50%;
  background:var(--surface)}
.jb-ring span{grid-area:1/1;position:relative;font-size:12.5px;font-weight:700}
.jb-owner{position:relative;padding-left:12px;border-left:1px solid var(--border)}
.jb-owner-btn{all:unset;cursor:pointer;display:flex;align-items:center;gap:8px;
  padding:4px 6px;border-radius:8px}
.jb-owner-btn:hover{background:var(--canvas)}
.jb-owner-name{color:var(--blue);font-size:15px;white-space:nowrap}
.jb-chev{display:inline-flex;color:var(--blue);transform:rotate(90deg);transition:transform .15s}
.jb-owner-btn[aria-expanded="true"] .jb-chev{transform:rotate(-90deg)}
.jb-owner-panel{position:absolute;right:0;top:calc(100% + 6px);z-index:40;width:290px;
  max-width:calc(100vw - 32px);background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius);box-shadow:var(--shadow);padding:14px 16px;font-size:14px;
  line-height:1.5}
.jb-owner-panel a{color:var(--blue);text-decoration:none}
.jb-owner-acts{display:flex;gap:18px;margin-top:10px}
.jb-owner-foot{position:relative;margin-top:12px;padding-top:12px;padding-right:36px;
  border-top:1px solid var(--border)}
.jb-owner-foot .ov-edit{position:absolute;right:0;bottom:0}
/* The job's quick links (Josh 2026-10-12): five tiles that each read as a
   link, not one solid bar. Label left, count right in the link blue. */
.jb-quick{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));
  gap:8px;margin-bottom:14px}
.jb-quick-cell{all:unset;box-sizing:border-box;cursor:pointer;display:flex;
  align-items:center;justify-content:space-between;gap:8px;padding:10px 12px;
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  font-size:13.5px;color:var(--ink);transition:border-color .12s,background .12s}
.jb-quick-cell:hover,.jb-quick-cell:focus-visible{border-color:var(--blue);background:var(--blue-light)}
.jb-quick-cell b{font-size:16px;color:var(--blue)}
.jb-quick-cell b.zero{color:var(--slate-light)}
/* The open tab: filled, so you can see where you are from across the room. */
.jb-quick-cell.on{border-color:var(--blue);background:var(--blue-light);font-weight:600}
.jb-quick-go{display:inline-flex;color:var(--slate-light)}
.jb-quick-cell.on .jb-quick-go,.jb-quick-cell:hover .jb-quick-go{color:var(--blue)}
.jb-quick{scroll-margin-top:calc(var(--topbar-h,49px) + 8px)}
/* Ten tiles on a phone: two across and shorter, so the page under them
   is still in reach of a thumb. */
@media (max-width: 640px) {
  .jb-quick{grid-template-columns:1fr 1fr;gap:6px}
  .jb-quick-cell{padding:8px 10px;font-size:13px}
}
/* ⚠️ ON A PHONE THE CARD OPENS IN PLACE. Josh, 2026-10-12: the dropdown was
   cut off on mobile. The bar wraps, the owner lands at the left edge, and a
   card hung from its right side ran off the screen. The owner takes its own
   row and the card opens full width under it, in the page's flow. */
@media (max-width: 640px) {
  .jb-owner{flex:1 0 100%;padding:8px 0 0;border-left:0;border-top:1px solid var(--border)}
  .jb-owner-btn{width:100%;box-sizing:border-box}
  .jb-chev{margin-left:auto}
  .jb-owner-panel{position:static;width:auto;max-width:none;margin-top:6px;box-shadow:none}
}
/* Sale approval (Josh 2026-10-12): the banner under the stage, the chips
   that say what is on file (red is missing), and the Approvals page tabs. */
.sale-banner{display:flex;flex-wrap:wrap;align-items:flex-start;gap:10px 16px;
  margin-top:12px;padding:10px 12px;border-radius:var(--radius);border:1px solid var(--border)}
.sale-banner.pending{background:var(--amber-light);border-color:var(--amber)}
.sale-banner.returned{background:var(--red-light);border-color:var(--red)}
.sale-banner.approved{background:var(--green-light);border-color:var(--green)}
.sale-banner-main{flex:1 1 320px;display:flex;flex-direction:column;gap:4px;font-size:13.5px}
.sale-banner-main b{display:inline-flex;align-items:center;gap:6px}
.sale-banner-acts{display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.sale-note{margin:2px 0;font-size:13px;color:var(--ink)}
.sale-facts{display:inline-flex;flex-wrap:wrap;gap:5px}
.sale-fact{font-size:12px;padding:2px 8px;border-radius:999px;border:1px solid var(--border);
  background:var(--surface);white-space:nowrap}
.sale-fact.bad{color:var(--red);border-color:var(--red);background:var(--red-light);font-weight:600}
.sale-fact.ok{color:var(--green)}
.sale-warn{display:flex;gap:6px;align-items:flex-start;margin:0 0 12px;font-size:13px;color:var(--red)}
.appr-tabs{display:flex;gap:8px;margin:0 0 14px;flex-wrap:wrap}
.appr-tab{all:unset;cursor:pointer;padding:8px 14px;border-radius:var(--radius);
  border:1px solid var(--border);background:var(--surface);font-size:14px}
.appr-tab b{margin-left:6px;color:var(--blue)}
.appr-tab.on{border-color:var(--blue);background:var(--blue-light);font-weight:600}
/* Unassigned leads (Josh 2026-10-14): the Manager overview's list and the
   reps' Leads up for grabs. One row per lead, the hand-off on the right. */
/* The Unassigned tile at the end of the bucket row: a bucket like the rest,
   amber while anything is waiting for an owner. */
.bucket-card.ul-tile.waiting{border-color:var(--amber);background:var(--amber-light)}
.bucket-card.ul-tile.waiting .bucket-n,.bucket-card.ul-tile.waiting .bucket-l{color:var(--amber)}
.ul-list{display:flex;flex-direction:column}
.ul-row{display:flex;flex-wrap:wrap;gap:8px 14px;align-items:center;padding:10px 0;
  border-top:1px solid var(--border)}
.ul-row:first-child{border-top:0}
.ul-main{flex:1 1 320px;display:flex;flex-wrap:wrap;gap:4px 8px;align-items:center;min-width:0}
.ul-name{font-weight:600;color:var(--blue);text-decoration:none}
.ul-sub{flex-basis:100%;font-size:12.5px;color:var(--slate)}
.ul-asked{flex-basis:100%;font-size:13px;color:var(--ink);font-style:italic}
.ul-acts{display:flex;gap:6px;align-items:center}
.ul-acts select{max-width:170px}
.job-sticky.head-in-view [data-bar-dup]{display:none}
.job-sticky.head-in-view{box-shadow:none}
.job-bar-name{font-size:16px;font-weight:600;letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:46vw}
.job-bar-value{font-size:15px;font-weight:600;white-space:nowrap}
.tab-count{display:inline-block;min-width:18px;padding:0 5px;margin-left:4px;
  border-radius:9px;font-size:11px;line-height:18px;text-align:center;
  background:var(--raise,rgba(128,128,128,.14));color:var(--slate);font-weight:600}
.tab.on .tab-count{background:var(--blue);color:#fff}
/* The tags hub: a panel of every message that tagged you. */
.tags-panel{min-width:340px;max-width:420px;max-height:70vh;overflow:auto;padding:0}
.tags-head{display:flex;align-items:center;gap:8px;padding:10px 12px;
  border-bottom:1px solid var(--border);font-size:13px}
.tags-row{display:flex;flex-direction:column;gap:2px;width:100%;text-align:left;
  padding:9px 12px;border:0;border-bottom:1px solid var(--border);
  background:none;color:var(--ink);font:inherit;cursor:pointer}
.tags-row:hover{background:var(--raise,rgba(128,128,128,.1))}
.tags-row.unread{box-shadow:inset 3px 0 0 var(--blue)}
.tags-row .tags-who{font-size:12.5px;font-weight:600}
.tags-row .tags-job{font-size:11.5px;color:var(--slate)}
.tags-row .tags-body{font-size:13px;line-height:1.35;color:var(--ink)}
.participants summary::-webkit-details-marker{display:none}
.participants summary{list-style:none}
@media (max-width:759px){
  .job-bar-name{max-width:60vw}
  .job-bar .grow{display:none}
}

/* ------------------------------------------------- the storm alert strip
   One line under the topbar, on every screen, until it is read or waved
   away. Amber because it is weather and money, not an error. */
.hail-strip { display: flex; align-items: stretch;
  background: var(--amber-light);
  border-bottom: 1px solid var(--amber); }
.hail-strip .hail-body { flex: 1; display: flex; align-items: center;
  gap: 8px; justify-content: center; padding: 9px 12px; border: 0;
  background: none; color: var(--ink); font: inherit; font-size: 13.5px;
  cursor: pointer; min-width: 0; flex-wrap: wrap; text-align: center; }
.hail-strip .hail-body b { color: var(--amber); }
.hail-strip .hail-x { border: 0; background: none; color: var(--slate);
  font-size: 20px; line-height: 1; padding: 0 14px; cursor: pointer; }
.hail-strip .hail-x:hover { color: var(--ink); }

/* ------------------------------------------------------------ stickies
   Stephen, 2026-09-06: "Make the note look like a fun sticky note."
   Real paper, then: a square-ish leaf, a faint grain, a shadow that sits
   under one corner rather than evenly all round (paper curls), and a
   couple of degrees of rotation so a wall of them looks stuck up rather
   than laid out on a grid. */
#stickyLayer { position: fixed; inset: 0; pointer-events: none; z-index: 900; }
.sticky {
  position: absolute; width: 232px; pointer-events: auto;
  display: flex; flex-direction: column;
  border-radius: 2px 2px 3px 3px;
  /* ⚠️ The shadow is OFFSET and tight. An even blur on all four sides
     reads as a floating card; paper touches the surface on one edge. */
  box-shadow: 0 1px 1px rgba(20,24,28,.14), 6px 10px 18px -8px rgba(20,24,28,.34);
  transform: rotate(var(--tilt, -1.1deg));
  transition: transform .12s ease, box-shadow .12s ease;
  color: #2a2a22;
}
.sticky:nth-of-type(2n) { --tilt: 1.4deg; }
.sticky:nth-of-type(3n) { --tilt: -2.1deg; }
.sticky:nth-of-type(5n) { --tilt: .7deg; }
.sticky.dragging {
  transform: rotate(0deg) scale(1.02);
  box-shadow: 0 4px 6px rgba(20,24,28,.16), 16px 26px 40px -14px rgba(20,24,28,.45);
  z-index: 20;
  transition: none;                 /* the finger sets the position, not an ease */
}
/* ⚠️ A LIFT, NOT A JUMP. Two pixels and a deeper shadow reads as paper
   coming off the desk under your hand; anything more and it is a card in a
   game. The tilt straightens slightly, the way a note does when you touch
   it to read it. */
.sticky:hover { transform: rotate(calc(var(--tilt, -1.1deg) * .4)) translateY(-2px); }
.sticky:hover:not(.dragging) {
  box-shadow: 0 2px 3px rgba(20,24,28,.13), 10px 16px 26px -10px rgba(20,24,28,.4);
}
/* Stuck to the wall: a short settle, once, when a note first appears. */
@keyframes stickyLand {
  0%   { transform: rotate(0deg) scale(.86); opacity: 0; }
  55%  { transform: rotate(calc(var(--tilt, -1.1deg) * 1.8)) scale(1.03); opacity: 1; }
  100% { transform: rotate(var(--tilt, -1.1deg)) scale(1); opacity: 1; }
}
.sticky.landing { animation: stickyLand .34s cubic-bezier(.2,.9,.3,1.2); }
@media (prefers-reduced-motion: reduce) {
  .sticky, .sticky.landing { animation: none; transition: none; }
  .sticky:hover { transform: rotate(var(--tilt, -1.1deg)); }
}
.sticky:focus-within { z-index: 15; }
/* The five papers. Warm, low-saturation — a screen-bright yellow is a
   highlighter, not a sticky note. */
.sticky-butter { background: #fdf0a8; }
.sticky-mint   { background: #cdf0cf; }
.sticky-sky    { background: #cfe6fa; }
.sticky-rose   { background: #fbd3d8; }
.sticky-lilac  { background: #e2d7f7; }

.sticky-top {
  display: flex; align-items: center; gap: 6px; padding: 6px 6px 2px;
  cursor: grab; touch-action: none;
}
.sticky.dragging .sticky-top { cursor: grabbing; }
.sticky-colors { display: flex; gap: 4px; }
.sticky-swatch {
  width: 11px; height: 11px; border-radius: 50%; cursor: pointer;
  border: 1px solid rgba(0,0,0,.16); padding: 0;
}
.sticky-swatch.on { box-shadow: 0 0 0 2px rgba(0,0,0,.34); }
.sticky-x {
  margin-left: auto; border: 0; background: none; cursor: pointer;
  font-size: 19px; line-height: 1; color: rgba(0,0,0,.38); padding: 0 3px;
}
.sticky-x:hover { color: rgba(0,0,0,.72); }

.sticky-body {
  border: 0; background: none; resize: none; outline: none;
  min-height: 132px; padding: 2px 12px 6px; color: inherit;
  /* A hand on paper. Caveat rides the same @import as the app's other
     faces (added for this); the stack falls back through the system's own
     handwriting before it reaches anything that would read as a form
     field — ⚠️ and it must, because a blocked font request would
     otherwise leave a sticky note set in the UI face and looking like a
     textarea. */
  font-family: 'Caveat', 'Bradley Hand', 'Segoe Print', cursive;
  font-size: 20px; line-height: 1.32;
}
.sticky-body::placeholder { color: rgba(0,0,0,.3); }

.sticky-foot {
  display: flex; align-items: center; gap: 6px; padding: 0 8px 8px;
  opacity: 0; transition: opacity .12s ease;
}
/* ⚠️ THE FOOT MUST NOT BE HOVER-ONLY ON A TOUCH SCREEN — that is the
   "control exists, cannot be reached" bug this codebase keeps finding.
   Hover reveals it on a mouse; a coarse pointer always sees it. */
.sticky:hover .sticky-foot, .sticky:focus-within .sticky-foot { opacity: 1; }
@media (hover: none) { .sticky-foot { opacity: 1; } }
.sticky-act {
  display: inline-flex; align-items: center; gap: 4px;
  border: 0; background: rgba(0,0,0,.07); cursor: pointer;
  border-radius: 5px; padding: 3px 8px; font: inherit; font-size: 12px;
  font-family: var(--body); color: rgba(0,0,0,.7);
}
.sticky-act:hover { background: rgba(0,0,0,.13); }
.sticky-act.danger { padding: 3px 7px; }
.sticky-act.danger:hover { background: rgba(190,42,58,.18); color: #7d1526; }
.sticky-act.danger svg { display: block; }
.sticky-quote {
  font-family: 'Caveat', 'Bradley Hand', cursive; font-size: 19px;
  background: #fdf0a8; color: #2a2a22; padding: 10px 12px;
  border-radius: 2px; margin: 0 0 14px; transform: rotate(-.6deg);
  box-shadow: 4px 6px 12px -6px rgba(20,24,28,.34);
}
.sticky-why {
  display: block; font-size: 11.5px; color: var(--muted); margin-top: 2px;
}

/* The sticky button is a split: the wide half writes a note, the caret
   opens the drawer. Both visible — a drawer behind a right click is a
   drawer with no handle. */
.splitbtn { display: inline-flex; }
.splitbtn > .btn:first-child { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.splitbtn-caret {
  border-top-left-radius: 0; border-bottom-left-radius: 0;
  border-left: 0; padding-left: 5px; padding-right: 6px;
}
.sticky-badge {
  margin-left: 5px; font-size: 11px; font-variant-numeric: tabular-nums;
  color: var(--muted);
}
/* The note's tool row: date, pin, mic, tidy. Same reveal rules as the
   footer — hover on a mouse, always on a coarse pointer. */
.sticky-tools {
  display: flex; align-items: center; gap: 5px; padding: 0 8px 4px;
  opacity: 0; transition: opacity .12s ease;
}
.sticky:hover .sticky-tools, .sticky:focus-within .sticky-tools { opacity: 1; }
@media (hover: none) { .sticky-tools { opacity: 1; } }
.sticky-date {
  border: 0; background: rgba(0,0,0,.07); border-radius: 5px;
  font: inherit; font-family: var(--body); font-size: 11px;
  padding: 2px 4px; color: rgba(0,0,0,.7); max-width: 118px;
}
.sticky-tool {
  border: 0; background: rgba(0,0,0,.07); border-radius: 5px; cursor: pointer;
  padding: 3px 6px; display: inline-flex; align-items: center;
  color: rgba(0,0,0,.62);
}
.sticky-tool:hover { background: rgba(0,0,0,.14); }
.sticky-tool.on { background: rgba(0,0,0,.2); color: rgba(0,0,0,.85); }

/* Keyboard shortcut keys in the estimator's cheat sheet. */
kbd {
  display: inline-block; min-width: 20px; text-align: center;
  padding: 2px 6px; margin-right: 2px;
  border: 1px solid var(--line); border-bottom-width: 2px;
  border-radius: 5px; background: var(--raise);
  font-family: var(--code); font-size: 11.5px; line-height: 1.5;
}

/* ⚠️ A STICKY ON A PHONE IS A SHEET, NOT A FLOATER. The desktop note is
   232px of draggable paper pinned by percentage; on a 375px screen that
   lands it across the tab bar and under the + button, with File it and the
   bin covered — Stephen's screenshot, 2026-09-07. Below 760px the layer
   becomes a column docked above the tab bar: full width, no tilt, no drag,
   newest at the bottom, scrolls when there are several. The + button steps
   aside while a note is out. */
@media (max-width: 760px) {
  #stickyLayer {
    position: fixed;
    inset: auto 10px calc(96px + env(safe-area-inset-bottom, 0px)) 10px;
    display: flex; flex-direction: column; gap: 10px;
    max-height: calc(100vh - 110px - var(--topbar-h) - env(safe-area-inset-bottom, 0px));
    overflow-y: auto; -webkit-overflow-scrolling: touch;
  }
  #stickyLayer .sticky {
    position: static; width: auto; flex: 0 0 auto;
    transform: none; border-radius: 6px;
  }
  #stickyLayer .sticky:hover, #stickyLayer .sticky.landing { transform: none; }
  #stickyLayer .sticky-body { min-height: 88px; }
  #stickyLayer .sticky-top { cursor: default; }
  body.sticky-open .fab { display: none; }
  /* Advance job on its own full width line, words centred, so the floating
     + at the right edge never covers them (phone walk, 2026-11-06). */
  .flow-now [data-flow] { flex: 1 1 100%; justify-content: center; }
}

/* estimator: optional-upgrade toggles on a line */
.opt-tog{display:inline-flex;align-items:center;gap:4px;font-size:11px;color:var(--muted,#8a94a6);margin:2px 8px 0 0;cursor:pointer;white-space:nowrap}
.opt-tog input{width:13px;height:13px;margin:0}
.struct-pick{display:inline-block;width:auto;font-size:11px;padding:1px 4px;margin:2px 0 0;height:auto;line-height:1.3}

/* texts: photos in the thread and the picker under the reply box */
.txt-shot{max-width:220px;max-height:220px;border-radius:10px;display:block;margin:0 0 6px}
.txt-picker{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px;padding:8px;border:1px dashed var(--line);border-radius:10px}
.txt-picker img{width:64px;height:64px;object-fit:cover;border-radius:8px;cursor:pointer;border:2px solid transparent}
.txt-picker img.on{border-color:var(--accent,#1f49e0)}
.txt-pick{position:relative;display:inline-block}
.txt-pick img{width:44px;height:44px;object-fit:cover;border-radius:8px;display:block}
.txt-pick b{position:absolute;top:-6px;right:-6px;background:#fff;border:1px solid var(--line);border-radius:50%;width:18px;height:18px;font-size:12px;line-height:16px;text-align:center;cursor:pointer}

/* Gap thirty-three: photo selection and the hidden-from-customer mark. */
.file-tile.picked { outline: 3px solid var(--accent, #2B6CB0); outline-offset: -3px; border-radius: 10px; }
.file-tile.tile-hidden img { opacity: .55; }
.tile-hiddenmark { position: absolute; top: 6px; left: 6px; background: rgba(20,24,32,.8); color: #fff; font-size: 10.5px; padding: 2px 6px; border-radius: 999px; }

/* Gap thirty-four: talk while shooting. */
.walk-stage { background: #000; border-radius: 12px; overflow: hidden; }
.walk-stage video { display: block; width: 100%; max-height: 52vh; object-fit: cover; transition: opacity .12s; }
.walk-stage video.flash { opacity: .25; }
.walk-words { min-height: 44px; margin: 10px 0 0; padding: 8px 10px; font-size: 13.5px; color: var(--muted); border: 1px dashed var(--border); border-radius: 10px; }
.walk-shutter { width: 68px; height: 68px; border-radius: 50%; border: 4px solid #fff; background: var(--blue); box-shadow: 0 0 0 3px var(--blue); cursor: pointer; }
.walk-shutter:active { transform: scale(.94); }
.walk-shutter:disabled { opacity: .4; cursor: default; }

/* ---- Demo mode + the guided tour (2026-09-12) ---- */
.demo-pill { background: linear-gradient(135deg, var(--blue), #7c3aed); color: #fff; border-color: transparent; }
.demo-pill:hover { filter: brightness(1.08); }
/* On a phone the pill is its star alone: the word pushed the top bar past
   the screen edge. */
@media (max-width: 600px) { .demo-pill .btn-label { display: none; } }
.demo-scene { display: flex; gap: 12px; padding: 10px 0; border-top: 1px solid var(--border); align-items: flex-start; }
.demo-scene:first-of-type { border-top: 0; }
.demo-scene .n { width: 26px; height: 26px; border-radius: 50%; background: var(--brand-wash, #eef3fb); color: var(--blue);
                 font-weight: 700; font-size: 12.5px; display: flex; align-items: center; justify-content: center; flex: none; }
.demo-scene b { display: block; font-size: 13.5px; }
.demo-scene span { font-size: 12.5px; color: var(--muted); }
/* ---- The demo story (2026-09-21): the card, the stages, the finale ----
   The card sits under every modal (100) and Ask the Stack (110) so the real
   app's own dialogs still work; the stages sit under the card. */
/* The quick-add button sits where the story card and the finale's buttons
   are; the story is the thing to press while it runs. */
body.in-story .fab { display: none; }
.story-dock { position: fixed; right: 16px; bottom: 16px; z-index: 90; width: min(400px, calc(100vw - 32px));
  max-height: calc(100vh - 90px); display: flex; flex-direction: column; background: var(--surface, #fff); color: var(--ink);
  border: 1px solid var(--border); border-radius: 16px; box-shadow: 0 22px 60px rgba(10, 16, 28, .28);
  animation: storyIn .28s cubic-bezier(.2, .8, .2, 1); }
@keyframes storyIn { from { opacity: 0; transform: translateY(10px) } to { opacity: 1; transform: none } }
.story-dock[hidden] { display: none; }
.story-dock.pill { width: auto; padding: 6px; border-radius: 999px; }
.story-dock .sd-top { padding: 12px 16px 0; }
.story-dock .sd-chapters { display: flex; gap: 10px; font-size: 10.5px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--slate); flex-wrap: wrap; }
.story-dock .sd-chapters span.on { color: var(--blue); }
.story-dock .sd-bar { height: 3px; background: var(--border); border-radius: 3px; margin-top: 8px; overflow: hidden; }
.story-dock .sd-bar i { display: block; height: 100%; background: var(--blue); transition: width .35s ease; }
.story-dock .sd-body { padding: 12px 16px 4px; overflow: auto; }
.story-dock .sd-k { font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--blue); }
.story-dock h3 { margin: 4px 0 6px; font-size: 19px; line-height: 1.25; }
.story-dock .sd-line { margin: 0 0 10px; font-size: 13.5px; line-height: 1.5; color: var(--slate); }
.story-dock .sd-facts { list-style: none; margin: 0 0 10px; padding: 0; display: grid; gap: 7px; }
.story-dock .sd-facts li { display: flex; gap: 8px; font-size: 13px; line-height: 1.45; animation: storyIn .3s ease both; }
.story-dock .sd-facts li svg { flex: none; margin-top: 3px; color: var(--green, #2f855a); }
.story-dock .sd-outbox { border: 1px dashed var(--border); border-radius: 10px; padding: 8px 10px; margin: 0 0 10px; display: grid; gap: 6px; }
.story-dock .sd-ob-h { font-size: 11.5px; font-weight: 650; color: var(--slate); display: flex; gap: 6px; align-items: center; }
.story-dock .sd-ob { font-size: 12.5px; line-height: 1.4; }
.story-dock .sd-ob span { display: block; color: var(--slate); }
.story-dock .sd-ob em { display: block; font-style: normal; font-size: 11.5px; color: var(--amber, #b7791f); }
.story-dock .sd-foot { display: flex; align-items: center; gap: 6px; padding: 10px 12px 12px; border-top: 1px solid var(--border); }
.story-dock .sd-count { font-size: 11.5px; color: var(--slate); margin-left: auto; white-space: nowrap; }
.story-dock .sd-go { white-space: nowrap; }
.story-dock .sd-hint { font-size: 11px; color: var(--slate); padding: 0 16px 10px; }
.story-dock.compact .sd-body { padding-bottom: 0; }
.story-dock .sd-form { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 0 0 10px; }
.story-dock .sd-form label { display: grid; gap: 3px; font-size: 11.5px; color: var(--slate); }
.story-dock .sd-form .wide { grid-column: 1 / -1; }
.story-dock .sd-form input:not([type="checkbox"]) { font: inherit; font-size: 14px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); color: var(--ink); width: 100%; box-sizing: border-box; }
.story-dock .sd-check { display: flex !important; align-items: center; gap: 8px; }
.story-glow { outline: 3px solid var(--blue); outline-offset: 4px; border-radius: 12px; animation: storyGlow 1.6s ease 2; }
@keyframes storyGlow { 50% { outline-color: transparent; } }

.story-stage { position: fixed; inset: 0; z-index: 88; display: flex; align-items: center; justify-content: center; }
/* The way out, on every step (2026-09-22): the story never traps anyone. */
.story-dock .sd-top { position: relative; padding-right: 44px; }
.story-dock .sd-x { position: absolute; top: 6px; right: 6px; width: 32px; height: 32px; padding: 0; justify-content: center; }
.story-dock.pill { display: flex; flex-direction: row; align-items: center; gap: 4px; }
.story-dock.pill .sd-x { position: static; }
.story-x { position: absolute; top: 14px; right: 14px; z-index: 2; display: inline-flex; align-items: center; gap: 6px;
  min-height: 40px; padding: 0 14px; border-radius: 999px; font: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer;
  border: 1px solid rgba(255,255,255,.3); background: rgba(255,255,255,.1); color: #fff; }
.story-x:hover { background: rgba(255,255,255,.18); }
.story-x:focus-visible, .story-dock .sd-x:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }
.story-stage.brand .story-x:focus-visible { outline-color: #fff; }
.story-stage.finale .story-x { position: fixed; border-color: var(--border); background: var(--surface, #fff); color: var(--ink); }
.story-stage.finale .story-x:hover { background: var(--hover, rgba(0,0,0,.04)); }
.ss-card { position: relative; }
.ss-card .btn.ss-x { position: absolute; top: 8px; right: 8px; width: 32px; height: 32px; padding: 0; justify-content: center; margin: 0; }
/* The header logo's ".brand:hover" fade also matched this stage, so a mouse
   resting on the website question let the app show through. */
.story-stage.brand:hover { opacity: 1; }
@media (max-width: 760px) {
  .story-x { top: 10px; right: 10px; padding: 0 12px; font-size: 13px; }
  body .story-stage.brand { padding-top: 64px; }
}
.story-stage.brand { background: radial-gradient(1200px 600px at 50% 0%, #26344d 0%, #0f1622 70%); color: #fff; padding: 16px; box-sizing: border-box; }
.story-stage.brand.reading .sb-card { opacity: 0; }
.sb-card { width: min(560px, 100%); text-align: center; transition: opacity .3s ease; }
.sb-eyebrow { font-size: 12px; letter-spacing: .14em; text-transform: uppercase; opacity: .7; margin: 0 0 14px; }
.sb-card h1 { font-size: clamp(28px, 6vw, 44px); line-height: 1.1; margin: 0 0 12px; letter-spacing: -.01em; }
.sb-sub { font-size: 15px; opacity: .8; margin: 0 0 22px; line-height: 1.5; }
.sb-note { font-size: 13.5px; background: rgba(255,255,255,.08); border-radius: 10px; padding: 10px 12px; margin: 0 0 16px; }
.sb-row { display: flex; gap: 8px; justify-content: center; }
.sb-row input { flex: 1; min-width: 0; font: inherit; font-size: 18px; padding: 14px 16px; border-radius: 12px; border: 1px solid rgba(255,255,255,.25); background: rgba(255,255,255,.96); color: #111; }
.sb-row .btn { font-size: 16px; padding: 0 22px; }
.sb-alt { margin: 16px 0 0; font-size: 13px; }
.sb-alt a { color: #fff; opacity: .75; }
.sb-swatches { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin: 0 0 18px; }
.sb-swatches button, .sb-custom { width: 38px; height: 38px; border-radius: 50%; border: 2px solid rgba(255,255,255,.35); cursor: pointer; padding: 0; }
.sb-swatches button.on { border-color: #fff; box-shadow: 0 0 0 3px rgba(255,255,255,.35); }
.sb-custom { display: inline-flex; overflow: hidden; background: conic-gradient(#e53e3e, #d69e2e, #38a169, #3182ce, #805ad5, #e53e3e); }
.sb-custom input { opacity: 0; width: 100%; height: 100%; cursor: pointer; }
.sb-field { display: grid; gap: 4px; text-align: left; font-size: 12px; opacity: .9; margin: 0 0 12px; }
.sb-field input { font: inherit; font-size: 15px; padding: 10px 12px; border-radius: 10px; border: 1px solid rgba(255,255,255,.25); background: rgba(255,255,255,.96); color: #111; }

.story-stage.phone { background: rgba(12, 18, 28, .55); backdrop-filter: blur(3px); justify-content: flex-start; padding-left: max(24px, calc(50vw - 420px)); gap: 24px; }
.sp-frame { position: relative; width: 390px; height: min(800px, calc(100vh - 48px)); border-radius: 44px; background: #0b0f16; padding: 14px; box-sizing: border-box; box-shadow: 0 30px 80px rgba(0,0,0,.45); flex: none; }
.sp-notch { position: absolute; top: 14px; left: 50%; transform: translateX(-50%); width: 110px; height: 22px; background: #0b0f16; border-radius: 0 0 14px 14px; z-index: 2; }
.sp-frame iframe, .sf-screen { width: 100%; height: 100%; border: 0; border-radius: 32px; background: #fff; display: block; }
.sf-screen { overflow: auto; color: #1a2333; padding: 38px 18px 18px; box-sizing: border-box; }
.sf-head { display: flex; align-items: center; gap: 10px; font-size: 15px; margin: 0 0 14px; }
.sf-head img { max-height: 30px; max-width: 120px; }
.sf-mark { width: 32px; height: 32px; border-radius: 9px; background: var(--blue); color: var(--on-accent, #fff); display: inline-flex; align-items: center; justify-content: center; font-weight: 800; font-size: 13px; }
.sf-tabs { display: flex; gap: 6px; margin: 0 0 16px; }
.sf-tabs button { flex: 1; font: inherit; font-size: 12.5px; padding: 8px 4px; border-radius: 9px; border: 1px solid #e3e5e1; background: #fff; color: #1a2333; cursor: pointer; }
.sf-tabs button.on { background: var(--blue); color: var(--on-accent, #fff); border-color: transparent; }
.sf-big { font-size: 44px; font-weight: 750; margin: 6px 0 0; color: var(--blue); }
.sf-cap { margin: 0 0 12px; font-size: 13.5px; color: #5a6472; }
.sf-note { font-size: 14px; line-height: 1.5; margin: 14px 0 0; }
.sf-open { color: #fff; max-width: 260px; display: grid; gap: 8px; font-size: 13px; }
.sf-open .btn { justify-self: start; }

.story-stage.sold { z-index: 95; background: rgba(12, 18, 28, .45); backdrop-filter: blur(2px); animation: storyIn .25s ease; }
.ss-card { background: var(--surface, #fff); color: var(--ink); border-radius: 20px; padding: 28px 32px 24px; text-align: center; width: min(420px, calc(100vw - 32px)); box-sizing: border-box; box-shadow: 0 30px 80px rgba(0,0,0,.35); }
.ss-ring { width: 88px; height: 88px; }
.ss-ring circle { fill: none; stroke: var(--blue); stroke-width: 5; stroke-dasharray: 340; stroke-dashoffset: 340; animation: ssDraw .7s ease forwards; }
.ss-ring path { fill: none; stroke: var(--blue); stroke-width: 7; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 80; stroke-dashoffset: 80; animation: ssDraw .45s .55s ease forwards; }
@keyframes ssDraw { to { stroke-dashoffset: 0; } }
.ss-k { font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--blue); margin: 10px 0 2px; }
.ss-v { font-size: 40px; font-weight: 750; margin: 0; letter-spacing: -.01em; }
.ss-s { font-size: 13.5px; color: var(--slate); margin: 6px 0 0; line-height: 1.45; }
.ss-card .btn { margin-top: 18px; }

.story-stage.finale { z-index: 92; background: var(--surface, #fff); color: var(--ink); overflow: auto; align-items: flex-start; padding: 40px 16px; box-sizing: border-box; }
.sfin { width: min(720px, 100%); margin: 0 auto; text-align: center; }
.sfin-mark img { max-height: 64px; max-width: 220px; }
.sfin-mark span { width: 64px; height: 64px; border-radius: 16px; background: var(--blue); color: var(--on-accent, #fff); display: inline-flex; align-items: center; justify-content: center; font-weight: 800; font-size: 22px; }
.sfin-k { font-size: 13px; color: var(--slate); margin: 10px 0 4px; }
.sfin h1 { font-size: clamp(26px, 5vw, 38px); line-height: 1.15; margin: 0 0 20px; }
.sfin-list { list-style: none; padding: 0; margin: 0 auto 26px; display: grid; grid-template-columns: 1fr 1fr; gap: 8px 18px; text-align: left; max-width: 640px; }
.sfin-list li { display: flex; gap: 8px; font-size: 14px; line-height: 1.4; }
.sfin-list li svg { flex: none; color: var(--blue); margin-top: 2px; }
.sfin-bands { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; margin: 0 0 10px; }
.sfin-band { border: 1px solid var(--border); border-radius: 12px; padding: 12px; display: grid; gap: 4px; }
.sfin-band b { font-size: 13px; }
.sfin-band span { font-size: 22px; font-weight: 700; }
.sfin-band small { font-size: 12px; color: var(--slate); font-weight: 500; }
.sfin-note { font-size: 13px; color: var(--slate); margin: 0 0 18px; }
.sfin-cta { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.sfin-cta .btn.primary { font-size: 16px; padding: 12px 26px; }
.sfin-back { font-size: 12.5px; margin-top: 18px; }

@media (max-width: 760px) {
  .story-dock { left: 0; right: 0; bottom: 0; width: auto; border-radius: 16px 16px 0 0; max-height: 52vh; }
  .story-dock.pill { left: auto; right: 12px; bottom: 12px; border-radius: 999px; }
  .story-dock .sd-form { grid-template-columns: 1fr; }
  .story-dock h3 { font-size: 17px; }
  .story-stage.phone { padding: 8px 8px 0; align-items: flex-start; justify-content: center; }
  .story-stage.phone .sp-frame { width: 100%; height: 46vh; border-radius: 18px; padding: 6px; }
  .story-stage.phone .sp-notch { display: none; }
  .story-stage.phone .sp-frame iframe, .story-stage.phone .sf-screen { border-radius: 13px; }
  .sf-screen { padding-top: 16px; }
  .sf-open { display: none; }
  .story-stage.phone.field .sf-open { display: grid; position: absolute; top: calc(46vh + 16px); left: 16px; right: 16px; max-width: none; }
  .sfin-list { grid-template-columns: 1fr; }
  .sb-row { flex-direction: column; }
  .sb-row .btn { padding: 12px; justify-content: center; }
}

/* ---- Where everyone is: the dispatch team map (2026-09-12) ---- */
.team-map { height: 380px; border-radius: 10px; overflow: hidden; background: var(--surface-2, #eef1f5); }
[data-basemaps] .seg-opt { padding: 4px 10px; font-size: 12px; }
@media (max-width: 760px) { .team-map { height: 260px; } }
.team-legend { display: flex; gap: 16px; flex-wrap: wrap; font-size: 12px; color: var(--muted); margin-top: 8px; align-items: center; }
.team-legend .tm-k { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 5px; vertical-align: -1px; }
.team-legend .tm-k.rep { background: var(--blue); } .team-legend .tm-k.stop { background: #f59e0b; } .team-legend .tm-k.knock { background: #7c3aed; }
/* The compass pin: face puck, a cone of light on the heading, arrow on the rim. */
.tm-cp { width: 120px; height: 120px; position: relative; }
.tm-cp .tm-cp-cone { position: absolute; inset: 0; border-radius: 50%; background: conic-gradient(from -28deg, var(--b200, rgba(43,108,176,.28)) 0 56deg, transparent 56deg); opacity: .75; transition: transform .6s ease; }
.tm-cp .tm-cp-puck { position: absolute; left: 35px; top: 35px; width: 50px; height: 50px; border-radius: 50%; background: var(--blue); border: 3px solid #fff; box-sizing: border-box;
                     display: flex; align-items: center; justify-content: center; overflow: hidden; box-shadow: 0 3px 8px rgba(0,0,0,.4); }
.tm-cp .tm-cp-puck img { width: 100% !important; height: 100% !important; object-fit: cover; display: block; }
.tm-cp .tm-cp-puck b { color: #fff; font-size: 17px; font-weight: 800; letter-spacing: .02em; }
.tm-cp .tm-cp-puck .tm-cp-emoji { font-size: 26px; line-height: 1; font-weight: 400; background: #fff; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; }
.tm-cp .tm-cp-arrow { position: absolute; left: 53px; top: 21px; width: 14px; height: 14px; color: var(--blue); transform-origin: 7px 39px; transition: transform .6s ease; filter: drop-shadow(0 1px 1px rgba(0,0,0,.4)); }
.tm-cp .tm-cp-arrow svg { width: 14px; height: 14px; display: block; }
.tm-cp .tm-cp-name { position: absolute; left: 50%; top: 88px; transform: translateX(-50%); font-size: 12px; font-weight: 800; color: #111827;
                     background: #fff; padding: 2px 8px; border-radius: 10px; white-space: nowrap; box-shadow: 0 1px 3px rgba(0,0,0,.25); }
.tm-cp.knock .tm-cp-puck { background: #7c3aed; }
.tm-cp.knock .tm-cp-cone { background: conic-gradient(from -28deg, rgba(124,58,237,.28) 0 56deg, transparent 56deg); }
.tm-cp.knock .tm-cp-arrow { color: #7c3aed; }
.tm-cp.stale .tm-cp-puck { background: #9aa3b2; }
.tm-cp.stale .tm-cp-puck img { filter: grayscale(1); opacity: .85; }
.tm-cp.stale .tm-cp-name { color: #6b7280; }
.tm-cp.moving .tm-cp-cone { animation: tmCone 1.6s ease-in-out infinite; }
@keyframes tmCone { 0%, 100% { opacity: .75 } 50% { opacity: 1 } }
@media (prefers-reduced-motion: reduce) { .tm-cp.moving .tm-cp-cone { animation: none; } }
.tm-stop span { display: block; width: 12px; height: 12px; border-radius: 50%; background: #f59e0b; border: 2px solid #fff; box-shadow: 0 1px 4px rgba(0,0,0,.35); }
.tm-stop.done span { background: #22c55e; }
.tm-office { width: 56px; height: 74px; position: relative; filter: drop-shadow(0 3px 4px rgba(0,0,0,.35)); }
/* A wordmark is wide: the tile grows sideways to fit it whole, centered on the spot. */
.tm-office .tm-office-tile { position: absolute; left: 50%; top: 0; transform: translateX(-50%); min-width: 48px; max-width: 120px; height: 48px; padding: 4px 7px;
                             border-radius: 12px; background: #fff; border: 3px solid #fff; display: flex; align-items: center; justify-content: center; box-sizing: border-box; }
.tm-office .tm-office-tile::after { content: ''; position: absolute; left: 50%; bottom: -9px; width: 12px; height: 12px; background: #fff; transform: translateX(-50%) rotate(45deg); }
/* Leaflet puts max-width/max-height: none !important on every marker image; an explicit height is what it cannot override. */
.leaflet-marker-pane .tm-office .tm-office-tile img { height: 34px !important; width: auto !important; max-width: none; object-fit: contain; display: block; }
.tm-office .tm-office-tile b { color: var(--blue); font-size: 17px; font-weight: 800; }
.tm-office .tm-office-name { position: absolute; left: 50%; top: 54px; transform: translateX(-50%); font-size: 11.5px; font-weight: 700; color: #111827;
                             background: #fff; padding: 2px 8px; border-radius: 10px; white-space: nowrap; box-shadow: 0 1px 3px rgba(0,0,0,.25); }

/* ---- The feel: company-wide look dials (2026-09-12) ---- */
:root.look-toned:not([data-theme="dark"]) { --canvas: var(--canvas-look); --border: var(--border-look); }
@media (prefers-color-scheme: dark) { :root.look-toned:not([data-theme="light"]) { --canvas: initial; } }
:root.look-compact { font-size: 93%; }
:root.look-compact .card { padding-top: 10px; padding-bottom: 10px; }
:root.look-compact .page-head { margin-bottom: 8px; }
.look-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; margin-top: 10px; }
.look-tile { text-align: left; border: 1px solid var(--border); background: var(--surface); border-radius: var(--radius); padding: 10px 12px; cursor: pointer; font: inherit; color: inherit; }
.look-tile.on { border-color: var(--blue); box-shadow: 0 0 0 2px var(--b100); }
.look-tile .sw { display: flex; gap: 4px; margin-bottom: 8px; }
.look-tile .sw i { display: block; width: 22px; height: 14px; border: 1px solid var(--border); }
.look-tile b { display: block; font-size: 13px; }
.look-tile span { font-size: 11.5px; color: var(--muted); line-height: 1.35; }
.look-row { display: flex; gap: 14px; flex-wrap: wrap; align-items: center; margin-top: 12px; }
.look-row .lbl { font-size: 13px; font-weight: 500; min-width: 64px; }

/* ---- Dispatch as mission control (2026-09-12) ---- */
.dsp-head { display: flex; align-items: flex-end; gap: 14px; flex-wrap: wrap; margin-bottom: 12px; }
.dsp-meter { min-width: 260px; flex: 1 1 320px; }
.dsp-meter .card { margin: 0; padding: 6px 12px; display: flex; align-items: center; gap: 10px 14px; flex-wrap: wrap; }
.dsp-meter .card > * { margin: 0; }
.dsp-urgent { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center; padding: 8px 12px; margin-bottom: 12px; border-radius: 10px;
              background: color-mix(in srgb, var(--red) 10%, var(--surface)); border: 1px solid color-mix(in srgb, var(--red) 40%, transparent); font-size: 13px; }
.dsp-urgent > b { color: var(--red); display: inline-flex; align-items: center; gap: 6px; }
.dsp-urgent-row { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.dsp-main { display: grid; grid-template-columns: 320px minmax(0, 1fr); gap: 0; border: 1px solid var(--border); border-radius: 14px; overflow: hidden; background: var(--surface); margin-bottom: 14px;
            height: clamp(460px, calc(100vh - var(--topbar-h) - 180px), 820px); }
@media (max-width: 860px) { .dsp-main { grid-template-columns: 1fr; grid-template-rows: minmax(0, 1fr) 190px; height: auto; min-height: 640px; } }
.dsp-rail { display: flex; flex-direction: column; min-height: 0; border-right: 1px solid var(--border); background: var(--surface); }
@media (max-width: 860px) { .dsp-rail { order: 2; border-right: 0; border-top: 1px solid var(--border); } }
.dsp-rail-head { display: flex; align-items: center; gap: 8px; padding: 12px 14px; border-bottom: 1px solid var(--border); font-size: 13.5px; }
.dsp-rail-head .dim { font-size: 12px; margin-right: auto; }
.dsp-rail-rows { overflow: auto; min-height: 0; }
@media (max-width: 860px) { .dsp-rail-rows { display: flex; overflow-x: auto; } .dsp-person { min-width: 240px; border-right: 1px solid var(--border); } }
.dsp-person { display: grid; grid-template-columns: 40px 1fr; grid-template-areas: "face who" "face state" "face next" "face bar"; column-gap: 10px; row-gap: 2px;
              width: 100%; text-align: left; padding: 10px 14px; border: 0; border-bottom: 1px solid var(--border); background: transparent; color: inherit; font: inherit; cursor: pointer; }
.dsp-person:hover { background: var(--brand-wash, rgba(43,108,176,.06)); }
.dsp-person.on { background: var(--b50, #EFF5FB); box-shadow: inset 3px 0 0 var(--blue); }
.dsp-face { grid-area: face; position: relative; width: 40px; height: 40px; border-radius: 50%; background: #fff; border: 2px solid var(--border); overflow: visible; display: flex; align-items: center; justify-content: center; font-size: 20px; }
.dsp-face img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
.dsp-face i { position: absolute; right: -2px; bottom: -2px; width: 12px; height: 12px; border-radius: 50%; background: #9aa3b2; border: 2px solid var(--surface); }
.st-live .dsp-face i { background: var(--green); } .st-moving .dsp-face i { background: var(--blue); animation: breatheDot 1.6s ease-in-out infinite; } .st-none .dsp-face { filter: grayscale(1); opacity: .7; }
@keyframes breatheDot { 0%, 100% { transform: scale(1) } 50% { transform: scale(1.35) } }
.dsp-who { grid-area: who; display: flex; align-items: baseline; gap: 6px; font-size: 13.5px; }
.dsp-who small { color: var(--muted); font-size: 11.5px; }
.dsp-state { grid-area: state; font-size: 12.5px; font-weight: 600; }
.st-moving .dsp-state { color: var(--blue); } .st-live .dsp-state { color: var(--green); } .st-quiet .dsp-state, .st-none .dsp-state { color: var(--muted); font-weight: 500; }
.dsp-next { grid-area: next; font-size: 12px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.dsp-bar { grid-area: bar; height: 3px; border-radius: 2px; background: var(--border); margin-top: 3px; overflow: hidden; }
.dsp-bar i { display: block; height: 100%; background: var(--blue); }
.dsp-map-wrap { position: relative; min-height: 0; }
.dsp-map { position: absolute; inset: 0; }
@media (max-width: 860px) { .dsp-map-wrap { min-height: 420px; } }
.dsp-map-top { position: absolute; top: 10px; right: 10px; z-index: 800; display: flex; align-items: center; gap: 8px; }
.dsp-asof { font-size: 11.5px; color: var(--muted); background: var(--surface); padding: 3px 8px; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.2); }
.dsp-map-top .seg { box-shadow: 0 1px 4px rgba(0,0,0,.2); }
.dsp-map-top .seg-opt { padding: 4px 10px; font-size: 12px; }
.dsp-legend { position: absolute; left: 10px; bottom: 10px; z-index: 800; display: flex; gap: 12px; flex-wrap: wrap; font-size: 12px; color: var(--muted);
              background: var(--surface); padding: 5px 10px; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.2); }
.dsp-legend .tm-k { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 5px; vertical-align: -1px; }
.dsp-legend .tm-k.rep { background: var(--green); } .dsp-legend .tm-k.quiet { background: #9aa3b2; } .dsp-legend .tm-k.stop { background: #f59e0b; } .dsp-legend .tm-k.knock { background: #7c3aed; }
.dsp-board { margin-bottom: 8px; }
.dsp-board > summary { cursor: pointer; padding: 8px 2px; font-size: 13.5px; list-style: none; }
.dsp-board > summary::-webkit-details-marker { display: none; }
.dsp-board > summary::before { content: '▸'; display: inline-block; margin-right: 6px; transition: transform .15s; color: var(--muted); }
.dsp-board[open] > summary::before { transform: rotate(90deg); }
.tm-dim { opacity: .28; filter: grayscale(.6); }
.tm-cp.on .tm-cp-puck { box-shadow: 0 0 0 4px rgba(43,108,176,.35), 0 3px 8px rgba(0,0,0,.4); }
.tm-stop.big span { width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 11px; font-weight: 800; }
.tm-drive span { display: inline-block; background: #2b6cb0; color: #fff; font-size: 11.5px; font-weight: 700; padding: 2px 8px; border-radius: 9px; white-space: nowrap; box-shadow: 0 1px 4px rgba(0,0,0,.3); }

/* ---- Dispatch direction 2: the map over the timeline (2026-09-12) ---- */
.d2 { border: 1px solid var(--border); border-radius: 14px; overflow: hidden; background: var(--surface); margin-bottom: 14px; }
.d2-map-wrap { position: relative; height: clamp(300px, 42vh, 460px); }
.d2-map { position: absolute; inset: 0; }
.d2-tl { border-top: 1px solid var(--border); overflow-x: auto; }
.d2-hours { display: grid; grid-template-columns: 200px 1fr; border-bottom: 1px solid var(--border); font-size: 11.5px; color: var(--muted); position: sticky; top: 0; background: var(--surface); z-index: 2; }
.d2-hours-label { padding: 8px 12px; font-size: 13px; color: var(--text); }
.d2-hours-track { position: relative; height: 30px; }
.d2-hours-track i { position: absolute; top: 8px; transform: translateX(-50%); font-style: normal; font-variant-numeric: tabular-nums; }
.d2-lane { display: grid; grid-template-columns: 200px 1fr; border-bottom: 1px solid var(--border); min-height: 58px; }
.d2-lane.on { background: var(--b50, #EFF5FB); }
.d2-who { display: grid; grid-template-columns: 34px 1fr 6px; gap: 9px; align-items: center; padding: 8px 10px; border: 0; border-right: 1px solid var(--border); background: transparent; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.d2-who:hover { background: var(--brand-wash, rgba(43,108,176,.06)); }
.d2-who b { display: block; font-size: 13px; line-height: 1.2; } .d2-who small { display: block; font-size: 11.5px; color: var(--muted); }
.d2-who.st-moving small { color: var(--blue); font-weight: 600; } .d2-who.st-live small { color: var(--green); font-weight: 600; }
.d2-face { position: relative; width: 34px; height: 34px; border-radius: 50%; background: #fff; border: 2px solid var(--border); display: flex; align-items: center; justify-content: center; font-size: 17px; }
.d2-face img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
.d2-face i { position: absolute; right: -3px; bottom: -3px; width: 11px; height: 11px; border-radius: 50%; background: #9aa3b2; border: 2px solid var(--surface); }
.st-live .d2-face i { background: var(--green); } .st-moving .d2-face i { background: var(--blue); animation: breatheDot 1.6s ease-in-out infinite; } .st-none .d2-face { filter: grayscale(1); opacity: .7; }
.d2-booked { width: 6px; height: 34px; border-radius: 3px; background: var(--border); position: relative; overflow: hidden; }
.d2-booked i { position: absolute; left: 0; right: 0; bottom: 0; background: var(--blue); }
.d2-track { position: relative; min-height: 58px; background-image: repeating-linear-gradient(90deg, var(--border) 0 1px, transparent 1px calc(100% / var(--hours))); background-size: calc(100% / var(--hours)) 100%; }
.d2-track.over { background-color: var(--b50, #EFF5FB); box-shadow: inset 0 0 0 2px var(--blue); }
.d2-blk { position: absolute; top: 9px; height: 40px; border-radius: 7px; border: 1px solid transparent; border-left-width: 4px; padding: 3px 8px; font: inherit; font-size: 12px; line-height: 1.25; text-align: left; color: var(--text); cursor: grab; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; box-sizing: border-box; box-shadow: 0 1px 2px rgba(0,0,0,.08); }
.d2-blk b { font-variant-numeric: tabular-nums; margin-right: 4px; } .d2-blk small { display: block; color: var(--muted); font-size: 11px; overflow: hidden; text-overflow: ellipsis; }
.d2-blk.st-scheduled { background: #E8F0FA; border-left-color: #8FB3E0; }
.d2-blk.st-confirmed { background: #DCE8F8; border-left-color: var(--blue); }
.d2-blk.st-dispatched { background: #EDE4FB; border-left-color: #7C3AED; }
.d2-blk.st-working { background: #DFF3E6; border-left-color: var(--green); }
.d2-blk.st-hold { background: #F1F1F1; border-left-color: #9aa3b2; opacity: .8; }
.d2-blk.st-done { background: #EEF0F2; border-left-color: #9aa3b2; color: var(--muted); }
.d2-blk.st-no_show, .d2-blk.st-cancelled { background: #F7E7E7; border-left-color: var(--red); text-decoration: line-through; color: var(--muted); }
.d2-blk.em { border-color: var(--red); box-shadow: 0 0 0 1px var(--red); }
.d2-blk.on { box-shadow: 0 0 0 2px var(--blue), 0 2px 8px rgba(0,0,0,.18); z-index: 2; }
.d2-blk.dragging { opacity: .5; cursor: grabbing; }
.d2-blk.flash { animation: blkFlash 1.4s ease; }
@keyframes blkFlash { 0%, 100% { box-shadow: 0 0 0 0 transparent } 30% { box-shadow: 0 0 0 4px var(--b300, #9DBEE0) } }
:root[data-theme="dark"] .d2-blk, :root:not([data-theme="light"]) .d2-blk { color: var(--text); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .d2-blk.st-scheduled { background: #1d2a3a; } :root:not([data-theme="light"]) .d2-blk.st-confirmed { background: #1f3350; } :root:not([data-theme="light"]) .d2-blk.st-dispatched { background: #2d2447; } :root:not([data-theme="light"]) .d2-blk.st-working { background: #1c3527; } :root:not([data-theme="light"]) .d2-blk.st-done, :root:not([data-theme="light"]) .d2-blk.st-hold { background: #262a30; } :root:not([data-theme="light"]) .d2-blk.st-no_show, :root:not([data-theme="light"]) .d2-blk.st-cancelled { background: #3a2424; } }
:root[data-theme="dark"] .d2-blk.st-scheduled { background: #1d2a3a; } :root[data-theme="dark"] .d2-blk.st-confirmed { background: #1f3350; } :root[data-theme="dark"] .d2-blk.st-dispatched { background: #2d2447; } :root[data-theme="dark"] .d2-blk.st-working { background: #1c3527; } :root[data-theme="dark"] .d2-blk.st-done, :root[data-theme="dark"] .d2-blk.st-hold { background: #262a30; } :root[data-theme="dark"] .d2-blk.st-no_show, :root[data-theme="dark"] .d2-blk.st-cancelled { background: #3a2424; }
.d2-drive { position: absolute; top: 20px; height: 18px; border: 1px dashed var(--blue); border-radius: 5px; font-size: 10.5px; color: var(--blue); display: flex; align-items: center; justify-content: center; opacity: .8; box-sizing: border-box; pointer-events: none; }
.d2-drive.tight { border-color: var(--red); color: var(--red); }
.d2-now { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--red); z-index: 1; pointer-events: none; }
.d2-now::before { content: ''; position: absolute; top: 0; left: -4px; width: 10px; height: 10px; border-radius: 50%; background: var(--red); }
.d2-menu { position: absolute; z-index: 20; width: 340px; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 14px 40px rgba(0,0,0,.25); padding: 10px 12px; font-size: 13px; }
.d2-menu-head b { display: block; } .d2-menu-head small { color: var(--muted); display: block; margin-bottom: 8px; }
.d2-menu-row { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin-top: 6px; }
.d2-menu-row label { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; color: var(--muted); }
.d2-menu-row select, .d2-menu-row input { font-size: 12.5px; padding: 3px 6px; }
.d2-tray { border-top: 1px solid var(--border); }
.d2-tray > summary { list-style: none; cursor: pointer; padding: 6px 10px; }
.d2-tray > summary::-webkit-details-marker { display: none; }
.d2-tabs { display: flex; gap: 4px; flex-wrap: wrap; }
.d2-tab { border: 0; background: transparent; font: inherit; font-size: 12.5px; color: var(--muted); padding: 5px 10px; border-radius: 8px; cursor: pointer; display: inline-flex; gap: 6px; align-items: center; }
.d2-tab i { font-style: normal; font-variant-numeric: tabular-nums; background: var(--border); border-radius: 8px; padding: 0 6px; font-size: 11px; color: var(--text); }
.d2-tab.on { background: var(--b50, #EFF5FB); color: var(--text); font-weight: 600; } .d2-tab.hot i { background: var(--red); color: #fff; }
.d2-tray-body { position: relative; max-height: 280px; overflow: auto; border-top: 1px solid var(--border); }
.d2-table { margin: 0; } .d2-table tr.draggable { cursor: grab; }
@media (max-width: 760px) { .d2-hours, .d2-lane { grid-template-columns: 130px 1fr; } .d2-who { grid-template-columns: 28px 1fr; } .d2-booked { display: none; } .d2-map-wrap { height: 300px; } }

/* A long company name can never push the top bar around (2026-09-13). */
.topbar .brand { min-width: 0; }
.topbar .brand-co { max-width: min(240px, 22vw); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- The review inbox (2026-09-13) ---- */
.src-chip { display: inline-block; padding: 1px 7px; border-radius: 8px; border: 1px solid var(--border); color: var(--muted); font-size: 11px; }
.src-chip.on { border-color: var(--green); color: var(--green); }
.rv { padding: 10px 0; border-top: 1px solid var(--border); }
.rv:first-of-type { border-top: 0; }
.rv.done { opacity: .8; }
.rv-stars { color: #c9a227; letter-spacing: 1px; font-size: 13px; } .rv-stars.good { color: #d99a00; } .rv-stars.bad { color: var(--red); }
.rv-text { margin: 4px 0 0; font-size: 13.5px; }
.rv-reply { margin: 6px 0 0; font-size: 12.5px; }
.rv-draft textarea { width: 100%; margin-top: 8px; font: inherit; font-size: 13px; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--border); background: var(--surface); color: inherit; }
.lh-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 8px 14px; }
.lh { display: flex; gap: 8px; align-items: flex-start; font-size: 13px; }
.lh i { width: 20px; height: 20px; border-radius: 50%; border: 1px solid var(--border); display: inline-flex; align-items: center; justify-content: center; font-style: normal; font-size: 12px; color: var(--muted); flex: none; }
.lh.ok i { background: var(--green); border-color: var(--green); color: #fff; }
.lh small { display: block; color: var(--muted); font-size: 11.5px; }

/* ---- Capacity rules editor (2026-09-13) ---- */
.cap-rule { display: grid; grid-template-columns: 150px 1fr; gap: 6px 10px; align-items: center; padding: 8px 0; border-top: 1px solid var(--border); font-size: 12.5px; }
.cap-rule select, .cap-rule input[type="number"] { font-size: 12.5px; padding: 3px 6px; }
.cap-rule input[type="number"] { width: 60px; }
.cap-months, .cap-ch { display: flex; gap: 6px 10px; flex-wrap: wrap; grid-column: 1 / -1; }
.cap-months label, .cap-ch label { display: inline-flex; align-items: center; gap: 3px; font-size: 11.5px; color: var(--muted); }
.cap-pct { grid-column: 1 / -1; }
.cap-rule [data-r-del] { grid-column: 2; justify-self: end; }

/* BRAND MARKS (2026-09-14): a platform's logo in front of its name, so a
   row of Facebook, Instagram, Google reads at a glance (js/brands.js). */
.brand-label { display: inline-flex; align-items: center; gap: 6px; vertical-align: middle; }
.plat-mark { flex: none; display: inline-block; }
.src-ico { display: inline-flex; opacity: .75; }
.brand-row { display: inline-flex; align-items: center; gap: 4px; vertical-align: -2px; margin-right: 4px; }
.pill .brand-label, .src-chip .brand-label { gap: 5px; }
/* MEASUREMENT VENDOR LOGOS (2026-10-03, js/brands.js vendorLogo). The
   files are used as published. EagleView never drawn under its brand minimum
   (250px horizontal, 150px stacked), so min-width holds it there even in a
   squeezed flex row, and its Dark-BG file replaces the light one in the dark
   theme. Hover's wordmark is black, so the dark theme inverts it to white.
   Keyed on the data-theme stamp alone: theme.js stamps "dark" for auto on a
   dark OS too, and REMOVES it for light, so a prefers-color-scheme rule here
   would turn the logos dark for someone who picked light on a dark Mac. */
.vlogo { display: inline-block; vertical-align: middle; flex: none; max-width: none; }
.vlogo-ev { line-height: 0; }
.vlogo-ev img { width: 100%; min-width: 100%; height: auto; display: block; }
.vlogo-ev .vlogo-dark { display: none; }
:root[data-theme="dark"] .vlogo-ev .vlogo-light { display: none; }
:root[data-theme="dark"] .vlogo-ev .vlogo-dark { display: block; }
:root[data-theme="dark"] .vlogo-hover { filter: invert(1); }
.vendor-logo-row { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 22px; margin: 10px 0 2px; }
.btn .vlogo-hover { margin-left: 4px; }
/* SIGN-IN AND CONNECT BUTTONS IN THE COMPANIES' OWN ART (2026-10-03,
   js/brands.js ssoButton / connectGlyph / qboConnectButton). Google's and
   Microsoft's buttons are the same 44px tall, so Google is never the smaller
   choice, and each is only ever scaled whole (height:auto, never a squeeze).
   Google ships a Dark button for the dark theme; Microsoft's light lockup is
   one of its two approved versions and reads on either. Same data-theme
   stamp rule as the vendor logos above. */
.sso-row { display: flex; flex-direction: column; align-items: center; gap: 10px; margin-top: 8px; }
.sso-btn { display: inline-block; line-height: 0; border-radius: 4px; }
/* Same width for both, so Google's button is never smaller than another
   provider's (Google's rule). Both stay their light versions in dark mode,
   a matched pair of white buttons, which both brands allow. */
.sso-btn img { width: 232px; height: auto; max-width: 100%; display: block; }
.sso-btn:focus-visible, .qbo-connect-btn:focus-visible { outline: 2px solid var(--b500, #2563eb); outline-offset: 2px; }
.sso-google .sso-dark { display: none; }

.connect-glyph { display: inline-block; vertical-align: middle; flex: none; }
.qbo-connect-btn { display: inline-block; padding: 0; border: 0; background: none; cursor: pointer; line-height: 0; border-radius: 4px; }
.qbo-connect-btn img { width: 220px; max-width: 100%; height: auto; display: block; }
.qbo-connect-btn:disabled { opacity: .6; cursor: progress; }
/* Logos stay in their colors even on a chip that is not connected yet: the
   chip's own fade already says "not connected", and a grey logo on a faded
   chip was hard to read, which is the one job these have. */

/* ==== THE LAYOUTS (2026-09-16) ==========================================
   Ten whole-app arrangements a company picks in Appearance (theme.js LAYOUTS,
   stamped as :root[data-layout]). Two rows is the default and needs no rule
   here. EVERY rule below sits above the phone breakpoint: a phone keeps its
   tab bar whatever the company chose. */
.sidenav, .sidepanel, #sectionsBtn, .tn-ico { display: none; }

@media (min-width: 761px) {
  /* -- the side column: Sidebar, Cockpit, Today feed, Icon rail -- */
  :root[data-layout="sidebar"] .secbar, :root[data-layout="cockpit"] .secbar,
  :root[data-layout="today"] .secbar, :root[data-layout="rail"] .secbar,
  :root[data-layout="focus"] .secbar, :root[data-layout="board"] .secbar { display: none; }
  :root[data-layout="sidebar"] .secpages, :root[data-layout="cockpit"] .secpages,
  :root[data-layout="today"] .secpages { display: none; }
  :root[data-layout="sidebar"] .sidenav, :root[data-layout="cockpit"] .sidenav,
  :root[data-layout="today"] .sidenav, :root[data-layout="rail"] .sidenav {
    display: flex; flex-direction: column; gap: 1px; flex: none; width: 220px;
    position: sticky; top: var(--topbar-h); height: calc(100vh - var(--topbar-h));
    overflow-y: auto; padding: 12px 10px; background: var(--surface);
    border-right: 1px solid var(--border);
  }
  :root[data-layout="today"] .sidenav { width: 190px; }
  :root[data-layout="cockpit"] .sidenav { width: 200px; }
  .sn-link, .sn-head {
    display: flex; align-items: center; gap: 9px; width: 100%; padding: 7px 10px;
    border: 0; background: transparent; border-radius: var(--radius-sm);
    font: inherit; font-size: 13.5px; color: var(--ink); cursor: pointer;
    text-align: left; text-decoration: none; white-space: nowrap;
  }
  .sn-link:hover, .sn-head:hover { background: var(--raise); }
  .sn-link:focus-visible, .sn-head:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
  .sn-link.on { background: var(--b50); color: var(--b800); font-weight: 600; }
  .sn-head {
    margin-top: 12px; padding-block: 4px; font-size: 10.5px; font-weight: 700;
    letter-spacing: .06em; text-transform: uppercase; color: var(--slate);
  }
  .sn-head svg, .sn-flyhead { display: none; }
  .sn-head.on { color: var(--ink); }
  .sn-pages { display: flex; flex-direction: column; gap: 1px; }

  /* -- Icon rail: icons only, a section's pages fly out on hover or focus -- */
  /* z-index: the flyouts must paint over the page beside the rail, and a
     sticky column only stacks above later siblings when it has one. */
  :root[data-layout="rail"] .sidenav { width: 64px; padding: 10px 8px; align-items: center; overflow: visible; gap: 4px; z-index: 35; }
  :root[data-layout="rail"] .sidenav > .sn-link, :root[data-layout="rail"] .sn-head {
    width: 44px; height: 44px; justify-content: center; padding: 0; margin: 0;
  }
  :root[data-layout="rail"] .sidenav > .sn-link span, :root[data-layout="rail"] .sn-head span { display: none; }
  :root[data-layout="rail"] .sn-head svg { display: block; }
  :root[data-layout="rail"] .sn-head.on { background: var(--b50); color: var(--b800); }
  :root[data-layout="rail"] .sn-group { position: relative; }
  :root[data-layout="rail"] .sn-pages {
    display: none; position: absolute; left: calc(100% + 8px); top: 0; z-index: 50;
    min-width: 210px; padding: 8px; background: var(--surface);
    border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-pop);
  }
  :root[data-layout="rail"] .sn-pages::before { content: ''; position: absolute; left: -12px; top: 0; bottom: 0; width: 12px; }
  :root[data-layout="rail"] .sn-group:hover .sn-pages,
  :root[data-layout="rail"] .sn-group:focus-within .sn-pages { display: flex; }
  :root[data-layout="rail"] .sn-flyhead {
    display: block; margin: 2px 8px 6px; font-size: 10.5px; font-weight: 700;
    letter-spacing: .06em; text-transform: uppercase; color: var(--slate);
  }

  /* -- Menu door: Board first and Focus tuck the sections away -- */
  :root[data-layout="board"] #sectionsBtn, :root[data-layout="focus"] #sectionsBtn { display: inline-flex; }

  /* -- Focus: one calm column, a size up -- */
  :root[data-layout="focus"] { font-size: 106%; }
  :root[data-layout="focus"] .main { max-width: 880px; margin-inline: auto; width: 100%; }

  /* -- Cockpit: the right panel -- */
  @media (min-width: 1280px) {
    :root[data-layout="cockpit"] .sidepanel {
      display: flex; flex-direction: column; gap: 6px; flex: none; width: 280px;
      position: sticky; top: var(--topbar-h); height: calc(100vh - var(--topbar-h));
      overflow-y: auto; padding: 14px; background: var(--surface);
      border-left: 1px solid var(--border);
    }
  }
  .sp-head { margin: 10px 2px 2px; font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--slate); }
  .sp-head:first-child { margin-top: 0; }
  .sp-list { display: flex; flex-direction: column; gap: 6px; }
  .sp-list .dim { font-size: 12.5px; margin: 0; }
  .sp-item {
    display: flex; flex-direction: column; gap: 1px; padding: 8px 10px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    color: var(--ink); text-decoration: none; font-size: 13px;
  }
  .sp-item:hover { background: var(--raise); }
  .sp-item b { font-family: var(--mono); font-weight: 500; font-size: 11.5px; color: var(--slate); }
  .sp-item span { color: var(--slate); font-size: 12px; }
  .sp-ask { margin-top: auto; justify-content: center; }

  /* -- Spreadsheet: tighter everything, sections as sheet tabs at the foot -- */
  :root[data-layout="sheet"] { font-size: 92%; }
  :root[data-layout="sheet"] .card { padding-top: 10px; padding-bottom: 10px; }
  :root[data-layout="sheet"] .page-head { margin-bottom: 8px; }
  :root[data-layout="sheet"] table td, :root[data-layout="sheet"] table th { padding-top: 5px; padding-bottom: 5px; }
  :root[data-layout="sheet"] .secbar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 45; height: 38px;
    border-bottom: 0; border-top: 1px solid var(--border); background: var(--surface);
  }
  :root[data-layout="sheet"] .secbar .topnav-link {
    border-bottom: 0; border-top: 2px solid transparent; margin: -1px 0 0; font-size: 12.5px;
  }
  :root[data-layout="sheet"] .secbar .topnav-link.on { border-top-color: var(--blue); background: var(--raise); }
  :root[data-layout="sheet"] .secbar .topnav-menu { top: auto; bottom: calc(100% + 4px); }
  :root[data-layout="sheet"] .main { padding-bottom: 64px; }

  /* -- Dock: a floating dock of sections, touch-sized -- */
  :root[data-layout="dock"] { font-size: 105%; }
  :root[data-layout="dock"] .btn { min-height: 38px; }
  :root[data-layout="dock"] .secbar {
    position: fixed; left: 50%; bottom: 16px; transform: translateX(-50%); z-index: 45;
    height: auto; width: max-content; max-width: calc(100vw - 32px); padding: 6px;
    border: 1px solid var(--border); border-radius: 22px; box-shadow: var(--shadow-pop);
    background: var(--surface);
  }
  :root[data-layout="dock"] .secbar .topnav-link {
    flex-direction: column; gap: 3px; min-width: 70px; padding: 8px 10px; margin: 0;
    border: 0; border-radius: 14px; font-size: 11.5px;
  }
  :root[data-layout="dock"] .secbar .topnav-link.on { background: var(--raise); }
  :root[data-layout="dock"] .tn-ico { display: inline-flex; }
  :root[data-layout="dock"] .secbar .topnav-menu { top: auto; bottom: calc(100% + 10px); }
  :root[data-layout="dock"] .main { padding-bottom: 120px; }

  /* -- Split view: the list on the left, the record opens beside it -- */
  #main.split-on { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); gap: 18px; align-items: start; }
  .split-list { min-width: 0; overflow-x: auto; }
  .split-pane {
    position: sticky; top: calc(var(--topbar-h) + 12px); min-width: 0;
    max-height: calc(100vh - var(--topbar-h) - 24px); overflow-y: auto;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 16px;
  }
  .split-pane .job-sticky { top: 0; }
  tr.split-picked td { background: var(--b50); }
}

/* The layout picker (Settings → Appearance) */
.layout-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 10px; margin-top: 10px; }
.layout-tile {
  display: flex; flex-direction: column; gap: 3px; text-align: left; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface); border-radius: var(--radius);
  padding: 10px 12px; font: inherit; color: inherit;
}
.layout-tile:hover { background: var(--raise); }
.layout-tile.on { border-color: var(--blue); box-shadow: 0 0 0 2px var(--b100); }
.layout-tile:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.layout-tile b { font-size: 13.5px; }
.layout-tile > span:not(.lm) { font-size: 12px; color: var(--slate); line-height: 1.35; }
.layout-tile .lm {
  position: relative; display: block; height: 62px; margin-bottom: 6px; overflow: hidden;
  border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--canvas);
}
.layout-tile .lm i { position: absolute; display: block; background: var(--border); border-radius: 2px; }
.layout-tile .lm i.b { background: var(--surface); border: 1px solid var(--border); }
.layout-tile.on .lm i:not(.b) { background: var(--b300); }

/* A customer texted (2026-09-16). The count is red like a missed text on a
   phone, and the strip sits under the header until Texts is opened. */
.nav-badge.texts-badge, .topnav .nav-badge.texts-badge {
  margin-left: 6px; min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 999px; background: #D92D20; color: #fff;
  font-family: var(--body); font-size: 11px; font-weight: 700;
  line-height: 18px; text-align: center; font-variant-numeric: tabular-nums;
}
.tab-item { position: relative; }
.tab-item .nav-badge.texts-badge { position: absolute; top: 2px; left: 50%; margin-left: 6px; }
.texts-strip { display: flex; background: var(--b50); border-bottom: 1px solid var(--b300); }
.texts-strip .texts-body {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px;
  flex-wrap: wrap; padding: 9px 12px; border: 0; background: none; cursor: pointer;
  color: var(--ink); font: inherit; font-size: 13.5px; text-align: center; min-width: 0;
}
.texts-strip .texts-body b { color: var(--b800); }
.texts-strip .texts-body span { color: var(--slate); min-width: 0; overflow-wrap: anywhere; }
.texts-strip .texts-body u { color: var(--blue); text-decoration: none; font-weight: 600; }
/* The inspection report builder: pick the photos, caption them for the report. */
.ir-grid { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(128px, 1fr));
  max-height: 46vh; overflow: auto; padding: 2px; }
.ir-tile { display: flex; flex-direction: column; gap: 4px; }
.ir-pick { position: relative; padding: 0; border: 2px solid var(--border); border-radius: 10px; overflow: hidden;
  background: var(--raise); cursor: pointer; aspect-ratio: 4 / 3; max-width: 100%; opacity: .5; }
.ir-pick img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ir-tile.on .ir-pick { border-color: var(--blue); opacity: 1; }
.ir-check { position: absolute; top: 5px; right: 5px; width: 20px; height: 20px; border-radius: 999px;
  display: none; align-items: center; justify-content: center; background: var(--blue); color: #fff; }
.ir-tile.on .ir-check { display: inline-flex; }
.ir-read { position: absolute; left: 5px; bottom: 5px; font-size: 10px; padding: 1px 6px; border-radius: 999px;
  background: rgba(15,19,26,.72); color: #fff; }
.ir-cap { font-size: 12px; padding: 4px 6px; }
/* A report sent to the homeowner, and whether they opened it. */
.tile-report { position: absolute; top: 6px; left: 6px; font-size: 10.5px; font-weight: 600; padding: 2px 7px;
  border-radius: 999px; background: rgba(20,24,32,.8); color: #fff; pointer-events: none; }
.tile-report.opened { background: var(--green, #1F9D55); }

/* Gap 10 (accessibility, 2026-09-19): a keyboard focus ring on anything that
   has not drawn its own, so Tab never loses its place. Kept at zero
   specificity (:where) so every component's own ring still wins. */
:where(a, button, [role="button"], [tabindex], summary, select):focus-visible {
  outline: 2px solid var(--blue); outline-offset: 2px;
}
.modal:focus { outline: none; }
.sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }

/* A dialog that slides in from the right edge: the job's Add document panel
   (modal(..., { drawer: true })). Full height, the list scrolls, the buttons
   stay at the bottom. On a phone it is the whole screen. */
.scrim.scrim-drawer{justify-content:flex-end;align-items:stretch;padding:0}
.modal.drawer{margin:0;max-width:none;width:min(480px,100vw);height:100%;max-height:none;
  border-radius:14px 0 0 14px;display:flex;flex-direction:column;
  animation:drawer-in .18s ease-out}
.modal.drawer .drawer-body{flex:1;overflow:auto;margin:0 -4px;padding:0 4px}
@keyframes drawer-in{from{transform:translateX(40px);opacity:.4}to{transform:none;opacity:1}}
@media (prefers-reduced-motion:reduce){.modal.drawer{animation:none}}

/* ⭐ THE STAGE STEP BAR (2026-09-28). Replaces the pill row on the job page:
   equal columns, a line through the circles, the days between two steps on
   the line between them. Scrolls sideways on a narrow phone. */
.stepper { list-style: none; margin: 0; padding: 18px 0 2px; flex: 1 1 auto; min-width: 0;
  display: grid; grid-template-columns: repeat(var(--steps, 5), minmax(78px, 1fr));
  overflow-x: auto; }
.step { position: relative; display: flex; flex-direction: column;
  align-items: center; text-align: center; gap: 4px; padding: 0 4px; }
.step::before { content: ""; position: absolute; top: 15px; right: 50%;
  width: 100%; height: 3px; background: var(--border); z-index: 0; }
.step:first-child::before { display: none; }
.step.lined::before { background: var(--green); }
.step-dot { position: relative; z-index: 1; width: 32px; height: 32px;
  border-radius: 50%; display: grid; place-items: center;
  font-size: 14px; font-weight: 700; background: var(--surface);
  border: 2px solid var(--border); color: var(--slate-light); }
.step.done .step-dot { background: var(--green); border-color: var(--green); color: #fff; }
.step.on .step-dot { background: var(--navy); border-color: var(--navy);
  box-shadow: 0 0 0 5px rgba(127, 178, 229, .35); }
.step.on .step-dot::after { content: ""; width: 10px; height: 10px;
  border-radius: 50%; background: #fff; }
.step-label { font-size: 13.5px; font-weight: 600; color: var(--slate); white-space: nowrap; }
.step.done .step-label { color: var(--green); }
.step.on .step-label { color: var(--ink); font-weight: 700; }
.step-date { font-size: 12px; color: var(--slate-light); font-variant-numeric: tabular-nums; }
/* centred on the connector, which runs from the last circle to this one,
   so its middle is this step's own left edge; just above the line */
.step-gap { position: absolute; top: -4px; left: 0; transform: translateX(-50%);
  white-space: nowrap; font-size: 11px; font-weight: 600; color: var(--slate-light); }
.job-bar-sub { font-size: 13px; color: var(--slate); white-space: nowrap;
  display: inline-flex; align-items: center; gap: 4px; text-decoration: none; }
a.job-bar-sub { color: var(--red); }
@media (max-width: 640px) { .job-bar-sub { display: none; } .job-sticky:not(.head-in-view) a.job-bar-sub { display: inline-flex; } }
@media (max-width: 480px) {
  .stepper { grid-template-columns: repeat(var(--steps, 5), minmax(60px, 1fr)); }
  .step-label { font-size: 12px; }
  .step-dot { width: 28px; height: 28px; font-size: 12.5px; }
  .step::before { top: 13px; }
}

/* ---- The estimate as options (Josh, 2026-10-14): the option cards are the
   screen, the commission steps are the one price lever, and Customer view
   hides what is ours so the screen can face the homeowner. */
.est2 { padding: 16px 18px; }
.est-top { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 12px; }
.est-top h3 { margin: 0; font-size: 17px; }
.cust-toggle.on { background: var(--blue-light); color: var(--blue); border-color: transparent; }
.est-meas { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--raise);
  font-size: 13.5px; margin-bottom: 12px; }
.est-meas svg { color: var(--slate); flex: none; }
.est-meas-txt { flex: 1 1 220px; min-width: 0; }
.meas-import { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px 12px; margin: 0 0 14px;
  border: 1px dashed var(--border); border-radius: var(--radius); background: var(--raise); }
/* The job's own reports and finished orders, above the import (11/3). */
.meas-sources { display: flex; flex-direction: column; gap: 6px; margin: 0 0 10px; }
.meas-src { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border: 1px solid var(--border);
  border-radius: var(--radius); background: var(--surface); }
.meas-src.on { border-color: var(--blue); background: var(--blue-light); }
.meas-src > svg { flex: none; color: var(--slate); }
.meas-src-t { flex: 1; min-width: 0; display: flex; flex-direction: column; font-size: 13px; }
.meas-src-t b { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.meas-src-t .dim { font-size: 12px; }
.meas-src .btn { flex: none; }
.est-measup { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 9px 12px; margin-bottom: 12px;
  border: 1px solid var(--amber); border-radius: var(--radius); background: var(--amber-light); font-size: 13px; }
.est-measup svg { color: var(--amber); flex: none; }
.est-comm { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 0 0 14px; }
.comm-seg { width: fit-content; flex-wrap: wrap; }
.comm-seg button { position: relative; min-width: 46px; font-variant-numeric: tabular-nums; }
.comm-seg button.on { background: var(--blue); color: #fff; }
.std-dot { position: absolute; top: 3px; right: 4px; width: 5px; height: 5px; border-radius: 50%;
  background: currentColor; opacity: .55; }
.comm-note { font-size: 13px; color: var(--slate); }
.comm-note b { color: var(--green); font-family: var(--mono); }
.opt-list { display: flex; flex-direction: column; gap: 10px; }
.opt-card { border: 1px solid var(--border); border-radius: 12px; background: var(--surface); }
.opt-card.on { border: 2px solid var(--blue); }
.opt-head { display: flex; align-items: center; gap: 12px; padding: 12px 14px; cursor: pointer; }
.opt-card.on .opt-head { cursor: default; }
.opt-head:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; border-radius: 10px; }
.opt-radio { flex: none; width: 18px; height: 18px; border-radius: 50%; border: 2px solid var(--slate-light); }
.opt-radio.on { border-color: var(--blue); box-shadow: inset 0 0 0 4px var(--surface); background: var(--blue); }
.opt-title { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.opt-title b { font-size: 15.5px; }
.opt-blurb { font-size: 12.5px; color: var(--slate); }
.opt-price { font-family: var(--display); font-size: 19px; font-weight: 600; white-space: nowrap;
  font-variant-numeric: tabular-nums; }
.opt-peek { columns: 2; column-gap: 24px; list-style: none; margin: -4px 0 0; padding: 0 14px 12px 44px;
  font-size: 12.5px; color: var(--slate); cursor: pointer; }
.opt-peek li { padding: 2px 0; break-inside: avoid; }
.opt-body { padding: 0 18px 16px; }
.opt-hero { display: block; width: 100%; max-height: 220px; object-fit: cover; border-radius: 10px; margin: 0 0 10px; }
.opt-lines { width: 100%; border-collapse: collapse; font-size: 14px; }
.opt-lines th { text-align: left; font-weight: 500; font-size: 12.5px; color: var(--slate);
  padding: 6px 0; border-bottom: 1px solid var(--border); }
.opt-lines td { padding: 9px 0; border-bottom: 1px solid var(--border); vertical-align: top; }
.opt-lines td.q { text-align: right; color: var(--slate); font-size: 12.5px; white-space: nowrap; padding-left: 12px; }
.opt-lines td.m { text-align: right; white-space: nowrap; width: 1%; padding-left: 12px;
  font-family: var(--mono); font-size: 13px; }
.opt-lines tr.custom td:first-child::after { content: 'added'; margin-left: 6px; font-size: 10.5px;
  text-transform: uppercase; letter-spacing: .05em; color: var(--blue); }
.opt-x { margin-left: 4px; padding: 0 4px; }
.opt-scope { margin: 12px 0 0; }
.opt-scope ul { margin: 4px 0 0; padding-left: 18px; font-size: 13px; color: var(--slate); }
.opt-scope li { margin: 2px 0; }
.opt-ups { margin: 12px 0 0; border-top: 1px dashed var(--border); padding-top: 8px; }
.opt-up { display: flex; justify-content: space-between; gap: 12px; font-size: 13.5px; padding: 3px 0; }
.opt-actions { gap: 8px; margin: 12px 0 0; }
.opt-sums { width: 100%; max-width: 380px; margin: 14px 0 0 auto; border-collapse: collapse; font-size: 14px; }
.opt-sums td { padding: 4px 0; color: var(--slate); }
.opt-sums td.m { text-align: right; font-family: var(--mono); color: var(--ink); white-space: nowrap; }
.opt-sums tr.grand td { border-top: 1px solid var(--border); padding-top: 8px; font-weight: 600;
  font-size: 17px; color: var(--ink); }
.disc-in { width: 64px; margin: 0 2px 0 6px; padding: 3px 6px; }
.opt-foot { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px;
  margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--border); font-size: 12.5px; color: var(--slate); }
.opt-foot b { color: var(--ink); }
.opt-logo { max-height: 40px; max-width: 120px; object-fit: contain; }
.opt-edit { padding: 0 14px 14px; }
.est-fold { margin-top: 14px; border-top: 1px solid var(--border); padding-top: 10px; }
.est-fold > summary { cursor: pointer; list-style: none; font-weight: 600; font-size: 13.5px;
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.est-fold > summary::-webkit-details-marker { display: none; }
.est-fold > summary svg { transition: transform .15s; }
.est-fold[open] > summary svg { transform: rotate(90deg); }
.est-fold > summary .dim { font-weight: 400; font-size: 12.5px; }
.est-fold-in { padding: 10px 0 2px; }
.pd-row { gap: 8px; align-items: center; margin: 0 0 8px; }
.pd-label { font-size: 12.5px; font-weight: 600; min-width: 150px; }
.est-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
.est2 .cust-only { display: none; }
.est2.cust .internal, .est2.cust .edit-only { display: none !important; }
.est2.cust .cust-only { display: inline; }
@media (max-width: 560px) {
  .est2 { padding: 12px; }
  .opt-peek { columns: 1; padding-left: 14px; }
  .opt-body { padding: 0 12px 12px; }
  .opt-price { font-size: 17px; }
  .pd-label { min-width: 0; width: 100%; }
}

/* ⭐ Starter color schemes in Settings > Appearance (2026-10-18). */
.scheme-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; margin-top: 8px; }
.scheme-tile { display: flex; align-items: center; gap: 10px; padding: 9px 10px; border: 1px solid var(--border);
  border-radius: var(--radius-sm, 8px); background: transparent; color: inherit; cursor: pointer; text-align: left; font-size: 13px; }
.scheme-tile:hover { border-color: var(--slate-light); }
.scheme-tile.on { border-color: var(--blue); box-shadow: 0 0 0 1px var(--blue) inset; }
.scheme-sw { display: inline-flex; flex: none; }
.scheme-sw i { width: 14px; height: 22px; display: inline-block; }
.scheme-sw i:first-child { border-radius: 5px 0 0 5px; }
.scheme-sw i:last-child { border-radius: 0 5px 5px 0; }
.fd-or { display: flex; align-items: center; gap: 10px; margin: 18px 0 4px; font-size: 12.5px; color: var(--slate); }
.fd-or span { flex: 1; height: 1px; background: var(--border); }
.fd-schemes { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* ⭐ Damage marks on a photo, for the inspection report (2026-10-19). */
.dmg-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.dmg-chip { display: inline-flex; align-items: center; gap: 4px; border: 1px solid var(--border);
  border-radius: 999px; padding: 2px 4px; font-size: 12.5px; }
.dmg-chip.on { border-color: var(--blue); background: var(--blue-light); }
.dmg-chip button { width: 24px; height: 24px; border-radius: 50%; border: 0; background: transparent;
  color: inherit; font-size: 15px; line-height: 1; cursor: pointer; }
.dmg-chip button:hover { background: var(--border); }
.dmg-chip b { font-weight: 700; }
.ir-marks { display: block; font-size: 11px; color: var(--slate); margin-top: 3px; line-height: 1.3; }

/* ---- The showcase demo (2026-10-23): the welcome over Home, the Demo
   menu, the guided tour's card (it borrows .story-dock) and Riley live. */
.sc-welcome { position: fixed; inset: 0; z-index: 95; display: flex;
  padding: 16px; box-sizing: border-box; background: rgba(10, 16, 28, .55); backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px); animation: storyIn .3s ease; overflow: auto; }
.scw-card { position: relative; margin: auto; width: min(720px, 100%); background: var(--surface, #fff); color: var(--ink);
  border-radius: 20px; padding: 28px 28px 20px; box-shadow: 0 30px 80px rgba(10, 16, 28, .35); text-align: center; }
.scw-x { position: absolute; top: 12px; right: 12px; width: 34px; height: 34px; padding: 0; justify-content: center; }
.scw-mark { width: 72px; height: 72px; margin: 0 auto 10px; border-radius: 18px; background: #fff;
  border: 1px solid var(--border); display: flex; align-items: center; justify-content: center; overflow: hidden; }
.scw-mark img { max-width: 86%; max-height: 86%; object-fit: contain; }
.scw-mark span { font-size: 26px; font-weight: 750; color: var(--blue); }
.scw-k { margin: 0; font-size: 12px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--blue); }
.scw-card h1 { margin: 6px 0 10px; font-size: clamp(24px, 4.4vw, 34px); line-height: 1.15; letter-spacing: -.01em; }
.scw-sub { margin: 0 auto 18px; max-width: 560px; font-size: 14.5px; line-height: 1.55; color: var(--slate); }
.scw-sub b { color: var(--ink); }
.scw-note { margin: -6px auto 16px; max-width: 520px; font-size: 13px; padding: 8px 12px; border-radius: 10px;
  background: var(--hover, rgba(0, 0, 0, .04)); }
.scw-picks { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; text-align: left; }
.scw-pick { display: grid; gap: 6px; align-content: start; padding: 16px; border-radius: 14px; cursor: pointer; font: inherit;
  border: 1px solid var(--border); background: var(--surface, #fff); color: var(--ink); transition: border-color .15s, transform .15s; }
.scw-pick svg { color: var(--blue); }
.scw-pick b { font-size: 15px; }
.scw-pick span { font-size: 12.5px; line-height: 1.45; color: var(--slate); }
.scw-pick:hover { border-color: var(--blue); transform: translateY(-1px); }
.scw-pick:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }
.scw-pick.primary { border-color: var(--blue); box-shadow: inset 0 0 0 1px var(--blue); }
.scw-riley { display: flex; gap: 10px; align-items: center; justify-content: center; flex-wrap: wrap; margin: 16px 0 0;
  font-size: 12.5px; color: var(--slate); }
.scw-foot { margin: 14px 0 0; font-size: 11.5px; color: var(--slate); }
@media (max-width: 640px) {
  .scw-card { padding: 22px 16px 16px; }
  .scw-picks { grid-template-columns: 1fr; }
}
.sc-menu { position: fixed; z-index: 96; min-width: 240px; padding: 6px; border-radius: 12px; background: var(--surface, #fff);
  border: 1px solid var(--border); box-shadow: 0 16px 40px rgba(10, 16, 28, .22); display: grid; }
.sc-menu button { display: flex; gap: 10px; align-items: center; padding: 10px 12px; border: 0; border-radius: 8px; background: none;
  font: inherit; font-size: 13.5px; color: var(--ink); cursor: pointer; text-align: left; }
.sc-menu button:hover, .sc-menu button:focus-visible { background: var(--hover, rgba(0, 0, 0, .05)); outline: none; }
.sc-menu button svg { color: var(--blue); flex: none; }
.sc-menu .sc-m-reset { border-top: 1px solid var(--border); border-radius: 0 0 8px 8px; margin-top: 4px; }
.sc-dock .sd-body .btn { margin: 0 0 10px; }
.sc-fin { display: grid; gap: 8px; }
.sc-rform { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 0 0 10px; }
.sc-consent { grid-column: 1 / -1; display: flex; gap: 10px; align-items: flex-start; font-size: 13px; line-height: 1.45; }
.sc-consent input { margin-top: 3px; }
.sc-calls { display: grid; gap: 6px; margin: 0 0 10px; }
.sc-call { border: 1px solid var(--border); border-radius: 10px; padding: 8px 10px; font-size: 13px; display: flex; gap: 10px; flex-wrap: wrap; align-items: baseline; }
.sc-call span { color: var(--slate); }
.sc-call details { flex-basis: 100%; }
.sc-call pre { white-space: pre-wrap; font: inherit; font-size: 12.5px; max-height: 220px; overflow: auto; margin: 6px 0 0; }
@media (max-width: 520px) { .sc-rform { grid-template-columns: 1fr; } }
/* A demo copy's top bar carries the Demo button too: on a phone the sticky
   notes give it their room, or the bar pushes the page 40px past the screen
   and the welcome card with it (measured at 375). */
@media (max-width: 600px) { .topbar-right:has(#tourBtn) .newmenu-wrap.splitbtn { display: none; } }

/* ---- The Report Studio (Josh, 2026-10-26): one full screen to scrub the
   photos and write the report. Under the app's dialogs (scrim 100), so a
   Callout's question and Build's answer open on top of it. */
body.rs-open { overflow: hidden; }
.rs { position: fixed; inset: 0; z-index: 95; background: var(--canvas); display: flex; flex-direction: column; }
.rs-top { display: flex; align-items: center; gap: 10px; padding: 8px 14px; background: var(--surface);
  border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.rs-title { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.rs-title b { font-size: 15px; }
.rs-title .dim { font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 36ch; }
.rs-modes button { font-weight: 600; }
.rs-saved { font-size: 12px; min-width: 70px; text-align: right; }
.rs-body { flex: 1; min-height: 0; display: flex; }
.rs-strip { width: 168px; flex: none; display: flex; flex-direction: column; border-right: 1px solid var(--border);
  background: var(--surface); min-height: 0; }
.rs-filter { display: flex; flex-wrap: wrap; gap: 4px; padding: 8px; border-bottom: 1px solid var(--border); }
.rs-filter button { font-size: 11.5px; padding: 3px 7px; border-radius: 999px; border: 1px solid var(--border);
  background: var(--surface); color: var(--slate); cursor: pointer; }
.rs-filter button.on { background: var(--ink); border-color: var(--ink); color: var(--surface); }
.rs-filter b { font-variant-numeric: tabular-nums; }
.rs-thumbs { flex: 1; overflow-y: auto; padding: 8px; display: grid; grid-template-columns: 1fr 1fr; gap: 6px; align-content: start; }
.rs-thumb { position: relative; padding: 0; border: 2px solid transparent; border-radius: 8px; overflow: hidden;
  aspect-ratio: 1 / 1; height: auto; background: var(--raise); cursor: pointer; }
.rs-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.rs-thumb.on { border-color: var(--blue); box-shadow: 0 0 0 2px var(--blue-light); }
.rs-thumb.in::after { content: ''; position: absolute; inset: 0; box-shadow: inset 0 0 0 2px var(--green); border-radius: 6px; pointer-events: none; }
.rs-n { position: absolute; left: 4px; top: 4px; font-size: 10.5px; font-weight: 700; color: #fff;
  background: rgba(15, 28, 46, .7); border-radius: 4px; padding: 0 4px; }
.rs-in { position: absolute; right: 3px; top: 3px; color: #fff; background: var(--green); border-radius: 50%;
  width: 16px; height: 16px; display: grid; place-items: center; }
.rs-count { position: absolute; right: 4px; bottom: 4px; font-size: 10.5px; font-weight: 700; color: #fff;
  background: #E5484D; border-radius: 999px; padding: 0 6px; }
.rs-seen { position: absolute; left: 5px; bottom: 5px; width: 7px; height: 7px; border-radius: 50%; background: #fff;
  box-shadow: 0 0 0 1.5px rgba(15, 28, 46, .55); }
.rs-add { margin: 8px; }
.rs-main { flex: 1; min-width: 0; display: flex; flex-direction: column; background: #0d1117; }
.rs-main.rs-empty { background: var(--canvas); align-items: center; justify-content: center; }
.rs-empty-in { max-width: 460px; width: 100%; padding: 24px 16px; }
/* The three ways in: camera, already in the Stack, this device. */
.rs-ways { display: flex; flex-direction: column; gap: 8px; }
.rs-way { display: flex; align-items: center; gap: 12px; width: 100%; text-align: left; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); color: var(--ink); cursor: pointer; }
.rs-way:hover, .rs-way:focus-visible { border-color: var(--blue); background: var(--blue-light); }
.rs-way > svg { flex: none; color: var(--blue); }
.rs-way span { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rs-way b { font-size: 14px; }
.rs-way small { font-size: 12.5px; color: var(--slate); }
.rs.rs-drop::after { content: 'Drop the photos to add them to the report'; position: absolute; inset: 10px; z-index: 5;
  display: flex; align-items: center; justify-content: center; border: 3px dashed var(--blue); border-radius: 14px;
  background: rgba(43, 108, 176, .12); color: var(--blue); font-weight: 700; font-size: 16px; pointer-events: none; }
/* This job's photos, ticked into the report. */
.rs-pk { max-height: min(62vh, 620px); overflow-y: auto; margin-top: 8px; }
.rs-pk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 6px; }
.rs-pk-ph { position: relative; aspect-ratio: 1 / 1; padding: 0; border: 2px solid transparent; border-radius: 8px;
  overflow: hidden; background: var(--canvas); cursor: pointer; }
.rs-pk-ph img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.rs-pk-ph.on { border-color: var(--blue); box-shadow: 0 0 0 2px var(--blue-light); }
.rs-pk-tick { position: absolute; right: 4px; top: 4px; width: 20px; height: 20px; border-radius: 50%; display: none;
  align-items: center; justify-content: center; background: var(--blue); color: #fff; }
.rs-pk-ph.on .rs-pk-tick { display: flex; }
/* One row that scrolls sideways: a toolbar that wraps eats the photo. */
.rs-tools { display: flex; flex-wrap: nowrap; overflow-x: auto; align-items: center; gap: 4px; padding: 6px 8px;
  background: #161b22; scrollbar-width: thin; flex: none; }
.rs-tools > * { flex: none; }
.rs-tool { border: 1px solid #30363d; background: #21262d; color: #e6edf3; border-radius: 7px; padding: 4px 8px;
  font-size: 12.5px; cursor: pointer; display: inline-flex; align-items: center; gap: 5px; line-height: 1.3; }
.rs-tool:hover { border-color: #8b949e; }
.rs-tool.on { background: #e6edf3; color: #0d1117; border-color: #e6edf3; }
.rs-type i { width: 10px; height: 10px; border-radius: 50%; background: var(--c); box-shadow: 0 0 0 1.5px #fff; }
.rs-type.on { background: var(--c); border-color: var(--c); color: #fff; }
.rs-type.on i { box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .9); background: #fff; }
.rs-sep { width: 1px; height: 22px; background: #30363d; margin: 0 4px; }
.rs-zoom { color: #c9d1d9; font-size: 12px; min-width: 42px; text-align: center; font-variant-numeric: tabular-nums; }
.rs-stage { position: relative; flex: 1; min-height: 0; overflow: hidden; touch-action: none; cursor: crosshair; user-select: none; }
.rs-view { position: absolute; left: 0; top: 0; transform-origin: 0 0; }
.rs-view img { display: block; width: 100%; height: 100%; pointer-events: none; }
.rs-view svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.rs-hint { position: absolute; left: 50%; bottom: 10px; transform: translateX(-50%); background: rgba(13, 17, 23, .78);
  color: #e6edf3; font-size: 12px; padding: 4px 10px; border-radius: 999px; pointer-events: none; white-space: nowrap; max-width: 92%;
  overflow: hidden; text-overflow: ellipsis; }
.rs-nav { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 10px; background: #161b22; color: #c9d1d9; }
.rs-side { width: 340px; flex: none; overflow-y: auto; padding: 12px 14px 20px; background: var(--surface); border-left: 1px solid var(--border); }
.rs-side .field { margin: 10px 0 0; }
.rs-side textarea { resize: vertical; }
.rs-side .btn.on { color: var(--amber); }
.rs-switch { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; font-size: 13.5px; cursor: pointer; }
.rs-switch input { width: 18px; height: 18px; accent-color: var(--green); }
.rs-counts { display: grid; grid-template-columns: 1fr; gap: 4px; }
.rs-countrow { display: flex; align-items: center; gap: 6px; padding: 3px 4px; border-radius: 8px; border: 1px solid var(--border); }
.rs-countrow.on { border-color: var(--c); background: color-mix(in srgb, var(--c) 9%, transparent); }
.rs-countrow b { min-width: 24px; text-align: center; font-variant-numeric: tabular-nums; }
.rs-pick { flex: 1; text-align: left; background: none; border: 0; padding: 3px 4px; font-size: 13px; color: var(--ink);
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer; border-radius: 6px; }
.rs-pick i { width: 11px; height: 11px; border-radius: 50%; background: var(--c); flex: none; }
.rs-pick.on { font-weight: 700; }
.rs-step { width: 26px; height: 26px; border-radius: 6px; border: 1px solid var(--border); background: var(--surface); color: var(--ink); cursor: pointer; }
.rs-ai { margin: 12px 0 6px; padding: 10px 12px; border-radius: var(--radius); background: var(--blue-light);
  border: 1px solid #2B6CB022; display: flex; flex-direction: column; gap: 7px; }
.rs-ai-h { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--blue); }
.rs-ai-st { margin: 0; font-size: 12.5px; line-height: 1.4; color: var(--slate); }
.rs-ai textarea { font-size: 13px; resize: vertical; min-height: 44px; }
.rs-ai > .btn { align-self: flex-start; }
.rs-marking { align-self: flex-start; }
.rs-grade { margin: 0 0 18px; padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
.rs-grade-why { margin: 8px 0; font-size: 12.5px; line-height: 1.45; color: var(--slate); }
.rs-letters { display: flex; flex-wrap: wrap; gap: 6px; }
.rs-letter { display: flex; flex-direction: column; align-items: center; min-width: 64px; padding: 6px 8px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--canvas); color: var(--ink); cursor: pointer; }
.rs-letter b { font-size: 18px; line-height: 1.1; }
.rs-letter span { font-size: 11px; color: var(--slate); }
.rs-letter.on { background: var(--blue); border-color: var(--blue); color: #fff; }
.rs-letter.on span { color: #fff; }
.rs-gtable { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.rs-grow { display: grid; grid-template-columns: minmax(120px, 1.1fr) 150px 10px 2fr; gap: 8px; align-items: center; font-size: 12.5px; }
.rs-grow select, .rs-grow input { font-size: 12.5px; }
.rs-gdot { width: 10px; height: 10px; border-radius: 50%; background: var(--slate); }
.rs-gdot.ok { background: #2f9a5b; } .rs-gdot.warn { background: #d39a1c; } .rs-gdot.bad { background: #c9452e; }
@media (max-width: 700px) { .rs-grow { grid-template-columns: 1fr 140px 10px; } .rs-grow input { grid-column: 1 / -1; } }
.rs-marking button { font-size: 12px; padding: 4px 10px; }
.rs-spin { display: inline-block; width: 11px; height: 11px; border-radius: 50%; border: 2px solid currentColor;
  border-right-color: transparent; vertical-align: -1px; animation: rs-spin .8s linear infinite; }
@keyframes rs-spin { to { transform: rotate(360deg); } }
.rs-thumb.wait::before { content: ''; position: absolute; inset: 0; z-index: 1; border-radius: 6px; pointer-events: none;
  background: linear-gradient(100deg, transparent 30%, rgba(255, 255, 255, .45) 50%, transparent 70%) 0 0 / 250% 100%;
  animation: rs-sheen 1.3s linear infinite; }
@keyframes rs-sheen { from { background-position: 100% 0; } to { background-position: -150% 0; } }
@media (prefers-reduced-motion: reduce) { .rs-spin, .rs-thumb.wait::before { animation: none; } }
.rs-tell > span { display: inline-flex; align-items: center; gap: 6px; color: var(--blue); }
.rs-warn { color: var(--amber); font-size: 12px; font-weight: 600; }
.rs-write { flex: 1; overflow-y: auto; display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(280px, 1fr); gap: 18px; padding: 16px 18px 40px; }
.rs-col { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 14px 16px; align-self: start; }
.rs-col h3 { font-size: 14.5px; margin: 0 0 8px; }
.rs-col textarea { width: 100%; resize: vertical; }
.rs-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 12px; }
.rs-grid2 .field { margin: 0; }
.rs-findings { display: flex; flex-direction: column; gap: 6px; }
.rs-frow { display: grid; grid-template-columns: 22px 150px 1fr 1fr 32px; gap: 6px; align-items: start; }
.rs-fn { font-weight: 700; color: var(--slate); padding-top: 8px; text-align: center; }
.rs-order { position: sticky; top: 0; }
.rs-orow { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 6px 0; border-top: 1px solid var(--border); }
.rs-orow img { width: 52px; height: 40px; object-fit: cover; border-radius: 6px; flex: none; }
.rs-ot { flex: 1 1 150px; min-width: 0; display: flex; flex-direction: column; font-size: 12.5px; }
.rs-obtns { display: flex; gap: 2px; margin-left: auto; }
.rs-ot b { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rs-ot .dim { font-size: 11.5px; }
.rs-orow .btn.on { color: var(--amber); }
@media (max-width: 1100px) {
  .rs-side { width: 290px; }
  .rs-strip { width: 132px; }
  .rs-thumbs { grid-template-columns: 1fr; }
}
@media (max-width: 820px) {
  .rs-body { flex-direction: column; overflow-y: auto; }
  .rs-strip { width: auto; border-right: 0; border-bottom: 1px solid var(--border); flex: none; }
  .rs-thumbs { display: flex; overflow-x: auto; overflow-y: hidden; padding: 6px 8px; }
  .rs-thumb { width: 64px; flex: none; }
  .rs-add { margin: 0 8px 8px; }
  .rs-main { flex: none; height: 62vh; }
  .rs-side { width: auto; border-left: 0; }
  .rs-write { grid-template-columns: 1fr; padding: 10px 10px 40px; }
  .rs-frow { grid-template-columns: 22px 1fr 32px; }
  .rs-frow textarea { grid-column: 2 / 3; }
  .rs-grid2 { grid-template-columns: 1fr; }
  .rs-title .dim { max-width: 22ch; }
  .rs-type span { display: none; }
}

/* ------------------------------------------------------------ the job board
   Eric Roper: "the board to me has less noise to it and easier to comprehend."
   Calm is the requirement here. One quiet row of filters, and a card that is
   a name, a place and one muted line. The only color on a card is the amber
   aging cue. */
.jb-bar { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
#main > .jb-bar, .main .jb-bar { position: relative; z-index: 10; }
.jb-bar .seg button { padding: 5px 12px; font-size: 13px; }
.jb-search {
  flex: 0 1 240px; min-width: 0; height: 32px; padding: 0 10px; font: inherit; font-size: 13px;
  color: var(--ink); background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
}
.jb-filter-wrap { position: relative; }
.jb-pop {
  position: absolute; left: 0; top: calc(100% + 6px); z-index: 40; width: 270px; padding: 12px;
  display: grid; gap: 10px; background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: var(--shadow-pop); font-size: 13px;
}
.jb-pop[hidden] { display: none; }
.jb-pop label { display: grid; gap: 4px; color: var(--slate); }
.jb-pop label.jb-check { display: flex; align-items: center; gap: 8px; color: var(--ink); }
.jb-pop select { width: 100%; }
.jb-pop .jb-note { margin: 0; font-size: 12px; color: var(--slate); }

.jb-scroll { overflow: auto; height: calc(100dvh - var(--jb-top, 220px) - 16px); min-height: 380px; }
.board.jb {
  display: flex; gap: 12px; width: max-content; min-width: 100%; min-height: 100%;
  align-items: stretch; overflow: visible; scroll-snap-type: none; padding: 0;
}
.jb .board-col { flex: 0 0 264px; display: flex; flex-direction: column; border-radius: 8px; }
.jb .jb-head {
  position: sticky; top: 0; z-index: 3; background: var(--canvas); padding: 2px 2px 8px;
}
.jb .jb-head .col-head { margin-bottom: 0; }
.jb .jb-head .col-head p { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.jb .jb-total { font-family: var(--mono); font-size: 11px; color: var(--slate-light); margin-top: 2px; }
.jb .jb-cards { flex: 1 1 auto; }
.jb .col-empty { border: 0; background: none; text-align: left; font-size: 12px; color: var(--slate-light); padding: 6px 2px; }

.jb-card { padding: 9px 11px; box-shadow: none; }
.jb-card:hover { transform: none; box-shadow: none; }
.jb-card .jb-top { display: flex; align-items: baseline; gap: 8px; }
.jb-card .name { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.jb-card .jb-work { flex: 0 0 auto; font-size: 11px; color: var(--slate-light); }
.jb-card .jb-line {
  margin: 2px 0 0; font-size: 12px; color: var(--slate);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.jb-card .jb-line.quiet { font-size: 11px; color: var(--slate-light); }
.jb-card .jb-foot {
  display: flex; align-items: center; gap: 10px; margin-top: 6px; min-height: 22px;
  font-size: 11px; color: var(--slate-light);
}
.jb-card .jb-foot span { display: inline-flex; align-items: center; gap: 3px; white-space: nowrap; }
.jb-card .jb-foot svg { opacity: .7; }
.jb-card.aging .jb-age { color: var(--amber); }
.jb-card .card-adv { border-color: transparent; background: none; color: var(--slate-light); }
.jb-card:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
.jb-more {
  width: 100%; margin: 2px 0 8px; padding: 6px; font: inherit; font-size: 12px; cursor: pointer;
  color: var(--slate); background: none; border: 1px dashed var(--border); border-radius: 8px;
}
@media (max-width: 760px) {
  .jb-bar { flex-wrap: wrap; }
  .jb-search { flex: 1 1 100%; order: 3; }
  .jb-filter-wrap { position: static; }
  .jb-pop { left: 0; right: 0; width: auto; }
  .jb-scroll { height: auto; min-height: 0; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; }
  .board.jb { display: flex; }
  .jb .board-col { flex: 0 0 min(84vw, 320px); scroll-snap-align: start; }
}

/* ---- the job's Tasks card: a real box to tick (Eric Roper, 11/2) */
.task-list { display: grid; }
.task-row {
  display: flex; align-items: flex-start; gap: 10px; padding: 8px 0; cursor: pointer;
  border-top: 1px solid var(--border);
}
.task-row:first-child { border-top: 0; padding-top: 2px; }
.task-row input[type=checkbox] { width: 18px; height: 18px; margin: 1px 0 0; flex: 0 0 auto; }
.task-text { display: grid; gap: 1px; min-width: 0; }
.task-title { font-size: 13.5px; color: var(--ink); overflow-wrap: anywhere; }
.task-meta { font-size: 12px; color: var(--slate-light); }
.task-meta.late { color: var(--red); }
.task-row.done .task-title { text-decoration: line-through; color: var(--slate-light); }
.task-row.done .task-meta { color: var(--slate-light); }

/* ---- board: snap off while a card is held (the edge scroll would fight it),
   and the "Move to" menu (right-click, long press, M on a focused card) */
.board-dragging, .board-dragging .jb-scroll, .board-dragging .board { scroll-snap-type: none !important; }
.lead-card { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
.move-menu {
  position: fixed; z-index: 1200; min-width: 200px; max-width: 280px;
  max-height: min(70vh, 460px); overflow-y: auto; padding: 6px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: var(--shadow-pop); font-size: 13px;
}
.move-menu .move-head { margin: 4px 8px 6px; font-size: 11px; color: var(--slate-light); }
.move-menu button {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 10px;
  font: inherit; color: var(--ink); text-align: left; background: none; border: 0;
  border-radius: 6px; cursor: pointer;
}
.move-menu button:hover:not([disabled]), .move-menu button:focus-visible { background: var(--canvas); outline: none; }
.move-menu button[disabled] { color: var(--slate-light); cursor: default; }
.move-menu .move-here { margin-left: auto; font-size: 11px; }
@media (max-width: 760px) {
  .move-menu { left: 8px !important; right: 8px; top: auto !important; bottom: 8px; max-width: none; }
  .move-menu button { padding: 11px 12px; font-size: 14px; }
}

/* ---- New estimate: what kind (Eric Roper, 11/2) */
.est-kinds { display: grid; gap: 6px; max-height: 60vh; overflow-y: auto; }
.est-kind {
  display: flex; align-items: flex-start; gap: 10px; padding: 9px 11px; cursor: pointer;
  border: 1px solid var(--border); border-radius: 8px; font-size: 13px;
}
.est-kind input { width: auto; margin-top: 3px; }
.est-kind > span { flex: 1; min-width: 0; }
.est-kind:has(input:checked) { border-color: var(--blue); }

/* ⭐ THE iOS APP (2026-11-05, js/native.js). The no-signal bar sits above
   the home indicator and the phone tab bar, says what still works, and
   goes away by itself when the signal comes back. */
.native-offline {
  position: fixed; left: 10px; right: 10px; z-index: 400;
  bottom: calc(92px + env(safe-area-inset-bottom, 0px));
  padding: 10px 14px; border-radius: 12px;
  background: #3B2A07; color: #FFE9B8; border: 1px solid #8A6418;
  font-size: 13px; line-height: 1.4; box-shadow: 0 8px 24px rgba(0, 0, 0, .25);
}
/* An app does not rubber band its whole page past the top bar, and a long
   press on a button should not offer to copy its words. */
html.ios-app, html.ios-app body { overscroll-behavior-y: none; }
html.ios-app .btn, html.ios-app button, html.ios-app .tab { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }

/* ==== HOME, THE NEW LOOK (Stephen, 11/6, the approved mock) ==============
   One rounded card: the layout's shade as a dark band (dashlook.js SHADES,
   passed in as --dz-band / --dz-soft / --dz-accent), the stage rings over its
   bottom edge, tiles and activity, then the leaderboard as bars. Light and
   dark both read through the app's own tokens; the band is dark in both. */
body[data-route="dashboard"] .main { background: var(--surface); }
.dz { --dz-red: #d92d20; --dz-line: var(--border); max-width: 1240px; margin: 0 auto; }
:root[data-theme="dark"] .dz { --dz-red: #f97066; }
.dz-card { background: var(--surface); border: 1px solid var(--dz-line); border-radius: 18px; overflow: hidden; margin-bottom: 22px; }
.dz-band { background: var(--dz-band); color: #fff; padding: 24px 28px 64px; }
.dz-soft { color: var(--dz-soft); font-size: 14px; }
.dz-band-top { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; margin-bottom: 20px; }
.dz-hello { min-width: 0; flex: 1; }
.dz-hello p { margin: 0 0 2px; font-size: 13px; }
.dz-hello h1 { margin: 0; color: #fff; font-size: 24px; font-weight: 650; letter-spacing: -.01em; }
.dz-band-acts { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.dz-chip, .dz-setup { display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 12px;
  border: 1px solid rgba(255, 255, 255, .25); border-radius: 9px; background: transparent;
  color: var(--dz-soft); font: inherit; font-size: 13.5px; text-decoration: none; cursor: pointer; }
.dz-chip:hover, .dz-setup:hover { background: rgba(255, 255, 255, .08); color: #fff; }
.dz-chip:focus-visible, .dz-setup:focus-visible, .dz-num:focus-visible { outline: 2px solid #c3d3de; outline-offset: 2px; }
.dz-period select { background: transparent; border: 0; color: inherit; font: inherit; padding: 0 2px; height: 32px; width: auto; cursor: pointer; box-shadow: none; }
.dz-period select option { color: var(--ink); background: var(--surface); }
.dz-setup-ring { width: 16px; height: 16px; border-radius: 50%;
  background: conic-gradient(#c3d3de calc(var(--p) * 1%), rgba(255, 255, 255, .22) 0); }
.dz-nums { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.dz-num { display: flex; flex-direction: column; gap: 2px; min-width: 0; color: #fff; text-decoration: none;
  border-radius: 10px; padding: 6px 8px; margin: -6px -8px; }
.dz-num:hover { background: rgba(255, 255, 255, .06); }
.dz-big { font-size: 32px; font-weight: 700; letter-spacing: -.02em; line-height: 1.15; font-variant-numeric: tabular-nums; }
.dz-num.over .dz-big { color: #fda29b; }
.dz-sub { font-size: 13px; color: var(--dz-soft); }
.dz-delta.up { color: #c3d3de; }
.dz-delta.down { color: #fda29b; }
.dz-trend { display: block; width: 100%; max-width: 140px; height: 22px; margin-top: 4px; color: var(--dz-soft); opacity: .8; }

/* The rings over the band's bottom edge, joined by one thin line. */
.dz-stages { position: relative; margin-top: -44px; padding: 0 24px 18px;
  display: grid; grid-template-columns: repeat(var(--dz-n, 7), minmax(0, 1fr)); }
.dz-rail { position: absolute; top: 36px; height: 2px; background: var(--dz-line);
  left: calc(24px + (100% - 48px) / var(--dz-n, 7) / 2); right: calc(24px + (100% - 48px) / var(--dz-n, 7) / 2); }
.dz-stage { position: relative; display: flex; flex-direction: column; align-items: center; gap: 0;
  background: none; border: 0; padding: 0 2px; font: inherit; color: var(--ink); cursor: pointer; min-width: 0; }
.dz-ring { width: 72px; height: 72px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  background: conic-gradient(var(--c) calc(var(--p) * 1%), var(--dz-line) 0); margin-bottom: 8px; transition: transform .15s; }
.dz-ring-in { width: 62px; height: 62px; border-radius: 50%; background: var(--surface); display: flex; align-items: center; justify-content: center; }
.dz-stage:hover .dz-ring { transform: translateY(-2px); }
.dz-stage:focus-visible .dz-ring { outline: 2px solid var(--blue); outline-offset: 3px; }
.dz-stage-n { font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; }
.dz-stage-l { font-size: 13px; color: var(--slate); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The soft square with the solid dot: the one icon shape. */
.dz-ic { position: relative; display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: var(--sz); height: var(--sz); border-radius: calc(var(--sz) * .32); background: var(--t); color: var(--c); }
.dz-ic::after { content: ''; position: absolute; top: calc(var(--sz) * -.07); right: calc(var(--sz) * -.07);
  width: calc(var(--sz) * .3); height: calc(var(--sz) * .3); border-radius: 50%; background: var(--c);
  border: 2px solid var(--surface); box-sizing: border-box; }

.dz-mid { display: grid; grid-template-columns: 1.3fr 1fr; gap: 16px; padding: 4px 24px 16px; align-items: start; }
.dz-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-content: start; }
.dz-tile { display: flex; align-items: center; gap: 14px; padding: 14px; border: 1px solid var(--dz-line);
  border-radius: 14px; background: var(--surface); color: var(--ink); font: inherit; text-align: left;
  text-decoration: none; cursor: pointer; min-width: 0; }
.dz-tile:hover { border-color: var(--slate-light); }
.dz-tile:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.dz-tile > span { min-width: 0; }
.dz-tile-n { display: block; font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; }
.dz-tile-l { display: block; font-size: 13px; color: var(--slate); margin-top: 2px; }
.dz-tile.zero .dz-tile-n { color: var(--slate-light); }
.dz-panel { border: 1px solid var(--dz-line); border-radius: 14px; padding: 14px; background: var(--surface); min-width: 0; }
.dz-panel-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.dz-panel-head h3 { margin: 0; font-size: 16px; display: flex; align-items: center; gap: 10px; }
.dz-link { background: none; border: 0; padding: 0; font: inherit; font-size: 13px; color: var(--blue); cursor: pointer; }
.dz-act { display: flex; align-items: center; gap: 10px; width: 100%; margin-top: 10px; padding: 3px 0;
  background: none; border: 0; font: inherit; font-size: 14px; color: var(--ink); text-align: left; cursor: pointer; }
.dz-act:hover .dz-act-b { text-decoration: underline; }
.dz-act-b { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dz-act-t { font-size: 13px; color: var(--slate); flex: none; }
.dz-lb { margin: 0 24px 24px; }
.dz-seg { display: inline-flex; gap: 2px; font-size: 13px; }
.dz-seg button { background: none; border: 0; padding: 4px 8px; border-radius: 7px; font: inherit; color: var(--slate); cursor: pointer; }
.dz-seg button.on { color: var(--blue); font-weight: 700; }
.dz-seg button + button::before { content: ''; }
.dz-bar { display: grid; grid-template-columns: 22px 34px minmax(90px, 160px) 1fr 76px; align-items: center; gap: 14px;
  width: 100%; padding: 7px 4px; background: none; border: 0; border-radius: 10px; font: inherit; color: var(--ink);
  text-align: left; cursor: pointer; }
.dz-bar:hover:not(:disabled) { background: var(--raise); }
.dz-bar:disabled { cursor: default; }
.dz-bar.me { background: var(--raise); }
.dz-rank { text-align: center; font-size: 16px; color: var(--slate-light); }
.dz-rank.gold { color: #e9a93a; } .dz-rank.silver { color: #98a2b3; } .dz-rank.bronze { color: #c4772e; }
.dz-av { width: 34px; height: 34px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700; background: var(--raise); color: var(--ink); }
.dz-av.lead { background: var(--blue); color: var(--on-accent, #fff); }
.dz-who { font-size: 14px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dz-who-n { display: block; font-size: 12px; color: var(--slate); }
.dz-track { height: 16px; border-radius: 999px; background: var(--raise); overflow: hidden; }
.dz-track i { display: block; height: 100%; border-radius: 999px; background: var(--blue); opacity: .38; }
.dz-track i.lead { opacity: 1; }
.dz-amt { font-size: 15px; text-align: right; font-variant-numeric: tabular-nums; }
.dz-more .card { border-radius: 14px; }
.dz-more .fold { border-radius: 14px; }
.dz-flash { outline: 2px solid var(--blue); outline-offset: 4px; border-radius: 14px; transition: outline-color .4s; }
.jb-focus { outline: 2px solid var(--blue); outline-offset: -2px; border-radius: 12px; }
.shade-tiles { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 8px; }
.shade-tile { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; padding: 8px; width: 132px;
  border: 1px solid var(--border); border-radius: 12px; background: var(--surface); font: inherit; font-size: 13px; color: var(--ink); cursor: pointer; }
.shade-tile.on { border-color: var(--blue); box-shadow: 0 0 0 2px var(--b100); }
.shade-sw { display: flex; align-items: flex-end; gap: 6px; width: 100%; height: 40px; border-radius: 8px; padding: 7px; box-sizing: border-box; }
.shade-sw i { width: 22px; height: 8px; border-radius: 4px; }
.shade-sw i:last-child { width: 14px; height: 14px; border-radius: 50%; margin-left: auto; }

@media (max-width: 900px) {
  .dz-mid { grid-template-columns: 1fr; }
}
@media (max-width: 760px) {
  .dz-card { border-radius: 14px; }
  .dz-band { padding: 18px 16px 56px; }
  .dz-hello h1 { font-size: 20px; }
  .dz-nums { grid-template-columns: 1fr 1fr; gap: 14px 12px; }
  .dz-big { font-size: 24px; }
  .dz-stages { display: flex; overflow-x: auto; gap: 4px; padding: 0 12px 14px; scrollbar-width: none; }
  .dz-stages::-webkit-scrollbar { display: none; }
  .dz-stage { flex: 0 0 76px; }
  .dz-rail { left: 50px; right: 50px; }
  .dz-mid { padding: 4px 12px 12px; }
  .dz-tiles { grid-template-columns: 1fr 1fr; gap: 8px; }
  .dz-tile { padding: 10px; gap: 10px; }
  .dz-lb { margin: 0 12px 14px; }
  .dz-bar { grid-template-columns: 18px 30px minmax(0, 1fr) 64px; gap: 8px; }
  .dz-bar .dz-track { grid-column: 2 / 5; grid-row: 2; height: 10px; }
  .dz-av { width: 30px; height: 30px; }
}

/* Sidebar wears the same look (Stephen, 11/6): white column, bold line
   icons, the shade's accent on the item you are on. */
@media (min-width: 761px) {
  :root[data-layout="sidebar"] .sidenav { padding: 14px 12px; }
  :root[data-layout="sidebar"] .sidenav svg { stroke-width: 2.1; }
  :root[data-layout="sidebar"] .sn-link { border-radius: 10px; padding: 8px 10px; font-weight: 500; color: var(--slate); }
  :root[data-layout="sidebar"] .sn-link:hover { color: var(--ink); }
  :root[data-layout="sidebar"] .sn-link.on { background: var(--b50); color: var(--b800); font-weight: 650;
    box-shadow: inset 3px 0 0 var(--blue); }
}

/* ==== THE LOOK, APP WIDE (Stephen, 11/6: "every page needs to have the same
   style and feel. Even settings") ==========================================
   One layer over the shared components, CSS only, so no page's markup or
   handlers change: a white page, flat white cards with a hairline border and
   14px corners, calmer controls, and the bold line icon in a soft square with
   a dot wherever a heading carries one. The accent is the layout's shade
   (dashlook.js applyAppLook writes it into --blue and its ladder). Light and
   dark both come from the same tokens; customer pages do not load this. */
:root {
  --radius: 14px;
  --radius-sm: 9px;
  --border: #eaecf0;
  --line: #eaecf0;
  --canvas: #f6f7f9;
  --ink: #101828;
  --raise: #f2f4f7;
  --shadow: none;
}
:root[data-theme="dark"] {
  --border: #283449;
  --line: #283449;
  --canvas: #111a27;
  --ink: #E8EDF5;
  --raise: #1F2A3C;
  --shadow: none;
}
body, .main { background: var(--surface); }
body[data-route="dashboard"] .main, body[data-route="week"] .main { background: var(--surface); }
.card { border-radius: var(--radius); padding: 16px 18px; box-shadow: none; }
.card-head { margin-bottom: 12px; gap: 10px; }
.card-head h3 { font-size: 16px; font-weight: 650; }
.page-head h1 { font-size: 24px; font-weight: 650; letter-spacing: -.01em; }
.page-head p { font-size: 13px; }
.fold { border-radius: var(--radius); }
.modal { border-radius: 16px; border: 1px solid var(--border); }
.btn { border-radius: var(--radius-sm); padding: 8px 14px; font-weight: 500; }
.btn.sm { padding: 5px 10px; border-radius: 8px; }
.btn.big { padding: 12px 18px; }
.seg { border-radius: 10px; }
.seg button { border-radius: 8px; }
input, select, textarea { border-radius: var(--radius-sm); }
.chip { border-radius: 6px; }
.badge { border-radius: 6px; }
table.data th { font-size: 12.5px; font-weight: 600; color: var(--slate); }
table.data td { padding: 10px 0; }
.list-row { padding: 10px 0; }
.lead-card { border-radius: 12px; }
.empty { border-radius: var(--radius); }

/* The bold line icon in a soft square, a solid dot at its corner, beside
   any card or page heading that has one. Drawn on the icon's own box, so it
   keeps the color the heading already gave it (currentColor). */
.main .card-head > svg:first-child,
.modal .card-head > svg:first-child {
  box-sizing: content-box; flex: none; padding: 7px; border-radius: 9px;
  stroke-width: 2.1;
  color: var(--blue);
  background:
    radial-gradient(circle at calc(100% - 4px) 4px, currentColor 0 3px, var(--surface) 3.4px 4.6px, transparent 5px),
    color-mix(in srgb, currentColor 12%, transparent);
}
.main .card-head > svg.orange:first-child { color: var(--orange); }
.main .card-head > svg.green:first-child { color: var(--green); }
.main .card-head > svg.red:first-child { color: var(--red); }
.main .card-head > svg.amber:first-child { color: var(--amber); }
.main .page-head svg, .main .btn svg, .main .seg svg { stroke-width: 2; }

/* ==== THE CUSTOMER FILE (Stephen, 11/6, the approved job mock) ==========
   The shade's band as the header: initials, name, chips, Call / Text / Email
   and the stage buttons translucent on the band, the next stage in the
   accent, four figures, and the tabs sitting on the band's bottom edge with
   the open one white. */
.jh { background: var(--jh-band); color: #fff; border-radius: 18px 18px 0 0; padding: 20px 26px 0; margin-top: 4px; }
.jh-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.jh-who { display: flex; gap: 16px; align-items: center; min-width: 0; flex: 1 1 420px; }
.jh-ini { width: 60px; height: 60px; border-radius: 16px; background: var(--blue); color: var(--on-accent, #fff); flex: none;
  font-size: 22px; font-weight: 700; display: flex; align-items: center; justify-content: center; }
.jh-id { min-width: 0; }
.jh-id h1 { margin: 0; color: #fff; font-size: 26px; font-weight: 700; letter-spacing: -.01em; overflow-wrap: anywhere; }
.jh-sub { margin: 3px 0 0; color: var(--jh-soft); font-size: 14px; }
.jh-chips { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; align-items: center; }
.jh-chip { display: inline-flex; align-items: center; gap: 6px; border-radius: 999px; padding: 4px 11px;
  font-size: 12px; font-weight: 600; background: rgba(255, 255, 255, .12); color: #fff; }
.jh-chip.on { background: var(--blue); color: var(--on-accent, #fff); }
.jh-chip.late { background: rgba(253, 162, 155, .22); color: #ffd6d2; }
.jh-chips .badge { background: #fff; }
.jh-unv { color: var(--jh-soft); font-size: 13px; }
.jh-acts, .jh-more { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.jh-more { margin-top: 12px; }
.jh-note { color: var(--jh-soft); font-size: 12.5px; }
.jh-btn { height: 38px; display: inline-flex; align-items: center; gap: 8px; padding: 0 13px; border-radius: 9px;
  border: 1px solid rgba(255, 255, 255, .22); background: rgba(255, 255, 255, .1); color: #fff;
  font: inherit; font-size: 14px; white-space: nowrap; text-decoration: none; cursor: pointer; }
.jh-btn:hover { background: rgba(255, 255, 255, .18); }
.jh-btn:focus-visible, .jh-tab:focus-visible, .jh-fig:focus-visible { outline: 2px solid #c3d3de; outline-offset: 2px; }
.jh-btn svg { stroke-width: 2.1; }
.jh-btn.go { background: var(--blue); border-color: var(--blue); color: var(--on-accent, #fff); font-weight: 650; }
.jh-btn.go:hover { filter: brightness(1.06); }
.jh-btn.blocked { border-style: dashed; color: #ffd8a8; }
.jh-btn.quiet { height: 32px; font-size: 13px; background: transparent; }
.jh-figs { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; margin-top: 20px; }
.jh-fig { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; min-width: 0; text-align: left;
  background: none; border: 0; padding: 6px 8px; margin: -6px -8px; border-radius: 10px; color: #fff; font: inherit; cursor: pointer; }
.jh-fig:hover:not(:disabled) { background: rgba(255, 255, 255, .06); }
.jh-fig:disabled { cursor: default; }
.jh-fig-l { color: var(--jh-soft); font-size: 13px; }
.jh-fig-v { font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jh-fig-v.small { font-size: 16px; font-weight: 600; margin-top: 4px; }
.jh-tabs { display: flex; gap: 4px; margin-top: 18px; overflow-x: auto; scrollbar-width: none; }
.jh-tabs::-webkit-scrollbar { display: none; }
.jh-tab { flex: none; display: inline-flex; align-items: center; gap: 6px; padding: 11px 14px; border: 0;
  border-radius: 10px 10px 0 0; background: transparent; color: var(--jh-soft); font: inherit; font-size: 14px; cursor: pointer; white-space: nowrap; }
.jh-tab:hover { color: #fff; }
.jh-tab.on { background: var(--surface); color: var(--ink); font-weight: 650; }
.jh-tab em { font-style: normal; font-size: 11px; background: rgba(255, 255, 255, .14); border-radius: 999px; padding: 1px 7px; }
.jh-tab.on em { background: var(--raise); color: var(--slate); }
.jh-tab em.zero { display: none; }
.jh + .sale-banner, .jh ~ .jh-tools { margin-top: 12px; }
.jh-tools { gap: 8px; }
#tabBody { margin-top: 18px; }

/* Overview: two columns over the cards it always had. */
.jo-top { display: grid; grid-template-columns: 1.55fr 1fr; gap: 20px; align-items: start; margin-bottom: 16px; }
.jo-left > .card + .card, .jo-right > .card + .card { margin-top: 16px; }
.jw-steps { list-style: none; margin: 4px 0 2px; padding: 0; display: grid; grid-template-columns: repeat(var(--n), minmax(0, 1fr)); }
.jw-step { position: relative; text-align: center; font-size: 12px; color: var(--slate); }
.jw-step::before { content: ''; position: absolute; top: 10px; left: 50%; width: 100%; height: 2px; background: var(--border); }
.jw-step:last-child::before { display: none; }
.jw-step.done::before { background: var(--blue); }
.jw-dot { position: relative; z-index: 1; width: 22px; height: 22px; margin: 0 auto 5px; border-radius: 50%;
  border: 2px solid var(--border); background: var(--surface); display: flex; align-items: center; justify-content: center; box-sizing: border-box; }
.jw-step.done .jw-dot { background: var(--blue); border-color: var(--blue); color: var(--on-accent, #fff); }
.jw-step.done .jw-dot svg { stroke-width: 2.6; }
.jw-step.done .jw-dot svg path:first-child { display: none; }
.jw-step.now .jw-dot { border-color: var(--blue); box-shadow: 0 0 0 4px var(--b100); }
.jw-step.now { color: var(--ink); font-weight: 700; }
.jw-l { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 2px; }
.jl-row { display: flex; gap: 12px; align-items: flex-start; padding: 10px 0; border-top: 1px solid var(--border); }
.jl-row:first-of-type { border-top: 0; }
.jl-b { font-weight: 600; font-size: 13.5px; display: block; overflow-wrap: anywhere; }
.jp-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.jp-cell { position: relative; aspect-ratio: 1; border-radius: 8px; overflow: hidden; border: 0; padding: 0; background: var(--raise); cursor: pointer; }
.jp-cell img { width: 100%; height: 100%; object-fit: cover; display: block; }
.jp-cell span { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: rgba(16, 24, 40, .45); color: #fff; font-weight: 600; }
.card-head > .dz-ic { flex: none; }

@media (max-width: 900px) {
  .jo-top { grid-template-columns: 1fr; }
}
@media (max-width: 760px) {
  .jh { padding: 16px 14px 0; border-radius: 14px 14px 0 0; }
  .jh-who { flex-basis: 100%; gap: 12px; }
  .jh-ini { width: 48px; height: 48px; font-size: 18px; border-radius: 13px; }
  .jh-id h1 { font-size: 21px; }
  .jh-acts { width: 100%; }
  .jh-acts .jh-btn { flex: 1 1 auto; justify-content: center; }
  .jh-figs { grid-template-columns: 1fr 1fr; gap: 12px; }
  .jh-fig-v { font-size: 18px; }
  .jw-l { font-size: 11px; }
}
.jh-tools { margin: 10px 0 12px; justify-content: flex-end; }
.jh-body { margin-top: 0 !important; border: 1px solid var(--border); border-top: 0; border-radius: 0 0 18px 18px;
  padding: 22px 26px; background: var(--surface); }
@media (max-width: 760px) { .jh-body { padding: 14px 12px; border-radius: 0 0 14px 14px; } .jh-tools { justify-content: flex-start; } }
.jh.job-head { display: block; }
/* Dark: lift the band a touch off the dark page so the card still reads. */
:root[data-theme="dark"] .dz-band, :root[data-theme="dark"] .jh {
  background-image: linear-gradient(rgba(255, 255, 255, .05), rgba(255, 255, 255, .05)); }

/* ==== THE CUSTOMER FILE'S TABS (Stephen, 11/6 tab mocks) =================
   Communications: lenses down the left, the thread as cards, texts as
   bubbles (the customer gray on the left, the team in the accent on the
   right), the log box under it as a segmented control. Estimate: the options
   side by side, the open one ringed in the accent. Photos: a category filter,
   bigger tiles with their drawer and damage marks. Invoices: four sums and a
   thin paid bar. */
.jc { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 18px; align-items: start; margin-top: 16px; }
.jc-lens { display: flex; flex-direction: column; gap: 4px; position: sticky; top: calc(var(--topbar-h) + 60px); }
.jc-lens button { display: flex; justify-content: space-between; align-items: center; padding: 9px 12px; border: 0;
  border-radius: 10px; background: transparent; color: var(--slate); font: inherit; font-size: 14px; cursor: pointer; text-align: left; }
.jc-lens button:hover { background: var(--raise); color: var(--ink); }
.jc-lens button.on { background: color-mix(in srgb, var(--blue) 14%, transparent); color: var(--ink); font-weight: 650; }
.jc-lens em { font-style: normal; font-size: 12.5px; color: var(--slate); }
.jc-main > .card + .card { margin-top: 16px; }
.jc-thread .tl-day { text-align: center; font-size: 12px; color: var(--slate); list-style: none; cursor: pointer; margin: 12px 0 4px; }
.jc-thread .tl-day::-webkit-details-marker { display: none; }
.jc-thread .tl-item { border: 1px solid var(--border); border-radius: 12px; padding: 10px 12px; margin: 10px 0; gap: 12px; align-items: flex-start; }
.jc-thread .tl-item .tl-icon { width: auto; height: auto; background: none; border-radius: 0; }
.jc-thread .tl-body .b { font-size: 14px; font-weight: 600; }
.jc-thread .tl-body .m { font-size: 12.5px; color: var(--slate); }
.jc-thread .tl-item.bubble { border: 0; max-width: 72%; padding: 11px 14px; border-radius: 14px; }
.jc-thread .tl-item.bubble .tl-icon { display: none; }
.jc-thread .tl-item.bubble .tl-body .b { font-weight: 400; line-height: 1.45; }
.jc-thread .tl-item.bubble.in { background: var(--raise); }
.jc-thread .tl-item.bubble.out { background: var(--blue); color: var(--on-accent, #fff); margin-left: auto; }
.jc-thread .tl-item.bubble.out .tl-body .m { color: inherit; opacity: .8; }
.jc-log .kind-row { display: inline-flex; flex-wrap: wrap; gap: 2px; background: var(--raise); border-radius: 9px; padding: 3px; width: fit-content; }
.jc-log .kind-row .phase { border: 0; background: transparent; border-radius: 7px; padding: 5px 12px; font-size: 13px; color: var(--slate); }
.jc-log .kind-row .phase.on { background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px rgba(0, 0, 0, .08); }
.jc-log .compose textarea { border-radius: 12px; }
.jc-log [data-savelog] { align-self: flex-end; }

@media (min-width: 1100px) {
  .opt-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 14px; align-items: start; }
  .opt-card.editing { grid-column: 1 / -1; }
}
.opt-card { border-radius: 16px; }
.opt-card.on { border: 2px solid var(--blue); box-shadow: 0 0 0 4px color-mix(in srgb, var(--blue) 14%, transparent); }
.opt-price { font-size: 22px; font-weight: 700; }

.ph-filter { width: fit-content; flex-wrap: wrap; margin: 14px 0; gap: 2px; }
.ph-filter button { font-variant-numeric: tabular-nums; }
.file-grid { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }
.file-tile { border-radius: 12px; }
.file-tile img { height: 158px; }
.tile-cat { position: absolute; left: 8px; top: 128px; background: rgba(255, 255, 255, .92); color: #101828;
  border-radius: 999px; padding: 2px 9px; font-size: 11px; font-weight: 600; pointer-events: none; }
.tile-marks { position: absolute; right: 8px; top: 34px; background: #d9577a; color: #fff; border-radius: 999px;
  padding: 2px 8px; font-size: 11px; font-weight: 700; pointer-events: none; }
.file-tile:not(:has(.tile-comments)) .tile-marks { top: 8px; }

.inv-sum { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 14px 28px; margin: 0 0 12px; }
.inv-sum > div { display: flex; flex-direction: column; gap: 2px; }
.inv-sum span { font-size: 13px; color: var(--slate); }
.inv-sum b { font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; }
.inv-sum b.ok { color: var(--green); }
.inv-sum b.owe { color: var(--orange); }
.inv-bar { display: flex; height: 10px; border-radius: 999px; background: var(--raise); overflow: hidden; margin: 0 0 16px; }
.inv-bar i { display: block; height: 100%; background: var(--blue); }
.inv-bar i.soft { opacity: .35; }
.badge.green, .badge.amber, .badge.red, .badge.blue, .badge.slate { border-radius: 999px; padding: 3px 10px; font-family: var(--body); font-weight: 600; }
.badge.green { background: var(--green-light); border-color: transparent; }
.badge.amber { background: var(--amber-light); border-color: transparent; }
.badge.red { background: var(--red-light); border-color: transparent; }
.badge.blue { background: var(--b50); border-color: transparent; }

@media (max-width: 760px) {
  .jc { grid-template-columns: 1fr; }
  .jc-lens { position: static; flex-direction: row; overflow-x: auto; scrollbar-width: none; }
  .jc-lens button { flex: none; gap: 8px; }
  .jc-thread .tl-item.bubble { max-width: 88%; }
  .inv-sum b { font-size: 18px; }
  .file-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
  .file-tile img { height: 118px; }
  .tile-cat { top: 90px; }
}

/* ==== THE DESKTOP, WITH DEPTH (Josh, 11/6: "on the desktop version it looks
   really white and boring") ===============================================
   Stephen's look stays: the shade, the steel accent, the bands, the icon
   shape. What changes is the ground under it, on a desktop only (a phone is
   untouched):
   1. The top bar and the section row wear the layout's shade, so the app has
      a frame and the Home band and the customer file's band belong to it.
   2. The page is a soft gray tinted from the shade (--app-ground), so a
      white card sits ON it. Cards get back a soft shadow.
   3. The bands get light: a soft glow from the top right and a slight
      deepening toward the bottom.
   4. An attention tile with something in it is washed in its own color;
      an empty one stays quiet white.
   5. The customer file's tabs open onto the ground and its cards float on
      it, instead of white cards inside a white panel.
   applyAppLook (dashlook.js) writes --app-band, --app-soft and --app-ground
   from the shade; the fallbacks below are Classic. */
@media (min-width: 761px) {
  :root { --ground: var(--app-ground, #edf1f3); --lift: 0 1px 2px rgba(16, 24, 40, .05), 0 6px 20px rgba(16, 24, 40, .06);
    --lift-hover: 0 2px 4px rgba(16, 24, 40, .06), 0 12px 28px rgba(16, 24, 40, .10); --card-line: #e3e8ec; }
  :root[data-theme="dark"] { --ground: var(--canvas); --lift: 0 1px 2px rgba(0, 0, 0, .3), 0 6px 18px rgba(0, 0, 0, .22);
    --lift-hover: 0 2px 4px rgba(0, 0, 0, .35), 0 12px 28px rgba(0, 0, 0, .35); --card-line: var(--border); }
  body, .main, body[data-route] .main { background: var(--ground); }

  /* 1. The frame. */
  .appbar .topbar, :root:not([data-layout="sheet"]):not([data-layout="dock"]) .appbar .secbar {
    background: var(--app-band, #1e3440); -webkit-backdrop-filter: none; backdrop-filter: none;
    border-bottom: 1px solid rgba(255, 255, 255, .07); color: #fff; }
  .appbar .topbar::after { display: none; }
  .appbar .topbar .brand-name, .appbar .topbar .brand-co.lead { color: #fff; }
  .appbar .topbar .brand-mark { background: rgba(255, 255, 255, .14); }
  .appbar .topbar .brand-co, .appbar .topbar .brand-product { color: var(--app-soft, #b6d0d8); border-left-color: rgba(255, 255, 255, .18); }
  /* A logo is drawn for paper, so it sits on a white plate here. */
  .appbar .topbar .brand-logo { background: #fff; border-radius: 8px; padding: 3px 8px; height: 30px; box-sizing: border-box; border-left: 0; }
  .appbar .topbar .btn { background: rgba(255, 255, 255, .08); border-color: rgba(255, 255, 255, .16); color: #fff; }
  .appbar .topbar .btn:hover { background: rgba(255, 255, 255, .16); border-color: rgba(255, 255, 255, .28); }
  .appbar .topbar .btn.primary { background: #fff; border-color: #fff; color: var(--app-band, #1e3440); font-weight: 650; }
  .appbar .topbar .btn.primary:hover { background: #e9eff3; border-color: #e9eff3; }
  .appbar .topbar .btn.demo-pill { background: linear-gradient(135deg, var(--blue), #7c3aed); border-color: transparent; }
  .appbar .topbar .sticky-badge { color: var(--app-soft, #b6d0d8); }
  .appbar .topbar .searchbox { background: rgba(255, 255, 255, .08); border-color: rgba(255, 255, 255, .14); color: var(--app-soft, #b6d0d8); }
  .appbar .topbar .searchbox:focus-within { background: rgba(255, 255, 255, .14); border-color: rgba(255, 255, 255, .4); }
  .appbar .topbar .searchbox svg { color: var(--app-soft, #b6d0d8); }
  .appbar .topbar .searchbox input { color: #fff; }
  .appbar .topbar .searchbox input::placeholder { color: var(--app-soft, #b6d0d8); opacity: .85; }
  .appbar .topbar .kbd-chip { background: transparent; border-color: rgba(255, 255, 255, .2); color: var(--app-soft, #b6d0d8); }
  .appbar .topbar .avatar { box-shadow: 0 0 0 2px rgba(255, 255, 255, .22); }
  :root:not([data-layout="sheet"]):not([data-layout="dock"]) .secbar .topnav-link { color: var(--app-soft, #b6d0d8); }
  :root:not([data-layout="sheet"]):not([data-layout="dock"]) .secbar .topnav-link:hover { color: #fff; }
  :root:not([data-layout="sheet"]):not([data-layout="dock"]) .secbar .topnav-link.on { color: #fff; border-bottom: 3px solid var(--app-soft, #b6d0d8); }
  :root:not([data-layout="sheet"]):not([data-layout="dock"]) .secbar .topnav-link:focus-visible { outline-color: #fff; }
  :root:not([data-layout="sheet"]):not([data-layout="dock"]) .secbar .nav-badge { background: rgba(255, 255, 255, .14); color: #fff; }
  .appbar .topbar .topnav-link { color: var(--app-soft, #b6d0d8); }
  .appbar .topbar .topnav-link:hover, .appbar .topbar .topnav-link.on { color: #fff; background: rgba(255, 255, 255, .1); }

  /* 2. Cards sit on the ground. A card inside a card stays flat. */
  .main .card, .main .fold, .main .empty { border-color: var(--card-line); box-shadow: var(--lift); }
  .main .card .card, .main .fold .card, .main .card .fold, .main .card .empty, .main .fold .empty, .modal .card { box-shadow: none; }
  .main .secpage { box-shadow: 0 1px 2px rgba(16, 24, 40, .05); }
  .dz-card { border-color: var(--card-line); box-shadow: var(--lift); border-radius: 20px; }
  /* Home fills the screen (Josh, 11/6: "the main page needs to fill screen
     not be boxed out"); it was held to 1240px in the middle. */
  .dz { max-width: none; }

  /* 3. Light in the bands. */
  .dz-band, .jh {
    background-color: var(--dz-band, var(--jh-band));
    background-image:
      radial-gradient(720px 300px at 92% -30%, rgba(255, 255, 255, .13), transparent 70%),
      radial-gradient(520px 240px at 8% 130%, color-mix(in srgb, var(--dz-soft, var(--jh-soft)) 14%, transparent), transparent 70%),
      linear-gradient(180deg, transparent, rgba(0, 0, 0, .16));
  }
  :root[data-theme="dark"] .dz-band, :root[data-theme="dark"] .jh {
    background-image:
      radial-gradient(720px 300px at 92% -30%, rgba(255, 255, 255, .12), transparent 70%),
      linear-gradient(rgba(255, 255, 255, .05), rgba(255, 255, 255, .05)); }
  .dz-big { text-shadow: 0 1px 0 rgba(0, 0, 0, .18); }
  .dz-num, .jh-fig { position: relative; }
  .dz-nums .dz-num + .dz-num::before, .jh-figs .jh-fig + .jh-fig::before {
    content: ''; position: absolute; left: -8px; top: 8px; bottom: 8px; width: 1px; background: rgba(255, 255, 255, .12); }

  /* 4. Tiles in their own color, a lift on hover. */
  .dz-tile { transition: transform .15s, box-shadow .15s, border-color .15s; }
  .dz-tile:not(.zero) { background: color-mix(in srgb, var(--c, var(--blue)) 7%, var(--surface));
    border-color: color-mix(in srgb, var(--c, var(--blue)) 26%, var(--card-line)); }
  .dz-tile:not(.zero) .dz-tile-n { color: color-mix(in srgb, var(--c, var(--ink)) 55%, var(--ink)); }
  .dz-tile:hover { transform: translateY(-2px); box-shadow: var(--lift-hover); }
  .dz-tile.zero { background: var(--surface); }
  .dz-tile:not(.zero) .dz-ic::after { border-color: color-mix(in srgb, var(--c, var(--blue)) 7%, var(--surface)); }
  .dz-panel { background: var(--surface); }
  .dz-stage .dz-ring { box-shadow: 0 4px 14px rgba(16, 24, 40, .10); }
  .dz-stage:hover .dz-ring { box-shadow: 0 8px 20px rgba(16, 24, 40, .16); }
  .dz-track i { background: linear-gradient(90deg, var(--blue), color-mix(in srgb, var(--blue) 60%, #fff)); }

  /* 5. The customer file opens onto the ground. */
  .jh { border-radius: 20px 20px 0 0; box-shadow: var(--lift); }
  /* The next stage is the brightest thing on the band, like New on the bar. */
  .jh-btn.go { background: #fff; border-color: #fff; color: var(--jh-band); }
  .jh-btn.go:hover { background: #e9eff3; border-color: #e9eff3; filter: none; }
  .jh-tab.on { background: var(--ground); }
  .jh-body { background: transparent; border: 0; padding: 20px 0 0; }
}

/* ==== THE OVERVIEW, TIDIED (Josh, 11/6, the approved mock) ===============
   Where the job is, then Primary contact and Location info side by side at
   one height (always, on a desktop: Josh's rule), then the work on the left
   and the facts on the right, then the admin tools closed at the foot. Every
   card head is the same: the soft square icon, the title, an action in the
   accent at the right; the gray strip the pair wore is gone. */
.ov-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px;
  align-items: stretch; margin: 16px 0; }
.ov-pair > .card { margin: 0; }
.ov-card { padding: 16px 18px; }
.ov-card .card-head { margin: 0 0 12px; padding: 0; background: none; border: 0; border-radius: 0; }
.ov-card .card-head h3 { font-size: 16px; font-weight: 650; }
/* The older rule painted every icon in an .ov-card head blue; the soft
   square keeps its own color. */
.ov-card .card-head .dz-ic svg { color: inherit; }
.card-head .dz-link { display: inline-flex; align-items: center; gap: 4px; }
.card-head .dz-link + .dz-link { margin-left: 14px; }
/* A mount that painted nothing takes no room between the cards. */
.jo-left > :not(:empty) ~ :not(:empty), .jo-right > :not(:empty) ~ :not(:empty) { margin-top: 16px; }
#portalNote:empty { display: none; }
/* To do: the next visit booked, then the tasks, then Repeat, quietly. */
.ov-next { display: flex; gap: 12px; align-items: center; padding: 10px 12px; margin: 0 0 6px;
  border-radius: 12px; background: color-mix(in srgb, var(--blue) 8%, var(--surface)); }
.ov-quiet { background: none; border: 0; padding: 8px 0 0; font: inherit; font-size: 12.5px;
  color: var(--slate); cursor: pointer; }
.ov-quiet:hover { color: var(--ink); text-decoration: underline; }
/* Latest activity's foot: log a call, a text or a note. */
.ov-log { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin-top: 12px;
  padding-top: 12px; border-top: 1px solid var(--border); }
.ov-log > .dim { font-size: 12.5px; margin-right: 4px; }
/* The one Stack card: every helper's buttons in one row, answers below. */
.ov-stack-since { font-size: 12.5px; color: var(--slate); }
.ov-since { background: none; border: 0; padding: 0; font: inherit; font-size: 12.5px; color: var(--slate); cursor: pointer; }
.ov-since:hover { color: var(--ink); text-decoration: underline; }
.ov-stack [data-stack-next]:not(:empty) { margin: 0 0 10px; }
.ov-stack [data-stack-next] .next-stop { margin: 0 0 4px; }
.ov-stack-acts { display: flex; flex-wrap: wrap; gap: 6px; }
.ov-stack-acts > span { display: contents; }
.ov-stack-msg { display: inline-flex; gap: 4px; align-items: center; }
.ov-stack-msg select { width: auto; height: 30px; padding: 2px 8px; font-size: 12.5px; }
.ov-stack .ai-list, .ov-stack [data-explain-out]:not([hidden]), .ov-stack-out { margin-top: 12px; }
.ov-stack-out { padding-top: 12px; border-top: 1px solid var(--border); }
.ov-stack-note { font-size: 12px; margin: 12px 0 0; }
/* Manage this job: one row per tool, the words on the left. */
.ov-manage { margin-top: 16px; }
.manage-row { display: flex; justify-content: space-between; align-items: center; gap: 18px;
  padding: 12px 0; border-top: 1px solid var(--border); }
.manage-row:first-child { border-top: 0; }
.manage-row p { margin: 2px 0 0; font-size: 12.5px; max-width: 64ch; }
@media (max-width: 760px) {
  .ov-pair { grid-template-columns: 1fr; gap: 12px; margin: 12px 0; }
  .manage-row { flex-direction: column; align-items: flex-start; gap: 8px; }
}

/* ==== THE BAND HOLDS THE STRIP (Josh, 11/6) ================================
   The strip above the customer file's band is gone: its tools are under More
   and its owner card under the Rep chip, both menus on the band. Collected
   carries the money lines only the strip had. */
/* Every child of #main sits at z-index 1 (the watermark rule above), so a
   menu on the band slid under the first card; the band sits a step up. */
#main > .jh { z-index: 2; }
.jh-more-wrap, .jh-rep-wrap { position: relative; display: inline-flex; }
.jh-menu { position: absolute; top: calc(100% + 8px); right: 0; z-index: 50; min-width: 280px; padding: 6px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--shadow-pop);
  color: var(--ink); text-align: left; }
/* ⚠️ The class sets display, so it must say [hidden] itself (the old nav trap). */
.jh-menu[hidden] { display: none; }
.jh-menu [role="menuitem"] { display: flex; align-items: flex-start; gap: 10px; width: 100%; padding: 9px 10px;
  border: 0; border-radius: 8px; background: transparent; color: var(--ink); font: inherit; font-size: 13.5px;
  text-align: left; text-decoration: none; cursor: pointer; box-sizing: border-box; }
.jh-menu [role="menuitem"]:hover, .jh-menu [role="menuitem"]:focus-visible { background: var(--raise); outline: none; }
.jh-menu [role="menuitem"] svg { flex: none; margin-top: 2px; color: var(--slate); }
.jh-menu small { display: block; margin-top: 1px; font-size: 12px; line-height: 1.35; color: var(--slate); }
.jh-menu hr { border: 0; border-top: 1px solid var(--border); margin: 6px 4px; }
.jh-menu-val { margin-left: auto; padding-left: 12px; color: var(--slate); font-variant-numeric: tabular-nums; }
.jh-chip-btn { border: 0; cursor: pointer; font: inherit; font-size: 12px; font-weight: 600; }
.jh-chip-btn:hover { background: rgba(255, 255, 255, .2); }
.jh-chip-btn:focus-visible { outline: 2px solid #c3d3de; outline-offset: 2px; }
.jh-chev { transform: rotate(90deg); }
.jh-owner { left: 0; right: auto; width: 290px; padding: 14px; }
.jh-owner-who { display: flex; gap: 12px; align-items: center; }
.jh-owner-who .avatar { width: 40px; height: 40px; font-size: 14px; }
.jh-owner-who .dim { font-size: 12.5px; }
.jh-owner-card { margin: 10px 0 12px; font-size: 13px; line-height: 1.5; color: var(--slate); }
.jh-owner-card a { color: var(--blue); }
.jh-owner .jb-owner-acts { display: flex; gap: 8px; margin-top: 10px; }
.jh-owner .jb-owner-acts a { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px;
  border-radius: 10px; background: var(--raise); color: var(--ink); }
.jh-owner .btn { width: 100%; justify-content: center; }
.jh-fig-sub { max-width: 100%; margin-top: 2px; font-size: 12px; line-height: 1.35; color: var(--jh-soft); }
[data-riley-late]:not(:empty), [data-riley-lead]:not(:empty) { margin-bottom: 10px; }
@media (max-width: 760px) {
  /* On a phone each menu spans the row it opens from, so none runs off the screen. */
  .jh-acts, .jh-chips { position: relative; }
  .jh-more-wrap, .jh-rep-wrap { position: static; }
  .jh-more-wrap { flex: 1 1 auto; }
  .jh-more-wrap > .jh-btn { width: 100%; justify-content: center; }
  .jh-menu { left: 0; right: 0; min-width: 0; width: auto; }
}

/* ============================================================
   THE WELCOME AND THE TOUR (11/6, welcome.js). Added on top: nothing
   above is changed. The question and the package are app modals; the
   tour is a dim with a spotlight cut around a real element and a small
   card beside it. Below the modals (100) so a dialog the page opens
   still sits on top.
   ============================================================ */
.brand-mark.brand-mark-stack { background: transparent; overflow: hidden; padding: 0; }
.brand-mark-stack .stack-mark { display: block; width: 100%; height: 100%; }
.appbar .topbar .brand-mark.brand-mark-stack { background: transparent;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .18); }

.wl-q { text-align: center; padding: 6px 4px 2px; }
.wl-mark { display: flex; justify-content: center; margin: 2px 0 12px; }
.wl-mark .stack-mark { border-radius: 14px; box-shadow: 0 6px 18px rgba(15, 28, 46, .22); }
.wl-q h2 { margin: 0 0 4px; font-size: 22px; }
.wl-sub { margin: 0 0 16px; color: var(--slate); font-size: 13.5px; }
.wl-choices { display: grid; gap: 10px; margin: 0 0 16px; text-align: left; }
.wl-choice { display: flex; align-items: center; gap: 12px; width: 100%; padding: 12px 14px;
  border: 1.5px solid var(--border); border-radius: 14px; background: var(--surface);
  color: inherit; font: inherit; cursor: pointer; text-align: left; }
.wl-choice:hover { border-color: color-mix(in srgb, var(--blue) 45%, var(--border)); }
.wl-choice.on { border-color: var(--blue); box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 16%, transparent); }
.wl-choice:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.wl-choice-t { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.wl-choice-t b { font-size: 14.5px; }
.wl-choice-t span { font-size: 12.5px; color: var(--slate); line-height: 1.4; }
.wl-radio { width: 18px; height: 18px; border-radius: 50%; border: 2px solid var(--border); flex: none; }
.wl-choice.on .wl-radio { border-color: var(--blue); background: radial-gradient(var(--blue) 0 4px, transparent 5px); }
.wl-go { width: 100%; justify-content: center; }
.wl-skip { margin: 12px 0 0; font-size: 13px; }
.wl-skip a, .wl-later { color: var(--slate); }

.wl-pack-head { display: flex; gap: 12px; align-items: center; margin: 0 0 12px; }
.wl-pack-head .stack-mark { border-radius: 9px; flex: none; }
.wl-pack-head h2 { margin: 0; font-size: 20px; }
.wl-pack-head .wl-sub { margin: 2px 0 0; }
.wl-rows { list-style: none; margin: 0 0 16px; padding: 0; display: grid;
  grid-template-columns: 1fr 1fr; gap: 10px 18px; }
.wl-row { display: flex; gap: 12px; align-items: flex-start; padding: 8px 4px;
  opacity: 0; transform: translateY(8px);
  animation: wlRowIn .42s cubic-bezier(.2, .7, .3, 1) forwards;
  animation-delay: calc(var(--i) * 140ms + 120ms); }
.wl-row > span:last-child { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding-top: 2px; }
.wl-row b { font-size: 14px; }
.wl-row span span { font-size: 12.5px; color: var(--slate); line-height: 1.42; }
.wl-row.wl-riley { grid-column: 1 / -1; padding: 12px; border-radius: 14px;
  background: color-mix(in srgb, #e9a93a 9%, var(--surface)); border: 1px solid color-mix(in srgb, #e9a93a 30%, var(--border)); }
.wl-row.wl-riley span span { color: var(--ink); }
@keyframes wlRowIn { to { opacity: 1; transform: none; } }
.wl-pack.still .wl-row { animation: none; opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .wl-row { animation: none; opacity: 1; transform: none; }
}
.wl-pack-foot { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.wl-pack-foot .wl-go { max-width: 320px; }
.wl-later { font-size: 13px; }
@media (max-width: 640px) {
  .wl-rows { grid-template-columns: 1fr; }
}

.wl-tour { position: fixed; inset: 0; z-index: 98; pointer-events: none; }
.wl-dim { position: fixed; inset: 0; background: rgba(10, 18, 30, .55); }
.wl-hole { position: fixed; border-radius: 12px; pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(10, 18, 30, .55), 0 0 0 3px rgba(255, 255, 255, .9), 0 0 24px 4px rgba(233, 169, 58, .35);
  transition: left .25s ease, top .25s ease, width .25s ease, height .25s ease; }
.wl-card { position: fixed; pointer-events: auto; width: min(360px, calc(100vw - 24px));
  background: var(--surface); color: var(--ink); border-radius: 14px; padding: 14px 16px 12px;
  box-shadow: 0 18px 50px rgba(10, 18, 30, .35); border: 1px solid var(--border);
  transition: left .25s ease, top .25s ease; }
.wl-card:focus { outline: none; }
.wl-tour.centered .wl-card { left: 50% !important; top: 50% !important; transform: translate(-50%, -50%); }
.wl-tour.narrow .wl-card { left: 12px !important; right: 12px; top: auto !important; transform: none;
  bottom: calc(12px + env(safe-area-inset-bottom, 0px)); width: auto; }
.wl-card-top { display: flex; align-items: center; justify-content: space-between; margin: 0 0 6px; }
.wl-count { font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--slate); font-weight: 650; }
.wl-end { font-size: 12.5px; color: var(--slate); }
.wl-card h3 { margin: 0 0 6px; font-size: 16.5px; display: flex; align-items: center; gap: 10px; }
.wl-body p { margin: 0 0 8px; font-size: 13.5px; line-height: 1.5; }
.wl-card-riley { width: min(400px, calc(100vw - 24px)); }
.wl-dots { display: flex; gap: 5px; margin: 6px 0 10px; flex-wrap: wrap; }
.wl-dots i { width: 7px; height: 7px; border-radius: 50%; background: var(--border); }
.wl-dots i.past { background: color-mix(in srgb, var(--blue) 45%, var(--border)); }
.wl-dots i.on { background: var(--blue); width: 18px; border-radius: 4px; }
.wl-foot { display: flex; justify-content: space-between; gap: 8px; }
.wl-site { gap: 8px; margin: 4px 0 6px; }
.wl-site input { flex: 1; min-width: 0; }
.wl-note { font-size: 12.5px; margin: 4px 0 6px; color: var(--slate); }
.wl-note.bad { color: var(--red); }
.wl-nosite { font-size: 12.5px; margin: 2px 0 4px; }
.wl-logo { display: flex; justify-content: center; padding: 10px; margin: 0 0 8px;
  background: #fff; border: 1px solid var(--border); border-radius: 12px; }
.wl-logo img { max-height: 54px; max-width: 220px; object-fit: contain; }
.wl-ok { display: flex; gap: 6px; align-items: flex-start; color: var(--green); font-weight: 600; }
@media (prefers-reduced-motion: reduce) {
  .wl-hole, .wl-card { transition: none; }
}

/* ==== SETTINGS AS PAGES (Stephen, 11/6: "clean up the settings section so it
   looks more like the CRM rather than a laundry list of jumbled text") =====
   settings.js: a left menu (sticky on a desktop, a list you tap into on a
   phone) with a search box, pages in five groups, each opening on a slim band
   in the layout's shade, and cards laid out as rows: the setting's name, one
   gray line, the control on the right, one Save at the bottom right. Scoped
   to the settings page; nothing above is changed. */
.sg-shell { display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: 24px; align-items: start; }
.sg-menu { position: sticky; top: var(--sp-top, 12px); max-height: calc(100vh - var(--sp-top, 12px) - 12px); overflow-y: auto;
  background: var(--surface); border: 1px solid var(--card-line, var(--border)); border-radius: 16px; padding: 12px 10px;
  box-shadow: var(--lift, none); scrollbar-width: thin; }
.sg-search { display: flex; align-items: center; gap: 8px; margin: 0 2px 8px; padding: 0 10px; border: 1px solid var(--border);
  border-radius: 10px; background: var(--raise); color: var(--slate); }
.sg-search:focus-within { border-color: var(--blue); background: var(--surface); }
.sg-search svg { flex: none; }
.main .sg-search input { flex: 1; min-width: 0; border: 0; background: transparent; padding: 8px 0; box-shadow: none; outline: none; font-size: 13.5px; }
.sg-hits { margin: 0 2px 10px; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; background: var(--surface); }
.sg-hit { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; width: 100%; padding: 8px 10px; border: 0;
  border-bottom: 1px solid var(--line); background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.sg-hit:last-child { border-bottom: 0; }
.sg-hit b { font-size: 13px; font-weight: 600; }
.sg-hit span { font-size: 11.5px; color: var(--slate); }
.sg-hit:hover, .sg-hit:focus-visible { background: var(--raise); outline: none; }
.sg-nohit { margin: 0; padding: 10px; font-size: 12.5px; color: var(--slate); }
.sg-group + .sg-group { margin-top: 8px; }
.sg-glabel { margin: 8px 10px 4px; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--slate); }
.sg-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px; border: 0; border-radius: 9px;
  background: none; color: var(--ink); font: inherit; font-size: 14px; text-align: left; cursor: pointer; }
.sg-item svg { flex: none; color: var(--slate); }
.sg-item span { flex: 1; min-width: 0; }
.sg-item .sg-chev { display: none; }
.sg-item:hover { background: var(--raise); }
.sg-item:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }
.sg-item.on { background: color-mix(in srgb, var(--blue) 13%, transparent); font-weight: 650; }
.sg-item.on svg { color: var(--blue); }
.sg-item.sg-dim { opacity: .38; }
.sg-item[hidden], .sg-group[hidden] { display: none; }
.sg-page[hidden] { display: none !important; }
.sg-back { display: none; }

/* The page's band, the same shade the Home band and the customer file wear. */
.sg-head { margin: 0 0 16px; padding: 18px 22px; border-radius: 16px; color: #fff;
  background-color: var(--app-band, #1e3440);
  background-image: radial-gradient(620px 220px at 92% -40%, rgba(255, 255, 255, .13), transparent 70%); }
.sg-head h2 { margin: 0; color: #fff; font-size: 20px; font-weight: 700; letter-spacing: -.01em; }
.sg-head p { margin: 3px 0 0; color: var(--app-soft, #b6d0d8); font-size: 13.5px; }

/* The cards on a page. */
.sg-page .card { padding: 18px 20px; }
.sg-page .mt-22, .sg-page .card + .card, .sg-page .card + div, .sg-page div + .card { margin-top: 16px; }
.sg-page .sg-head + .card, .sg-page .sg-head + div > .card:first-child { margin-top: 0; }
.sg-page .card-head { align-items: flex-start; margin-bottom: 14px; flex-wrap: wrap; row-gap: 8px; }
.sg-page .card-head > .btn, .sg-page .card-head > label.btn, .sg-page .card-head > a.btn, .sg-page .card-head > .pill, .sg-page .card-head > select { margin-top: 3px; }
.sg-titles { flex: 1 1 200px; min-width: 0; display: flex; flex-direction: column; padding-top: 4px; }
.sg-page .card-head > .grow { display: none; }
.sg-titles h3 { margin: 0; }
.main .sg-page .sg-lede { margin: 2px 0 0; font-size: 13px; color: var(--slate); line-height: 1.45; max-width: 78ch;
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; }
.main .sg-page .sg-lede.open { display: block; -webkit-line-clamp: unset; }
/* Folded cards on a job tab (11/10), the same look as Settings'. */
.card.card-fold > .card-head { cursor: pointer; }
.card.card-fold.sg-shut > .card-head { margin-bottom: 0; }
.card.card-fold.sg-shut > :not(.card-head) { display: none !important; }
.card.card-fold:not(.sg-shut) .sg-chev { transform: rotate(90deg); }
.card.card-fold > .card-head:focus-visible { outline: 2px solid var(--blue); outline-offset: 4px; border-radius: 6px; }
/* Folded cards (11/10): the title and its gray line, a tap opens the rest. */
.sg-page .card.sg-fold > .card-head { cursor: pointer; }
.sg-page .card.sg-shut > .card-head { margin-bottom: 0; }
.sg-page .card.sg-shut > :not(.card-head) { display: none !important; }
.sg-page .card.sg-shut { padding-top: 14px; padding-bottom: 14px; }
.sg-chev { margin-left: auto; align-self: center; color: var(--slate); display: inline-flex; transition: transform .15s ease; }
.sg-page .card.sg-fold:not(.sg-shut) .sg-chev { transform: rotate(90deg); }
.sg-page .card.sg-fold > .card-head:focus-visible { outline: 2px solid var(--blue); outline-offset: 4px; border-radius: 6px; }
.sg-more { align-self: flex-start; margin-top: 1px; padding: 0; border: 0; background: none; color: var(--blue);
  font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; }
.sg-page .card .card-head > .grow + .dim, .sg-page .card .card-head > span.dim { font-size: 12px; }

/* Rows: name and one gray line on the left, the control on the right. */
.sg-rows { display: flex; flex-direction: column; }
.sg-row { display: flex; align-items: center; justify-content: space-between; gap: 18px; padding: 12px 0; border-top: 1px solid var(--line); }
.sg-rows > .sg-row:first-child { border-top: 0; padding-top: 2px; }
.sg-row-t { flex: 1 1 240px; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.sg-row-t b { font-size: 14px; font-weight: 600; }
.sg-row-t span { font-size: 12.5px; color: var(--slate); line-height: 1.4; }
.sg-row-c { flex: 0 1 380px; min-width: 0; display: flex; justify-content: flex-end; align-items: center; gap: 8px; }
.sg-row-c > input:not([type=checkbox]):not([type=color]):not([type=radio]), .sg-row-c > select, .sg-row-c > textarea { width: 100%; max-width: 380px; }
.sg-row-wide { flex-direction: column; align-items: stretch; gap: 8px; }
.sg-row-wide .sg-row-t { flex: none; }
.sg-row-wide .sg-row-c { flex: none; justify-content: flex-start; flex-wrap: wrap; }
.sg-row-wide .sg-row-c > input:not([type=checkbox]), .sg-row-wide .sg-row-c > textarea { max-width: none; }
.sg-row-wide .sg-row-c > .layout-tiles, .sg-row-wide .sg-row-c > .shade-tiles, .sg-row-wide .sg-row-c > .scheme-grid { margin-top: 0; width: 100%; }
.sg-row-sub { padding: 9px 0 9px 22px; }
.sg-row-sub .sg-row-t b { font-size: 13.5px; font-weight: 500; }
.sg-addr { display: flex; flex-direction: column; gap: 8px; width: 100%; max-width: 380px; }
.sg-addr-parts { display: grid; grid-template-columns: 1fr 1.3fr .6fr .9fr; gap: 8px; }
.sg-chips { gap: 6px; }
.sg-preview { padding: 2px 0 12px; }
.sg-note { margin: 10px 0 0; font-size: 12px; color: var(--slate); }
.sg-aside { margin: 16px 2px 0; font-size: 12.5px; color: var(--slate); }
.sg-foot { display: flex; justify-content: flex-end; align-items: center; gap: 8px; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
.sg-page .row.sg-foot { flex-direction: row-reverse; justify-content: flex-start; }
.sg-page .card > .btn.sg-save-end { display: flex; margin: 14px 0 0 auto; }
.sg-link-card .card-head { margin-bottom: 6px; }
.sg-link-card > p.dim { margin: 0; font-size: 13px; }

/* A switch, for every on or off setting on the page. */
.sg-page input[type=checkbox].sg-switch,
.sg-page .card > label.row > input[type=checkbox]:first-child,
.sg-page .card > div:not(.row) > label.row > input[type=checkbox]:first-child {
  -webkit-appearance: none; appearance: none; position: relative; flex: none; width: 38px !important; height: 22px; margin: 0;
  border: 0; border-radius: 999px; padding: 0; cursor: pointer; transition: background .15s;
  background: color-mix(in srgb, var(--slate) 38%, transparent); }
.sg-page input[type=checkbox].sg-switch::before,
.sg-page .card > label.row > input[type=checkbox]:first-child::before,
.sg-page .card > div:not(.row) > label.row > input[type=checkbox]:first-child::before {
  content: ''; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: #fff;
  box-shadow: 0 1px 2px rgba(16, 24, 40, .25); transition: transform .15s; }
.sg-page input[type=checkbox].sg-switch:checked,
.sg-page .card > label.row > input[type=checkbox]:first-child:checked,
.sg-page .card > div:not(.row) > label.row > input[type=checkbox]:first-child:checked { background: var(--blue); }
.sg-page input[type=checkbox].sg-switch:checked::before,
.sg-page .card > label.row > input[type=checkbox]:first-child:checked::before,
.sg-page .card > div:not(.row) > label.row > input[type=checkbox]:first-child:checked::before { transform: translateX(16px); }
.sg-page input[type=checkbox].sg-switch:focus-visible,
.sg-page .card > label.row > input[type=checkbox]:first-child:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.sg-page input[type=checkbox].sg-switch:disabled { opacity: .5; cursor: default; }
/* An older card's switch line reads as a row too: words left, switch right. */
.sg-page .card > label.row:has(> input[type=checkbox]:first-child),
.sg-page .card > div:not(.row) > label.row:has(> input[type=checkbox]:first-child) {
  flex-direction: row-reverse; justify-content: space-between; align-items: center; gap: 16px; width: 100%;
  padding: 10px 0; border-top: 1px solid var(--line); font-size: 13.5px; }

/* Tables keep their structure, restyled. */
.sg-page table.data { width: 100%; border-collapse: separate; border-spacing: 0; border: 1px solid var(--line); border-radius: 10px; }
.sg-page table.data th { background: var(--raise); padding: 8px 10px; text-align: left; border-bottom: 1px solid var(--line); }
.sg-page table.data th:first-child { border-top-left-radius: 10px; }
.sg-page table.data th:last-child { border-top-right-radius: 10px; }
.sg-page table.data td { padding: 8px 10px; border-top: 1px solid var(--line); vertical-align: middle; }
.sg-page table.data tbody tr:first-child td { border-top: 0; }
.sg-page .card p.micro { margin-top: 16px; }

.sg-flash { box-shadow: 0 0 0 2px var(--blue) !important; transition: box-shadow .3s; }
.sg-row.sg-flash, label.sg-flash { border-radius: 8px; background: color-mix(in srgb, var(--blue) 8%, transparent); }

@media (min-width: 761px) and (max-width: 1180px) {
  .sg-shell { grid-template-columns: 210px minmax(0, 1fr); gap: 16px; }
}
@media (max-width: 760px) {
  .sg-shell { display: block; }
  .sg-menu { position: static; max-height: none; overflow: visible; padding: 10px 8px; border-radius: 14px; box-shadow: none; }
  .sg-shell[data-view="page"] .sg-menu { display: none; }
  .sg-shell[data-view="menu"] .sg-body { display: none; }
  .sg-item { padding: 12px 10px; font-size: 15px; border-radius: 10px; }
  .sg-item .sg-chev { display: block; color: var(--slate); }
  .sg-item.on { background: none; font-weight: 500; }
  .sg-item.on svg { color: var(--slate); }
  .sg-group .sg-item + .sg-item { border-top: 1px solid var(--line); border-radius: 0; }
  .sg-back { display: inline-flex; align-items: center; gap: 6px; margin: 0 0 10px; padding: 4px 0; border: 0; background: none;
    color: var(--blue); font: inherit; font-size: 14px; font-weight: 600; cursor: pointer; }
  .sg-head { padding: 14px 16px; border-radius: 14px; margin-bottom: 12px; }
  .sg-head h2 { font-size: 18px; }
  .sg-page .card { padding: 14px; }
  .sg-row { flex-wrap: wrap; gap: 8px; }
  .sg-row-c { flex: 1 1 100%; justify-content: flex-start; flex-wrap: wrap; }
  .sg-row:has(> .sg-row-c > .sg-switch) { flex-wrap: nowrap; }
  .sg-row:has(> .sg-row-c > .sg-switch) > .sg-row-c { flex: none; }
  .sg-row-c > input:not([type=checkbox]):not([type=color]), .sg-row-c > select, .sg-row-c > textarea, .sg-addr { max-width: none; }
  .sg-row-c .row { justify-content: flex-start !important; }
}
.sg-row[hidden], .sg-foot[hidden] { display: none; }
.sg-details { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 12px; }
.sg-details > summary { cursor: pointer; font-weight: 600; font-size: 13.5px; }
.sg-details[open] > summary { margin-bottom: 8px; }
.sg-choice { cursor: pointer; }
.sg-choice .sg-row-t b { font-weight: 500; }
.sg-choice .sg-row-c { flex: none; }
.sg-choice input[type=radio] { width: 18px; height: 18px; margin: 0; accent-color: var(--blue); }
.sg-row-flow { justify-content: flex-start; }
.sg-page .card-head + .sg-row-flow { border-top: 0; padding-top: 2px; }
.sg-page [data-focus-key="people"] td:first-child .row { flex-wrap: nowrap; }
.sg-page [data-focus-key="people"] td:first-child span { white-space: nowrap; }
.sg-page [data-focus-key="people"] td { white-space: normal; }
.sg-page table.sg-people td:nth-child(4) { white-space: nowrap; }
.sg-page table.sg-people td:last-child { white-space: nowrap; }
@media (max-width: 760px) {
  .sg-page .card > table.data { display: block; overflow-x: auto; }
}

/* ==== PHONE AND RILEY (Stephen approved the two mockups, 11/6) ==========
   views/callcenter.js: the Call Center as a console. A band in the layout's
   shade with the company number on the right and the tabs on its bottom
   edge (the customer file's way), white cards with the soft square icon and
   a status dot, rows with the control on the right, the gray steel accent
   for switches and picked pills. `pr-` classes only. */
.pr { --pr-steel: #4f6272; --pr-steel-soft: color-mix(in srgb, var(--pr-steel) 12%, transparent); max-width: 1080px; }
:root[data-theme="dark"] .pr { --pr-steel: #9db0c0; }
.pr-band { color: #fff; border-radius: 18px; padding: 20px 24px 0; margin: 4px 0 16px;
  background-color: var(--app-band, #1e3440);
  background-image: radial-gradient(620px 220px at 92% -40%, rgba(255, 255, 255, .13), transparent 70%); }
.pr-band-main { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; padding-bottom: 14px; }
.pr-band-t { min-width: 0; flex: 1 1 320px; }
.pr-band h1 { margin: 0; color: #fff; font-size: 24px; font-weight: 700; letter-spacing: -.01em; }
.pr-band-t p { margin: 4px 0 0; color: var(--app-soft, #b6d0d8); font-size: 14px; }
.pr-band-line { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; text-align: right; }
.pr-band-line b { font-size: 20px; color: #fff; letter-spacing: .01em; }
.pr-band-label { font-size: 11.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--app-soft, #b6d0d8); }
.pr-live { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--app-soft, #b6d0d8); }
.pr-live i { width: 8px; height: 8px; border-radius: 50%; background: #4ade80; box-shadow: 0 0 0 3px rgba(74, 222, 128, .2); }
.pr-band-req { max-width: 320px; }
.pr-band-req .lr-block p, .pr-band-req .dim { color: var(--app-soft, #b6d0d8) !important; }
.pr-band-req .pill { background: rgba(255, 255, 255, .16); color: #fff; }
.pr-band-req .btn.ghost { color: #fff; border-color: rgba(255, 255, 255, .3); }
.pr-tabs { display: flex; gap: 4px; overflow-x: auto; scrollbar-width: none; }
.pr-tabs::-webkit-scrollbar { display: none; }
.pr-tab { flex: none; padding: 11px 16px; border: 0; border-radius: 10px 10px 0 0; background: transparent;
  color: var(--app-soft, #b6d0d8); font: inherit; font-size: 14px; cursor: pointer; white-space: nowrap; }
.pr-tab:hover { color: #fff; }
.pr-tab.on { background: var(--surface); color: var(--ink); font-weight: 650; }
.pr-tab:focus-visible { outline: 2px solid #c3d3de; outline-offset: -2px; }
.pr-pane[hidden] { display: none !important; }
.pr-banner { border-left: 4px solid var(--amber); margin-bottom: 14px; }
.pr-group { margin: 22px 2px 8px; font-size: 11.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--slate); }

.pr .pr-card { padding: 18px 20px; margin: 0 0 16px; }
.pr-card-head { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 12px; }
.pr-ico { position: relative; flex: none; display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px;
  border-radius: 11px; color: var(--pr-steel); background: var(--pr-steel-soft); }
.pr-ico svg { stroke-width: 2.1; }
.pr-ico::after { content: ''; position: absolute; top: -3px; right: -3px; width: 10px; height: 10px; border-radius: 50%;
  background: var(--pr-steel); border: 2px solid var(--surface); box-sizing: border-box; }
.pr-ico-sm { width: 32px; height: 32px; border-radius: 10px; }
.pr-card-t { flex: 1; min-width: 0; }
.pr-card-t h3 { margin: 2px 0 0; font-size: 16px; font-weight: 650; }
.pr-card-t p { margin: 3px 0 0; font-size: 13px; color: var(--slate); line-height: 1.45; }
.pr-dot { flex: none; display: inline-flex; align-items: center; gap: 6px; margin-top: 4px; padding: 3px 10px; border-radius: 999px;
  font-size: 12px; font-weight: 600; background: var(--raise); color: var(--slate); white-space: nowrap; }
.pr-dot i { width: 7px; height: 7px; border-radius: 50%; background: var(--slate-light, #98a2b3); }
.pr-dot-on i { background: var(--green); }
.pr-dot-warn i { background: var(--amber); }

.pr-rows { display: flex; flex-direction: column; }
.pr-row { display: flex; align-items: center; justify-content: space-between; gap: 18px; padding: 12px 0; border-top: 1px solid var(--line); }
.pr-rows > .pr-row:first-child { border-top: 0; padding-top: 2px; }
.pr-row[hidden] { display: none; }
.pr-row-t { flex: 1 1 240px; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.pr-row-t b { font-size: 14px; font-weight: 600; }
.pr-row-t span { font-size: 12.5px; color: var(--slate); line-height: 1.4; }
.pr-row-c { flex: 0 1 380px; min-width: 0; display: flex; justify-content: flex-end; align-items: center; gap: 8px; }
.pr-row-c > input:not([type=checkbox]), .pr-row-c > select, .pr-row-c > textarea { width: 100%; max-width: 380px; }
.pr-row-wide { flex-direction: column; align-items: stretch; gap: 8px; }
.pr-row-wide .pr-row-t { flex: none; }
.pr-row-wide .pr-row-c { flex: none; justify-content: flex-start; flex-wrap: wrap; }
.pr-row-wide .pr-row-c > input, .pr-row-wide .pr-row-c > textarea { max-width: none; }
.pr-big { font-size: 22px; font-variant-numeric: tabular-nums; }
.pr-foot { display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); flex-wrap: wrap; }
.pr-foot .grow { flex: 1; }
.pr-note { margin: 12px 0 0; font-size: 12.5px; color: var(--slate); display: flex; gap: 6px; align-items: flex-start; }
.pr-note svg { flex: none; margin-top: 2px; color: var(--green); }
.pr-err { margin: 10px 0 0; color: var(--red, #c0392b); font-size: 12.5px; }
.pr-err[hidden] { display: none; }
.pr-warn { margin: 8px 0 0; padding: 8px 10px; border-radius: 8px; background: color-mix(in srgb, var(--amber) 14%, transparent); font-size: 13px; }
.pr-sub { margin: 8px 0 0; font-size: 12.5px; display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.pr-sub a { display: inline-flex; align-items: center; gap: 4px; font-weight: 600; }
.pr-check { display: flex; gap: 10px; align-items: flex-start; font-size: 13.5px; cursor: pointer; }
.pr-check input { margin-top: 3px; accent-color: var(--pr-steel); }
.pr-details { margin-top: 12px; border-top: 1px solid var(--line); padding-top: 10px; }
.pr-details > summary { cursor: pointer; font-weight: 600; font-size: 13.5px; }
.pr-scroll { overflow-x: auto; }
.pr-always { font-size: 12.5px; font-weight: 600; color: var(--slate); white-space: nowrap; }

/* The switch, in the steel accent. */
.pr input[type=checkbox].pr-switch { -webkit-appearance: none; appearance: none; position: relative; flex: none;
  width: 38px; height: 22px; margin: 0; border: 0; border-radius: 999px; padding: 0; cursor: pointer;
  background: color-mix(in srgb, var(--slate) 34%, transparent); transition: background .15s; }
.pr input[type=checkbox].pr-switch::before { content: ''; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px;
  border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(16, 24, 40, .25); transition: transform .15s; }
.pr input[type=checkbox].pr-switch:checked { background: var(--pr-steel); }
.pr input[type=checkbox].pr-switch:checked::before { transform: translateX(16px); }
.pr input[type=checkbox].pr-switch:disabled { opacity: .45; cursor: default; }
.pr input[type=checkbox].pr-switch:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

/* Radio cards and pills. */
.pr-radios { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 8px; }
.pr-radio { display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px; cursor: pointer; }
.pr-radio.on { border-color: var(--pr-steel); box-shadow: 0 0 0 1px var(--pr-steel); background: var(--pr-steel-soft); }
.pr-radio input { margin-top: 3px; accent-color: var(--pr-steel); }
.pr-radio b { display: block; font-size: 14px; }
.pr-radio small { display: block; margin-top: 2px; font-size: 12.5px; color: var(--slate); line-height: 1.4; }
.pr-radio:has(input:disabled) { opacity: .6; cursor: default; }
.pr-pills, .pr-filters, .pr-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.pr-pill, .pr-chip { padding: 6px 12px; border: 1px solid var(--border); border-radius: 999px; background: var(--surface);
  color: var(--ink); font: inherit; font-size: 13px; cursor: pointer; }
.pr-pill.on, .pr-chip.on { background: var(--pr-steel); border-color: var(--pr-steel); color: #fff; font-weight: 600; }
:root[data-theme="dark"] .pr-pill.on, :root[data-theme="dark"] .pr-chip.on { color: #0f1722; }
.pr-pill:disabled { opacity: .45; cursor: default; }
.pr-pill:focus-visible, .pr-chip:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.pr-filters { margin-bottom: 10px; }

/* Business hours. */
.pr-hours { border-top: 1px solid var(--line); padding-top: 4px; }
.pr-hours[hidden] { display: none; }
.pr-hours-row { display: flex; align-items: center; gap: 12px; padding: 7px 0; flex-wrap: wrap; }
.pr-hours-day { display: flex; align-items: center; gap: 10px; width: 150px; font-size: 13.5px; cursor: pointer; }
.pr-hours-times { display: flex; align-items: center; gap: 6px; }
.pr-hours-times[hidden], .pr-hours-closed[hidden] { display: none; }
.pr-hours-times select { width: auto; }

/* Questions callers ask. */
.pr-faqs { flex-direction: column; align-items: stretch !important; gap: 8px; width: 100%; }
.pr-faq { display: grid; grid-template-columns: 1fr 1.4fr auto; gap: 8px; align-items: start; }
.pr-faq textarea { min-height: 38px; }

/* What Riley calls about. */
.pr-out { display: flex; gap: 12px; align-items: flex-start; padding: 14px 0; border-top: 1px solid var(--line); }
.pr-out:first-child { border-top: 0; padding-top: 2px; }
.pr-out-t { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.pr-out-t > b { font-size: 14.5px; font-weight: 600; }
.pr-out-t > span { font-size: 12.5px; color: var(--slate); line-height: 1.4; }
.pr-out-chips { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.pr-rule { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 8px; background: var(--raise);
  font-size: 12.5px; color: var(--ink); }
.pr-rule input[type=number] { width: 58px; padding: 2px 6px; height: 26px; }
.pr-rule select { width: auto; padding: 2px 6px; height: 28px; font-size: 12.5px; max-width: 260px; }
.pr-rule input[type=checkbox] { accent-color: var(--pr-steel); margin: 0; }
.pr-rule-read { color: var(--slate); }
.pr-link { align-self: flex-start; margin-top: 8px; display: inline-flex; align-items: center; gap: 4px; padding: 0; border: 0; background: none;
  color: var(--blue); font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; text-decoration: none; }
.pr-out-c { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.pr-offnote { font-size: 11.5px; color: var(--slate); white-space: nowrap; }
.pr-offnote[hidden] { display: none; }

/* Calls. */
.pr-calls { display: flex; flex-direction: column; }
.pr-call { display: flex; gap: 12px; align-items: flex-start; padding: 12px 0; border-top: 1px solid var(--line); }
.pr-call:first-child { border-top: 0; }
.pr-call[hidden] { display: none; }
.pr-play { flex: none; width: 36px; height: 36px; border-radius: 50%; border: 0; display: inline-flex; align-items: center; justify-content: center;
  background: var(--pr-steel); color: #fff; cursor: pointer; }
.pr-play:disabled { background: var(--raise); color: var(--slate); cursor: default; }
:root[data-theme="dark"] .pr-play:not(:disabled) { color: #0f1722; }
.pr-call-who { flex: 1; min-width: 0; }
.pr-call-who b { font-size: 14px; }
.pr-call-who span { display: block; font-size: 12.5px; color: var(--slate); }
.pr-call-who p { margin: 4px 0 0; font-size: 13px; line-height: 1.4; }
.pr-call-who audio { width: 100%; max-width: 360px; margin-top: 6px; height: 34px; }
.pr-call-r { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.pr-out-chip { padding: 2px 9px; border-radius: 999px; font-size: 12px; font-weight: 600; background: var(--pr-steel-soft); color: var(--pr-steel); white-space: nowrap; }
.pr-call-when { font-size: 12px; white-space: nowrap; }
.pr-sample p { margin: 0 0 10px; font-size: 14px; line-height: 1.5; }
.pr-sample b.r { color: var(--blue); }
.pr-sample b.c { color: var(--green); }

@media (max-width: 760px) {
  .pr-band { padding: 16px 16px 0; border-radius: 14px; }
  .pr-band h1 { font-size: 20px; }
  .pr-band-line { align-items: flex-start; text-align: left; }
  .pr .pr-card { padding: 14px; }
  .pr-radios { grid-template-columns: 1fr; }
  .pr-row { flex-wrap: wrap; gap: 8px; }
  .pr-row-c { flex: 1 1 100%; justify-content: flex-start; flex-wrap: wrap; }
  .pr-row:has(> .pr-row-c > .pr-switch) { flex-wrap: nowrap; }
  .pr-row:has(> .pr-row-c > .pr-switch) > .pr-row-c { flex: none; }
  .pr-row-c > input:not([type=checkbox]), .pr-row-c > select, .pr-row-c > textarea { max-width: none; }
  .pr-faq { grid-template-columns: 1fr auto; }
  .pr-faq textarea { grid-column: 1 / -1; grid-row: 2; }
  .pr-call { flex-wrap: wrap; }
  .pr-call-r { flex-direction: row; align-items: center; flex-wrap: wrap; width: 100%; padding-left: 48px; }
  .pr-hours-day { width: 130px; }
  .pr-card-head { flex-wrap: wrap; }
  .pr-dot { margin-left: 48px; }
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .pr { --pr-steel: #9db0c0; }
  :root:not([data-theme="light"]) .pr-pill.on, :root:not([data-theme="light"]) .pr-chip.on,
  :root:not([data-theme="light"]) .pr-play:not(:disabled) { color: #0f1722; }
}
@media (max-width: 760px) {
  .pr-offnote { white-space: normal; text-align: right; max-width: 92px; }
}

/* ⭐ Follow-ups select all (11/7, Eric Roper). The boxes, the toolbar, and
   the bar pinned to the bottom while anything is ticked. On a phone it
   sits above the tab bar, and the floating New button steps aside. */
.fu-check { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; margin: 0; }
.fu-check input, .fu-hit input { width: 18px; height: 18px; margin: 0; cursor: pointer;
  accent-color: var(--blue); flex: none; }
.fu-check h3 { margin: 0; }
.fu-tools { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 10px 14px; }
td.fu-cb { vertical-align: top; padding-left: 8px; padding-right: 0; }
.fu-hit { display: inline-flex; padding: 2px 6px 6px 2px; cursor: pointer; }
/* Fixed. `#main > :not(.brand-mark-wash)` makes every child of the view
   relative, so the position needs the id to win. */
#main > .fu-bar { position: fixed; }
.fu-bar { position: fixed; bottom: calc(16px + env(safe-area-inset-bottom, 0px)); z-index: 60;
  left: 50%; transform: translateX(-50%); width: min(720px, calc(100vw - 32px));
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  padding: 10px 12px; box-shadow: var(--shadow-pop); }
.fu-bar[hidden] { display: none; }
@media (max-width: 760px) {
  .fu-bar { bottom: calc(84px + env(safe-area-inset-bottom, 0px)); gap: 6px; padding: 8px 10px;
    left: 10px; right: 10px; width: auto; transform: none; }
  body.fu-selecting[data-route="followups"] .main { padding-bottom: calc(170px + env(safe-area-inset-bottom, 0px)); }
  .fu-bar strong { flex-basis: 100%; font-size: 13px; }
  .fu-bar .grow { display: none; }
  .fu-bar .btn { flex: 1 1 auto; }
  body[data-route="followups"].fu-selecting .fab,
  body[data-route="followups"].fu-selecting .fab-sheet { display: none; }
}
@media (min-width: 761px) {
  body.fu-selecting[data-route="followups"] .main { padding-bottom: 96px; }
}
