/* ============================================================================
   activity-bar.css
   ----------------------------------------------------------------------------
   The combined activity panel: what used to be "Biggest Influencers" and
   "Tech Mafias" in the original right column, now one tall feed.

   The card and its head are transcribed from _reference/ycglobe-index.html,
   or expressed through the token that tokens.css transcribed it into, with
   provenance noted per block as (orig CSS Lnn).

   The ROWS are not. They are respaced to the friend.tech-style trade feed the
   brief measured (docs/briefs/panels-spacing.md): a 78px list item with 15px
   vertical / 12px horizontal padding, a hairline divider, an overlapping
   28/36px avatar pair, two lines of 14px text and a stacked amount + time on
   the right. The original's dense 26px influencer row is gone; the frame it
   sat in is untouched. Every size below is either the brief's measured number
   or the tokens.css token that already carries it - 15px is --sp-14, 12px is
   --sp-11, 14px is --fs-xl, 12px is --fs-base, 4px is --sp-3.

   Load order: tokens.css, then this file.

   Why the root carries two classes. The mount point is
   <div class="panel act-panel">. `.panel` is the class the real page already
   styles, so when this module is mounted there the page's own rule applies and
   this file's `.act-panel` block declares the identical values on top of it -
   duplicate but byte-identical, so cascade order cannot matter. Standalone (the
   demo) only `.act-panel` exists, and the panel still looks right.
   ========================================================================== */

/* -- the card (orig CSS L207-209, .panel) - frame, unchanged --------------- */

.act-panel{
  position:relative;            /* the original is position:fixed because the page
                                   drags it around; a module is placed by its host */
  display:flex; flex-direction:column; overflow:hidden;
  background:var(--paper-66);
  -webkit-backdrop-filter:var(--blur-panel); backdrop-filter:var(--blur-panel);
  border:1px solid var(--brand-20);
  border-radius:var(--r-16);
  box-shadow:var(--sh-4-panel);
  color:var(--ink);
  font-family:var(--font-body);
}

/* -- head (orig CSS L210-212, .panel-head / .ph-title / .ph-sub) - frame --- */

.act-panel .panel-head{
  display:flex; align-items:center; gap:var(--gap-row);
  padding:11px 13px 9px;
  user-select:none; flex:0 0 auto;
  cursor:default;               /* orig is cursor:move - that belongs to the page's
                                   drag behaviour, which a module does not own */
}
.act-panel .ph-title{
  font-family:var(--font-display); font-weight:var(--fw-semibold); font-size:var(--fs-lg-p);
}
.act-panel .ph-sub{ font-size:var(--fs-base); color:var(--graphite); }
.act-panel .ph-sub b{ color:var(--ink); }

/* -- kind filter (orig CSS L653-656, #mofilter .mf-chips / .mfc / .mfc.on) -
   The original's filter chips, moved out of the mobile filter tile and into
   this panel's head. The .on state is the brand fill it already had.

   Respaced with the rows: the chips sit on the row grid now, so they take the
   rows' 12px gutter (--sp-11) rather than the head's 13px, a 6px gap instead
   of 4px, and 12px of air below them before the first row. The brief asked for
   the chip row to stop crowding the header; this is that. */

.act-chips{
  display:flex; flex-wrap:wrap; gap:var(--gap-tight);
  padding:0 var(--sp-11) var(--sp-11);
  flex:0 0 auto;
}
.act-chip{
  font-family:inherit;
  font-size:var(--fs-sm); padding:var(--sp-3) var(--sp-7); border-radius:var(--r-7);
  border:1px solid var(--border); background:var(--white); cursor:pointer;
  display:inline-flex; align-items:center; gap:var(--sp-3);
  white-space:nowrap; color:var(--ink);
  line-height:var(--lh-tight);
}
.act-chip.on{ background:var(--brand); color:var(--on-brand, var(--white)); border-color:var(--brand); }
.act-chip:hover:not(.on){ border-color:var(--brand); background:var(--brand-08); }
.act-chip:focus-visible{ outline:2px solid var(--brand-55); outline-offset:2px; }

