/* css/calendar.css
 *
 * Month and week grids, their density modes, and the slot composer.
 */

/* ---- month ------------------------------------------------------------- */
/* The month grid fills the height it is given instead of stopping at a fixed
   6 × 108px and leaving the rest of the page blank. On a tall window that was
   200-300px of unused space directly under the grid while cells were still
   truncating their content to "+N". A column flex chain — shell → scroller →
   grid — lets the rows share whatever is actually available; `min-height: 0`
   at each link is what allows them to shrink below content height rather than
   overflowing the shell. */
.calshell {
  background: var(--canvas); border-radius: var(--radius);
  box-shadow: var(--shadow); overflow: hidden;
  display: flex; flex-direction: column; min-height: 0;
}
/* Only the MONTH grid stretches. The week view's own scroller sizes itself
   from the hour band and must not be pulled taller.
   The height is `100dvh` minus the chrome, NOT `flex: 1` on the shell: there
   is an unclassed, `display: block` view wrapper between `.calshell` and
   `.mainscroll`, so the flex chain from the scroller never reaches this
   element and the shell simply grew to its content. Nor `height: 100%` up that
   wrapper — that made the page itself overflow without bounding the shell.
   186px is measured, not guessed: the app bar, the add bar and the scroller's
   padding come to exactly that across the sizes tested. `dvh` so a mobile URL
   bar sliding away does not leave the grid overhanging. */
body.view-month .calshell { max-height: calc(100dvh - 186px); }
/* No `min-height` on the shell: the floor belongs to the grid tracks above,
   where it can differ per mode. A single shell floor sized for the titles mode
   forced the half-height bars and dots modes taller than their content. */
