/* InteliRain Golf Control — Hole 18 */

:root {
  --bg:            #080b0d;
  --bg-1:          #0d1215;
  --surface:       #121a1e;
  --surface-2:     #18242a;
  --surface-3:     #1f3038;
  --line:          #23343c;
  --line-soft:     #1a262c;

  --text:          #e8f1f3;
  --text-2:        #9db1b9;
  /* muted text still has to be readable: #8aa2ab clears WCAG AA (4.5:1) on
     every surface token, including the lightest (--surface-3, 5.09:1) */
  --text-3:        #8aa2ab;

  --accent:        #00d4a0;
  --accent-dim:    #0b7c62;
  --accent-glow:   rgba(0, 212, 160, 0.16);
  --accent-2:      #38bdf8;

  --warn:          #f5a524;
  /* #f66872 clears 4.5:1 on every surface, including the lightest table row */
  --danger:        #f66872;
  /* filled badges carry white text, which needs a deeper red than the
     text-on-dark --danger to reach 4.5:1 */
  --danger-solid:  #cf2431;
  --ok:            #35d07f;

  --fairway:       #7fe57f;
  --rough:         #d9b25a;
  --green-zone:    #57d4ff;
  --tee:           #c58bff;
  --collar:        #ff5c8a;

  --radius:        10px;
  --radius-sm:     7px;
  --shadow:        0 18px 40px rgba(0, 0, 0, 0.55);
  --ease:          cubic-bezier(0.22, 0.9, 0.3, 1);

  --header-h:      68px;
  --rail-w:        344px;
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  background: var(--bg);
  color: var(--text);
  font: 15.5px/1.5 "Inter", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto,
        Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}

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

.num { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }

/* ─────────────────────────── app shell ─────────────────────────── */

.app {
  display: grid;
  grid-template-rows: var(--header-h) 1fr;
  /* minmax(0, 1fr), not the implicit `auto`: an auto column sizes to
     max-content, so a viewport narrower than the header's natural width let
     every child overflow the screen instead of the header adapting. Above
     1425px the two are identical, so the desktop layout is untouched. */
  grid-template-columns: minmax(0, 1fr);
  height: 100%;
}

.header {
  display: flex;
  align-items: center;
  gap: 22px;
  padding: 0 20px;
  background: linear-gradient(180deg, #101a1e 0%, #0b1215 100%);
  border-bottom: 1px solid var(--line);
  position: relative;
  z-index: 700;
}

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

/* the badge is already round; the radius just guards against any letterboxing */
.brand__mark {
  width: 38px; height: 38px; flex: none;
  border-radius: 50%; object-fit: cover; display: block;
  background: #fff;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.14), 0 6px 18px rgba(0, 0, 0, 0.4);
}

.brand__name {
  font-size: 16.5px; font-weight: 650; letter-spacing: 0.2px; white-space: nowrap;
}
.brand__name em {
  font-style: normal; color: var(--accent);
}
.brand__sub {
  font-size: 12.5px; color: var(--text-3); letter-spacing: 0.5px;
  text-transform: uppercase; margin-top: 1px;
  /* carries the course name when signed in; never widens the brand block */
  max-width: 210px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.header__ctx {
  display: flex; align-items: center; gap: 8px;
  padding-left: 20px; border-left: 1px solid var(--line);
}

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border-radius: 100px;
  background: var(--surface-2); border: 1px solid var(--line);
  font-size: 13.5px; color: var(--text-2); white-space: nowrap;
}
.chip strong { color: var(--text); font-weight: 600; }
/* these carry their own display rule, which would otherwise win over [hidden] */
.chip[hidden], .account[hidden], .account__menu[hidden], .account__item[hidden] { display: none !important; }
/* between 1200 and 1500px the signed-in header is one control too wide: the
   name lives in the menu, the button keeps the avatar */
/* Signed in, the account button makes the single-row header one control too
   wide until about 1600px: the two-row layout (tabs beneath) runs on to
   1500px, and the name stays in the menu until there is room for it. */
@media (min-width: 1425px) and (max-width: 1500px) {
  body.is-remote { --header-h: auto; }
  body.is-remote .header { flex-wrap: wrap; row-gap: 6px; padding: 8px 18px; }
  body.is-remote .header__spacer { display: none; }
  body.is-remote .header__ctx { order: 2; }
  body.is-remote .setpoint { order: 3; margin-left: auto; }
  body.is-remote .bell { order: 4; }
  body.is-remote .account { order: 5; }
  body.is-remote .tabs {
    order: 6; flex: 1 1 100%; min-width: 0;
    overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
  }
  body.is-remote .tabs::-webkit-scrollbar { display: none; }
  body.is-remote .tabs__ink { display: none; }
}
@media (min-width: 901px) and (max-width: 1600px) {
  body.is-remote .header { column-gap: 14px; }
  body.is-remote .account__btn { padding-right: 6px; }
  body.is-remote .account__name { display: none; }
}
.chip--accent { border-color: var(--accent-dim); background: var(--accent-glow); color: var(--accent); }

.header__spacer { flex: 1; }

.setpoint {
  display: flex; align-items: center; gap: 9px;
  padding: 5px 8px 5px 12px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 100px;
}
.setpoint label {
  font-size: 12.5px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--text-3);
}
.setpoint input {
  width: 66px; padding: 5px 9px; text-align: right;
  background: var(--bg); border: 1px solid var(--line); border-radius: 6px;
  font-variant-numeric: tabular-nums; font-weight: 600;
  transition: border-color 0.18s var(--ease), box-shadow 0.18s var(--ease);
}
.setpoint input:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
}
.setpoint span { font-size: 13.5px; color: var(--text-3); }

/* the hole picker lives inside a header chip: the select is styled away so
   the chip reads as "Hole 18" with a caret, and as plain text when there is
   only one hole to pick (the local build) */
.chip--select { cursor: pointer; }
.chip__select {
  appearance: none; -webkit-appearance: none;
  border: 0; color: var(--text); font: inherit; font-weight: 600;
  /* a select sizes itself to its widest option, and the greyed-out ones
     carry a reason — so the box is given the width of "18" plus the caret,
     and the dropdown list still shows the full text */
  width: 44px; padding: 0 13px 0 1px; cursor: pointer;
  /* the native arrow is a different width on every platform; draw our own */
  background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'%3E%3Cpath d='M2 3.5 5 6.5 8 3.5' fill='none' stroke='%239db1b9' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right center / 10px 10px;
}
.chip__select:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.chip__select:disabled { background-image: none; width: 24px; padding-right: 1px; opacity: 1; cursor: default; }
.chip__select option { background: var(--surface-2); color: var(--text); }
.chip__select option:disabled { color: var(--text-3); }

/* ─── sync state: the one honest indicator of "did my change reach the
   server" — spins while a write is out, ticks when it lands, warns when
   it did not. Only the signed-in build shows it. ─── */
.sync {
  position: absolute; right: 0; top: calc(100% + 7px); z-index: 790;
  display: inline-flex; align-items: center; gap: 7px;
  padding: 4px 10px; border-radius: 100px; font-size: 12.5px;
  color: var(--text-3); background: var(--surface); border: 1px solid var(--line);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
  opacity: 0; transform: translateY(-3px);
  transition: opacity 0.22s var(--ease), transform 0.22s var(--ease), color 0.2s, border-color 0.2s;
  pointer-events: none; white-space: nowrap;
}
.sync.is-saving, .sync.is-saved, .sync.is-failed { opacity: 1; transform: none; }
.sync__dot { width: 9px; height: 9px; border-radius: 50%; background: var(--text-3); flex: none; }
.sync.is-saving .sync__dot {
  background: transparent; border: 2px solid var(--surface-3); border-top-color: var(--accent);
  width: 11px; height: 11px; animation: spin 0.7s linear infinite;
}
.sync.is-saved { color: var(--ok); } .sync.is-saved .sync__dot { background: var(--ok); }
.sync.is-failed { color: var(--danger); border-color: rgba(246, 104, 114, 0.4); }
.sync.is-failed .sync__dot { background: var(--danger); }

/* ─────────────────────────── account ─────────────────────────── */

.account { position: relative; }
.account__btn {
  display: flex; align-items: center; gap: 8px; max-width: 150px;
  padding: 4px 11px 4px 5px; border-radius: 100px;
  background: var(--surface-2); border: 1px solid var(--line);
  color: var(--text-2); font-size: 13.5px;
  transition: background 0.18s var(--ease), border-color 0.18s var(--ease);
}
.account__btn:hover, .account__btn[aria-expanded="true"] { background: var(--surface-3); border-color: var(--text-3); }
.account__avatar {
  width: 26px; height: 26px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  background: var(--accent-glow); color: var(--accent);
}
.account__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account__menu {
  position: absolute; right: 0; top: calc(100% + 8px); min-width: 230px; z-index: 800;
  background: var(--surface); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow); padding: 6px; animation: pop 0.2s var(--ease);
}
.account__who {
  display: flex; flex-direction: column; gap: 3px;
  padding: 8px 10px 10px; margin-bottom: 4px; border-bottom: 1px solid var(--line-soft);
}
.account__course { font-size: 14px; font-weight: 600; }
.account__role { font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--accent); }
.account__item {
  display: block; width: 100%; text-align: left; padding: 8px 10px;
  border: 0; background: none; color: var(--text); border-radius: 8px;
  font-size: 14px; cursor: pointer;
}
.account__item:hover { background: var(--surface-2); }

/* ─────────────────────────── holes panel ─────────────────────────── */

.holes-list { display: flex; flex-direction: column; gap: 6px; }
.holes-row {
  display: flex; align-items: center; gap: 12px; padding: 8px 10px;
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--surface-2);
}
.holes-row.is-empty { opacity: 0.55; }
.holes-row__num {
  width: 30px; text-align: center; font-weight: 700; font-size: 15px;
  font-variant-numeric: tabular-nums;
}
.holes-row__meta { flex: 1; min-width: 0; }
.holes-row__name { font-size: 14px; font-weight: 600; }
.holes-row__status { font-size: 12.5px; color: var(--text-3); }
.holes-row .switch:disabled { opacity: 0.35; cursor: not-allowed; }

