/* Denton Ranch - every colour resolves through tokens.css, so light/dark is
   handled once, in the token layer, and never repeated here. */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
/* The UA rule for [hidden] is display:none at specificity 0, so ANY class rule
   that sets display (.gate, .sheet, .filters...) silently beats it and the
   element stays on screen. Everything here toggles visibility with .hidden, so
   this one rule has to win. */
[hidden] { display: none !important; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.45;
  padding-bottom: env(safe-area-inset-bottom);
}
h1, h2, h3 { font-family: var(--font-display); font-weight: 560; margin: 0; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }

.eyebrow {
  margin: 0; text-transform: uppercase; letter-spacing: .18em;
  font-size: .58rem; font-weight: 700; color: var(--accent-deep);
}
.field-label { font-size: .78rem; color: var(--ink-soft); }

/* ---------- buttons ---------- */
.btn-primary {
  background: linear-gradient(var(--accent), var(--accent-deep));
  color: var(--on-accent); border: 0; border-radius: var(--r-pill);
  padding: 10px 18px; font-weight: 650; font-size: .9rem;
  box-shadow: var(--shadow-1);
}
.btn-quiet {
  background: var(--surface-2); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-pill);
  padding: 9px 16px; font-size: .85rem;
}
.btn-quiet.danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, var(--line)); }
:where(button, input, select, textarea, a):focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}

/* ---------- gate ---------- */
.gate {
  position: fixed; inset: 0; z-index: 90; background: var(--bg);
  display: grid; place-items: center; padding: 24px;
}
.gate-card {
  width: min(380px, 100%); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-xl);
  padding: 30px 26px; box-shadow: var(--shadow-3);
  display: flex; flex-direction: column; gap: 12px; text-align: center;
}
.gate-title { font-size: 1.9rem; letter-spacing: -.01em; }
.gate-sub { margin: 0; color: var(--ink-soft); font-size: .88rem; }
.gate-card input {
  background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 12px 14px; text-align: center; letter-spacing: .1em;
}
.gate-err { margin: 0; min-height: 1.2em; color: var(--danger); font-size: .82rem; }
.shake { animation: shake 340ms var(--ease); }
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-7px); }
  45% { transform: translateX(6px); }
  70% { transform: translateX(-3px); }
}

/* ---------- chrome ---------- */
.topbar {
  position: sticky; top: 0; z-index: 20;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
  padding-top: env(safe-area-inset-top);
}
.topbar-in {
  max-width: var(--maxw); margin: 0 auto; padding: 12px 18px;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.brand { font-size: 1.32rem; line-height: 1.15; letter-spacing: -.01em; }
.brand-2 { color: var(--accent-deep); }
.icon-btn {
  background: none; border: 0; color: var(--ink-soft);
  display: grid; place-items: center; width: 40px; height: 40px;
  border-radius: var(--r-pill); font-size: 1.4rem; line-height: 1;
}
.icon-btn:hover { background: var(--surface-2); color: var(--ink); }

.wrap {
  max-width: var(--maxw); margin: 0 auto; padding: var(--sp-5) 18px 64px;
  display: flex; flex-direction: column; gap: var(--rhythm);
}

/* ---------- pull to refresh ----------
   Sits above the app bar, so pulling pushes the bar down with the page. Height is
   driven from JS as the finger moves; collapsed it is 0px and contributes nothing.

   The app bar is position:sticky top:0, which still behaves: at scroll 0 its
   static position moves down with this element, and it only pins once you scroll.

   .pulling adds the safe-area inset ONLY while open. With viewport-fit=cover and a
   black-translucent status bar the inset is nonzero, and without this the indicator
   would render up under the notch. It cannot be a permanent padding because
   box-sizing:border-box would then give the collapsed bar a real height. */
.ptr {
  height: 0; overflow: hidden;
  display: flex; align-items: flex-end; justify-content: center;
  background: var(--bg);
}
.ptr.pulling { padding-top: env(safe-area-inset-top, 0px); }
.ptr.snap { transition: height var(--dur-2) var(--ease); }
.ptr-in {
  display: flex; align-items: center; gap: 8px;
  padding-bottom: 10px; font-size: .74rem; color: var(--ink-soft);
  white-space: nowrap;
}
/* an arc that fills as you pull, then spins while it works */
.ptr-mark {
  width: 15px; height: 15px; border-radius: 50%; flex: none;
  border: 2px solid var(--line); border-top-color: var(--accent);
  transition: transform var(--dur-1) var(--ease);
}
.ptr.armed .ptr-mark { transform: rotate(180deg); border-top-color: var(--accent-deep); }
.ptr.armed .ptr-in { color: var(--accent-deep); font-weight: 600; }
.ptr.busy .ptr-mark { animation: ptr-spin .7s linear infinite; transition: none; }
@keyframes ptr-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .ptr.busy .ptr-mark { animation: none; }
  .ptr.snap { transition: none; }
}
.foot { text-align: center; margin: 0; }

