:root {
  /* Taken from the Navazia logo. Cool neutrals rather than the old warm
     paper, so the blue reads clean instead of muddy. */
  --paper:      #f4f6fa;
  --card:       #ffffff;
  --ink:        #10193a;
  --ink-soft:   #4f5a73;
  --ink-faint:  #687186;   /* was #7d8794, which failed contrast at 3.6 */
  --rule:       #dde2ec;

  --accent:     #0b3ea6;   /* the logo blue; white on it reads at 9.3 */
  --accent-bg:  #e7eefb;

  /* Gold is for highlights only -- the brand band, the active marker.
     It sits close to the amber used for "due soon", so it must never
     become a general accent or a warning would read as decoration. */
  --gold:       #c98a1f;
  --gold-light: #f2c24b;
  --gold-bg:    #fbf1dc;
  --gold-ink:   #8a5a0c;

  /* Status. Strong enough to read at a glance in daylight. */
  --late:       #a01b12;
  --late-bg:    #ffdedb;
  --late-bar:   #d32f22;

  --soon:       #8a4b00;
  --soon-bg:    #ffe9c2;
  --soon-bar:   #e08a00;

  --done:       #14612f;
  --done-bg:    #cdeed8;
  --done-bar:   #1f8a45;

  /* One colour per line of business, so a record reads by eye. */
  --tax:        #7a3ba8;
  --tax-bg:     #ede0f7;
  --ins:        #0f5f8a;
  --ins-bg:     #d8ecf7;
  --inv:        #14612f;
  --inv-bg:     #cdeed8;
  --lend:       #8a4b00;
  --lend-bg:    #ffe9c2;
  --prop:       #a01b12;
  --prop-bg:    #ffdedb;
  --pulse:      #0b6b63;
  --pulse-bg:   #d5efec;

  /* One colour per kind of card, so the filter row reads by eye */
  --c-bday:     #a8317a;
  --c-bday-bg:  #fbe2f0;
  --c-appt:     #0f5f8a;
  --c-appt-bg:  #d8ecf7;
  --c-follow:   #7a3ba8;
  --c-follow-bg:#ede0f7;
  --c-dead:     #8a4b00;
  --c-dead-bg:  #ffe9c2;
  --c-reply:    #14612f;
  --c-reply-bg: #cdeed8;

  --r:          12px;
  --tap:        44px;
}

* { box-sizing: border-box; }

/* The hidden attribute must always win. Any rule that sets display on
   an element -- .sheet uses flex, .act-grid uses grid -- overrides the
   browser default of display:none and leaves hidden elements visible. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;
  font-size: 16px;
  line-height: 1.45;
  -webkit-text-size-adjust: 100%;
  font-variant-numeric: tabular-nums;
}

body { padding-bottom: env(safe-area-inset-bottom); }

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

/* Plain links were falling back to the browser's own blue, which is a
   different blue from the brand and turns purple once visited. Anything
   that sets its own colour -- the tabs, the bar, the action grid --
   still wins, since this is the weakest rule there is. */
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

button {
  min-height: var(--tap);
  border: 1px solid var(--rule);
  background: var(--card);
  border-radius: var(--r);
  padding: 0 14px;
  cursor: pointer;
}

button:active { background: var(--accent-bg); }

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

button.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  width: 100%;
  font-weight: 500;
}

button.primary:disabled { opacity: .5; cursor: default; }

input {
  width: 100%;
  min-height: var(--tap);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--card);
  padding: 0 12px;
}

/* Checkboxes and radios are not text fields. Without this they stretch
   to full width and push their label to the far edge of the card. */
input[type="checkbox"],
input[type="radio"] {
  width: auto;
  min-height: 0;
  flex: 0 0 auto;
  margin: 0;
  padding: 0;
  accent-color: var(--accent);
  transform: scale(1.25);
}

label.inline {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: var(--tap);
  margin: 0 0 8px;
  font-size: 15px;
  color: var(--ink);
}

label {
  display: block;
  font-size: 14px;
  color: var(--ink-soft);
  margin-bottom: 6px;
}

.field { margin-bottom: 14px; }

/* ---------- login ---------- */

.login-wrap {
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: var(--paper);
}

/* A white card on the pale page, with the brand band along its top */
.login {
  width: 100%;
  max-width: 360px;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 24px;
  overflow: hidden;
  padding: 0 26px 26px;
}

.login-band {
  height: 6px;
  margin: 0 -26px;
  background: var(--accent);
  box-shadow: 0 3px 0 var(--gold);
}

.login-logo {
  display: block;
  width: 84px;
  height: auto;
  margin: 34px auto 22px;
}

.mark {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-align: center;
  color: var(--ink);
  margin-bottom: 4px;
}

.mark-sub {
  color: var(--ink-soft);
  font-size: 14px;
  text-align: center;
  margin-bottom: 26px;
}

.login .field input {
  background: var(--paper);
  border-color: var(--rule);
}

.login .field input:focus {
  background: var(--card);
  border-color: var(--accent);
}

/* The code is the step people fumble -- switching apps, thirty seconds
   before it rolls over -- so it is the field that stands out */
.code-input {
  letter-spacing: 0.35em;
  text-align: center;
  font-size: 20px;
  font-weight: 600;
  border-width: 1.5px !important;
  border-color: var(--accent) !important;
  background: var(--card) !important;
}

/* the placeholder must not look like a code already filled in */
.code-input::placeholder {
  color: var(--rule);
  font-weight: 400;
}

.login button.primary {
  min-height: 48px;
  margin-top: 6px;
  font-size: 16px;
}

.login-foot {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  margin-top: 18px;
  font-size: 13px;
  color: var(--ink-faint);
}

.login-foot .dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--gold);
}

.msg {
  margin-top: 14px;
  padding: 10px 12px;
  border-radius: var(--r);
  font-size: 14px;
  background: var(--late-bg);
  color: var(--late);
}

/* ---------- app shell ---------- */

.bar {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 16px 16px 12px;
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
}

.bar h1 { font-size: 19px; font-weight: 600; margin: 0; flex: 1; }
.bar .date { font-size: 14px; color: var(--ink-faint); }

main { padding: 14px 16px 40px; max-width: 640px; margin: 0 auto; }

.counts { display: flex; gap: 8px; margin-bottom: 20px; }

.count {
  flex: 1;
  border-radius: var(--r);
  padding: 10px 12px;
  background: var(--card);
  border: 1px solid var(--rule);
}

.count.late { background: var(--late-bg); border-color: transparent; color: var(--late); }
.count.soon { background: var(--soon-bg); border-color: transparent; color: var(--soon); }

.count b { display: block; font-size: 22px; font-weight: 600; line-height: 1.1; }
.count span { font-size: 13px; }

.group {
  font-size: 14px;
  color: var(--ink-soft);
  margin: 0 0 8px;
  padding-top: 4px;
}

.alert {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 12px 14px;
  margin-bottom: 8px;
}

