/* Jobby's look: a white workspace, the Schmidt navy kept for the one primary action, the book
   on screen, and colour otherwise only where it means something
   (status, notes, the one answer that can't be undone). Light mode only. See docs/shell.md. */

@font-face {
  font-family: "Geist";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/geist-latin-wght-normal.woff2") format("woff2-variations");
}

@font-face {
  font-family: "Geist Mono";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/geist-mono-latin-wght-normal.woff2") format("woff2-variations");
}

:root {
  color-scheme: light;

  --brand: #1d4e89;
  --brand-deep: #163f70;
  --brand-soft: #edf3fb;
  --brand-line: #cddcf0;

  --canvas: #f5f6f8;   /* fields, the segmented control, dialog footers */
  --surface: #ffffff;
  --ink: #101828;
  --ink-2: #4a5567;
  --ink-3: #8a94a6;
  --line: #e7eaef;
  --line-2: #f0f2f5;   /* between rows */

  /* Job statuses: text colour + tinted background. */
  --open: #2563eb;      --open-bg: #eef4ff;
  --done: #0f8a5f;      --done-bg: #e8f7f0;
  --cancelled: #6b7584; --cancelled-bg: #f1f3f6;
  --cancelled-text: #5f6978; /* a cancelled row's text: 5:1 on white */
  --error: #c93a1f;     --error-bg: #fdeeea;
  --error-deep: #a92e17;
  /* A note in the margin: a colour no status uses, so a note never reads as a status. */
  --note: #7a5000;      --note-bg: #fff6d6;   --note-line: #f1c94a;

  --radius: 10px;
  --topbar-h: 64px;
  --gutter: 32px;
  --shadow: 0 1px 2px rgba(16, 24, 40, .05);
  --shadow-float: 0 1px 2px rgba(16, 24, 40, .04), 0 12px 32px rgba(16, 24, 40, .12);
  --shadow-dialog: 0 24px 60px rgba(16, 24, 40, .22), 0 2px 6px rgba(16, 24, 40, .08);

  --font: "Geist", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "Geist Mono", ui-monospace, Consolas, monospace;
}

* { box-sizing: border-box; }

[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--surface);
  color: var(--ink);
  font: 14px/1.5 var(--font);
  -webkit-font-smoothing: antialiased;
}

button, input, select, textarea { font: inherit; }

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

.mono { font-family: var(--mono); }

/* Top bar */

.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 12px;
  height: var(--topbar-h);
  /* The logo's icon (38px) is centred over the folded sidebar's icons, 30px in. */
  padding: 0 var(--gutter) 0 11px;
  border-bottom: 1px solid var(--line);
  background: rgba(255, 255, 255, .94);
  backdrop-filter: blur(8px);
}

/* The logo: the bolt icon, with the name set as text beside it so it stays sharp and readable
   at any size. Its navy and teal are the logo's own, not the app's. */
.logo {
  display: flex;
  flex: none;
  gap: 10px;
  align-items: center;
}

.logo img {
  display: block;
  width: 38px;
  height: 38px;
}

.logo-text {
  display: flex;
  flex-direction: column;
  line-height: 1;
  text-align: left;
}

.logo-name {
  color: #17324d;
  font-size: 20px;
  font-weight: 750;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.logo-tag {
  margin-top: 4px;
  color: #2a7069;
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: .16em;
  text-transform: uppercase;
}

.button-icon {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}

.new-job {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 6px;
  padding: 0 14px 0 12px;
}

/* The search box on the bar: jobs, clients and contacts. */

.search {
  position: relative;
  width: 320px;
  margin-left: auto;
}

.search-icon {
  position: absolute;
  top: 50%;
  left: 11px;
  width: 15px;
  height: 15px;
  transform: translateY(-50%);
  fill: none;
  stroke: var(--ink-3);
  stroke-width: 2;
  stroke-linecap: round;
  pointer-events: none;
}

.search-input {
  width: 100%;
  height: 36px;
  padding: 0 34px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--canvas);
  color: var(--ink);
  -webkit-appearance: none;
  appearance: none;
}

.search-input::placeholder { color: var(--ink-3); }
.search-input::-webkit-search-cancel-button { -webkit-appearance: none; }

.search-input:focus {
  border-color: var(--brand-line);
  outline: none;
  background: var(--surface);
  box-shadow: 0 0 0 3px var(--brand-soft);
}

