/* ============================================================================
   MAVEN RO — AI COMPANION  (Lane C)

   The seam between two finished things: the SYSTEM UI kit (web/system-ui)
   and the ro-ai service (services/ai). This file adds ONLY what the kit does
   not already ship — a composer, a status strip, a naming field and a couple
   of state modifiers on surfaces the kit owns.

   RULES FOLLOWED HERE (CONTRACT.md §5, §8):
     · Every colour is a kit token or a raw kit channel triple. There is not a
       single literal hex in this file.
     · Interior sizing is in `cqi`, because every .sys-panel is a size
       container and the kit's own interior scales that way. Fixed px is used
       only where the kit itself uses fixed px — the dock chip, and hit
       targets that must stay tappable.
     · Nothing here restyles a kit component's own composition. Modifiers are
       additive and namespaced `.mrc-*`, applied to nodes we created or as a
       state attribute on a node the kit handed us via a documented handle.
   ========================================================================= */

/* ---------------------------------------------------------------------------
   1. THE WINDOW

   `data-mrc-chat` is stamped on handle.el (documented, CONTRACT.md §3). It
   scopes everything below so no other panel on the page is affected.
   ------------------------------------------------------------------------ */

.sys-window[data-mrc-chat] {
  /* Wide enough for a readable line, narrow enough to leave the map playable.
     The kit's own clamp against the viewport still applies underneath. */
  --mrc-transcript-h: clamp(170px, 38vh, 380px);
}

/* The transcript gets a real, stable height so the window does not resize on
   every message — a window that grows under the cursor is the thing that makes
   an in-game chat feel unusable. */
.sys-window[data-mrc-chat] .sys-body {
  /* Floor and ceiling rather than a fixed height. The window is docked
     bottom-right, so growth pushes the TOP up and the composer never moves
     under the cursor — which is the behaviour that actually matters. A fixed
     height was tried first and left a large dead area on a short chat. */
  min-height: 130px;
  max-height: var(--mrc-transcript-h);
  flex: none;
}

/* The kit's transcript is a flex column sized by its content, so it needs the
   body's height to have anything to align inside. flex-end then keeps the
   newest message against the composer, the way every chat behaves — while the
   empty state's `margin: auto` still centres it, because auto margins absorb
   the free space before justify-content gets a look in. */
.sys-window[data-mrc-chat] .sys-transcript { min-height: 100%; justify-content: flex-end; }

/* A quiet, honest empty state before any history exists. */
.sys-root .mrc-empty{
  margin: auto;
  min-height: 100px;
  display: grid;
  place-items: center;
  padding: 4cqi;
  text-align: center;
  color: var(--sys-ink-faint);
  font-size: 3.2cqi;
  line-height: 1.6;
}

/* ---------------------------------------------------------------------------
   2. LOCAL NOTICES

   The kit's transcript has three voices: `system` (green name — the model),
   `you`, and `other` (neutral). Every line this file writes itself — rate
   limits, errors, the off switch — goes in as `other` and is marked with
   .mrc-notice, so a machine-written status line can never be mistaken for
   something the model said. That distinction is the whole point.
   ------------------------------------------------------------------------ */

.sys-root .mrc-notice .sys-msg__text{
  border-style: dashed;
  background: rgb(var(--sys-rgb-lift) / 0.06);
  color: var(--sys-ink-dim);
  font-style: italic;
}
.sys-root .mrc-notice .sys-msg__who{ color: var(--sys-ink-faint); }

.sys-root .mrc-notice[data-tone="warn"] .sys-msg__text{
  /* The tone colour is already on this rule; derive the rim from it rather
     than restating the hex. */
  border-color: color-mix(in srgb, currentColor 55%, transparent);
  color: var(--sys-accent-gold);
}
.sys-root .mrc-notice[data-tone="danger"] .sys-msg__text{
  border-color: color-mix(in srgb, currentColor 55%, transparent);
  color: var(--sys-accent-red);
}

/* ---------------------------------------------------------------------------
   3. THE FOOT — status strip + composer

   Appended to handle.frame (documented, CONTRACT.md §3), so it sits inside
   the kit's frame, below the scrolling body, and inherits the frame's gap.
   ------------------------------------------------------------------------ */

.sys-root .mrc-foot{
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 2cqi;
}

/* -- 3.1 status strip ---------------------------------------------------- */

