/* ==========================================================================
   Component library. Naming: .block, .block__part, .block--variant, .is-state
   Every component reads tokens only, so both themes come for free.
   Live preview: /ui/
   ========================================================================== */

/* ---------- Card ---------- */
.card {
  position: relative;
  min-width: 0;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  padding: var(--sp-5);
}
.card--elevated { background: var(--card-2); }
.card--flush { padding: 0; overflow: hidden; }
.card--interactive { transition: border-color var(--dur-2), transform var(--dur-3) var(--ease-out), box-shadow var(--dur-3); }
.card--interactive:hover { border-color: var(--border-strong); transform: translateY(-2px); box-shadow: var(--shadow-1); }
.card--interactive:active { transform: translateY(0) scale(0.995); }
.card--danger { border-color: color-mix(in srgb, var(--tone-red) 30%, transparent); }
.card--production { border-color: color-mix(in srgb, var(--tone-plum) 28%, var(--border)); }

/* Cursor spotlight (pointer position set by app.js on [data-spotlight]) */
[data-spotlight] { isolation: isolate; }
[data-spotlight]::before {
  content: "";
  position: absolute;
  inset: -1px;
  z-index: -1;
  border-radius: inherit;
  padding: 1px;
  background: radial-gradient(260px circle at var(--mx, 50%) var(--my, 50%), color-mix(in srgb, var(--accent) 45%, transparent), transparent 70%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
  transition: opacity var(--dur-3);
  pointer-events: none;
}
[data-spotlight]:hover::before { opacity: 1; }

.card__head { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-4); min-width: 0; }
.card__title { font-size: var(--fs-base); font-weight: var(--fw-regular); color: var(--text-title); line-height: var(--lh-snug); min-width: 0; }
.card__subtitle { font-size: var(--fs-xs); color: var(--text-3); }
.card__action { margin-inline-start: auto; flex: none; }
.card__foot { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin-top: var(--sp-4); padding-top: var(--sp-4); border-top: 1px solid var(--divider); font-size: var(--fs-sm); color: var(--text-2); }

/* Circular icon chip (Monef card headers) */
.chip-icon {
  width: 36px; height: 36px;
  flex: none;
  display: grid; place-items: center;
  border-radius: var(--r-full);
  background: var(--chip);
  color: var(--text-2);
}
.chip-icon--sm { width: 28px; height: 28px; }
.chip-icon--lg { width: 44px; height: 44px; }
.chip-icon--solid { background: var(--chip-active); color: var(--chip-active-ink); }
.chip-icon--green { background: var(--tone-green-bg); color: var(--tone-green-fg); }
.chip-icon--red { background: var(--tone-red-bg); color: var(--tone-red-fg); }
.chip-icon--amber { background: var(--tone-amber-bg); color: var(--tone-amber-fg); }
.chip-icon--plum { background: var(--tone-plum-bg); color: var(--tone-plum-fg); }
.chip-icon--indigo { background: var(--tone-indigo-bg); color: var(--tone-indigo-fg); }
.chip-icon--sky { background: var(--tone-sky-bg); color: var(--tone-sky-fg); }
.chip-icon--neutral { background: var(--tone-neutral-bg); color: var(--tone-neutral-fg); }

/* Hero card (Monef "AI Assistant") — an aurora surface: --hero-mesh (beam, cone, corner orbs, halo) over the
   --hero-bg base, plus a dot grid (::after) that fades out from the top. ::before stays free for data-spotlight.
   Shared parts: .hero-title (gradient heading) and .hero-field (glass search/ask pill). */