/* ---------- generic card ---------- */
.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 18px; box-shadow: var(--shadow-2);
  position: relative; overflow: hidden;
}
/* a severity stripe reads before the words do */
.card.ok::before, .card.warn::before, .card.crit::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 3px;
}
.card.ok::before { background: var(--ok); }
.card.warn::before { background: var(--warn); }
.card.crit::before { background: var(--crit); }
.card-h {
  font-family: var(--font-display); font-size: 1.12rem; cursor: pointer;
  list-style: none; display: flex; align-items: baseline; gap: 10px;
}
.card-h::-webkit-details-marker { display: none; }
.card-h::after { content: "+"; margin-left: auto; color: var(--ink-soft); font-family: var(--font-body); }
details.card[open] > .card-h::after { content: "\2212"; }
.card-sub { color: var(--ink-soft); font-size: .82rem; margin: 8px 0 12px; }
.range-sub { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--line); }
.cron-line { margin-top: 14px; font-size: .74rem; }
.cron-line.stale { color: var(--crit); font-weight: 600; }

/* ---------- the two clocks: the one place with real visual weight ---------- */
.clocks { display: grid; grid-template-columns: 1fr auto 1fr; gap: 10px; align-items: center; text-align: center; }
.clock { display: flex; flex-direction: column; gap: 2px; }
.big {
  font-family: var(--font-display); font-size: clamp(1.5rem, 6vw, 2.1rem); line-height: 1.05;
  font-variant-numeric: tabular-nums;
}
.clocks.warn .big, .clocks.warn .gap-n { color: var(--warn); }
.clocks.crit .big, .clocks.crit .gap-n { color: var(--crit); }
.lab { text-transform: uppercase; letter-spacing: .18em; font-size: .58rem; font-weight: 700; color: var(--accent-deep); }
.sub { font-size: .72rem; color: var(--ink-soft); }
.gap {
  display: flex; flex-direction: column; gap: 2px; padding: 0 12px;
  border-left: 1px solid var(--line); border-right: 1px solid var(--line);
}
.gap-n { font-family: var(--font-display); font-size: 1.3rem; font-variant-numeric: tabular-nums; }

/* ---------- filters ---------- */
.filters { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: var(--sp-4); }
.chip {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-pill);
  padding: 6px 13px; font-size: .8rem; color: var(--ink-soft);
}
.chip.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 650; }
.chip.dead { opacity: .45; }
.hint { margin: -8px 0 var(--sp-4); font-size: .78rem; color: var(--ink-soft); font-style: italic; }

