/* Nebula Sans (SIL OFL 1.1, see NebulaSans-OFL.txt) — used for the clock,
   where a plain sans with tabular figures reads as a readout. Oswald remains
   the display face for headings: it was chosen to match the seal. */
@font-face {
  font-family: 'Nebula Sans';
  src: url('../fonts/NebulaSans-Medium.woff2') format('woff2');
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: 'Nebula Sans';
  src: url('../fonts/NebulaSans-Semibold.woff2') format('woff2');
  font-weight: 600;
  font-display: swap;
}

@font-face {
  font-family: 'Oswald';
  src: url('../fonts/Oswald-Regular.ttf') format('truetype');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Oswald';
  src: url('../fonts/Oswald-Bold.ttf') format('truetype');
  font-weight: 700;
  font-display: swap;
}

/* FieldReport — visual system.
 *
 * The old palette was a desaturated grey-green on grey-white: safe, and drab.
 * This one commits. Deep pine carries the chrome, the neutrals are warm rather
 * than grey so white cards sit on paper instead of concrete, and there is one
 * accent — the orange of surveyor's flagging tape — spent only on the thing
 * that wants attention. Nothing else competes with it.
 *
 * Both themes are defined at the token level; components never reach past a
 * variable, so dark mode is a palette swap and not a second stylesheet.
 */
:root {
  /* chrome */
  --green:        #0E4430;
  --green-light:  #17624A;
  --green-pale:   #E4EDE6;
  --green-deep:   #0A3323;
  --on-green:     #ffffff;

  /* the one accent */
  --sun:          #C0761A;
  --sun-strong:   #A8620F;
  --sun-wash:     #FBF0DB;
  --sun-line:     #EBD9B4;

  /* type */
  --ink:          #15201A;
  --ink-soft:     #3F5049;
  --muted:        #6E7B73;

  /* ground — warm, so white reads as paper */
  --bg:           #F5F2EA;
  --card:         #ffffff;
  --card-sunk:    #FAF8F2;
  --line:         #E3DDD1;
  --line-soft:    #EDE8DD;
  --line-strong:  #CDC5B5;

  /* state */
  --danger:       #A8322A;
  --danger-wash:  #FAE7E4;
  --danger-line:  #EFD2CE;
  --warn:         #8A5B00;
  --warn-wash:    #FBF1D9;
  --warn-line:    #EDDFB2;
  --ok:           #1D7A46;
  --ok-deep:      #175C35;
  --ok-wash:      #E2F0E7;
  --ok-line:      #C9E0D2;
  --neutral-wash: #EFECE4;
  --dot-none:     #C6C0B3;

  /* The masthead is a brand surface, not a themed one: it stays deep green in
     both themes. Inverting it would put mint behind white text. */
  --bar-top:      #17624A;
  --bar-mid:      #0E4430;
  --bar-bot:      #0A3323;
  --bar-ink:      #ffffff;

  --toast-bg:     #14261C;
  --scrim:        rgba(18,26,21,.46);
  --tabbar-bg:    rgba(255,255,255,.92);

  /* depth — two levels, warm-tinted rather than pure black */
  --lift:      0 1px 2px rgba(28,36,30,.05), 0 2px 8px rgba(28,36,30,.045);
  --lift-2:    0 2px 6px rgba(28,36,30,.07), 0 10px 26px rgba(28,36,30,.08);
  --lift-bar:  0 -1px 0 var(--line), 0 -8px 24px rgba(28,36,30,.05);

  /* The company seal has the name lettered around it in a condensed bold sans.
     Setting the app's own chrome in the same voice makes the phone, the report
     and the mark on the door look like one thing.

     Display only, deliberately: Oswald is condensed and tall, which is what a
     masthead wants and the opposite of what a column of diameters wants. */
  --display: 'Oswald', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --serif: ui-serif, "Iowan Old Style", Charter, "Palatino Linotype", Palatino, Georgia, serif;
  --radius:     14px;
  --radius-sm:  10px;

  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}

@media (prefers-color-scheme: dark) {
  :root {
    --green:        #74C79E;
    --green-light:  #93D8B6;
    --green-pale:   #16291F;
    --green-deep:   #0B1D15;
    --on-green:     #08130D;

    --sun:          #E3A251;
    --sun-strong:   #F0B268;
    --sun-wash:     #2A2114;
    --sun-line:     #453722;

    --ink:          #E3EAE4;
    --ink-soft:     #AAB8AF;
    --muted:        #85938B;

    --bg:           #0C120F;
    --card:         #141C17;
    --card-sunk:    #101713;
    --line:         #26332B;
    --line-soft:    #1C2620;
    --line-strong:  #38473D;

    --danger:       #EE9C90;
    --danger-wash:  #2C1B18;
    --danger-line:  #472A25;
    --warn:         #DEBB75;
    --warn-wash:    #282112;
    --warn-line:    #42381F;
    --ok:           #7CC291;
    --ok-deep:      #9CD3AC;
    --ok-wash:      #16291F;
    --ok-line:      #2A4231;
    --neutral-wash: #1A211C;
    --dot-none:     #4A574E;

    --bar-top:      #16311F;
    --bar-mid:      #0D2419;
    --bar-bot:      #081710;
    --bar-ink:      #DCEBE1;

    --toast-bg:     #223529;
    --scrim:        rgba(0,0,0,.64);
    --tabbar-bg:    rgba(20,28,23,.93);

    --lift:      0 1px 2px rgba(0,0,0,.34), 0 2px 8px rgba(0,0,0,.28);
    --lift-2:    0 2px 6px rgba(0,0,0,.4), 0 10px 26px rgba(0,0,0,.36);
    --lift-bar:  0 -1px 0 var(--line), 0 -8px 24px rgba(0,0,0,.3);
  }
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* An explicit `display` in a rule below outranks the UA stylesheet's
   `[hidden] { display: none }`, so state the intent once, loudly. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  overscroll-behavior-y: none;
}

/* ------------------------------------------------------------- app bar */

#appbar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: calc(var(--safe-top) + 10px) 12px 10px;
  background: var(--green);
  color: var(--on-green);
  box-shadow: 0 1px 3px rgba(0,0,0,.18);
}

.bar-title { flex: 1; min-width: 0; display: flex; flex-direction: column; }
#barTitle {
  font-family: var(--display);
  letter-spacing: .012em;
  font-size: 19px; font-weight: 600;
  letter-spacing: -.015em;
}
#barSub { font-size: 11.5px; opacity: .8; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.icon-btn {
  background: rgba(255,255,255,.14);
  border: none;
  color: var(--on-green);
  width: 34px; height: 34px;
  border-radius: 9px;
  font-size: 19px;
  line-height: 1;
  display: grid; place-items: center;
  cursor: pointer;
  flex: none;
}
.icon-btn:active { background: rgba(255,255,255,.28); }
a.icon-btn { text-decoration: none; font-weight: 700; font-size: 17px; }

/* ------------------------------------------------------------- banners */

#offlineBanner, #queueBanner {
  padding: 8px 14px;
  font-size: 13px;
  text-align: center;
  background: var(--warn-wash);
  color: var(--warn);
  border-bottom: 1px solid var(--warn-line);
}
#queueBanner { background: var(--green-pale); color: var(--green); border-color: var(--ok-line); }
#queueBanner button {
  margin-left: 8px; border: none; background: var(--green); color: var(--on-green);
  padding: 4px 10px; border-radius: 6px; font-size: 12px; font-weight: 600;
}

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

