/* Jobs calendar — day/week time-grid + month grid. Custom, no JS calendar lib.
   Reuses the app's navy/gold palette via the :root vars defined in crm.css. */

/* position: relative — the popover positions absolutely against THIS box;
   without it the JS's wrap-relative coordinates land far from the block. */
.cal-wrap { margin: 0 0 32px; position: relative; }

/* ── toolbar ─────────────────────────────────────────────────────────── */
.cal-toolbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 0 0 14px;
}
.cal-nav { display: flex; gap: 4px; align-items: center; }
.cal-nav a {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 34px; height: 34px; padding: 0 10px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--card);
  color: var(--teal); text-decoration: none; font-size: 14px; line-height: 1;
}
.cal-nav a:hover { background: #f6f6f1; }
.cal-title { font-size: 18px; font-weight: 700; color: var(--navy); margin: 0 6px; }
.cal-views { display: flex; gap: 4px; margin-left: auto; }
.cal-views a {
  text-decoration: none; padding: 6px 14px; border-radius: 999px; font-size: 13.5px;
  color: var(--teal); border: 1px solid var(--line); background: var(--card);
}
.cal-views a.active { background: var(--navy); color: #fff; border-color: var(--navy); }

/* ── legend ──────────────────────────────────────────────────────────── */
.cal-legend { display: flex; gap: 14px; flex-wrap: wrap; margin: 0 0 12px; font-size: 12px; color: var(--muted); }
.cal-legend span { display: inline-flex; align-items: center; gap: 5px; }
.cal-legend i { width: 12px; height: 12px; border-radius: 3px; display: inline-block; }
.cal-legend .li-planned { background: var(--blue); }
.cal-legend .li-done { background: var(--green); }
.cal-legend .li-canceled { background: var(--grey); }
.cal-legend .cal-hint { color: var(--muted); font-style: italic; margin-left: auto; }

/* ── time-grid (day & week) ──────────────────────────────────────────── */
.cal-grid {
  background: var(--card); border: 1px solid var(--line); border-radius: 10px;
  overflow: hidden;
}

/* The header, the all-day strip and the body below are three SEPARATE grids that
   have to line up column-for-column, so all three repeat the same track list —
   and every one of them says minmax(0, 1fr), never a bare 1fr.
   `1fr` is shorthand for minmax(auto, 1fr), and that auto floor is the track's
   MIN-CONTENT width. An all-day chip sets white-space: nowrap, so its min-content
   is the entire task name: one long name widened its own track in the all-day
   grid alone, that day's column stopped lining up with the same day in the header
   and body, and the chip visibly ran across the neighbouring days. The 0 floor
   lets the track stay a true 1/7th and hands the overflow to the chip's own
   text-overflow: ellipsis, which is what is meant to absorb it. */

/* The vertical lines between days are a step darker than --line: the horizontal
   hour lines and the ribbon washes both lean on --line's lightness, and once
   every day carried ribbons the day boundaries sank to the same weight as
   everything else — the week read as one striped wall. Day edges are structure;
   they outrank texture. */
.cal-grid { --cal-daysep: #c8c8bc; }

/* day header row: a gutter column then one column per day */
.cal-dayhead {
  display: grid;
  grid-template-columns: var(--cal-gutter, 56px) repeat(var(--cal-cols, 7), minmax(0, 1fr));
  border-bottom: 1px solid var(--line);
  background: var(--paper);
}
.cal-dayhead .cal-gutter-cell { border-right: 1px solid var(--cal-daysep); }
.cal-dayhead .cal-dayhead-cell {
  padding: 6px 8px; text-align: center; font-size: 12.5px; color: var(--muted);
  border-right: 1px solid var(--cal-daysep);
}
.cal-dayhead .cal-dayhead-cell:last-child { border-right: 0; }
.cal-dayhead .cal-dayhead-cell.is-weekend { background: #f6f6f1; }
.cal-dayhead .cal-dayhead-cell.is-today { background: #fdf7ec; color: var(--navy); font-weight: 700; }
.cal-dayhead .dh-dow { font-weight: 600; color: var(--text); text-transform: uppercase; letter-spacing: .06em; font-size: 11px; }
.cal-dayhead .dh-date { font-size: 11px; }

/* all-day / untimed strip, mirrors the column layout */
.cal-allday {
  display: grid;
  grid-template-columns: var(--cal-gutter, 56px) repeat(var(--cal-cols, 7), minmax(0, 1fr));
  border-bottom: 1px solid var(--line);
  min-height: 26px;
}
.cal-allday .cal-gutter-cell {
  border-right: 1px solid var(--cal-daysep); font-size: 9px; color: var(--muted);
  font-weight: 600; letter-spacing: .04em; text-transform: uppercase; white-space: nowrap;
  display: flex; align-items: center; justify-content: flex-end; padding: 0 6px;
}
/* The strip lays a day's chips out as side-by-side LANES, not a stack: each chip
   is the cap of the ribbon its .cal-band continues below, so the chips must
   divide the column exactly the way the bands do — equal flex lanes, no gap, no
   side padding (the body column has none either, and 3px of it was enough to
   knock every spine out of line with its band). */
.cal-allday .cal-allday-col {
  border-right: 1px solid var(--cal-daysep); padding: 3px 4px 0; min-height: 26px;
  display: flex; align-items: stretch;
}
.cal-allday .cal-allday-col:last-child { border-right: 0; }
.cal-allday .cal-allday-col.is-weekend { background: #f6f6f1; }
.cal-allday .cal-allday-col.is-today { background: #fdf7ec55; }

/* the scrolling body: gutter + day columns share the same row template */
.cal-body {
  display: grid;
  grid-template-columns: var(--cal-gutter, 56px) repeat(var(--cal-cols, 7), minmax(0, 1fr));
  position: relative;
}
.cal-hours {
  display: grid;
  grid-template-rows: repeat(var(--cal-rows, 11), var(--cal-rowh, 48px));
  border-right: 1px solid var(--cal-daysep);
}
.cal-hour-label {
  font-size: 11px; color: var(--muted); text-align: right; padding: 0 6px;
  transform: translateY(-7px); /* sit the label on the hour line */
}
.cal-col {
  position: relative;
  border-right: 1px solid var(--cal-daysep);
  display: grid;
  grid-template-rows: repeat(var(--cal-rows, 11), var(--cal-rowh, 48px));
}
.cal-col:last-child { border-right: 0; }
.cal-col.is-weekend { background: #f6f6f1; }
.cal-col.is-today { background: #fdf7ec33; }
/* empty-slot affordance: the grid cell reads as clickable to add a job */
.cal-col, .cal-allday-col, .cal-month-cell { cursor: cell; }
/* faint hour lines */
.cal-col .cal-slot { border-bottom: 1px solid var(--line); }
.cal-col .cal-slot:last-child { border-bottom: 0; }

/* An all-day task is ONE object: the chip in the strip is its cap, this band is
   its tail — a ribbon hanging from the cap to the bottom of the grid. What makes
   them read as one thing: the cap and the band share a lane (same left/width, by
   construction — see .cal-allday-col), share one unbroken 3px spine crossing the
   strip border, and the cap's pale fill continues as the wash. The task's name
   runs vertically down the wash (.band-title), so with five ribbons the day
   reads as full AND each stripe still says which work it is — the caps alone go
   too narrow to read at that point. The whole ribbon IS the task to the pointer
   too: clicking anywhere on it opens the task's popover and hovering it lights
   it (.is-hot), exactly like its cap — anything else would break the "one
   object" promise the visuals make. Ribbons sit behind the timed blocks, which
   keep their own clicks. DELIBERATE TRADE-OFF: the lanes tile the whole
   column, so a day with any all-day work has no empty surface left —
   click-to-add there survives only in the 4px day gutters; add to such a day
   from the month view or the Jobs page. Ribbon-free days keep click-to-add
   everywhere.
   The wash is the state colour at low alpha rather than the pale --*-bg tokens:
   those are tuned to sit inside a bordered block, and spread over a whole empty
   column they vanished — the day has to look loaded from across the week. */
/* The ribbons live in a wrapper inset from the day's side edges: a few px of
   bare column between one day's washes and the next day's is what keeps seven
   fully-ribboned days reading as seven days instead of one striped wall. The
   all-day strip pads its caps by the same 4px, so cap and band stay
   lane-aligned. The wrapper itself takes no pointer events (any bare sliver of
   it stays click-to-add); the bands inside re-enable them — each ribbon is its
   task's click target. */
.cal-ribbons { position: absolute; top: 0; bottom: 0; left: 4px; right: 4px; z-index: 0; pointer-events: none; }
.cal-band {
  position: absolute; top: 0; bottom: 0; z-index: 0;
  pointer-events: auto; /* re-enabled inside the hands-off .cal-ribbons wrapper */
  cursor: pointer;
  overflow: hidden;
  background: rgba(30, 90, 102, .12); border-left: 3px solid var(--teal);
}
.cal-band.state-planned { border-left-color: var(--blue); background: rgba(58, 110, 165, .13); }
.cal-band.state-done { border-left-color: var(--green); background: rgba(79, 122, 74, .13); }
.cal-band.state-canceled { border-left-color: var(--grey); background: rgba(154, 160, 166, .12); }

/* The task's name reading down the ribbon. vertical-lr keeps the text column at
   the lane's left edge, tight against the spine it belongs to. Constrained
   height + nowrap so a long name ellipsizes down the column instead of clipping
   mid-letter. */
.cal-band .band-title {
  display: block; writing-mode: vertical-lr;
  /* Stop at a uniform depth well short of the grid bottom: a full-height name
     kept resurfacing as word fragments in the gaps between timed blocks. */
  max-height: min(300px, calc(100% - 14px)); margin: 8px 0 0 3px;
  font-size: 10.5px; font-weight: 600; letter-spacing: .03em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  color: var(--teal); opacity: .8;
  /* Fade the tail out rather than cutting it: a timed block often interrupts
     the name mid-word, and a soft fade makes any cut point look deliberate.
     (Browsers without mask support keep the ellipsis above.) */
  -webkit-mask-image: linear-gradient(to bottom, #000 72%, transparent);
  mask-image: linear-gradient(to bottom, #000 72%, transparent);
}
.cal-band.state-planned .band-title { color: var(--blue); }
.cal-band.state-done .band-title { color: var(--green); }
.cal-band.state-canceled .band-title { color: var(--grey); text-decoration: line-through; }

/* Hovering the cap lights the whole ribbon — the moment the two glow together,
   their being one object stops needing explanation. */
.cal-band.is-hot { background: rgba(30, 90, 102, .22); }
.cal-band.is-hot.state-planned { background: rgba(58, 110, 165, .22); }
.cal-band.is-hot.state-done { background: rgba(79, 122, 74, .22); }
.cal-band.is-hot.state-canceled { background: rgba(154, 160, 166, .2); }

/* a job block: absolutely positioned over the column via inline top/height/left/width */
.cal-event {
  position: absolute; z-index: 2; /* above the all-day bands */
  border-radius: 6px; padding: 3px 6px; overflow: hidden;
  font-size: 11.5px; line-height: 1.25; cursor: pointer;
  border-left: 3px solid var(--teal); background: #e7eef0; color: var(--text);
  box-shadow: 0 1px 2px rgba(0,0,0,.06);
  user-select: none;
}
.cal-event:hover { filter: brightness(0.97); box-shadow: 0 2px 6px rgba(0,0,0,.12); z-index: 5; }
.cal-event .ev-time { font-weight: 700; font-size: 10.5px; display: block; }
.cal-event .ev-title { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-event .ev-sub { color: var(--muted); font-size: 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* state styling */
.cal-event.state-planned { border-left-color: var(--blue); background: var(--blue-bg); }
.cal-event.state-done { border-left-color: var(--green); background: var(--green-bg); }
.cal-event.state-canceled { border-left-color: var(--grey); background: var(--grey-bg); color: var(--muted); }
.cal-event.state-canceled .ev-title { text-decoration: line-through; }
/* Past blocks dim by DESATURATION, not opacity — all-day ribbons (and their
   vertical names) now live behind the blocks, and an opacity-faded block let
   that text ghost through its own label. The hover rule composes the two
   filters by hand: is-past and :hover tie on specificity, so whichever is
   declared later would otherwise silently drop the other's filter. */
.cal-event.is-past { filter: grayscale(.45); }
.cal-event.is-past:hover { filter: grayscale(.45) brightness(0.97); }

/* small chip used in all-day strip + month cells */
.cal-chip {
  position: relative;
  display: block; font-size: 11px; padding: 1px 6px; border-radius: 5px;
  border-left: 3px solid var(--teal); background: #e7eef0; color: var(--text);
  cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cal-chip.state-planned { border-left-color: var(--blue); background: var(--blue-bg); }
.cal-chip.state-done { border-left-color: var(--green); background: var(--green-bg); }
.cal-chip.state-canceled { border-left-color: var(--grey); background: var(--grey-bg); color: var(--muted); text-decoration: line-through; }

/* In the all-day strip (only — month cells keep stacked chips) a chip is the CAP
   of its ribbon: an equal flex lane over its band, squared off at the bottom so
   it pours into the wash below, its 3px spine continuing as the band's.
   container-type makes each cap measure its own lane so the name can bow out
   (via the @container rule) when the lane is too narrow to say anything — the
   vertical .band-title below carries the name from there. */
.cal-allday .cal-chip {
  flex: 1 1 0; min-width: 0;
  display: flex; align-items: center;
  border-radius: 5px 5px 0 0;
  container-type: inline-size;
}
.cal-allday .cal-chip .chip-name {
  min-width: 0; flex: 1 1 auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@container (max-width: 54px) {
  .cal-allday .cal-chip .chip-name { display: none; }
}

/* "day N of M" badge placement for a multi-day job (2/3 = day two of three);
   the .daybadge base box itself lives in crm.css, shared with the jobs list.
   On a block/chip: pinned to the top-right corner (a positioned ancestor) */
.ev-daybadge { position: absolute; top: 2px; right: 3px; z-index: 2; pointer-events: none; }
/* keep the block/chip text from sliding under the corner badge */
.cal-event:has(.ev-daybadge) .ev-time { padding-right: 24px; }
.cal-chip:has(.ev-daybadge) { padding-right: 22px; }
/* in the popover: inline after the date */
.pop-daybadge { display: inline-block; vertical-align: middle; margin-left: 5px; }
.pop-daybadge[hidden] { display: none; }

/* the "now" line */
.cal-now {
  position: absolute; left: 0; right: 0; height: 0;
  border-top: 2px solid var(--red); z-index: 6; pointer-events: none;
}
.cal-now::before {
  content: ""; position: absolute; left: -4px; top: -4px;
  width: 7px; height: 7px; border-radius: 50%; background: var(--red);
}

/* drag-drop affordances */
.cal-event.dragging, .cal-chip.dragging { opacity: .55; z-index: 20; }
.cal-col.drop-target,
.cal-allday-col.drop-target,
.cal-month-cell.drop-target { background: #fdf7ec88; outline: 2px dashed var(--accent); outline-offset: -2px; }
/* chips are draggable to another day (all-day strip + month view) */
.cal-allday-col .cal-chip[draggable="true"],
.cal-month .cal-chip[draggable="true"] { cursor: grab; }
/* a failed autosave (reschedule, day move, or status change) flashes red */
.cal-event--error { outline: 2px solid var(--red) !important; outline-offset: -1px; }
/* Red dot marking the dragged block's top-left corner — the day/time it lands on. */
.cal-drop-dot {
  position: fixed; width: 13px; height: 13px; margin: -7px 0 0 -7px;
  border-radius: 50%; background: var(--red);
  box-shadow: 0 0 0 3px rgba(255,255,255,.7), 0 0 7px rgba(211,47,47,.7);
  pointer-events: none; z-index: 1000;
}

/* ── month grid ──────────────────────────────────────────────────────── */
/* minmax(0, 1fr) for the same reason as the time-grid above — here it bit harder,
   because the chips and the weekday headers share one grid: long chip names grew
   Mon–Thu and crushed Fri/Sat/Sun to ~35px, where overflow: hidden then clipped
   them off the calendar entirely. */
.cal-month { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); background: var(--card);
  border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.cal-month .cal-month-dow {
  padding: 6px 8px; text-align: center; font-size: 12px; font-weight: 600;
  color: var(--muted); background: var(--paper); border-bottom: 1px solid var(--line);
  border-right: 1px solid var(--line);
}
.cal-month .cal-month-dow:nth-child(7) { border-right: 0; }
.cal-month .cal-month-cell {
  min-height: 108px; padding: 4px 5px; border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line); display: flex; flex-direction: column; gap: 2px;
}
.cal-month .cal-month-cell:nth-child(7n) { border-right: 0; }
.cal-month .cal-month-cell.is-other { background: #f6f6f1; }
.cal-month .cal-month-cell.is-today .mc-date { background: var(--navy); color: #fff; border-radius: 50%; }
.cal-month .mc-date {
  font-size: 12px; color: var(--text); align-self: flex-end;
  width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center;
}
.cal-month .mc-more { font-size: 11px; color: var(--muted); padding: 0 4px; }
.cal-month .mc-more a { color: var(--teal); text-decoration: none; }

/* ── popover ─────────────────────────────────────────────────────────── */
.cal-popover {
  position: absolute; z-index: 50; width: 270px; max-width: 90vw;
  background: var(--card); border: 1px solid var(--line); border-top: 3px solid var(--accent);
  border-radius: 10px; box-shadow: 0 8px 28px rgba(0,0,0,.18); padding: 12px 14px;
  font-size: 13px;
}
.cal-popover[hidden] { display: none; }
.cal-popover .pop-title { font-weight: 700; color: var(--navy); margin: 0 0 2px; font-size: 14px; }
/* the interactive status pills: dim until active, the current state lit up */
.cal-popover .pop-state-set { display: inline-flex; gap: 4px; }
/* while a status save is in flight the pills lock + dim — no change shows until
   the backend confirms it */
.cal-popover .pop-state-set.is-saving { opacity: .5; pointer-events: none; }
.pop-state-btn {
  font-size: 10px; text-transform: uppercase; letter-spacing: .3px; font-weight: 700;
  border: 1px solid var(--line); background: var(--card); color: var(--muted);
  border-radius: 999px; padding: 2px 9px; cursor: pointer; line-height: 1.5;
}
.pop-state-btn:hover { background: #f6f6f1; }
.pop-state-btn.is-active.state-planned { background: var(--blue-bg); color: var(--blue); border-color: var(--blue); }
.pop-state-btn.is-active.state-done { background: var(--green-bg); color: var(--green); border-color: var(--green); }
.pop-state-btn.is-active.state-canceled { background: var(--grey-bg); color: var(--muted); border-color: var(--grey); }
/* the attention flag as a pill row, mirroring the status pills: muted until
   active, the current level lit in its colour (urgent orange, problematic red) */
.cal-popover .pop-attn-row { display: flex; align-items: center; margin: 0 0 8px; }
.cal-popover .pop-attn-set { display: inline-flex; gap: 4px; }
.cal-popover .pop-attn-set.is-saving { opacity: .5; pointer-events: none; }
.pop-attn-btn {
  font-size: 10px; text-transform: uppercase; letter-spacing: .3px; font-weight: 700;
  border: 1px solid var(--line); background: var(--card); color: var(--muted);
  border-radius: 999px; padding: 2px 9px; cursor: pointer; line-height: 1.5;
}
.pop-attn-btn:hover { background: #f6f6f1; }
.pop-attn-btn.is-active[data-attn="normal"] { background: var(--grey-bg); color: var(--muted); border-color: var(--grey); }
.pop-attn-btn.is-active[data-attn="urgent"] { background: #fdf1e6; color: var(--orange); border-color: var(--orange); }
.pop-attn-btn.is-active[data-attn="problematic"] { background: var(--red-bg); color: var(--red); border-color: var(--red); }

.cal-popover dl { display: grid; grid-template-columns: max-content 1fr; gap: 3px 12px; margin: 8px 0; align-items: center; }
/* dt = label species (matches the app-wide dt rule; restated because this
   file's older rule used to override it). */
.cal-popover dt { color: var(--muted); font-size: 10px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
.cal-popover dt[hidden] { display: none; }
.cal-popover dd { margin: 0; font-size: 12.5px; }
.cal-popover dd[hidden] { display: none; }
/* compact edit inputs sitting in the dl's value column */
.cal-popover .pop-edit { display: flex; align-items: center; gap: 5px; }
.cal-popover .pop-num, .cal-popover .pop-time-input {
  border: 1px solid var(--line); border-radius: 6px; background: var(--card);
  color: var(--text); font-size: 12.5px; padding: 2px 6px; line-height: 1.4;
}
.cal-popover .pop-time-input { width: 52px; text-align: center; }
.cal-popover .pop-num { width: 66px; }
.cal-popover .pop-num:focus, .cal-popover .pop-time-input:focus {
  outline: none; border-color: var(--teal); box-shadow: 0 0 0 2px rgba(30,90,102,.12);
}
.cal-popover .pop-time-input.field-invalid, .cal-popover .pop-num.field-invalid {
  border-color: var(--red); box-shadow: 0 0 0 2px var(--red-bg);
}
.cal-popover .pop-dash { color: var(--muted); }
.cal-popover .pop-unit { color: var(--muted); font-size: 11px; }
.cal-popover .pop-labour { font-weight: 700; color: var(--navy); }
.cal-popover .pop-desc { margin: 6px 0; color: var(--text); }
.cal-popover .pop-actions { display: flex; justify-content: space-between; align-items: center; margin-top: 8px; }
.cal-popover .pop-close { background: none; border: none; color: var(--muted); cursor: pointer; font-size: 18px; line-height: 1; padding: 0; }
.cal-popover .pop-open { color: var(--teal); text-decoration: none; font-weight: 600; }

/* ── click-to-add popover ────────────────────────────────────────────── */
.cal-newpop {
  position: absolute; z-index: 55; width: 240px; max-width: 90vw;
  background: var(--card); border: 1px solid var(--line); border-top: 3px solid var(--accent);
  border-radius: 10px; box-shadow: 0 8px 28px rgba(0,0,0,.18); padding: 12px 14px;
  font-size: 13px; cursor: auto;
}
.cal-newpop[hidden] { display: none; }
.cal-newpop .np-title { font-weight: 700; color: var(--navy); margin: 0 0 2px; font-size: 14px; }
.cal-newpop .np-when { color: var(--muted); font-size: 12px; margin: 0 0 8px; }
.cal-newpop .np-label { display: block; font-size: 10.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.cal-newpop .np-label select {
  display: block; width: 100%; margin-top: 3px; padding: 5px 6px;
  border: 1px solid var(--line); border-radius: 6px; background: var(--card); font-size: 13px;
  text-transform: none; letter-spacing: normal; font-weight: 400;
}
.cal-newpop .np-note { color: var(--red); font-size: 11.5px; margin: 6px 0 0; }
.cal-newpop .np-note[hidden] { display: none; }
.cal-newpop .np-actions { display: flex; gap: 6px; margin-top: 10px; }

.cal-empty { color: var(--muted); font-size: 13px; padding: 16px; }

@media (max-width: 760px) {
  .cal-views { margin-left: 0; }
  .cal-month .cal-month-cell { min-height: 72px; }
}