.alert-top { display: flex; gap: 10px; align-items: flex-start; }
.alert-title { font-weight: 500; flex: 1; }
.alert-sub { color: var(--ink-soft); font-size: 14px; margin-top: 2px; }

.chip {
  font-size: 13px;
  padding: 2px 9px;
  border-radius: var(--r);
  white-space: nowrap;
  background: var(--accent-bg);
  color: var(--ink-soft);
}

.chip.late { background: var(--late-bg); color: var(--late); font-weight: 600; }
.chip.soon { background: var(--soon-bg); color: var(--soon); font-weight: 600; }
.chip.ok   { background: var(--done-bg); color: var(--done); font-weight: 600; }

.actions { display: flex; gap: 8px; margin-top: 10px; }
.actions button { flex: 1; min-height: 38px; font-size: 14px; }

.empty {
  text-align: center;
  padding: 48px 20px;
  color: var(--ink-faint);
}

.empty b { display: block; color: var(--ink); font-weight: 500; margin-bottom: 4px; }

.loading { padding: 40px; text-align: center; color: var(--ink-faint); }

.foot {
  margin-top: 28px;
  padding-top: 14px;
  border-top: 1px solid var(--rule);
  display: flex;
  gap: 8px;
}

.foot button { flex: 1; font-size: 14px; min-height: 38px; }

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

/* ---------- bottom tabs ---------- */

/* Three fixed rows: header, scrolling body, tab bar. Nothing is
   positioned, so nothing can detach during momentum scroll. The
   minmax(0,1fr) matters -- without it the middle row refuses to
   shrink and pushes the tab bar off screen. */

body.has-tabs {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  /* svh, not dvh. dvh includes the strip behind Safari's bottom
     toolbar, which is why the tab bar was sitting under the URL bar.
     In the installed app the two are identical. */
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  padding-bottom: 0;
}

body.has-tabs .bar {
  position: static;
  grid-row: 1;
}

body.has-tabs main {
  grid-row: 2;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  min-height: 0;

  /* Full bleed on a phone. An auto margin on a grid item makes it
     shrink to fit its content instead of filling the column, which
     is what squeezed everything into the middle. */
  margin: 0;
  width: auto;
  max-width: none;
  justify-self: stretch;
  padding: 14px 16px 28px;
}

/* Centre the column again only where the screen is actually wide. */
@media (min-width: 760px) {
  body.has-tabs main {
    width: 100%;
    max-width: 640px;
    justify-self: center;
  }
}

body.has-tabs .tabs { grid-row: 3; }

/* Same fixed shell for pages with a header but no tab bar, so they
   feel like screens rather than scrolling web pages. */
body.app-shell {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  padding-bottom: 0;
}

body.app-shell .bar { grid-row: 1; position: static; }

body.app-shell main {
  grid-row: 2;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  min-height: 0;
  margin: 0;
  width: auto;
  max-width: none;
  justify-self: stretch;
  padding: 14px 16px calc(28px + env(safe-area-inset-bottom));
}

@media (min-width: 760px) {
  body.app-shell main {
    width: 100%;
    max-width: 640px;
    justify-self: center;
  }
}

.tabs {
  display: flex;
  background: var(--card);
  border-top: 1px solid var(--rule);
  padding-bottom: env(safe-area-inset-bottom);
}

.tabs a {
  flex: 1;
  min-width: 0;
  text-align: center;
  padding: 14px 2px;
  font-size: 13px;
  color: var(--ink-faint);
  text-decoration: none;
  min-height: var(--tap);
  white-space: nowrap;
}

.tabs a.on {
  color: var(--accent);
  font-weight: 500;
  background: var(--accent-bg);
  box-shadow: inset 0 3px 0 var(--gold);
}

/* ---------- search ---------- */

.search { margin-bottom: 16px; }

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

.row-link {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 12px 14px;
  margin-bottom: 8px;
  text-decoration: none;
  color: inherit;
  min-height: var(--tap);
}

.initials {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: var(--accent-bg);
  color: var(--accent);
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 600;
  flex-shrink: 0;
}

.row-main { flex: 1; min-width: 0; }

/* These are spans inside a span, so without display:block the name
   and the reason run together on one line. */
.row-name { display: block; font-weight: 500; }
.row-why  { display: block; font-size: 14px; color: var(--ink-soft); margin-top: 2px; }

.row-why.seen { color: var(--done); font-weight: 500; }
.row-why.unseen { color: var(--soon); }

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

.rec-head { display: flex; gap: 12px; align-items: center; margin-bottom: 12px; }
.rec-name { font-size: 18px; font-weight: 600; }
.rec-sub { font-size: 14px; color: var(--ink-soft); }

.tags { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 14px; }

.quick { display: flex; gap: 8px; margin-bottom: 18px; }
.quick a, .quick button {
  flex: 1;
  display: flex; align-items: center; justify-content: center;
  min-height: 42px; font-size: 14px;
  border: 1px solid var(--rule); border-radius: var(--r);
  background: var(--card); color: inherit; text-decoration: none;
}

.panel {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  overflow: hidden;
  margin-bottom: 18px;
}

.panel-row { padding: 11px 14px; border-bottom: 1px solid var(--rule); }
.panel-row:last-child { border-bottom: 0; }
.panel-row .t { display: flex; justify-content: space-between; gap: 10px; }
.panel-row .n { font-weight: 500; }
.panel-row .m { font-size: 14px; color: var(--ink-soft); margin-top: 2px; }
.panel-row .m.warn { color: var(--late); }
.panel-row .m.none { color: var(--ink-faint); }

.sec-head {
  display: flex; justify-content: space-between; align-items: center;
  padding: 12px 2px; cursor: pointer;
  border-top: 1px solid var(--rule);
  font-weight: 500;
}

.sec-head .count { font-weight: 400; color: var(--ink-faint); font-size: 14px; }
.sec-body { padding-bottom: 6px; }

/* ---------- forms ---------- */

.form-sec { margin: 22px 0 10px; font-weight: 500; }
.two { display: flex; gap: 10px; }

/* min-width:0 matters. Flex items default to min-width:auto, which
   refuses to shrink below the content width and makes the fields
   spill past the edge of the card. */
.two .field { flex: 1 1 0; min-width: 0; }
.two input, .two select { max-width: 100%; min-width: 0; }

/* Date and time inputs on iOS carry a fixed intrinsic width that
   ignores the container and pushes out past the card edge. */
input[type="date"],
input[type="time"],
input[type="datetime-local"] {
  min-width: 0;
  width: 100%;
  -webkit-appearance: none;
  appearance: none;
  text-align: left;
}

select {
  width: 100%; min-height: var(--tap);
  border: 1px solid var(--rule); border-radius: var(--r);
  background: var(--card); padding: 0 10px;
}

.kid { border: 1px solid var(--rule); border-radius: var(--r); padding: 12px; margin-bottom: 10px; }
.link-btn { background: none; border: 0; color: var(--accent); padding: 6px 0; min-height: 36px; text-decoration: underline; cursor: pointer; }

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