.sys-root .mrc-status{
  display: flex;
  align-items: center;
  gap: 2cqi;
  padding-bottom: 1.6cqi;
  border-bottom: 1px solid rgb(var(--sys-rgb-hairline) / 0.16);
  font-size: 2.7cqi;
  letter-spacing: var(--sys-track-meta);
  text-transform: uppercase;
}

/* Rename shares the switch's chassis but never reads as a state: no dot, and
   it is pinned to the "off" colourway so the eye does not confuse the two. */
.sys-root .mrc-rename{
  color: var(--sys-ink-faint);
  border-color: rgb(var(--sys-rgb-hairline) / 0.22);
  font-weight: 600;
}
.sys-root .mrc-rename:hover{ color: var(--sys-ink); }

.sys-root .mrc-quota{
  margin-left: auto;
  color: var(--sys-ink-faint);
  font-family: var(--sys-font-mono);
  letter-spacing: 0.04em;
  font-size: 2.6cqi;
  white-space: nowrap;
}
.sys-root .mrc-quota[data-strain="near"]{ color: var(--sys-accent-gold); }
.sys-root .mrc-quota[data-strain="spent"]{ color: var(--sys-accent-red); }

/* -- 3.2 the on/off switch ----------------------------------------------
   This is requirement 5. It is a real toggle: aria-pressed carries the state
   for assistive tech, the dot carries it visually, and both are driven from
   the backend's `enabled` flag rather than from a local variable. */

.sys-root .mrc-power{
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 1.6cqi;
  padding: 1.4cqi 2.6cqi;
  min-height: 28px;
  border: 1px solid rgb(var(--sys-rgb-hairline) / 0.38);
  border-radius: var(--sys-r-btn);
  background: rgb(var(--sys-rgb-lift) / 0.10);
  color: var(--sys-ink-dim);
  font: inherit;
  font-size: 2.7cqi;
  font-weight: 700;
  letter-spacing: var(--sys-track-meta);
  text-transform: uppercase;
  cursor: pointer;
  transition: background 160ms var(--sys-ease-settle),
              border-color 160ms var(--sys-ease-settle),
              color 160ms var(--sys-ease-settle),
              box-shadow 160ms var(--sys-ease-settle);
}
.sys-root .mrc-power:hover:not(:disabled){
  background: rgb(var(--sys-rgb-lift) / 0.26);
  border-color: rgb(var(--sys-rgb-hairline) / 0.8);
}
.sys-root .mrc-power:disabled{ opacity: 0.5; cursor: progress; }