.card--hero {
  background: var(--hero-mesh), var(--hero-bg);
  color: var(--hero-fg);
  border-color: var(--hero-border);
  box-shadow: var(--hero-shadow);
  overflow: hidden;
}
.card--hero::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(circle, var(--hero-pattern) 1px, transparent 1.5px) 50% 0 / 18px 18px;
  -webkit-mask: radial-gradient(ellipse 72% 88% at 50% 0%, #000 8%, transparent 72%);
  mask: radial-gradient(ellipse 72% 88% at 50% 0%, #000 8%, transparent 72%);
  pointer-events: none;
}
.card--hero > * { position: relative; z-index: 1; }
.card--hero .card__title { color: var(--hero-fg-2); }
.card--hero .chip-icon { background: var(--hero-chip); color: var(--hero-accent); box-shadow: inset 0 0 0 1px var(--hero-chip-border); }
.card--hero .kbd { background: var(--hero-chip); border-color: var(--hero-chip-border); color: var(--hero-fg-2); }
.card--hero .hero-title {
  width: fit-content;
  max-width: 100%;
  margin-inline: auto;
  background: var(--hero-title);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* Glass pill with a gradient hairline (no backdrop blur: the mesh behind is smooth, and the focus drift stays cheap). Focus: the hairline brightens and its aurora slowly drifts,
   an indigo ring + glow appear and the pill lifts 1px (static under reduced motion). */
.card--hero .hero-field {
  position: relative;
  background: var(--hero-input);
  border: 1px solid transparent;
  box-shadow: var(--hero-input-shadow);
  color: var(--hero-fg);
  transition: box-shadow var(--dur-3) var(--ease-out), transform var(--dur-3) var(--ease-out);
}
.card--hero .hero-field::before {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 1px;
  background: var(--hero-input-ring) 0 0 / 200% 100%;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0.6;
  pointer-events: none;
  transition: opacity var(--dur-3), padding var(--dur-2);
}
.card--hero .hero-field:hover { border-color: transparent; }
.card--hero .hero-field:hover::before { opacity: 0.9; }
.card--hero .hero-field:focus-within { border-color: transparent; box-shadow: var(--hero-input-shadow), var(--hero-input-focus); transform: translateY(-1px); }
.card--hero .hero-field:focus-within::before { opacity: 1; padding: 1.5px; animation: hero-ring 5s var(--ease-in-out) infinite alternate; }
.card--hero .hero-field input { text-overflow: ellipsis; }
.card--hero .hero-field input::placeholder { color: var(--hero-placeholder); opacity: 1; }
.card--hero .hero-field > .chip-icon { background: transparent; box-shadow: none; color: var(--hero-fg-2); transition: color var(--dur-2), transform var(--dur-3) var(--ease-spring); }
.card--hero .hero-field:focus-within > .chip-icon { color: var(--hero-accent); transform: scale(1.08); }
@keyframes hero-ring { to { background-position: 100% 0; } }
@media (prefers-reduced-motion: reduce) {
  .card--hero .hero-field, .card--hero .hero-field > .chip-icon { transition: none; }
  .card--hero .hero-field:focus-within, .card--hero .hero-field:focus-within > .chip-icon { transform: none; }
  .card--hero .hero-field:focus-within::before { animation: none; }
}

/* ---------- KPI ---------- */
.kpi { display: flex; flex-direction: column; gap: var(--sp-1); }
.kpi__row { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); flex-wrap: wrap; }
.kpi__value { font-size: var(--fs-3xl); font-weight: var(--fw-semibold); line-height: 1.15; letter-spacing: -0.01em; color: var(--text); font-variant-numeric: tabular-nums; }
.kpi__unit { font-size: var(--fs-md); font-weight: var(--fw-regular); color: var(--text-2); margin-inline-start: 4px; }
.kpi__hint { font-size: var(--fs-sm); color: var(--text-3); }

.delta {
  display: inline-flex; align-items: center; gap: 2px;
  height: 26px; padding-inline: 9px;
  border-radius: var(--r-sm);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.delta--up { background: var(--tone-green-bg); color: var(--tone-green-fg); }
.delta--down { background: var(--tone-red-bg); color: var(--tone-red-fg); }

/* ---------- Buttons ---------- */
.btn {
  --btn-h: var(--control-h);
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  height: var(--btn-h);
  padding-inline: var(--sp-5);
  border-radius: var(--r-full);
  border: 1px solid transparent;
  font-size: var(--fs-md);
  font-weight: var(--fw-medium);
  line-height: 1;
  white-space: nowrap;
  user-select: none;
  transition: background var(--dur-2), border-color var(--dur-2), color var(--dur-2), transform var(--dur-1) var(--ease-out), box-shadow var(--dur-2), opacity var(--dur-2);
}
.btn:active:not(:disabled) { transform: scale(0.97); }
.btn:focus-visible { border-radius: var(--r-full); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: 0.45; pointer-events: none; }

.btn--glass { background: var(--glass-bg); border-color: var(--glass-border); box-shadow: var(--glass-highlight); color: var(--text); }
.btn--glass:hover { background: var(--glass-bg-hover); }
.btn--primary { background: var(--accent); color: var(--accent-ink); box-shadow: 0 10px 24px -12px var(--accent-glow); font-weight: var(--fw-semibold); }
.btn--primary:hover { filter: brightness(1.06); box-shadow: 0 14px 30px -12px var(--accent-glow); }
.btn--indigo { background: var(--indigo); color: #fff; box-shadow: 0 10px 24px -12px var(--indigo); }
.btn--indigo:hover { filter: brightness(1.1); }
.btn--secondary { background: var(--chip); color: var(--text); }
.btn--secondary:hover { background: var(--chip-hover); }
.btn--ghost { color: var(--text-2); }
.btn--ghost:hover { color: var(--text); background: var(--hover); }
.btn--danger { background: var(--tone-red); color: #fff; }
.btn--danger:hover { filter: brightness(1.08); }
.btn--danger-soft { background: var(--tone-red-bg); color: var(--tone-red-fg); }
.btn--danger-soft:hover { background: color-mix(in srgb, var(--tone-red) 22%, transparent); }

.btn--sm { --btn-h: var(--control-h-sm); padding-inline: var(--sp-4); font-size: var(--fs-sm); }
.btn--lg { --btn-h: var(--control-h-lg); padding-inline: var(--sp-6); font-size: var(--fs-base); }
.btn--block { width: 100%; }

/* Loading state: <button class="btn is-loading"> keeps its width, shows a spinner */
.btn.is-loading { color: transparent !important; pointer-events: none; }
.btn.is-loading::after {
  content: "";
  position: absolute;
  inset: 0; margin: auto;
  width: 18px; height: 18px;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-color: var(--text) var(--text) var(--text) transparent;
  animation: iv-spin 700ms linear infinite;
}
.btn--primary.is-loading::after { border-color: var(--accent-ink) var(--accent-ink) var(--accent-ink) transparent; }

/* Icon button (Monef round header buttons) */
.icon-btn {
  --ib: var(--control-h);
  position: relative;
  width: var(--ib); height: var(--ib);
  flex: none;
  display: inline-grid; place-items: center;
  border-radius: var(--r-full);
  background: var(--chip);
  color: var(--text-2);
  transition: background var(--dur-2), color var(--dur-2), transform var(--dur-1) var(--ease-out);
}
.icon-btn:hover { background: var(--chip-hover); color: var(--text); }
.icon-btn:active { transform: scale(0.92); }
.icon-btn:focus-visible { border-radius: var(--r-full); }
.icon-btn--sm { --ib: 32px; }
.icon-btn--lg { --ib: 52px; }
.icon-btn--ghost { background: transparent; }
.icon-btn--ghost:hover { background: var(--chip); }
.icon-btn--outline { background: var(--sunken); border: 1px solid var(--border); }
.icon-btn__dot {
  position: absolute; top: 9px; inset-inline-end: 10px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 2px var(--panel);
}

/* Pill action (Monef "Filter" / "Export": icon chip + label) */
.pill-action {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  height: 48px;
  padding-inline: 6px var(--sp-4);
  border-radius: var(--r-full);
  background: var(--sunken);
  border: 1px solid var(--border);
  color: var(--text-2);
  font-size: var(--fs-md);
  white-space: nowrap;
  transition: color var(--dur-2), border-color var(--dur-2), background var(--dur-2);
}
.pill-action .chip-icon { width: 36px; height: 36px; }
.pill-action:hover { color: var(--text); border-color: var(--border-strong); }
.pill-action.is-active { color: var(--text); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.pill-action.is-active .chip-icon { background: var(--accent-soft); color: var(--accent-text); }

/* ---------- Forms ---------- */
.field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.field__label { font-size: var(--fs-sm); font-weight: var(--fw-medium); color: var(--text-title); }
.field__hint { font-size: var(--fs-xs); color: var(--text-3); }
.field__error { display: flex; align-items: center; gap: 6px; font-size: var(--fs-xs); color: var(--tone-red-fg); }

.input, .select, .textarea {
  width: 100%;
  min-width: 0;
  height: var(--control-h);
  padding-inline: var(--sp-4);
  border-radius: var(--r-md);
  border: 1px solid var(--input-border);
  background: var(--input-bg);
  color: var(--text);
  font-size: var(--fs-md);
  transition: border-color var(--dur-2), box-shadow var(--dur-2), background var(--dur-2);
}
.input::placeholder, .textarea::placeholder { color: var(--placeholder); }
.input:hover, .select:hover, .textarea:hover { border-color: var(--input-border-hover); }
.input:focus-visible, .select:focus-visible, .textarea:focus-visible { border-color: var(--indigo); box-shadow: var(--focus-ring); border-radius: var(--r-md); }
.input:disabled, .select:disabled, .textarea:disabled { opacity: 0.5; cursor: not-allowed; }
.input[aria-invalid="true"], .is-invalid .input, .is-invalid .select, .is-invalid .textarea { border-color: var(--tone-red); }
.input[aria-invalid="true"]:focus-visible { box-shadow: var(--focus-ring-danger); }
.input--ltr { direction: ltr; text-align: left; font-family: var(--font-mono); font-size: var(--fs-sm); }
/* Secrets (passwords, keys, tokens): typed LTR so revealed characters keep their order, but anchored to
   the form's start like every other field — beside the leading lock, on the right in RTL. A class, not
   [type=password]: the reveal toggle swaps the type and the text must not jump sides. */
.input--secret { direction: ltr; text-align: end; }
:dir(ltr) > .input--secret { text-align: start; }
.input--secret::-ms-reveal { display: none; }
.textarea { height: auto; min-height: 104px; padding-block: var(--sp-3); line-height: var(--lh-snug); resize: vertical; }

.select {
  appearance: none;
  padding-inline-end: var(--sp-10);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%239e9da7' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: left var(--sp-4) center;
  cursor: pointer;
}
.select option { background: var(--dropdown-bg); color: var(--text); }

/* Input with a leading icon (`> .icon`) and optional end actions (`> .input-wrap__end` of icon buttons).
   The wrap reserves room for both — --iw-lead for the icon, --iw-trail from how many actions it holds —
   and the input applies it against the WRAP's direction, so an LTR value inside the RTL page still clears
   the icon on the right and the buttons on the left. Long values scroll inside that room. */
.input-wrap {
  --iw-lead: var(--sp-4);
  --iw-trail: var(--sp-4);
  --iw-edge: 6px;       /* actions' distance from the field edge */
  --iw-act: 32px;       /* one action button */
  --iw-act-gap: 4px;
  --iw-acts: 0;
  position: relative; display: flex; align-items: center; min-width: 0;
}
.input-wrap:has(> .icon) { --iw-lead: 44px; }
.input-wrap:has(> .input-wrap__end > :nth-child(1)) { --iw-acts: 1; }
.input-wrap:has(> .input-wrap__end > :nth-child(2)) { --iw-acts: 2; }
.input-wrap:has(> .input-wrap__end > :nth-child(3)) { --iw-acts: 3; }
.input-wrap:has(> .input-wrap__end > *) {
  --iw-trail: calc(var(--iw-edge) + var(--iw-acts) * var(--iw-act) + (var(--iw-acts) - 1) * var(--iw-act-gap) + var(--sp-2));
}
.input-wrap > .icon { position: absolute; inset-inline-start: var(--sp-4); color: var(--text-3); pointer-events: none; }
.input-wrap > .input { --iw-from: var(--iw-lead); --iw-to: var(--iw-trail); padding-inline: var(--iw-from) var(--iw-to); }
/* The input's own inline axis runs against the wrap's (an LTR value in the RTL page): swap the sides. */
.input-wrap:dir(rtl) > .input:is(.input--ltr, :dir(ltr)),
.input-wrap:dir(ltr) > .input:dir(rtl) { --iw-from: var(--iw-trail); --iw-to: var(--iw-lead); }
.input-wrap__end { position: absolute; inset-inline-end: var(--iw-edge); display: flex; align-items: center; gap: var(--iw-act-gap); }
.input-wrap__end > .icon-btn { --ib: var(--iw-act); }
/* Touch: 44px hit areas, edge to edge; the chip still paints 32px (content-box), so the field looks the same.
   (Padding, not a pseudo-element hit area, so ::before/::after stay free for the buttons' own states.) */
@media (pointer: coarse) {
  .input-wrap { --iw-edge: 0px; --iw-act: 44px; --iw-act-gap: 0px; }
  .input-wrap__end > .icon-btn { padding: 6px; background-clip: content-box; }
}

/* Monef search: chip icon + borderless pill */
.search {
  display: flex; align-items: center; gap: var(--sp-2);
  height: 48px;
  min-width: 0;
  width: min(380px, 100%);
  padding-inline: 6px var(--sp-3);
  border-radius: var(--r-full);
  background: var(--sunken);
  border: 1px solid var(--border);
  color: var(--text-3);
  font-size: var(--fs-md);
  transition: border-color var(--dur-2), color var(--dur-2), box-shadow var(--dur-2);
  text-align: start;
}
.search:hover { border-color: var(--border-strong); color: var(--text-2); }
.search .chip-icon { background: var(--chip); }
.search__input { flex: 1; min-width: 0; height: 100%; background: none; border: 0; padding: 0; color: var(--text); }
.search__input::placeholder { color: var(--text-3); }
.search__input:focus-visible { box-shadow: none; }
.search:focus-within { border-color: var(--indigo); box-shadow: var(--focus-ring); }
.search--lg { height: 56px; width: 100%; font-size: var(--fs-base); }

.kbd {
  display: inline-flex; align-items: center; justify-content: center; gap: 2px;
  min-width: 24px; height: 24px; padding-inline: 6px;
  border-radius: 7px;
  border: 1px solid var(--border-strong);
  border-bottom-width: 2px;
  background: var(--card-2);
  color: var(--text-2);
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  direction: ltr;
}

/* Checkbox & switch */
.check { display: inline-flex; align-items: center; gap: var(--sp-2); cursor: pointer; font-size: var(--fs-md); }
.check input { appearance: none; width: 20px; height: 20px; flex: none; margin: 0; border-radius: 6px; border: 1.5px solid var(--input-border-hover); background: var(--input-bg); display: grid; place-items: center; transition: background var(--dur-2), border-color var(--dur-2); cursor: pointer; }
.check input::after { content: ""; width: 10px; height: 6px; border: 2px solid var(--accent-ink); border-top: 0; border-right: 0; transform: rotate(-45deg) scale(0); margin-top: -2px; transition: transform var(--dur-2) var(--ease-spring); }
.check input:checked { background: var(--accent); border-color: var(--accent); }
.check input:checked::after { transform: rotate(-45deg) scale(1); }

/* Switch: <label|span class="switch"><input type="checkbox" role="switch"> [text]</label>.
   The knob is the input's own ::before, positioned inside the track (the input is its containing block),
   so it stays centred whatever the label's height or alignment. Variants set the custom properties:
   --switch-w / --switch-h / --switch-knob (size), --switch-on / --switch-knob-on (checked colours).
   State rules below never restate background, border-color or the knob transform, so page variants
   that set those directly keep working. */
.switch {
  --switch-w: 44px;
  --switch-h: 26px;
  --switch-knob: 18px;
  --switch-on: var(--accent);
  --switch-knob-on: var(--accent-ink);
  display: inline-flex; align-items: center; gap: var(--sp-3);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.switch input {
  --_inset: calc((var(--switch-h) - 2px - var(--switch-knob)) / 2); /* 2px = the track's two hairlines */
  --_travel: calc(var(--switch-w) - var(--switch-h));
  position: relative;
  flex: none;
  width: var(--switch-w); height: var(--switch-h);
  margin: 0;
  appearance: none;
  border-radius: var(--r-full);
  border: 1px solid var(--border-strong);
  background: var(--card-3);
  cursor: pointer;
  transition: background-color var(--dur-2), border-color var(--dur-2), box-shadow var(--dur-2);
}
.switch input::before {
  content: "";
  position: absolute;
  top: var(--_inset); inset-inline-start: var(--_inset);
  width: var(--switch-knob); height: var(--switch-knob);
  border-radius: 50%;
  background: var(--text-2);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--overlay) 60%, transparent);
  transition: transform var(--dur-3) var(--ease-spring), background-color var(--dur-2);
}
/* RTL: the knob starts on the right and travels left; [dir="ltr"] islands mirror it. */
.switch input:checked { background: var(--switch-on); border-color: var(--switch-on); }
.switch input:checked::before { background: var(--switch-knob-on); transform: translateX(calc(var(--_travel) * -1)); }
[dir="ltr"] .switch input:checked::before { transform: translateX(var(--_travel)); }
.switch:hover input:not(:checked, :disabled) { border-color: var(--input-border-hover); }
.switch:hover input:not(:checked, :disabled)::before { background: var(--text-title); }
.switch:hover input:not(:disabled, :focus-visible) { box-shadow: 0 0 0 4px var(--chip); }
.switch input:focus-visible { box-shadow: var(--focus-ring); }
.switch:has(input:disabled) { opacity: 0.55; cursor: not-allowed; }
.switch input:disabled { cursor: not-allowed; }
@media (forced-colors: active) {
  .switch input::before { background: CanvasText; }
  .switch input:checked { background: Highlight; border-color: Highlight; }
  .switch input:checked::before { background: HighlightText; }
}

/* Segmented control / tabs */
.segmented {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 4px;
  border-radius: var(--r-full);
  background: var(--sunken);
  border: 1px solid var(--border);
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}
.segmented::-webkit-scrollbar { display: none; }
.segmented__item {
  display: inline-flex; align-items: center; gap: 6px;
  height: 36px;
  padding-inline: var(--sp-4);
  border-radius: var(--r-full);
  color: var(--text-2);
  font-size: var(--fs-sm);
  white-space: nowrap;
  transition: background var(--dur-2), color var(--dur-2), box-shadow var(--dur-2);
}
.segmented__item:hover { color: var(--text); }
.segmented__item.is-active, .segmented__item[aria-selected="true"], .segmented__item[aria-current="page"] {
  background: var(--card-3);
  color: var(--text);
  box-shadow: var(--glass-highlight);
}
.segmented__count { font-size: var(--fs-2xs); color: var(--text-3); }

.tabs { display: flex; gap: var(--sp-1); border-bottom: 1px solid var(--divider); overflow-x: auto; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tabs__item {
  position: relative;
  display: inline-flex; align-items: center; gap: var(--sp-2);
  height: 48px;
  padding-inline: var(--sp-4);
  color: var(--text-2);
  font-size: var(--fs-md);
  white-space: nowrap;
  transition: color var(--dur-2);
}
.tabs__item::after {
  content: "";
  position: absolute;
  inset-inline: var(--sp-3);
  bottom: -1px;
  height: 2px;
  border-radius: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transition: transform var(--dur-3) var(--ease-out);
}
.tabs__item:hover { color: var(--text); }
.tabs__item.is-active, .tabs__item[aria-selected="true"] { color: var(--text); }
.tabs__item.is-active::after, .tabs__item[aria-selected="true"]::after { transform: scaleX(1); }

/* Filter chips */
.filter-chip {
  display: inline-flex; align-items: center; gap: 6px;
  height: 34px;
  padding-inline: var(--sp-3);
  border-radius: var(--r-full);
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-2);
  font-size: var(--fs-sm);
  white-space: nowrap;
  transition: all var(--dur-2);
}
.filter-chip:hover { border-color: var(--border-strong); color: var(--text); }
.filter-chip.is-active, .filter-chip[aria-pressed="true"] { background: var(--accent-soft); border-color: color-mix(in srgb, var(--accent) 40%, transparent); color: var(--accent-text); }

/* ---------- Badges ---------- */
.badge {
  display: inline-flex; align-items: center; gap: 6px;
  height: 26px;
  padding-inline: 10px;
  border-radius: var(--r-full);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  white-space: nowrap;
  line-height: 1;
  background: var(--tone-neutral-bg);
  color: var(--tone-neutral-fg);
}
.badge__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.badge--green { background: var(--tone-green-bg); color: var(--tone-green-fg); }
.badge--red { background: var(--tone-red-bg); color: var(--tone-red-fg); }
.badge--amber { background: var(--tone-amber-bg); color: var(--tone-amber-fg); }
.badge--plum { background: var(--tone-plum-bg); color: var(--tone-plum-fg); }
.badge--indigo { background: var(--tone-indigo-bg); color: var(--tone-indigo-fg); }
.badge--sky { background: var(--tone-sky-bg); color: var(--tone-sky-fg); }
.badge--outline { background: transparent; border: 1px solid var(--border-strong); color: var(--text-2); }
.badge--sm { height: 22px; padding-inline: 8px; font-size: var(--fs-2xs); }
/* Production is never only a color: it gets a glowing pulse dot as well */
.badge--plum.badge--environment .badge__dot { box-shadow: 0 0 0 3px color-mix(in srgb, var(--tone-plum) 25%, transparent); animation: iv-pulse 2.4s ease-in-out infinite; }
.badge--green.badge--status .badge__dot { box-shadow: 0 0 8px var(--tone-green); }

/* ---------- Avatar ---------- */
.avatar {
  --av: 36px;
  width: var(--av); height: var(--av);
  flex: none;
  display: inline-grid; place-items: center;
  border-radius: 50%;
  background: linear-gradient(135deg, hsl(var(--hue) 62% 58%), hsl(calc(var(--hue) + 40) 58% 42%));
  color: #fff;
  font-size: calc(var(--av) * 0.38);
  font-weight: var(--fw-semibold);
  line-height: 1;
  user-select: none;
}
.avatar--xs { --av: 24px; }
.avatar--sm { --av: 30px; }
.avatar--lg { --av: 48px; }
.avatar--xl { --av: 72px; }
.avatar--ring { box-shadow: 0 0 0 2px var(--panel), 0 0 0 4px color-mix(in srgb, var(--accent) 60%, transparent); }
/* Image avatars: the box keeps its size before the image arrives (no layout shift); the image fills the circle.
   Layered in the one grid cell (no positioning, so avatars never join the positioned stacking order of menus). */
.avatar__img {
  grid-area: 1 / 1;
  width: 100%; height: 100%;
  min-width: 0; min-height: 0;
  border-radius: inherit;
  object-fit: cover;
  -webkit-user-drag: none;
}
/* Default illustration: a soft wash of the user's hue shows through the artwork's transparent parts. */
.avatar--art {
  background:
    radial-gradient(circle at 50% 30%, hsl(var(--hue) 80% 86% / 0.9), transparent 70%),
    linear-gradient(160deg, hsl(var(--hue) 62% 78%), hsl(calc(var(--hue) + 35) 52% 60%));
}
/* Own photo: a quiet neutral placeholder while it loads, and a hairline so light photos keep their edge. */
.avatar--photo { background: var(--card-3); }
.avatar--photo::after {
  content: "";
  grid-area: 1 / 1;
  width: 100%; height: 100%;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text) 10%, transparent);
  pointer-events: none;
}
.avatar-group { display: inline-flex; align-items: center; }
.avatar-group > .avatar { box-shadow: 0 0 0 2px var(--card); }
.avatar-group > * + * { margin-inline-start: -10px; }
.avatar-group__more { --av: 30px; background: var(--card-3); color: var(--text-2); font-size: var(--fs-2xs); }

/* Gender choice (settings › profile, user admin): a segmented radio group with a tiny preview of each illustration. */
.gender-field { margin: 0; padding: 0; border: 0; min-width: 0; }
.gender-field > legend { padding: 0; margin-bottom: 6px; }
.gender-seg { display: flex; flex-wrap: wrap; gap: 2px; width: fit-content; max-width: 100%; overflow: visible; }
.gender-seg__item { position: relative; cursor: pointer; padding-inline: 6px var(--sp-4); }
.gender-seg__item:has(input:checked) { background: var(--card-3); color: var(--text); box-shadow: var(--glass-highlight); }
.gender-seg__item:has(input:focus-visible) { box-shadow: var(--focus-ring); }
.gender-seg__thumb { --av: 26px; }
.gender-seg__item:not(:has(input:checked)) .gender-seg__thumb { filter: saturate(0.6); opacity: 0.8; }
@media (max-width: 479px) {
  .gender-seg { width: 100%; border-radius: var(--r-lg); }
  .gender-seg__item { flex: 1 1 auto; justify-content: center; }
}

/* ---------- Tables (become card lists on mobile) ---------- */
.table-wrap { overflow-x: auto; margin-inline: calc(var(--sp-5) * -1); padding-inline: var(--sp-5); }
.table { font-size: var(--fs-md); }
.table th {
  height: 44px;
  padding-inline: var(--sp-3);
  text-align: start;
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: var(--text-3);
  white-space: nowrap;
  border-bottom: 1px solid var(--divider);
}
.table td { height: 64px; padding: var(--sp-2) var(--sp-3); border-bottom: 1px solid var(--divider); vertical-align: middle; }
.table tbody tr { transition: background var(--dur-1); }
.table tbody tr:hover { background: var(--row-hover); }
.table tbody tr:last-child td { border-bottom: 0; }
.table tr.is-production td:first-child { box-shadow: inset -3px 0 0 var(--tone-plum); }
.table__primary { font-weight: var(--fw-medium); color: var(--text); }
.table__secondary { font-size: var(--fs-xs); color: var(--text-3); }
.table__link { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; }
.table__link:hover .table__primary { color: var(--accent-text); }

@media (max-width: 767px) {
  .table--stack thead { display: none; }
  .table--stack, .table--stack tbody, .table--stack tr, .table--stack td { display: block; width: 100%; }
  .table--stack tr {
    margin-bottom: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--card-2);
  }
  .table--stack tr.is-production { border-color: color-mix(in srgb, var(--tone-plum) 35%, var(--border)); }
  .table--stack tr.is-production td:first-child { box-shadow: none; }
  .table--stack td { height: auto; padding: 6px 0; border: 0; display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); min-height: 44px; }
  .table--stack td[data-label]::before { content: attr(data-label); font-size: var(--fs-xs); color: var(--text-3); flex: none; }
  .table--stack td:first-child { border-bottom: 1px solid var(--divider); padding-bottom: var(--sp-3); margin-bottom: var(--sp-1); }
  .table--stack td:first-child::before { display: none; }
  .table-wrap { margin-inline: 0; padding-inline: 0; overflow: visible; }
}