body.view-month .calscroll { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
/* The 108px floor is for the SHORT-window case, where the grid scrolls. Once
   the rows are dividing a bounded height it has to go, or six of them re-impose
   648px and push the grid off the page again. */
body.view-month .mgrid .cell { min-height: 0; }
/* `1fr` is `minmax(auto, 1fr)`, and that `auto` floor is the whole problem:
   a row containing a six-chip cell claims its full content height and the grid
   grows past the viewport instead of clipping. `minmax(0, 1fr)` drops the
   floor so the six rows divide exactly the height available, and each cell
   clips its own overflow. */
/* The floor is per-MODE and lives in the track, not on the cell: `minmax(0,…)`
   drops the automatic minimum, so a `min-height` on `.cell` no longer holds a
   row open. Restating it as the track's own minimum keeps the titles mode from
   collapsing while letting bars and dots stay deliberately half-height. */
body.view-month .mgrid { flex: 1 1 auto; min-height: 0; grid-auto-rows: minmax(108px, 1fr); }
body.view-month .calshell.mode-bars .mgrid,
body.view-month .calshell.mode-dots .mgrid { grid-auto-rows: minmax(62px, 1fr); }
.mhead { display: grid; grid-template-columns: repeat(7, 1fr); border-bottom: .5px solid var(--sep); }
.mhead div {
  padding: 7px 9px; font-size: 0.7857em; font-weight: 590; color: var(--text-2);
  text-transform: uppercase; letter-spacing: .04em; text-align: right;
}
.mhead div.we { color: var(--text-3); }

.mgrid { display: grid; grid-template-columns: repeat(7, 1fr); }
.cell {
  position: relative;   /* anchor for the "+N" counter */
  min-height: 108px; padding: 5px 6px 6px; overflow: hidden;
  border-right: .5px solid var(--sep-soft); border-bottom: .5px solid var(--sep-soft);
  display: flex; flex-direction: column; gap: 2px; min-width: 0;
  background: none; text-align: left; font: inherit; color: inherit;
  cursor: pointer; border-top: 0; border-left: 0; border-radius: 0; box-shadow: none;
}
.cell:hover { background: var(--fill); filter: none; }
.cell:nth-child(7n) { border-right: 0; }
.mgrid .cell:nth-last-child(-n+7) { border-bottom: 0; }
.cell.dim { background: var(--chrome); }
.cell.dim:hover { background: var(--chrome-2); }
.cell.dim .num { color: var(--text-3); }
.cell .num {
  font-size: 0.8929em; font-weight: 500; text-align: right; padding: 1px 2px 2px;
  font-variant-numeric: tabular-nums; align-self: flex-end;
}
/* Today needs to be findable in a 42-cell grid, not just a blue circle the
   eye has to hunt for. A faint wash on the whole cell does that without
   competing with the task chips inside it. */
.cell.now { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.cell.now:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.cell.now .num {
  background: var(--accent); color: var(--accent-ink); border-radius: 50%;
  width: 21px; height: 21px; display: grid; place-items: center;
  font-size: 0.8571em; padding: 0;
}
/* `--hl` is the task's raw highlight, set inline by the renderer; it is unset
   for a task with no colour, so the fallbacks below are what an uncoloured
   chip gets. The MIX happens here rather than in JS because the right amount
   of colour depends on what the chip is sitting on: the same tint that reads
   as a clear label on white is invisible on a dark canvas, and a fixed alpha
   baked into the markup cannot tell the two apart.
   26% in light is the point where the hue is unmistakable at 11px while black
   text still clears AA on every one of the 25 palette entries. */
.chip {
  /* Never squashed. In a flex column a chip is shrinkable by default, so a
     cell shorter than its contents compressed every chip toward zero height
     and painted a stack of unreadable 3px slivers instead of overflowing.
     Holding the height means the surplus is CLIPPED by the cell — a clean cut
     the "+N" counter already accounts for. */
  flex: 0 0 auto;
  font-size: 0.7857em; line-height: 1.3; padding: 2px 5px 2px 6px; border-radius: 4px;
  /* Two lines, then the ellipsis — not one. A month cell is ~110px of chip box
     and a chip is ~23px, so a day holding one task was spending 20% of the
     space it had on the title and leaving the other 80% blank while printing
     "Кофе с кор…". The wrap is worth more than the extra row it costs: a title
     the eye can read without hovering is the whole point of the titles mode.
     Clamped at 2 rather than left free, because a long title would otherwise
     eat a four-chip cell by itself and the day would read as emptier than it
     is. `-webkit-box` is the only clamp with real support; `line-clamp` is
     alongside it for the browsers that have taken the standard property.
     `break-word` is what keeps a single long unbroken token (a URL, a German
     compound) from pushing the chip wider than the cell instead of wrapping.
     `trimMonthCells` needs no arithmetic change for this: it already measures
     each chip's own `offsetHeight` against the box rather than assuming a
     fixed per-chip row, so a two-line chip simply counts as the taller box it
     is and the "+N" it computes stays true. */
  display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 2; line-clamp: 2;
  overflow: hidden; overflow-wrap: break-word;
  background: color-mix(in srgb, var(--hl, var(--hl-fallback, var(--text-3))) 26%, var(--canvas));
  border-left: 2.5px solid var(--hl, var(--hl-fallback, var(--text-3)));
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-force="light"]) .chip {
    /* A tint over a dark ground has to work harder before the hue registers,
       and the ink flips to the light end of the ramp. */
    background: color-mix(in srgb, var(--hl, var(--hl-fallback, var(--text-3))) 34%, var(--canvas));
  }
}
:root[data-force="dark"] .chip {
  background: color-mix(in srgb, var(--hl, var(--hl-fallback, var(--text-3))) 34%, var(--canvas));
}
/* Time reads as data, not as part of the title. Inside a tinted chip it has
   to stay legible against the fill, so it dims relative to the chip's own
   text rather than to the page. */
.chip i { font-style: normal; opacity: .62; font-variant-numeric: tabular-nums; }
/* The clamp above sets `display` on `.chip`, and an author `display` beats the
   UA sheet's `[hidden] { display: none }` — so the moment the chips became
   two-line boxes, every chip `trimMonthCells` hid went on painting. The cell
   then showed a chip clipped through the middle of its second line while the
   counter beside it claimed that chip was among the hidden ones. Restating the
   rule here puts `hidden` back in charge. */