.sys-root .mrc-power__dot{
  width: 1.9cqi;
  height: 1.9cqi;
  min-width: 8px;
  min-height: 8px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

.sys-root .mrc-power[aria-pressed="true"]{
  color: var(--sys-accent);
  border-color: rgb(var(--sys-rgb-accent) / 0.5);
  text-shadow: var(--sys-accent-glow);
}
.sys-root .mrc-power[aria-pressed="true"] .mrc-power__dot{
  box-shadow: 0 0 8px rgb(var(--sys-rgb-accent) / 0.9);
}
.sys-root .mrc-power[aria-pressed="false"]{
  color: var(--sys-ink-faint);
  border-color: rgb(var(--sys-rgb-hairline) / 0.22);
  text-shadow: none;
}
.sys-root .mrc-power[aria-pressed="false"] .mrc-power__dot{
  background: none;
  box-shadow: inset 0 0 0 1px currentColor;
}

/* -- 3.3 composer -------------------------------------------------------- */

.sys-root .mrc-compose{
  display: flex;
  align-items: flex-end;
  gap: 2cqi;
}

.sys-root .mrc-input{
  flex: 1;
  min-width: 0;
  resize: none;
  padding: 2.2cqi 2.6cqi;
  min-height: 38px;
  max-height: 22vh;
  border: 1px solid rgb(var(--sys-rgb-hairline) / 0.42);
  border-radius: var(--sys-r-btn);
  background: color-mix(in srgb, var(--sys-field) 55%, transparent);
  color: var(--sys-ink);
  font-family: var(--sys-font);
  font-size: 3.3cqi;
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: var(--sys-track-body);
  transition: border-color 160ms var(--sys-ease-settle),
              box-shadow 160ms var(--sys-ease-settle);
}
.sys-root .mrc-input::placeholder{
  color: var(--sys-ink-faint);
  /* brand.css italicises every placeholder on the site in Cinzel. Not here. */
  font-family: var(--sys-font);
  font-style: normal;
}
.sys-root .mrc-input:focus{
  outline: none;
  border-color: rgb(var(--sys-rgb-hairline) / 0.95);
  box-shadow: 0 0 0 1px rgb(var(--sys-rgb-hairline) / 0.4),
              0 0 18px rgb(var(--sys-rgb-glow) / 0.55);
}
/* Focus is the state that matters most here: while this field has focus the
   game is not receiving keys, and the player must be able to see that at a
   glance. Hence a visible ring on plain :focus and not only :focus-visible. */
.sys-root .mrc-input:disabled{
  opacity: 0.55;
  cursor: not-allowed;
}

.sys-root .mrc-send{ flex: none; white-space: nowrap; }
.sys-root .mrc-send:disabled{
  opacity: 0.45;
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
}

/* -- 3.4 the line under the composer ------------------------------------- */

.sys-root .mrc-hint{
  display: flex;
  align-items: baseline;
  gap: 2cqi;
  min-height: 1.4em;
  font-size: 2.6cqi;
  line-height: 1.35;
  color: var(--sys-ink-faint);
  letter-spacing: var(--sys-track-body);
}
.sys-root .mrc-hint[data-tone="warn"]{ color: var(--sys-accent-gold); }
.sys-root .mrc-hint[data-tone="danger"]{ color: var(--sys-accent-red); }
.sys-root .mrc-hint[data-tone="busy"]{ color: var(--sys-accent-cyan); }

.mrc-hint__msg { flex: 1; min-width: 0; }

.sys-root .mrc-count{
  flex: none;
  font-family: var(--sys-font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--sys-ink-faint);
}
.sys-root .mrc-count[data-over="near"]{ color: var(--sys-accent-gold); }
.sys-root .mrc-count[data-over="yes"]{ color: var(--sys-accent-red); }

kbd.mrc-kbd {
  padding: 0.2em 0.45em;
  border: 1px solid rgb(var(--sys-rgb-hairline) / 0.34);
  border-radius: 4px;
  background: rgb(var(--sys-rgb-lift) / 0.12);
  font-family: var(--sys-font-mono);
  font-size: 0.92em;
  color: var(--sys-ink-dim);
}

/* ---------------------------------------------------------------------------
   4. THE NAMING FLOW

   A modal .sys-panel with our field inside it. Deliberately not a settings
   form: the copy is the System addressing the player, so the prose keeps the
   kit's voice and the input is the only interactive thing on screen.
   ------------------------------------------------------------------------ */

.sys-root .mrc-name{
  display: flex;
  flex-direction: column;
  gap: 2.6cqi;
  text-align: left;
}

.sys-root .mrc-name__field{
  width: 100%;
  padding: 2.8cqi 3cqi;
  min-height: 44px;
  border: 1px solid rgb(var(--sys-rgb-accent) / 0.45);
  border-radius: var(--sys-r-btn);
  background: color-mix(in srgb, var(--sys-field) 60%, transparent);
  color: var(--sys-accent);
  font-family: var(--sys-font);
  font-size: 4.6cqi;
  font-weight: 700;
  letter-spacing: var(--sys-track-title);
  text-align: center;
  text-shadow: var(--sys-accent-glow);
  transition: border-color 160ms var(--sys-ease-settle),
              box-shadow 160ms var(--sys-ease-settle);
}
.sys-root .mrc-name__field::placeholder{
  color: var(--sys-ink-faint);
  font-family: var(--sys-font);
  font-style: normal;
  font-weight: 400;
  letter-spacing: var(--sys-track-body);
  text-shadow: none;
}
.sys-root .mrc-name__field:focus{
  outline: none;
  border-color: rgb(var(--sys-rgb-accent) / 0.95);
  box-shadow: 0 0 22px rgb(var(--sys-rgb-accent) / 0.35);
}
.sys-root .mrc-name__field[aria-invalid="true"]{
  border-color: color-mix(in srgb, var(--sys-accent-red) 80%, transparent);
  color: var(--sys-accent-red);
  text-shadow: none;
}

.sys-root .mrc-name__note{
  min-height: 2.6em;
  margin: 0;
  font-size: 2.9cqi;
  line-height: 1.45;
  color: var(--sys-ink-faint);
  letter-spacing: var(--sys-track-body);
}
.sys-root .mrc-name__note[data-tone="danger"]{ color: var(--sys-accent-red); }
.sys-root .mrc-name__note[data-tone="busy"]{ color: var(--sys-accent-cyan); }

/* ---------------------------------------------------------------------------
   4b. WORKAROUND — a modal .sys-panel is buried under its own scrim

   FOUND 2026-08-23 while wiring the naming flow. Reproduces in the kit with
   nothing of ours involved:  System.panel({ scrim: true })  →  every button in
   that panel is unclickable.

   Why: system-ui.js appends the scrim node to the overlay ROOT, and
   system-ui.css gives .sys-scrim  z-index: calc(var(--sys-z-alert) - 1),
   i.e. base+39. .sys-layer--panel is base+30. So the scrim lands ABOVE the
   panel layer and swallows the clicks. Alerts are unaffected — their layer is
   base+40, one above the scrim — which is why this only bites panels.

   THE REAL FIX belongs in the kit: give the scrim the band of the surface that
   owns it. Until then, the modal panel LAYER is lifted into the alert band
   while one of OUR modal panels is open, and only then. We do not set --sys-z
   on a surface (CONTRACT.md §8.5) and we do not invent a value: the band token
   is used as-is. companion.js adds and removes .mrc-modal-lift around the
   naming panel, so nothing outside that moment is affected.
   ------------------------------------------------------------------------ */

.sys-root.mrc-modal-lift .sys-layer--panel { z-index: var(--sys-z-alert); }

/* ---------------------------------------------------------------------------
   5. THE DOCK CHIP  (requirement 4)

   The kit owns the chip's geometry, position and stacking. We add exactly two
   things: an idle calm so it does not fight the map, and an unmistakable
   offline state so the dock reflects requirement 5 without opening anything.
   ------------------------------------------------------------------------ */

.sys-layer--dock .sys-chip {
  /* Unobtrusive over gameplay. The kit already brightens the chip on hover
     and whenever data-unread is non-zero, so this only affects the idle,
     nothing-to-say state. */
  opacity: 0.74;
  transition: opacity 200ms var(--sys-ease-settle),
              filter 200ms var(--sys-ease-settle);
}
.sys-layer--dock .sys-chip:hover,
.sys-layer--dock .sys-chip:focus-visible,
.sys-layer--dock .sys-chip[data-unread]:not([data-unread="0"]) {
  opacity: 1;
}

/* Deactivated: the light goes out. Same chip, same position, same hit target
   — a player can still click it to come back, which is how they turn it on. */
.sys-chip.mrc-chip--off {
  filter: saturate(0.18);
  opacity: 0.6;
}
.sys-chip.mrc-chip--off .sys-chip__dot {
  background: none;
  box-shadow: inset 0 0 0 1px rgb(var(--sys-rgb-hairline) / 0.5);
  color: transparent;
}
.sys-chip.mrc-chip--off:hover { opacity: 0.9; }

/* Thinking: the chip breathes while a reply is in flight, so a player who
   minimised mid-question can see that something is still happening. */
.sys-chip.mrc-chip--busy .sys-chip__dot {
  animation: mrc-pulse 1.1s ease-in-out infinite;
}
@keyframes mrc-pulse {
  0%, 100% { box-shadow: 0 0 0 rgb(var(--sys-rgb-accent) / 0); }
  50%      { box-shadow: 0 0 12px 2px rgb(var(--sys-rgb-accent) / 0.75); }
}

/* ---------------------------------------------------------------------------
   6. REDUCED MOTION / FORCED COLOURS
   The kit handles its own; these are ours. (CONTRACT.md §8.6)
   ------------------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  .sys-chip.mrc-chip--busy .sys-chip__dot { animation: none; }
  .sys-root .mrc-input, .sys-root .mrc-power, .sys-root .mrc-name__field{ transition: none; }
}

@media (forced-colors: active) {
  .sys-root .mrc-input, .sys-root .mrc-power, .sys-root .mrc-name__field{ border: 1px solid ButtonBorder; }
  .sys-root .mrc-power[aria-pressed="true"]{ forced-color-adjust: none; }
}

/* ---------------------------------------------------------------------------
   7. NARROW VIEWPORTS
   Below ~560px the kit already goes full-width for toasts. The window follows
   its own clamp; all we do is stop the composer from crushing the send button.
   ------------------------------------------------------------------------ */

@media (max-width: 560px) {
  .sys-window[data-mrc-chat] { --mrc-transcript-h: clamp(140px, 34vh, 300px); }
  .sys-root .mrc-compose{ flex-wrap: wrap; }
  .sys-root .mrc-send{ width: 100%; }
}