/* -- body + list (orig CSS L229 .panel-body; L272 .influ-list) ------------
   The body's 13px side padding is dropped to 0 and re-declared on the row as
   the brief's 12px, so a row is full-bleed and its hairline divider can run
   the width of the panel like a list item rather than floating inside a second
   inset. Vertical padding is the original's. */

.act-panel .panel-body{
  flex:1 1 auto; overflow:hidden; padding:0 0 var(--sp-11); min-height:0;
}
.act-list{
  display:flex; flex-direction:column; gap:0;   /* rows are divided, not gapped */
  height:100%; overflow-y:auto;
  -webkit-overflow-scrolling:touch; overscroll-behavior:contain;   /* orig L244 */
}
.act-empty{
  font-size:var(--fs-md-p); color:var(--graphite);
  padding:var(--sp-11);
  line-height:var(--lh-relaxed);
}

/* -- one row --------------------------------------------------------------
   78px: 15px + the 48px avatar column + 15px. The avatar column is the tallest
   thing in the row, so the height is set by it and by the padding alone - the
   two text lines (2 x 14px x 1.4 + 4px = 43.2px) sit inside it and cannot push
   it. That is deliberate: every row in the feed is exactly the same height
   whatever it says, which is what makes the list read as a rhythm.

   The row is a real <button>, so it is reachable by keyboard and announced as
   a control; the button's own chrome is reset away. */

.act-row{
  position:relative;
  display:flex; align-items:center; gap:var(--sp-11);
  padding:var(--sp-14) var(--sp-11);
  cursor:pointer;
  border:none; background:none; margin:0;
  font:inherit; color:inherit; text-align:left; width:100%;
  flex:0 0 auto;
}

/* The hairline. A pseudo-element rather than a border, so the divider costs the
   row no height and every row measures exactly 78px. Inset to the row's own
   gutter, so it starts where the content does. */
.act-row + .act-row::before{
  content:""; position:absolute; left:var(--sp-11); right:var(--sp-11); top:0;
  height:1px; background:var(--border);
}

.act-row:hover{ background:var(--act-row-hover); }
.act-row:focus-visible{ outline:2px solid var(--brand-55); outline-offset:-2px; }

/* -- the avatar pair ------------------------------------------------------
   The brief's pair: a small circle top-left and a larger one overlapping it to
   the lower right, in a 48px column. Ours are two identicons - the actor small
   at 28px, and at 36px whatever the row's second line names: the counterparty
   on a payment, the memory on every kind that has one. So the large avatar is
   always the face of the bold line, and the pair is not decoration.

   `agent_registered` names nothing else, so it renders the actor alone at the
   large 36px, vertically centred, and keeps the column - the text edge stays
   aligned all the way down the list. */

.act-av{ position:relative; display:block; width:48px; height:48px; flex:0 0 auto; }
.act-av .av-a,
.act-av .av-b{
  position:absolute; overflow:hidden;
  background:var(--img-placeholder); display:block;
}
.act-av .av-a{
  left:0; top:0; width:28px; height:28px;
  border:1px solid var(--border); border-radius:var(--r-8);
}
.act-av .av-b{
  right:0; bottom:0; width:36px; height:36px;
  border:2px solid var(--paper);   /* the ring that cuts the large one out */
  border-radius:var(--r-10);
}
/* one avatar only: the actor takes the large size and the column's middle */
.act-av.solo .av-a{
  top:6px; width:36px; height:36px; border-radius:var(--r-10);
}
.act-av svg{ display:block; width:100%; height:100%; }

/* -- the sentence, two lines ----------------------------------------------
   Line 1 is the actor in mono medium and the verb in grey; line 2 is the thing
   the event is about, bold. Both lines truncate rather than wrap: a wrapped
   line would break the fixed 78px row, and an ellipsis is the honest failure
   mode in a panel too narrow for the sentence. */