/* ---------- a day ---------- */
#agenda { display: flex; flex-direction: column; gap: var(--rhythm-tight); }
.day {
  background: var(--surface); border: 1px solid var(--line);
  border-left: 3px solid var(--line); border-radius: var(--r-lg);
  padding: 14px 16px 10px; box-shadow: var(--shadow-1);
  scroll-margin-top: 84px;
}
.day.is-today { border-left-color: var(--accent); box-shadow: var(--shadow-2); }
.day.is-past { opacity: .72; }
.day.is-overdue { border-left-color: var(--crit); opacity: 1; }
/* A day with nothing on it is scaffolding, not content - it should read as a
   thin ruled line you can drop something onto, not as a card of its own. */
.day.is-empty {
  padding: 9px 16px 6px; box-shadow: none;
  background: color-mix(in srgb, var(--surface) 55%, transparent);
}
.day.is-empty .day-h { margin-bottom: 0; }
.day.is-empty .day-t { font-size: .93rem; color: var(--ink-soft); }
.day.is-empty .add-open { padding: 5px 0; font-size: .8rem; }
.day-h { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.day-t { font-size: 1.05rem; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.day-s { margin: 1px 0 0; font-size: .74rem; color: var(--ink-soft); }
.day-n {
  flex: none; font-size: .74rem; font-weight: 650; color: var(--ink-soft);
  font-variant-numeric: tabular-nums; padding-top: 3px;
}
.chip-today {
  font-family: var(--font-body); font-size: .56rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .1em;
  background: var(--accent); color: var(--on-accent);
  border-radius: var(--r-pill); padding: 2px 8px;
}
.day-empty { margin: 6px 0; font-size: .82rem; color: var(--ink-soft); font-style: italic; }

/* ---------- a task ---------- */
.task {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 0; border-top: 1px solid var(--line);
}
.task:first-of-type { border-top: none; }
.task-tick { display: grid; place-items: center; flex: none; width: 30px; height: 30px; cursor: pointer; }
.task-tick input { width: 20px; height: 20px; accent-color: var(--accent); cursor: pointer; }
.task-text {
  flex: 1; min-width: 0; text-align: left; background: none; border: 0;
  padding: 6px 0; font-size: .93rem; line-height: 1.35; color: var(--ink);
  display: flex; flex-direction: column; gap: 2px;
}
/* strike the words, not the time and place - those stay legible as a record */
.task.done .task-text { color: var(--ink-soft); text-decoration: line-through; }
.task.done .task-meta { text-decoration: none; }
.task-meta { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; font-size: .74rem; }
.task-time { color: var(--accent-deep); font-weight: 650; font-variant-numeric: tabular-nums; }
.task-place { color: var(--ink-soft); }
.task-dot { color: var(--ink-soft); opacity: .6; }
.task-cal {
  font-size: .58rem; font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
  color: var(--accent-deep); border: 1px solid currentColor; border-radius: var(--r-sm);
  padding: 0 4px; line-height: 1.5;
}
.edit-allday { margin-top: 10px; font-size: .82rem; color: var(--ink-soft); }
.edit-hint { margin: 6px 0 0; font-size: .74rem; color: var(--ink-soft); font-style: italic; }
.edit-place { display: flex; flex-direction: column; gap: 3px; margin-top: 10px; }
.edit-place input, .edit-fields input[type="time"] {
  background: var(--bg); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-sm); padding: 8px 10px;
}

/* the assignee badge: a hue per person, so a glance down the list separates
   them without reading the letters */
/* The border is always the neutral --line and is NEVER overridden per person.
   That is what makes the chip's edge visible against the card, which frees each
   fill to be chosen purely for text legibility and for separation from the other
   person - those three jobs fight each other if one colour has to do all of them. */
/* padding:0 is load-bearing. A button carries the UA's default 1px 6px, which
   leaves an 18px content box inside the 32px circle - and "C+H" is 20px wide, so
   it overflowed and spilled right instead of centering. "C" and "H" are narrow
   enough to fit, which is why only the Both chip looked off. */
.who {
  flex: none; width: 32px; height: 32px; border-radius: var(--r-pill);
  padding: 0;
  border: 1px solid var(--line); background: var(--surface-2); color: var(--ink-soft);
  font-size: .68rem; font-weight: 700; letter-spacing: .02em; line-height: 1;
  display: grid; place-items: center;
}
.who-colby { background: var(--who-colby); color: var(--who-colby-on); }
.who-heidi { background: var(--who-heidi); color: var(--who-heidi-on); }
.who-both  { background: var(--who-both);  color: var(--who-both-on); font-size: .58rem; }
.who-none  { border-style: dashed; font-size: 1rem; font-weight: 500; }

/* ---------- dragging a task ----------
   A lifted row is torn out of the flow and positioned against the viewport, so it
   tracks the finger rather than the page. pointer-events:none is what lets
   elementFromPoint report the row UNDERNEATH the one being dragged. */
/* a cursor should say the row is draggable, and stay "grabbing" while it is up */
@media (hover: hover) and (pointer: fine) {
  .task { cursor: grab; }
  .task.editing { cursor: auto; }
  .task button, .task input, .task label { cursor: pointer; }
  body.is-dragging, body.is-dragging .task { cursor: grabbing; }
}
.task.dragging {
  position: fixed; z-index: 70; pointer-events: none;
  margin: 0; border-top: 0;
  background: var(--surface); border-radius: var(--r-md);
  box-shadow: var(--shadow-3);
  padding-left: 10px; padding-right: 10px;
  transform: scale(1.02); opacity: .96;
}
/* the gap that opens up where it will land */
.drop-holder {
  border-radius: var(--r-md);
  border: 1px dashed var(--accent);
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  margin: 3px 0;
}
/* while a row is in the air, stop long-press text selection and iOS's callout */
body.is-dragging {
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
}
/* a row is draggable, so suppress the callout on all of them */
.task-text { -webkit-touch-callout: none; }
@media (prefers-reduced-motion: reduce) {
  /* a cursor should say the row is draggable, and stay "grabbing" while it is up */
@media (hover: hover) and (pointer: fine) {
  .task { cursor: grab; }
  .task.editing { cursor: auto; }
  .task button, .task input, .task label { cursor: pointer; }
  body.is-dragging, body.is-dragging .task { cursor: grabbing; }
}
.task.dragging { transform: none; }
}

/* ---------- editing a task ---------- */
.task.editing { display: block; padding: 12px 0; }
.edit-box {
  width: 100%; background: var(--bg); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 10px 12px; resize: vertical; line-height: 1.4;
}
.edit-fields { display: flex; gap: 10px; margin-top: 10px; flex-wrap: wrap; }
.edit-fields label { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 130px; }
.edit-fields select, .quiet-row select, .datefield input {
  background: var(--bg); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-sm); padding: 8px 10px;
}
.edit-btns { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.edit-btns .btn-quiet.danger { margin-left: auto; }

/* ---------- adding ---------- */
.add-open {
  display: block; width: 100%; text-align: left; margin-top: 4px;
  background: none; border: 0; padding: 9px 0;
  color: var(--accent-deep); font-size: .84rem; font-weight: 600;
}
.add-open:hover { color: var(--accent); }
.add-row { display: flex; gap: 7px; margin: 8px 0 4px; flex-wrap: wrap; }
.add-row input {
  flex: 1; min-width: 140px; background: var(--bg); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-md); padding: 10px 12px;
}