/* ── staff overview: every hole of every course ── */
.modal.modal--wide { width: min(760px, 100%); }
.overview { display: flex; flex-direction: column; gap: 14px; }
.overview__loading {
  display: flex; align-items: center; gap: 12px; padding: 18px 4px;
  color: var(--text-3); font-size: 14px;
}
.overview__loading .boot__ring { width: 22px; height: 22px; border-width: 2px; margin: 0; }
.overview__error { color: var(--danger); font-size: 14px; padding: 12px 4px; }
.overview-course {
  border: 1px solid var(--line-soft); border-radius: var(--radius);
  background: var(--surface-2); padding: 12px;
  animation: overview-in 0.28s var(--ease) both;
}
.overview-course.is-current { border-color: var(--accent-dim); box-shadow: 0 0 0 1px var(--accent-glow) inset; }
.overview-course__head {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: 4px 12px; margin-bottom: 10px;
}
.overview-course__name { font-weight: 700; font-size: 15px; min-width: 0; overflow-wrap: anywhere; }
.overview-course__meta { font-size: 12.5px; color: var(--text-3); }
.overview-course__here { color: var(--accent); font-weight: 600; }
/* front nine over back nine */
.overview-grid { display: grid; grid-template-columns: repeat(9, minmax(0, 1fr)); gap: 6px; }
.overview-hole {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  min-height: 50px; padding: 5px 2px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--surface-3); color: var(--text);
  font: inherit; cursor: pointer; min-width: 0;
  transition: transform 0.12s var(--ease), border-color 0.12s var(--ease), background 0.12s var(--ease);
}
.overview-hole__n { font-weight: 700; font-size: 15px; font-variant-numeric: tabular-nums; line-height: 1.1; }
.overview-hole__sub {
  font-size: 10.5px; color: var(--text-3); max-width: 100%;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.overview-hole.is-open { border-color: var(--accent-dim); background: linear-gradient(180deg, rgba(0, 212, 160, 0.14), rgba(0, 212, 160, 0.04)); }
.overview-hole.is-open .overview-hole__sub { color: var(--accent); }
.overview-hole.is-open:hover { transform: translateY(-1px); border-color: var(--accent); }
.overview-hole.is-open:active { transform: translateY(1px) scale(0.98); }
.overview-hole.is-open:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.overview-hole.is-current { box-shadow: 0 0 0 2px var(--accent) inset; }
.overview-hole.is-off { opacity: 0.7; cursor: not-allowed; }
.overview-hole.is-off .overview-hole__sub { color: var(--warn); }
.overview-hole.is-empty { opacity: 0.4; cursor: not-allowed; background: transparent; }
@keyframes overview-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (max-width: 560px) {
  .overview-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
@media (prefers-reduced-motion: reduce) {
  .overview-course { animation: none; }
  .overview-hole { transition: none; }
}

.hist-skel { display: flex; flex-direction: column; gap: 10px; }
.hist-skel__card {
  height: 96px; border-radius: var(--radius-sm); border: 1px solid var(--line-soft);
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%);
  background-size: 200% 100%; animation: shimmer 1.3s linear infinite;
}
.hist-skel__msg { font-size: 13px; color: var(--text-3); text-align: center; padding: 6px 0 2px; }
.hist-card { transition: transform 0.16s var(--ease), box-shadow 0.18s var(--ease), border-color 0.16s var(--ease); }
.hist-card:hover { transform: translateY(-2px); box-shadow: 0 10px 22px rgba(0, 0, 0, 0.35); }

/* history rail with nothing (yet) to show */
.hist-empty {
  padding: 22px 14px; text-align: center; font-size: 14px; line-height: 1.5;
  color: var(--text-3); border: 1px dashed var(--line); border-radius: var(--radius-sm);
}

/* ─────────────────────────── read-only accounts ─────────────────────────── */

body.is-viewer .edit-only,
body.is-viewer #btnDrawFence,
body.is-viewer #btnSubmitTable,
body.is-viewer #btnResetTable,
body.is-viewer #rtSave,
body.is-viewer #rtDiscard,
body.is-viewer [data-adjust] { display: none !important; }
body.is-viewer #targetMoisture { pointer-events: none; opacity: 0.7; }
body.is-viewer .rt-input { opacity: 0.6; }

/* ─────────────────────────── sign-in ─────────────────────────── */

.boot.is-login { overflow: hidden; }
.boot.is-login::before, .boot.is-login::after {
  content: ""; position: absolute; border-radius: 50%; filter: blur(70px); pointer-events: none;
  animation: glow-drift 14s ease-in-out infinite;
}
.boot.is-login::before { width: 55vmax; height: 55vmax; left: -18vmax; top: -22vmax; background: rgba(0, 212, 160, 0.13); }
.boot.is-login::after  { width: 50vmax; height: 50vmax; right: -16vmax; bottom: -20vmax; background: rgba(56, 189, 248, 0.10); animation-delay: -7s; }
.boot.is-login .boot__inner { position: relative; }
.login {
  width: min(380px, calc(100vw - 32px));
  display: flex; flex-direction: column; gap: 13px; text-align: left;
  padding: 28px 26px 22px;
  background: linear-gradient(180deg, rgba(24, 36, 42, 0.96) 0%, rgba(18, 26, 30, 0.98) 100%);
  border: 1px solid rgba(255, 255, 255, 0.09); border-radius: 18px;
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  animation: pop 0.32s var(--ease);
}
.login.is-error { animation: shake 0.45s var(--ease); }
.login .field input { padding: 11px 12px; font-size: 15px; border-radius: 10px; }
.login .field input:focus { box-shadow: 0 0 0 4px var(--accent-glow); }
.login__pw { position: relative; }
.login__pw input { display: block; width: 100%; padding-right: 44px !important; }
.login__eye {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 32px; height: 32px; border-radius: 8px; border: 0; background: none;
  color: var(--text-3); display: grid; place-items: center; cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.login__eye:hover { color: var(--text); background: var(--surface-3); }
.login__eye svg { width: 17px; height: 17px; }
/* the phone layout stretches .field for horizontal form rows; the sign-in
   card is a column and its fields must keep their natural height */
.login .field { flex: none; }
.login__mark {
  width: 54px; height: 54px; align-self: center; border-radius: 50%;
  background: #fff; object-fit: cover;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.14), 0 6px 18px rgba(0, 0, 0, 0.4);
}
.login__brand { text-align: center; font-size: 18px; font-weight: 650; }
.login__brand em { font-style: normal; color: var(--accent); }
.login__sub { text-align: center; font-size: 13.5px; color: var(--text-3); margin-bottom: 6px; }
.login__error {
  font-size: 13.5px; color: var(--danger); padding: 8px 10px; border-radius: 8px;
  background: rgba(244, 82, 92, 0.1); border: 1px solid rgba(244, 82, 92, 0.3);
}
.login__error.is-info { color: var(--accent); background: var(--accent-glow); border-color: var(--accent-dim); }
.login__submit { margin-top: 6px; padding: 12px; font-size: 15px; border-radius: 10px; }
.login__hint { font-size: 12.5px; color: var(--text-3); margin-top: -6px; }
.login__link {
  align-self: center; padding: 0; border: 0; background: none; cursor: pointer;
  color: var(--text-2); font-size: 13px; text-decoration: underline;
}
.login__link:hover { color: var(--text); }
.login__foot { text-align: center; font-size: 12px; color: var(--text-3); margin-top: 4px; }
.boot__actions { display: flex; gap: 8px; justify-content: center; margin-top: 16px; }

/* ─────────────────────────── tabs ─────────────────────────── */

.tabs {
  display: flex; align-items: center; gap: 2px;
  position: relative;
}

.tab {
  position: relative;
  padding: 9px 15px;
  background: none; border: 0; border-radius: var(--radius-sm);
  color: var(--text-2); font-size: 14.5px; font-weight: 500;
  display: inline-flex; align-items: center; gap: 7px;
  transition: color 0.18s var(--ease), background 0.18s var(--ease);
}
.tab:hover { color: var(--text); background: var(--surface-2); }
.tab.is-active { color: var(--text); }
.tab__badge {
  min-width: 21px; height: 21px; padding: 0 6px;
  display: grid; place-items: center;
  border-radius: 100px; background: var(--danger-solid); color: #fff;
  font-size: 12px; line-height: 1; font-weight: 700; font-variant-numeric: tabular-nums;
}
.tab__badge:empty, .tab__badge[data-count="0"] { display: none; }

.tabs__ink {
  position: absolute; bottom: -1px; height: 2px;
  background: var(--accent); border-radius: 2px;
  box-shadow: 0 0 10px var(--accent);
  transition: transform 0.32s var(--ease), width 0.32s var(--ease);
  pointer-events: none;
}

/* ─────────────────────────── panels ─────────────────────────── */

.views { position: relative; overflow: hidden; }

.view {
  position: absolute; inset: 0;
  opacity: 0; visibility: hidden;
  transform: translateY(6px);
  transition: opacity 0.26s var(--ease), transform 0.26s var(--ease),
              visibility 0s linear 0.26s;
}
.view.is-active {
  opacity: 1; visibility: visible; transform: none;
  transition: opacity 0.26s var(--ease), transform 0.26s var(--ease),
              visibility 0s;
}

/* ─── map view ─── */

.mapview { display: grid; grid-template-columns: var(--rail-w) 1fr; height: 100%; }

.rail {
  background: var(--bg-1);
  border-right: 1px solid var(--line);
  overflow-y: auto;
  padding: 14px;
  display: flex; flex-direction: column; gap: 12px;
}

.card {
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  overflow: hidden;
  flex: none;              /* the rail scrolls; cards must not be squashed */
}
.card__head {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 10px 13px;
  border-bottom: 1px solid var(--line-soft);
  font-size: 12.5px; font-weight: 650; letter-spacing: 0.7px;
  text-transform: uppercase; color: var(--text-3);
}
.card__body { padding: 12px 13px; display: flex; flex-direction: column; gap: 11px; }

.card { animation: rise 0.3s var(--ease) both; }
.stat-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.stat__value { transition: color 0.3s var(--ease); }
.stat.is-changed .stat__value { animation: pop 0.3s var(--ease); }
/* an odd last tile spans the row rather than leaving a hole beside it */
.stat-grid > .stat:last-child:nth-child(odd) { grid-column: 1 / -1; }
.stat {
  padding: 9px 11px; border-radius: var(--radius-sm);
  background: var(--surface-2); border: 1px solid var(--line-soft);
}
.stat__label {
  font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.6px;
  color: var(--text-3); margin-bottom: 3px;
}
.stat__value {
  font-size: 21px; font-weight: 650; font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.stat__value small { font-size: 12.5px; font-weight: 500; color: var(--text-3); margin-left: 2px; }
.stat--warn .stat__value { color: var(--warn); }
.stat--accent .stat__value { color: var(--accent); }

/* layer rows */

.layer {
  display: flex; flex-direction: column; gap: 8px;
  padding: 9px 10px; border-radius: var(--radius-sm);
  background: var(--surface-2); border: 1px solid transparent;
  transition: border-color 0.18s var(--ease), background 0.18s var(--ease);
}
.layer.is-on { border-color: var(--accent-dim); background: #14232a; }
.layer__top { display: flex; align-items: center; gap: 9px; }
.layer__name { flex: 1; font-size: 14.5px; font-weight: 500; }
.layer__swatch {
  width: 26px; height: 12px; border-radius: 3px; border: 1px solid rgba(255,255,255,0.14);
}
/* the controls slide open with the switch, and the swatch becomes a ring
   while the surface is being painted (a 1024-cell raster takes a moment) */
.layer { transition: border-color 0.2s var(--ease), background 0.2s var(--ease); }
.layer__top { position: relative; }
.layer.is-busy .layer__swatch { visibility: hidden; }
.layer.is-busy .layer__top::after {
  content: ""; position: absolute; right: 2px; top: 50%; margin-top: -8px;
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid var(--surface-3); border-top-color: var(--accent);
  animation: spin 0.7s linear infinite;
}
.layer__controls {
  display: none; flex-direction: column; gap: 7px;
  padding-top: 3px; border-top: 1px solid var(--line-soft);
  animation: slide-down 0.24s var(--ease);
}
.layer.is-on .layer__controls { display: flex; animation: slide-down 0.22s var(--ease); }

.ctl { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ctl label {
  font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px;
  color: var(--text-3); width: 64px; flex: none;
}
.ctl output {
  font-size: 12.5px; color: var(--text-2); font-variant-numeric: tabular-nums;
  width: 62px; text-align: right; flex: none; white-space: nowrap;
}

/* toggle switch */

.switch {
  position: relative; width: 34px; height: 19px; flex: none;
  border-radius: 100px; background: var(--surface-3);
  border: 1px solid var(--line); padding: 0;
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease);
}
.switch::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 13px; height: 13px; border-radius: 50%;
  background: var(--text-3);
  transition: transform 0.22s var(--ease), background 0.22s var(--ease);
}
.switch[aria-pressed="true"] { background: var(--accent-dim); border-color: var(--accent); }
.switch[aria-pressed="true"]::after { transform: translateX(15px); background: #fff; }
.switch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.switch:active::after { width: 17px; }
.switch[aria-pressed="true"]:active::after { transform: translateX(13px); }
.switch.is-busy { pointer-events: none; }
.switch.is-busy::after {
  border: 2px solid rgba(255, 255, 255, 0.35); border-top-color: transparent;
  background: transparent; animation: spin 0.7s linear infinite;
}

input[type="range"] {
  /* min-width:0 is required — a range input's intrinsic width (~129px) would
     otherwise stop the flex item shrinking and push the value out of the card */
  flex: 1 1 0; min-width: 0; width: 100%;
  height: 4px; -webkit-appearance: none; appearance: none;
  background: var(--surface-3); border-radius: 100px; outline: none;
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; width: 13px; height: 13px; border-radius: 50%;
  background: var(--accent); border: 2px solid var(--bg-1); cursor: pointer;
  transition: transform 0.15s var(--ease);
}
input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.18); }
input[type="range"]::-moz-range-thumb {
  width: 13px; height: 13px; border-radius: 50%; border: 2px solid var(--bg-1);
  background: var(--accent); cursor: pointer;
}

/* dual-handle range window — "show me only this slice of the data"
   Two range inputs share one track: the track and fill are drawn by the divs
   beneath, the inputs themselves are transparent and only their thumbs take
   the pointer, so either handle can be grabbed anywhere along the bar. */

.ctl--dual output { width: 90px; }

.dual {
  position: relative; flex: 1 1 0; min-width: 0;
  height: 18px; display: flex; align-items: center;
}
.dual__track {
  position: absolute; left: 0; right: 0; height: 4px;
  background: var(--surface-3); border-radius: 100px; pointer-events: none;
}
.dual__fill {
  position: absolute; top: 0; bottom: 0; left: 0; right: 0;
  background: var(--accent); border-radius: 100px; opacity: 0.55;
}
.dual input[type="range"] {
  position: absolute; left: 0; width: 100%; height: 18px; margin: 0;
  background: none; pointer-events: none;
}
.dual input[type="range"]::-webkit-slider-thumb { pointer-events: auto; }
.dual input[type="range"]::-moz-range-thumb { pointer-events: auto; }
.dual input[type="range"]::-moz-range-track { background: none; }
/* the handle being dragged sits on top of its twin at the ends of the range */
.dual input[type="range"]:focus-visible::-webkit-slider-thumb {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
.dual.is-windowed .dual__fill { opacity: 0.9; }

@media (max-width: 440px) {
  /* on a phone the two handles need the whole row: label and readout share a
     line above, the track gets the full width beneath them */
  .ctl--dual { flex-wrap: wrap; row-gap: 0; }
  .ctl--dual label { width: auto; flex: 1 1 auto; }
  .ctl--dual output { width: auto; }
  .ctl--dual .dual { order: 3; flex: 1 0 100%; }
}

@media (hover: none) {
  /* a 13px thumb is under the 44px touch target, so grow it on touch devices */
  .dual { height: 26px; }
  .dual input[type="range"] { height: 26px; }
  .dual input[type="range"]::-webkit-slider-thumb { width: 18px; height: 18px; }
  .dual input[type="range"]::-moz-range-thumb { width: 18px; height: 18px; }
}

/* legend — a floating window pinned to the map's top-left corner */

/* top-left column: the colour scale, then the live readout beneath it */
.map-stack {
  position: absolute; top: 14px; left: 14px; z-index: 620;
  width: 330px; max-width: calc(100% - 28px);
  display: flex; flex-direction: column; gap: 10px;
  pointer-events: none;
}
.map-stack > * { pointer-events: auto; }
.map-stack > .map-legend {
  position: static; top: auto; left: auto; width: 100%;
}

.map-legend {
  position: absolute; top: 14px; left: 14px; z-index: 620;
  width: 302px; padding: 15px 17px 16px;
  background: rgba(10, 16, 19, 0.90);
  backdrop-filter: blur(11px); -webkit-backdrop-filter: blur(11px);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.55);
  animation: legend-in 0.28s var(--ease);
}
.map-legend[hidden] { display: none; }
.map-legend__head {
  font-size: 12px; font-weight: 650; letter-spacing: 0.8px;
  text-transform: uppercase; color: var(--text-3);
  margin-bottom: 11px;
}

.legend__bar {
  height: 20px; border-radius: 4px; border: 1px solid rgba(255,255,255,0.16);
  position: relative;
}
/* the part of the scale a value window is hiding from the map */
.legend__mute {
  position: absolute; top: 0; bottom: 0;
  background: rgba(8, 12, 14, 0.74); border-radius: 3px;
}

/* the TARGET caption sits above the bar — reserve room so it clears the title */
.legend__bar--targeted { margin-top: 21px; }
.legend__ticks {
  display: flex; justify-content: space-between;
  font-size: 13px; color: var(--text-2); font-variant-numeric: tabular-nums;
  margin-top: 6px;
}
.legend__target {
  position: absolute; top: -4px; bottom: -4px; width: 2px;
  background: #fff; box-shadow: 0 0 0 1px rgba(0,0,0,0.7);
  border-radius: 2px;
}
.legend__target::after {
  content: attr(data-label); position: absolute; top: -14px; left: 50%;
  transform: translateX(-50%);
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.7px;
  color: #fff; white-space: nowrap; text-shadow: 0 1px 3px #000;
}
.legend + .legend {
  margin-top: 15px; padding-top: 14px; border-top: 1px solid var(--line-soft);
}
.legend__title {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 10px; font-size: 14.5px; font-weight: 600; color: var(--text);
  margin-bottom: 8px;
}
.legend__title span:last-child {
  color: var(--text-3); font-size: 12px; font-weight: 500;
  white-space: nowrap; flex: none;
}

@keyframes legend-in {
  from { opacity: 0; transform: translateX(-10px) scale(0.98); }
}

/* map key */

.key { display: flex; flex-wrap: wrap; gap: 7px 12px; }
.key__item { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text-2); }
.key__dot { width: 9px; height: 9px; border-radius: 50%; border: 1.5px solid rgba(0,0,0,0.5); }

/* the map itself */

.mapwrap { position: relative; }
#map { position: absolute; inset: 0; background: #05080a; }

/* ─── map full screen ───
   Native fullscreen already fills the screen, so the wrapper needs nothing;
   the fallback (Safari on iPhone has no element fullscreen) does it with a
   fixed overlay instead. Both carry .is-fs, so everything below reads one
   class. */
.mapwrap.is-fs-fallback {
  position: fixed; inset: 0; z-index: 3000;
  width: auto; height: auto;
  background: #05080a;
}
.mapwrap.is-fs { background: #05080a; }
.mapwrap.is-fs > #map,
.mapwrap.is-fs > #histMap { position: absolute; inset: 0; height: auto; min-height: 0; }

/* the fullscreen button sits under the zoom control */
.leaflet-bar a.ir-fs__btn,
.ir-fs a {
  display: grid; place-items: center;
  width: 30px; height: 30px;
}
.ir-fs a svg { width: 15px; height: 15px; display: block; }

.map-overlay-tr {
  position: absolute; top: 12px; right: 12px; z-index: 500;
  display: flex; flex-direction: column; gap: 8px; align-items: flex-end;
}

/* live readout of every active raster under the cursor */
.map-probe {
  padding: 13px 16px 14px; border-radius: 13px;
  background: rgba(9, 15, 18, 0.92); backdrop-filter: blur(10px);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  font-size: 16px; color: var(--text);
  animation: fade 0.14s var(--ease);
}
.map-probe[hidden] { display: none; }
.map-probe__head {
  font-size: 12.5px; font-weight: 700; letter-spacing: 0.9px;
  text-transform: uppercase; color: var(--text-3);
  margin-bottom: 9px;
}
.map-probe__row {
  display: flex; align-items: center; gap: 12px;
  justify-content: space-between; padding: 4px 0;
}
.map-probe__k {
  color: var(--text-2); display: flex; align-items: center; gap: 9px;
  font-size: 15px;
}
.map-probe__sw {
  width: 14px; height: 14px; border-radius: 4px; flex: none;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.28);
}
.map-probe__v {
  font-variant-numeric: tabular-nums; font-weight: 700; font-size: 17px;
}
.map-probe__v--none { color: var(--text-3); font-weight: 500; font-size: 15px; }
.map-probe__ll {
  margin-top: 9px; padding-top: 8px; border-top: 1px solid var(--line-soft);
  font-size: 13.5px; color: var(--text-3); font-variant-numeric: tabular-nums;
}

/* sprinkler key, top-right over the map */
.map-key {
  width: 250px; max-width: calc(100vw - 28px);
  padding: 11px 14px 12px; border-radius: 12px;
  background: rgba(9, 15, 18, 0.9); backdrop-filter: blur(10px);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
}
.map-key__head {
  font-size: 12.5px; font-weight: 700; letter-spacing: 0.9px;
  text-transform: uppercase; color: var(--text-3);
  margin-bottom: 9px;
}
.map-key .key { gap: 7px 14px; }
.map-key .key__item { font-size: 13.5px; }

.map-hint[hidden] { display: none; }
.map-hint {
  padding: 7px 12px; border-radius: 100px;
  background: rgba(9, 15, 18, 0.86); backdrop-filter: blur(9px);
  border: 1px solid var(--line);
  font-size: 13px; color: var(--text-2);
}

/* reshape bar — same corner as the spotlight, which is cleared before a
   reshape starts, so the two are never up together */
.map-editbar {
  /* above .toasts (3000): the bar is the only thing on screen that has to
     stay tappable, and a toast must never sit on its Save button */
  position: absolute; left: 50%; bottom: 22px; z-index: 3100;
  transform: translateX(-50%);
  max-width: calc(100% - 28px);
  display: flex; align-items: center; gap: 14px;
  padding: 10px 10px 10px 16px; border-radius: 100px;
  background: rgba(9, 15, 18, 0.94); backdrop-filter: blur(10px);
  border: 1px solid var(--accent-dim);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  font-size: 15px; color: var(--text);
  animation: pop 0.28s var(--ease);
}
.map-editbar[hidden] { display: none; }
.map-editbar { animation: rise-up 0.3s var(--ease); }
.map-editbar__msg { display: flex; align-items: center; gap: 10px; min-width: 0; }
.map-editbar__dot {
  width: 9px; height: 9px; border-radius: 50%; flex: none;
  background: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-glow);
  animation: halo-dot 2s var(--ease) infinite;
}
.map-editbar__text { min-width: 0; }
.map-editbar__text strong { color: var(--accent); font-weight: 650; }
.map-editbar__hint {
  display: block; font-size: 12.5px; color: var(--text-3); margin-top: 1px;
}
.map-editbar__actions { display: flex; align-items: center; gap: 8px; flex: none; }
.map-editbar__count {
  font-size: 13px; color: var(--text-3); font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* spotlight bar — bottom-centre, clear of the legend (top-left), the hint
   (top-right) and Leaflet's zoom + attribution (bottom-right) */
.map-spotlight {
  /* above .toasts (3000), for the same reason the reshape bar is: this bar has
     to stay tappable, and a toast must never land on its buttons */
  position: absolute; left: 50%; bottom: 22px; z-index: 3100;
  transform: translateX(-50%);
  display: flex; align-items: center; gap: 12px;
  padding: 10px 14px; border-radius: 100px;
  background: rgba(9, 15, 18, 0.92); backdrop-filter: blur(10px);
  border: 1px solid rgba(245, 165, 36, 0.5);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  font-size: 15px; color: var(--text-1); white-space: nowrap;
  animation: pop 0.28s var(--ease);
}
.map-spotlight[hidden] { display: none; }
.map-spotlight { animation: rise-up 0.3s var(--ease); }
.map-spotlight__dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--warn); flex: none;
  box-shadow: 0 0 0 4px rgba(245, 165, 36, 0.22);
  animation: halo-dot 2s var(--ease) infinite;
}
@keyframes halo-dot {
  0%, 100% { box-shadow: 0 0 0 3px rgba(245, 165, 36, 0.18); }
  50%      { box-shadow: 0 0 0 7px rgba(245, 165, 36, 0.06); }
}
@media (max-width: 720px) {
  .map-spotlight { white-space: normal; max-width: calc(100% - 28px); }
}

