/* Splash Office, the Daylight direction (Mike approved 2026-08-28
   from the redesign canvas). Ocean blue refined: calm light surfaces,
   Public Sans, one accent, color reserved for meaning. Variable NAMES
   are unchanged on purpose so every page keeps working; the VALUES are
   the redesign. */
:root {
  --ink: var(--op-17233a,#17233A);
  --muted: var(--op-5e6e87,#5E6E87);
  --line: var(--op-e4eaf3,#E4EAF3);
  --paper: var(--op-f6f8fb,#F6F8FB);
  --card: #FFFFFF;
  --brand: var(--op-0b5fa5,#0B5FA5);
  --brand-deep: var(--op-083a5d,#083A5D);
  --brand-tint: var(--op-eaf2fa,#EAF2FA);
  --accent: var(--op-0e9c9c,#0E9C9C);
  --danger: #B3261E;
  --danger-bg: #FBE9E7;
  --amber: #8A5A00;
  --amber-bg: #FFF4D9;
  --amber-line: #E39A0C;   /* graphics only, never text */
  --ok: #178A50;
  --ok-bg: #E4F5EC;
  --shadow: 0 1px 3px rgba(23, 35, 58, .07);
}
* { box-sizing: border-box; }
body { margin: 0; font: 14.5px/1.45 "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; color: var(--ink); background: var(--paper); }
a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }

.shell { display: flex; min-height: 100vh; }
/* The sidebar is its own scroll region pinned to the viewport, so a
   long menu and a long page scroll independently. align-self is load
   bearing: without it the flex container stretches the sidebar to the
   full page height and sticky has nothing to pin against. */
.sidebar { width: 210px; background: var(--brand-deep); color: #fff; display: flex;
  flex-direction: column; flex-shrink: 0; position: sticky; top: 0;
  align-self: flex-start; height: 100vh; overflow-y: auto;
  overscroll-behavior: contain; }
/* No width transition here on purpose: animating a flex item's width
   against the sticky container left the collapsed sidebar stuck at
   its full width, measured repeatedly in a real browser. Collapsing
   instantly is also just better. */
.side-head { padding: 18px 16px; font-weight: 700; font-size: 17px; }
.side-head a { color: #fff; }
.sidebar nav { display: flex; flex-direction: column; padding: 6px 8px; gap: 2px; flex: 1; }
.sidebar nav a { color: var(--op-cfe2f3,#CFE2F3); padding: 8px 11px; border-radius: 9px;
  display: flex; align-items: center; gap: 10px; font-weight: 500; }
.sidebar nav a:hover { background: rgba(255,255,255,.08); text-decoration: none; }
.sidebar nav a.on { background: rgba(255,255,255,.15); color: #fff; font-weight: 650; }
.nav-ic { flex-shrink: 0; opacity: .85; }
.sidebar nav a .nav-badge { margin-left: auto; }
/* Frequency, not category: the five daily pages sit ungrouped at the
   top, the rest live under quiet labels, and the touch-once pages
   hide inside Setup. Badges appear only when something is waiting. */
.nav-label { color: var(--op-7e9db8,#7E9DB8); font-size: 10.5px; letter-spacing: .09em;
  text-transform: uppercase; font-weight: 700; margin: 14px 10px 3px; }
.nav-badge { background: #FDB913; color: var(--op-173b52,#173B52); border-radius: 99px;
  padding: 0 7px; font-size: 11.5px; font-weight: 700; }
.nav-setup { margin-top: 14px; }
.nav-setup > summary { color: var(--op-7e9db8,#7E9DB8); font-size: 10.5px; letter-spacing: .09em;
  text-transform: uppercase; font-weight: 700; margin: 0 10px 3px; cursor: pointer;
  list-style: none; padding: 4px 0; }
.nav-setup > summary::-webkit-details-marker { display: none; }
.nav-setup > summary::after { content: " +"; }
.nav-setup[open] > summary::after { content: " -"; }
.nav-setup > summary:hover { color: var(--op-cfe2f3,#CFE2F3); }
.side-foot a { font-size: 13px; }
.side-foot { padding: 12px 16px; font-size: 13px; color: var(--op-9fb8ce,#9FB8CE); display: flex; flex-direction: column; gap: 4px; }
.side-foot a { color: var(--op-cfe2f3,#CFE2F3); }
/* SCREEN REAL ESTATE (Mike, 2026-08-15). The office works in this all
   day on 24 to 27 inch monitors, and a 1200px cap left roughly half of a
   2560px screen empty, which cost far more than the browser's own bars
   ever did. So the cap is now generous and, on the pages that are
   genuinely a board or a table, gone entirely.
   The cap still exists at all because a line of prose 2000px wide is
   unreadable; the answer is to widen the CONTAINER and keep the TEXT
   measured, which is what the prose rule below does. */
main { flex: 1; padding: 18px 24px; max-width: 1700px; min-width: 0; }
main.wide { max-width: none; }
/* Explanatory text stays at a readable measure however wide the page
   gets. Scoped to a card's own paragraphs so it can never squeeze text
   inside a table cell or a form row. */
.card > p, .card > .hint, main > .hint { max-width: 82ch; }
.menu-btn { display: none; }

/* Collapse to a narrow strip. The toggle is the one child that stays
   visible, so there is always a way back. The reading cap lifts while
   collapsed, which is the entire point of collapsing. */
/* A small tab, not a full width bar: it should read as a handle on
   the edge of the panel, not as a menu item (Mike, 2026-08-15). */
.side-toggle { border: 0; background: rgba(255,255,255,.10); color: var(--op-cfe2f3,#CFE2F3);
  cursor: pointer; font-size: 14px; line-height: 1; width: 30px; height: 26px;
  padding: 0; margin: 9px 8px 2px auto; border-radius: 7px; flex-shrink: 0; }
.side-toggle:hover { background: rgba(255,255,255,.2); color: #fff; }
html.nav-collapsed .sidebar { width: 46px; }
html.nav-collapsed .side-toggle { margin-right: auto; margin-left: auto; }
html.nav-collapsed .sidebar > *:not(.side-toggle) { display: none; }
html.nav-collapsed main { max-width: none; }

/* INSTALLED AS AN APP. There is no tab strip and no address bar, which is
   most of the point, so the page can start a little higher. The cost of
   display: standalone is that the browser's Back button goes with them,
   and this app drills down constantly (customer, then job, then invoice),
   so we put Back back ourselves. It exists in every window and only
   shows itself in the installed app. */
.app-back { display: none; }
html.standalone .app-back { display: inline-flex; align-items: center; gap: 6px;
  background: transparent; border: 1px solid var(--line); color: var(--muted);
  border-radius: 8px; padding: 4px 10px; font: inherit; font-size: 13px;
  cursor: pointer; margin-bottom: 10px; }
html.standalone .app-back:hover { border-color: var(--brand); color: var(--brand); }
html.standalone main { padding-top: 12px; }

h1 { font-size: 19px; font-weight: 700; margin: 0 0 12px; }
h2 { font-size: 16.5px; margin: 18px 0 8px; }
h3 { font-size: 15px; margin: 13px 0 7px; }

.card { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 14px 17px; margin-bottom: 13px; box-shadow: var(--shadow); }
.grid { display: grid; gap: 14px; }
.grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.stat { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 13px 16px; box-shadow: var(--shadow); }
.stat .n { font-size: 24px; font-weight: 700; color: var(--brand); font-variant-numeric: tabular-nums; }
.stat .l { color: var(--muted); font-size: 12.5px; font-weight: 500; }

table { border-collapse: collapse; width: 100%; background: var(--card); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; box-shadow: var(--shadow); }
th, td { text-align: left; padding: 8px 11px; border-bottom: 1px solid var(--line); font-size: 13.5px; vertical-align: top; font-variant-numeric: tabular-nums; }
th { background: var(--card); color: var(--muted); font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; border-bottom: 2px solid var(--line); }
tr:last-child td { border-bottom: none; }

form.inline { display: inline; }
label { display: block; font-size: 13px; color: var(--muted); margin: 8px 0 2px; }
input, select, textarea { font: inherit; padding: 7px 10px; border: 1px solid var(--line); border-radius: 9px; width: 100%; max-width: 420px; background: #fff; }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--brand-tint); border-color: var(--brand); }
textarea { min-height: 70px; }
.row { display: flex; gap: 12px; flex-wrap: wrap; }
.row > div { flex: 1; min-width: 140px; }

.btn { display: inline-flex; align-items: center; gap: 7px; background: var(--brand); color: #fff; border: none; border-radius: 9px; padding: 7px 14px; font: inherit; font-weight: 600; cursor: pointer; }
.btn:hover { background: var(--brand-deep); text-decoration: none; }
.btn.ghost { background: var(--card); color: var(--ink); border: 1px solid var(--line); font-weight: 500; }
.btn.ghost:hover { background: var(--card); border-color: var(--brand); color: var(--brand); }
.btn.danger { background: transparent; color: var(--danger); border: 1px solid var(--line); }
.btn.danger:hover { background: var(--danger-bg); border-color: var(--danger); }
.btn.small { padding: 4px 10px; font-size: 12.5px; }

.badge { display: inline-flex; align-items: center; gap: 6px; padding: 2px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 600; white-space: nowrap; }
.badge::before { content: ""; width: 6px; height: 6px; border-radius: 99px; background: currentColor; flex-shrink: 0; }
.badge.ok { background: var(--ok-bg); color: var(--ok); }
.badge.pending { background: var(--amber-bg); color: var(--amber); }
.badge.danger { background: var(--danger-bg); color: var(--danger); }
.badge.muted { background: var(--brand-tint); color: var(--brand-deep); }

.brand-logo { width: auto; vertical-align: middle; display: inline-block; }
.brand-chip { display: inline-block; padding: 2px 9px; border-radius: 999px; color: #fff; font-size: 12px; font-weight: 600; }
.hint { color: var(--muted); font-size: 13px; }
.msg-ok { color: var(--ok); font-size: 14px; }
.msg-err { color: var(--danger); font-size: 14px; }
.right { text-align: right; }

.login-wrap { min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; background: var(--brand-deep); }
.login-card { background: #fff; border-radius: 14px; padding: 30px 34px; width: 360px; }
.login-card h1 { color: var(--brand-deep); }

@media (max-width: 860px) {
  .shell { flex-direction: column; }
  /* On a phone the menu button owns showing and hiding, so the
     sidebar goes back to flowing with the page and the collapse
     toggle would just be a second confusing control. */
  .sidebar { width: 100%; display: none; position: static; height: auto; }
  .sidebar.open { display: flex; }
  .side-toggle { display: none; }
  html.nav-collapsed .sidebar { width: 100%; }
  html.nav-collapsed .sidebar > * { display: block; }
  html.nav-collapsed .sidebar > nav { display: flex; }
  .menu-btn { display: inline-block; margin-bottom: 10px; background: var(--brand); color: #fff; border: none; border-radius: 8px; padding: 6px 12px; }
  main { padding: 14px; }
  .grid.cols-3, .grid.cols-2 { grid-template-columns: 1fr; }
}

/* Who can drive, at a glance on the dispatch board (Mike, 2026-08-17).
   A crew is made up by eye in a hurry, so the licence has to be visible
   while the crew is being made, not discovered when the truck cannot
   leave. Colour is a cue and never the only signal: the name carries a
   tooltip, and a crew with nobody licensed says so in words. */
.who { font-weight: 600; }
.who.lic { color: var(--brand-deep); }
.who.nolic { color: var(--muted); text-decoration: underline dotted var(--amber); }
.crew-nodrive { margin: 6px 0 8px; padding: 7px 10px; border-radius: 8px;
  background: var(--amber-bg); color: var(--amber); font-size: 13px; font-weight: 600; }

/* ---- The walkthrough ------------------------------------------------
   A guide that sits over the real pages, so these styles have to read
   clearly on top of any page in the app without moving its layout.

   The ring is AMBER, not brand blue, and that is deliberate: an active
   control is often already brand blue, and a brand ring around it is
   invisible. Amber is the app's "look here" colour everywhere else too. */
.guide-ring {
  outline: 3px solid var(--amber-line);
  outline-offset: 3px;
  border-radius: 8px;
}
.guide-bubble {
  border: 1px solid var(--brand);
  background: var(--brand-tint);
  border-radius: 12px;
  padding: 12px 16px 13px;
  margin: 12px 0;
  max-width: 560px;
  box-shadow: 0 6px 20px rgba(22, 35, 59, .13);
}
.guide-bubble h3 { margin: 2px 0 6px; font-size: 17px; }
.guide-bubble p { margin: 0 0 8px; font-size: 14.5px; }
.guide-eyebrow {
  font-size: 12.5px; font-weight: 600; letter-spacing: .01em;
  color: var(--brand-deep); margin: 0 0 2px !important;
}
.guide-count { float: right; font-weight: 500; letter-spacing: 0; opacity: .8; }
/* Black, not muted: an extra carries a second real thing to know,
   not a footnote about the software (Mike, 2026-08-23). */
.guide-extra { color: var(--ink); }
/* Black, not a muted aside: on the customer tour these lines carry real
   content Mike wrote, not a footnote about the software. */
.guide-missing { color: var(--ink); }
.guide-actions { display: flex; gap: 8px; margin-top: 10px; }
/* The card's built-in illustration: a mock of the screen or the email
   the step describes, drawn in HTML so it survives the demo data being
   deleted at go-live and never shows a real customer. */
.guide-art { margin: 2px 0 10px; }
.guide-art svg { max-width: 100%; height: auto; display: block; }
.guide-art img { max-width: 100%; }

/* The guide index. Sections are collapsed by default so the whole walk
   is one screen you can scan, not a wall you have to scroll. */
.guide-section { border-top: 1px solid var(--line); padding: 2px 0; }
.guide-section:first-of-type { border-top: 0; }
.guide-section > summary {
  cursor: pointer; padding: 9px 2px; font-weight: 600; list-style: none;
}
.guide-section > summary::-webkit-details-marker { display: none; }
.guide-section > summary::before { content: "\25B8  "; color: var(--muted); }
.guide-section[open] > summary::before { content: "\25BE  "; }
.guide-section .g-mins { float: right; font-weight: 400; color: var(--muted); font-size: 13px; }
.guide-steps { margin: 0 0 10px; padding: 0 0 0 22px; }
.guide-steps li { margin: 4px 0; font-size: 14px; }
.guide-idea {
  border-left: 3px solid var(--brand); background: var(--card);
  border: 1px solid var(--line); border-left: 3px solid var(--brand);
  padding: 9px 13px; border-radius: 0 8px 8px 0; margin: 0 0 12px;
}

/* The nav link the highlighted control lives under, lit at the same
   time as the control itself (Mike, 2026-08-23). Without it a card
   explains a page without ever saying how you get back to it, which is
   the one thing somebody being taught most needs to know. It is a fill
   rather than a ring because the sidebar is dark navy and a ring on it
   reads as a smudge. */
.sidebar nav a.guide-nav-on,
.sidebar nav a.on.guide-nav-on,
.portal-nav a.guide-nav-on,
.portal-nav a.on.guide-nav-on {
  background: var(--amber-line);
  color: var(--op-16233b,#16233B);
  font-weight: 700;
  border-radius: 6px;
}
@media (max-width: 720px) {
  .guide-bubble { max-width: none; }
}

/* The start card leads the guide index, so it carries a little more
   weight than the cards under it without shouting. */
.guide-start { border-color: var(--brand); }
.guide-start h2 { color: var(--brand-deep); }

/* ---- The customer portal shell -------------------------------------
   One bar, brand mark always upper left, and it has to read on a phone
   in a driveway, a tablet on a kitchen counter, and a desktop. The nav
   scrolls sideways rather than wrapping or collapsing behind a
   hamburger: a customer has five destinations, and a menu they have to
   open is a menu they do not use. */
.portal-top {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 10px 0 12px; margin-bottom: 14px;
  border-bottom: 1px solid var(--line);
}
.portal-brand {
  display: flex; align-items: center; gap: 9px; text-decoration: none;
  font-weight: 700; font-size: 19px; color: var(--ink); flex: 0 0 auto;
}
.portal-brand:hover { text-decoration: none; }
.portal-nav {
  display: flex; gap: 4px; margin-left: auto; flex-wrap: nowrap;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.portal-nav::-webkit-scrollbar { display: none; }
.portal-nav a {
  padding: 8px 12px; border-radius: 999px; white-space: nowrap;
  font-size: 14.5px; color: var(--muted); text-decoration: none;
}
.portal-nav a:hover { background: var(--brand-tint); color: var(--brand-deep); }
.portal-nav a.on { background: var(--brand); color: #fff; font-weight: 600; }

/* SPLASH SAYS IT. A helper card is drawn as a speech bubble with him
   beside it, so the words read as his rather than as the software's
   (Mike, 2026-08-23). The tail is a rotated square, which stays put at
   any card height and costs no image. */
.splash-say { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 12px; }
.splash-say > img { width: 52px; flex: 0 0 52px; margin-top: 4px; }
.splash-bubble {
  position: relative; flex: 1 1 auto;
  background: var(--brand-tint); border: 1px solid var(--brand);
  border-radius: 14px; padding: 12px 16px;
}
.splash-bubble::before {
  content: ""; position: absolute; left: -7px; top: 20px;
  width: 12px; height: 12px; transform: rotate(45deg);
  background: var(--brand-tint);
  border-left: 1px solid var(--brand); border-bottom: 1px solid var(--brand);
}
.splash-bubble p:last-child { margin-bottom: 0; }
@media (max-width: 560px) {
  .splash-say > img { width: 40px; flex: 0 0 40px; }
  .portal-brand { font-size: 17px; }
  .portal-nav { margin-left: 0; width: 100%; flex-wrap: wrap; overflow: visible; }
}

/* ---- Dispatch, map first (Mike's pick, 2026-08-23) ------------------
   The map holds the left half and stays put; the crews scroll beside
   it. Hiding the map collapses to one column. On a narrow screen the
   split stacks, map on top at a shorter height, because half of a
   phone is no map at all. */
.disp-toolbar { display: flex; align-items: center; gap: 10px;
  flex-wrap: wrap; padding: 10px 14px; }
.disp-split { display: grid; grid-template-columns: minmax(380px, 1fr) 1fr;
  gap: 14px; align-items: start; }
/* THE MAP IS ALWAYS WHOLE, AND THE LIST SCROLLS PAST IT (Mike,
   2026-08-29: "i have to scroll to the bottom of the customer list to
   get to the bottom of the map"). A sticky element TALLER than the
   window pins its top and puts its OWN bottom permanently out of
   reach: it only came back into view once the crew column ended, so
   reaching the legend meant scrolling the entire list. Two fixes, and
   the pair is the point: the column can never exceed the window (and
   scrolls inside itself if it somehow does), and the map sizes to the
   space actually there instead of a fixed 560px. */
.disp-map-col { position: sticky; top: 12px;
  max-height: calc(100vh - 24px); overflow-y: auto; }
/* 230px is the card around the map MEASURED, not guessed: a header
   that wraps to three lines in a half width column (107), the legend
   (38), margins, padding and border come to 191, and the rest is room
   for a legend that wraps further on a busy day. */
#dispatchMap { height: clamp(300px, calc(100vh - 230px), 560px); }
.disp-stop { display: flex; align-items: baseline; gap: 7px;
  border: 1px solid var(--line); border-radius: 8px;
  padding: 6px 10px; margin-bottom: 6px; flex-wrap: wrap; }
.disp-stop:hover { border-color: var(--brand); background: var(--brand-tint); }
.disp-menu { position: relative; display: inline-block; }
.disp-menu > summary { list-style: none; cursor: pointer; }
.disp-menu > summary::-webkit-details-marker { display: none; }
.disp-menu-pop { position: absolute; right: 0; top: 115%; z-index: 30;
  background: var(--card); border: 1px solid var(--line);
  border-radius: 10px; padding: 10px 12px; white-space: nowrap;
  box-shadow: 0 6px 20px rgba(22, 35, 59, .13); }
.disp-stop .disp-menu > summary { padding: 0 6px; color: var(--muted);
  font-size: 17px; }
@media (max-width: 980px) {
  .disp-split { grid-template-columns: 1fr; }
  .disp-map-col { position: static; max-height: none; overflow: visible; }
  #dispatchMap { height: 320px !important; }
}

/* REPORTS AS DISCLOSURES (Mike, 2026-08-26: "way too cluttered").
   Six long sections stacked on one page meant scrolling past five to
   reach the one you wanted. Each is a disclosure now, closed by
   default, so the page opens as a list of what is here and you open
   the one you came for. Same shape as the walkthrough's sections, on
   purpose: one idiom for "there is more inside this". */
.rep-section { border-top: 1px solid var(--line); }
.rep-section:first-of-type { border-top: 0; }
.rep-section > summary {
  cursor: pointer; padding: 13px 2px; font-size: 17px; font-weight: 600;
  list-style: none;
}
.rep-section > summary::-webkit-details-marker { display: none; }
.rep-section > summary::before { content: "\25B8  "; color: var(--muted); }
.rep-section[open] > summary::before { content: "\25BE  "; }
.rep-section > summary:hover { color: var(--brand); }
.rep-section .rep-body { padding: 0 2px 14px; }
.grid.cols-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
@media (max-width: 900px) { .grid.cols-4 { grid-template-columns: repeat(2, 1fr); } }

/* ROW CHECKBOXES ARE TAP TARGETS (Mike, 2026-08-26: "extremely
   small"). Every list checkbox gets a real finger-sized box. */
.th-check, .obx-check, .aud-check,
table input[type="checkbox"] {
  width: 20px; height: 20px; accent-color: var(--brand, var(--op-16607a,#16607A));
  cursor: pointer;
}

/* BILLING TABS (Mike, 2026-08-26: "make it obvious those are three
   tabs"). Real tabs, not small ghost buttons: big labels, an
   underline on the active one. */
.bill-tabs { display: flex; gap: 4px; border-bottom: 2px solid var(--line); margin: 0 0 16px; }
.bill-tabs a {
  padding: 10px 22px; font-size: 17px; font-weight: 600;
  color: var(--muted, var(--op-5f7484,#5F7484)); text-decoration: none;
  border-bottom: 3px solid transparent; margin-bottom: -2px;
}
.bill-tabs a.on { color: var(--ink, var(--op-16303f,#16303F)); border-bottom-color: var(--brand, var(--op-16607a,#16607A)); }
.bill-tabs a:hover { color: var(--ink, var(--op-16303f,#16303F)); }

/* THE OFFER SHEET IS A REAL GRID (Mike, 2026-08-28: rows and columns
   line up, use the space). One track list shared by the header and
   every row, so nothing can drift out of column. */
.svc-grid, .svc-grid-head {
  display: grid;
  grid-template-columns: minmax(210px, 1fr) 34px 70px 110px 158px 78px;
  gap: 8px; align-items: center;
}
.svc-scroll { overflow-x: auto; }
.svc-scroll .svc-grid, .svc-scroll .svc-grid-head { min-width: 690px; }
.svc-grid { padding: 3px 0; border-bottom: 1px solid var(--line); }
.svc-grid-head { padding: 4px 0; border-bottom: 2px solid var(--line);
                 font-weight: 600; position: sticky; top: 0; background: var(--bg, #fff); }
@media (max-width: 760px) {
  .svc-grid, .svc-grid-head { grid-template-columns: minmax(150px, 1fr) 30px 58px 90px 110px 70px; font-size: 13px; }
}


/* ---- The redesign's shared patterns (2026-08-28) ------------------ */
.eyebrow { font-size: 11px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted); margin: 0 0 9px; }

/* Crew lanes: the day's shape in one glance, every crew's route as
   blocks on a shared clock. Widths follow the stop's minutes; this is
   a schedule schematic, not a GPS claim. */
.lanes { border-top: 1px solid var(--line); margin: 0 -17px;
  overflow-x: auto; }   /* a 17:45 day scrolls instead of clipping */
.lane { display: flex; align-items: center; border-bottom: 1px solid var(--line);
  min-width: fit-content; }
.lane:last-child { border-bottom: none; }
.lane-head { width: 210px; flex-shrink: 0; padding: 9px 14px;
  /* Crew names stay put while the clock scrolls under them. */
  position: sticky; left: 0; background: var(--card); z-index: 2; }
.lane-head b { font-size: 13px; }
.lane-head .hint { font-size: 11.5px; font-variant-numeric: tabular-nums; }
.lane-track { flex: 1; position: relative; height: 40px; overflow: hidden;
  background: repeating-linear-gradient(90deg, transparent 0 93px, var(--line) 93px 94px); }
.lane-block { position: absolute; top: 7px; height: 26px; border-radius: 6px;
  display: flex; align-items: center; padding: 0 7px; font-size: 10.5px;
  color: var(--ink); overflow: hidden; white-space: nowrap; border: 1px solid; }

/* Filter chips: quiet until picked; the picked one carries its count. */
.chip { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--line);
  border-radius: 999px; padding: 4px 13px; font-size: 12.5px; color: var(--muted);
  background: var(--card); cursor: pointer; }
.chip:hover { text-decoration: none; border-color: var(--brand); color: var(--brand); }
.chip-on { background: var(--brand-tint); color: var(--brand); border-color: rgba(11,95,165,.33);
  font-weight: 650; }


/* The page head band (the approved boards' topbar): the page's name,
   its context, and its primary actions in one white bar before the
   work. Adopted page by page. */
.page-head { display: flex; align-items: center; gap: 13px; flex-wrap: wrap;
  background: var(--card); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow); padding: 11px 17px; margin: 0 0 13px; }
.page-head h1 { margin: 0; font-size: 18px; }
.page-head .ctx { color: var(--muted); font-size: 13px; }
.page-head .spacer { flex: 1; }

/* Row avatars: the initial in a tinted circle, the boards' list look. */
.avatar { width: 32px; height: 32px; border-radius: 999px; background: var(--brand-tint);
  color: var(--brand); display: inline-flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 12.5px; flex-shrink: 0; }

/* CSS bar chart, no library: a row of bottom-aligned bars. */
.bars { display: flex; align-items: flex-end; gap: 13px; height: 120px; padding: 4px 2px 0; }
.bars .bar { display: flex; flex-direction: column; align-items: center; gap: 5px; }
.bars .bar i { display: block; width: 30px; border-radius: 6px 6px 0 0; background: var(--brand); opacity: .4; }
.bars .bar.hot i { opacity: 1; }
.bars .bar b { font-size: 11px; color: var(--muted); font-weight: 600; }

/* Live lanes: the drop target glow, the flash on the jumped-to stop,
   and the now line on today's axis. */
.lane-over { outline: 2px solid var(--brand); outline-offset: -2px; background: var(--brand-tint); }
.lane-nowline { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--danger); opacity: .55; pointer-events: none; }
.stop-flash { background: var(--amber-bg) !important; transition: background .3s; }

/* Never -webkit-user-drag: element here: that makes the block NATIVELY
   draggable, and the native drag fires pointercancel, which kills the
   pointer-event dragging that actually moves stops between lanes. */
.lane-block { -webkit-user-drag: none; user-select: none; -webkit-user-select: none; }


/* Billing's three tabs as the boards' chip row. */
.bill-tabs { display: flex; gap: 8px; margin: 0 0 13px; }
.bill-tabs a { border: 1px solid var(--line); border-radius: 999px; padding: 5px 15px;
  font-size: 13px; color: var(--muted); background: var(--card); text-decoration: none; }
.bill-tabs a:hover { border-color: var(--brand); color: var(--brand); }
.bill-tabs a.on { background: var(--brand-tint); color: var(--brand);
  border-color: rgba(11,95,165,.33); font-weight: 650; }


/* Segmented choices: real radios wearing pills, the boards' control. */
.seg-row { display: flex; gap: 7px; flex-wrap: wrap; }
.seg { border: 1px solid var(--line); border-radius: 8px; padding: 6px 14px;
  font-size: 13px; color: var(--muted); cursor: pointer; margin: 0; display: inline-flex; }
.seg input { display: none; }
.seg:has(input:checked) { background: var(--brand-tint); color: var(--brand);
  border-color: rgba(11,95,165,.33); font-weight: 650; }
.lane-block { touch-action: none; }
.prop-block { touch-action: none; user-select: none; -webkit-user-select: none;
  -webkit-user-drag: none; }

/* THE INFO DOT (Mike, 2026-08-29: "a little info button that creates
   text when you hover... utilized other places in app when
   appropriate"). A small circled i beside a label; hover or keyboard
   focus opens the full explanation, so the page carries one short line
   and the detail waits until asked for. Usage:
   <span class="info" tabindex="0">i<span class="tip">...</span></span> */
.info { display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; border-radius: 999px; border: 1px solid var(--muted);
  color: var(--muted); font-size: 10px; font-weight: 700; font-style: normal;
  cursor: help; position: relative; vertical-align: 1px; margin-left: 5px;
  user-select: none; }
.info .tip { display: none; position: absolute; z-index: 60; left: 50%;
  transform: translateX(-50%); bottom: calc(100% + 7px); width: 250px;
  background: var(--ink); color: #fff; font-size: 12px; font-weight: 400;
  line-height: 1.45; border-radius: 8px; padding: 8px 11px; text-align: left;
  box-shadow: 0 8px 22px rgba(23,35,58,.28); white-space: normal; }
.info:hover .tip, .info:focus .tip { display: block; }

/* CREATE A QUOTE, collapsed (Mike, 2026-08-29). The summary IS the
   button, so the four kinds stay out of the way until wanted. */
.new-quote > summary { list-style: none; display: inline-block; cursor: pointer; }
.new-quote > summary::-webkit-details-marker { display: none; }
.new-quote[open] > summary { background: var(--card); color: var(--brand);
  border: 1px solid var(--brand); }

/* THE BILLING FILTER BAR (Mike, 2026-08-29: "they dont line up").
   .row makes every child flex:1, so a search box, three dropdowns and
   a date field all stretched to the same arbitrary width and wrapped
   raggedly. Here each control gets the width it actually needs, they
   sit on one baseline, and the buttons never stretch. */
.filter-bar { display: flex; flex-wrap: wrap; align-items: center;
  gap: 8px; margin: 0 0 4px; }
.filter-bar > * { margin: 0; }
.filter-bar .fb-search { flex: 1 1 200px; min-width: 170px; max-width: 320px; }
.filter-bar select { width: auto; min-width: 130px; max-width: none; }
.filter-bar .rangepick { width: 150px; max-width: none; }
.filter-bar .fb-go { margin-left: auto; display: flex; gap: 8px; align-items: center; }
.filter-bar input, .filter-bar select, .filter-bar .btn { height: 36px; }
.filter-bar .btn { padding-top: 0; padding-bottom: 0; }
@media (max-width: 820px) {
  .filter-bar .fb-go { margin-left: 0; }
  .filter-bar .fb-search { max-width: none; }
}
/* Bulk actions under a filter bar: their own line behind a rule, so a
   whole form and a couple of buttons stop fighting for one flex row. */
.fb-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }

/* Walkthrough panels float independently of the product's layout. */
.guide-bubble{position:fixed;z-index:1100;box-sizing:border-box;width:min(380px,calc(100vw - 24px));max-width:none;max-height:calc(100dvh - 32px);overflow:auto;overscroll-behavior:contain;margin:0;padding:18px;background:#fff;border:1px solid var(--op-8fbbd8,#8fbbd8);border-top:4px solid var(--op-2582be,#2582be);box-shadow:0 12px 36px var(--op-1236542b,#1236542b);left:12px;top:12px}
.guide-bubble:focus{outline:none}
.guide-bubble h3{font-size:19px;padding-right:22px}
.guide-bubble p{font-size:14px;line-height:1.55}
.guide-bubble .guide-eyebrow{padding-right:26px;display:flex;gap:12px;justify-content:space-between;font-size:11px}
.guide-bubble .guide-count{float:none;white-space:nowrap}
.guide-close{position:absolute;top:7px;right:7px;border:0;background:transparent;color:var(--op-35546b,#35546b);font-size:25px;cursor:pointer;width:32px;height:32px;border-radius:6px}
.guide-close:hover{background:var(--op-eaf3f8,#eaf3f8)}
.guide-example{border:1px solid var(--op-d4e3ec,#d4e3ec);border-radius:8px;background:var(--op-f6fafc,#f6fafc);margin:10px 0;padding:7px 10px}
.guide-example summary{font-size:13px;font-weight:600;cursor:pointer}
.guide-example .guide-art{margin-top:10px}
.guide-locate{background:none;border:0;padding:4px 0;color:var(--op-17639a,#17639a);text-decoration:underline;font-size:12px;cursor:pointer}
.guide-actions{position:sticky;bottom:-18px;background:#fff;padding:12px 0 4px;justify-content:space-between;flex-wrap:wrap;border-top:1px solid var(--op-e0eaf0,#e0eaf0)}
.guide-bubble :focus-visible{outline:3px solid #c17f13;outline-offset:2px}
.guide-ring{scroll-margin-top:24px}
@media(max-width:760px){.guide-bubble{max-height:46dvh;padding:14px}.guide-bubble h3{font-size:17px}.guide-bubble p{font-size:13px}.guide-actions{bottom:-14px}}

/* Wide operational grids scroll within their own card on phones. */
.team-layout,.team-layout>.card{min-width:0}
.timecard-week{overflow-x:auto}
.service-matrix-scroll{max-width:100%;overflow-x:auto}
@media(max-width:760px){.team-layout{grid-template-columns:minmax(0,1fr)!important}.badge{max-width:100%;white-space:normal;overflow-wrap:anywhere}}
[data-guide-resume][hidden]{display:none}

/* Save/error feedback stays in view after returning to a lower form. */
.navigation-notice{position:fixed!important;bottom:18px;left:50%;transform:translateX(-50%);z-index:150;max-width:min(640px,calc(100vw - 32px));width:max-content;box-sizing:border-box;box-shadow:0 5px 24px #173b5226;display:flex;gap:16px;align-items:center;max-height:35vh;overflow:auto}
.navigation-notice button{background:transparent;border:1px solid currentColor;border-radius:6px;padding:5px 9px;color:inherit;cursor:pointer;flex-shrink:0}

/* Online booking access details wait here until the office accepts them. */
.office-job-access-proposal{margin:18px 0;padding:16px;border:1px solid var(--op-b9dcd5,#b9dcd5);border-radius:12px;background:var(--op-f3faf8,#f3faf8)}
.office-job-access-proposal h3{margin:0 0 5px;font-size:16px;line-height:24px}
.office-job-access-proposal p{margin:6px 0;overflow-wrap:anywhere}
.office-job-saved-access{margin:10px 0;color:var(--muted);font-size:.9rem}
.office-job-saved-access summary{cursor:pointer;color:var(--link)}
.office-job-saved-access p{white-space:pre-wrap;margin:7px 0 0;overflow-wrap:anywhere}
.office-job-access-proposal-text{white-space:pre-wrap}
.office-job-access-proposal-actions{display:flex;flex-wrap:wrap;gap:9px;margin-top:12px}
.office-job-access-proposal-actions form{margin:0}
.office-job-access-proposal textarea{display:block;width:100%;min-height:74px;max-width:100%;margin:5px 0 12px;font:inherit}
.office-job-access-choice{border:0;padding:0;margin:0 0 12px}
.office-job-access-choice legend{font-size:13px;font-weight:700;margin-bottom:4px}
.office-job-access-choice label{display:flex;align-items:center;gap:8px;min-height:36px;margin:0;font-size:13px}
.office-job-access-choice input{width:auto;margin:0;flex:none}
.office-job-gate-choice{border-top:1px solid var(--op-d3e7e2,#d3e7e2);padding-top:10px}
.office-job-gate-choice summary{font-size:13px;font-weight:700;color:var(--op-086c82,#086c82);cursor:pointer;min-height:32px}
.office-job-gate-choice label{display:block;margin:6px 0 3px;font-size:13px}
.office-job-gate-choice input{max-width:300px;width:100%;font-size:16px}

/* New-job routing reuses the job page's skill and people choices. */
/* Keep map panes inside the map, beneath the fixed Splash panel. */
.leaflet-container{isolation:isolate}
.office-job-routing-choices{border:1px solid var(--line);border-radius:10px;padding:14px;margin:12px 0}
.office-job-routing-choices[hidden]{display:none}
.office-job-routing-choices legend{font-weight:700;padding:0 6px}
.office-job-routing-choices>select{max-width:320px;margin-bottom:10px}
.office-job-capable-people{display:flex;flex-wrap:wrap;gap:6px 18px}
.office-job-capable-people label{display:flex;align-items:center;gap:6px;min-width:180px}
.office-job-create .office-job-capable-people input[type=checkbox]{width:auto;flex:none;margin:0}