/* ---------- key dates ---------- */
.datefield {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  padding: 9px 0; border-top: 1px solid var(--line);
}
.datefield + .datefield { border-top: 1px solid var(--line); }
.range-sub + .datefield { border-top: none; }

/* ---------- sync pill + toast ---------- */
.sync {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: .72rem; color: var(--ink-soft);
}
.sync .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); }
.sync[data-state="saving"] .dot { background: var(--warn); }
.sync[data-state="offline"] .dot { background: var(--crit); }
.toast {
  position: fixed; left: 50%; bottom: calc(22px + env(safe-area-inset-bottom));
  transform: translate(-50%, 14px); z-index: 80;
  background: var(--ink); color: var(--bg);
  padding: 9px 16px; border-radius: var(--r-pill); font-size: .82rem;
  opacity: 0; pointer-events: none; transition: opacity var(--dur-2) var(--ease), transform var(--dur-2) var(--ease);
  margin: 0; max-width: 88vw; text-align: center;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ---------- settings sheet ---------- */
.sheet-scrim { position: fixed; inset: 0; z-index: 60; background: rgb(0 0 0 / .38); }
.sheet {
  position: fixed; z-index: 61; inset: auto 0 0 0;
  max-height: 88vh; overflow-y: auto;
  background: var(--surface); border-top: 1px solid var(--line);
  border-radius: var(--r-xl) var(--r-xl) 0 0; box-shadow: var(--shadow-3);
  padding-bottom: calc(24px + env(safe-area-inset-bottom));
}
@media (min-width: 640px) {
  .sheet {
    inset: 50% auto auto 50%; transform: translate(-50%, -50%);
    width: min(460px, 92vw); border-radius: var(--r-xl); border: 1px solid var(--line);
    padding-bottom: 24px;
  }
}
.sheet-head {
  position: sticky; top: 0; background: var(--surface);
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 18px 10px; border-bottom: 1px solid var(--line);
}
.sheet-head h2 { font-size: 1.15rem; }
.sheet-body { padding: 4px 18px 0; display: flex; flex-direction: column; gap: var(--sp-5); }
.set-block { display: flex; flex-direction: column; gap: 9px; align-items: flex-start; }
.set-block h3 { font-size: .95rem; }
.set-note { margin: 0; font-size: .78rem; color: var(--ink-soft); }
.seg { display: flex; gap: 6px; flex-wrap: wrap; }
.seg-btn {
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-pill);
  padding: 7px 15px; font-size: .84rem; color: var(--ink-soft);
}
.seg-btn.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 650; }
/* skin buttons carry a two-tone chip of the palette they switch to, so the choice
   is visible before you commit to it */