.search-key {
  position: absolute;
  top: 50%;
  right: 8px;
  min-width: 20px;
  padding: 0 6px;
  transform: translateY(-50%);
  border: 1px solid var(--line);
  border-radius: 5px;
  background: var(--surface);
  color: var(--ink-3);
  font: 500 11px/18px var(--mono);
  text-align: center;
  pointer-events: none;
}

.search-input:focus ~ .search-key,
.search-input:not(:placeholder-shown) ~ .search-key { display: none; }

.search-results {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  width: min(500px, calc(100vw - 32px));
  max-height: 60vh;
  overflow-y: auto;
  padding: 6px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-float);
}

.search-result {
  display: grid;
  /* A fixed first column keeps companies lined up across results. */
  grid-template-columns: 92px minmax(0, 1fr) auto;
  grid-template-areas:
    "number company status"
    "number description status";
  align-items: center;
  gap: 0 12px;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.search-result:hover,
.search-result:focus-visible,
.search-result[aria-selected="true"] {
  outline: none;
  background: var(--brand-soft);
}

.search-result .job-number { grid-area: number; justify-self: start; color: var(--brand); }
.search-result .badge { grid-area: status; }

.search-company {
  grid-area: company;
  font-weight: 550;
}

.search-description {
  grid-area: description;
  overflow: hidden;
  color: var(--ink-3);
  font-size: 12.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Jobs, Clients, Job descriptions and Contacts, over each group of results. */
.search-group {
  margin: 6px 10px 2px;
  color: var(--ink-3);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.search-group:first-child { margin-top: 2px; }

.search-result.client-result {
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "company" "description";
}

.search-message {
  margin: 0;
  padding: 10px;
  color: var(--ink-3);
}

/* The sidebar: the app's sections. The books are tabs inside Jobs, never in here. */

.layout {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
}

.sidebar {
  position: sticky;
  top: var(--topbar-h);
  display: flex;
  flex-direction: column;
  gap: 2px;
  height: calc(100vh - var(--topbar-h));
  padding: 16px 12px;
  border-right: 1px solid var(--line);
}

.sidebar-link {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 36px;
  /* 10px in, so the icons sit 30px from the edge, as when folded, under the logo's icon. */
  padding: 0 12px 0 10px;
  border-radius: 8px;
  color: var(--ink-2);
  font-weight: 550;
  text-decoration: none;
  white-space: nowrap;
}

.sidebar-link:hover { background: var(--line-2); color: var(--ink); }

.sidebar-link[aria-current="page"] {
  background: var(--brand-soft);
  color: var(--brand);
}

.sidebar-icon {
  flex: none;
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* At the bottom of the sidebar, the button that folds it down to its icons and back. */
.sidebar-fold {
  width: 100%;
  margin-top: auto;
  border: 0;
  background: none;
  color: var(--ink-3);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}

.is-folded .sidebar-fold .sidebar-icon { transform: scaleX(-1); }

/* Who is signed in, at the foot of the sidebar: their initials in a circle, which opens a small
   menu with Preferences (not built yet) and Sign out. */
.account { position: relative; }

.account-button {
  width: 100%;
  border: 0;
  background: none;
  font: inherit;
  cursor: pointer;
}

.account-button .sidebar-label { overflow: hidden; text-overflow: ellipsis; }

/* 24px across, but taking the 16px of an icon, so its centre lines up with theirs. */
.avatar {
  display: grid;
  flex: none;
  place-items: center;
  width: 24px;
  height: 24px;
  margin: 0 -4px;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: .02em;
}

.account-menu {
  position: absolute;
  bottom: calc(100% + 6px);
  left: 0;
  z-index: 20;
  width: 240px;
  padding: 6px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  box-shadow: var(--shadow-float);
}

.account-menu form { margin: 0; }

.account-who {
  margin: 0 0 4px;
  padding: 8px 10px 10px;
  overflow: hidden;
  border-bottom: 1px solid var(--line-2);
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.menu-soon {
  overflow: hidden;
  color: var(--ink-3);
  font-size: 12.5px;
  text-overflow: ellipsis;
}

.menu-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  height: 34px;
  padding: 0 10px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.menu-item:hover:not(:disabled) { background: var(--line-2); }
.menu-item:disabled { color: var(--ink-3); cursor: default; }

/* Folded, the sidebar keeps only its icons, which name themselves on hover. The words stay for a
   screen reader. Below 1200px the board needs the width, so it is always folded there and the
   button that unfolds it goes. */
.layout.is-folded { grid-template-columns: 61px minmax(0, 1fr); }
.is-folded .sidebar { padding: 16px 10px; }
.is-folded .sidebar-link { justify-content: center; padding: 0; }
.is-folded .sidebar-label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (max-width: 1200px) {
  .layout { grid-template-columns: 61px minmax(0, 1fr); }
  .sidebar { padding: 16px 10px; }
  .sidebar-link { justify-content: center; padding: 0; }
  .sidebar-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .sidebar-fold { display: none; }
  .account { margin-top: auto; }
}

/* Tabs, one per job book: an underline on the book on screen. */

.tabs {
  display: flex;
  gap: 4px;
  margin: 0 var(--gutter);
  padding-top: 8px;
  overflow-x: auto;
  /* The rule under the tabs is drawn inside the strip, so the underline of the book on screen
     can sit on it without reaching past the strip's edge. Reaching past it by even a pixel
     gave the strip something to scroll, and a scrollbar wherever scrollbars always show. */
  box-shadow: inset 0 -1px 0 var(--line);
}

.tab {
  min-width: 52px;
  padding: 10px 12px;
  border-bottom: 2px solid transparent;
  color: var(--ink-3);
  font: 600 13px/1.4 var(--mono);
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
}

.tab:hover { color: var(--ink); }

.tab[aria-current="page"] {
  border-bottom-color: var(--brand);
  color: var(--brand);
}

/* The board */

main {
  padding: 16px var(--gutter) 40px;
}

.notice {
  margin: 0 0 14px;
  padding: 10px 14px;
  border-radius: 9px;
  background: var(--error-bg);
  color: var(--error);
  font-weight: 500;
}

.empty {
  margin: 0;
  padding: 40px 32px;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  background: var(--canvas);
  color: var(--ink-3);
  text-align: center;
}

.table-wrap { overflow-x: auto; }

.jobs {
  width: 100%;
  border-collapse: collapse;
}

.jobs th {
  padding: 0 12px 10px;
  border-bottom: 1px solid var(--line);
  color: var(--ink-3);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .06em;
  text-align: left;
  text-transform: uppercase;
  white-space: nowrap;
}

.jobs td {
  padding: 13px 12px;
  border-bottom: 1px solid var(--line-2);
  vertical-align: middle;
}

.jobs th:first-child,
.jobs td:first-child { padding-left: 14px; }

.jobs tbody tr:hover { background: #fafbfc; }

.jobs .opened {
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Company over description. They and Notes share what the other columns leave. */
.jobs .what {
  width: 55%;
  min-width: 240px;
}

.jobs .company {
  display: block;
  font-weight: 600;
  line-height: 1.35;
}

.jobs .description {
  display: block;
  color: var(--ink-2);
  line-height: 1.4;
}

.jobs .notes {
  width: 45%;
  min-width: 200px;
}

/* Just above the card layout, narrower minimums let the whole table fit without scrolling
   sideways. */
@media (max-width: 1200px) {
  .jobs .what { min-width: 180px; }
  .jobs .notes { min-width: 150px; }
}

/* Struck through, the way the book crosses out a cancelled line, and greyed, but still
   readable on white, which --ink-3 is not. The number is left
   plain: it still holds its place and is what people look up. */
.jobs .is-cancelled .company,
.jobs .is-cancelled .description {
  color: var(--cancelled-text);
  text-decoration: line-through;
  text-decoration-color: rgba(95, 105, 120, .6);
}

.jobs .is-cancelled .company { font-weight: 450; }

.job-number {
  display: inline-block;
  color: var(--ink);
  font: 600 13.5px/1.5 var(--mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* On the board a job number is a button that copies it. */
button.job-number {
  margin: -2px -6px;
  padding: 2px 6px;
  border: 0;
  border-radius: 6px;
  background: none;
  cursor: pointer;
}

button.job-number:hover {
  background: var(--brand-soft);
  color: var(--brand);
}

/* "Copied" beside the number just clicked. Positioned without offsets, it sits where it would
   have been in the line, right after the number, but out of the flow, so the row doesn't move. */
.copied {
  position: absolute;
  margin: 1px 0 0 12px; /* level with the number */
  padding: 2px 8px;
  border-radius: 6px;
  background: var(--ink);
  color: #fff;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.5;
  white-space: nowrap;
  pointer-events: none;
}

/* A job's note, highlighted like a margin note. It is the button that edits it. */
.note {
  display: inline-block;
  max-width: 100%;
  padding: 3px 10px;
  border: 0;
  border-radius: 6px;
  background: var(--note-bg);
  box-shadow: inset 2px 0 0 var(--note-line);
  color: var(--note);
  font-size: 13px;
  font-weight: 550;
  line-height: 1.45;
  text-align: left;
  white-space: pre-line;
  overflow-wrap: anywhere;
  cursor: text;
}

.note:hover { box-shadow: inset 2px 0 0 var(--note-line), inset 0 0 0 1px var(--note-line); }

/* Add note shows on the row under the pointer, or when tabbed to; a touch screen, with no
   pointer to hover, always shows it. The copy beside the row's buttons is the phone's. */
.add-note {
  height: 26px;
  padding: 0 9px;
  border: 1px dashed var(--brand-line);
  border-radius: 6px;
  background: transparent;
  color: var(--brand);
  font-size: 12.5px;
  font-weight: 550;
  white-space: nowrap;
  opacity: 0;
  cursor: pointer;
}

.jobs tr:hover .add-note,
.add-note:focus-visible { opacity: 1; }

@media (hover: none) {
  .add-note { opacity: 1; }
}

.add-note:hover {
  border-color: var(--brand);
  background: var(--brand-soft);
}

.row-actions .add-note { display: none; }

.note-edit {
  display: grid;
  gap: 4px;
}

.note-input {
  width: 100%;
  padding: 5px 10px;
  border: 1px solid var(--brand);
  border-radius: 8px;
  box-shadow: 0 0 0 3px var(--brand-soft);
  color: var(--ink);
  font: 13.5px/1.45 var(--font);
  resize: none;
  outline: none;
}

.note-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  color: var(--ink-3);
  font-size: 11.5px;
}

.note-meta kbd {
  padding: 0 4px;
  border: 1px solid var(--line);
  border-radius: 4px;
  color: var(--ink-2);
  font: 500 10.5px var(--mono);
}

.note-buttons { display: none; }

/* A status is a dot and a word. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 9px 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  text-transform: capitalize;
  white-space: nowrap;
}

.badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.badge-open { background: var(--open-bg); color: var(--open); }
.badge-done { background: var(--done-bg); color: var(--done); }
.badge-cancelled { background: var(--cancelled-bg); color: var(--cancelled); }

.row-actions {
  text-align: right;
  white-space: nowrap;
}

/* A row's Close, Cancel and Reopen: quiet until pointed at. */
.small-button {
  height: 28px;
  margin-left: 2px;
  padding: 0 10px;
  border: 1px solid transparent;
  border-radius: 7px;
  background: none;
  color: var(--ink-2);
  font-size: 13px;
  font-weight: 550;
  cursor: pointer;
}

.small-button:hover {
  background: var(--line-2);
  color: var(--ink);
}

.small-button.cancel:hover {
  background: var(--error-bg);
  color: var(--error);
}

.small-button.primary {
  border-color: var(--brand);
  background: var(--brand);
  color: #fff;
}

.small-button.primary:hover { background: var(--brand-deep); }

/* Above the board: All or Open only, and on a client's page the Jobs heading before them. */
.board-tools {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

/* All or Open only: a segmented control. */

.board-view {
  display: inline-flex;
  gap: 2px;
  margin-bottom: 16px;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--canvas);
}

.board-view .page-button {
  height: 28px;
  border-color: transparent;
  background: none;
}

.board-view .page-button[aria-pressed="true"] {
  border-color: var(--line);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow);
}

/* The pager under the board */

.pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 16px;
  margin-top: 16px;
  color: var(--ink-3);
  font-size: 13px;
}

.pager-summary {
  margin: 0;
  font-variant-numeric: tabular-nums;
}

.pager-pages {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.page-button {
  min-width: 30px;
  height: 30px;
  padding: 0 10px;
  border: 1px solid transparent;
  border-radius: 7px;
  background: none;
  color: var(--ink-2);
  font-size: 13px;
  font-weight: 550;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}

.page-button:hover:not(:disabled, [aria-pressed="true"], [aria-current="page"]) {
  background: var(--line-2);
  color: var(--ink);
}

.page-button:disabled { opacity: .4; cursor: default; }

.page-button[aria-current="page"] {
  border-color: var(--line);
  background: var(--surface);
  color: var(--ink);
  font-weight: 600;
  box-shadow: var(--shadow);
  opacity: 1;
}

.page-gap {
  align-self: center;
  padding: 0 4px;
  color: var(--ink-3);
}

.pager-size {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* The browser's own arrow sits wherever the platform puts it, in Chrome hard against the right
   border, so it is replaced with a caret drawn as two gradient triangles (the CSP allows no data:
   URL), set in from the right as far as the number is from the left. */
.pager-size select {
  height: 30px;
  padding: 0 28px 0 10px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background:
    linear-gradient(45deg, transparent 50%, var(--ink-2) 50%) right 15px center / 5px 5px no-repeat,
    linear-gradient(135deg, var(--ink-2) 50%, transparent 50%) right 10px center / 5px 5px no-repeat,
    var(--surface);
  color: var(--ink);
  font: inherit;
  appearance: none;
  cursor: pointer;
}

/* Companies: the list, and the top of one company's page */

.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px 16px;
  margin-bottom: 16px;
}

.page-head h2 {
  margin: 0;
  font-size: 20px;
  font-weight: 650;
  letter-spacing: -.01em;
}

.companies {
  width: 100%;
  border-collapse: collapse;
}

.companies th {
  padding: 0 12px 10px;
  border-bottom: 1px solid var(--line);
  color: var(--ink-3);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .06em;
  text-align: left;
  text-transform: uppercase;
  white-space: nowrap;
}

.companies td {
  padding: 12px;
  border-bottom: 1px solid var(--line-2);
}

.companies tbody tr:hover { background: #fafbfc; }
.companies .company { font-weight: 600; }
.companies .address-cell { color: var(--ink-2); }
.companies .count,
.companies:not(.contacts) th:nth-child(3),
.companies:not(.contacts) th:nth-child(4) { text-align: right; font-variant-numeric: tabular-nums; }
.companies .opened { color: var(--ink-3); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* A company's name is a link to its page, in the board and in the list. */
a.company { color: inherit; text-decoration: none; }
a.company:hover { color: var(--brand); text-decoration: underline; }

.back-link {
  display: inline-block;
  margin-bottom: 8px;
  color: var(--ink-3);
  font-size: 13px;
  font-weight: 550;
  text-decoration: none;
}

.back-link:hover { color: var(--brand); }

/* A client's page: the name with its two Add buttons, then two columns, its sites over its
   jobs on the left, and its billing address and contacts on the right. Counts sit beside
   each heading rather than in boxes of their own. */
.client-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px 24px;
  margin-bottom: 20px;
}

.client-head h2 {
  margin: 0;
  font-size: 24px;
  font-weight: 650;
  letter-spacing: -.015em;
}

.company-summary {
  margin: 2px 0 0;
  color: var(--ink-3);
}

.client-actions { display: flex; gap: 8px; }

.client-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  grid-template-rows: auto 1fr;
  grid-template-areas: "sites aside" "jobs aside";
  gap: 0 28px;
  align-items: start;
}

.client-sites { grid-area: sites; }
.client-aside { grid-area: aside; display: grid; gap: 16px; }
.client-jobs-area { grid-area: jobs; }

/* (3) beside a heading, and the open jobs as a small blue tag. */
.count { color: var(--ink-3); font-weight: 500; }

.open-count {
  margin-left: 4px;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--open-bg);
  color: var(--open);
  font-size: 12px;
  font-weight: 600;
  vertical-align: 1px;
}

.client-jobs-area .board-tools { justify-content: flex-start; align-items: center; margin-bottom: 4px; }
.client-jobs-area .board-tools .section-title { margin: 0; }

.panel {
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: 48px;
  padding: 8px 16px;
  border-bottom: 1px solid var(--line-2);
}

.panel-head h3 { margin: 0; font-size: 14px; font-weight: 650; }
.panel-head .small-button { margin: 0 -8px 0 0; color: var(--brand); }
.panel-body { display: grid; justify-items: start; gap: 8px; margin: 0; padding: 14px 16px; }
.panel-body .hint { margin: 0; }
.panel-body .add-note { opacity: 1; }
.billing { margin: 0; white-space: pre-line; }

/* The address being edited, in place of the address. */
.address-input {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid var(--brand);
  border-radius: 8px;
  box-shadow: 0 0 0 3px var(--brand-soft);
  color: var(--ink);
  font: 14px/1.5 var(--font);
  resize: vertical;
  outline: none;
}

.address-buttons { display: flex; gap: 6px; }
.address-buttons .small-button { margin: 0; border-color: var(--line); }
.address-buttons .small-button.primary { border-color: var(--brand); }

/* A contact: initials, who they are, and the call or the email one tap away. */
.person {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) auto;
  gap: 10px;
  padding: 12px 8px 12px 16px;
  border-bottom: 1px solid var(--line-2);
}

.person:last-child { border-bottom: 0; }

.person-initials {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--canvas);
  color: var(--ink-2);
  font-size: 12.5px;
  font-weight: 650;
}

.person-about { display: grid; justify-items: start; min-width: 0; }
.person-name { font-weight: 600; line-height: 1.3; }
.person-role { color: var(--ink-3); font-size: 12.5px; }
.person-links { display: grid; gap: 2px; margin-top: 6px; font-size: 13px; }

.person-links a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--brand);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.person-links a:hover { text-decoration: underline; }

.person-links svg {
  flex: none;
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.person-site {
  margin-top: 6px;
  padding: 0 7px;
  border-radius: 5px;
  background: var(--canvas);
  color: var(--ink-2);
  font-size: 12px;
}

.person .small-button { margin: -4px 0 0; }

.section-title {
  margin: 0 0 12px;
  font-size: 15px;
  font-weight: 650;
}

.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 12px;
  margin-bottom: 12px;
}

.section-head .section-title { margin: 0; }
.section-head .hint { margin: 0; }

.site-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 12px;
  margin-bottom: 28px;
}

/* A site card is the button that shows only its jobs, with Edit in its bottom corner. */
.site-card {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.site-card:hover { border-color: var(--brand-line); }

.site-card:has(> [aria-pressed="true"]) {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-soft);
}

.site-pick {
  display: grid;
  align-content: start;
  gap: 4px;
  width: 100%;
  height: 100%;
  padding: 14px 16px 12px;
  border: 0;
  border-radius: var(--radius);
  background: none;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.site-edit { position: absolute; right: 8px; bottom: 7px; }

.site-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 4px 8px;
}

.site-name { font-weight: 600; }

.site-address {
  color: var(--ink-2);
  font-size: 13px;
  line-height: 1.45;
  white-space: pre-line;
}

/* Under a site: its open jobs, all its jobs and who is there, leaving Edit its corner. */
.site-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 10px;
  margin-top: 8px;
  padding: 9px 52px 0 0;
  border-top: 1px solid var(--line-2);
  color: var(--ink-3);
  font-size: 12.5px;
}

.site-foot .open-jobs { color: var(--open); font-weight: 600; }

/* A client's jobs: no client column, since every row would repeat it, and the site in a
   column of its own. The note goes under the description, and Add note at the end of it. */
.client-jobs .what { width: 100%; }
.client-jobs .description { display: inline; color: var(--ink); font-weight: 500; }
.client-jobs .job-note { margin-top: 6px; }
.client-jobs .job-note:has(> .add-note) { display: inline-block; margin: 0 0 0 8px; }
.client-jobs .is-cancelled .description { font-weight: 450; }
.client-jobs .site-cell { white-space: nowrap; }
.client-jobs .site-picker { margin: 0 0 0 -6px; color: var(--ink-2); font-size: 13.5px; }

@media (max-width: 1100px) {
  .client-grid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    grid-template-areas: "sites" "aside" "jobs";
  }
  .client-aside { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); align-items: start; margin-bottom: 28px; }
}