main {
  padding: 12px 12px calc(78px + var(--safe-bottom));
  max-width: 900px;
  margin: 0 auto;
}

#tabbar {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: 40;
  display: flex;
  background: var(--tabbar-bg);
  backdrop-filter: saturate(180%) blur(14px);
  border-top: 1px solid var(--line);
  padding-bottom: var(--safe-bottom);
}
#tabbar button {
  flex: 1;
  border: none; background: none;
  padding: 7px 0 8px;
  font-size: 10.5px; font-weight: 600;
  color: var(--muted);
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  cursor: pointer;
}
#tabbar button span { font-size: 21px; line-height: 1; }
#tabbar button.active { color: var(--green); }

/* --------------------------------------------------------------- cards */

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

.activity-card {
  display: flex; align-items: center; gap: 13px;
  padding: 15px 14px;
  cursor: pointer;
  width: 100%;
  border: none; background: var(--card);
  text-align: left;
  font: inherit; color: inherit;
}
.activity-card:active { background: var(--green-pale); }
.activity-card .emoji { font-size: 27px; flex: none; width: 36px; text-align: center; }
.activity-card .meta { flex: 1; min-width: 0; }
.activity-card .name { font-weight: 640; font-size: 15.5px; }
.activity-card .desc { font-size: 12.5px; color: var(--muted); margin-top: 1px; }
.activity-card .chev { color: var(--line-strong); font-size: 22px; flex: none; }

.section-label {
  font-size: 11.5px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted);
  margin: 18px 4px 7px;
}
.section-label:first-child { margin-top: 4px; }

/* Settings categories.
   The existing .section-label names one setting; this names the group it is
   filed under, so it has to read a clear level above — bigger, in the ink
   colour rather than muted, and separated by a rule instead of whitespace. */
.set-group-head {
  font-family: var(--display);
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%;
  font-size: 15.5px; font-weight: 680; letter-spacing: -.01em;
  color: var(--ink);
  margin: 26px 2px 2px;
  padding: 0 0 8px;
  border-bottom: 1px solid var(--line);
  background: none;
  text-align: left;
}
.set-group-head.is-static { display: block; }
.set-group-head:first-child { margin-top: 6px; }
.set-group-body > .section-label:first-child { margin-top: 12px; }

/* The one group that stays shut. */
.set-group.is-foldable { margin-top: 26px; }
.set-group.is-foldable .set-group-head {
  margin-top: 0; cursor: pointer; border: 1px solid var(--line);
  border-radius: 12px; padding: 13px 14px; background: var(--card);
}
.set-group.is-foldable .set-group-body { display: none; }
.set-group.is-foldable.open .set-group-body { display: block; }
.set-group.is-foldable.open .set-group-head { border-radius: 12px 12px 0 0; border-bottom-color: transparent; }
.set-chev { color: var(--muted); display: inline-flex; transition: transform .18s ease; }
.set-group.is-foldable.open .set-chev { transform: rotate(90deg); }
.set-group-head:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

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

/* ------------------------------------------------------------ sections */

.sec { background: var(--card); border: 1px solid var(--line); border-radius: 13px; margin-bottom: 10px; }
.sec-head {
  display: flex; align-items: center; gap: 9px;
  padding: 13px 14px;
  cursor: pointer; user-select: none;
}
.sec-head .caret { color: var(--muted); font-size: 13px; transition: transform .16s; flex: none; width: 12px; }
.sec.open .sec-head .caret { transform: rotate(90deg); }
.sec-head .t { flex: 1; font-weight: 640; font-size: 15px; }
.sec-head .badge {
  font-size: 11px; font-weight: 700;
  background: var(--green-pale); color: var(--green);
  padding: 2px 8px; border-radius: 20px;
}
.sec-head .badge.req { background: var(--danger-wash); color: var(--danger); }
.sec-body { display: none; padding: 0 14px 14px; }
.sec.open .sec-body { display: block; }
.sec-help {
  font-size: 12px; color: var(--muted); font-style: italic;
  margin: -2px 0 12px; padding: 8px 10px;
  background: var(--card-sunk); border-left: 2px solid var(--line); border-radius: 0 6px 6px 0;
}

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

.field { margin-bottom: 13px; }
.field > label {
  display: block;
  font-size: 12.5px; font-weight: 620; color: var(--ink-soft);
  margin-bottom: 5px;
}
.field > label .req { color: var(--danger); margin-left: 2px; }

input[type=text], input[type=number], input[type=date], input[type=time],
input[type=tel], input[type=email], input[type=password], select, textarea {
  width: 100%;
  padding: 11px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  font-size: 16px; /* 16px keeps iOS from zooming on focus */
  font-family: inherit;
  background: var(--card);
  color: var(--ink);
  appearance: none;
}
textarea { resize: vertical; min-height: 84px; line-height: 1.45; }
select {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill='%236b7280' d='M6 8.5 2 4.5h8z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 11px center;
  background-size: 12px;
  padding-right: 32px;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--green-light);
  box-shadow: 0 0 0 3px rgba(45,107,65,.13);
}
input.invalid, select.invalid, textarea.invalid { border-color: var(--danger); }

/* Brief flash so it's obvious which fields the app filled in for you. */
@keyframes autofill-flash {
  from { background: var(--ok-wash); border-color: var(--green-light); }
  to   { background: var(--card);    border-color: var(--line); }
}
input.autofilled, select.autofilled, textarea.autofilled {
  animation: autofill-flash 1.6s ease-out;
}

.check {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 0; cursor: pointer;
}
.check input { width: 21px; height: 21px; accent-color: var(--green); flex: none; }
.check span { font-size: 14.5px; }

.chips { display: flex; flex-wrap: wrap; gap: 7px; }
.chip {
  padding: 7px 13px;
  border: 1px solid var(--line);
  border-radius: 20px;
  background: var(--card);
  font-size: 13.5px;
  cursor: pointer;
  user-select: none;
}
.chip.on { background: var(--green); color: var(--on-green); border-color: var(--green); font-weight: 600; }

/* --------------------------------------------------------------- table */