/* Key/value metadata grid (detail pages) */
.meta-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr)); gap: var(--sp-2); }
.meta-item { display: flex; flex-direction: column; gap: 2px; padding: var(--sp-3) var(--sp-4); border-radius: var(--r-md); background: var(--card-2); border: 1px solid var(--border); min-width: 0; }
.meta-item__label { font-size: var(--fs-xs); color: var(--text-3); }
.meta-item__value { font-size: var(--fs-md); color: var(--text); font-weight: var(--fw-medium); min-width: 0; overflow-wrap: anywhere; }

/* ---------- Meter & progress ring ---------- */
.meter { --value: 0; --tone: var(--accent); height: 6px; border-radius: var(--r-full); background: var(--chip); overflow: hidden; }
.meter__bar { height: 100%; width: calc(var(--value) * 1%); border-radius: inherit; background: var(--tone); transform-origin: right; animation: iv-grow var(--dur-4) var(--ease-out) both; }
.meter--warn { --tone: var(--tone-amber); }
.meter--danger { --tone: var(--tone-red); }
@keyframes iv-grow { from { transform: scaleX(0); } }

.ring { --value: 0; --size: 52px; --stroke: 5; --tone: var(--accent); position: relative; width: var(--size); height: var(--size); flex: none; }
.ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.ring__track { fill: none; stroke: var(--chip); }
.ring__value { fill: none; stroke: var(--tone); stroke-linecap: round; stroke-dasharray: 100; stroke-dashoffset: calc(100 - var(--value)); transition: stroke-dashoffset var(--dur-4) var(--ease-out); filter: drop-shadow(0 0 4px color-mix(in srgb, var(--tone) 50%, transparent)); }
.ring__label { position: absolute; inset: 0; display: grid; place-items: center; font-size: var(--fs-2xs); font-weight: var(--fw-semibold); color: var(--text); }