/* ---------- colour bars: the fastest thing to read ---------- */

.alert { border-left: 5px solid var(--rule); }
.alert.is-late { border-left-color: var(--late-bar); }
.alert.is-soon { border-left-color: var(--soon-bar); }
.alert.is-ok   { border-left-color: var(--done-bar); }

.row-link { border-left: 5px solid var(--rule); }
.row-link.is-late { border-left-color: var(--late-bar); }
.row-link.is-soon { border-left-color: var(--soon-bar); }
.row-link.is-ok   { border-left-color: var(--done-bar); }

.count.late b, .count.soon b { font-weight: 700; }

/* Line-of-business colour coding on the record */
.lob { border-left: 5px solid var(--rule); padding-left: 9px; }
.lob-tax  { border-left-color: var(--tax);  }
.lob-ins  { border-left-color: var(--ins);  }
.lob-inv  { border-left-color: var(--inv);  }
.lob-lend { border-left-color: var(--lend); }
.lob-prop { border-left-color: var(--prop); }
.lob-pulse { border-left-color: var(--pulse); }

.lob .n { color: var(--ink); }
.lob-tax  .n { color: var(--tax);  }
.lob-ins  .n { color: var(--ins);  }
.lob-inv  .n { color: var(--inv);  }
.lob-lend .n { color: var(--lend); }
.lob-prop .n { color: var(--prop); }
.lob-pulse .n { color: var(--pulse); }

/* ---------- app feel, not web feel ---------- */

.bar {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--paper);
}

body { overscroll-behavior-y: none; }

a, button, .row-link, .alert { -webkit-tap-highlight-color: transparent; }

.row-link:active, .alert:active { background: var(--accent-bg); }
.tabs a:active { background: var(--accent-bg); }

/* No text selection on chrome, so a long press does not pop a menu */
.bar, .tabs, .chip, .count, .sec-head {
  -webkit-user-select: none;
  user-select: none;
}

.tabs a { transition: none; }

@media (display-mode: standalone) {
  body { min-height: 100dvh; }
}

/* ---------- header tap targets ---------- */

/* The back and action links in the bar were plain text with no height,
   so they were hard to hit and sat too close to the status bar. */
.bar {
  padding-top: calc(18px + env(safe-area-inset-top));
  padding-bottom: 10px;
  min-height: calc(58px + env(safe-area-inset-top));
  gap: 6px;
}

.bar a.date,
.bar a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 10px;
  margin: 0 -10px;
  color: var(--accent);
  text-decoration: none;
  font-size: 15px;
  font-weight: 500;
}

.bar a:active { background: var(--accent-bg); border-radius: var(--r); }

.bar span.date { display: inline-flex; align-items: center; min-height: var(--tap); }

.build {
  text-align: center;
  font-size: 12px;
  color: var(--ink-faint);
  margin: 14px 0 0;
}

/* ---------- actions on an alert card ---------- */

.reach {
  display: flex;
  gap: 6px;
  margin-top: 10px;
}

.mini {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 38px;
  font-size: 14px;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--card);
  color: var(--accent);
  text-decoration: none;
  padding: 0 4px;
  cursor: pointer;
}

.mini:active { background: var(--accent-bg); }

.notebox { margin-top: 10px; }
.notebox textarea { width: 100%; min-height: 76px; font-size: 15px; }
.notebox .actions { margin-top: 8px; }

.btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 42px;
  font-size: 15px;
  padding: 0 14px;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--card);
  color: var(--accent);
  text-decoration: none;
  cursor: pointer;
}

.btn:active { background: var(--accent-bg); }

.actions .btn { min-height: 38px; font-size: 14px; }

.actions button.done {
  border-color: var(--done);
  color: var(--done);
  font-weight: 500;
}

textarea {
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--card);
  padding: 10px 12px;
  font-family: inherit;
  resize: vertical;
}

/* ---------- undo line left behind by Done and Snooze ---------- */

.undo {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--surface, var(--accent-bg));
  border: 1px solid var(--rule);
  border-left: 5px solid var(--done-bar);
  border-radius: var(--r);
  padding: 10px 12px 10px 14px;
  margin-bottom: 8px;
  font-size: 14px;
  color: var(--ink-soft);
}

.undo span { flex: 1; }

.undo button {
  min-height: 34px;
  padding: 0 12px;
  font-size: 14px;
  color: var(--accent);
  border-color: var(--rule);
}

/* ---------- calendar ---------- */

.cal {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 10px 8px 12px;
  margin-bottom: 18px;
}

.cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 4px 8px;
}

.cal-head span { font-weight: 500; }

.cal-head button {
  min-height: 36px;
  min-width: 40px;
  padding: 0;
  font-size: 20px;
  line-height: 1;
  border-color: transparent;
  color: var(--accent);
}

.cal-dow, .cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
}

.cal-dow span {
  text-align: center;
  font-size: 12px;
  color: var(--ink-faint);
  padding-bottom: 4px;
}

.cal-day {
  position: relative;
  min-height: 42px;
  border: 0;
  background: transparent;
  border-radius: 8px;
  padding: 4px 0 0;
  font-size: 15px;
  color: var(--ink);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.cal-day.outside { color: var(--ink-faint); opacity: .45; }
.cal-day.is-today { font-weight: 700; color: var(--accent); }
.cal-day.is-picked { background: var(--accent); color: #fff; }
.cal-day.is-picked.is-today { color: #fff; }

.cal-day .dot {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--done-bar);
  display: block;
}

.cal-day .dot[data-many] { width: 14px; border-radius: 3px; }
.cal-day.is-picked .dot { background: #fff; }

/* ---------- open time slots ---------- */

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

.slot {
  min-height: 38px;
  padding: 0 12px;
  font-size: 14px;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--card);
  color: var(--accent);
}

.slot.on {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  font-weight: 500;
}

/* ---------- booking calendar: available days must stand out ---------- */

.book-cal { padding: 12px 10px 14px; }

.book-cal .cal-day {
  min-height: 46px;
  font-size: 16px;
  justify-content: center;
  border: 1px solid transparent;
  margin: 2px;
}

/* Not available: quiet, and not tappable */
.book-cal .cal-day:disabled {
  color: var(--ink-faint);
  opacity: .35;
  background: transparent;
}

/* Available: the thing the eye should land on */
.book-cal .cal-day.has-slots {
  background: var(--accent-bg);
  border-color: var(--accent-bg);
  color: var(--accent);
  font-weight: 600;
}

.book-cal .cal-day.has-slots:active {
  background: var(--accent);
  color: #fff;
}

.book-cal .cal-day.is-picked,
.book-cal .cal-day.has-slots.is-picked {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.book-cal .cal-day.is-today:not(.has-slots) { color: var(--ink-soft); }

.book-cal .cal-head button:disabled { opacity: .25; }

/* Times for the chosen day */
#times .slot { min-height: 46px; font-size: 16px; padding: 0 18px; }

#times-wrap { margin-top: 6px; }

/* ---------- person tiles ---------- */

.person {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 12px 14px;
  margin-bottom: 8px;
}

.person-top { display: flex; align-items: center; gap: 11px; }
.person-name { font-weight: 600; font-size: 16px; display: block; }
.person-role { font-size: 14px; color: var(--ink-soft); display: block; margin-top: 1px; }

.person-contact {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--rule);
}

.contact {
  color: var(--accent);
  text-decoration: none;
  font-size: 15px;
  min-height: 32px;
  display: flex;
  align-items: center;
  word-break: break-all;
}

.contact.none { color: var(--ink-faint); font-size: 14px; }

/* ---------- shared action grid ---------- */

/* Eight actions, four across, two even rows. Three columns would leave
   a ragged pair on the last row. */
.act-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 18px;
}

.act-grid button,
.act-grid a {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: 50px;
  font-size: 13px;
  line-height: 1.2;
  overflow-wrap: break-word;
  min-width: 0;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--card);
  color: var(--accent);
  text-decoration: none;
  cursor: pointer;
  padding: 0 6px;
}