/* ─── generic page views ─── */

.page {
  height: 100%; overflow-y: auto; padding: 20px 24px 40px;
}
.page__inner { max-width: 1380px; margin: 0 auto; }

.page__head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 20px; margin-bottom: 18px; flex-wrap: wrap;
}
.page__title { font-size: 21px; font-weight: 650; margin: 0 0 4px; }
.page__desc { font-size: 14.5px; color: var(--text-2); margin: 0; max-width: 640px; }
.page__actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* Buttons are tactile: a gradient face with a highlight along the top edge,
   a lift on hover, a press on click, and a spinner state while a write is
   on its way. Every state is a transform or shadow, never a reflow. */
.btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 9px 16px; border-radius: var(--radius-sm);
  background: linear-gradient(180deg, #1c2b32 0%, #15222a 100%);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 1px 2px rgba(0, 0, 0, 0.35);
  color: var(--text); font-size: 14.5px; font-weight: 500;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background 0.16s var(--ease), border-color 0.16s var(--ease),
              transform 0.14s var(--ease), box-shadow 0.18s var(--ease), color 0.16s var(--ease);
}
.btn:hover {
  background: linear-gradient(180deg, #233640 0%, #1a2b33 100%);
  border-color: var(--text-3);
  transform: translateY(-1px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 6px 16px rgba(0, 0, 0, 0.35);
}
.btn:active { transform: translateY(1px) scale(0.985); box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.4); transition-duration: 0.06s; }
.btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-glow), 0 0 0 1px var(--accent); }
.btn svg { width: 15px; height: 15px; }
.btn--primary {
  background: linear-gradient(180deg, #14e2ad 0%, #07a07c 100%);
  border-color: #17d9a8; color: #04231c; font-weight: 640;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35), 0 2px 6px rgba(0, 212, 160, 0.25);
}
.btn--primary:hover {
  background: linear-gradient(180deg, #2af0bf 0%, #0bb88e 100%);
  border-color: #2af0bf;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 8px 22px rgba(0, 212, 160, 0.35);
}
.btn--danger {
  color: var(--danger); border-color: rgba(246, 104, 114, 0.4);
  background: linear-gradient(180deg, rgba(246, 104, 114, 0.10) 0%, rgba(246, 104, 114, 0.04) 100%);
}
.btn--danger:hover { background: rgba(246, 104, 114, 0.18); border-color: var(--danger); box-shadow: 0 6px 16px rgba(244, 82, 92, 0.2); }
.btn--ghost { background: none; box-shadow: none; }
.btn--ghost:hover { background: var(--surface-2); box-shadow: none; }
.btn--sm { padding: 5px 10px; font-size: 13.5px; }
.btn:disabled { opacity: 0.42; pointer-events: none; transform: none; box-shadow: none; }
/* a write in flight: the label dims and a ring spins in its place */
.btn.is-busy { pointer-events: none; color: transparent !important; }
.btn.is-busy > * { visibility: hidden; }
.btn.is-busy::after {
  content: ""; position: absolute; width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.25); border-top-color: currentColor;
  color: var(--text); animation: spin 0.7s linear infinite;
}
.btn--primary.is-busy::after { border-color: rgba(4, 35, 28, 0.25); border-top-color: #04231c; color: #04231c; }
.btn.is-ok::before {
  content: "✓"; position: absolute; inset: 0; display: grid; place-items: center;
  font-weight: 800; animation: pop 0.25s var(--ease);
}
.btn.is-ok > * { visibility: hidden; }

/* ─── tables ─── */

.tablewrap {
  border: 1px solid var(--line-soft); border-radius: var(--radius);
  overflow: auto; background: var(--surface); max-height: calc(100vh - 300px);
}

table.grid { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 14.5px; }
/* narrow side-by-side tables: let columns breathe and the wrapper scroll */
table.grid--compact { min-width: 720px; }
table.grid--compact td .item__meta { max-width: 190px; }
table.grid th {
  position: sticky; top: 0; z-index: 2;
  background: var(--surface-2);
  padding: 11px 13px; text-align: left; white-space: nowrap;
  font-size: 12px; font-weight: 650; letter-spacing: 0.6px; text-transform: uppercase;
  color: var(--text-3); border-bottom: 1px solid var(--line);
  cursor: pointer; user-select: none;
}
table.grid th:hover { color: var(--text-2); }
table.grid th[data-sort]::after {
  content: ""; display: inline-block; width: 0; height: 0; margin-left: 6px;
  vertical-align: middle; opacity: 0;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
}
table.grid th.sort-asc::after  { opacity: 1; border-bottom: 5px solid var(--accent); }
table.grid th.sort-desc::after { opacity: 1; border-top: 5px solid var(--accent); }
table.grid th.no-sort { cursor: default; }

table.grid td {
  padding: 9px 13px; border-bottom: 1px solid var(--line-soft);
  white-space: nowrap; color: var(--text);
}
table.grid tbody tr { transition: background 0.14s var(--ease); }
table.grid tbody tr:hover { background: var(--surface-2); }
table.grid tbody tr.is-selected { background: rgba(0, 212, 160, 0.10); }

/* A row whose New RT differs from the live plan: the operator's review queue.
   The left rule survives row hover and selection, so a highlighted row stays
   findable while it is being worked on. */
table.grid tbody tr.is-proposed { background: rgba(245, 165, 36, 0.09); }
table.grid tbody tr.is-proposed:hover { background: rgba(245, 165, 36, 0.15); }
table.grid tbody tr.is-proposed > td:first-child {
  box-shadow: inset 3px 0 0 var(--warn);
}
table.grid tbody tr.is-proposed.is-selected { background: rgba(245, 165, 36, 0.17); }

.propose-note {
  margin: 0 0 14px;
  padding: 11px 15px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-2);
  color: var(--text-3);
  font-size: 15px;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease),
              color 0.2s var(--ease);
}
.propose-note.is-live {
  border-color: rgba(245, 165, 36, 0.45);
  background: rgba(245, 165, 36, 0.09);
  color: var(--text-2);
}
.propose-note.is-live strong { color: var(--warn); }
.propose-note .btn { margin-left: 10px; vertical-align: baseline; }
table.grid tbody tr.flash { animation: row-flash 1.1s var(--ease); }