.tbl-rows { display: flex; flex-direction: column; gap: 9px; }
.tbl-row {
  border: 1px solid var(--line);
  border-radius: 11px;
  overflow: hidden;
  background: var(--card-sunk);
}
.tbl-row-head {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 11px;
  background: var(--green-pale);
  font-size: 12.5px; font-weight: 660; color: var(--green);
}
.tbl-row-head .n { flex: 1; }
.tbl-row-head button {
  border: none; background: none; color: var(--danger);
  font-size: 17px; padding: 0 4px; cursor: pointer; line-height: 1;
}
.tbl-row-body { padding: 11px; display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.tbl-row-body .field { margin: 0; }
.tbl-row-body .field.wide { grid-column: 1 / -1; }
.tbl-row-body input, .tbl-row-body select { padding: 9px 10px; font-size: 15px; }
.tbl-row-body select { background-position: right 9px center; }
.tbl-row-body > .field > label { font-size: 11.5px; margin-bottom: 3px; }

.btn-add {
  width: 100%;
  margin-top: 9px;
  padding: 11px;
  border: 1.5px dashed var(--line-strong);
  border-radius: 10px;
  background: var(--card);
  color: var(--green);
  font-size: 14px; font-weight: 640;
  cursor: pointer;
}
.btn-add:active { background: var(--green-pale); }
.dup-btn { color: var(--muted) !important; font-size: 15px !important; }

/* -------------------------------------------------------------- photos */

.photo-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.photo-cell { position: relative; aspect-ratio: 4/3; border-radius: 9px; overflow: hidden; border: 1px solid var(--line); background: var(--line-soft); }
.photo-cell img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-cell .del {
  position: absolute; top: 3px; right: 3px;
  width: 22px; height: 22px; border-radius: 50%;
  background: rgba(0,0,0,.6); color: var(--on-green); border: none;
  font-size: 14px; line-height: 1; cursor: pointer;
  display: grid; place-items: center;
}
.photo-cell .cap {
  position: absolute; bottom: 0; left: 0; right: 0;
  background: linear-gradient(transparent, rgba(0,0,0,.72));
  color: var(--on-green); font-size: 10px; padding: 12px 5px 4px;
  border: none; width: 100%; text-align: left;
}
.photo-add {
  aspect-ratio: 4/3;
  border: 1.5px dashed var(--line-strong); border-radius: 9px;
  background: var(--card); color: var(--green);
  font-size: 25px; cursor: pointer;
  display: grid; place-items: center;
}

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

.sig-block { margin-bottom: 16px; }
/* A coordinate button inside a table cell. Narrow, because it sits in a row of
   number boxes and must not be the widest thing there. */
.cell-gps {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  width: 100%; min-height: 42px;
  padding: 8px 6px;
  border: 1px solid var(--line); border-radius: 9px;
  background: var(--card); color: var(--muted);
  font: 600 12px/1.2 inherit;
  cursor: pointer;
}
.cell-gps svg { flex: none; }
.cell-gps.has-fix { color: var(--ok-deep); border-color: var(--ok-line); background: var(--ok-wash); }
.cell-gps:disabled { opacity: .6; }
.cell-gps:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

.sig-canvas-wrap { position: relative; border: 1px solid var(--line); border-radius: 10px; background: var(--card); overflow: hidden; }
.sig-canvas-wrap canvas { display: block; width: 100%; height: 150px; touch-action: none; }
.sig-canvas-wrap .hint {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  color: var(--muted); font-size: 13.5px; pointer-events: none;
}
.sig-canvas-wrap.signed .hint { display: none; }
.sig-actions { display: flex; gap: 8px; margin-top: 7px; align-items: center; }
.sig-actions button {
  padding: 7px 13px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--card); font-size: 13px; cursor: pointer; color: var(--ink);
}
.sig-unavailable { flex: 1; display: flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--muted); justify-content: flex-end; }
.sig-unavailable input { width: 19px; height: 19px; accent-color: var(--green); }
.sig-disabled { opacity: .42; pointer-events: none; }

/* ----------------------------------------------------- computed panel */

.computed { font-variant-numeric: tabular-nums; }

.stat-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; margin-bottom: 11px; }
.stat {
  background: var(--green-pale); border-radius: 10px;
  padding: 9px 6px; text-align: center;
}
.stat-v { font-size: 19px; font-weight: 700; color: var(--green); line-height: 1.1; }
.stat-l { font-size: 10.5px; font-weight: 650; color: var(--ink-soft); margin-top: 2px; }
.stat-s { font-size: 9.5px; color: var(--muted); }

/* The sketch map. Padded because plot markers on the boundary would otherwise
   be clipped by the box, and `overflow: visible` on the svg lets the outermost
   ones spill into that padding rather than being cut in half. */
/* The key under the plot map. Without it the shading is three colours nobody
   explained, on a document that goes to somebody who did not choose them. */
/* The one-line "what this sample is for" under a demo row. */
.hist-item .shows {
  font-size: 11.5px; line-height: 1.35;
  color: var(--muted);
  margin-top: 3px;
}

/* Sits above the tab bar so it cannot be mistaken for part of the form, and
   waits rather than reloading on its own — see showUpdatePrompt. */
/* Company logo, in Settings. Chequerboard so a transparent PNG reads as
   transparent rather than as a white rectangle somebody has to guess about. */
.logo-preview {
  display: grid; place-items: center;
  min-height: 76px; padding: 10px;
  border: 1px solid var(--line); border-radius: 10px;
  background-color: var(--card-sunk);
  background-image:
    linear-gradient(45deg, var(--line-soft) 25%, transparent 25%),
    linear-gradient(-45deg, var(--line-soft) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, var(--line-soft) 75%),
    linear-gradient(-45deg, transparent 75%, var(--line-soft) 75%);
  background-size: 12px 12px;
  background-position: 0 0, 0 6px, 6px -6px, -6px 0;
}
.logo-preview img { max-height: 56px; max-width: 100%; object-fit: contain; }
.logo-carries {
  display: flex; align-items: flex-start; gap: 9px;
  margin-top: 12px; cursor: pointer;
}
.logo-carries input { width: 19px; height: 19px; margin-top: 1px; flex: none; accent-color: var(--green); }
.logo-carries b { display: block; font-size: 13.5px; font-weight: 620; }
.logo-carries i { display: block; font-size: 12px; font-style: normal; color: var(--muted); margin-top: 2px; }

.logo-actions { display: flex; gap: 8px; margin-top: 8px; }
.logo-actions .btn { width: auto; margin: 0; padding: 9px 14px; }

.update-bar {
  position: fixed;
  left: 12px; right: 12px;
  bottom: calc(74px + var(--safe-bottom));
  z-index: 60;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 11px 12px 11px 15px;
  background: var(--toast-bg); color: #fff;
  border-radius: 12px;
  box-shadow: var(--lift-2);
  font-size: 13.5px; font-weight: 560;
  opacity: 0; transform: translateY(8px);
  transition: opacity .22s ease, transform .22s ease;
}
.update-bar.on { opacity: 1; transform: none; }
.update-bar button {
  flex: none;
  border: none; border-radius: 8px;
  background: var(--green-light); color: #fff;
  padding: 7px 14px;
  font: inherit; font-weight: 650;
  cursor: pointer;
}
@media (prefers-reduced-motion: reduce) { /* Company logo, in Settings. Chequerboard so a transparent PNG reads as
   transparent rather than as a white rectangle somebody has to guess about. */
.logo-preview {
  display: grid; place-items: center;
  min-height: 76px; padding: 10px;
  border: 1px solid var(--line); border-radius: 10px;
  background-color: var(--card-sunk);
  background-image:
    linear-gradient(45deg, var(--line-soft) 25%, transparent 25%),
    linear-gradient(-45deg, var(--line-soft) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, var(--line-soft) 75%),
    linear-gradient(-45deg, transparent 75%, var(--line-soft) 75%);
  background-size: 12px 12px;
  background-position: 0 0, 0 6px, 6px -6px, -6px 0;
}
.logo-preview img { max-height: 56px; max-width: 100%; object-fit: contain; }
.logo-carries {
  display: flex; align-items: flex-start; gap: 9px;
  margin-top: 12px; cursor: pointer;
}
.logo-carries input { width: 19px; height: 19px; margin-top: 1px; flex: none; accent-color: var(--green); }
.logo-carries b { display: block; font-size: 13.5px; font-weight: 620; }
.logo-carries i { display: block; font-size: 12px; font-style: normal; color: var(--muted); margin-top: 2px; }

.logo-actions { display: flex; gap: 8px; margin-top: 8px; }
.logo-actions .btn { width: auto; margin: 0; padding: 9px 14px; }

.update-bar { transition: none; } }