.act-grid button:active,
.act-grid a:active { background: var(--accent-bg); }

/* ---------- who? sheet ---------- */

.sheet {
  position: fixed;
  inset: 0;
  background: rgba(20, 23, 26, .45);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 50;
  padding: 16px;
  padding-bottom: calc(16px + env(safe-area-inset-bottom));
}

.sheet-card {
  background: var(--paper);
  border-radius: 16px;
  padding: 16px;
  width: 100%;
  max-width: 420px;
  max-height: 70vh;
  overflow-y: auto;
}

.sheet-title { margin: 0 0 12px; font-weight: 600; font-size: 17px; }

.sheet-row {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  min-height: 58px;
  padding: 10px 12px;
  margin-bottom: 8px;
  color: var(--ink);
  text-decoration: none;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  text-align: left;
}

.sheet-row:active { background: var(--accent-bg); }

/* ---------- accordions on the record ---------- */

.acc {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  margin-bottom: 10px;
  overflow: hidden;
}

.acc-head {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 54px;
  padding: 0 14px;
  border: 0;
  border-radius: 0;
  background: var(--card);
  text-align: left;
  cursor: pointer;
}

.acc-head:active { background: var(--accent-bg); }

.acc-title {
  flex: 1;
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
}

.acc-count {
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-soft);
  background: var(--paper);
  border-radius: 20px;
  padding: 3px 10px;
  white-space: nowrap;
}

/* Chevron drawn in CSS so there is no icon font to load */
.acc-arrow {
  width: 9px;
  height: 9px;
  border-right: 2px solid var(--ink-faint);
  border-bottom: 2px solid var(--ink-faint);
  transform: rotate(-45deg);
  transition: transform .15s ease;
  flex-shrink: 0;
  margin-left: 2px;
}

.acc.is-open .acc-arrow { transform: rotate(45deg); }

.acc-body { display: none; border-top: 1px solid var(--rule); }
.acc.is-open .acc-body { display: block; }

/* The panels inside an accordion should not double up borders */
.acc-body > .panel {
  border: 0;
  border-radius: 0;
  margin: 0;
}

@media (prefers-reduced-motion: reduce) {
  .acc-arrow { transition: none; }
}

/* ---------- list picker ---------- */

.list-head { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; }

.pick-list {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--card);
  color: var(--ink);
  font-size: 15px;
  font-weight: 500;
  text-align: left;
}

.pick-list #pick-label { flex: 1; }
.pick-list .acc-arrow { border-color: var(--ink-faint); transform: rotate(45deg); }

.pick-list.on {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.pick-list.on .acc-arrow { border-color: rgba(255,255,255,.8); }

.clear-x {
  width: 44px;
  min-height: 44px;
  padding: 0;
  font-size: 24px;
  line-height: 1;
  color: var(--ink-soft);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--card);
  flex-shrink: 0;
}

/* Two per row, count first so the eye scans down the numbers */
.pick-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.pick-item {
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 50px;
  padding: 0 12px;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--card);
  text-align: left;
}

.pick-n {
  font-size: 16px;
  font-weight: 700;
  color: var(--accent);
  min-width: 24px;
  flex-shrink: 0;
}

.pick-name {
  font-size: 14px;
  line-height: 1.25;
  color: var(--ink);
}

.pick-item.on {
  background: var(--accent);
  border-color: var(--accent);
}

.pick-item.on .pick-n,
.pick-item.on .pick-name { color: #fff; }

.sheet-tall { max-height: 82vh; }

/* Still used by the note sheet's topic chips */
.seg-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 14px;
}

.seg {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 38px;
  padding: 0 12px;
  font-size: 14px;
  border: 1px solid var(--rule);
  border-radius: 20px;
  background: var(--card);
  color: var(--ink);
  cursor: pointer;
}

.seg-n {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-soft);
  background: var(--paper);
  border-radius: 12px;
  padding: 1px 8px;
  min-width: 22px;
  text-align: center;
}