/* Hatched surface (Monef chart fills / tracks) */
.hatch { background-image: repeating-linear-gradient(-45deg, var(--hatch) 0 1.5px, transparent 1.5px 7px); }

/* ---------- Dropdown ---------- */
.dropdown { position: relative; display: inline-flex; }
.dropdown__menu {
  position: absolute;
  top: calc(100% + 8px);
  inset-inline-end: 0;
  z-index: var(--z-dropdown);
  min-width: 220px;
  padding: 6px;
  border-radius: var(--r-lg);
  background: var(--popover-bg);
  -webkit-backdrop-filter: var(--popover-backdrop);
  backdrop-filter: var(--popover-backdrop);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-pop);
  transform-origin: top left;
}
/* A block hosting an open menu rises above the blocks after it (cards, page heads and their siblings may be
   stacking contexts: hover lifts, spotlight isolation), so the menu is never painted underneath them. */
:is(.card, .page-head, .page-head__actions):has([aria-expanded="true"]) { position: relative; z-index: 5; } /* < sticky topbar */
/* Inside the topbar (itself a backdrop-filter, i.e. a backdrop root) the glass menu could only blur the topbar,
   so the page below showed through it sharp: menus there are solid. */
.topbar .dropdown__menu { background: var(--dropdown-bg); }
.dropdown__menu--start { inset-inline-end: auto; inset-inline-start: 0; transform-origin: top right; }
.dropdown__menu--up { top: auto; bottom: calc(100% + 8px); transform-origin: bottom left; }
.dropdown__item {
  display: flex; align-items: center; gap: var(--sp-3);
  width: 100%;
  min-height: 42px;
  padding-inline: var(--sp-3);
  border-radius: var(--r-sm);
  color: var(--text-2);
  font-size: var(--fs-md);
  text-align: start;
  transition: background var(--dur-1), color var(--dur-1);
}
.dropdown__item:hover, .dropdown__item:focus-visible { background: var(--hover); color: var(--text); box-shadow: none; }
.dropdown__item.is-active { color: var(--text); }
.dropdown__item.is-active::after { content: ""; margin-inline-start: auto; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
.dropdown__item--danger { color: var(--tone-red-fg); }
.dropdown__label { padding: var(--sp-2) var(--sp-3) var(--sp-1); font-size: var(--fs-2xs); color: var(--text-3); }
.dropdown__sep { height: 1px; margin: 6px; background: var(--divider); }

/* Alpine transition helpers (x-transition:enter="t-pop-enter" ...) */
.t-pop-enter { transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out); }
.t-pop-from { opacity: 0; transform: translateY(-4px) scale(0.97); }
.t-pop-leave { transition: opacity var(--dur-1) ease-in, transform var(--dur-1) ease-in; }
.t-fade-enter { transition: opacity var(--dur-2); }
.t-fade-from { opacity: 0; }