.map-key {
  display: flex; flex-wrap: wrap; gap: 4px 14px;
  margin: 9px 2px 0;
  font-size: 11.5px; color: var(--muted);
}
.map-key-item { display: inline-flex; align-items: center; gap: 5px; }
.map-key-item i {
  width: 11px; height: 11px; border-radius: 50%;
  border: 1.5px solid var(--muted); background: var(--neutral-wash);
  flex: none;
}
.map-key-item.is-ok i     { background: var(--ok-wash);     border-color: var(--ok-deep); }
.map-key-item.is-warn i   { background: var(--warn-wash);   border-color: var(--warn); }
.map-key-item.is-bad i    { background: var(--danger-wash); border-color: var(--danger); }
.map-key-item.is-planned i { background: none; border-style: dashed; }
.map-key-item.is-route i {
  width: 16px; height: 0; border-radius: 0;
  border: none; border-top: 1.5px dashed var(--muted); background: none;
}

.standmap {
  background: var(--neutral-wash, #f4f6f4);
  border-radius: 10px; padding: 14px 12px 10px;
  margin: 11px 0;
}

.tract-total {
  background: var(--green); color: var(--on-green);
  border-radius: 10px; padding: 11px 13px; margin-bottom: 11px;
}
.tract-total strong { font-size: 18px; }
.tract-total .err { font-size: 11.5px; opacity: .85; margin-top: 3px; }

table.ctbl {
  width: 100%; border-collapse: collapse;
  font-size: 12px; margin-bottom: 11px;
}
table.ctbl th {
  text-align: right; font-size: 10px; text-transform: uppercase;
  letter-spacing: .04em; color: var(--muted); font-weight: 700;
  padding: 4px 5px; border-bottom: 1px solid var(--line);
}
table.ctbl th:first-child { text-align: left; }
table.ctbl td {
  text-align: right; padding: 5px; border-bottom: 1px solid var(--line-soft);
}
table.ctbl td:first-child { text-align: left; font-weight: 600; }
table.ctbl tr:last-child td { border-bottom: none; }

.reliability {
  font-size: 12px; font-weight: 600; line-height: 1.4;
  padding: 9px 11px; border-radius: 8px; border-left: 3px solid;
  margin-bottom: 9px;
}
.reliability.good         { background: var(--ok-wash); color: var(--ok-deep); border-color: var(--ok-deep); }
.reliability.fair         { background: var(--warn-wash); color: var(--warn); border-color: var(--warn-line); }
.reliability.poor         { background: var(--danger-wash); color: var(--danger); border-color: var(--danger); }
.reliability.insufficient { background: var(--neutral-wash); color: var(--ink-soft); border-color: var(--muted); }

.basis { font-size: 10.5px; color: var(--muted); font-style: italic; }

/* --------------------------------------------------------------- misc */

.gps-box { display: flex; align-items: center; gap: 11px; }
.gps-box .val { flex: 1; font-size: 13.5px; font-variant-numeric: tabular-nums; color: var(--muted); }
.gps-box .val strong { color: var(--ink); display: block; font-size: 14px; }

.btn {
  display: block; width: 100%;
  padding: 15px;
  border: none; border-radius: 12px;
  background: var(--green); color: var(--on-green);
  font-size: 16.5px; font-weight: 680;
  cursor: pointer;
  margin-top: 10px;
}
.btn:active { background: var(--green-light); }
.btn[disabled] { opacity: .5; }
.btn.secondary { background: var(--card); color: var(--green); border: 1.5px solid var(--line); }
.btn.danger { background: var(--card); color: var(--danger); border: 1.5px solid var(--danger-line); }
.btn-row { display: flex; gap: 9px; }
.btn-row .btn { margin-top: 0; }

.recip-list { display: flex; flex-direction: column; gap: 7px; margin-bottom: 9px; }
.recip {
  display: flex; align-items: center; gap: 9px;
  padding: 10px 12px;
  background: var(--green-pale); border-radius: 9px;
  font-size: 14px;
}
.recip .addr { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.recip button { border: none; background: none; color: var(--danger); font-size: 17px; cursor: pointer; padding: 0 3px; }

.hist-item {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 14px;
  border-bottom: 1px solid var(--line);
  cursor: pointer;
  background: var(--card);
}
.hist-item:last-child { border-bottom: none; }
.hist-item:active { background: var(--green-pale); }
.hist-item .emoji { font-size: 22px; flex: none; }
.hist-item .info { flex: 1; min-width: 0; }
.hist-item .ref { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.hist-item .ttl { font-weight: 620; font-size: 14.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hist-item .sub { font-size: 12.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.status-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.status-dot.ok { background: var(--ok); }
.status-dot.fail { background: var(--danger); }
.status-dot.none { background: var(--dot-none); }
.status-dot.queued { background: var(--warn); }
/* A certificate about to lapse. Mapped from contractors.js but never styled, so
   the one state that wanted a heads-up was a transparent circle. */
.status-dot.warn { background: var(--warn); }

.sample-tag {
  display: inline-block;
  background: var(--danger-wash); color: var(--danger);
  font-size: 9px; font-weight: 800; letter-spacing: .06em;
  padding: 1px 5px; border-radius: 4px;
  margin-right: 6px; vertical-align: 1px;
}
/* Practice is somebody's own work with an invented tract; a sample ships with
   the app. Same shape of tag, different word and weight, so the two folds in
   History do not read as the same thing listed twice. */
.sample-tag.is-practice { background: var(--neutral-wash); color: var(--muted); }

.empty { text-align: center; padding: 46px 20px; color: var(--muted); }
.empty .big { font-size: 42px; margin-bottom: 10px; }
.empty .msg { font-size: 14.5px; }

/* Finding a report among a year of them. The field is 16px so iOS does not
   zoom the page when it takes focus, and tall enough to hit with a thumb in
   a glove. `type=search` gets the keyboard's Search key and the clear cross. */
.search-wrap {
  display: flex; align-items: center; gap: 8px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: 12px; padding: 0 12px; margin: 4px 0 6px;
}
.search-wrap svg { flex: none; color: var(--muted); }
.search-box {
  flex: 1; border: none; background: none; outline: none;
  font: inherit; font-size: 16px; color: var(--ink);
  padding: 13px 0; min-width: 0;
}
.search-box::placeholder { color: var(--muted); }
.search-box::-webkit-search-cancel-button { cursor: pointer; }

.hint-text { font-size: 12.5px; color: var(--muted); margin: 6px 2px 0; }
.hint-text a { color: var(--green); }

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

#toast {
  position: fixed;
  left: 50%; transform: translateX(-50%);
  bottom: calc(84px + var(--safe-bottom));
  z-index: 90;
  background: var(--toast-bg); color: var(--on-green);
  padding: 11px 18px; border-radius: 22px;
  font-size: 14px; font-weight: 550;
  max-width: 88vw; text-align: center;
  box-shadow: 0 4px 16px rgba(0,0,0,.28);
}
#toast.err { background: var(--danger); }

/* -------------------------------------------------------------- modal */

#modal {
  position: fixed; inset: 0; z-index: 100;
  background: var(--scrim);
  display: grid; place-items: center;
  padding: 20px;
}
.modal-card {
  background: var(--card); border-radius: 15px;
  width: 100%; max-width: 420px;
  max-height: 82vh; display: flex; flex-direction: column;
  overflow: hidden;
}
.modal-title {
  font-family: var(--serif);
  padding: 17px 18px 4px;
  font-size: 19px; font-weight: 600; letter-spacing: -.012em;
}
.modal-body { padding: 6px 18px 14px; overflow-y: auto; font-size: 14.5px; color: var(--ink-soft); }
.modal-actions { display: flex; gap: 9px; padding: 12px 18px calc(16px + var(--safe-bottom)); border-top: 1px solid var(--line); }
.modal-actions .btn { margin: 0; padding: 12px; font-size: 15px; }

.spin {
  display: inline-block; width: 15px; height: 15px;
  border: 2px solid rgba(255,255,255,.35); border-top-color: var(--on-green);
  border-radius: 50%; animation: spin .7s linear infinite;
  vertical-align: -2px; margin-right: 7px;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* -------------------------------------------------- field help sheet */

/* The info mark beside a field label. Deliberately quiet — present when a
   field has an explainer, out of the way until you want it. A real button,
   so a tap on it never focuses or toggles the field it sits next to. */
.fhelp-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; margin-left: 5px; padding: 0;
  border: 0; border-radius: 50%; background: none;
  color: var(--muted); cursor: pointer; vertical-align: -4px;
  -webkit-tap-highlight-color: transparent;
}
.fhelp-mark:active { color: var(--green); }
.tbl-row-body .fhelp-mark { width: 17px; height: 17px; margin-left: 4px; vertical-align: -3px; }

/* A sheet across the bottom rather than a centred dialog: reading it does not
   cover the form, and a tap anywhere puts it away. Sits under the toast and
   the modal so it never fights either. */
.fhelp-wrap { position: fixed; inset: 0; z-index: 80; }
.fhelp-scrim {
  position: absolute; inset: 0;
  background: var(--scrim); opacity: 0;
  transition: opacity .22s ease;
}
.fhelp-sheet {
  position: absolute; left: 0; right: 0; bottom: 0;
  margin: 0 auto; max-width: 560px;
  background: var(--card);
  border-radius: 16px 16px 0 0;
  box-shadow: 0 -6px 24px rgba(0,0,0,.14);
  padding: 8px 20px calc(18px + var(--safe-bottom));
  transform: translateY(102%);
  transition: transform .24s cubic-bezier(.32,.72,.28,1);
}
.fhelp-wrap.on .fhelp-scrim { opacity: .55; }
.fhelp-wrap.on .fhelp-sheet { transform: translateY(0); }
.fhelp-grip {
  width: 34px; height: 4px; border-radius: 2px;
  background: var(--line-strong);
  margin: 2px auto 12px;
}
.fhelp-title {
  font-size: 11.5px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted);
  margin-bottom: 5px;
}
.fhelp-text { font-size: 14.5px; line-height: 1.45; color: var(--ink-soft); }

/* ------------------------------------------------------------- reaching */
/* Ringing somebody has to be a thumb-sized target sitting on the row, not a
   number to read out and retype into the Phone app. */

.reach {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 44px; padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  color: var(--green);
  text-decoration: none;
  font-size: 14px; font-weight: 600;
  flex: none;
}
.reach:active { background: var(--green-pale); }

/* On a row it is just the handset, at the far right, away from the tap that
   opens the record. */
.lead-row { gap: 10px; }
.lead-row .reach { border: none; padding: 0 4px 0 10px; margin-left: 2px; }
.lead-row .meta, .lead-row .emoji, .lead-row .pill { cursor: pointer; }

.reach-row { display: flex; gap: 8px; margin: 0 0 10px; flex-wrap: wrap; }
.reach-row .reach { flex: 1; justify-content: center; min-width: 0; overflow: hidden; }
.reach-row .reach:only-child { flex: none; }

/* ----------------------------------------------------------- note sheet */
/* Same sheet as the field help, because it does the same thing: comes up
   over the work without taking you away from it. */

.note-wrap { position: fixed; inset: 0; z-index: 82; }
.note-sheet { padding-bottom: calc(14px + var(--safe-bottom)); }
.note-sheet textarea {
  width: 100%; min-height: 96px; resize: vertical;
  margin: 2px 0 10px;
}
.note-kinds { display: flex; gap: 8px; margin-bottom: 10px; }
.note-kinds .chip { flex: 1; text-align: center; }
/* What the note is carrying, said plainly rather than attached silently. */
.note-where {
  font-size: 12px; color: var(--muted);
  line-height: 1.4; margin-bottom: 12px;
}
.note-where b { color: var(--ink-soft); font-weight: 600; }
.note-actions { display: flex; gap: 10px; }
.note-actions .btn { flex: 1; margin: 0; }

/* The section the note is about, outlined behind the sheet so it is obvious
   which part of the screen is being reported on. */
.note-target {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 12px;
}

/* A note in the settings list. */
.note-row { padding: 10px 0; border-top: 1px solid var(--line-soft); }
.note-row:first-child { border-top: none; }
.note-row .nr-head {
  display: flex; align-items: baseline; gap: 8px;
  font-size: 11.5px; color: var(--muted); margin-bottom: 3px;
}
.note-row .nr-head .grow { flex: 1; min-width: 0; }
.note-row .nr-text { font-size: 14px; line-height: 1.45; white-space: pre-wrap; }

@media (min-width: 640px) {
  .tbl-row-body { grid-template-columns: repeat(3, 1fr); }
  .photo-grid { grid-template-columns: repeat(4, 1fr); }
}

/* ------------------------------------------------------ billing panel */

.bill-box { display: flex; flex-direction: column; gap: 2px; margin-bottom: 11px; }
.bill-row {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  font-size: 13.5px; color: var(--muted);
  padding: 4px 0;
  font-variant-numeric: tabular-nums;
}
.bill-row strong { color: var(--ink); font-weight: 620; }
.bill-row.total {
  border-top: 1px solid var(--line);
  margin-top: 4px; padding-top: 8px;
  font-size: 16px; color: var(--ink); font-weight: 650;
}
.bill-row.total strong { font-size: 18px; color: var(--green); font-weight: 700; }

/* Margin is Kakalaki Creek's business, not the client's. Marked plainly so
   nobody mistakes this panel for something the landowner sees. */
.internal-box {
  border: 1px dashed var(--line-strong);
  border-radius: 10px;
  padding: 11px 13px;
  margin: 12px 0;
  background: var(--card-sunk);
}
.internal-tag {
  font-size: 10px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
  color: var(--warn); margin-bottom: 7px;
}

/* ------------------------------------------------- outstanding invoices */

.ar-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; margin-bottom: 12px; }
.ar-amount { font-size: 27px; font-weight: 700; color: var(--green); line-height: 1.05; font-variant-numeric: tabular-nums; }
.ar-overdue { text-align: right; }
.ar-overdue-amt { font-size: 19px; font-weight: 700; color: var(--danger); line-height: 1.1; font-variant-numeric: tabular-nums; }
.ar-label { font-size: 11.5px; color: var(--muted); margin-top: 2px; }

/* Ageing as one bar — the shape of the debt reads faster than the numbers. */
.ar-bar { display: flex; height: 7px; border-radius: 4px; overflow: hidden; gap: 1px; margin-bottom: 8px; }
.ar-seg { min-width: 3px; }
.ar-seg.current { background: var(--ok); }
.ar-seg.d1_30   { background: #8aa63c; }
.ar-seg.d31_60  { background: var(--warn); }
.ar-seg.d61_90  { background: #c2701f; }
.ar-seg.d90plus { background: var(--danger); }

.ar-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 11px; color: var(--muted); margin-bottom: 12px; }
.ar-legend i { display: inline-block; width: 7px; height: 7px; border-radius: 2px; margin-right: 5px; }
.ar-legend .dot-current { background: var(--ok); }
.ar-legend .dot-d1_30   { background: #8aa63c; }
.ar-legend .dot-d31_60  { background: var(--warn); }
.ar-legend .dot-d61_90  { background: #c2701f; }
.ar-legend .dot-d90plus { background: var(--danger); }

.ar-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 9px 0; border-top: 1px solid var(--line-soft); cursor: pointer;
}
.ar-row-main { min-width: 0; }
.ar-client { font-weight: 620; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ar-meta { font-size: 11.5px; color: var(--muted); margin-top: 1px; }
.ar-bal { font-weight: 660; font-size: 15px; font-variant-numeric: tabular-nums; flex: none; }
.ar-bal.late { color: var(--danger); }

.toast-action {
  background: none; border: none;
  color: var(--green-light);
  font: inherit; font-weight: 700;
  margin-left: 14px; padding: 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
#toast.err .toast-action { color: #ffd9d4; }

.pulled-tag {
  font-size: 10px; font-weight: 700; letter-spacing: .04em;
  background: var(--green-pale); color: var(--green);
  padding: 2px 7px; border-radius: 5px; flex: none;
}

/* ---------------------------------------------------- tracts & what's due */

.due-head {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 11px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase;
  padding: 10px 0 6px; border-bottom: 1px solid var(--line-soft); margin-bottom: 2px;
}
.due-head:first-child { padding-top: 0; }
.due-head.overdue { color: var(--danger); }
.due-head.soon    { color: var(--warn); }
.due-head.quarter { color: var(--muted); }

.due-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 0; border-bottom: 1px solid var(--line-soft);
  cursor: pointer;
}
.due-row:last-child { border-bottom: none; }
.due-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.due-dot.overdue { background: var(--danger); }
.due-dot.soon    { background: var(--warn); }
.due-dot.quarter { background: var(--dot-none); }
.due-when {
  font-size: 12px; font-weight: 660; flex: none;
  font-variant-numeric: tabular-nums; color: var(--muted);
}
.due-when.overdue { color: var(--danger); }
.due-when.soon    { color: var(--warn); }

/* A timeline reads more like a property's story than a list does. */
.tl-row {
  display: grid; grid-template-columns: 62px 22px 1fr;
  gap: 10px; align-items: start;
  padding: 11px 0; cursor: pointer;
  border-bottom: 1px solid var(--line-soft);
}
.tl-row:last-child { border-bottom: none; }
.tl-date {
  font-size: 11.5px; color: var(--muted); padding-top: 2px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.tl-mark {
  font-size: 16px; line-height: 1.2; text-align: center;
  position: relative;
}
/* Connect the marks so it reads as one thread. */
.tl-row:not(:last-child) .tl-mark::after {
  content: ''; position: absolute;
  left: 50%; top: 22px; bottom: -13px; width: 1px;
  background: var(--line); transform: translateX(-50%);
}
.tl-title { font-weight: 640; font-size: 14.5px; }
.tl-note { font-size: 12.5px; color: var(--muted); margin-top: 1px; }

/* Rate table in Settings — role, bill, cost, remove. Four columns so the two
   rates line up under their headings and can be read against each other. */
.rate-head,
.rate-row {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr) 32px;
  gap: 8px;
  align-items: center;
}
.rate-head {
  margin: 6px 0 4px;
  font-size: 12px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}
.rate-rows { display: flex; flex-direction: column; gap: 6px; }
.rate-row input { width: 100%; min-width: 0; }
.btn-icon {
  border: 1px solid var(--line);
  background: transparent;
  color: var(--muted);
  border-radius: 8px;
  height: 32px;
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
}
.btn-icon:hover { color: var(--danger, #b4342a); border-color: currentColor; }

/* Hours tab */
.hours-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.hours-figure { font-variant-numeric: tabular-nums; font-size: 26px; font-weight: 600; }
.hours-figure small { display: block; font-size: 12px; font-weight: 400; color: var(--muted); letter-spacing: .04em; text-transform: uppercase; }
.ts-table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.ts-table th, .ts-table td { padding: 7px 8px; text-align: left; border-bottom: 1px solid var(--line); }
.ts-table th { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); font-weight: 600; }
.ts-table td.num, .ts-table th.num { text-align: right; }
.ts-scroll { overflow-x: auto; }
.ts-neg { color: var(--danger, #b4342a); }

/* ===================================================================
   Icons and the polish that goes with them.
   Appended so the intent reads in one place rather than as edits
   scattered through the rules above.
   =================================================================== */

svg { display: block; flex: none; }

/* App bar: a gradient rather than a flat band, and a hairline that stops the
   green from just butting into the page. */
#appbar {
  background: linear-gradient(176deg, var(--bar-top) -35%, var(--bar-mid) 60%, var(--bar-bot) 180%);
  color: var(--bar-ink);
  box-shadow: 0 1px 0 rgba(0,0,0,.18), 0 6px 18px -8px rgba(0,0,0,.32);
  gap: 10px;
}
.icon-btn { color: var(--bar-ink); }
#appbar .brand-mark { color: var(--bar-ink); opacity: .92; }
#barTitle { font-size: 19.5px; letter-spacing: -.02em; }
#barSub { opacity: .78; letter-spacing: .01em; }

.icon-btn {
  background: rgba(255,255,255,.13);
  border: 1px solid rgba(255,255,255,.1);
  width: 36px; height: 36px;
  border-radius: 11px;
  transition: background .14s ease;
}
.icon-btn:active { background: rgba(255,255,255,.3); }
a.icon-btn { font-size: inherit; font-weight: inherit; }

/* Tab bar: the active tab gets the accent and a marker, so which screen you
   are on reads at a glance rather than by comparing two greens. */
#tabbar { box-shadow: var(--lift-bar); border-top: none; }
#tabbar button {
  padding: 9px 0 9px;
  gap: 3px;
  font-size: 10.5px;
  letter-spacing: .015em;
  position: relative;
  transition: color .14s ease;
}
#tabbar button span.ico { font-size: 0; line-height: 0; }
#tabbar button.active { color: var(--green); }
#tabbar button.active::before {
  content: '';
  position: absolute;
  top: 0; left: 50%;
  width: 26px; height: 2.5px;
  transform: translateX(-50%);
  background: var(--sun);
  border-radius: 0 0 3px 3px;
}

/* Activity rows: the icon sits in a tinted well, which gives the list a spine
   to scan down and stops the drawings floating in whitespace. */
.card { border-radius: var(--radius); box-shadow: var(--lift); }
.activity-card { padding: 14px; gap: 13px; }
.activity-card .emoji {
  width: 42px; height: 42px;
  border-radius: 12px;
  background: var(--green-pale);
  color: var(--green);
  display: grid; place-items: center;
  font-size: 0;
  border: 1px solid transparent;
  transition: background .14s ease, color .14s ease;
}
.activity-card:active .emoji { background: var(--green); color: var(--on-green); }
.activity-card .name { font-size: 15.5px; letter-spacing: -.005em; }
.activity-card .chev { color: var(--line-strong); font-size: 0; }

/* Empty states: the drawing is quiet, the sentence does the work. */
.empty { padding: 54px 22px; }
.empty .big {
  font-size: 0;
  color: var(--line-strong);
  display: grid; place-items: center;
  margin: 0 auto 14px;
  width: 74px; height: 74px;
  border-radius: 50%;
  background: var(--neutral-wash);
}
.empty .msg { font-size: 14.5px; max-width: 30ch; margin: 0 auto; line-height: 1.5; }

/* Login. */
.login-mark { color: var(--green); display: grid; place-items: center; margin-bottom: 12px; }
.login-mark svg { margin: 0 auto; }

.section-label { letter-spacing: .085em; font-size: 11px; }

/* The accent, spent where it belongs: money owed, things overdue, the active
   tab. Everything else stays green or grey. */
.due-head.overdue span, .ts-neg { color: var(--danger); }
.hours-figure { letter-spacing: -.02em; }

/* Figures pair up on a phone. One number per row wastes the screen and makes
   two related totals read as two unrelated facts. */
.hours-grid { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
.hours-figure { font-size: 23px; }
.hours-figure small { margin-top: 3px; letter-spacing: .06em; }

/* The well tint carries meaning rather than decoration: field work is green,
   the two documents that move money are the accent. Scanning the list for
   "the invoice one" then costs a glance rather than a read. */
.activity-card .emoji.is-money {
  background: var(--sun-wash);
  color: var(--sun-strong);
}
.activity-card:active .emoji.is-money { background: var(--sun-strong); color: #fff; }

/* The mark, so the bar is a masthead rather than a label. */
#appbar .brand-mark { color: rgba(255,255,255,.9); flex: none; margin-right: 2px; }
#appbar .brand-mark svg { width: 26px; height: 26px; }
#barTitle { line-height: 1.15; }

/* A button that leads with an icon: the drawing and the words share a
   baseline and the button's colour, rather than the icon being a glyph the
   text happens to start with. */
.btn svg, .btn-quiet svg { margin-right: 7px; }
.btn, .btn-quiet { display: inline-flex; align-items: center; justify-content: center; }
.row-lead { display: flex; align-items: center; gap: 7px; }

/* Staff rows carry a name and a role, so two columns rather than the rate
   table's three. */
.rate-head.staff-row, .rate-row.staff-row {
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) 32px;
}
/* A price needs four things and a phone is not wide enough for four. The
   service takes its own line and the rest sit under it. */
.rate-row.price-row {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, .8fr) 32px;
  row-gap: 6px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--line-soft);
}
.rate-row.price-row .svc { grid-column: 1 / -1; }
.rate-row select { width: 100%; min-width: 0; }

/* Status pills. The tone says what state something is in without the reader
   having to parse the word: green is settled, amber wants attention, grey is
   closed and needs nothing. */
.pill {
  flex: none;
  align-self: center;
  font-size: 11px;
  font-weight: 650;
  letter-spacing: .01em;
  padding: 4px 9px;
  border-radius: 999px;
  white-space: nowrap;
  border: 1px solid transparent;
}
.pill.ok     { background: var(--ok-wash);      color: var(--ok-deep);  border-color: var(--ok-line); }
.pill.warn   { background: var(--warn-wash);    color: var(--warn);     border-color: var(--warn-line); }
.pill.open   { background: var(--sun-wash);     color: var(--sun-strong); border-color: var(--sun-line); }
.pill.muted  { background: var(--neutral-wash); color: var(--muted);    border-color: var(--line); }

/* ===================================================================
   Form layout.

   Every field used to be a full-width block, so a two-digit stand age
   got the same 380px as a street address and a fourteen-field section
   ran to eleven hundred pixels of scroll. The body is a two-column grid
   now: anything short sits half-width beside its neighbour, everything
   else spans both. Which is which is declared in the template, because
   only the template knows whether a text field holds a PIN or a legal
   description.
   =================================================================== */

.sec.open .sec-body {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 11px 10px;
  align-items: start;
}
/* Full width is the safe default: a field nobody has classified reads
   fine wide, and a long value squeezed into half a row does not. */
.sec-body > * { grid-column: 1 / -1; min-width: 0; }
.sec-body > .field { margin-bottom: 0; }
.sec-body > .field.half { grid-column: span 1; }

/* A sub-heading inside a long section, so fourteen fields read as three
   groups of related things rather than one undifferentiated column. */
.field-group {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 8px;
  margin: 5px 0 -2px;
  font-size: 11px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted);
}
.field-group::after {
  content: ''; flex: 1; height: 1px; background: var(--line-soft);
}
.field-group:first-child { margin-top: 0; }

/* Units belong in the box, not bolted onto the label. "Acres" as a
   suffix leaves the label free to say what the number is *of*. */
.field.has-unit { position: relative; }
.field.has-unit input { padding-right: 44px; }
.field.has-unit .unit {
  position: absolute;
  right: 11px;
  bottom: 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  pointer-events: none;
}

.field > label { font-size: 12px; letter-spacing: .005em; margin-bottom: 4px; }
input[type=text], input[type=number], input[type=date], input[type=time],
input[type=tel], input[type=email], input[type=password], select, textarea {
  padding: 10px 11px;
}
textarea { min-height: 72px; }
.sec-body { padding: 0 13px 14px; }

/* A half-width field with no partner takes the whole row rather than sitting
   beside a gap. Which fields those are is worked out in the renderer, because
   it means counting the length of each run of short fields and CSS cannot
   count. The templates only say which fields are *short*; they do not also have
   to be hand-ordered so the short ones happen to fall in twos. */
.sec-body > .field.half.solo { grid-column: 1 / -1; }

/* Add and copy sit side by side under a table. Copy is the quieter of the two
   because it only makes sense once there is a row to copy. */
.row-actions { display: flex; gap: 8px; }
.row-actions .btn-add { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 7px; }
.row-actions .btn-copy { flex: 0 1 auto; color: var(--muted); }
.row-actions .btn-copy:active { color: var(--green); }

/* The section caret is an icon now, so it rotates as a box rather than as a
   character sitting on a baseline. */
.sec-head .caret { width: 13px; height: 13px; display: grid; place-items: center; }

/* "This section has something in it" — drawn, so it matches every other mark
   in the app rather than being whichever tick the font happens to ship. */
.sec-head .badge.tick {
  width: 20px; height: 20px; padding: 0;
  display: grid; place-items: center;
}
.sec-head .badge.tick::before {
  content: '';
  width: 9px; height: 5px;
  border-left: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg) translate(1px, -1px);
}

/* Something that is not an error but will quietly cost you money if ignored. */
.warn-note {
  grid-column: 1 / -1;
  margin: 2px 0 4px;
  padding: 9px 11px;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--warn);
  background: var(--warn-wash);
  border: 1px solid var(--warn-line);
  border-radius: var(--radius-sm);
}