.cell-num { text-align: right; font-variant-numeric: tabular-nums; }

.zone-tag {
  display: inline-block; padding: 1.5px 8px; border-radius: 100px;
  font-size: 12px; font-weight: 600; letter-spacing: 0.3px;
  border: 1px solid currentColor; opacity: 0.95;
}
.zone-fairway { color: var(--fairway); }
.zone-rough   { color: var(--rough); }
.zone-green   { color: var(--green-zone); }
.zone-tee     { color: var(--tee); }
.zone-collar  { color: var(--collar); }
.zone-other   { color: var(--text-3); }

.rt-input {
  width: 86px; padding: 5px 9px; text-align: right;
  background: var(--bg); border: 1px solid var(--line); border-radius: 6px;
  font-variant-numeric: tabular-nums;
  transition: border-color 0.16s var(--ease), box-shadow 0.16s var(--ease);
}
.rt-input:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow);
}
.rt-input.is-dirty { border-color: var(--warn); color: var(--warn); }
.rt-input.is-invalid, input.is-invalid {
  border-color: var(--danger) !important; box-shadow: 0 0 0 3px rgba(246, 104, 114, 0.18);
  animation: shake 0.4s var(--ease);
}

.pill {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 9px; border-radius: 100px; font-size: 12.5px; font-weight: 600;
}
.pill--pending  { background: rgba(245, 165, 36, 0.16); color: var(--warn); }
.pill--approved { background: rgba(53, 208, 127, 0.14); color: var(--ok); }
.pill--modified { background: rgba(56, 189, 248, 0.14); color: var(--accent-2); }
.pill--rejected { background: rgba(244, 82, 92, 0.14); color: var(--danger); }
.pill--fence    { background: rgba(0, 212, 160, 0.14); color: var(--accent); }
.pill--muted    { background: var(--surface-3); color: var(--text-3); }

