/* css/lasttime.css
 *
 * «Последний раз» — the cards, their category sections, and the two sheets.
 *
 * The card is built around ONE number. Everything else on it (the interval, the
 * due badge, the mark button) is subordinate to "how long has it been", because
 * that is the only question the section exists to answer — so that line gets the
 * display face and the size, and the rest sits at caption weight around it.
 */

.lasttime { padding: 4px 2px 20px; }

.ltbar {
  display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: center;
  margin-bottom: 14px;
}
.lthead { font-size: 1.05em; font-weight: 640; }
.ltnew {
  margin-left: auto; flex: none; font-size: 0.9em; padding: 7px 15px;
  border-radius: 999px; font-weight: 590;
}

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

.ltgroup + .ltgroup { margin-top: 22px; }
/* Sticky, so the section a long list is scrolled into stays named. The header
   is the only thing telling two identically-shaped cards apart. */
.ltgh {
  display: flex; align-items: center; gap: 7px;
  margin: 0 0 10px 2px; font-size: 0.78em; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase; color: var(--text-3);
  position: sticky; top: 0; z-index: 1;
  background: var(--canvas); padding: 4px 0;
}
.ltgh .c {
  margin-left: auto; font-variant-numeric: tabular-nums;
  letter-spacing: normal; opacity: .8;
}

/* `stretch`, not `start`: a card with no interval has one row fewer than its
   neighbours, and left to size itself it sits short with its mark button riding
   up out of line with the row. Stretching makes every card in a row the height
   of the tallest, and the card's own `margin-top: auto` on the button pins the
   action to the bottom edge — so the buttons line up across mixed rows instead
   of stepping. */
.ltgrid {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  align-items: stretch;
}

/* ---- the card -------------------------------------------------------- */

.ltcard {
  background: var(--chrome); border-radius: 18px; padding: 14px 15px 12px;
  box-shadow: var(--shadow); cursor: pointer; position: relative;
  display: flex; flex-direction: column; gap: 8px; text-align: left;
  transition: transform .18s cubic-bezier(.32,.72,0,1), box-shadow .18s ease;
}
/* The item's colour as a tint over the page's own canvas, exactly as a note
   card is filled — same `color-mix` against `--canvas` so it stays readable in
   both themes rather than being a saturated block with text on it. */
.ltcard[style*="--lc"] {
  background: color-mix(in srgb, var(--lc) var(--note-tint), var(--canvas));
  box-shadow: 0 0 0 .5px color-mix(in srgb, var(--lc) var(--note-edge), transparent),
              0 1px 2px rgba(0,0,0,.05);
}
.ltcard:hover { transform: translateY(-1px); box-shadow: var(--shadow-lg); }
.ltcard:active { transform: scale(.985); }
.ltcard:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ltcard.pending { opacity: .6; }
@media (prefers-reduced-motion: reduce) {
  .ltcard { transition: none; }
  .ltcard:hover, .ltcard:active { transform: none; }
}

.lttop { display: flex; align-items: flex-start; gap: 8px; }
.ltemoji { font-size: 1.15em; line-height: 1.2; flex: none; }
.lttitle {
  margin: 0; font-size: 0.98em; font-weight: 620; line-height: 1.3;
  overflow-wrap: anywhere;
}

/* The answer. Tabular figures so a grid of cards keeps its numbers on one
   optical column instead of jittering as the counts change width. */
.ltstat {
  font-family: var(--display); font-size: 1.25em; font-weight: 660;
  line-height: 1.15; font-variant-numeric: tabular-nums;
}
/* An overdue card states it in the danger colour ONCE, on the badge. Recolouring
   the big number too would leave the card with two red things competing, and the
   number is a fact ("42 дня назад") rather than a warning. */
.ltcard.due .ltdue.over { color: var(--danger); }