.chip[hidden] { display: none; }

/* Density switcher sits next to the view segmented control. */
.segmented.dense button { padding: 5px 11px; font-size: 0.8929em; }

/* --- bars mode: one capsule per day, split between the day's colours ----- */
.daybar {
  display: flex; height: 4px; border-radius: 999px; overflow: hidden;
  margin: 2px 2px 0;
}
.daybar i { flex: 1 1 0; min-width: 0; }

/* --- dots mode ---------------------------------------------------------- */
.dots { display: flex; align-items: center; gap: 3px; margin-top: 2px; padding: 0 2px; flex-wrap: wrap; }
.dots .dot { width: 5px; height: 5px; border-radius: 50%; flex: 0 0 auto; }
.dots .gly { font-size: 0.7857em; line-height: 1; flex: 0 0 auto; }
.dots .over { font-size: 0.6786em; color: var(--text-3); font-variant-numeric: tabular-nums; }

/* Denser modes need far less room than titles do. Letting all three keep the
   108px cell would leave bars floating in an empty box. */
.calshell.mode-bars .cell, .calshell.mode-dots .cell { min-height: 62px; }
.calshell.mode-bars .num, .calshell.mode-dots .num { font-size: 0.9286em; }

/* Weekends read as the edge of the week, as on the phone. Declared BEFORE the
   today rule below, which must win: a weekend today was painting red-on-blue
   and the number disappeared into the circle. */
.cell.we .num { color: var(--danger); }
.cell.dim.we .num { color: color-mix(in srgb, var(--danger) 45%, transparent); }

/* Today's number sits on a filled accent disc, so it is always the inverse
   ink — whatever the weekday rules above decided. */
.cell.now .num, .cell.now.we .num, .cell.now.dim.we .num { color: var(--accent-ink); }
/* Finished work should not read as loud as work still to do — but it still has
   to be READABLE. `--text-3` over the done chip's own pale tint fell under the
   contrast floor and the chip read as an empty box, so the ink stays at
   `--text-2` and the step down is carried by opacity instead. The rule through
   the title goes with it: at this size a strikethrough on 11px text is a
   smear, and the greyed ink already says "done". */
/* Done keeps its hue — losing it entirely made a finished chip read as an
   empty box, which is what "не видно" was — but at roughly half strength, so
   open work stays the louder of the two. The ink steps down with it instead
   of being struck through: at 11px a rule through the title is a smear. */
.chip.done {
  background: color-mix(in srgb, var(--hl, var(--hl-fallback, var(--text-3))) 13%, var(--canvas));
  border-left-color: color-mix(in srgb, var(--hl, var(--hl-fallback, var(--sep))) 55%, var(--canvas));
  color: var(--text-2); text-decoration: none;
}
.chip.done i { color: var(--text-2); }
@media (prefers-color-scheme: dark) {
  :root:not([data-force="light"]) .chip.done {
    background: color-mix(in srgb, var(--hl, var(--hl-fallback, var(--text-3))) 18%, var(--canvas));
  }
}
:root[data-force="dark"] .chip.done {
  background: color-mix(in srgb, var(--hl, var(--hl-fallback, var(--text-3))) 18%, var(--canvas));
}
/* "+N" is pinned to the bottom of the cell rather than sitting after the last
   chip. Once the cell clips, the counter is exactly what gets cut off first —
   so a short window hid three chips AND the only sign that they existed. Held
   here it always survives the clip.
   `sticky` inside the cell's own scroll-less overflow keeps it in normal flow
   for tall cells (where it simply follows the chips) while sticking to the
   floor once the content is taller than the box. The background covers the
   chip it now overlaps. */
/* Reserved, not overlaid. `sticky` kept the counter visible but let it float
   over the chip beneath it, and a chip clipped mid-height still showed a
   sliver under it — two artefacts instead of one. An `order`-promoted flex
   item at the end of the column takes its own row: the chips get the space
   that is left, so whatever they overflow is cut cleanly ABOVE the counter and
   nothing is ever drawn behind it. */