.act-i{ flex:1; min-width:0; display:flex; flex-direction:column; gap:var(--sp-3); }
.act-line{
  font-size:var(--fs-xl); line-height:var(--lh-body);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.act-actor{
  font-family:var(--font-mono-short); font-weight:var(--fw-medium); color:var(--ink);
}
.act-verb{ color:var(--graphite); }
.act-obj{ font-weight:var(--fw-bold); color:var(--ink); }
.act-obj.act-mem{
  font-family:var(--font-mono-short);
  color:var(--cat, var(--ind-fallback));
}
.act-obj.act-agent{ font-family:var(--font-mono-short); }
.act-arrow{ color:var(--graphite); font-weight:var(--fw-regular); }

/* -- amount + time (orig CSS L275 .influ-co, L276 .influ-f) ----------------
   Amount in bold mono, tone-coloured, over a 12px mono grey time. Capped at
   45% of the row so a long failure reason cannot starve the sentence; reasons
   are words rather than figures, so they take the smaller size. */

.act-r{
  display:flex; flex-direction:column; align-items:flex-end; justify-content:center;
  gap:var(--sp-1);
  white-space:nowrap; flex:0 1 auto; max-width:45%; text-align:right;
}
.act-amt{
  font:var(--fw-bold) var(--fs-xl)/1.2 var(--font-mono-short);
  color:var(--tone, var(--graphite));
  max-width:100%; overflow:hidden; text-overflow:ellipsis;
}
.act-amt.word{ font-size:var(--fs-md-p); }
.act-when{
  font-size:var(--fs-base); line-height:var(--lh-tight); color:var(--graphite);
  font-family:var(--font-mono-short);
  font-variant-numeric:tabular-nums;
}

/* Tones. The source keeps two greens and two reds and uses them for different
   jobs: --ok / --danger are the status *dot* fills, --ok-text / --danger-text
   are what it writes words in (.fb-note.ok and .fb-note.err). The amount is a
   word, so it takes the text pair - which is also the pair that clears 4.5:1
   on this ground (5.02 and 5.13; the dot pair measures 3.11 and 4.48).
   `warn` is carried for parity with the Quest.Tech tone type - no Cognia kind
   currently maps to it, and it resolves to the page's attention colour. */
.act-row[data-tone="good"]{    --tone:var(--ok-text); }
.act-row[data-tone="bad"]{     --tone:var(--danger-text); }
.act-row[data-tone="warn"]{    --tone:var(--brand); }
.act-row[data-tone="neutral"]{ --tone:var(--graphite); }

/* -- category colours for memory ids --------------------------------------
   The engine owns this mapping. src/graph/graph.js exports CATEGORY (light) and
   DARK_THEME.category (dark); tokens.css --ind-* / tokens-dark.css --ind-* are
   the same eight values under their token names, so every pair below resolves
   to exactly what the engine paints that category, in whichever theme is live:

     Coding         #1F3A93 / #8FAEFF   --ind-b2b
     Infrastructure #1A1A1A / #D8CCC0   --ind-industrials
     Browser        #7A2FB0 / #C9A0ED   --ind-consumer
     Data           #1C6FA8 / #78C7E8   --ind-education
     Security       #C0392B / #F28D86   --ind-healthcare
     Operations     #5C3A16 / #D4AD78   --ind-realestate
     Finance        #0E7C5A / #75CBA7   --ind-fintech
     Research       #3d566e / #A2BCCB   --ind-government

   Three of these used to be wrong in BOTH themes — Infrastructure read the
   clone's real-estate colour, Operations government and Research industrials.
   Because the row only ever names a token, a theme switch re-points the whole
   ramp with no repaint; nothing here caches a colour.

   Still declared on this panel as overridable custom properties: a host that
   wants to bind the panel to the engine's live map rather than to the token
   layer passes `categoryColors` to createActivityBar (see README), which writes
   these same properties from JS and wins over the defaults below. */

.act-panel{
  --cat-coding:         var(--ind-b2b);
  --cat-infrastructure: var(--ind-industrials);
  --cat-security:       var(--ind-healthcare);
  --cat-data:           var(--ind-education);
  --cat-browser:        var(--ind-consumer);
  --cat-operations:     var(--ind-realestate);
  --cat-finance:        var(--ind-fintech);
  --cat-research:       var(--ind-government);
}
.act-row[data-cat="Coding"]         .act-mem{ --cat:var(--cat-coding); }
.act-row[data-cat="Infrastructure"] .act-mem{ --cat:var(--cat-infrastructure); }
.act-row[data-cat="Security"]       .act-mem{ --cat:var(--cat-security); }
.act-row[data-cat="Data"]           .act-mem{ --cat:var(--cat-data); }
.act-row[data-cat="Browser"]        .act-mem{ --cat:var(--cat-browser); }
.act-row[data-cat="Operations"]     .act-mem{ --cat:var(--cat-operations); }
.act-row[data-cat="Finance"]        .act-mem{ --cat:var(--cat-finance); }
.act-row[data-cat="Research"]       .act-mem{ --cat:var(--cat-research); }

/* -- a row arriving (orig CSS L504-505, .dbrow.rowflash) -------------------
   The whole motion language for a new row, transcribed unchanged. The original
   page announces an inserted row by flashing its ground and nothing else - no
   slide, no height animation, no fade - and the Quest.Tech panel likewise
   declares that it animates rows not at all. Adding either would be a decision
   both references declined to make. Untouched by the respacing pass. */

.act-row.rowflash{ animation:rowflash var(--anim-rowflash) var(--ease); }
@keyframes rowflash{
  0%,55%{ background:var(--brand-16); }
  100%{ background:transparent; }
}

@media (prefers-reduced-motion:reduce){
  .act-row.rowflash{ animation:none; }
}

/* -- dark ─────────────────────────────────────────────────────────────────
   tokens-dark.css re-points every colour token above, so the panel, its rows
   and the whole category ramp theme themselves. Only two things survive that,
   and they are the two this file expressed as something other than a colour:

     .act-row:hover  a 12%-of-brand wash over TRANSPARENT. On paper that is a
                     visible warm tint; over charcoal it is very nearly nothing,
                     so dark takes the opaque --brand-08 (brand mixed into the
                     raised surface) instead of a transparency.
     .act-chip.on    handled inline above via --on-brand, which only exists on
                     dark and falls back to --white in light.

   Declared as a custom property with the light value as its default, so light
   renders byte-identically whether or not tokens-dark.css is loaded. */

.act-panel{ --act-row-hover:color-mix(in srgb, var(--brand) 12%, transparent); }
[data-theme="dark"] .act-panel{ --act-row-hover:var(--brand-08); }

/* The page carries this for its own panels; the module carries it for itself so
   the demo and any other host get it too. On dark a panel that drops its blur
   must still read as raised, which --paper (the page ground) would not. */
@media (prefers-reduced-transparency: reduce){
  [data-theme="dark"] .act-panel{
    background:var(--surface); -webkit-backdrop-filter:none; backdrop-filter:none; }
}

/* -- phone (orig CSS L666-668, the #influbox mobile block) -----------------
   The same row at a smaller scale, not a different row: the proportions hold.
   12px padding, a 40px avatar column (24 + 30 overlapping), 12px text, 10.5px
   time. 12 + 40 + 12 = 64px. */

@media (max-width:768px){
  .act-panel{
    /* orig L688: six 18px-blur tiles compositing over WebGL jank the map */
    -webkit-backdrop-filter:var(--blur-md); backdrop-filter:var(--blur-md);
  }
  .act-panel .panel-head{ padding:8px 9px 4px; }
  .act-panel .ph-title{ font-size:var(--fs-md-p); }
  .act-panel .panel-body{ padding:0 0 var(--sp-8); }
  .act-chips{ padding:0 var(--sp-9) var(--sp-8); }
  .act-row{ gap:var(--sp-9); padding:var(--sp-11) var(--sp-9); }
  .act-row + .act-row::before{ left:var(--sp-9); right:var(--sp-9); }
  .act-av{ width:40px; height:40px; }
  .act-av .av-a{ width:24px; height:24px; border-radius:var(--r-7); }
  .act-av .av-b{ width:30px; height:30px; border-radius:var(--r-8); }
  .act-av.solo .av-a{ top:5px; width:30px; height:30px; border-radius:var(--r-8); }
  .act-i{ gap:var(--sp-2); }
  .act-line{ font-size:var(--fs-base); }
  .act-amt{ font-size:var(--fs-base); }
  .act-amt.word{ font-size:var(--fs-sm-p); }
  .act-when{ font-size:var(--fs-sm-p); }
}