.delta-up   { color: var(--accent-2); }
.delta-down { color: var(--warn); }

/* ─── filters ─── */

.filters {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  margin-bottom: 12px;
}
.field { display: flex; flex-direction: column; gap: 4px; }
.field > label {
  font-size: 12px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--text-3);
}
.field input, .field select, .field textarea {
  padding: 7px 10px; border-radius: var(--radius-sm);
  background: var(--bg); border: 1px solid var(--line);
  transition: border-color 0.16s var(--ease), box-shadow 0.16s var(--ease);
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow);
}
.field--grow { flex: 1; min-width: 180px; }
.field.is-invalid input, .field.is-invalid select, .field.is-invalid textarea {
  border-color: var(--danger); box-shadow: 0 0 0 3px rgba(246, 104, 114, 0.18);
  animation: shake 0.4s var(--ease);
}
.field__error {
  display: flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--danger); animation: slide-down 0.18s var(--ease);
}
.field__error::before { content: "!"; flex: none; width: 15px; height: 15px; border-radius: 50%;
  display: grid; place-items: center; font-size: 10px; font-weight: 800;
  background: var(--danger-solid); color: #fff; }
.field__error[hidden] { display: none; }
.setpoint.is-invalid input { border-color: var(--danger); box-shadow: 0 0 0 3px rgba(246, 104, 114, 0.18); animation: shake 0.4s var(--ease); }

.segmented {
  display: inline-flex; padding: 3px; gap: 3px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 9px;
}
.segmented button {
  padding: 6px 13px; border: 0; border-radius: 6px; background: none;
  color: var(--text-2); font-size: 14px; font-weight: 500;
  transition: background 0.18s var(--ease), color 0.18s var(--ease);
}
.segmented button.is-active { background: var(--surface-3); color: var(--text); }

/* ─── two-column layouts ─── */

.split { display: grid; grid-template-columns: 340px 1fr; gap: 16px; align-items: start; }
/* the geofence list carries cards, not controls, so it gets a wider column */
.split--zones { grid-template-columns: minmax(360px, 0.8fr) 1fr; }
@media (max-width: 1080px) { .split--zones { grid-template-columns: 1fr; } }
@media (max-width: 1080px) {
  .split { grid-template-columns: 1fr; }
}

.list { display: flex; flex-direction: column; gap: 10px; }

.item {
  border: 1px solid var(--line-soft); border-radius: var(--radius);
  background: var(--surface); padding: 12px 14px;
  animation: rise 0.3s var(--ease) both;
  transition: border-color 0.18s var(--ease);
}
.item:hover { border-color: var(--line); }
.item__row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.item__title { font-weight: 600; font-size: 15.5px; display: flex; align-items: center; gap: 8px; }
.item__meta { font-size: 13.5px; color: var(--text-3); margin-top: 3px; }
.item__actions { display: flex; gap: 6px; flex: none; }

/* ─── geofence zone card ───
   Name, then facts, then members, then actions — each on its own line. Four
   buttons never fit beside the title in this column, and making them try is
   what pushed them over the text. */
.zone { padding: 14px 15px 13px; }
.zone__head {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  margin-bottom: 7px;
}
.zone__name {
  font-weight: 650; font-size: 16px; color: var(--text);
  overflow-wrap: anywhere;
}
.zone__meta {
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  font-size: 13.5px; color: var(--text-3);
}
.zone__meta > span { display: inline-flex; align-items: center; gap: 5px; }
.zone__meta > span + span::before {
  content: ""; width: 3px; height: 3px; border-radius: 50%;
  background: currentColor; opacity: 0.55; margin-right: 9px;
}
.zone__meta strong { color: var(--text-2); font-weight: 650; }
.zone__heads {
  display: flex; flex-wrap: wrap; gap: 5px;
  margin-top: 11px; padding-top: 11px; border-top: 1px solid var(--line-soft);
}
.zone__more { font-size: 13px; color: var(--text-3); align-self: center; }
.zone__actions {
  display: flex; flex-wrap: wrap; gap: 7px;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line-soft);
}
.zone__actions .btn { flex: 1 1 auto; min-width: 0; justify-content: center; }
.zone__actions .btn--danger { flex: 0 1 auto; }

.empty {
  padding: 44px 20px; text-align: center; color: var(--text-3);
  border: 1px dashed var(--line); border-radius: var(--radius); background: var(--surface);
}
.empty svg { width: 30px; height: 30px; opacity: 0.4; margin-bottom: 10px; }
.empty p { margin: 0; font-size: 14.5px; }

/* ─── modal ─── */

.modal-backdrop {
  position: fixed; inset: 0; z-index: 2000;
  background: rgba(3, 6, 8, 0.66); backdrop-filter: blur(3px);
  display: grid; place-items: center; padding: 24px;
  animation: fade 0.18s var(--ease);
}
.modal {
  width: min(460px, 100%);
  /* A dialog taller than the screen used to run off both ends of a centred
     grid cell with nothing to scroll. Cap it, and let the body scroll while
     the title and the buttons stay put. */
  max-height: 100%;
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 14px; box-shadow: var(--shadow);
  animation: pop 0.26s var(--ease);
  overflow: hidden;
}
.modal__head {
  padding: 15px 18px; border-bottom: 1px solid var(--line-soft);
  flex: none;
}
.modal__head h3 { margin: 0; font-size: 17px; font-weight: 650; }
.modal__head p { margin: 4px 0 0; font-size: 14px; color: var(--text-3); }
.modal__body {
  padding: 16px 18px; display: flex; flex-direction: column; gap: 14px;
  min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch;
}
.modal__foot {
  padding: 13px 18px; border-top: 1px solid var(--line-soft);
  display: flex; justify-content: flex-end; gap: 8px;
  background: var(--bg-1);
  flex: none;
}

.radio-cards { display: flex; flex-direction: column; gap: 8px; }
.radio-card {
  display: flex; gap: 11px; padding: 11px 13px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface-2); cursor: pointer;
  transition: border-color 0.16s var(--ease), background 0.16s var(--ease);
}
.radio-card:hover { border-color: var(--text-3); }
.radio-card.is-on { border-color: var(--accent); background: var(--accent-glow); }
.radio-card input { margin: 2px 0 0; accent-color: var(--accent); }
.radio-card__t { font-size: 14.5px; font-weight: 600; }
.radio-card__d { font-size: 13px; color: var(--text-3); margin-top: 2px; }

/* ─── notifications ─── */