/* Residential or commercial: a tinted word, in colours no job status uses. */
.kind {
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 600;
}

.kind-residential { background: var(--note-bg); color: var(--note); }
.kind-commercial { background: var(--brand-soft); color: var(--brand); }

.contacts td { padding-top: 10px; padding-bottom: 10px; }
.contacts .contact-name .company { display: block; }
.contact-role { display: block; color: var(--ink-3); font-size: 13px; }
.contact-link a { color: var(--brand); text-decoration: none; }
.contact-link a:hover { text-decoration: underline; }
.contact-site { color: var(--ink-2); }
.contact-client a { color: var(--ink); text-decoration: none; }
.contact-client a:hover { text-decoration: underline; }

/* A job's site, under its description: named on a book's board, picked on a client's page. */
.jobs .site {
  display: block;
  color: var(--ink-3);
  font-size: 12.5px;
}

/* A site's name on the board is a button that copies its address. */
.site-copy {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.site-copy:hover { color: var(--brand); text-decoration: underline; }

.site-picker {
  max-width: 100%;
  margin: 4px 0 0 -6px;
  padding: 1px 4px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: none;
  color: var(--ink-3);
  font-size: 12.5px;
  cursor: pointer;
}

.site-picker:hover { border-color: var(--line); color: var(--ink); }

/* Dialogs */

.dialog {
  width: min(440px, calc(100vw - 32px));
  padding: 0;
  border: 0;
  border-radius: 16px;
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-dialog);
}