/* ---------- Tooltip ----------
   <el data-tip="متن" [data-tip-pos="top|bottom|start|end"] [data-tip-align="start|end"]>
   static/js/tooltip.js shows every tip in ONE bubble (.tooltip) in the browser's top layer (popover="manual"),
   so no card, scroller, hero or stacking context can clip it or paint over it — it is above open dialogs and
   the sidebar too. It measures the trigger once per show, keeps the preferred side (logical: RTL start =
   right, end = left) or flips/shifts to stay 8px inside the viewport, then sets data-side (physical:
   top|bottom|left|right), --tip-ax/--tip-ay (where the arrow points, from the bubble's left/top edge) and the
   layer's transform. data-tip-align pins a top/bottom bubble to the trigger's start or end edge.
   Desktop hover and keyboard focus only, never touch; muted after a press or Escape (data-tip-off), while the
   trigger's menu is open (aria-expanded) and while it is loading (.is-loading). Colours: --tooltip-* tokens. */
.tooltip {
  /* The positioned layer; resets the UA popover box. */
  position: fixed;
  inset: 0 auto auto 0;
  z-index: 2147483647; /* only matters without the top layer (no Popover API) */
  width: max-content;
  max-width: min(260px, calc(100vw - 16px));
  height: auto;
  margin: 0;
  padding: 0;
  border: 0;
  overflow: visible;
  background: transparent;
  color: var(--tooltip-fg);
  pointer-events: none;
  transition-property: none; /* tooltip.js measures it at once (also under reduced motion's global 1ms transitions) */
}
.tooltip::backdrop { background: none; }
/* Triggers stay positioned so they paint (and take the hover) above a row's stretched-link overlay. */
[data-tip] { position: relative; }
.tooltip__body {
  --_tip-x: 0px; --_tip-y: 4px; /* entrance offset: the tip slides out from the trigger */
  position: relative;
  display: block;
  padding: 6px 11px 7px;
  border-radius: var(--r-xs);
  background: var(--tooltip-surface);
  box-shadow: 0 0 0 1px var(--tooltip-ring), var(--tooltip-shadow);
  font: var(--fw-medium) var(--fs-xs) / 1.6 var(--font-sans);
  letter-spacing: normal;
  text-align: center;
  text-transform: none;
  text-wrap: balance;
  white-space: normal;
  overflow-wrap: anywhere;
  transform-origin: var(--tip-ax, 50%) 100%; /* scales from where the arrow joins */
  animation: iv-tip var(--dur-2) var(--ease-out) both;
}
.tooltip__text { display: block; unicode-bidi: plaintext; }
/* Arrow: a border triangle over the bubble's edge (its base tucks 1px in, covering the ring where they meet). */
.tooltip__arrow { position: absolute; width: 0; height: 0; border: 6px solid transparent; }
.tooltip[data-side="top"] .tooltip__arrow {
  top: calc(100% - 1px); left: var(--tip-ax); translate: -50% 0;
  border-bottom-width: 0; border-top-color: var(--tooltip-surface);
}
.tooltip[data-side="bottom"] .tooltip__arrow {
  bottom: calc(100% - 1px); left: var(--tip-ax); translate: -50% 0;
  border-top-width: 0; border-bottom-color: var(--tooltip-surface);
}
.tooltip[data-side="left"] .tooltip__arrow {
  left: calc(100% - 1px); top: var(--tip-ay); translate: 0 -50%;
  border-right-width: 0; border-left-color: var(--tooltip-surface);
}
.tooltip[data-side="right"] .tooltip__arrow {
  right: calc(100% - 1px); top: var(--tip-ay); translate: 0 -50%;
  border-left-width: 0; border-right-color: var(--tooltip-surface);
}
.tooltip[data-side="bottom"] .tooltip__body { --_tip-y: -4px; transform-origin: var(--tip-ax, 50%) 0; }
.tooltip[data-side="left"] .tooltip__body { --_tip-x: 4px; --_tip-y: 0px; transform-origin: 100% var(--tip-ay, 50%); }
.tooltip[data-side="right"] .tooltip__body { --_tip-x: -4px; --_tip-y: 0px; transform-origin: 0 var(--tip-ay, 50%); }
/* Hand-off between neighbouring triggers: the next tip is just there. */
.tooltip[data-instant] .tooltip__body { animation: none; }
@media (prefers-reduced-motion: reduce) { .tooltip__body { animation: none; } }
@keyframes iv-tip { from { opacity: 0; transform: translate(var(--_tip-x), var(--_tip-y)) scale(0.94); } }