.seg.on {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.seg.on .seg-n { background: rgba(255,255,255,.22); color: #fff; }

/* Rows gain quick actions while working a list */
.row-wrap { margin-bottom: 8px; }
.row-wrap .row-link { margin-bottom: 0; }

.row-acts {
  display: flex;
  gap: 6px;
  padding: 8px 0 0 46px;
}

.row-acts .mini { flex: 0 0 auto; min-width: 84px; }

/* ---------- worked-list strip ---------- */

/* ---------- topic tags in history ---------- */

.tag-row { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }

.tag {
  font-size: 12px;
  padding: 2px 8px;
  border-radius: 12px;
  background: var(--accent-bg);
  color: var(--accent);
}

/* An empty list is still worth seeing -- it usually means you have
   not asked yet, rather than that nobody qualifies. */
.pick-item.empty { opacity: .4; }
.pick-item.empty .pick-n { color: var(--ink-faint); }

/* ---------- notes in history ---------- */

.panel-row.voided .note-body {
  margin-top: 4px;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

/* only a voided note is struck through */
.panel-row.voided .note-body {
  text-decoration: line-through;
  color: var(--ink-faint);
}

.panel-row.voided { background: var(--paper); }

.fixnote {
  min-height: 44px;
  padding: 0 16px;
  font-size: 14px;
  color: var(--accent);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--card);
  flex-shrink: 0;
}

.note-body { margin-top: 2px; }

/* ---------- client briefing ---------- */

.brief-text {
  white-space: pre-line;
  line-height: 1.55;
  font-size: 15px;
}

.sent-body {
  margin: 10px 0 0;
  padding: 10px 12px;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  font-family: ui-monospace, Menlo, Consolas, monospace;
  font-size: 12px;
  line-height: 1.45;
  max-height: 320px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
}

/* ---------- checklist questions ---------- */

/* Full-width rows, not wrapping pills. The labels vary too much in
   length for a chip grid to look like anything but a ragged block. */

.q-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 54px;
  padding: 10px 14px;
  border: 0;
  border-bottom: 1px solid var(--rule);
  border-radius: 0;
  background: var(--card);
  text-align: left;
  cursor: pointer;
}

.q-row:last-child { border-bottom: 0; }
.q-row:active { background: var(--accent-bg); }

.q-box {
  width: 22px;
  height: 22px;
  border: 2px solid var(--rule);
  border-radius: 6px;
  flex-shrink: 0;
  position: relative;
}

.q-text {
  flex: 1;
  font-size: 16px;
  line-height: 1.35;
  color: var(--ink);
}

.q-row.on { background: var(--accent-bg); }
.q-row.on .q-box { background: var(--accent); border-color: var(--accent); }
.q-row.on .q-text { font-weight: 500; color: var(--accent); }

/* the tick */
.q-row.on .q-box::after {
  content: "";
  position: absolute;
  left: 6px;
  top: 2px;
  width: 6px;
  height: 11px;
  border: solid #fff;
  border-width: 0 2.5px 2.5px 0;
  transform: rotate(45deg);
}

.check-item {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  line-height: 1.45;
}

.check-item::before {
  content: "";
  width: 16px;
  height: 16px;
  border: 2px solid var(--rule);
  border-radius: 4px;
  flex-shrink: 0;
  margin-top: 3px;
}

@media print {
  .bar, #ask, #book, #printme { display: none !important; }
  body { background: #fff; }
  .panel { break-inside: avoid; }
}

/* ---------- count on a tab ---------- */

.tabs a { position: relative; }

.tab-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  margin-left: 6px;
  border-radius: 10px;
  background: var(--late-bar);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  vertical-align: middle;
}

/* ---------- a written follow-up on a card ---------- */

.draft {
  margin-top: 10px;
  padding: 10px 12px;
  background: var(--accent-bg);
  border-radius: var(--r);
}

.draft-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: .04em;
  margin-bottom: 6px;
}

.draft-body {
  width: 100%;
  min-height: 110px;
  font-size: 15px;
  line-height: 1.5;
  background: var(--card);
}

/* ---------- category filters on the To do page ---------- */

/* Three across, always. A grid rather than a scrolling row means every
   tile is the same width whatever its label, and nothing runs off the
   edge of a narrow phone. A fourth category wraps onto a second row. */
/* One row. Four tiles on a phone means the labels have to be short --
   Appts, Bdays, Biz, Follow up -- and the gaps and padding come in. */
.cats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
  margin-bottom: 18px;
}

/* Biz has three, so they get more room each */
body.biz-page .cats { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.cat {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  min-width: 0;
  min-height: 74px;
  padding: 8px 7px;
  border: 2px solid transparent;
  border-radius: var(--r);
  background: var(--surface-1, var(--card));
  text-align: left;
  cursor: pointer;
  overflow: hidden;
}

.cat b {
  display: block;
  font-size: 22px;
  font-weight: 700;
  line-height: 1;
}

.cat span {
  display: block;
  font-size: 12px;
  line-height: 1.2;
  margin-top: 3px;
  overflow-wrap: break-word;
  hyphens: auto;
}

.cat .cat-late {
  display: block;
  font-size: 11px;
  font-style: normal;
  font-weight: 700;
  color: var(--late);
  margin-top: auto;
  padding-top: 3px;
}

/* A little more room where there is a little more room */
@media (min-width: 400px) {
  .cat { min-height: 78px; padding: 9px 10px; }
  .cat span { font-size: 13px; }
}

/* Biz has three tiles, so it can afford longer labels */
body.biz-page .cat { padding: 9px 10px; }

.cat-bday   { background: var(--c-bday-bg);   color: var(--c-bday); }
.cat-appt   { background: var(--c-appt-bg);   color: var(--c-appt); }
.cat-follow { background: var(--c-follow-bg); color: var(--c-follow); }

/* the chosen one */
.cat.on { border-color: currentColor; }

/* A pinned tile at zero: still there, clearly nothing in it */
.cat.empty {
  background: var(--paper);
  color: var(--ink-faint);
  border-color: var(--rule);
  cursor: default;
}

.cat.empty b { font-weight: 500; }

/* Card bars match the filter colours. Overdue still overrides, because
   late matters more than what kind of thing it is. */
.alert.bar-birthday { border-left-color: var(--c-bday); }
.alert.bar-appt     { border-left-color: var(--c-appt); }
.alert.bar-followup { border-left-color: var(--c-follow); }
.alert.is-late      { border-left-color: var(--late-bar); }

/* A pinned category with nothing in it. Still visible, because knowing
   there are no appointments tomorrow is information. Not tappable,
   because there is nothing to filter to. */
.cat.zero {
  opacity: .5;
  cursor: default;
}

.cat.zero b { font-weight: 500; }

/* A box that shows an answer rather than taking one */
input.computed {
  background: var(--paper);
  border-style: dashed;
  font-weight: 600;
  color: var(--ink);
  cursor: default;
}

input.computed.is-loss { color: var(--late); }

/* ---------- business cards ---------- */
/* One card, everything inside it. The owner and the call buttons were
   sitting outside the border, which read as if they belonged to
   nothing. */

.biz-card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-left: 5px solid var(--rule);
  border-radius: var(--r);
  margin-bottom: 8px;
  overflow: hidden;
}

.biz-card.is-late { border-left-color: var(--late-bar); }
.biz-card.is-soon { border-left-color: var(--soon-bar); }
.biz-card.is-ok   { border-left-color: var(--done-bar); }

.biz-main {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  text-decoration: none;
  color: inherit;
  min-height: var(--tap);
}

.biz-main:active { background: var(--accent-bg); }

.biz-foot {
  display: flex;
  gap: 6px;
  padding: 0 14px 12px 60px;
  flex-wrap: wrap;
}

.biz-foot .mini { flex: 0 0 auto; min-width: 76px; }
.biz-foot .mini:first-child { flex: 1 1 auto; justify-content: flex-start; }

/* the business tile */
.cat-biz  { background: var(--tax-bg);  color: var(--tax); }
.alert.bar-biz { border-left-color: var(--tax); }

/* ============================================================
   DESKTOP
   ============================================================
   Same markup, rearranged. The phone layout is the default and
   everything below only applies once there is room for it, so a
   narrow window falls back to the phone layout on its own.

   The shells are already CSS grid, so the tab bar becomes a left
   rail by changing the axis rather than repositioning anything. */