/* Lets New job's client list hang past the bottom of the dialog. The others scroll when the
   screen is too short for them. */
#new-job-dialog { overflow: visible; }

.dialog::backdrop {
  background: rgba(16, 24, 40, .38);
  backdrop-filter: blur(2px);
}

.dialog-form {
  display: grid;
  gap: 16px;
  padding: 22px 24px 0;
}

.dialog-form h2 {
  margin: 0;
  font-size: 17px;
  font-weight: 650;
  letter-spacing: -.01em;
}

.dialog-form label {
  display: grid;
  gap: 6px;
}

.label {
  color: var(--ink-2);
  font-size: 13px;
  font-weight: 550;
}

.dialog-form select,
.dialog-form textarea,
.dialog-form input {
  height: 40px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--surface);
  color: var(--ink);
}

.dialog-form input.mono { font-weight: 600; letter-spacing: .02em; }

.dialog-form textarea { height: auto; padding: 9px 12px; resize: vertical; }

.dialog-form select:focus,
.dialog-form textarea:focus,
.dialog-form input:focus {
  border-color: var(--brand);
  outline: none;
  box-shadow: 0 0 0 3px var(--brand-soft);
}

.dialog-form input::placeholder { color: var(--ink-3); font-weight: 400; }

/* New job's company field and the list of companies under it. */
.combo { position: relative; display: grid; gap: 6px; }