.skin-btn { display: inline-flex; align-items: center; gap: 8px; }
#skinRow { gap: 6px; }
#skinRow .seg-btn { padding: 6px 12px; font-size: .8rem; }
.swatch {
  width: 16px; height: 16px; border-radius: 50%;
  border: 1px solid rgb(var(--shadow-ch) / .28); flex: none;
}
/* Each swatch is the skin's accent against its dark ground, so the choice is
   visible before you commit to it. The team skins use their two real colours. */
.sw-house     { background: linear-gradient(135deg, #B8945F 50%, #2B2724 50%); }
.sw-desert    { background: linear-gradient(135deg, #BE6C36 50%, #14110E 50%); }
.sw-storybook { background: linear-gradient(135deg, #E08A3C 50%, #241A12 50%); }
.sw-heirloom  { background: linear-gradient(135deg, #A5854A 50%, #10192E 50%); }
.sw-woodland  { background: linear-gradient(135deg, #6F8A54 50%, #1A211A 50%); }
.sw-asu       { background: linear-gradient(135deg, #8C1D40 50%, #FFC627 50%); }
.sw-boise     { background: linear-gradient(135deg, #0033A0 50%, #D64309 50%); }
.sw-cap       { background: linear-gradient(135deg, #B22234 50%, #1B2A4A 50%); }
.row-check { display: flex; align-items: center; gap: 9px; font-size: .85rem; }
.row-check input { width: 18px; height: 18px; accent-color: var(--accent); }
.quiet-row { display: flex; gap: 12px; }
.quiet-row label { display: flex; flex-direction: column; gap: 3px; }

@media (prefers-reduced-motion: reduce) {
  .shake { animation: none; }
  .toast { transition: none; }
}
