/* Tavern Chronicle lobby sticky note (always-visible link → /chronicle).
   Standalone stylesheet loaded by the terminal layout. Kept OUT of the
   terminal/ bundle on purpose so the lobby affordance doesn't grow the
   terminal CSS rule-block count. Reuses the .postit visual classes; only
   positioning lives here. */

/* THE NOTE IS LOBBY-ONLY, AND UNTIL #11411 ONLY THE SERVER BELIEVED THAT.
   ======================================================================
   `terminal/_floating_postits.html.erb` opens with

     return unless @session.current_room == 'lobby' || @session.current_room.nil?

   so the room scope is already declared, already shipped, and named in every
   other signal this note carries: the file header above, `.chronicle-note`'s
   dismiss key `lobby-chronicle`, its testid `lobby-chronicle-note`, and
   #10569's own commit subject ("lift LOBBY chronicle post-it clear of the
   action dock").

   That gate cannot hold, because the partial renders into `#postit-portal`,
   which lives in the LAYOUT (`layouts/terminal.html.erb`) and is therefore
   rendered exactly ONCE, at page load. A client-side room transition re-renders
   `terminal/grid_layout` only (`RoomTransitioner#broadcast_room_content`), and
   the portal is not in it — the same never-re-rendered hazard the RENDERED IN
   EVERY ROOM note in `terminal/panels/_contextual_actions.html.erb` warns about
   for the left zone. So a player who loads the page in the lobby and walks into
   the game room carries every lobby post-it with them.

   The floating cluster survives that harmlessly: #3731 ships it
   `postit-group--stripped`, i.e. `display:none`. This note was deliberately put
   OUTSIDE that group so it paints on first frame — which makes it the one lobby
   affordance that arrives in the game room as a VISIBLE, `pointer-events:auto`,
   viewport-fixed 212x123 card anchored at `left: 1rem`: directly on top of the
   left zone.

   #10569 met this as a VERTICAL collision with the action dock and answered it
   with a vertical offset plus a "keep this in sync" comment (see `bottom:`
   below). #11391 then moved the dock out of `.input-area` and into the left-zone
   Contextual Sheet, and an offset tuned against `.input-area` cannot know that.
   Measured 2026-08-21, 1280x720, game room, `.terminal-container[data-room=game]`:

     elementFromPoint over .action-dock__more-summary -> P.postit__body
     elementFromPoint over .action-dock__suggest      -> P.postit__title

   both of them this note — a control the player can see, cannot press, and gets
   no explanation for. So gate on the ROOM, which is what the server already
   gates on, instead of tuning the offset a third time against whatever surface
   moves next.

   `.terminal-container[data-room]` is the SINGLE client-side room signal:
   stamped by `terminal/show.html.erb` at render and updated on every transition
   by `room_controller.js` and `lib/state_reconciler.ts`. `:has()` reads that one
   existing value rather than introducing a second copy that could disagree with
   it — the same idiom `terminal/components/_contextual_chips_docked.css` uses
   for its empty-state hint.

   Two cases this deliberately leaves alone:
   - No `.terminal-container` (the welcome page, no session) matches nothing and
     keeps the note. That is the `current_room.nil?` half of the server's gate.
   - The SEAMLESS transition path is already covered, by accident and not by this
     rule: `room_transition_coordinator.ts#_swapDOM` clears `#postit-portal` and
     re-inserts only `.postit-group--floating` from the new room HTML — which
     never contains any post-it, since `_floating_postits` renders from the
     layout alone. On that path the whole portal is simply wiped. Do not read
     this rule as restoring the note when the player walks back to the lobby;
     on the seamless path there is nothing left to restore (#11412). */
body:has(.terminal-container:not([data-room="lobby"])) .chronicle-note {
  display: none;
}