.combo-options {
  position: absolute;
  top: 72px; /* under the field, over the fields below it */
  right: 0;
  left: 0;
  z-index: 1;
  max-height: 240px;
  overflow-y: auto;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  box-shadow: var(--shadow-float);
}

.combo-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 7px 10px;
  border-radius: 7px;
  cursor: pointer;
}

.combo-option:hover,
.combo-option[aria-selected="true"] { background: var(--brand-soft); }

.combo-option kbd {
  padding: 0 5px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--surface);
  color: var(--ink-3);
  font: 500 10.5px/16px var(--mono);
}

.hint {
  color: var(--ink-3);
  font-size: 12.5px;
}

.form-error {
  margin: 0;
  color: var(--error);
  font-size: 13px;
  font-weight: 500;
}

.confirm-text {
  margin: 0;
  padding-top: 4px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.45;
}

/* The buttons sit on a grey footer across the dialog's full width. */
.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin: 6px -24px 0;
  padding: 14px 24px;
  border-top: 1px solid var(--line);
  border-radius: 0 0 16px 16px;
  background: var(--canvas);
}

.button {
  height: 36px;
  padding: 0 16px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink);
  font-size: 13.5px;
  font-weight: 550;
  white-space: nowrap;
  box-shadow: var(--shadow);
  cursor: pointer;
}