@media (min-width: 900px) {

  /* ---- the tab bar becomes a rail ---- */

  body.has-tabs {
    grid-template-columns: 216px minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
  }

  body.has-tabs .bar  { grid-column: 2; grid-row: 1; }
  body.has-tabs main  { grid-column: 2; grid-row: 2; }

  body.has-tabs .tabs {
    grid-column: 1;
    grid-row: 1 / 3;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: 2px;
    padding: 16px 10px;
    border-top: 0;
    border-right: 1px solid var(--rule);
    background: var(--paper);
  }

  body.has-tabs .tabs a {
    flex: 0 0 auto;
    text-align: left;
    padding: 11px 14px;
    font-size: 15px;
    border-radius: var(--r);
    white-space: nowrap;
  }

  body.has-tabs .tabs a:hover { background: var(--card); }

  body.has-tabs .tabs a.on {
    background: var(--accent-bg);
    color: var(--accent);
    font-weight: 500;
    box-shadow: inset 3px 0 0 var(--gold);
  }

  .tab-badge { float: right; margin-left: 0; }

  /* ---- room to breathe ---- */

  main { max-width: 900px; padding: 22px 28px 60px; margin: 0; }
  .bar { padding: 14px 28px; }
  .bar h1 { font-size: 20px; }

  /* ---- a record opens into two columns ---- */
  /* (moved out of the 900px block below, so it also applies in the
     split pane, which is narrower than the window) */

  /* ---- eight actions in one row ---- */

  .act-grid { grid-template-columns: repeat(10, minmax(0, 1fr)); }
  .act-grid button, .act-grid a { font-size: 13px; min-height: 46px; }

  /* ---- the To do tiles get their long labels back ---- */

  .cats { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
  .cat { min-height: 86px; padding: 12px 14px; }
  .cat b { font-size: 26px; }
  .cat span { font-size: 14px; }

  body.biz-page .cats { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  /* ---- lists sit more comfortably ---- */

  .alert { padding: 16px 18px; }
  .row-link, .biz-main { padding: 14px 18px; }
  .panel-row { padding: 13px 16px; }

  /* two businesses across, since the cards are short */
  body.biz-page #list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
    align-items: start;
  }
  body.biz-page .biz-card { margin-bottom: 0; }

  /* ---- record and form pages scroll like a page ---- */
  /* The phone shell pins the header and scrolls only the body, which
     gives main a fixed height. CSS columns inside a fixed height
     overflow sideways instead of growing downwards, so on desktop the
     whole page scrolls and the header sticks instead. */

  body.app-shell {
    display: block;
    height: auto;
    overflow: visible;
  }

  body.app-shell .bar {
    position: sticky;
    top: 0;
    z-index: 20;
  }

  body.app-shell main {
    overflow: visible;
    height: auto;
    min-height: 0;
    max-width: 760px;
    padding: 22px 28px 60px;
  }
  .field input, .field select, .field textarea { font-size: 15px; }

  /* a mouse can hit a smaller target than a thumb */
  .mini { min-height: 34px; font-size: 13px; }
  .slot { min-height: 40px; }

  /* ---- sheets become dialogs ---- */

  .sheet { align-items: center; }

  .sheet-card {
    max-width: 520px;
    margin: 0 auto;
    border-radius: 14px;
    max-height: 82vh;
  }

  .sheet-tall { max-height: 86vh; }
}

@media (min-width: 1500px) {
  main { max-width: 1100px; }
}

/* Short label on a phone, full one once there is room */
.lbl-long  { display: none; }
@media (min-width: 900px) {
  .lbl-short { display: none; }
  .lbl-long  { display: block; }
}

/* ---------- a record shown inside a list page ---------- */

/* A record inside the pane drops its own bar; the list beside it is
   the context. Forms keep theirs, because Cancel and Save live there. */
body.is-embedded .bar { display: none; }
body.is-embedded main { padding-top: 16px; }

/* A form inside the pane gets a tighter bar, since it is a column
   rather than a window. */
@media (min-width: 1000px) {
  .split-detail .bar { padding: 12px 18px; }
}

/* ---------- desktop: the list and the record together ---------- */

.split { display: contents; }
.split-detail { display: none; }

/* The split-on class is set by nav.js, which is the only thing that
   decides. No media query here, so the stylesheet and the click
   handler cannot disagree -- which is what kept sending a click to a
   full page instead of the pane. */

body.split-on main {
  max-width: none;
  padding: 0;
  display: grid;
  grid-template-columns: 340px minmax(0, 1fr);
  height: 100%;
  min-height: 0;
}

body.split-on .split-list {
  overflow-y: auto;
  padding: 18px 18px 40px;
  border-right: 1px solid var(--rule);
  min-height: 0;
}

body.split-on .split-detail {
  display: block;
  min-height: 0;
  background: var(--paper);
}

body.split-on .split-detail iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

body.split-on .split-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--ink-faint);
  font-size: 15px;
  text-align: center;
  padding: 40px;
}

/* the row you are reading stays marked */
body.split-on .row-card.is-chosen,
body.split-on .biz-card.is-chosen { border-color: var(--accent); }

body.split-on .row-card.is-chosen > .row-link,
body.split-on .biz-card.is-chosen .biz-main { background: var(--accent-bg); }

body.split-on .alert.is-chosen { background: var(--accent-bg); }
body.split-on .split-list .alert { cursor: pointer; }

/* the list column is narrow, so ease the padding */
body.split-on .split-list .row-link,
body.split-on .split-list .biz-main { padding: 11px 12px; }