.chronicle-note {
  position: fixed;
  left: var(--space-4, 1rem);
  /* #10569: sit ABOVE the input area, never over it — this is a SPATIAL fix, not a
     z-index or pointer-events one. `.input-area` is pinned to the bottom of the
     narrative panel (just above the hotbar) and is capped at min(42vh, 320px) by
     #10530. When the DM's action dock inflated it, a note anchored just above the
     hotbar landed on top of the dock's contextual offers and — being a VISIBLE,
     interactive card — ate their clicks (measured 2026-08-11: elementFromPoint over a
     `.action-dock__suggest` returned `.chronicle-note`). A stacking fix cannot solve
     this: the note is `position:fixed` in #postit-portal (a body child, root z=1) while
     the dock is buried inside the isolated `.zone--main` stacking context (root z=0),
     so nothing on the dock side can be raised above the note, and dropping the note
     below `.zone--main` would hide it behind the opaque panel. #10515's control also
     requires a visible post-it to catch its OWN click, so pointer-events is off the
     table. Clearing the input area's maximum height is the only fix that keeps the note
     visible AND leaves the dock clickable.

     #11411 NARROWED WHAT THIS OFFSET IS RESPONSIBLE FOR. It no longer protects the
     action dock at all — the dock moved to the left-zone Contextual Sheet in #11391,
     and the room gate at the top of this file is what keeps the note off it. This
     offset now governs the LOBBY layout only: it keeps the note clear of the lobby's
     own input area and chip row, in the one room where the note renders. The old
     instruction here — "keep this offset in sync with the `.input-area` max-height" —
     is exactly the kind of coupling that cannot report itself stale, and it did not:
     #11391 moved the surface and this comment kept asserting an adjacency that had
     stopped existing. Kept for the lobby, but do not restore an action-dock
     responsibility to it; if a lobby surface moves, re-measure rather than
     re-synchronising against a value in another file. */
  bottom: calc(var(--hotbar-height, 56px) + min(42vh, 320px) + var(--space-4, 1rem));
  width: 13rem;
  max-width: 42vw;
  z-index: var(--z-raised, 50);
  text-decoration: none;
  cursor: pointer;
  transform: rotate(2deg);
  transition: transform var(--timing-fast, 120ms) var(--ease-default, ease);
}
.chronicle-note:hover {
  transform: rotate(2deg) translateY(-3px) scale(1.03);
  text-decoration: none;
}
/* Inner link carries the clickable card content; the wrapper owns the
   .postit visual + the dismiss button. Reset link styling so the card looks
   unchanged from the previous single-<a> markup. */
.chronicle-note__link {
  display: block;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}
.chronicle-note__link:hover { text-decoration: none; }
.chronicle-note .postit__command { cursor: pointer; }