.ltmeta {
  display: flex; flex-wrap: wrap; gap: 6px 8px; align-items: center;
  font-size: 0.78em; color: var(--text-3);
}
.ltevery { font-variant-numeric: tabular-nums; }
.ltdue {
  margin-left: auto; font-variant-numeric: tabular-nums;
  padding: 2px 8px; border-radius: 999px;
  background: color-mix(in srgb, var(--text-3) 14%, transparent);
}
.ltdue.over {
  font-weight: 600; letter-spacing: .01em;
  background: color-mix(in srgb, var(--danger) 16%, transparent);
}

/* The primary action, so it is a filled pill rather than a link: marking is
   what the user comes to this list to do, and it must be reachable without
   opening the card first. */
.ltmark {
  margin-top: auto; width: 100%; cursor: pointer;
  font-size: 0.86em; font-weight: 590; padding: 8px 10px; border-radius: 12px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent); box-shadow: none;
}
.ltmark:hover { filter: none; background: color-mix(in srgb, var(--accent) 20%, transparent); }
.ltmark:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.ltempty { color: var(--text-3); padding: 26px 4px; text-align: center; }
.ltempty.small { padding: 14px 4px; font-size: 0.9em; }

/* ---- the sheets ------------------------------------------------------
 *
 * `.ltpane` is a `.pane` inside the shared `.taskedit` backdrop, so it already
 * carries the panel's surface, radius and dark-theme repoint. What it adds is
 * the note editor's COLUMN behaviour — fixed header, one scrolling body — which
 * lives on `.noteedit` selectors and so has to be restated rather than reused.
 * Narrower than the note sheet: this is a form and a log, not running prose.
 * -------------------------------------------------------------------- */
.taskedit .pane.ltpane {
  width: min(520px, 100%);
  padding: 0; border-radius: 20px;
  display: flex; flex-direction: column; overflow: hidden;
  max-height: 92vh;
  background: var(--canvas);
}
.ltpane .ne-bar {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: 10px; padding: 11px 14px; flex: none;
  border-bottom: .5px solid var(--sep-soft);
  background: color-mix(in srgb, var(--canvas) 82%, transparent);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
}
.ltpane .ne-bar .t {
  grid-column: 2; font-size: 0.95em; font-weight: 600; text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ltpane .ne-bar button {
  background: none; box-shadow: none; padding: 4px 2px; cursor: pointer;
  font-size: 0.95em; color: var(--accent); border-radius: 8px;
}
.ltpane .ne-bar button:hover { filter: none; opacity: .65; }
.ltpane .ne-bar .cancel { justify-self: start; grid-column: 1; }
.ltpane .ne-bar .done { justify-self: end; grid-column: 3; font-weight: 600; }
/* The one scroller. `min-height: 0` is what lets a flex item shrink below its
   content height — without it the overflow escapes the pane instead. */
.ltpane .ne-body {
  padding: 14px; display: flex; flex-direction: column; gap: 16px;
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
}
.ltpane .ne-body > * { flex: none; }

/* Grouped rows, 44px tall — the minimum touch target, and what makes a stack of
   them read as a list rather than as loose fields. */
.ltpane .ne-rows {
  background: var(--chrome); border-radius: 14px;
  box-shadow: 0 0 0 .5px var(--sep-soft); overflow: hidden;
}
.ltpane .ne-r {
  display: flex; align-items: center; gap: 12px; min-height: 44px;
  padding: 0 14px;
}
.ltpane .ne-r + .ne-r { border-top: .5px solid var(--sep-soft); }
.ltpane .ne-r .lbl { font-size: 0.94em; flex: none; }
.ltpane .ne-cap {
  margin: 0 0 7px 4px; font-size: 0.76em; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-3);
}
.ltpane .ne-hint { margin: -8px 4px 0; font-size: 0.82em; color: var(--text-3); }
.ltpane .ne-err { margin: 0 4px; font-size: 0.86em; color: var(--danger); min-height: 1.1em; }

/* Every field is reset and restyled. A bare input painting the platform's own
   bevel and focus ring is the single loudest tell that a sheet is a web form. */