.bell {
  position: relative; width: 40px; height: 40px; flex: none;
  display: grid; place-items: center; border-radius: 9px;
  background: var(--surface-2); border: 1px solid var(--line);
  transition: background 0.16s var(--ease), border-color 0.16s var(--ease);
}
.bell:hover { background: var(--surface-3); }
.bell svg { width: 19px; height: 19px; }
.bell.has-unread svg { animation: bell-ring 0.85s var(--ease); }
.bell__count {
  position: absolute; top: -6px; right: -6px;
  min-width: 21px; height: 21px; padding: 0 5px;
  display: none; place-items: center;
  border-radius: 100px; background: var(--danger-solid); color: #fff;
  font-size: 11.5px; line-height: 1; font-weight: 700; font-variant-numeric: tabular-nums;
  border: 2px solid #101a1e;
}
.bell.has-unread .bell__count { display: grid; }

.notif-panel {
  position: absolute; top: calc(100% + 8px); right: 16px; width: 372px;
  max-height: 460px; overflow: hidden;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; box-shadow: var(--shadow);
  z-index: 900;
  display: none; flex-direction: column;
}
.notif-panel.is-open { display: flex; animation: slide-down 0.22s var(--ease); }
.notif-panel__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 14px; border-bottom: 1px solid var(--line-soft);
  font-size: 13.5px; font-weight: 650; letter-spacing: 0.5px; text-transform: uppercase;
  color: var(--text-3);
}
.notif-list { overflow-y: auto; }
.notif {
  display: flex; gap: 11px; padding: 12px 14px;
  border-bottom: 1px solid var(--line-soft); cursor: pointer;
  transition: background 0.15s var(--ease);
  animation: rise 0.3s var(--ease) both;
}
.notif:hover { background: var(--surface-2); }
.notif__dot {
  width: 7px; height: 7px; border-radius: 50%; margin-top: 6px; flex: none;
  background: var(--accent); box-shadow: 0 0 8px var(--accent);
}
.notif.is-read .notif__dot { background: var(--line); box-shadow: none; }
.notif__t { font-size: 14.5px; font-weight: 600; margin-bottom: 2px; }
.notif__b { font-size: 13.5px; color: var(--text-2); line-height: 1.4; }
.notif__at { font-size: 12.5px; color: var(--text-3); margin-top: 4px; }

/* toasts */

.toasts {
  position: fixed; right: 18px; bottom: 18px; z-index: 3000;
  display: flex; flex-direction: column; gap: 9px; align-items: flex-end;
  pointer-events: none;
}
.toast {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 15px; min-width: 240px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm); box-shadow: var(--shadow);
  font-size: 14.5px; pointer-events: auto;
  animation: toast-in 0.32s var(--ease);
}
.toast.is-out { animation: toast-out 0.26s var(--ease) forwards; }
.toast--ok     { border-left-color: var(--ok); }
.toast--warn   { border-left-color: var(--warn); }
.toast--danger { border-left-color: var(--danger); }
.toast svg { width: 17px; height: 17px; flex: none; }
.toast--ok svg     { color: var(--ok); }
.toast--warn svg   { color: var(--warn); }
.toast--danger svg { color: var(--danger); }

/* ─── leaflet skinning ─── */

.leaflet-container { background: #05080a; font: inherit; }
.leaflet-popup { animation: popup-in 0.22s var(--ease); transform-origin: bottom center; }
.leaflet-tooltip { animation: fade 0.16s var(--ease); }
.leaflet-control-attribution {
  background: rgba(8, 12, 14, 0.78) !important; color: var(--text-3) !important;
  font-size: 11.5px !important;
}
.leaflet-control-attribution a { color: var(--text-2) !important; }
.leaflet-bar a {
  background: rgba(15, 22, 26, 0.94); color: var(--text);
  border-bottom-color: var(--line);
}
.leaflet-bar a:hover { background: var(--surface-3); color: #fff; }

.ir-raster { transition: opacity 0.35s var(--ease); }

.leaflet-popup-content-wrapper {
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow); padding: 0;
}
.leaflet-popup-content { margin: 0; width: 312px !important; line-height: 1.5; }
.leaflet-popup-tip { background: var(--surface); border: 1px solid var(--line); }
.leaflet-popup-close-button {
  color: var(--text-3) !important;
  width: 30px !important; height: 30px !important;
  padding: 0 !important;
  font-size: 20px !important; line-height: 30px !important; text-align: center;
}
.leaflet-popup-close-button:hover { color: var(--text) !important; }

.sp-pop__head {
  padding: 12px 14px 10px; border-bottom: 1px solid var(--line-soft);
}
.sp-pop__id { font-size: 16.5px; font-weight: 680; letter-spacing: 0.2px; }
.sp-pop__sub { font-size: 13px; color: var(--text-3); margin-top: 2px; }
.sp-pop__body { padding: 11px 14px 13px; display: flex; flex-direction: column; gap: 9px; }
.sp-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  font-size: 14px;
}
.sp-row__k { color: var(--text-3); }
.sp-row__v { font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }
.sp-sep { height: 1px; background: var(--line-soft); margin: 1px 0; }
.sp-metrics { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.sp-metric {
  padding: 8px 10px; border-radius: 7px;
  background: var(--surface-2); border: 1px solid var(--line-soft);
}
.sp-metric__k {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--text-3);
}
.sp-metric__v {
  font-size: 17.5px; font-weight: 650; font-variant-numeric: tabular-nums; margin-top: 2px;
  display: flex; align-items: center; gap: 6px;
}
.sp-metric__sw { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.sp-metric__n { font-size: 11.5px; color: var(--text-3); margin-top: 2px; }

.sp-copy {
  display: flex; align-items: center; gap: 7px;
  padding: 7px 9px; border-radius: 7px; width: 100%;
  background: var(--surface-2); border: 1px solid var(--line);
  font-size: 13px; font-variant-numeric: tabular-nums; color: var(--text-2);
  transition: border-color 0.16s var(--ease), color 0.16s var(--ease);
}
.sp-copy:hover { border-color: var(--accent); color: var(--text); }
.sp-copy.is-copied { border-color: var(--ok); color: var(--ok); }
.sp-copy svg { width: 13px; height: 13px; flex: none; }
.sp-copy span { flex: 1; text-align: left; }

.sp-override {
  padding: 8px 10px; border-radius: 7px;
  background: rgba(0, 212, 160, 0.09); border: 1px solid var(--accent-dim);
}
.sp-override--pending {
  background: rgba(245, 165, 36, 0.09); border-color: rgba(245, 165, 36, 0.45);
}
.sp-override__k {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.6px;
  color: var(--text-3); margin-bottom: 3px;
}
.sp-override__v { font-size: 14.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
.sp-strike { color: var(--text-3); text-decoration: line-through; font-weight: 500; }
.sp-arrow { color: var(--text-3); margin: 0 4px; }

.sp-actions { display: flex; gap: 7px; }
.sp-actions .btn { flex: 1; justify-content: center; }

.sp-label {
  background: none; border: 0; box-shadow: none; padding: 0;
  color: #fff; font-size: 11.5px; font-weight: 600;
  text-shadow: 0 1px 3px #000, 0 0 6px #000;
  white-space: nowrap;
}
.sp-label::before { display: none; }

/* spotlit heads carry their station and the runtime step they are proposing */
.sp-label--spot {
  padding: 3px 8px; border-radius: 100px;
  background: rgba(9, 15, 18, 0.9);
  border: 1px solid rgba(245, 165, 36, 0.55);
  color: var(--warn); font-size: 12.5px;
  text-shadow: none;
}

.fence-label {
  background: rgba(0, 212, 160, 0.92); border: 0; border-radius: 5px;
  color: #04231c; font-size: 12.5px; font-weight: 700; padding: 2px 8px;
  box-shadow: 0 3px 10px rgba(0,0,0,0.5);
}
.fence-label::before { display: none; }

.marker-pulse { animation: marker-pulse 1.1s var(--ease) 2; transform-origin: center; }

/* ─── geofence drawing ───
   Every vertex looks alike once a few are down, but only the first one closes
   the polygon — so it is drawn as a red dot with a standing label. */
.leaflet-editing-icon {
  border-radius: 3px;
  border: 1px solid var(--bg) !important;
  background: var(--accent) !important;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.55);
}
.leaflet-editing-icon.ir-vertex-first {
  border-radius: 50%;
  background: var(--danger-solid) !important;
  border: 2px solid #fff !important;
  box-shadow: 0 0 0 3px rgba(207, 36, 49, 0.35), 0 2px 6px rgba(0, 0, 0, 0.6);
  animation: vertex-first 1.7s var(--ease) infinite;
  z-index: 1000 !important;
}
@keyframes vertex-first {
  0%, 100% { box-shadow: 0 0 0 3px rgba(207, 36, 49, 0.35), 0 2px 6px rgba(0,0,0,0.6); }
  50%      { box-shadow: 0 0 0 7px rgba(207, 36, 49, 0.12), 0 2px 6px rgba(0,0,0,0.6); }
}
/* Reshaping a saved zone: Leaflet.draw drops a solid handle on every vertex
   and, at each midpoint, a half-opacity one that becomes a new vertex when it
   is dragged. Opacity alone is too subtle to read as "this one is different",
   so the midpoints get a hollow ring instead. */
.leaflet-editing-icon[style*="opacity: 0.6"] {
  opacity: 1 !important;
  border-radius: 50%;
  background: rgba(0, 212, 160, 0.22) !important;
  border: 2px dashed var(--accent) !important;
  box-shadow: none;
}

.ir-vertex-tip {
  background: rgba(207, 36, 49, 0.94);
  border: 0; border-radius: 100px; padding: 3px 9px;
  color: #fff; font-size: 12.5px; font-weight: 650; white-space: nowrap;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45);
}
.ir-vertex-tip::before { border-top-color: rgba(207, 36, 49, 0.94); }

/* a head held in the spotlight keeps a slow halo so it stays findable while the
   operator pans around the hole */
.marker-spotlit { animation: marker-halo 2.4s var(--ease) infinite; }

/* ─────────────────────────── animations ─────────────────────────── */

@keyframes fade      { from { opacity: 0; } }
@keyframes pop       { from { opacity: 0; transform: translateY(10px) scale(0.975); } }
@keyframes rise      { from { opacity: 0; transform: translateY(7px); } }
@keyframes slide-down{ from { opacity: 0; transform: translateY(-7px); } }
@keyframes toast-in  { from { opacity: 0; transform: translateX(26px) scale(0.97); } }
@keyframes toast-out { to   { opacity: 0; transform: translateX(26px) scale(0.97); } }
@keyframes row-flash {
  0%   { background: rgba(0, 212, 160, 0.26); }
  100% { background: transparent; }
}
@keyframes bell-ring {
  0%, 100% { transform: rotate(0); }
  15% { transform: rotate(13deg); }  35% { transform: rotate(-11deg); }
  55% { transform: rotate(7deg); }   75% { transform: rotate(-4deg); }
}
@keyframes marker-pulse {
  0%   { stroke-width: 2;  opacity: 1; }
  50%  { stroke-width: 11; opacity: 0.45; }
  100% { stroke-width: 2;  opacity: 1; }
}
@keyframes marker-halo {
  0%, 100% { stroke-width: 3;  }
  50%      { stroke-width: 9; }
}
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes rise-up   { from { opacity: 0; transform: translateY(14px); } }
@keyframes shake {
  10%, 90% { transform: translateX(-1px); } 20%, 80% { transform: translateX(2px); }
  30%, 50%, 70% { transform: translateX(-4px); } 40%, 60% { transform: translateX(4px); }
}
@keyframes shimmer { from { background-position: -200% 0; } to { background-position: 200% 0; } }
@keyframes glow-drift {
  0%   { transform: translate(0, 0) scale(1); }
  50%  { transform: translate(4%, -6%) scale(1.08); }
  100% { transform: translate(0, 0) scale(1); }
}
@keyframes popup-in { from { opacity: 0; transform: translateY(8px) scale(0.96); } }

/* boot splash */

.boot {
  position: fixed; inset: 0; z-index: 5000;
  display: grid; place-items: center;
  background: var(--bg);
  transition: opacity 0.4s var(--ease), visibility 0s linear 0.4s;
}
.boot.is-done { opacity: 0; visibility: hidden; }
.boot__inner { text-align: center; }
.boot__ring {
  width: 40px; height: 40px; margin: 0 auto 16px;
  border: 3px solid var(--surface-3); border-top-color: var(--accent);
  border-radius: 50%; animation: spin 0.85s linear infinite;
}
.boot__msg { font-size: 14.5px; color: var(--text-2); }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--surface-3); border-radius: 10px; border: 2px solid var(--bg); }
::-webkit-scrollbar-thumb:hover { background: #2b4149; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* ─────────────────────── historical maps ─────────────────────── */

.histview {
  display: grid; grid-template-columns: 372px 1fr; height: 100%;
}

.hist-rail {
  background: var(--bg-1); border-right: 1px solid var(--line);
  overflow-y: auto; padding: 16px 15px 20px;
  display: flex; flex-direction: column; gap: 14px;
}
.hist-rail__head { flex: none; }

.hist-gallery { display: flex; flex-direction: column; gap: 15px; flex: none; }

.hist-week__head {
  font-size: 11px; font-weight: 650; letter-spacing: 0.8px; text-transform: uppercase;
  color: var(--text-3); margin-bottom: 8px;
  display: flex; align-items: center; gap: 9px;
}
.hist-week__head::after {
  content: ""; flex: 1; height: 1px; background: var(--line-soft);
}
.hist-week__grid { display: grid; grid-template-columns: 1fr; gap: 9px; }

.hist-card {
  display: flex; flex-direction: column; gap: 7px;
  padding: 8px; text-align: left;
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm); color: var(--text);
  transition: border-color 0.16s var(--ease), background 0.16s var(--ease),
              transform 0.16s var(--ease);
  animation: rise 0.3s var(--ease) both;
}
.hist-card:hover {
  border-color: var(--text-3); background: var(--surface-2);
  transform: translateY(-2px);
}
.hist-card.is-active {
  border-color: var(--accent); background: var(--accent-glow);
  box-shadow: 0 0 0 1px var(--accent-dim);
}

