/* ===========================================================================
   The activity log - My Profile's Activity tab and the Admin Directory's
   activity dialog. Class prefix .al-*, because this is ONE component on two
   screens (app/js/activity-log.js).

   TWO PANES WHERE THE HOST IS WIDE, ONE WHERE IT IS NOT. The old paint was a
   list stretched across 1,900px with everything hugging the left edge. The
   rail carries what is true of the WHOLE log - who, the span, the kind
   counts, the most-opened pages - and the timeline carries the rows, grouped
   by local day under a sticky heading.

   THE CONTAINER IS `.al`, NOT THE HOST. A container query styles the
   container's descendants and can never style the container itself, and the
   host is whichever element a caller hands over, so the component wraps its
   own outer box and queries that. The single-column layout is the plain
   declaration; the two-pane one is the override, so a browser without
   container queries gets one column rather than nothing.
   =========================================================================== */

/* --al-sticky-top is where the day headings (and the rail, two-pane) stick:
   62px is the header's MEASURED height, not the 56px --header-h floor, and it
   is right for a host that scrolls with the page. A host that scrolls inside a
   dialog overrides it ON .al - `#thatHost .al { --al-sticky-top: 0; }` - not on
   the host, because a value declared here on .al beats one inherited from
   above it. */
.al { container-type: inline-size; min-width: 0; --al-sticky-top: 62px; }
.al-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.1rem; align-items: start; }
@container (min-width: 900px) {
  .al-body { grid-template-columns: 280px minmax(0, 1fr); gap: 1.6rem; }
  .al-rail { position: sticky; top: var(--al-sticky-top); }
}

/* ---- the rail ---------------------------------------------------------- */
.al-rail { min-width: 0; display: flex; flex-direction: column; gap: 1rem; }