.ltpane .lte-title, .ltpane .lte-emoji, .ltpane .lte-num,
.ltpane .ltd-date, .ltpane .ltd-note {
  background: none; border: 0; box-shadow: none; outline: none;
  font: inherit; font-size: 0.94em; color: var(--text);
  -webkit-appearance: none; appearance: none; border-radius: 8px;
}
.ltpane .lte-title, .ltpane .lte-emoji, .ltpane .lte-num {
  margin-left: auto; text-align: right; padding: 6px; min-width: 0;
}
.ltpane .lte-title { flex: 1 1 auto; }
.ltpane .lte-emoji { flex: none; width: 4.5em; font-size: 1.1em; }
.ltpane .lte-num { flex: none; width: 5.5em; font-variant-numeric: tabular-nums; }
.ltpane .lte-title:focus-visible, .ltpane .lte-emoji:focus-visible,
.ltpane .lte-num:focus-visible, .ltpane .ltd-date:focus-visible,
.ltpane .ltd-note:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* The select repeats the note editor's: platform arrow off, a drawn chevron on,
   right-aligned like every other value in a grouped row. */
.ltpane .ne-folder {
  margin-left: auto; flex: 0 1 auto; min-width: 0; max-width: 62%;
  background: none; border: 0; box-shadow: none; outline: none;
  -webkit-appearance: none; appearance: none;
  font: inherit; font-size: 0.94em; color: var(--text-3);
  text-align: right; text-align-last: right;
  padding: 6px 18px 6px 6px; cursor: pointer; border-radius: 8px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='11' viewBox='0 0 7 11'%3E%3Cpath d='M1.2 1.2 5.4 5.5 1.2 9.8' fill='none' stroke='%238e8e93' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 4px center;
}
.ltpane .ne-folder:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Round chips, the shape iOS uses wherever a colour is being PICKED rather than
   displayed. */
.ltsw-row {
  display: flex; flex-wrap: wrap; gap: 8px;
  background: var(--chrome); border-radius: 14px; padding: 12px;
  box-shadow: 0 0 0 .5px var(--sep-soft);
}
.ltsw {
  width: 26px; height: 26px; flex: none; border-radius: 50%;
  background: var(--sw); box-shadow: 0 0 0 .5px rgba(0,0,0,.14); cursor: pointer;
  padding: 0;
}
.ltsw:hover { filter: none; transform: scale(1.08); }
/* A ring OUTSIDE the chip, so the swatch itself is never covered by the mark
   that says it is chosen. */
.ltsw.on { box-shadow: 0 0 0 2px var(--canvas), 0 0 0 4px var(--accent); }
.ltsw:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* ---- the charts ------------------------------------------------------
 *
 * Both sit in the same panel shape as the grouped rows above them, so the sheet
 * reads as one stack of cards rather than as a form with pictures stuck to it.
 *
 * `--lc` is the item's own colour, set on the pane. It is the MAGNITUDE channel
 * for the heatmap (one hue, four opacities) and the fallback for bars that have
 * no interval to be judged against. Where a bar IS judged, the colour means
 * good/late/over and comes from the status tokens instead — the one thing on
 * these charts that is about state rather than about quantity.
 * -------------------------------------------------------------------- */

.ltchart { display: flex; flex-direction: column; }
.lthm, .ltbars {
  background: var(--chrome); border-radius: 14px; padding: 12px;
  box-shadow: 0 0 0 .5px var(--sep-soft);
}

/* The strip scrolls rather than squeezing: 52 columns inside a 520px sheet
   would put the cells below a legible size, and a heatmap whose cells are
   smaller than the gaps between them stops reading as a field. */
/* `scrollbar-width: none` — the strip is a picture, and a scrollbar drawn
   through the middle of the panel reads as a rule across the data. It still
   scrolls by drag, wheel and keyboard. */