/* ===================================================================
   Stages, and tags that carry rank.

   Fifteen collapsed sections all looked the same and all shouted at
   the same volume, so nothing told you where to start. Sections group
   under four stage headings, and the tag on each says which of three
   states it is in — needs you, done, or nothing required — loudly
   enough to scan without reading.
   =================================================================== */

.phase-head {
  display: flex; align-items: center; gap: 9px;
  margin: 20px 3px 8px;
}
.phase-head:first-child { margin-top: 2px; }
.phase-name {
  font-size: 11.5px; font-weight: 750; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-soft);
}
.phase-count {
  font-size: 10.5px; font-weight: 700;
  min-width: 17px; height: 17px; padding: 0 5px;
  display: grid; place-items: center;
  border-radius: 20px;
  color: var(--muted); background: var(--neutral-wash);
}
.phase-head::after { content: ''; flex: 1; height: 1px; background: var(--line); }

/* Outstanding work is the accent, filled — not a wash of red that reads as an
   error. Nothing is wrong; it just is not done. Filled beats tinted because on
   a dark screen in sunlight a tint is invisible. */
.sec-head .badge.req {
  background: var(--sun);
  color: #fff;
  border: none;
  box-shadow: 0 1px 2px rgba(0,0,0,.18);
}
@media (prefers-color-scheme: dark) {
  .sec-head .badge.req { color: #14100a; }
}

/* Done is the one green thing on the screen, so a finished section reads at a
   glance against everything still outstanding. */
.sec-head .badge.tick {
  background: var(--ok);
  color: #fff;
  border-radius: 50%;
}
@media (prefers-color-scheme: dark) {
  .sec-head .badge.tick { color: #08130d; }
}
/* A plain count (rows entered, photos taken) stays quiet — it is information,
   not a demand. */
.sec-head .badge:not(.req):not(.tick) {
  background: var(--neutral-wash); color: var(--muted);
}

/* A result drawn under the section it is the result of, set off by a rule so
   it reads as a conclusion rather than as more input. */
.attached-panel {
  grid-column: 1 / -1;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.attached-title {
  font-size: 11px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted);
  margin-bottom: 8px;
}

/* A folded-in section's body sits inside one that already has padding. */
.attached-body { padding: 0; }

/* Open and closed should not look alike. The one you are working in is the
   only lit thing on the screen; the rest sit back and wait. */
.sec {
  background: var(--card-sunk);
  border-color: var(--line-soft);
  box-shadow: none;
  transition: background .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.sec .sec-head .t { color: var(--ink-soft); font-weight: 620; }

.sec.open {
  background: var(--card);
  border-color: var(--green);
  box-shadow: var(--lift-2);
}
.sec.open .sec-head {
  background: var(--green-pale);
  border-radius: 13px 13px 0 0;
  border-bottom: 1px solid var(--line-soft);
}
.sec.open .sec-head .t { color: var(--green); font-weight: 700; }
.sec.open .sec-head .caret { color: var(--green); }
.sec.open .sec-body { padding-top: 13px; }

/* ===================================================================
   Calculator.

   Acres times a rate, a tank mix, a check that the loads add up. Big
   targets because it gets used outdoors with cold hands, and the answer
   sits above the sum the whole time rather than waiting for equals —
   most of this arithmetic is one operation.
   =================================================================== */

.calc-wrap { position: fixed; inset: 0; z-index: 70; }
.calc-scrim {
  position: absolute; inset: 0;
  background: var(--scrim);
  opacity: 0; transition: opacity .2s ease;
}
.calc-wrap.on .calc-scrim { opacity: 1; }
.calc-sheet {
  position: absolute; left: 0; right: 0; bottom: 0;
  background: var(--card);
  border-radius: 18px 18px 0 0;
  border-top: 1px solid var(--line);
  box-shadow: 0 -12px 40px rgba(0,0,0,.28);
  padding: 8px 12px calc(12px + var(--safe-bottom));
  transform: translateY(102%);
  transition: transform .24s cubic-bezier(.32,.72,0,1);
  max-width: 480px; margin: 0 auto;
}
.calc-wrap.on .calc-sheet { transform: translateY(0); }
.calc-grip {
  width: 36px; height: 4px; border-radius: 3px;
  background: var(--line-strong); margin: 2px auto 8px;
}
.calc-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.calc-title {
  flex: 1;
  font-size: 11.5px; font-weight: 750; letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted);
}

/* The tape. Halfway through pricing a job you want the number from two sums
   ago, and re-typing it is where a digit gets dropped — so they are tappable. */
.calc-tape { display: flex; flex-direction: column; gap: 2px; margin-bottom: 6px; }
.calc-tape-row {
  display: flex; align-items: baseline; gap: 10px;
  border: none; background: none; padding: 3px 4px;
  font: inherit; text-align: left; cursor: pointer;
  border-radius: 7px;
}
.calc-tape-row:active { background: var(--green-pale); }
.calc-tape-row .te { flex: 1; font-size: 12px; color: var(--muted); }
.calc-tape-row .tv { font-size: 13px; font-weight: 650; color: var(--ink-soft); font-variant-numeric: tabular-nums; }

.calc-display {
  background: var(--card-sunk);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 12px 14px;
  margin-bottom: 10px;
  min-height: 68px;
  display: flex; flex-direction: column; justify-content: center;
}
.calc-answer {
  font-size: 30px; font-weight: 680; letter-spacing: -.02em;
  color: var(--green); font-variant-numeric: tabular-nums;
  min-height: 34px; word-break: break-all;
}
.calc-expr {
  font-size: 14px; color: var(--muted);
  font-variant-numeric: tabular-nums; word-break: break-all;
}

.calc-pad { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; }
.calc-key {
  height: 52px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink);
  border-radius: 12px;
  font-size: 20px; font-weight: 600; font-family: inherit;
  cursor: pointer;
  display: grid; place-items: center;
  -webkit-tap-highlight-color: transparent;
}
.calc-key:active { background: var(--green-pale); border-color: var(--green); }
.calc-key.op { color: var(--green); font-weight: 700; }
.calc-key.fn { color: var(--muted); font-size: 17px; }
.calc-key.eq {
  background: var(--green); color: var(--on-green); border-color: var(--green);
}
.calc-key.eq:active { background: var(--green-light); }
.calc-key.wide { width: 52px; height: 34px; }

/* What is known about a person, as opposed to what was said on one call.
   Pre-wrap because it accumulates a line at a time and the lines are the
   structure. */
.know-box {
  white-space: pre-wrap;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ink-soft);
  background: var(--neutral-wash);
  border-radius: 10px;
  padding: 10px 12px;
  max-height: 40vh;
  overflow-y: auto;
}