/* ---------- Breadcrumb ---------- */
.breadcrumb { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; font-size: var(--fs-sm); color: var(--text-3); margin-bottom: var(--sp-2); }
.breadcrumb a { color: var(--text-2); transition: color var(--dur-1); }
.breadcrumb a:hover { color: var(--text); }
.breadcrumb [aria-current="page"] { color: var(--text-2); }
.breadcrumb .icon { opacity: 0.6; }

/* ---------- Modal & drawer (native <dialog>) ---------- */
.modal {
  width: min(560px, calc(100vw - 24px));
  max-height: calc(100dvh - 48px);
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-xl);
  background: var(--card-2);
  color: var(--text);
  box-shadow: var(--shadow-pop);
  overflow: hidden;
  opacity: 0;
  transform: translateY(14px) scale(0.97);
  transition: opacity var(--dur-3) var(--ease-out), transform var(--dur-3) var(--ease-out), overlay var(--dur-3) allow-discrete, display var(--dur-3) allow-discrete;
}
.modal[open] { opacity: 1; transform: none; display: flex; flex-direction: column; }
@starting-style { .modal[open] { opacity: 0; transform: translateY(14px) scale(0.97); } }
.modal::backdrop { background: var(--overlay); backdrop-filter: blur(4px); opacity: 0; transition: opacity var(--dur-3), overlay var(--dur-3) allow-discrete, display var(--dur-3) allow-discrete; }
.modal[open]::backdrop { opacity: 1; }
@starting-style { .modal[open]::backdrop { opacity: 0; } }
.modal--sm { width: min(420px, calc(100vw - 24px)); }
.modal--lg { width: min(760px, calc(100vw - 24px)); }
.modal__head { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-5) var(--sp-5) var(--sp-4); }
.modal__title { font-size: var(--fs-lg); font-weight: var(--fw-semibold); }
.modal__desc { font-size: var(--fs-sm); color: var(--text-2); }
.modal__close { margin-inline-start: auto; }
.modal__body { padding: 0 var(--sp-5) var(--sp-5); overflow-y: auto; }
.modal__foot { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: var(--sp-2); padding: var(--sp-4) var(--sp-5); border-top: 1px solid var(--divider); background: color-mix(in srgb, var(--card) 50%, transparent); }