.button:hover { border-color: #d9dde4; background: #f8f9fb; }

.button.primary {
  border-color: var(--brand);
  background: var(--brand);
  color: #fff;
}

.button.primary:hover { border-color: var(--brand-deep); background: var(--brand-deep); }

/* The yes button of a question whose answer can't be undone. */
.button.danger {
  border-color: var(--error);
  background: var(--error);
  color: #fff;
}

.button.danger:hover { border-color: var(--error-deep); background: var(--error-deep); }

.button:disabled { opacity: .6; cursor: default; }

/* Remove in a site or contact dialog: at the far left, away from Save, in the error colour. */
.button.remove { margin-right: auto; color: var(--error); }
.button.remove:hover { border-color: var(--error); background: var(--error-bg); }

a.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}

/* The page shown when signed out, or when a sign-in was refused: one card, centred. */

.sign-in-page {
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: 24px 16px;
  background:
    radial-gradient(1200px 500px at 50% -10%, var(--brand-soft), transparent 70%),
    var(--canvas);
}

.sign-in {
  display: grid;
  justify-items: center;
  width: min(380px, 100%);
  padding: 32px 32px 28px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--surface);
  box-shadow: var(--shadow-float);
  text-align: center;
}

.sign-in .logo { justify-content: center; }
.sign-in .logo img { width: 48px; height: 48px; }
.sign-in .logo-name { font-size: 24px; }
.sign-in .logo-tag { font-size: 12px; }