/* ---------------------------------------------------------------- clock */
/* Tapping the time is how an hour gets written down. A coin-sized readout in
   the middle of the Hours tab, because the thing that stops time being
   recorded is having to go and find where to record it. */

.clock-wrap {
  display: flex; flex-direction: column; align-items: center;
  gap: 9px; padding: 20px 0 22px;
}
.clock-btn {
  width: 104px; height: 104px; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 0;
  border: 1px solid var(--line-strong);
  background: var(--card);
  color: var(--ink);
  font-family: 'Nebula Sans', ui-sans-serif, system-ui, sans-serif;
  /* Figures the same width, so the minute changing does not shuffle the row. */
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  box-shadow: 0 1px 4px rgba(0,0,0,.10);
  transition: transform .1s ease, background .15s ease;
}
.clock-btn:active { background: var(--green-pale); transform: scale(.97); }
.clock-time { font-size: 26px; font-weight: 600; line-height: 1; letter-spacing: -.01em; }
.clock-mer  { font-size: 9.5px; font-weight: 600; letter-spacing: .18em; color: var(--muted); line-height: 1; margin-top: 3px; }
.clock-date { font-size: 8.5px; font-weight: 500; letter-spacing: .12em; color: var(--muted); margin-top: 5px; }
.clock-cap  { font-size: 12.5px; color: var(--muted); }