body.split-on .split-list .cats {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

body.split-on .split-list .cat { min-height: 70px; padding: 9px 10px; }
body.split-on .split-list .cat b { font-size: 20px; }
body.split-on .split-list .cat span { font-size: 12px; }

body.biz-page.split-on .split-list .cats {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

body.biz-page.split-on .split-list #list {
  grid-template-columns: minmax(0, 1fr);
}



/* ============================================================
   DESKTOP DENSITY
   ============================================================
   The phone layout stacks everything because there is one column.
   With two, that stacking turns into long runs of empty space. */

@media (min-width: 1000px) {

  /* ---- people read as rows, not cards ---- */

  .person-tile { padding: 10px 14px; }

  .person-contact {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 6px;
    padding-top: 6px;
  }

  .contact {
    padding: 3px 9px;
    font-size: 13px;
    border: 1px solid var(--rule);
    border-radius: 20px;
    min-height: 0;
  }

  .contact.none { border: 0; padding-left: 0; }

  /* ---- the header carries more, in less ---- */

  .rec-head { margin-bottom: 8px; }
  .rec-name { font-size: 20px; }
  .tags { margin-bottom: 12px; }

  /* ---- sections stop shouting ---- */

  .acc { margin-bottom: 0; }
  .acc-head { padding: 11px 14px; }
  .acc-title { font-size: 15px; }

  /* an open section does not need its arrow to be prominent */
  .acc.is-open .acc-arrow { opacity: 0.35; }

  /* ---- panels tighten up ---- */

  .panel-row { padding: 10px 14px; }
  .panel-row .t { gap: 10px; }
  .lob-row { padding: 9px 14px 9px 12px; }

  /* ---- the actions are a strip, not eight buttons ---- */

  .act-grid { gap: 6px; margin-bottom: 14px; }
  .act-grid button, .act-grid a { min-height: 40px; font-size: 13px; }
}

/* The name sits above the rail on desktop, and is out of the way on
   a phone where the tab bar is along the bottom. */
.rail-name { display: none; }

@media (min-width: 900px) {
  /* The logo mark sits beside the name, set here rather than in nav.js
     so the rail markup does not have to change */
  .rail-name {
    display: block;
    padding: 6px 14px 18px 46px;
    min-height: 40px;
    font-size: 18px;
    font-weight: 600;
    line-height: 32px;
    color: var(--ink);
    letter-spacing: -0.01em;
    background: url('/icons/logo-mark.png') no-repeat 14px 4px / 24px auto;
  }
}

/* ---------- the record head, as one card ---------- */



/* The record splits into two columns once there is room, whether that
   is a browser window or the pane inside the client list.

   Two real columns rather than CSS multicol: multicol balances the
   flow into two independent runs, which is why the tops of the two
   sides never lined up. This way each column is its own stack and
   both start at the same line.

   The scroll release has to happen at the SAME width -- the phone
   shell gives main a definite height, and a fixed height would clip
   the columns. */
@media (min-width: 700px) {

  body.app-shell {
    display: block;
    height: auto;
    overflow: visible;
  }

  body.app-shell .bar {
    position: sticky;
    top: 0;
    z-index: 20;
  }

  body.app-shell main {
    overflow: visible;
    height: auto;
    min-height: 0;
  }

  main#wrap { max-width: 1180px; }

  .rec-cols {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 16px;
    align-items: start;
  }

  /* nine actions, nine columns. Icon only, so they fit. */
  .act-grid { grid-template-columns: repeat(10, minmax(0, 1fr)); gap: 5px; }
  .act-grid button, .act-grid a { font-size: 12.5px; padding: 0 4px; }
}

@media (min-width: 1400px) {
  main#wrap { max-width: 1420px; }
  .act-grid button, .act-grid a { font-size: 14px; }
}

/* Each column is a plain stack, so the sections in it sit flush */
.rec-cols > div > .acc { margin-bottom: 14px; }
.rec-cols > div > .acc:last-child { margin-bottom: 0; }

/* ============================================================
   THE RECORD HEADER
   ============================================================
   One card: name and Edit across the top, then the people as rows
   with hairlines between them, and the address alongside. */

.rec-card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 0;
  margin-bottom: 16px;
  overflow: hidden;
}

.hdr-top {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 16px 18px 0;
}

.hdr-avatar {
  width: 46px;
  height: 46px;
  font-size: 15px;
  flex-shrink: 0;
}

.hdr-title { flex: 1; min-width: 0; }

.hdr-title .rec-name {
  display: block;
  font-size: 19px;
  font-weight: 600;
  line-height: 1.25;
}

.hdr-title .rec-sub {
  display: block;
  font-size: 14px;
  color: var(--ink-soft);
  margin-top: 1px;
}

.hdr-edit {
  flex-shrink: 0;
  align-self: flex-start;
  padding: 6px 16px;
  font-size: 14px;
  font-weight: 500;
  color: var(--accent);
  background: var(--accent-bg);
  border-radius: 20px;
  text-decoration: none;
  min-height: 32px;
  display: inline-flex;
  align-items: center;
}

.hdr-edit:active { opacity: 0.7; }

.rec-card .tags { padding: 12px 18px 0; margin: 0; }

.hdr-body {
  display: grid;
  grid-template-columns: 1fr;
  margin-top: 14px;
  border-top: 1px solid var(--rule);
}

/* ---- the people ---- */

.hdr-person {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 18px;
  border-bottom: 1px solid var(--rule);
}

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

.hdr-person .initials {
  width: 32px;
  height: 32px;
  font-size: 12px;
  flex-shrink: 0;
}

.hdr-who { flex: 1; min-width: 0; }

.hdr-name {
  display: block;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.3;
}

.hdr-role {
  display: block;
  font-size: 13px;
  color: var(--ink-soft);
  line-height: 1.3;
}

.hdr-contact {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 1px;
  text-align: right;
  flex-shrink: 0;
}

.hdr-reach {
  font-size: 13px;
  color: var(--accent);
  text-decoration: none;
  max-width: 190px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hdr-reach.none { color: var(--ink-faint); }

/* ---- the side column ---- */

.hdr-side {
  padding: 12px 18px 14px;
  border-top: 1px solid var(--rule);
}

.hdr-fact { margin-bottom: 13px; font-size: 14px; line-height: 1.45; }
.hdr-fact:last-child { margin-bottom: 0; }

.hdr-label {
  display: block;
  font-size: 13px;
  color: var(--ink-faint);
  margin-bottom: 1px;
}

.hdr-fact .none { color: var(--ink-faint); }
.hdr-fact .hdr-reach { display: block; margin-top: 4px; max-width: none; }

.hdr-fact .one-line {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Once there is room the address moves beside the people. No window
   breakpoint -- this page can be a pane inside the client list. */
@media (min-width: 620px) {
  .hdr-body { grid-template-columns: minmax(0, 1.6fr) minmax(200px, 1fr); }

  .hdr-side {
    border-top: 0;
    border-left: 1px solid var(--rule);
    padding: 14px 18px;
  }
}

/* ---------- inline icons ---------- */
/* The size lives on the svg element itself. These rules only stop it
   growing -- an svg in a flex row will otherwise stretch. */

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

/* Sized to the button they sit in. CSS overrides the width and height
   attributes on the element -- those are only there so the icon has an
   intrinsic size and a flex parent cannot stretch it. */

.act-grid .ico { width: 26px; height: 26px; }   /* 50px buttons */
.mini .ico     { width: 21px; height: 21px; }   /* 38px buttons */

.actions button .ico,
.actions a .ico { width: 21px; height: 21px; }

.hdr-edit .ico { width: 15px; height: 15px; margin-right: 5px; }

.act-grid button,
.act-grid a,
.mini { gap: 6px; }

@media (min-width: 900px) {
  .act-grid .ico { width: 24px; height: 24px; }  /* 46px buttons */
  .mini .ico     { width: 19px; height: 19px; }  /* 34px buttons */
  .actions button .ico,
  .actions a .ico { width: 19px; height: 19px; }
}

@media (min-width: 1400px) {
  .act-grid .ico { width: 21px; height: 21px; }  /* 40px buttons */
}

/* ---------- client cards ---------- */
/* One card, with the reach buttons inside it. They were siblings of
   the link, which put them outside the border. */

.row-card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-left: 5px solid var(--rule);
  border-radius: var(--r);
  margin-bottom: 8px;
  overflow: hidden;
}

.row-card.is-late { border-left-color: var(--late-bar); }
.row-card.is-soon { border-left-color: var(--soon-bar); }
.row-card.is-ok   { border-left-color: var(--done-bar); }
.row-card.is-new  { border-left-color: var(--accent); }

.row-card > .row-link {
  border: 0;
  border-radius: 0;
  margin: 0;
  background: transparent;
}

.row-card > .row-acts {
  display: flex;
  gap: 6px;
  padding: 0 12px 11px 56px;
  flex-wrap: wrap;
}

.row-card > .row-acts .mini { flex: 0 0 auto; min-width: 62px; }

.row-card.is-chosen { border-color: var(--accent); }
.row-card.is-chosen > .row-link { background: var(--accent-bg); }

/* ---------- the rail ---------- */

.rail-new { display: none; }
.rail-only { display: none; }

.tabs a .ico { display: none; }

@media (min-width: 900px) {
  .rail-only { display: flex; }

  .tabs a {
    display: flex;
    align-items: center;
    gap: 11px;
  }

  .tabs a .ico { display: block; width: 19px; height: 19px; }

  .rail-new {
    display: flex;
    align-items: center;
    gap: 9px;
    margin: 0 4px 14px;
    padding: 10px 14px;
    border: 0;
    border-radius: var(--r);
    background: var(--accent);
    color: #fff;
    font-size: 15px;
    font-weight: 500;
    cursor: pointer;
    min-height: 42px;
  }

  .rail-new:active { opacity: 0.85; }
  .rail-new .ico { width: 18px; height: 18px; }

  /* Settings sits away from the rest */
  .rail-foot { margin-top: auto; }

  .tabs { padding-bottom: 16px; }
}

/* ---------- the deadlines grid ---------- */
/* Stacked on a phone, filling the width on a desktop. The day heading
   spans the row so a week still reads as a week. */

.dl-grid .day-head { margin: 18px 0 8px; }

@media (min-width: 700px) {
  main .dl-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(205px, 1fr));
    gap: 10px;
    align-items: start;
  }

  .dl-grid .day-head {
    grid-column: 1 / -1;
    margin: 14px 0 0;
  }

  .dl-grid .row-card { margin-bottom: 0; }

  /* compact enough for five or six across */
  .dl-grid .row-link {
    padding: 11px 12px;
    align-items: flex-start;
  }

  .dl-grid .row-name { font-size: 14px; line-height: 1.3; }
  .dl-grid .row-why  { font-size: 12.5px; line-height: 1.35; }

  .dl-grid .row-acts {
    padding: 0 10px 10px;
    gap: 5px;
  }

  .dl-grid .row-acts .mini { flex: 1 1 auto; min-width: 0; min-height: 32px; }
  .dl-grid .row-acts .ico { width: 17px; height: 17px; }
}