/* `--cell` is a LENGTH, set inline by the renderer.
 *
 * It was briefly a percentage expression here — `min(16px, max(9px, (100% - …)
 * / var(--w)))` — which is wrong in a way worth recording: a `%` inside a
 * custom property is not resolved where it is declared, it is substituted as
 * text and resolved against whatever box finally consumes it. Feeding the same
 * variable to `grid-auto-columns` and `grid-template-rows` therefore resolved
 * it against the width for one and the HEIGHT for the other, and the strip
 * collapsed to two rows. A number computed once, in JS, cannot do that. */
/* Centred when it is narrower than the panel — a 12-week strip cannot fill the
   width at any cell size that still reads as a heatmap, and left-aligned it
   looks like a block that failed to load.
   `justify-content: safe center` rather than plain centring: when the strip IS
   wider than the panel (52 weeks), plain `center` overflows equally in both
   directions and puts the first columns out of reach above the scroll origin.
   `safe` falls back to flex-start in exactly that case. */
.lthm-scroll {
  display: flex; justify-content: safe center;
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none; -ms-overflow-style: none;
}
/* One block, so the month labels stay over the columns they name. */
.lthm-inner { flex: none; }
.lthm-scroll::-webkit-scrollbar { display: none; }

/* Column-major: SEVEN explicit rows and nothing else. Declaring the columns as
   well makes the two axes fight — the cells fill the declared columns
   row-by-row and the whole strip collapses to seven wide. The column count
   comes from `grid-auto-columns` as the cells flow.

   `--cell` is computed from the week count so a 12-week strip FILLS the panel
   instead of sitting as a small block against the left edge, while a 52-week
   one falls back to a legible floor and scrolls. `min()` picks whichever of the
   two applies without a media query or a second class. */
.lthm-grid {
  display: grid; gap: 3px;
  grid-template-rows: repeat(7, var(--cell));
  grid-auto-flow: column; grid-auto-columns: var(--cell);
  width: max-content;
}
/* The month strip uses the SAME track geometry so a label lines up with the
   week it names, but each label is allowed to overhang the ones after it —
   "сентябрь" is far wider than the 11px column it belongs to. Overlap is
   prevented in the markup instead, which skips a label too close to the last
   one drawn. */
.lthm-months {
  display: grid; gap: 3px;
  grid-auto-flow: column; grid-auto-columns: var(--cell);
  width: max-content;
  margin-bottom: 5px; font-size: 0.62em; color: var(--text-3);
  letter-spacing: .02em; white-space: nowrap;
}
.lthm-months span { overflow: visible; }

/* No width/height: the cell fills the track the grid gave it, so the size lives
   in ONE place (`--cell`) instead of being restated here and drifting. The key
   swatches below are outside the grid and set their own. */
.lth-c {
  border-radius: 3px; display: block; min-width: 0;
  background: color-mix(in srgb, var(--text-3) 14%, transparent);
}
.lthm-key .lth-c { width: 11px; height: 11px; }
/* The ramp. Four steps only — past three entries in a day the eye stops reading
   depth, which is exactly where the phone stops too.

   Mixed against `--chrome`, the panel these sit on, rather than against
   `transparent`. A transparent mix composites over whatever is behind and the
   bottom step came out near-invisible on a dark panel — the one step that MUST
   be legible, since a single entry is the common case. Mixing against the known
   surface makes the lightest step a definite colour in both themes. */
.lth-c[data-lv="1"] { background: color-mix(in srgb, var(--lc, var(--accent)) 55%, var(--chrome)); }
.lth-c[data-lv="2"] { background: color-mix(in srgb, var(--lc, var(--accent)) 78%, var(--chrome)); }
.lth-c[data-lv="3"] { background: var(--lc, var(--accent)); }
/* Days that have not happened yet are fainter than an empty past day, so the
   trailing edge of the current week does not read as a run of misses. */
.lth-c.fut { background: color-mix(in srgb, var(--text-3) 6%, transparent); }
/* Today is ringed, not filled: it must be findable without claiming an entry
   the user has not made. */