.drawer {
  margin: 0;
  margin-inline-end: 0;
  inset-inline-start: auto;
  inset-inline-end: 12px;
  inset-block: 12px;
  height: auto;
  max-height: none;
  width: min(460px, calc(100vw - 24px));
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-xl);
  background: var(--card-2);
  color: var(--text);
  box-shadow: var(--shadow-pop);
  transform: translateX(-110%);
  transition: transform var(--dur-3) var(--ease-out), overlay var(--dur-3) allow-discrete, display var(--dur-3) allow-discrete;
}
.drawer[open] { transform: none; display: flex; flex-direction: column; }
@starting-style { .drawer[open] { transform: translateX(-110%); } }
.drawer::backdrop { background: var(--overlay); backdrop-filter: blur(3px); opacity: 0; transition: opacity var(--dur-3), overlay var(--dur-3) allow-discrete, display var(--dur-3) allow-discrete; }
.drawer[open]::backdrop { opacity: 1; }
@starting-style { .drawer[open]::backdrop { opacity: 0; } }

/* A dialog the next page re-opens in place (form errors after a submit from the dialog, see app.js) does
   not replay its entrance. */
dialog.is-instant, dialog.is-instant::backdrop { transition: none !important; }

/* Below the desktop shell the document itself scrolls: lock it while a modal is open (the desktop shell
   already scrolls inside .main, which a modal's backdrop never chains to). */
@media (max-width: 1023px) {
  :root:has(dialog:modal) { overflow: hidden; }
}

@media (max-width: 767px) {
  /* Full width, resting just above the home indicator (viewport-fit=cover). */
  .modal {
    width: calc(100vw - 16px);
    max-height: calc(100dvh - 16px - env(safe-area-inset-top) - env(safe-area-inset-bottom));
    margin-bottom: calc(8px + env(safe-area-inset-bottom));
    border-radius: var(--r-xl);
  }
  .modal__foot .btn { flex: 1; }
}

/* ---------- Toasts ---------- */
.toasts {
  position: fixed;
  inset-inline-end: var(--sp-5);
  bottom: var(--sp-5);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column-reverse;
  gap: var(--sp-2);
  width: min(380px, calc(100vw - 24px));
  pointer-events: none;
}
.toast {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-lg);
  background: var(--dropdown-bg);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-pop);
  pointer-events: auto;
  overflow: hidden;
  position: relative;
}
.toast__body { flex: 1; min-width: 0; padding-top: 6px; }
.toast__title { font-size: var(--fs-md); font-weight: var(--fw-medium); line-height: var(--lh-snug); }
.toast__text { font-size: var(--fs-sm); color: var(--text-2); line-height: var(--lh-snug); margin-top: 2px; }
.toast__timer { position: absolute; inset-inline: 0; bottom: 0; height: 2px; background: currentColor; opacity: 0.35; transform-origin: right; animation: iv-timer linear forwards; }
@keyframes iv-timer { to { transform: scaleX(0); } }
.toast-enter { transition: opacity var(--dur-3) var(--ease-out), transform var(--dur-3) var(--ease-spring); }
.toast-from { opacity: 0; transform: translateY(16px) scale(0.96); }
.toast-leave { transition: opacity var(--dur-2), transform var(--dur-2); }
.toast-to { opacity: 0; transform: translateX(-24px); }
@media (max-width: 767px) {
  .toasts { inset-inline: 12px; width: auto; bottom: calc(92px + env(safe-area-inset-bottom)); }
}

/* ---------- Alerts ---------- */
.alert {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  border: 1px solid transparent;
  font-size: var(--fs-md);
  line-height: var(--lh-snug);
}
.alert .icon { margin-top: 2px; }
.alert__title { font-weight: var(--fw-semibold); }
.alert__text { color: inherit; opacity: 0.85; font-size: var(--fs-sm); }
.alert--info { background: var(--tone-indigo-bg); color: var(--tone-indigo-fg); border-color: color-mix(in srgb, var(--tone-indigo) 25%, transparent); }
.alert--success { background: var(--tone-green-bg); color: var(--tone-green-fg); border-color: color-mix(in srgb, var(--tone-green) 25%, transparent); }
.alert--warning { background: var(--tone-amber-bg); color: var(--tone-amber-fg); border-color: color-mix(in srgb, var(--tone-amber) 25%, transparent); }
.alert--danger { background: var(--tone-red-bg); color: var(--tone-red-fg); border-color: color-mix(in srgb, var(--tone-red) 25%, transparent); }
.alert--production { background: var(--tone-plum-bg); color: var(--tone-plum-fg); border-color: color-mix(in srgb, var(--tone-plum) 30%, transparent); }

/* ---------- Empty / error states ---------- */
.empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-2);
  padding: var(--sp-10) var(--sp-5);
  text-align: center;
}
.empty__art {
  position: relative;
  width: 96px; height: 96px;
  display: grid; place-items: center;
  margin-bottom: var(--sp-3);
  border-radius: 50%;
  color: var(--text-2);
  background: radial-gradient(circle, var(--card-3) 0 34%, transparent 35%), radial-gradient(circle, var(--chip) 0 52%, transparent 53%);
}
.empty__art::before, .empty__art::after { content: ""; position: absolute; inset: 0; border-radius: 50%; border: 1px dashed var(--border-strong); }
.empty__art::after { inset: -14px; border-style: solid; border-color: var(--divider); }
.empty--error .empty__art { color: var(--tone-red-fg); }
.empty__title { font-size: var(--fs-lg); font-weight: var(--fw-semibold); }
.empty__text { max-width: 360px; font-size: var(--fs-md); color: var(--text-2); line-height: var(--lh-snug); }
.empty__actions { margin-top: var(--sp-3); display: flex; gap: var(--sp-2); flex-wrap: wrap; justify-content: center; }