.hist-card__thumb {
  width: 100%; display: block;
  /* the grid is square; stretch it back to the hole's true proportions */
  aspect-ratio: var(--hist-aspect, 3.9);
  object-fit: fill;
  border-radius: 5px; background: #0a1013;
  border: 1px solid var(--line-soft);
}
.hist-card__meta {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
}
.hist-card__date {
  font-size: 13px; font-weight: 600;
  display: flex; align-items: baseline; gap: 8px;
}
.hist-card__time { font-size: 11.5px; color: var(--text-3); font-variant-numeric: tabular-nums; font-weight: 500; }
.hist-card__vals { font-size: 12.5px; color: var(--text-2); font-weight: 600; }
.hist-card.is-active .hist-card__vals { color: var(--accent); }

#histMap { position: absolute; inset: 0; background: #05080a; }

.hist-banner {
  position: absolute; left: 14px; bottom: 14px; z-index: 620;
  display: flex; align-items: center; gap: 22px;
  padding: 12px 18px;
  background: rgba(10, 16, 19, 0.90);
  backdrop-filter: blur(11px); -webkit-backdrop-filter: blur(11px);
  border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.55);
  animation: legend-in 0.28s var(--ease);
}
.hist-banner__stamp { font-size: 15px; font-weight: 650; letter-spacing: 0.1px; }
.hist-banner__ago { font-size: 12px; color: var(--text-3); margin-top: 3px; }
.hist-banner__stats { display: flex; gap: 20px; }
.hist-stat { display: flex; flex-direction: column; gap: 2px; }
.hist-stat span {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--text-3);
}
.hist-stat strong { font-size: 15px; font-weight: 650; }

#histLegendPanel { top: 14px; left: 14px; }

.map-overlay-tr .map-hint { display: flex; align-items: center; }
/* must outrank the rule above, or a hidden hint still reserves its row */
.map-overlay-tr .map-hint[hidden] { display: none; }
.map-overlay-tr .map-hint output {
  font-size: 11.5px; color: var(--text-2); font-variant-numeric: tabular-nums;
  min-width: 38px; text-align: right;
}

