/* =====================================================================
   Lario product layer.

   The brand sheet describes a marketing site. It has no text field, no
   select, no checkbox, no table, no status, no toast and no modal, so none
   of a Lario product screen can be built from it. Everything below fills
   that gap: built only from brand tokens, in the brand's shape and motion.

   Load it AFTER lario.css. Nothing in here edits a brand rule.

   Three colours are new. The brand palette has no semantic colour at all -
   lime is 2.05:1 on white, orange is reserved for rating stars, and there
   is no red. An invoicing product cannot say "payment failed" without one.
   See foundations/status.html for the derivation and the measurements.
   ===================================================================== */

:root {
  /* Status. Derived by darkening along the brand's own hues until each one
     passes 4.5:1 as text on white. The three sit in a 5.11-5.44 band so no
     one of them shouts louder than the others. */
  --lr-paid:    light-dark(#4C7A1F, #6B9A42);
  --lr-pending: light-dark(#A85600, #D07B38);
  --lr-failed:  light-dark(#C0392B, #F16655);

  /*            light     on #FFF   dark      on #1D1D20   hue
     paid       #4C7A1F    5.11:1   #6B9A42    5.07:1      132.8 -> 132.5
     pending    #A85600    5.26:1   #D07B38    5.26:1       55.5 ->  55.8
     failed     #C0392B    5.44:1   #F16655    5.42:1       29.7 ->  29.4

     These three are the only colours in the system that needed a dark
     step. The dark values hold the light one's hue and chroma exactly and
     raise lightness until the contrast lands back in the same 5.07-5.46
     band, so no status shouts louder than the others in either theme.
     Carrying the light values over would have put them at 3.09-3.29:1 on
     the dark canvas - passing 3:1 as a mark, failing 4.5:1 as the badge
     text they actually are. */

  /* Control radii. The brand's surface scale starts at 15px, which turns a
     22px checkbox into a circle. These three sit below it. */
  --lr-r-field: 18px;
  --lr-r-check: 7px;     /* 11px on a 22px box is a circle - and then a
                            checkbox and a radio look identical */
  --lr-r-switch: 13px;
}

/* --------------------------------------------------------------- fields */
.lr-field { display: flex; flex-direction: column; gap: 8px; }
.lr-label { font: 400 14px/1.5 var(--lr-font-text); letter-spacing: .01em; color: var(--lr-ink); }
.lr-label .lr-opt { color: var(--lr-ink-2); }

.lr-input, .lr-textarea, .lr-select {
  width: 100%;
  padding: 12px 16px;
  background: var(--lr-mist);
  border: 1px solid var(--lr-line);
  border-radius: calc(var(--lr-r-field) * var(--lr-k));
  corner-shape: superellipse(1.5);
  color: var(--lr-ink);
  font: 400 16px/1.5 var(--lr-font-text);
  letter-spacing: .01em;
  transition: background-color .4s var(--lr-spring), border-color .4s var(--lr-spring);
}
.lr-textarea { min-height: 120px; resize: vertical; }
.lr-input::placeholder, .lr-textarea::placeholder { color: var(--lr-gray); }
.lr-input:hover, .lr-textarea:hover, .lr-select:hover { border-color: var(--lr-ink-2); }
.lr-input:focus, .lr-textarea:focus, .lr-select:focus {
  background: var(--lr-paper);
  border-color: var(--lr-ink);
}
.lr-input:focus-visible, .lr-textarea:focus-visible, .lr-select:focus-visible {
  outline: 2px solid var(--lr-ink);
  outline-offset: 3px;
}
.lr-input:disabled, .lr-textarea:disabled, .lr-select:disabled {
  color: var(--lr-gray);
  border-color: var(--lr-line-soft);
  cursor: not-allowed;
}
.lr-input[readonly] { color: var(--lr-ink-2); }

.lr-hint { font: 400 14px/1.5 var(--lr-font-text); letter-spacing: .01em; color: var(--lr-ink-2); }
.lr-err {
  display: flex; align-items: center; gap: 6px;
  font: 400 14px/1.5 var(--lr-font-text); letter-spacing: .01em;
  color: var(--lr-failed);
}
.lr-err svg { width: 16px; height: 16px; flex: none; fill: currentColor; }
.lr-field--invalid :is(.lr-input, .lr-textarea, .lr-select) { border-color: var(--lr-failed); }

/* money and other prefixed inputs */
.lr-input-wrap { position: relative; display: flex; align-items: center; }
.lr-input-wrap .lr-input { padding-right: 44px; }
.lr-input-wrap__suffix {
  position: absolute; right: 16px;
  font: 400 16px/1.5 var(--lr-font-text); color: var(--lr-ink-2);
  pointer-events: none;
}
.lr-input--num { font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------- select */
.lr-select-wrap { position: relative; display: block; }
.lr-select { appearance: none; padding-right: 44px; cursor: pointer; }
.lr-select-wrap svg {
  position: absolute; top: 50%; right: 16px;
  width: 20px; height: 20px;
  transform: translateY(-50%);
  fill: var(--lr-ink-2);
  pointer-events: none;
}

/* ------------------------------------------------------ checkbox, radio */
/* --------------------------------------------------- custom select */
/* A styled listbox for pointer devices. The native menu is still the right
   answer on a phone, and it is what renders before JavaScript runs - the
   component upgrades to this only when it sees a fine pointer, so the
   platform picker survives where it is genuinely better.

   Focus never enters the popup. The trigger keeps it and points at the
   active option with aria-activedescendant, which is what makes a focus
   trap structurally impossible rather than merely avoided. */

.lr-combo { position: relative; }

/* The trigger is the field shell: same padding, border, radius and states as
   .lr-select, so nothing moves when the component upgrades. */
.lr-combo__btn {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  background: var(--lr-mist);
  border: 1px solid var(--lr-line);
  border-radius: calc(var(--lr-r-field) * var(--lr-k));
  corner-shape: superellipse(1.5);
  color: var(--lr-ink);
  font: 400 16px/1.5 var(--lr-font-text);
  letter-spacing: .01em;
  text-align: left;
  cursor: pointer;
  transition: background-color .4s var(--lr-spring), border-color .4s var(--lr-spring);
}
.lr-combo__btn:hover { border-color: var(--lr-ink-2); }
.lr-combo__btn[aria-expanded="true"] { background: var(--lr-paper); border-color: var(--lr-ink); }
.lr-combo__btn:focus-visible { outline: 2px solid var(--lr-ink); outline-offset: 3px; }
.lr-combo__btn:disabled { color: var(--lr-gray); border-color: var(--lr-line-soft); cursor: not-allowed; }
.lr-field--invalid .lr-combo__btn { border-color: var(--lr-failed); }

.lr-combo__value { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lr-combo__caret { width: 18px; height: 18px; flex: none; fill: var(--lr-ink-2); transition: transform .18s ease-out; }
.lr-combo__btn[aria-expanded="true"] .lr-combo__caret { transform: rotate(180deg); }

/* The popup. A menu is a direct response to a key or a click, so it moves at
   180ms rather than the brand's 0.4s hover spring. */
.lr-combo__list {
  position: absolute;
  z-index: 40;
  top: calc(100% + 8px);
  left: 0;
  right: 0;
  max-height: 264px;
  overflow-y: auto;
  margin: 0;
  padding: 6px;
  list-style: none;
  background: var(--lr-paper);
  border: 1px solid var(--lr-line-soft);
  border-radius: calc(20px * var(--lr-k));
  corner-shape: superellipse(1.5);
  box-shadow: var(--lr-shadow-float);
  transform-origin: top center;
  animation: lr-combo-in .18s ease-out;
}
@keyframes lr-combo-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

.lr-combo__opt {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;              /* the touch floor, even on a pointer device */
  padding: 8px 12px;
  border-radius: calc(15px * var(--lr-k));
  corner-shape: superellipse(1.5);
  color: var(--lr-ink-2);
  cursor: pointer;
}
.lr-combo__opt:hover { background: var(--lr-mist); color: var(--lr-ink); }
/* The keyboard's position. Focus is still on the trigger, so this is the only
   thing telling a sighted keyboard user where they are - it has to be at
   least as loud as hover. */
.lr-combo__opt[data-active] { background: var(--lr-mist); color: var(--lr-ink); }
.lr-combo__opt[aria-selected="true"] { color: var(--lr-ink); font-weight: 500; }
.lr-combo__opt[aria-disabled="true"] { color: var(--lr-gray); cursor: not-allowed; }
.lr-combo__tick { width: 16px; height: 16px; flex: none; fill: currentColor; opacity: 0; }
.lr-combo__opt[aria-selected="true"] .lr-combo__tick { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .lr-combo__list { animation: none; }
  .lr-combo__caret, .lr-combo__btn { transition: none; }
}

.lr-choice {
  position: relative;
  display: flex; align-items: flex-start; gap: 12px;
  padding: 11px 0;                 /* 22px box + 22px = a 44px target */
  cursor: pointer;
  color: var(--lr-ink);
  font: 400 16px/1.5 var(--lr-font-text);
  letter-spacing: .01em;
}
.lr-choice input {
  position: absolute; width: 22px; height: 22px; margin: 0;
  opacity: 0; cursor: pointer;     /* stays focusable and hit-testable */
}
.lr-box {
  display: grid; place-items: center;
  width: 22px; height: 22px; flex: none;
  margin-top: 1px;
  background: var(--lr-paper);
  border: 1px solid var(--lr-ink-2);
  border-radius: calc(var(--lr-r-check) * var(--lr-k));
  corner-shape: superellipse(1.5);
  color: transparent;
  transition: background-color .4s var(--lr-spring), border-color .4s var(--lr-spring), color .4s var(--lr-spring);
}
.lr-box svg { width: 14px; height: 14px; fill: currentColor; }
.lr-choice--radio .lr-box { border-radius: 50%; corner-shape: normal; }
.lr-box .lr-dot { width: 10px; height: 10px; border-radius: 50%; background: currentColor; }
.lr-choice input:checked ~ .lr-box { background: var(--lr-ink); border-color: var(--lr-ink); color: var(--lr-mist); }
.lr-choice input:focus-visible ~ .lr-box { outline: 2px solid var(--lr-ink); outline-offset: 3px; }
.lr-choice input:disabled ~ .lr-box { background: var(--lr-mist); border-color: var(--lr-line); }
.lr-choice:has(input:disabled) { color: var(--lr-gray); cursor: not-allowed; }
.lr-choice__copy { display: flex; flex-direction: column; gap: 2px; }
.lr-choice__copy small { font-size: 14px; color: var(--lr-ink-2); }

/* --------------------------------------------------------------- switch */
.lr-toggle { position: relative; display: inline-flex; align-items: center; gap: 12px; padding: 9px 0; cursor: pointer; }
.lr-toggle input { position: absolute; width: 44px; height: 26px; margin: 0; opacity: 0; cursor: pointer; }
.lr-switch {
  position: relative; flex: none;
  width: 44px; height: 26px;
  background: var(--lr-gray);
  border-radius: var(--lr-r-switch);
  transition: background-color .4s var(--lr-spring);
}
.lr-switch::after {
  content: "";
  position: absolute; top: 3px; left: 3px;
  width: 20px; height: 20px;
  background: var(--lr-paper);
  border-radius: 50%;
  transition: transform .4s var(--lr-spring);
}
.lr-toggle input:checked ~ .lr-switch { background: var(--lr-ink); }
.lr-toggle input:checked ~ .lr-switch::after { transform: translateX(18px); }
.lr-toggle input:focus-visible ~ .lr-switch { outline: 2px solid var(--lr-ink); outline-offset: 3px; }
.lr-toggle input:disabled ~ .lr-switch { background: var(--lr-line); }

/* --------------------------------------------------------------- status */
.lr-badge {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 5px 12px;
  background: var(--lr-mist);
  border: 1px solid var(--lr-line-soft);
  border-radius: calc(15px * var(--lr-k));
  corner-shape: superellipse(1.5);
  color: var(--lr-ink);
  font: 500 12px/1.5 var(--lr-font-text);
  letter-spacing: .01em;
  white-space: nowrap;
}
.lr-badge::before {
  content: "";
  width: 8px; height: 8px; flex: none;
  border-radius: 50%;
  background: var(--lr-dot, var(--lr-ink-2));
}
.lr-badge--paid    { --lr-dot: var(--lr-paid); }
.lr-badge--pending { --lr-dot: var(--lr-pending); }
.lr-badge--failed  { --lr-dot: var(--lr-failed); }

/* ---------------------------------------------------------------- toast */
/* The stack a ToastProvider renders into. Bottom-centre on a phone so it sits
   above the thumb, bottom-right from 600px. Stays clear of the safe area. */
.lr-toast-region {
  position: fixed;
  z-index: 60;
  left: 16px; right: 16px;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  display: flex;
  flex-direction: column;
  gap: 12px;
  pointer-events: none;
}
.lr-toast-region:empty { display: none; }
.lr-toast-region > * { pointer-events: auto; }
@media (min-width: 600px) {
  .lr-toast-region { left: auto; right: 24px; bottom: 24px; max-width: 420px; }
}

.lr-toast {
  display: flex; align-items: flex-start; gap: 12px;
  max-width: 400px; padding: 16px 20px;
  background: var(--lr-ink);
  border-radius: calc(20px * var(--lr-k));
  corner-shape: superellipse(1.5);
  color: var(--lr-mist);
  font: 400 16px/1.5 var(--lr-font-text);
  letter-spacing: .01em;
  box-shadow: var(--lr-shadow-float);
}
.lr-toast svg { width: 20px; height: 20px; flex: none; margin-top: 2px; fill: var(--lr-mist); }
.lr-toast strong { display: block; color: var(--lr-mist); font-weight: 500; }
.lr-toast__close {
  margin-left: auto; padding: 0; background: none; border: 0;
  color: var(--lr-mist); cursor: pointer;
}
.lr-toast__close svg { width: 18px; height: 18px; margin: 0; }
.lr-toast__close:focus-visible { outline: 2px solid var(--lr-mist); outline-offset: 3px; border-radius: 4px; }

/* ---------------------------------------------------------------- table */
.lr-table-wrap { width: 100%; overflow-x: auto; }
.lr-table {
  width: 100%;
  border-collapse: collapse;
  font: 400 16px/1.5 var(--lr-font-text);
  letter-spacing: .01em;
  font-variant-numeric: tabular-nums;
}
.lr-table th {
  padding: 0 16px 12px 0;
  border-bottom: 1px solid var(--lr-line);
  color: var(--lr-ink-2);
  font: 500 12px/1.5 var(--lr-font-text);
  text-align: left;
  white-space: nowrap;
}
.lr-table td {
  padding: 16px 16px 16px 0;
  border-bottom: 1px solid var(--lr-line-soft);
  color: var(--lr-ink-2);
  vertical-align: middle;
}
.lr-table td:first-child, .lr-table th:first-child { color: var(--lr-ink); }
.lr-table :is(td, th):last-child { padding-right: 0; }
.lr-table .lr-num { text-align: right; font-variant-numeric: tabular-nums; }
.lr-table tbody tr { transition: background-color .4s var(--lr-spring); }
.lr-table tbody tr:hover { background: var(--lr-mist); }
.lr-table tbody tr:last-child td { border-bottom: 0; }
.lr-table caption { padding-bottom: 16px; text-align: left; color: var(--lr-ink-2); font-size: 14px; }

/* ----------------------------------------------------------- empty state */
.lr-empty {
  display: flex; flex-direction: column; align-items: center; gap: 20px;
  padding: 48px 32px;
  background: var(--lr-mist);
  border: 1px solid var(--lr-line);
  border-radius: calc(28px * var(--lr-k));
  corner-shape: superellipse(1.5);
  text-align: center;
}
.lr-empty__copy { display: flex; flex-direction: column; gap: 8px; max-width: 360px; }

/* -------------------------------------------------------------- skeleton */
.lr-skel {
  background: var(--lr-line-soft);
  border-radius: calc(15px * var(--lr-k));
  corner-shape: superellipse(1.5);
  animation: lr-pulse 1.6s ease-in-out infinite;
}
.lr-skel--text { height: 14px; }
.lr-skel--title { height: 22px; }
.lr-skel--circle { border-radius: 50%; corner-shape: normal; }
@keyframes lr-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .5; } }

/* ----------------------------------------------------------------- modal */
.lr-modal {
  width: min(480px, 100%);
  padding: 32px;
  background: var(--lr-paper);
  border: 0;
  border-radius: calc(45px * var(--lr-k));
  corner-shape: superellipse(1.5);
  color: var(--lr-ink-2);
}
.lr-modal::backdrop { background: var(--lr-scrim); }
.lr-modal__body { display: flex; flex-direction: column; gap: 24px; }
.lr-modal__copy { display: flex; flex-direction: column; gap: 12px; }
.lr-modal__actions { display: flex; flex-wrap: wrap; gap: 12px; }

@media (max-width: 809.98px) {
  .lr-modal { padding: 24px; border-radius: calc(32px * var(--lr-k)); }
  .lr-modal__actions .lr-btn { flex: 1 1 auto; }
}

/* ------------------------------------------------------- screen reader */
/* For text that has to be announced but not seen - a loading state beside
   a skeleton, a live region, a label a visual design leaves implicit. */
.lr-sr {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------------------------------------------------------------- action */

/* The brand sheet has one button and nothing else that acts. A product screen
   needs a row of actions on an invoice, a menu of the ones that do not fit, a
   view switcher and a toolbar - none of which can be built from .lr-btn alone.
   Everything below is the brand button's shape, motion and ink, re-cut.

   Two things are deliberately absent. There is no second shadow: the elevation
   page says one shadow, five places, and a raised segment would have made it
   six. And nothing here flattens a corner to join two controls - the squircle
   does not survive being cut in half, so a group is a hairline box with
   hairline dividers instead. */

/* Icon button. The brand button with the label taken out, which is the whole
   difficulty: the name has to come from somewhere, and that somewhere is
   aria-label or a visually hidden span. See components/icon-button.html. */
.lr-icon-btn {
  --r: 18px;
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0;
  border: 1px solid transparent; background: transparent;
  border-radius: calc(var(--r) * var(--lr-k)); corner-shape: superellipse(1.5);
  color: var(--lr-ink-2); cursor: pointer;
  transition: background-color .4s var(--lr-spring), color .4s var(--lr-spring),
              border-color .4s var(--lr-spring);
}
.lr-icon-btn svg { width: 20px; height: 20px; fill: currentColor; }
.lr-icon-btn:hover { background: var(--lr-mist); color: var(--lr-ink); }
.lr-icon-btn[aria-expanded="true"] { background: var(--lr-mist); color: var(--lr-ink); }
.lr-icon-btn:focus-visible { outline: 2px solid var(--lr-ink); outline-offset: 3px; }
.lr-icon-btn:disabled { color: var(--lr-gray); cursor: not-allowed; }
.lr-icon-btn--solid { background: var(--lr-ink); border-color: var(--lr-ink); color: var(--lr-mist); }
.lr-icon-btn--solid:hover { background: transparent; color: var(--lr-ink); }
.lr-icon-btn--outline { border-color: var(--lr-line); }
.lr-icon-btn--outline:hover { background: transparent; border-color: var(--lr-ink); color: var(--lr-ink); }
/* 40px is comfortable with a mouse and two pixels short of the touch floor. */
@media (pointer: coarse) { .lr-icon-btn { width: 44px; height: 44px; } }

/* Link. Ink text with a gray rule under it that darkens on hover, so the link
   is not carried by colour alone - the palette has no link blue and is not
   getting one. */
.lr-link {
  color: var(--lr-ink);
  text-decoration: underline; text-decoration-thickness: 1px;
  text-underline-offset: 3px; text-decoration-color: var(--lr-gray);
  transition: text-decoration-color .4s var(--lr-spring), color .4s var(--lr-spring);
}
.lr-link:hover { text-decoration-color: var(--lr-ink); }
.lr-link:focus-visible { outline: 2px solid var(--lr-ink); outline-offset: 2px; border-radius: 4px; }
.lr-link--quiet { color: var(--lr-ink-2); text-decoration: none; }
.lr-link--quiet:hover { color: var(--lr-ink); text-decoration: underline; text-decoration-color: var(--lr-gray); }
.lr-link__ext { width: 14px; height: 14px; fill: currentColor; vertical-align: -2px; margin-left: 4px; }

/* Button group. One hairline box, hairline dividers, square inner corners
   because the box already carries the radius. The focus ring is inset: the
   box clips its overflow, and an outline outside the child would be cut off
   by it on the first and last segment. */
.lr-btn-group {
  display: inline-flex; align-items: stretch; overflow: hidden;
  background: var(--lr-paper); border: 1px solid var(--lr-line);
  border-radius: calc(20px * var(--lr-k)); corner-shape: superellipse(1.5);
}
.lr-btn-group > * + * { border-left: 1px solid var(--lr-line); }
.lr-btn-group :is(.lr-btn, .lr-icon-btn, .lr-btn-group__item) {
  --r: 0;
  border: 0; border-radius: 0; background: transparent; color: var(--lr-ink-2);
}
.lr-btn-group .lr-btn-group__item {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 40px; padding: 0 16px;
  font: 400 14px/1 var(--lr-font-text); white-space: nowrap; cursor: pointer;
  transition: background-color .4s var(--lr-spring), color .4s var(--lr-spring);
}
.lr-btn-group .lr-btn-group__item svg { width: 16px; height: 16px; fill: currentColor; }
.lr-btn-group :is(.lr-btn, .lr-icon-btn, .lr-btn-group__item):hover {
  background: var(--lr-mist); color: var(--lr-ink);
}
.lr-btn-group :is(.lr-btn, .lr-icon-btn, .lr-btn-group__item):focus-visible {
  outline: 2px solid var(--lr-ink); outline-offset: -2px;
}
.lr-btn-group :is(.lr-btn, .lr-icon-btn, .lr-btn-group__item):disabled { color: var(--lr-gray); cursor: not-allowed; }
/* The split button: one real action, and a caret for the rest of them. */
.lr-btn-group--split .lr-btn-group__item:first-child { color: var(--lr-ink); }
.lr-btn-group--split .lr-icon-btn { width: 36px; }

/* Segmented control. A mist track; the chosen segment is paper and ink. No
   shadow, no sliding indicator - the brand has one shadow and one spring, and
   neither is for this. */
.lr-seg {
  display: inline-flex; gap: 2px; padding: 3px;
  background: var(--lr-mist); border: 1px solid var(--lr-line);
  border-radius: calc(18px * var(--lr-k)); corner-shape: superellipse(1.5);
}
.lr-seg__item { position: relative; display: inline-flex; }
.lr-seg__item input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.lr-seg__label {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 34px; padding: 0 16px;
  border-radius: calc(15px * var(--lr-k)); corner-shape: superellipse(1.5);
  font: 400 14px/1 var(--lr-font-text); color: var(--lr-ink-2); white-space: nowrap;
  transition: background-color .4s var(--lr-spring), color .4s var(--lr-spring);
}
.lr-seg__label svg { width: 16px; height: 16px; fill: currentColor; }
.lr-seg__item input:checked + .lr-seg__label { background: var(--lr-paper); color: var(--lr-ink); }
.lr-seg__item input:focus-visible + .lr-seg__label { outline: 2px solid var(--lr-ink); outline-offset: 2px; }
.lr-seg__item input:disabled + .lr-seg__label { color: var(--lr-gray); cursor: not-allowed; }

/* Toggle button. Off is an outline, on is the ink fill - the same inversion
   the brand button performs on hover, held as a state instead. */
.lr-tbtn {
  --r: 18px;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 38px; padding: 0 16px;
  border: 1px solid var(--lr-line); background: var(--lr-paper);
  border-radius: calc(var(--r) * var(--lr-k)); corner-shape: superellipse(1.5);
  font: 400 14px/1 var(--lr-font-text); color: var(--lr-ink-2);
  white-space: nowrap; cursor: pointer;
  transition: background-color .4s var(--lr-spring), color .4s var(--lr-spring),
              border-color .4s var(--lr-spring);
}
.lr-tbtn svg { width: 18px; height: 18px; fill: currentColor; }
.lr-tbtn:hover { border-color: var(--lr-ink-2); color: var(--lr-ink); }
.lr-tbtn[aria-pressed="true"] { background: var(--lr-ink); border-color: var(--lr-ink); color: var(--lr-mist); }
.lr-tbtn[aria-pressed="true"]:hover { background: var(--lr-ink); color: var(--lr-mist); }
.lr-tbtn:focus-visible { outline: 2px solid var(--lr-ink); outline-offset: 3px; }
.lr-tbtn:disabled { color: var(--lr-gray); border-color: var(--lr-line-soft); cursor: not-allowed; }

/* Toggle button group. A row of them. The single-select form is radios, so the
   browser enforces that exactly one is chosen and arrow keys already work. */
.lr-tgroup { display: inline-flex; flex-wrap: wrap; gap: 8px; }
.lr-tgroup__item { position: relative; display: inline-flex; }
.lr-tgroup__item input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.lr-tgroup__item input:checked + .lr-tbtn { background: var(--lr-ink); border-color: var(--lr-ink); color: var(--lr-mist); }
.lr-tgroup__item input:focus-visible + .lr-tbtn { outline: 2px solid var(--lr-ink); outline-offset: 3px; }
.lr-tgroup__item input:disabled + .lr-tbtn { color: var(--lr-gray); border-color: var(--lr-line-soft); cursor: not-allowed; }

/* Menu popup. Same geometry and the same 180ms as the select's listbox, which
   is why it borrows that animation rather than declaring a second one: a menu
   and a listbox differ in semantics, not in how they arrive. .lr-combo__list
   should fold into this the next time the select is touched. */
.lr-dropdown { position: relative; display: inline-flex; }
.lr-pop {
  position: absolute; z-index: 40; top: calc(100% + 8px); left: 0;
  min-width: 208px; margin: 0; padding: 6px; list-style: none;
  background: var(--lr-paper); border: 1px solid var(--lr-line-soft);
  border-radius: calc(20px * var(--lr-k)); corner-shape: superellipse(1.5);
  box-shadow: var(--lr-shadow-float);
  transform-origin: top center;
  animation: lr-combo-in .18s ease-out;
}
.lr-pop--right { left: auto; right: 0; }
.lr-pop__item {
  display: flex; align-items: center; gap: 10px;
  width: 100%; min-height: 44px; padding: 8px 12px;
  border: 0; background: transparent; text-align: left;
  border-radius: calc(15px * var(--lr-k)); corner-shape: superellipse(1.5);
  font: 400 15px/1.4 var(--lr-font-text); color: var(--lr-ink-2); cursor: pointer;
}
.lr-pop__item svg { width: 18px; height: 18px; flex: none; fill: currentColor; }
.lr-pop__item:hover { background: var(--lr-mist); color: var(--lr-ink); }
/* Roving focus moves the ring itself, so this only has to mark hover's twin. */
.lr-pop__item[data-active] { background: var(--lr-mist); color: var(--lr-ink); }
.lr-pop__item:focus-visible { outline: 2px solid var(--lr-ink); outline-offset: -2px; }
.lr-pop__item:disabled, .lr-pop__item[aria-disabled="true"] { color: var(--lr-gray); cursor: not-allowed; }
.lr-pop__item--danger { color: var(--lr-failed); }
.lr-pop__item--danger:hover { background: var(--lr-mist); color: var(--lr-failed); }
.lr-pop__item__key { margin-left: auto; font: 400 13px/1 var(--lr-font-code); color: var(--lr-gray); }
.lr-pop__sep { height: 1px; margin: 6px 8px; background: var(--lr-line-soft); }
.lr-pop__label {
  padding: 8px 12px 4px;
  font: 400 13px/1.4 var(--lr-font-text); color: var(--lr-ink-2);
}

/* Toolbar. A hairline tray for the actions that belong to one thing. */
.lr-toolbar {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px;
  padding: 6px;
  background: var(--lr-paper); border: 1px solid var(--lr-line);
  border-radius: calc(20px * var(--lr-k)); corner-shape: superellipse(1.5);
}
.lr-toolbar__sep { width: 1px; align-self: stretch; margin: 4px 6px; background: var(--lr-line); }
.lr-toolbar__gap { flex: 1 1 auto; }

/* ------------------------------------------------------------------ chat */

/* The assistant surface. Two decisions run through all of it.

   The assistant does not speak in a bubble. Its answer is the page's own
   text - ink, 15px, full measure - and only the person's own words are put
   in one. A conversation where both sides are bubbles reads as a chat app;
   this one has to read as an answer that happens to have been asked for.

   Nothing here invents motion. The thinking dots and a running tool reuse
   lr-pulse, the one loop the system already had, because a second loop would
   be a second thing for a reader to learn and for reduced-motion to switch
   off. */

.lr-chat {
  display: flex; flex-direction: column; min-height: 0; overflow: hidden;
  background: var(--lr-paper); border: 1px solid var(--lr-line);
  border-radius: calc(28px * var(--lr-k)); corner-shape: superellipse(1.5);
}
.lr-chat__log {
  flex: 1; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 20px;
  padding: 24px;
}
.lr-chat__foot { padding: 12px; border-top: 1px solid var(--lr-line-soft); }

/* A message. The person's is a mist bubble on the right; the assistant's is
   text on the page, left, with no fill to read around. */
.lr-msg { display: flex; flex-direction: column; gap: 6px; max-width: 78%; }
.lr-msg--user { align-self: flex-end; align-items: flex-end; }
.lr-msg--agent { align-self: flex-start; max-width: 100%; }
.lr-msg__body {
  font: 400 15px/1.55 var(--lr-font-text); color: var(--lr-ink);
}
.lr-msg--user .lr-msg__body {
  padding: 12px 16px;
  background: var(--lr-mist); border: 1px solid var(--lr-line);
  border-radius: calc(22px * var(--lr-k)); corner-shape: superellipse(1.5);
}
.lr-msg__body p { margin: 0 0 10px; }
.lr-msg__body p:last-child { margin-bottom: 0; }

/* Metadata. Charcoal, 13px, and quiet enough that the answer above it is
   still the thing being read. */
.lr-msg__meta {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px;
  font: 400 13px/1.4 var(--lr-font-text); color: var(--lr-ink-2);
}
.lr-msg__meta time { color: var(--lr-ink-2); }
.lr-msg__actions { display: flex; align-items: center; gap: 2px; }
.lr-msg__actions .lr-icon-btn { width: 32px; height: 32px; }
.lr-msg__actions .lr-icon-btn svg { width: 16px; height: 16px; }
/* 32px is below the touch floor, and the icon button's own coarse-pointer
   rule cannot win against this more specific selector - so it is restated
   here rather than silently lost. */
@media (pointer: coarse) {
  .lr-msg__actions .lr-icon-btn { width: 44px; height: 44px; }
}
.lr-msg__err {
  display: flex; align-items: center; gap: 6px;
  font: 400 13px/1.4 var(--lr-font-text); color: var(--lr-failed);
}
.lr-msg__err svg { width: 16px; height: 16px; flex: none; fill: currentColor; }
.lr-msg--failed .lr-msg__body { border-color: var(--lr-failed); }

/* A system message is the conversation talking about itself: a date, someone
   joining, a thread being closed. Centred, small, and never a bubble. */
.lr-chat-sys {
  align-self: center; display: flex; align-items: center; gap: 12px;
  max-width: 100%;
  font: 400 13px/1.5 var(--lr-font-text); color: var(--lr-ink-2); text-align: center;
}
.lr-chat-sys svg { width: 16px; height: 16px; flex: none; fill: currentColor; }
.lr-chat-sys--rule { width: 100%; }
.lr-chat-sys--rule::before, .lr-chat-sys--rule::after {
  content: ""; flex: 1; height: 1px; background: var(--lr-line-soft);
}

.lr-thinking {
  display: inline-flex; align-items: center; gap: 10px;
  font: 400 14px/1 var(--lr-font-text); color: var(--lr-ink-2);
}
.lr-thinking__dots { display: inline-flex; gap: 4px; }
.lr-thinking__dots i {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--lr-ink-2);
  animation: lr-pulse 1.6s ease-in-out infinite;
}
.lr-thinking__dots i:nth-child(2) { animation-delay: .2s; }
.lr-thinking__dots i:nth-child(3) { animation-delay: .4s; }

/* Tool calls. Collapsed to one line by default, because the answer is the
   point and the work behind it is only interesting when it goes wrong. */
.lr-tools {
  border: 1px solid var(--lr-line-soft);
  border-radius: calc(20px * var(--lr-k)); corner-shape: superellipse(1.5);
}
.lr-tools > summary {
  display: flex; align-items: center; gap: 10px;
  min-height: 44px; padding: 8px 14px;
  font: 400 14px/1.4 var(--lr-font-text); color: var(--lr-ink-2);
  cursor: pointer; list-style: none;
  border-radius: calc(20px * var(--lr-k)); corner-shape: superellipse(1.5);
}
.lr-tools > summary::-webkit-details-marker { display: none; }
.lr-tools > summary:hover { color: var(--lr-ink); }
.lr-tools > summary:focus-visible { outline: 2px solid var(--lr-ink); outline-offset: -2px; }
.lr-tools__caret { width: 16px; height: 16px; flex: none; fill: currentColor; transition: transform .18s ease-out; }
.lr-tools[open] .lr-tools__caret { transform: rotate(90deg); }
.lr-tools__list { margin: 0; padding: 2px 8px 10px; list-style: none; }
.lr-tool {
  display: flex; align-items: center; gap: 10px; padding: 6px 6px;
  font: 400 13px/1.4 var(--lr-font-code); color: var(--lr-ink-2);
}
.lr-tool__state { width: 16px; height: 16px; flex: none; fill: currentColor; }
.lr-tool--ok .lr-tool__state { fill: var(--lr-paid); }
.lr-tool--failed .lr-tool__state { fill: var(--lr-failed); }
.lr-tool--running .lr-tool__state { fill: var(--lr-pending); animation: lr-pulse 1.6s ease-in-out infinite; }
.lr-tool__name { flex: none; color: var(--lr-ink); }
.lr-tool__arg { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lr-tool__time { margin-left: auto; flex: none; color: var(--lr-ink-2); }  /* charcoal, not gray: gray is the disabled step and measures 1.48:1 */

/* The composer. The border follows the text field - darker on focus, with the
   ring only for the keyboard - except that it is drawn on the wrapper, since
   the textarea inside has no border of its own to darken. */
.lr-composer {
  display: flex; align-items: flex-end; gap: 8px;
  padding: 6px 6px 6px 16px;
  background: var(--lr-paper); border: 1px solid var(--lr-line);
  border-radius: calc(26px * var(--lr-k)); corner-shape: superellipse(1.5);
  transition: border-color .4s var(--lr-spring);
}
.lr-composer:hover { border-color: var(--lr-ink-2); }
.lr-composer:focus-within { border-color: var(--lr-ink); }
.lr-composer:has(.lr-composer__input:focus-visible) { outline: 2px solid var(--lr-ink); outline-offset: 3px; }
.lr-composer__input {
  flex: 1; min-width: 0;
  min-height: 32px; max-height: 168px; padding: 10px 0;
  border: 0; background: transparent; resize: none;
  font: 400 15px/1.5 var(--lr-font-text); color: var(--lr-ink);
}
/* The ring belongs to the shell, so the field must not draw its own. The
   documentation chrome has a blanket `.lr :focus-visible` ring and loads
   after this sheet, so at equal specificity it won and both were drawn -
   this selector carries one class more and settles it. */
.lr-composer .lr-composer__input:focus,
.lr-composer .lr-composer__input:focus-visible { outline: none; }
.lr-composer__input::placeholder { color: var(--lr-gray); }
.lr-composer__send { flex: none; align-self: flex-end; }
.lr-composer__hint {
  display: block; margin: 8px 4px 0;
  font: 400 12px/1.4 var(--lr-font-text); color: var(--lr-ink-2);
}

/* -------------------------------------------------------------- citation */

/* An assistant that states a figure has to be able to say where it got it.
   The marker sits in the sentence; the sources sit under the answer.

   The mark on a source is an icon or an initial, never a favicon fetched
   from the site being cited: a remote favicon tells that site which of its
   pages the reader just had summarised, which is not a thing a citation
   should cost. */
.lr-cite {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px;
  margin-left: 3px; vertical-align: 2px;
  background: var(--lr-mist); border: 1px solid var(--lr-line);
  border-radius: calc(9px * var(--lr-k)); corner-shape: superellipse(1.5);
  font: 400 11px/1 var(--lr-font-text); color: var(--lr-ink-2);
  text-decoration: none; cursor: pointer;
  transition: background-color .4s var(--lr-spring), color .4s var(--lr-spring),
              border-color .4s var(--lr-spring);
}
.lr-cite:hover { background: var(--lr-ink); border-color: var(--lr-ink); color: var(--lr-mist); }
.lr-cite:focus-visible { outline: 2px solid var(--lr-ink); outline-offset: 2px; }

.lr-source {
  display: inline-flex; align-items: center; gap: 7px;
  max-width: 100%; padding: 4px 11px 4px 5px;
  background: var(--lr-paper); border: 1px solid var(--lr-line);
  border-radius: calc(15px * var(--lr-k)); corner-shape: superellipse(1.5);
  font: 400 13px/1.3 var(--lr-font-text); color: var(--lr-ink-2);
  text-decoration: none;
  transition: border-color .4s var(--lr-spring), color .4s var(--lr-spring);
}
.lr-source:hover { border-color: var(--lr-ink); color: var(--lr-ink); }
.lr-source:focus-visible { outline: 2px solid var(--lr-ink); outline-offset: 3px; }
.lr-source__mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; flex: none;
  background: var(--lr-mist); border: 1px solid var(--lr-line-soft);
  border-radius: 50%; corner-shape: normal;
  font: 500 11px/1 var(--lr-font-text); color: var(--lr-ink-2);
}
.lr-source__mark svg { width: 12px; height: 12px; fill: currentColor; }
.lr-source__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.lr-sources { display: flex; flex-direction: column; gap: 10px; }
.lr-sources__label { font: 400 13px/1.4 var(--lr-font-text); color: var(--lr-ink-2); }
.lr-sources__list {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin: 0; padding: 0; list-style: none;
}