/* ---------- Skeleton ---------- */
.skeleton {
  display: block;
  border-radius: var(--r-xs);
  background: linear-gradient(90deg, var(--skeleton) 25%, var(--skeleton-shine) 37%, var(--skeleton) 63%) 0 0 / 400% 100%;
  animation: iv-shimmer 1.4s ease infinite;
}
.skeleton--text { height: 12px; }
.skeleton--title { height: 22px; width: 50%; }
.skeleton--circle { border-radius: 50%; }
.skeleton--card { height: 140px; border-radius: var(--r-xl); }

/* ---------- Pagination ---------- */
.pagination { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); flex-wrap: wrap; padding-top: var(--sp-4); font-size: var(--fs-sm); color: var(--text-3); }
.pagination__pages { display: flex; align-items: center; gap: 4px; }
.pagination__page { min-width: 36px; height: 36px; padding-inline: 8px; display: inline-grid; place-items: center; border-radius: var(--r-full); color: var(--text-2); transition: background var(--dur-1), color var(--dur-1); }
.pagination__page:hover { background: var(--hover); color: var(--text); }
.pagination__page.is-active { background: var(--chip-active); color: var(--chip-active-ink); font-weight: var(--fw-semibold); }
.pagination__page[aria-disabled="true"] { opacity: 0.35; pointer-events: none; }

/* ---------- Activity timeline ---------- */
.timeline { position: relative; display: flex; flex-direction: column; }
.timeline__item { position: relative; display: flex; gap: var(--sp-3); padding-bottom: var(--sp-4); min-width: 0; }
.timeline__item:not(:last-child)::before {
  content: "";
  position: absolute;
  inset-inline-start: 17px;
  top: 40px; bottom: 4px;
  border-inline-start: 1px dashed var(--border-strong);
}
.timeline__node { position: relative; z-index: 1; }
.timeline__body { flex: 1; min-width: 0; padding-top: 4px; line-height: var(--lh-snug); }
.timeline__text { font-size: var(--fs-md); color: var(--text-2); }
.timeline__text b, .timeline__text strong { color: var(--text); font-weight: var(--fw-medium); }
.timeline__meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px var(--sp-2); margin-top: 4px; font-size: var(--fs-xs); color: var(--text-3); }
.timeline__item.is-sensitive .timeline__node .chip-icon { box-shadow: 0 0 0 3px color-mix(in srgb, var(--tone-amber) 22%, transparent); }

/* ---------- Secret field ---------- */
.secret {
  display: flex; align-items: center; gap: var(--sp-2);
  min-height: 56px;
  padding: 6px 6px 6px var(--sp-4);
  padding-inline: var(--sp-4) 6px;
  border-radius: var(--r-lg);
  background: var(--sunken);
  border: 1px solid var(--border);
  transition: border-color var(--dur-2), background var(--dur-2);
}
.secret.is-revealed { border-color: color-mix(in srgb, var(--accent) 40%, transparent); background: color-mix(in srgb, var(--accent) 5%, var(--sunken)); }
.secret--production.is-revealed { border-color: color-mix(in srgb, var(--tone-plum) 50%, transparent); background: color-mix(in srgb, var(--tone-plum) 6%, var(--sunken)); }
.secret__label { flex: none; min-width: 92px; font-size: var(--fs-sm); color: var(--text-2); }
.secret__value {
  flex: 1;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-md);
  direction: ltr;
  text-align: left;
  color: var(--text);
  overflow-wrap: anywhere;
  white-space: pre-wrap;
  max-height: 180px;
  overflow-y: auto;
}
.secret__mask { letter-spacing: 0.2em; color: var(--text-3); user-select: none; }
.secret__actions { display: flex; align-items: center; gap: 4px; flex: none; }
.secret__timer { --value: 100; --size: 32px; --stroke: 3; }
.secret__value.is-entering { animation: iv-unblur var(--dur-4) var(--ease-out) both; }
@keyframes iv-unblur { from { filter: blur(6px); opacity: 0.2; letter-spacing: 0.25em; } to { filter: none; opacity: 1; } }
@media (max-width: 767px) {
  .secret { flex-wrap: wrap; padding: var(--sp-3); }
  .secret__label { min-width: 0; width: 100%; }
  .secret__actions .icon-btn { --ib: 44px; }
}

/* Copy button feedback */
.copy-btn .icon-check { display: none; }
.copy-btn.is-copied { color: var(--accent-text); background: var(--accent-soft); }
.copy-btn.is-copied .icon-copy { display: none; }
.copy-btn.is-copied .icon-check { display: block; animation: iv-pop var(--dur-3) var(--ease-spring); }

/* ---------- Status dot ---------- */
.status-dot { --tone: var(--tone-neutral); position: relative; width: 8px; height: 8px; flex: none; border-radius: 50%; background: var(--tone); }
.status-dot--green { --tone: var(--tone-green); box-shadow: 0 0 8px var(--tone-green); }
.status-dot--red { --tone: var(--tone-red); }
.status-dot--amber { --tone: var(--tone-amber); }
.status-dot--live::after { content: ""; position: absolute; inset: 0; border-radius: 50%; background: var(--tone); animation: iv-ping 2s var(--ease-out) infinite; }

/* ---------- Project / list cards shared bits ---------- */
.accent-swatch { --sw: var(--tone-neutral); width: 10px; height: 10px; border-radius: 3px; background: var(--sw); flex: none; }
.accent--green { --sw: var(--tone-green); --accent-bg: var(--tone-green-bg); --accent-fg: var(--tone-green-fg); }
.accent--indigo { --sw: var(--tone-indigo); --accent-bg: var(--tone-indigo-bg); --accent-fg: var(--tone-indigo-fg); }
.accent--plum { --sw: var(--tone-plum); --accent-bg: var(--tone-plum-bg); --accent-fg: var(--tone-plum-fg); }
.accent--amber { --sw: var(--tone-amber); --accent-bg: var(--tone-amber-bg); --accent-fg: var(--tone-amber-fg); }
.accent--sky { --sw: var(--tone-sky); --accent-bg: var(--tone-sky-bg); --accent-fg: var(--tone-sky-fg); }
.accent--slate { --sw: var(--tone-neutral); --accent-bg: var(--tone-neutral-bg); --accent-fg: var(--tone-neutral-fg); }

.code-chip {
  display: inline-flex; align-items: center; gap: 6px;
  max-width: 100%;
  height: 28px;
  padding-inline: 10px;
  border-radius: var(--r-xs);
  background: var(--chip);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  direction: ltr;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
button.code-chip { cursor: copy; transition: background var(--dur-1); }
button.code-chip:hover { background: var(--chip-hover); }

.timeline__link { color: inherit; transition: color var(--dur-1); }
.timeline__link:hover b { color: var(--accent-text); }
.timeline--compact .timeline__item { padding-bottom: var(--sp-3); }
.timeline--compact .timeline__text { font-size: var(--fs-sm); }