/* DISMISS TARGET — the affordance that makes covering acceptable (#11416).
   ======================================================================
   JP, 2026-08-21: "it's allowed to cover stuff since it is dismissable
   (though the X could be bigger)." The note is deliberately a visible,
   `pointer-events: auto`, viewport-fixed card, so the X is the ONLY escape
   from whatever it lands on. A 16x16 escape hatch does not carry that weight.

   Measured on this file's own markup in Firefox ESR 140.13.0 (the browser JP
   filed from) @ 1280x600, by sampling EVERY pixel of the button's bounding box
   with elementFromPoint and counting the ones that actually hit-test to the
   button. Sampling, not getBoundingClientRect, because the card carries
   `transform: rotate(2deg)`: a rect probe reports the axis-aligned bounding
   box, which for a rotated square is both too big and includes corners that
   belong to whatever is behind it.

     before   16 x 16 declared    258 px^2 clickable   largest square 15 x 15
     after    44 x 44 declared   1920 px^2 clickable   largest square 41 x 41

   7.4x the clickable area. The 16 px^2 short of a nominal 1936 is the rotation
   slivers at the corners falling past the card edge, and 41 rather than 44 is
   the largest AXIS-ALIGNED square inscribed in a square rotated 2 degrees —
   both are properties of the tilt, not of the target. Area is preserved under
   rotation, so the 44x44 floor (WCAG 2.5.5 / 2.5.8) is genuinely met; the
   axis-aligned figure is recorded here so the next person to measure it does
   not read 41 as a regression.

   THE TARGET IS ANCHORED INSIDE THE CARD, NOT INFLATED AROUND THE GLYPH.
   The obvious idiom here is `_base.css`'s transparent `::before { inset: -Npx }`
   hit expansion, and it is the WRONG one for this element: the glyph sits at
   `top: 4px; right: 6px`, so growing 16 -> 44 symmetrically pushes 10px above
   and 8px past the card's top-right corner — an invisible, click-eating region
   floating over the narrative panel. That is the exact defect class this note
   has already caused twice (#10569, #11411: elementFromPoint over a control
   returning a post-it). Instead the button is pinned to `top: 0; right: 0` and
   given the full 44x44 corner, with the glyph held in its old visual position
   by padding + flex alignment. The card does not grow, nothing overflows it,
   and the note's own bounding box is unchanged.

   Costs ~8% of the card's click area (1936 of ~24,300 px^2) to the link. That
   is the trade JP asked for: the X is what makes covering acceptable.

   SCOPE IS DELIBERATE. `.postit__dismiss` in `terminal/atoms/_postit.css` is
   still 16x16 for every other post-it. That is a real WCAG 2.5.8 gap, but the
   sibling post-its ship inside `postit-group--stripped` (display:none, #3731)
   and the `scene_hints_controller.js` cards are 180px wide, where a 44px corner
   takes 24% of the width — a visual change that needs its own measurement, not
   a drive-by. Do not read the narrow selector as an oversight.

   The resting `opacity: 0` (reveal on `.postit:hover`) is inherited from the
   atom and kept — but an invisible control is unusable by keyboard, so
   `:focus-visible` both reveals it and rings it. The offset is NEGATIVE: the
   button is flush with the card corner, so an outward ring would draw onto the
   panel behind it. */
.chronicle-note .postit__dismiss {
  top: 0;
  right: 0;
  width: 44px;
  height: 44px;
  min-width: 44px;
  min-height: 44px;
  /* Hold the glyph where the 16x16 button used to put it: hard against the
     card's top-right corner, so enlarging the target does not move the X. */
  align-items: flex-start;
  justify-content: flex-end;
  padding: 4px 6px 0 0;
  /* Proportionate to the new target — JP asked for a bigger X, not just a
     bigger invisible box. 14px -> 18px reads as bigger without crowding a
     208px-wide card. */
  font-size: 18px;
  border-radius: var(--postit-radius, 2px);
  /* MEASURED, NOT ASSUMED (#11416). At 16x16 the button cleared the card's text
     entirely, so nothing here needed a stacking rule. At 44x44 it overlaps
     `.postit__title` and `.postit__body`, and a grid scan of every pixel in the
     target found 451 of them hit-testing to that TEXT rather than to the button
     (postit__body 416, postit__title 35) — 1571 of a nominal 1936 px^2 usable,
     i.e. a control that measures 44x44 and is not clickable across a fifth of
     itself. That is the same false-green shape as #11411, where the dock was
     "visible, enabled and stable" and still could not be clicked.
     `var(--z-raised)` — the scale's "just above siblings" layer, value 1 — lifts
     the button over the in-flow link content inside `.postit`'s own stacking
     context; it does NOT escape that context, so the note's position relative to
     the rest of the page is untouched. The token is not decoration: the
     `z_index_literals` ratchet is BLOCKING at 0, and it counts the raw form in a
     COMMENT as readily as in a declaration — this comment tripped it once. */
  z-index: var(--z-raised, 1);
}

.chronicle-note .postit__dismiss:focus-visible {
  opacity: 1;
  outline: 2px solid var(--focus-ring-color, #ffd700);
  outline-offset: -2px;
}

/* Desktop affordance only — the chronicle is reachable at /chronicle directly. */
@media (max-width: 767px) {
  .chronicle-note { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .chronicle-note,
  .chronicle-note:hover { transform: rotate(2deg); }
}