/* The chips live in their own column so the count that FITS can be decided in
   CSS, and the counter sits under it as a sibling — never over a chip, never
   clipped with them. The column clips; the counter is outside it.  */
.cell .chips {
  display: flex; flex-direction: column; gap: 2px;
  /* `1 1 auto`: the box must GROW into the cell, not just shrink. With
     `0 1 auto` it sized to content and then collapsed under the counter,
     leaving cells showing nothing at all. */
  flex: 1 1 auto; min-height: 0; overflow: hidden; order: 1;
}
/* The counter sits under the chips and takes only the room it needs. It is
   `absolute` only when it would otherwise force the chip box to give up a
   whole row for a 14px line — see `trimMonthCells`, which decides how many
   chips fit against the box's height and lets this line share the last one's
   gap rather than displacing it. */
.cell .more {
  font-size: 0.75em; color: var(--text-2); padding: 1px 4px 0;
  order: 2; flex: 0 0 auto; line-height: 1.15;
}
/* The counter is written on every cell so the sticky floor exists before the
   count is known; it is only shown when something is actually hidden — either
   past MAX_CHIPS (the `hidden` attribute, set by the renderer) or past the
   cell's own height, which only CSS can know. */
.cell .more[hidden] { display: none; }

/* ---- week -------------------------------------------------------------- */
.wgrid { display: grid; grid-template-columns: 52px repeat(7, 1fr); }
/* A button now, so the day-name reset has to undo the app's button chrome —
   background, radius and shadow would otherwise turn the week header into a
   row of seven pills. */
.whead {
  padding: 8px 7px 7px; text-align: center;
  border-bottom: .5px solid var(--sep); border-right: .5px solid var(--sep-soft);
  background: none; box-shadow: none; border-radius: 0; color: inherit;
  font: inherit; display: block; width: 100%; cursor: pointer;
}
.whead:hover { background: var(--fill); filter: none; }
.whead:last-of-type { border-right: 0; }
.whead .d {
  font-size: 0.75em; font-weight: 590; color: var(--text-2);
  text-transform: uppercase; letter-spacing: .04em;
}
.whead .n {
  font-size: 1.3571em; font-weight: 500; letter-spacing: -.017em; margin-top: 1px;
  font-variant-numeric: tabular-nums;
}
.whead.now .n {
  background: var(--accent); color: var(--accent-ink); border-radius: 50%;
  width: 27px; height: 27px; display: grid; place-items: center; margin: 1px auto 0;
  font-size: 1.1429em;
}
.wgutter { border-right: .5px solid var(--sep-soft); border-bottom: .5px solid var(--sep); }
/* Untimed work has no row on the clock. It sits in a strip above the grid —
   visible, but never pinned to an hour it does not have. */
/* Capped and scrollable: a day with twelve untimed tasks must not push the
   hour grid off the screen, and every other column would inherit that height
   since they share a grid row. */
.wallday {
  /* No height cap and no scroller. Every earlier attempt here capped the strip
     at ~3 chips and let the rest scroll, which meant a busy day hid work
     behind a scrollbar the eye never finds — and a scrollbar inside a 3px-gap
     grid cell is barely operable anyway. The strip now grows to its content
     and the hour grid starts below it.
     The cost this was originally guarding against is real but small: all seven
     columns share one grid row, so the tallest day sets the height for the
     week. That is the correct trade — an all-day row is a handful of items in
     practice, and a week with twelve untimed tasks SHOULD look tall, rather
     than looking empty while hiding eleven of them. */
  border-right: .5px solid var(--sep-soft); border-bottom: .5px solid var(--sep);
  padding: 3px 3px 4px; display: flex; flex-direction: column; gap: 2px;
  min-height: 26px; min-width: 0;
  position: relative;   /* containing block for the .wopen backdrop */
}
/* The chips must stay above the backdrop that fills the cell behind them,
   or clicking a task would open the day instead of hitting the task. */