/* the page itself needs the width to make use of it */
@media (min-width: 900px) {
  body.has-tabs main.wide { max-width: 1500px; }
}

/* ---------- the day, hour by hour ---------- */

.day-grid {
  position: relative;
  margin-top: 4px;
}

.day-hour {
  position: absolute;
  left: 0;
  right: 0;
  height: 0;
  border-top: 1px solid var(--rule);
}

.day-time {
  position: absolute;
  left: 0;
  top: -8px;
  width: 50px;
  text-align: right;
  font-size: 12px;
  color: var(--ink-faint);
  background: var(--paper);
  padding-right: 6px;
}

/* where you are in the day */
.day-now {
  position: absolute;
  left: 52px;
  right: 0;
  height: 2px;
  background: var(--late);
  z-index: 3;
}

.day-now::before {
  content: "";
  position: absolute;
  left: -4px;
  top: -3px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--late);
}

.day-appt {
  position: absolute;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 9px;
  padding: 4px 10px;
  border-radius: 8px;
  border-left: 4px solid var(--accent);
  background: var(--accent-bg);
  color: var(--ink);
  text-decoration: none;
  overflow: hidden;
  z-index: 2;
}

.day-appt:active { opacity: 0.8; }

.day-appt.is-theirs {
  border-left-color: var(--soon-bar);
  background: var(--soon-bg);
}

.day-appt.is-off {
  border-left-color: var(--rule);
  background: var(--paper);
  color: var(--ink-faint);
  text-decoration: line-through;
}

.day-appt-time {
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
  white-space: nowrap;
}

.day-appt.is-theirs .day-appt-time { color: var(--soon); }
.day-appt.is-off .day-appt-time { color: var(--ink-faint); }

.day-appt-who {
  font-size: 14px;
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  flex: 0 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* the trailing detail gives way first when the block is narrow */
.day-appt-why {
  font-size: 12.5px;
  color: var(--ink-soft);
  line-height: 1.25;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1 1 auto;
  min-width: 0;
}

.day-appt-time { flex: 0 0 auto; }

/* a long appointment has room to breathe */
.day-appt.is-tall {
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 2px;
  padding: 8px 12px;
}

.day-appt.is-tall .day-appt-why,
.day-appt.is-tall .day-appt-who { white-space: normal; }

/* ---------- the calendar, split ---------- */
/* Month and new bookings on the left, the chosen day on the right.
   Stacked on a phone, side by side once there is room. */

.cal-right { margin-top: 20px; }

@media (min-width: 900px) {
  body.has-tabs main.cal-split {
    max-width: 1320px;
    display: grid;
    grid-template-columns: minmax(340px, 420px) minmax(0, 1fr);
    gap: 24px;
    align-items: start;
  }

  .cal-left  { min-width: 0; }
  .cal-right { margin-top: 0; min-width: 0; }

  /* the day column scrolls on its own, so the month stays put */
  .cal-right #agenda {
    max-height: calc(100vh - 190px);
    overflow-y: auto;
    padding-right: 4px;
  }

  .cal-right .group { margin-top: 0; }

  /* the state message belongs across the bottom */
  main.cal-split > #state { grid-column: 1 / -1; }
}

/* the calculator shortcut in the To do bar, phone only */
#calclink {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  min-height: 40px;
  color: var(--accent);
}

@media (min-width: 900px) { #calclink { display: none; } }

/* which language a link will go in */
.link-lang {
  display: block;
  width: 100%;
  margin: -4px 0 12px;
  padding: 8px 12px;
  border: 1px solid var(--rule);
  border-radius: 20px;
  background: var(--card);
  color: var(--ink-soft);
  font-size: 13px;
  text-align: center;
  cursor: pointer;
}

.link-lang.is-es {
  background: var(--accent-bg);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 500;
}

/* something you asked for yourself, rather than the system noticing */
.alert.is-reminder { border-left-color: var(--accent); }

.alert.is-reminder .alert-title::before {
  /* the first space after \00b7 ends the escape and is swallowed, so a
     second one is needed to actually show a space */
  content: "Reminder \00b7  ";
  color: var(--accent);
  font-weight: 600;
}

/* a reminder chip carries its bell inline */
/* .ico is display:block so a flex parent cannot stretch it; inside a
   chip that pushed the text onto its own line, so here it sits inline */
.chip .ico {
  display: inline-block;
  width: 13px;
  height: 13px;
  vertical-align: -2px;
  margin-right: 3px;
}