.lth-c.now { box-shadow: 0 0 0 1.5px var(--text-2); }

.lthm-key {
  display: flex; align-items: center; gap: 4px; margin-top: 9px;
  font-size: 0.68em; color: var(--text-3);
}
.lthm-key span:first-child { margin-right: 2px; }
.lthm-key span:last-child { margin-left: 2px; }

/* One uniformly-scaled SVG. `height: auto` keeps the aspect the viewBox
   declares, so the 24-unit bar cap and the 9px label sizes stay in the
   proportion they were drawn in at every panel width. */
.ltbars svg { display: block; width: 100%; height: auto; }
.ltb path { fill: color-mix(in srgb, var(--lc, var(--accent)) 70%, transparent); }
/* Status, not identity: how the gap came out against the interval the user
   asked for. Amber is local to this file — the app's tokens have --ok and
   --danger but no warning step, and one colour is not worth a global token. */
.ltb.ok path   { fill: color-mix(in srgb, var(--ok) 85%, transparent); }
.ltb.warn path { fill: #f5a524; }
.ltb.over path { fill: color-mix(in srgb, var(--danger) 85%, transparent); }
/* The amber needs its own dark step for the same reason --ok and --danger have
   one: the light value goes muddy against a near-black panel. `data-force` is
   the app's explicit theme switch and must win over the system preference in
   BOTH directions, exactly as tokens.css orders them. */
@media (prefers-color-scheme: dark) { .ltb.warn path { fill: #ffb340; } }
:root[data-force="dark"] .ltb.warn path { fill: #ffb340; }
:root[data-force="light"] .ltb.warn path { fill: #f5a524; }

/* The reference line is a solid hairline, not a dash: dashing reads as
   "projection" when this is a fixed target the user set. */
.ltb-ref { stroke: var(--sep); stroke-width: 1; vector-effect: non-scaling-stroke; }
.ltb-reft, .ltb-pk, .ltb-x {
  fill: var(--text-3); font-size: 9px; font-weight: 600;
  font-family: inherit; font-variant-numeric: tabular-nums;
}
.ltb-reft { text-anchor: end; }
.ltb-pk { text-anchor: middle; fill: var(--text-2); }
.ltb-x { text-anchor: middle; font-weight: 500; }

/* ---- the log --------------------------------------------------------- */

/* Date, note and a delete, in one row per entry. */
.ltadd {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  background: var(--chrome); border-radius: 14px; padding: 10px 12px;
  box-shadow: 0 0 0 .5px var(--sep-soft);
}
.ltpane .ltd-date { flex: none; padding: 6px; color: var(--text-2); }
.ltpane .ltd-note { flex: 1 1 120px; min-width: 0; padding: 6px; }
.ltd-go {
  flex: none; cursor: pointer; font-size: 0.86em; font-weight: 590;
  padding: 7px 13px; border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent); box-shadow: none;
}
.ltd-go:hover { filter: none; background: color-mix(in srgb, var(--accent) 20%, transparent); }

.ltlog {
  margin: 0; padding: 0; list-style: none;
  background: var(--chrome); border-radius: 14px; overflow: hidden;
  box-shadow: 0 0 0 .5px var(--sep-soft);
}
.ltlog li {
  display: flex; align-items: center; gap: 10px;
  min-height: 44px; padding: 6px 8px 6px 14px;
}
.ltlog li + li { border-top: .5px solid var(--sep-soft); }
.lte { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
/* Date, clock and "N days ago" on one line, in falling emphasis: the absolute
   date is what the row is FOR, the rest qualifies it. */
.lte-h { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
.lte .d { font-size: 0.9em; font-weight: 560; font-variant-numeric: tabular-nums; }
.lte .tm {
  font-size: 0.8em; color: var(--text-3); font-variant-numeric: tabular-nums;
}
.lte .ago { font-size: 0.8em; color: var(--text-3); }
.lte .n { font-size: 0.84em; color: var(--text-3); overflow-wrap: anywhere; }
/* The gap since the previous entry. Muted and tabular: it is a column of
   numbers down the right of the list, and it reads as rhythm only if the digits
   line up. */
.lte-g {
  margin-left: auto; flex: none; font-size: 0.78em; color: var(--text-3);
  font-variant-numeric: tabular-nums; opacity: .85;
  padding: 2px 7px; border-radius: 999px;
  background: color-mix(in srgb, var(--text-3) 10%, transparent);
  /* A fixed box, right-aligned: the chips are a COLUMN down the list and only
     read as rhythm if they start on one edge. Sized to fit "+365 дн." — past a
     year the number wraps rather than pushing the delete button around. */
  min-width: 4.6em; text-align: center;
}
/* Faint until the row is hovered or the button focused, for the reason the note
   pin is: a permanently visible ✕ on every entry reads as state rather than as
   an affordance, and it is destructive. */
/* `auto` margin lives on the gap chip now, which may be absent (the oldest
   entry has no previous one) — so the delete keeps its own, and whichever of
   the two comes first pushes the pair right. */
.ltx {
  margin-left: auto; flex: none; background: none; box-shadow: none;
  color: var(--text-3); font-size: 0.9em; line-height: 1;
  padding: 6px 8px; border-radius: 8px; cursor: pointer;
  opacity: 0; transition: opacity .12s ease;
}
.ltlog li:hover .ltx, .ltx:focus-visible { opacity: 1; }
.ltx:hover { filter: none; color: var(--danger); background: var(--fill); }
/* Touch cannot hover, which would make entries undeletable there. */
@media (hover: none) { .ltx { opacity: .5; } }

.ltpane .ne-del {
  width: 100%; background: var(--chrome); box-shadow: 0 0 0 .5px var(--sep-soft);
  color: var(--danger); border-radius: 14px; min-height: 44px; cursor: pointer;
  font-size: 0.95em;
}
.ltpane .ne-del:hover { filter: none; background: color-mix(in srgb, var(--danger) 10%, var(--chrome)); }

/* ---- icon picker --------------------------------------------------------
   The icon row shows the current emoji as a chip; tapping it unfolds a grid
   of the icons these items actually use, with a free field at the end for
   anything else. A bare text input asked the user to produce an emoji from
   memory, which on desktop means the OS picker or nothing. */
.lte-emobtn {
  margin-left: auto; width: 38px; height: 38px; border-radius: 10px; border: 0; cursor: pointer;
  background: var(--fill); box-shadow: none; font-size: 1.25em; line-height: 1;
  display: grid; place-items: center; padding: 0;
}
.lte-emobtn:hover { filter: none; background: color-mix(in srgb, var(--fill) 78%, var(--text-3) 9%); }
.lte-emobtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.lte-emopick {
  display: grid; grid-template-columns: repeat(8, 1fr); gap: 4px;
  padding: 10px 12px; background: var(--canvas); border-radius: 12px;
  box-shadow: inset 0 0 0 .5px var(--sep-soft);
  /* Lives INSIDE the .ne-rows card (between its rows), so it needs its own
     inset margins — flush to the card's walls it read as a broken row. */
  margin: 8px 10px 10px;
}
.lte-emopick[hidden] { display: none; }
.lte-emopick button {
  aspect-ratio: 1; border: 0; border-radius: 8px; cursor: pointer;
  background: none; box-shadow: none; font-size: 1.15em; line-height: 1;
  display: grid; place-items: center; padding: 0;
}
.lte-emopick button:hover { filter: none; background: var(--fill); }
.lte-emopick button.on { background: color-mix(in srgb, var(--accent) 18%, transparent); box-shadow: 0 0 0 1.5px var(--accent); }
/* The free field spans the row's tail so it reads as "…or type your own". */
.lte-emofree {
  grid-column: span 4; font: inherit; font-size: 0.85em;
  padding: 4px 8px; border-radius: 8px; min-width: 0;
}