.wallday .chip { flex: 0 0 auto; text-align: left; box-shadow: none; cursor: pointer; position: relative; }
/* Hover deepens the chip's own colour instead of replacing it with a flat
   grey; a coloured chip that turns grey under the pointer loses the only
   thing distinguishing it from its neighbours. */
.wallday .chip:hover {
  filter: none;
  background: color-mix(in srgb, var(--hl, var(--hl-fallback, var(--text-3))) 38%, var(--canvas));
}

.wallday:last-of-type { border-right: 0; }
.wallday-lbl {
  border-right: .5px solid var(--sep-soft); border-bottom: .5px solid var(--sep);
  font-size: 0.6786em; color: var(--text-3); text-transform: uppercase;
  letter-spacing: .04em; padding: 5px 6px 0 0; text-align: right;
}
.whours { padding-top: 8px; border-right: .5px solid var(--sep-soft); }
/* Must equal BAND_PX — the labels are a parallel column to the band lines,
   and any drift slides the clock away from the rows it names. */
.hourlbl {
  height: 64px; font-size: 0.75em; color: var(--text-3); text-align: right;
  padding-right: 7px; transform: translateY(-6px); font-variant-numeric: tabular-nums;
}
/* Fills the column beneath the events, so empty space opens the day. z-index
   is deliberately absent: the events come later in source order and are
   positioned, so they already paint above it. */
.wopen {
  position: absolute; inset: 0; background: none; box-shadow: none;
  border: 0; border-radius: 0; padding: 0; width: 100%; cursor: pointer;
}
.wopen:hover { background: var(--fill); filter: none; }

/* One half-hour target. Invisible until pointed at — a grid showing 28 empty
   boxes per column would read as content rather than as space. */
.wslot {
  position: absolute; left: 0; right: 0; background: none; box-shadow: none;
  border: 0; border-radius: 0; padding: 0; cursor: pointer; width: 100%;
  display: block; overflow: hidden;
}
.wslot .plus {
  display: none; font-size: 0.7em; font-variant-numeric: tabular-nums;
  color: var(--accent); padding-left: 5px; line-height: 1.5;
}
.wslot:hover {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent);
  filter: none;
}
.wslot:hover .plus { display: block; }
/* Keyboard reach: the slots are tabindex="-1" (28 per column would swamp the
   tab order), so focus-visible only fires when one is focused directly. */
.wslot:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* The slot composer. Fixed-position backdrop so a click anywhere outside
   dismisses it, with the popover itself placed in viewport coordinates by
   openSlotComposer — the grid scrolls, so an absolutely-positioned popover
   inside it would drift away from its slot. */
.slotcompose { position: fixed; inset: 0; z-index: 45; background: transparent; }
.slotcompose .pop {
  position: fixed; width: 268px; background: var(--chrome);
  border-radius: 14px;
  box-shadow: 0 0 0 .5px color-mix(in srgb, var(--sep) 70%, transparent),
              0 16px 40px -8px rgba(0,20,40,.30);
  padding: 12px 13px 13px;
}
.slotcompose .pophead {
  display: flex; align-items: baseline; gap: 7px; margin-bottom: 8px;
}
.slotcompose .clock {
  font-weight: 660; font-variant-numeric: tabular-nums; font-size: 1.05em;
  color: var(--accent);
}
.slotcompose .on { font-size: 0.82em; color: var(--text-3); }
.slotcompose .popclose {
  margin-left: auto; background: none; box-shadow: none; color: var(--text-3);
  font-size: 1.3em; line-height: 1; padding: 0 5px; border-radius: 6px; cursor: pointer;
}
.slotcompose .popclose:hover { background: var(--fill); color: var(--text); filter: none; }
.slotcompose .poprow { display: flex; gap: 7px; }
.slotcompose input { flex: 1 1 auto; min-width: 0; font-size: 0.95em; padding: 7px 10px; }
.slotcompose .popadd { flex: none; }
/* ---- notes ----------------------------------------------------------
   Cards in a masonry-ish grid rather than rows: a note is a block of text
   with no time, no status and nothing to line up in columns, so the row
   layout the day view uses would waste most of the width on whitespace. */