.al-who { display: flex; align-items: flex-start; gap: .7rem; min-width: 0; }
.al-av {
  width: 40px; height: 40px; border-radius: var(--r-circle); flex: 0 0 auto;
  display: grid; place-items: center;
  font-size: var(--fs-sm); font-weight: var(--fw-bold); letter-spacing: .02em;
  color: var(--accent-ink); background: var(--accent-weak); border: 1px solid var(--accent-line);
}
.al-who-t { min-width: 0; }
.al-name { display: block; font-size: var(--fs-lg); font-weight: var(--fw-bold); color: var(--text); line-height: var(--lh-tight); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.al-lede { margin: .2rem 0 0; font-size: var(--fs-sm); color: var(--text-soft); line-height: var(--lh-normal); }
/* When the caller's chrome already names the person (`named`), the lede is the
   rail's first line and takes the weight the name had, so the rail still opens
   on WHOSE log this is rather than on a footnote. */
.al-lede.is-lead { margin: 0; font-size: var(--fs-md); color: var(--text); font-weight: var(--fw-medium); }

/* The span in words. Tabular numerals so a count sits still under a repaint. */
.al-span { margin: 0; font-size: var(--fs-sm); color: var(--text-dim); font-variant-numeric: tabular-nums; }

/* THE KIND CHIPS ARE BUTTONS, and the active one says so twice - the tint and
   aria-pressed - because colour never carries state alone here. Their counts
   are the whole log's, off `summary.by_kind`, never the rows on screen. */
.al-chips { display: flex; flex-wrap: wrap; gap: .4rem; }
.al-chip {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .28rem .65rem .28rem .55rem; border-radius: var(--r-pill);
  border: 1px solid var(--border); background: var(--surface); color: var(--text-soft);
  font: inherit; font-size: var(--fs-xs); font-weight: var(--fw-medium); line-height: var(--lh-snug);
  cursor: pointer; transition: background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
.al-chip .bi { font-size: var(--fs-sm); }
.al-chip:hover { background: var(--inset); color: var(--text); }
.al-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.al-chip.is-on { background: var(--accent-weak); border-color: var(--accent-line); color: var(--accent-ink); }
.al-chip-w { white-space: nowrap; }
.al-chip-n { font-style: normal; font-variant-numeric: tabular-nums; color: var(--text-dim); font-weight: var(--fw-normal); }
.al-chip.is-on .al-chip-n { color: var(--accent-ink); }

/* "Most opened": name, count, and a bar proportional to the first row. ONE
   HUE - a single series encodes no identity, so gold here is chrome. */
.al-top { display: flex; flex-direction: column; gap: .35rem; min-width: 0; }
.al-h { margin: 0 0 .15rem; font-size: var(--fs-2xs); font-weight: var(--fw-bold); letter-spacing: var(--ls-caps); text-transform: uppercase; color: var(--text-soft); }
.al-top-r { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .1rem .6rem; align-items: baseline; font-size: var(--fs-sm); }
.al-top-n { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.al-top-c { color: var(--text-dim); font-variant-numeric: tabular-nums; }
.al-top-bar { grid-column: 1 / -1; display: block; height: 5px; border-radius: 3px; background: var(--surface-3); overflow: hidden; }
.al-top-bar i { display: block; height: 100%; border-radius: 3px; background: var(--accent-fill); }
.al-none { margin: 0; font-size: var(--fs-sm); color: var(--text-dim); }

/* A footnote carries the asymmetry of the log; it is prose, so --text-soft
   rather than the 3:1 label token. */
.al-foot { margin: 0; font-size: var(--fs-xs); color: var(--text-soft); line-height: var(--lh-normal); }

/* ---- the timeline ------------------------------------------------------ */
.al-main { min-width: 0; }

.al-dayg { min-width: 0; }
.al-dayg + .al-dayg { margin-top: .6rem; }

/* THE DAY HEADING STICKS to whatever scrolls the host - the page under
   .main-content by default; see --al-sticky-top on .al for a dialog. Nothing
   here creates a scroller of its own: the rows scroll with their container,
   never inside a nested one. */
.al-day {
  position: sticky; top: var(--al-sticky-top); z-index: 2;
  display: flex; align-items: baseline; gap: .5rem;
  margin: 0; padding: .45rem .5rem .35rem;
  font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: var(--ls-caps); text-transform: uppercase;
  color: var(--text-soft); background: var(--surface); border-bottom: 1px solid var(--border-soft);
}
.al-day-n { font-style: normal; font-weight: var(--fw-normal); letter-spacing: 0; text-transform: none; color: var(--text-dim); font-variant-numeric: tabular-nums; }

/* A hairline runs down behind the glyph discs, so the column reads as one
   thread rather than fifty separate rows. Its position is the time column's
   72px plus the row's .5rem padding plus half a 26px disc.
   THE THREE rgba() LITERALS BELOW ARE THE ONLY NON-TOKEN COLOURS IN THIS FILE,
   and deliberately so: a hairline that has to sit on whatever surface the host
   gives it - a white pane, a dark dialog body, a card - is a translucent black
   in light and a translucent white in dark, which is the dark rail's own idiom
   (`rgba(255,255,255,.08)` in layout.css) rather than a colour a token could
   name once for every ground. Nothing else here may follow suit. */
.al-rows { position: relative; display: flex; flex-direction: column; padding: .25rem 0; }
.al-rows::before {
  content: ''; position: absolute; top: .25rem; bottom: .25rem;
  left: calc(.5rem + 72px + .6rem + 12px); width: 2px;
  background: rgba(0, 0, 0, .07); pointer-events: none;
}
/* EVERY DARK VALUE IS DECLARED TWICE - inside the media query for a dark-OS
   user who never touched the toggle, and on the attribute so the toggle beats
   the OS in both directions. Written as one selector list OUTSIDE the media
   query, `:root:not([data-theme="light"])` matches in LIGHT mode too whenever
   no attribute is set - the fault company-chooser.css already paid for. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .al-rows::before { background: rgba(255, 255, 255, .09); }
}
:root[data-theme="dark"] .al-rows::before { background: rgba(255, 255, 255, .09); }

/* ~40px a row, so fifty fit in about two thousand pixels of scroll. Time |
   disc | sentence | route, with the sentence the only flexible track. */
.al-row {
  position: relative; display: grid; grid-template-columns: 72px 26px minmax(0, 1fr) auto;
  gap: .6rem; align-items: center; min-height: 40px; padding: .3rem .5rem;
  border-radius: var(--r-sm); font-size: var(--fs-md); color: var(--text);
  transition: background .18s var(--ease);
}
.al-row:hover { background: var(--inset); }
.al-time { font-size: var(--fs-sm); color: var(--text-dim); font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }

/* The glyph disc: icon and tone by KIND only. Neutral for a page, gold-weak
   for a record, the info tint for a search, ok-weak for a decision - and
   never by reading the sentence. Colour never carries identity alone: each
   carries its icon and a tooltip naming the kind. */
.al-i {
  width: 26px; height: 26px; border-radius: var(--r-circle); display: grid; place-items: center;
  font-size: var(--fs-sm); background: var(--inset); color: var(--text-soft);
}
.al-t-page   { background: var(--inset);       color: var(--text-soft); }
.al-t-record { background: var(--accent-weak); color: var(--accent-ink); }
.al-t-search { background: var(--info-weak);   color: var(--info-ink); }
.al-t-action { background: var(--ok-weak);     color: var(--ok-ink); }
.al-t-other  { background: var(--surface-3);   color: var(--text-dim); }

.al-what { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--fw-medium); }
/* A LINK IS QUIET AT REST. Nearly every row links somewhere, so an underline
   on each was fifty underlines down the page - a wall, read in the first
   browser render, that made the one thing every row shares the loudest thing
   on it. At rest a link carries the row's own ink and a small trailing
   arrow-glyph in the dim ink, which is what says "this opens" without a rule
   under every sentence; the underline and the accent arrive on hover and on
   keyboard focus, where they mean something. */
.al-link { color: inherit; text-decoration: none; border-bottom: 1px solid transparent; }
.al-link::after { content: '\F1C5'; font-family: 'bootstrap-icons'; font-size: .72em; margin-left: .32em; color: var(--text-dim); vertical-align: 0; opacity: .85; }
.al-link:hover, .al-link:focus-visible { color: var(--accent-ink); border-bottom-color: var(--accent); }
.al-link:hover::after, .al-link:focus-visible::after { color: var(--accent-ink); }
.al-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }

/* The route is the WHERE: a hash this app owns, so it is set as one. */
.al-route {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: var(--fs-xs);
  color: var(--text-dim); background: var(--inset); border-radius: var(--r-xs);
  padding: .1rem .4rem; max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@container (max-width: 559.98px) {
  .al-route { display: none; }
  .al-row { grid-template-columns: 64px 26px minmax(0, 1fr); }
  .al-rows::before { left: calc(.5rem + 64px + .6rem + 12px); }
}

/* ---- the pager --------------------------------------------------------- */
.al-pager { display: flex; align-items: center; gap: .4rem; margin-top: .8rem; padding: 0 .5rem; font-size: var(--fs-sm); color: var(--text-soft); }
.al-range { font-variant-numeric: tabular-nums; margin-right: auto; }
.al-prev, .al-next { flex: 0 0 auto; }

/* ---- the states -------------------------------------------------------- */
/* Nothing recorded is an ANSWER and reads as one; a filtered-empty names the
   filter and offers the way back. `safe center` so a tall sentence never
   clips both ways inside a short box. */
.al-empty {
  display: flex; flex-direction: column; gap: .4rem;
  align-items: center; align-items: safe center; text-align: center;
  padding: 2rem 1rem; color: var(--text-dim);
}
.al-empty i { width: 52px; height: 52px; border-radius: var(--r-circle); display: grid; place-items: center; font-size: var(--fs-2xl); background: var(--accent-weak); color: var(--accent-ink); }
.al-empty b { font-size: var(--fs-lg); color: var(--text-soft); font-weight: var(--fw-medium); }
/* PROSE, SO IT TAKES THE SOFT INK. It inherited --text-dim from .al-empty,
   which this project holds to 3:1 as a non-prose label token - the same fault
   already corrected on .xo-off-needs and .aa-rec-note. It matters more here
   since 20260918000100: the empty state can now run to two sentences
   explaining why a log is empty, which is exactly the reading .al-empty's
   parent colour is not rated for.
   The flex column's .4rem gap already separates them, so nothing else is
   needed for the second sentence. */
.al-empty span { font-size: var(--fs-md); max-width: 46ch; line-height: var(--lh-normal); color: var(--text-soft); }
.al-empty .btn { margin-top: .4rem; }

/* THE REFUSAL. A log that is not this person's draws nothing but this. */
.al-refused {
  display: flex; gap: .7rem; align-items: flex-start;
  padding: .8rem 1rem; border: 1px solid var(--warn-line); border-radius: var(--r-sm);
  background: var(--warn-weak); color: var(--text); font-size: var(--fs-md);
}
.al-refused i { color: var(--warn-ink); font-size: var(--fs-lg); line-height: 1.2; }
.al-refused b { display: block; font-weight: var(--fw-bold); }
.al-refused span { display: block; color: var(--text-soft); font-size: var(--fs-sm); margin-top: .15rem; }

@media (prefers-reduced-motion: reduce) {
  .al-chip, .al-row { transition: none; }
}