@media (max-width: 1200px) {
  .histview { grid-template-columns: 320px 1fr; }
  .hist-banner { gap: 14px; padding: 10px 13px; flex-wrap: wrap; }
  .hist-banner__stats { gap: 13px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   RESPONSIVE — phones and small tablets
   ═══════════════════════════════════════════════════════════════════════════
   Everything above this line is the desktop layout and is left untouched; the
   rules below only take effect under 900px. Three structural moves carry most
   of the work:

     1. the header wraps, and the tab strip becomes a horizontal scroller
     2. every two-pane view (map + rail, gallery + map, list + preview) becomes
        one column with the map on top at a fixed share of the screen
     3. the map overlays — legend, hover readout, sprinkler key — leave the map
        and drop into the flow beneath it, so nothing covers the imagery

   The map is the one element that cannot simply reflow: #map is absolutely
   positioned, so its wrapper needs an explicit height at every breakpoint.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Narrow desktops and landscape tablets keep the two-pane layout — only the
   header needs help. Its single row has a 1425px min-content width, so at
   1280 or 1366 it used to push the whole page sideways. */
@media (min-width: 901px) and (max-width: 1424px) {
  :root { --header-h: auto; }
  .header { flex-wrap: wrap; row-gap: 6px; padding: 8px 18px; }
  .header__spacer { display: none; }
  .header__ctx { order: 2; }
  .setpoint { order: 3; margin-left: auto; }
  .bell { order: 4; }
  .account { order: 4; }
  .tabs {
    order: 5; flex: 1 1 100%; min-width: 0;
    overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
  }
  .tabs::-webkit-scrollbar { display: none; }
  .tabs__ink { display: none; }
}

@media (max-width: 900px) {
  :root { --header-h: auto; }

  /* the shell scrolls per-view rather than as one page */
  .app { grid-template-rows: auto 1fr; height: 100%; }

  /* ── header ── */
  .header {
    flex-wrap: wrap;
    gap: 10px 14px;
    padding: 9px 12px;
    height: auto;
  }
  /* the brand yields first — it can wrap, the numeric controls cannot */
  .brand { flex: 1 1 110px; min-width: 0; gap: 9px; }
  .brand__mark { width: 32px; height: 32px; }
  .brand__name { font-size: 15px; white-space: normal; overflow-wrap: anywhere; }
  .brand__sub { display: none; }
  .header__spacer { display: none; }
  .header__ctx { order: 3; flex: 1 1 100%; gap: 6px; }
  .header__ctx .chip { font-size: 12px; padding: 3px 9px; }

  /* the tab strip scrolls sideways instead of forcing the page wide */
  .tabs {
    order: 4; flex: 1 1 100%; min-width: 0;
    overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 2px;
  }
  .tabs::-webkit-scrollbar { display: none; }
  .tab { flex: none; padding: 9px 11px; font-size: 14px; }
  .tabs__ink { display: none; }

  /* "Target moisture" alone is a 218px floor that forces the header wide;
     the short caption keeps the control labelled at a third of the width */
  .setpoint { padding: 4px 7px 4px 10px; gap: 6px; min-width: 0; }
  .setpoint label { display: none; }
  .setpoint::before {
    content: "TARGET";
    font-size: 11px; font-weight: 700; letter-spacing: 0.7px;
    color: var(--text-3); white-space: nowrap;
  }
  .setpoint input { width: 50px; }
  .bell { width: 36px; height: 36px; }
  /* signed in, the account button shares the second row with the hole
     picker and the data date, at the right-hand end — that row has the room,
     the brand row does not on a narrow phone */
  .account { order: 3; margin-left: auto; }
  body.is-remote .header__ctx { flex: 1 1 auto; }
  body.is-remote .header { column-gap: 10px; }
  .account__btn { max-width: 120px; padding-right: 8px; }
  .account__name { display: none; }
  /* the button can land anywhere on the wrapped header row, so the menu is
     pinned to the viewport instead of to the button */
  .account__menu {
    position: fixed; left: 12px; right: 12px; min-width: 0;
    top: var(--account-menu-top, 64px);
  }

  .notif-panel { width: min(340px, calc(100vw - 20px)); right: 8px; }

  /* ── map view: map on top, controls beneath ── */
  .mapview {
    display: flex; flex-direction: column;
    height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch;
  }
  /* The map takes an explicit height and returns to the flow, so the panels
     that used to float over it simply follow it. They are DOM children of
     .mapwrap, so `order` on .mapview could never have moved them — the wrapper
     itself has to stop being height-constrained. */
  .mapwrap { order: 1; flex: none; height: auto; }
  #map { position: relative; inset: auto; height: 60vh; min-height: 320px; }
  .rail {
    order: 2; flex: none;
    width: auto; border-right: 0; border-top: 1px solid var(--line);
    overflow: visible; padding: 12px;
  }

  /* overlays leave the map so they can never cover it */
  .map-stack {
    position: static; width: auto; max-width: none;
    padding: 12px 12px 0; gap: 10px;
    background: var(--bg-1);
  }
  .map-stack > .map-legend,
  .map-probe { width: 100%; }
  .map-legend { backdrop-filter: none; background: var(--surface); }
  .map-probe { backdrop-filter: none; background: var(--surface); }
  .map-overlay-tr {
    position: static; align-items: stretch;
    padding: 12px 12px 0; background: var(--bg-1);
  }
  .map-key {
    width: 100%; max-width: none;
    backdrop-filter: none; background: var(--surface); box-shadow: none;
  }
  .map-key .key { gap: 8px 16px; }
  /* The geofence drawing hint stays over the map — it is an instruction, not a
     legend. Scoped to the map view: the history tab uses .map-hint for its
     opacity slider, which must stay with the layer chooser. */
  #view-map .map-overlay-tr .map-hint {
    position: fixed; top: auto; left: 12px; right: 12px;
    bottom: 12px; z-index: 660; justify-content: center;
    white-space: normal; text-align: center;
  }

  /* the spotlight bar is an active-mode control, so it floats above the page
     rather than scrolling away with the map */
  .map-spotlight {
    position: fixed;
    left: 8px; right: 8px; bottom: 10px; transform: none;
    justify-content: center; flex-wrap: wrap; gap: 8px;
    font-size: 13.5px; padding: 9px 11px; white-space: normal;
  }

  /* ── full screen ──
     Stacking the panels under the map is right for a 60vh preview; in full
     screen there is room again, so they go back over the map and the map
     itself takes the whole wrapper. */
  .mapwrap.is-fs { order: 0; height: 100%; }
  .mapwrap.is-fs > #map,
  .mapwrap.is-fs > #histMap {
    position: absolute; inset: 0; height: auto; min-height: 0;
  }
  .mapwrap.is-fs .map-stack {
    position: absolute; top: 10px; left: 10px; z-index: 620;
    width: min(320px, calc(100% - 20px)); max-width: none;
    max-height: 52%; overflow-y: auto; -webkit-overflow-scrolling: touch;
    padding: 0; background: none; gap: 8px;
  }
  .mapwrap.is-fs .map-overlay-tr {
    position: absolute; top: 10px; right: 10px; left: auto; z-index: 500;
    width: auto; padding: 0; background: none; align-items: flex-end;
  }
  .mapwrap.is-fs .map-key { width: 200px; max-width: 45vw; }
  /* the history tab keeps its layer chooser on top, so its legend goes below */
  .histview .mapwrap.is-fs #histLegendPanel {
    position: absolute; left: 10px; right: auto; top: auto; bottom: 10px;
    width: min(310px, calc(100% - 20px)); margin: 0;
    max-height: 52%; overflow-y: auto; -webkit-overflow-scrolling: touch;
  }
  .histview .mapwrap.is-fs .hist-banner { display: none; }

  /* Leaflet.draw already swaps in a 20px handle when it sees a touch device,
     but not every phone browser reports one — a 8px target is unusable either
     way, so the size is pinned here. */
  .leaflet-editing-icon {
    width: 20px !important; height: 20px !important;
    margin-left: -10px !important; margin-top: -10px !important;
  }

  /* toasts own the bottom of the screen here, which is where the reshape and
     spotlight bars go — so while either is up the toasts stack above it. The
     height comes from UI.syncBottomBar, with a fallback for the frame before
     it has measured. */
  body.is-reshaping .toasts,
  body.is-spotlit .toasts { bottom: calc(var(--bottom-bar-h, 96px) + 18px); }

  /* the reshape bar wraps and spans the width rather than truncating */
  .map-editbar {
    position: fixed; left: 8px; right: 8px; bottom: 10px;
    transform: none; max-width: none;
    flex-wrap: wrap; justify-content: space-between; gap: 8px 10px;
    border-radius: 14px; padding: 10px 12px;
    font-size: 14px; white-space: normal;
  }
  .map-editbar__msg { flex: 1 1 100%; align-items: flex-start; }
  .map-editbar__dot { margin-top: 6px; }
  .map-editbar__hint { font-size: 12px; }
  .map-editbar__actions { flex: 1 1 100%; justify-content: flex-end; }
  .map-editbar__actions .btn { flex: 1 1 auto; justify-content: center; }

  /* ── history view ── */
  .histview {
    display: flex; flex-direction: column;
    height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch;
  }
  .histview .mapwrap { order: 1; height: auto; }
  #histMap { position: relative; inset: auto; height: 50vh; min-height: 280px; }
  .hist-rail {
    order: 2; border-right: 0; border-top: 1px solid var(--line);
    overflow: visible; padding: 12px;
  }
  .hist-week__grid { gap: 10px; }
  /* the layer chooser stays over the map — it is the tab's main control —
     while the readouts drop into the flow underneath it */
  .histview .map-overlay-tr {
    position: absolute; top: 8px; right: 8px; left: 8px; z-index: 640;
    padding: 0; background: none; align-items: stretch; gap: 6px;
  }
  #histLayer { flex-wrap: wrap; }
  #histLayer button { flex: 1 1 auto; padding: 6px 9px; font-size: 13px; }
  .histview .map-hint { justify-content: space-between; }
  #histLegendPanel {
    position: static; width: auto; max-width: none;
    margin: 12px 12px 0;
    background: var(--surface); backdrop-filter: none;
  }
  .hist-banner {
    position: static; margin: 12px 12px 0;
    flex-wrap: wrap; gap: 8px 16px; padding: 11px 13px;
    background: var(--surface); backdrop-filter: none; -webkit-backdrop-filter: none;
  }
  .hist-banner__stats { gap: 14px; flex-wrap: wrap; }

  /* ── pages ── */
  .page { padding: 14px 12px 32px; }
  .page__head { gap: 12px; margin-bottom: 14px; }
  .page__title { font-size: 19px; }
  .page__desc { font-size: 14px; }
  .page__actions { flex-wrap: wrap; gap: 8px; }
  .split, .split--zones { grid-template-columns: 1fr; }

  .filters { gap: 8px; }
  .field { flex: 1 1 150px; }
  .field--grow { flex: 1 1 100%; }
  /* that flex-basis is for filter rows; inside a column dialog body it
     stretched every field to 150px tall and pushed the controls apart */
  .modal__body .field { flex: none; }
  .filters .btn { flex: 1 1 auto; justify-content: center; white-space: nowrap; }

  .segmented { flex-wrap: wrap; }
  /* the backdrop's padding is the dialog's margin, and .modal is capped at the
     height that leaves — so a tall dialog scrolls its body instead of running
     off both ends of the screen */
  .modal-backdrop { padding: 12px; }
  .modal__head { padding: 13px 14px; }
  .modal__head h3 { font-size: 16px; }
  .modal__head p { font-size: 13px; }
  .modal__body { padding: 13px 14px; gap: 12px; }
  .modal__foot { padding: 11px 14px; }
  .modal__foot .btn { flex: 1 1 auto; justify-content: center; }
  .radio-card { padding: 10px 11px; gap: 9px; }
  .radio-card__d { font-size: 12.5px; }

  /* ── sprinkler popup ──
     It used to be a fixed 312px of unscrollable detail over a map that is only
     part of the page, so the top of it was clipped. Now it fits the screen and
     scrolls inside itself, with the station header staying put. */
  .leaflet-popup-content { width: min(300px, calc(100vw - 62px)) !important; }
  .sp-pop__body {
    max-height: 42vh; overflow-y: auto; -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
  }
  .sp-pop__head { padding: 11px 13px 9px; }
  .sp-pop__id { font-size: 15.5px; }
  .sp-metric__v { font-size: 16px; }
  /* Leaflet's attribution wraps onto the scale bar at this width */
  .leaflet-control-attribution {
    font-size: 9.5px; max-width: 62vw;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .leaflet-control-scale { font-size: 10px; }

  .toasts { left: 10px; right: 10px; bottom: 10px; }
  .toast { width: auto; }
}

@media (max-width: 560px) {
  /* the context chips repeat what the header and tabs already say */
  .header__ctx { display: none; }
  /* ...except when signed in, where the hole picker lives there: keep the
     picker and the data date, drop the head count */
  body.is-remote .header__ctx { display: flex; }
  body.is-remote #ctxHeads { display: none; }

  .mapwrap.is-fs .map-key { display: none; }

  /* the map is 56vh here, and Leaflet needs ~70px of that for the anchor and
     its autoPan padding — 30vh of scrollable body keeps the whole popup on it */
  .leaflet-popup-content { width: min(276px, calc(100vw - 54px)) !important; }
  .sp-pop__body { max-height: 30vh; }

  #map { height: 56vh; min-height: 300px; }
  #histMap { height: 46vh; min-height: 260px; }

  .stat-grid { grid-template-columns: 1fr 1fr; }
  .stat__value { font-size: 22px; }

  .page__title { font-size: 18px; }
  .zone__actions .btn { flex: 1 1 44%; }

  /* wide tables scroll inside their card rather than stretching the page */
  table.grid { min-width: 780px; }
  table.grid--compact { min-width: 640px; }

  .hist-banner { font-size: 13px; }
  .hist-banner__stamp { font-size: 14px; }
}