.sign-in h1 {
  margin: 14px 0 0;
  color: var(--ink-3);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.sign-in h2 {
  margin: 10px 0 4px;
  font-size: 20px;
  font-weight: 650;
  letter-spacing: -.01em;
  text-wrap: balance;
}

.sign-in p {
  margin: 0 0 22px;
  color: var(--ink-3);
}

.sign-in .button {
  width: 100%;
  height: 42px;
  font-size: 14px;
}

/* Each job becomes a small card: number and status, company and description, the note, then
   the buttons with the date. The table's columns don't fit below about 1000px, so tablets
   and narrow windows get cards too. */
@media (max-width: 1000px) {
  main { padding-top: 12px; }
  .table-wrap { margin: 0 calc(-1 * var(--gutter)); border-top: 1px solid var(--line-2); }
  .jobs thead { display: none; }
  .jobs, .jobs tbody { display: block; }

  .jobs tr {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "number status"
      "what what"
      "notes notes"
      "actions opened";
    align-items: center;
    gap: 6px 10px;
    padding: 14px var(--gutter);
    border-bottom: 1px solid var(--line-2);
  }

  .jobs td { padding: 0; border: 0; }
  .jobs td:first-child { padding-left: 0; }
  .jobs .number { grid-area: number; }
  .jobs .status { grid-area: status; justify-self: end; }
  .jobs .what { grid-area: what; width: auto; min-width: 0; }
  .jobs .notes { grid-area: notes; width: auto; min-width: 0; }
  .jobs .row-actions { grid-area: actions; text-align: left; }
  .jobs .opened { grid-area: opened; justify-self: end; font-size: 12.5px; }
  .jobs .row-actions:empty { display: none; }
  .client-jobs tr { grid-template-areas: "number status" "what what" "site site" "actions opened"; }
  .client-jobs .site-cell { grid-area: site; }
  .client-jobs .site-cell:empty { display: none; }
  .client-jobs .job-note:has(> .add-note) { display: none; }

  .small-button {
    margin: 0 6px 0 0;
    border-color: var(--line);
    background: var(--surface);
  }

  /* A job without a note gets no line for it, only + Note beside its buttons. */
  .jobs .notes:has(> .add-note) { display: none; }

  .row-actions .add-note {
    display: inline-block;
    height: 28px;
    margin: 0 6px 0 0;
    padding: 0 10px;
    font-size: 13px;
    opacity: 1;
  }

  /* Save note and Cancel stand in for the row's buttons while the note is open. */
  .jobs .is-editing .row-actions { visibility: hidden; }
  .note-input { font-size: 15px; }
  .note-keys { display: none; }
  .note-buttons { display: flex; order: -1; gap: 6px; }

  .note-meta {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 4px 10px;
  }
}

@media (max-width: 860px) {
  :root { --gutter: 16px; --topbar-h: 60px; }
  /* A smaller logo, and New job as a plus alone, leave the search box room on a phone. */
  .new-job { padding: 0 10px; }
  .new-job-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .logo { gap: 8px; }
  .logo img { width: 32px; height: 32px; }
  .logo-name { font-size: 16px; }
  .logo-tag { font-size: 8.5px; letter-spacing: .1em; }
  /* The sidebar is a row under the bar here, so the logo lines up with the page instead. */
  .topbar { gap: 8px; padding-left: var(--gutter); }
  .search { flex: 1; width: auto; min-width: 0; }
  .search-key { display: none; }

  /* The sections become a row under the top bar, sharing its width. */
  /* .layout in front, so these win over the folded sidebar's rules too. */
  .layout { display: block; }
  .layout .sidebar {
    position: static;
    flex-direction: row;
    height: auto;
    padding: 6px var(--gutter);
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }
  .layout .sidebar-link { flex: 1; justify-content: center; height: 34px; padding: 0 12px; }
  .layout .sidebar-label { position: static; width: auto; height: auto; clip-path: none; }
  .layout .account-button { width: auto; padding: 0 12px; }
  .layout .account-button .sidebar-label { display: none; }
  .layout .account-menu { top: calc(100% + 6px); right: 0; bottom: auto; left: auto; }

  /* A contact becomes a small card: name and role, then phone, email, client and site, one to
     a line. */
  .contacts, .contacts tbody { display: block; }
  .contacts thead { display: none; }
  .contacts tr {
    display: grid;
    gap: 2px;
    padding: 12px var(--gutter);
    border-bottom: 1px solid var(--line-2);
  }
  .contacts td, .contacts td:first-child { padding: 0; border: 0; }
  .contacts td:empty { display: none; }
  .companies th:nth-child(2), .companies .address-cell,
  .companies th:nth-child(5), .companies .opened { display: none; }

  /* The books share the width, so all ten fit on a phone instead of running off the edge. */
  .tabs { gap: 0; margin: 0; padding: 4px 6px 0; }
  .tab { flex: 1; min-width: 0; padding: 10px 2px; font-size: 12px; }

  .search-results {
    position: fixed;
    top: calc(var(--topbar-h) + 4px);
    right: 16px;
    left: 16px;
    width: auto;
  }
}
