/* ═══════════════════════════════════════════════════════════════════════
   RA-UI — shared UI library for all Life Logging web surfaces
   Layer 1: base tokens (theme-independent scale)
   Layer 2: theme-token DEFAULTS (dark values; the active themes/*.css
            file overrides these on :root)
   Layer 3: component tokens (derived from layer 2) + component classes
   Load order per page:
     <link href="/ui/ra-ui.css">
     <link id="ra-theme-css" href="/ui/themes/<active>.css">
     <script src="/ui/ra-ui.js" defer></script>
   User overrides are applied by ra-ui.js as inline custom properties on
   <html>, which beat any stylesheet value — no !important needed.
   ═══════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Layer 1 — base scale ── */
  --ra-density: 1;             /* user spacing multiplier (compact <1, comfy >1) */
  --ra-space-1: calc(2px * var(--ra-density, 1));
  --ra-space-2: calc(4px * var(--ra-density, 1));
  --ra-space-3: calc(8px * var(--ra-density, 1));
  --ra-space-4: calc(12px * var(--ra-density, 1));
  --ra-space-5: calc(16px * var(--ra-density, 1));
  --ra-space-6: calc(24px * var(--ra-density, 1));
  --ra-radius-base: 6px;       /* single knob; sm/md/lg derive (themes may still
                                  pin explicit values — retro 0, glass 8/12/18) */
  --ra-radius-sm: calc(var(--ra-radius-base) * .67);
  --ra-radius-md: var(--ra-radius-base);
  --ra-radius-lg: calc(var(--ra-radius-base) * 1.67);
  --ra-radius-pill: 999px;
  --ra-border-w: 1px;
  --ra-fs-xs: calc(9px * var(--fsc, 1) * var(--ra-fs-scale, 1));
  --ra-fs-sm: calc(10px * var(--fsc, 1) * var(--ra-fs-scale, 1));
  --ra-fs-md: calc(11px * var(--fsc, 1) * var(--ra-fs-scale, 1));
  --ra-fs-lg: calc(12px * var(--fsc, 1) * var(--ra-fs-scale, 1));
  --ra-fs-xl: calc(14px * var(--fsc, 1) * var(--ra-fs-scale, 1));
  --ra-font-body: 'Source Serif 4', Georgia, 'Iowan Old Style', 'Palatino Linotype', serif;   /* v184: default is a serif; themes and the fonts pack override */
  --ra-font-display: var(--ra-font-body);
  --ra-fs-scale: 1;            /* theme/user text-size multiplier, stacks with --fsc */
  --ra-hover-style: tint;      /* press | glow | shift | tint — how interactive elements react on hover
                                  (RAUI reads this and stamps body[data-ra-hover]) */
  --ra-motion: .15s;           /* duration base — themes set their motion character */
  --ra-motion-slow: calc(var(--ra-motion) * 2.5);
  --ra-ease: ease;             /* easing curve — e.g. steps(2) for retro, smooth bezier for glass */
  --ra-spring: linear(0, .5 10%, .8 20%, .95 32%, 1.04 45%, 1.07 56%, 1.03 68%, 1.005 80%, 1);
                                /* native CSS spring — overshoot capped ~7%, UI-scale not game-scale */
  --ra-z-fab: 9998;
  --ra-z-overlay: 9999;
  --ra-z-max: 99999;
  --ra-shadow-pressed: inset 2px 2px 5px rgba(0, 0, 0, .25);
  --ra-shadow-pressed-deep: var(--ra-shadow-pressed);
  --ra-shadow-1: 0 2px 8px rgba(0, 0, 0, .35);
  --ra-shadow-2: 0 6px 20px rgba(0, 0, 0, .5);

  /* ── Layer 2 — theme tokens (dark defaults; themes/*.css overrides) ── */
  --ra-bg: #080d18;
  --ra-surface-1: #0d1626;       /* topbar, panels, cards */
  --ra-surface-2: #1a2030;       /* buttons, chips, inputs */
  --ra-surface-3: #0f2744;       /* accent-tinted surface */
  --ra-border: #1e2a3a;
  --ra-border-strong: #2d3a4a;
  --ra-divider: #0f1626;       /* subtle row/list separators, fainter than border */
  --ra-text: #c9d1d9;
  --ra-text-bright: #e2e8f0;   /* titles, emphasized values */
  --ra-text-mid: #9ca3af;      /* secondary body text */
  --ra-text-dim: #6b7280;
  --ra-text-faint: #4b5563;    /* metadata, timestamps */
  --ra-text-muted: #374151;    /* labels, least prominent */
  --ra-accent: #60a5fa;
  --ra-accent-strong: #3b82f6;
  --ra-accent-bg: #0f2040;
  --ra-accent-border: #1e3a5f;
  --ra-ok: #34d399;      --ra-ok-strong: #10b981;     --ra-ok-bg: #052e16;     --ra-ok-border: #064e3b;
  --ra-warn: #fbbf24;    --ra-warn-strong: #f59e0b;   --ra-warn-bg: #2d1b06;   --ra-warn-border: #78350f;
  --ra-danger: #f87171;  --ra-danger-strong: #ef4444; --ra-danger-bg: #2d0a0a; --ra-danger-border: #7f1d1d;
  --ra-info: #60a5fa;    --ra-info-bg: #0f2040;   --ra-info-border: #1e3a5f;
  --ra-purple: #a78bfa;  --ra-purple-bg: #1e1040; --ra-purple-border: #4c1d95;
  --ra-mode: dark;       /* dark | light — informational */
  --ra-backdrop: var(--ra-bg);  /* body background treatment — themes may layer
                                   gradients/patterns (glass gradient, terminal
                                   scanlines, paper dot-grid) over the base bg */

  /* ── Layer 3 — component tokens (derive from layer 2) ── */
  --ra-btn-bg: var(--ra-surface-2);
  --ra-btn-border: var(--ra-border-strong);
  --ra-btn-text: var(--ra-text-dim);
  --ra-btn-radius: var(--ra-radius-md);
  --ra-control-shadow: var(--ra-shadow-1);
  --ra-control-shadow-active: var(--ra-shadow-pressed-deep);
  --ra-control-min-h: 36px;
  --ra-card-bg: var(--ra-surface-1);
  --ra-card-border: var(--ra-border);
  --ra-card-radius: var(--ra-radius-md);
  --ra-badge-radius: var(--ra-radius-sm);
  --ra-input-bg: var(--ra-surface-1);
  --ra-input-border: var(--ra-border);
  --ra-input-text: var(--ra-text);
  --ra-tab-text: var(--ra-text-muted);
  --ra-tab-active: var(--ra-accent);
  --ra-progress-track: var(--ra-surface-2);
  --ra-progress-fill: var(--ra-accent-strong);
  --ra-table-stripe: rgba(255, 255, 255, .02);
}

/* Host adoption layer. Raw native controls are normalized without replacing
   semantic classes or the active theme's distinctive material treatment. */
body, button, input, select, textarea, option {
  color: var(--ra-text);
  font-family: var(--ra-font-body);
}
body, select { color-scheme: var(--ra-mode, dark); }
option { background: var(--ra-input-bg); color: var(--ra-input-text); }
.ra-dashboard-input,
.ra-dashboard-control {
  min-height: var(--ra-control-min-h);
  box-sizing: border-box;
}
.ra-dashboard-input {
  background: var(--ra-input-bg) !important;
  border: var(--ra-border-w) solid var(--ra-input-border) !important;
  color: var(--ra-input-text) !important;
  border-radius: var(--ra-btn-radius);
  padding: var(--ra-space-2) var(--ra-space-3);
  box-shadow: var(--ra-control-shadow);
}
.ra-dashboard-input:focus {
  outline: 2px solid var(--ra-accent-strong);
  outline-offset: 1px;
}
button.ra-dashboard-control {
  background: var(--ra-btn-bg);
  border: var(--ra-border-w) solid var(--ra-btn-border);
  color: var(--ra-btn-text);
  border-radius: var(--ra-btn-radius);
  padding: var(--ra-space-2) var(--ra-space-3);
  box-shadow: var(--ra-control-shadow);
  cursor: pointer;
}
button.ra-dashboard-control:hover { border-color: var(--ra-accent-strong); }
button.ra-dashboard-control:active { box-shadow: var(--ra-control-shadow-active); }

/* Raw checkbox/radio adoption — a compact box matching the theme instead of
   the browser's bare native control. Kept simple (no appearance:none, which
   would drop native check/radio rendering on hosts without JS to draw the
   mark) — this just gives the native control theme-matched sizing, a
   pointer cursor, and a visible focus ring, and relies on accent-color
   (:root rule below) for the checked-state fill browsers already support. */
.ra-dashboard-check {
  width: 16px;
  height: 16px;
  min-height: 16px;
  flex: none;
  margin: 0;
  cursor: pointer;
  vertical-align: middle;
}
.ra-dashboard-check:focus-visible {
  outline: 2px solid var(--ra-accent-strong);
  outline-offset: 1px;
}
/* .ra-toggle already hides its own <input> (display:none) — same specificity
   as .ra-dashboard-check, but that rule is declared later in this file, so
   it wins the tie and a toggle's underlying checkbox stays hidden. */

/* ═══ Global element theming (all themes) ═══ */
:root { accent-color: var(--ra-accent-strong); }   /* checkboxes, radios, range */

/* keyboard navigation is visible in every theme */
button:focus-visible, a:focus-visible,
.ra-btn:focus-visible, .ra-tab:focus-visible,
.ra-input:focus-visible, .ra-select:focus-visible, .ra-textarea:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--ra-accent);
  outline-offset: 1px;
}

/* theme swatch dots (picker buttons) */
.ra-sw {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-inline-end: 3px;
  border: 1px solid rgba(128, 128, 128, .4);
  vertical-align: middle;
}

/* scrollbars follow the theme */
* { scrollbar-color: var(--ra-border-strong) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--ra-border-strong);
  border-radius: var(--ra-radius-pill);
  border: 2px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--ra-text-dim); border: 2px solid transparent; background-clip: content-box; }

/* ═══ Component classes (adopt incrementally — Phase 3+) ═══ */

.ra-btn {
  background: var(--ra-btn-bg);
  border: var(--ra-border-w) solid var(--ra-btn-border);
  color: var(--ra-btn-text);
  font-family: var(--ra-font-body);
  font-size: var(--ra-fs-md);
  padding: var(--ra-space-3) var(--ra-space-5);
  border-radius: var(--ra-btn-radius);
  cursor: pointer;
  transition: background-color var(--ra-motion) var(--ra-ease), border-color var(--ra-motion) var(--ra-ease), color var(--ra-motion) var(--ra-ease), box-shadow var(--ra-motion) var(--ra-ease), transform var(--ra-motion) var(--ra-ease);
  min-height: 38px;
}
.ra-btn:hover { border-color: var(--ra-text-dim); color: var(--ra-text); }
.ra-btn.active, .ra-btn-primary {
  background: var(--ra-accent-bg);
  border-color: var(--ra-accent-strong);
  color: var(--ra-accent);
}
.ra-btn-ghost { background: none; border-color: transparent; }
.ra-btn-danger {
  background: var(--ra-danger-bg);
  border-color: var(--ra-danger-border);
  color: var(--ra-danger);
}

.ra-badge {
  display: inline-block;
  padding: var(--ra-space-1) var(--ra-space-3);
  border-radius: var(--ra-badge-radius);
  font-size: var(--ra-fs-sm);
  font-weight: 600;
  letter-spacing: .04em;
  white-space: nowrap;
  background: var(--ra-surface-2);
  color: var(--ra-text-dim);
  border: var(--ra-border-w) solid var(--ra-border-strong);
}
.ra-badge-ok     { background: var(--ra-ok-bg);     color: var(--ra-ok);     border-color: var(--ra-ok-border); }
.ra-badge-warn   { background: var(--ra-warn-bg);   color: var(--ra-warn);   border-color: var(--ra-warn-border); }
.ra-badge-danger { background: var(--ra-danger-bg); color: var(--ra-danger); border-color: var(--ra-danger-border); }
.ra-badge-info   { background: var(--ra-info-bg);   color: var(--ra-info);   border-color: var(--ra-info-border); }
.ra-badge-purple { background: var(--ra-purple-bg); color: var(--ra-purple); border-color: var(--ra-purple-border); }

.ra-card {
  background: var(--ra-card-bg);
  border: var(--ra-border-w) solid var(--ra-card-border);
  border-radius: var(--ra-card-radius);
  padding: var(--ra-space-4);
}

.ra-input, .ra-select, .ra-textarea {
  background: var(--ra-input-bg);
  border: var(--ra-border-w) solid var(--ra-input-border);
  color: var(--ra-input-text);
  font-family: var(--ra-font-body);
  font-size: var(--ra-fs-sm);
  padding: var(--ra-space-2) var(--ra-space-3);
  border-radius: var(--ra-radius-sm);
}
.ra-input:focus, .ra-select:focus, .ra-textarea:focus {
  outline: none;
  border-color: var(--ra-accent-strong);
}

.ra-tabs { display: flex; gap: var(--ra-space-2); overflow-x: auto; }
.ra-tab {
  background: none;
  border: none;
  color: var(--ra-tab-text);
  font-family: var(--ra-font-body);
  font-size: var(--ra-fs-md);
  padding: var(--ra-space-3) var(--ra-space-4);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}
.ra-tab:hover { color: var(--ra-text-dim); }
.ra-tab.active { color: var(--ra-tab-active); border-bottom-color: var(--ra-accent-strong); }

.ra-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--ra-space-2);
  background: var(--ra-surface-2);
  border: var(--ra-border-w) solid var(--ra-border);
  border-radius: var(--ra-radius-pill);
  padding: var(--ra-space-1) var(--ra-space-3);
  font-size: var(--ra-fs-sm);
  color: var(--ra-text-dim);
  white-space: nowrap;
}

.ra-progress {
  height: 5px;
  background: var(--ra-progress-track);
  border-radius: 3px;
  overflow: hidden;
}
.ra-progress > .ra-progress-fill {
  height: 100%;
  background: var(--ra-progress-fill);
  border-radius: 3px;
  transition: width var(--ra-motion-slow) var(--ra-ease);
}

.ra-table { width: 100%; border-collapse: collapse; font-size: inherit; }
.ra-table th {
  text-align: start;
  /* v143: was --ra-text-muted (the dimmest tier, 1.2-3:1 on most themes). Header labels are real content: use the
     secondary text tier; a theme can still set --ra-th-text. scripts/qa-matrix.mjs guards the ratio. */
  color: var(--ra-th-text, var(--ra-text-mid));
  text-transform: uppercase;
  letter-spacing: .08em;
  font-size: inherit;
  padding: var(--ra-space-2) var(--ra-space-3);
  border-bottom: var(--ra-border-w) solid var(--ra-border);
}
.ra-table td {
  padding: var(--ra-space-2) var(--ra-space-3);
  border-bottom: var(--ra-border-w) solid var(--ra-border);
  color: var(--ra-text);
}
.ra-table tr:nth-child(even) td { background: var(--ra-table-stripe); }

.ra-h {
  font-size: var(--ra-fs-sm);
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--ra-text-muted);
  margin-bottom: var(--ra-space-3);
}

/* ═══ Interaction style (driven by --ra-hover-style via body[data-ra-hover]) ═══
   Opt any element out of the generic feedback rules with data-ra-nofx
   (generic marker — no page-specific selectors in the kit). */
body[data-ra-hover="press"] button:not([data-ra-nofx]):hover,
body[data-ra-hover="press"] .tab:hover {
  box-shadow: var(--ra-shadow-pressed) !important;
}
body[data-ra-hover="press"] button:not([data-ra-nofx]):active {
  box-shadow: var(--ra-shadow-pressed-deep) !important;
}
body[data-ra-hover="glow"] button:not([data-ra-nofx]):hover,
body[data-ra-hover="glow"] .tab:hover {
  box-shadow: 0 0 12px var(--ra-accent-border) !important;
  border-color: var(--ra-accent) !important;
}
body[data-ra-hover="shift"] button:not([data-ra-nofx]):hover {
  transform: translate(1px, 1px);
}
body[data-ra-hover="shift"] button:not([data-ra-nofx]):active {
  transform: translate(2px, 2px);
}
/* tint = default: theme/page hover rules apply unchanged */

/* universal press feedback — every theme, every button (shift has its own) */
body:not([data-ra-hover="shift"]) button:not([data-ra-nofx]):active:not(:disabled) {
  transform: scale(.97);
}
button { transition: transform var(--ra-motion) var(--ra-spring, var(--ra-ease)); }

/* ═══ Motion primitives (v13) — all durations ride --ra-motion ═══ */
@keyframes ra-fade-in  { from { opacity: 0 } to { opacity: 1 } }
@keyframes ra-slide-up { from { transform: translateY(24px); opacity: 0 } to { transform: none; opacity: 1 } }
@keyframes ra-rise     { from { transform: translateY(8px);  opacity: 0 } to { transform: none; opacity: 1 } }
@keyframes ra-pulse    { 0%, 100% { opacity: 1 } 50% { opacity: .45 } }
@keyframes ra-shimmer  { to { transform: translateX(100%) } }
@keyframes ra-indet    { from { margin-inline-start: -40% } to { margin-inline-start: 100% } }
@keyframes ra-spin     { to { transform: rotate(360deg) } }
@keyframes ra-flash-ok    { from { box-shadow: 0 0 0 0 var(--ra-ok) }     to { box-shadow: 0 0 0 9px transparent } }
@keyframes ra-flash-error { from { box-shadow: 0 0 0 0 var(--ra-danger) } to { box-shadow: 0 0 0 9px transparent } }

/* live badge — pulsing status dot */
.ra-badge-live {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.ra-badge-live::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  animation: ra-pulse 1.6s var(--ra-ease) infinite;
}

/* skeleton loading shimmer */
.ra-skeleton {
  position: relative;
  overflow: hidden;
  background: var(--ra-surface-2);
  border-radius: var(--ra-radius-sm);
  min-height: 12px;
  color: transparent;
}
.ra-skeleton::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .08), transparent);
  animation: ra-shimmer 1.4s infinite;
}

/* indeterminate progress — unknown duration work */
.ra-progress.indeterminate > .ra-progress-fill {
  width: 38%;
  animation: ra-indet 1.2s var(--ra-ease) infinite;
}

/* busy state — RAUI.busy(el, true) or class directly */
.ra-busy {
  pointer-events: none;
  opacity: .65;
}
.ra-busy::after {
  content: '';
  display: inline-block;
  width: .85em;
  height: .85em;
  margin-inline-start: 6px;
  vertical-align: -.12em;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: ra-spin .7s linear infinite;
}

/* result flash — RAUI.flash(el, 'ok'|'error') */
.ra-flash-ok    { animation: ra-flash-ok    .6s var(--ra-ease); }
.ra-flash-error { animation: ra-flash-error .6s var(--ra-ease); }

/* toasts — RAUI.toast(msg, kind) */
#ra-toasts {
  position: fixed;
  right: calc(16px + env(safe-area-inset-right, 0px));
  bottom: calc(72px + env(safe-area-inset-bottom, 0px));  /* clears the FAB */
  z-index: var(--ra-z-overlay);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  pointer-events: none;
}
.ra-toast {
  pointer-events: auto;
  max-width: min(340px, 86vw);
  background: var(--ra-surface-1);
  border: var(--ra-border-w) solid var(--ra-border-strong);
  border-inline-start: 3px solid var(--ra-accent);
  border-radius: var(--ra-radius-md);
  box-shadow: var(--ra-shadow-2);
  color: var(--ra-text);
  font-family: var(--ra-font-body);
  font-size: var(--ra-fs-md);
  padding: var(--ra-space-3) var(--ra-space-5);
  animation: ra-rise calc(var(--ra-motion) * 2) var(--ra-spring, var(--ra-ease));
  cursor: pointer;   /* click to dismiss */
}
.ra-toast-ok    { border-inline-start-color: var(--ra-ok); }
.ra-toast-warn  { border-inline-start-color: var(--ra-warn); }
.ra-toast-error { border-inline-start-color: var(--ra-danger); }
.ra-toast.out   { opacity: 0; transform: translateY(6px); transition: opacity calc(var(--ra-motion) * 2) var(--ra-ease), transform calc(var(--ra-motion) * 2) var(--ra-ease); }
.ra-toast-with-action { display: flex; align-items: center; justify-content: space-between; gap: var(--ra-space-4); }
.ra-toast-action {
  flex: none;
  background: none;
  border: none;
  color: var(--ra-accent);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  padding: 2px 4px;
}
.ra-toast-action:hover { text-decoration: underline; }

/* ═══ v17 primitives ═══ */

/* toggle switch — <label class="ra-toggle"><input type="checkbox"><i></i> Label</label> */
.ra-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--ra-space-3);
  cursor: pointer;
  font-family: var(--ra-font-body);
  font-size: var(--ra-fs-md);
  color: var(--ra-text);
}
.ra-toggle input { display: none; }
.ra-toggle i {
  width: 34px;
  height: 18px;
  flex: none;
  border-radius: var(--ra-radius-pill);
  background: var(--ra-surface-2);
  border: var(--ra-border-w) solid var(--ra-border-strong);
  position: relative;
  transition: background var(--ra-motion) var(--ra-ease), border-color var(--ra-motion) var(--ra-ease);
}
.ra-toggle i::after {
  content: '';
  position: absolute;
  top: 1px;
  left: 1px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--ra-text-dim);
  transition: transform var(--ra-motion) var(--ra-ease), background var(--ra-motion) var(--ra-ease);
}
.ra-toggle input:checked + i {
  background: var(--ra-accent-bg);
  border-color: var(--ra-accent-strong);
}
.ra-toggle input:checked + i::after {
  transform: translateX(16px);
  background: var(--ra-accent);
}

/* drag & drop feedback — consumers stamp these during their drag handlers */
.ra-dragging {
  opacity: .65;
  transform: rotate(1.5deg) scale(1.02);
  box-shadow: var(--ra-shadow-2);
  cursor: grabbing;
}
.ra-drop-target {
  outline: 2px dashed var(--ra-accent);
  outline-offset: -2px;
  background: var(--ra-accent-bg);
  animation: ra-pulse 1.2s var(--ra-ease) infinite;
}
.ra-drop-settle { animation: ra-rise calc(var(--ra-motion) * 2) var(--ra-ease); }

/* ═══ v15 primitives ═══ */

/* tooltip — <el data-ra-tip="text">, CSS-only */
[data-ra-tip] { position: relative; }
[data-ra-tip]:hover::after,
[data-ra-tip]:focus-visible::after {
  content: attr(data-ra-tip);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  background: var(--ra-surface-2);
  color: var(--ra-text);
  border: var(--ra-border-w) solid var(--ra-border-strong);
  border-radius: var(--ra-radius-sm);
  padding: 3px 8px;
  font-family: var(--ra-font-body);
  font-size: var(--ra-fs-sm);
  white-space: nowrap;
  box-shadow: var(--ra-shadow-1);
  z-index: var(--ra-z-max);
  pointer-events: none;
  animation: ra-fade-in var(--ra-motion) var(--ra-ease);
}

/* ═══ ra-info-btn — reusable ℹ️ info-tooltip control (v95) ═══
   A small round icon-only control that reveals a description on
   hover/focus, for "what is this section / how do I use it" text next to
   a card or section header. Built on [data-ra-tip] above, but as its own
   component rather than the bare kit-default tooltip because:
   1. ALWAYS a <span data-ra-tip="..."> — never a <button>. Any app that
      globally enhances every <button> with a click-ripple effect
      (overflow:hidden to contain the ripple circle) will silently clip
      this tooltip's ::after content to the button's own tiny box. A
      <span> (tabindex="0" for keyboard focus) sidesteps that entire bug
      class regardless of host app — confirmed the hard way in
      realtime-assistant (core-nav.js renderPinBar pin-bar badge, 2026-07-27;
      the Habits-tab info button, 2026-08-03).
   2. The bare kit tooltip is nowrap/single-line by design (good for short
      hints); this one wraps full sentences into a small stylized card —
      rounded, bordered, drop shadow, a caret pointing at the control — and
      resets font-weight/text-transform/letter-spacing, since ::after
      inherits computed style from its host and a bold/uppercase card
      header (a common place to put one of these) would otherwise bleed
      straight into the tooltip text.
   3. Anchor modifiers — plain .ra-info-btn centers under the control
      (fine when there's room on both sides). Add .ra-tip-start when the
      control sits near the LEFT of a wide row (a short label + control,
      e.g. a section divider) — anchors the tooltip's left edge to the
      control so it extends rightward instead of off the viewport's left
      edge. Add .ra-tip-end when the control sits at the RIGHT edge of a
      card/header (the common case, via margin-left:auto) — anchors the
      tooltip's right edge instead, extending leftward over the card.
      Centering alone overflows one side or the other once a control gets
      close to a viewport edge in either direction; this kit previously
      hard-coded position:fixed CSS Anchor Positioning for exactly this,
      but it computed a broken off-screen position in at least one host
      environment (top:1447px in a Cowork preview pane) — these two
      explicit modifiers are the deliberate, always-correct fallback.
   Usage: RAUI.infoBtn("description text", {anchor: 'end'}) in JS, or
   author the span directly: <span class="ra-info-btn ra-tip-end"
   tabindex="0" data-ra-tip="...">ℹ️</span> */
.ra-info-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 17px;
  height: 17px;
  border-radius: 999px;
  border: var(--ra-border-w) solid var(--ra-border);
  background: var(--ra-surface-1);
  color: var(--ra-text-dim);
  font-size: 9.5px;
  line-height: 1;
  cursor: help;
  transition: border-color var(--ra-motion) var(--ra-ease), color var(--ra-motion) var(--ra-ease), background var(--ra-motion) var(--ra-ease);
}
.ra-info-btn:hover, .ra-info-btn:focus-visible {
  border-color: var(--ra-accent);
  color: var(--ra-accent);
  background: var(--ra-accent-bg);
  outline: none;
}
.ra-info-btn[data-ra-tip]:hover::after,
.ra-info-btn[data-ra-tip]:focus-visible::after {
  white-space: normal;
  width: min(240px, 70vw);
  text-align: start;
  line-height: 1.5;
  font-size: var(--ra-fs-sm);
  font-weight: 400 !important;
  text-transform: none !important;
  letter-spacing: normal !important;
  padding: 9px 11px;
  border-radius: var(--ra-radius-md);
  background: var(--ra-surface-2);
  border-color: var(--ra-border-strong);
  box-shadow: var(--ra-shadow-2);
  position: absolute !important;
  top: auto !important;
  bottom: calc(100% + 9px) !important;
  opacity: 1 !important;
}
/* caret — small diamond, half-hidden behind the tooltip's own bottom edge
   so only its lower triangle shows, pointing down at the control */
.ra-info-btn[data-ra-tip]:hover::before,
.ra-info-btn[data-ra-tip]:focus-visible::before {
  content: '';
  position: absolute;
  bottom: calc(100% + 5px);
  left: 50%;
  transform: translateX(-50%) rotate(45deg);
  width: 8px;
  height: 8px;
  background: var(--ra-surface-2);
  border-inline-end: var(--ra-border-w) solid var(--ra-border-strong);
  border-bottom: var(--ra-border-w) solid var(--ra-border-strong);
  z-index: var(--ra-z-max);
  animation: ra-fade-in var(--ra-motion) var(--ra-ease);
}
.ra-info-btn.ra-tip-start[data-ra-tip]:hover::after,
.ra-info-btn.ra-tip-start[data-ra-tip]:focus-visible::after { left: 0 !important; right: auto !important; transform: none !important; }
.ra-info-btn.ra-tip-start[data-ra-tip]:hover::before,
.ra-info-btn.ra-tip-start[data-ra-tip]:focus-visible::before { left: 8px; transform: rotate(45deg); }
.ra-info-btn.ra-tip-end[data-ra-tip]:hover::after,
.ra-info-btn.ra-tip-end[data-ra-tip]:focus-visible::after { left: auto !important; right: 0 !important; transform: none !important; }
.ra-info-btn.ra-tip-end[data-ra-tip]:hover::before,
.ra-info-btn.ra-tip-end[data-ra-tip]:focus-visible::before { left: auto; right: 8px; transform: rotate(45deg); }

/* empty state */
.ra-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--ra-space-3);
  padding: var(--ra-space-6);
  color: var(--ra-text-dim);
  text-align: center;
  font-family: var(--ra-font-body);
  font-size: var(--ra-fs-md);
}
.ra-empty .ra-empty-icon { font-size: 28px; opacity: .5; }

/* form validation states */
@keyframes ra-shake { 0%, 100% { transform: none } 25% { transform: translateX(-4px) } 75% { transform: translateX(4px) } }
/* .ra-input-error/-ok always pair with .ra-input in markup — the compound
   selector matches :focus's specificity (0,2,0) and wins on source order,
   no !important needed to beat an active focus ring */
.ra-input.ra-input-error, .ra-input-error { border-color: var(--ra-danger); animation: ra-shake calc(var(--ra-motion) * 2) var(--ra-ease); }
.ra-input.ra-input-ok, .ra-input-ok       { border-color: var(--ra-ok); }

/* layout utilities — spacing stays on-token */
.ra-stack { display: flex; flex-direction: column; gap: var(--ra-space-4); }
.ra-row   { display: flex; align-items: center; gap: var(--ra-space-3); flex-wrap: wrap; }
.ra-grid  { display: grid; gap: var(--ra-space-4); grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }

/* confirm dialog — RAUI.confirm(msg) */
.ra-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--ra-z-overlay);
  background: rgba(0, 0, 0, .55);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: ra-fade-in calc(var(--ra-motion) * 1.5) var(--ra-ease);
}
.ra-modal {
  background: var(--ra-surface-1);
  border: var(--ra-border-w) solid var(--ra-border);
  border-radius: var(--ra-radius-lg);
  box-shadow: var(--ra-shadow-2);
  padding: 18px;
  width: min(360px, 90vw);
  font-family: var(--ra-font-body);
  color: var(--ra-text);
  animation: ra-rise calc(var(--ra-motion) * 2) var(--ra-spring, var(--ra-ease));
}
.ra-modal-msg  { font-size: var(--ra-fs-md); margin-bottom: 14px; }
.ra-modal-btns { display: flex; gap: 8px; justify-content: flex-end; }

/* command palette — Cmd/Ctrl+K, RAUI.openPalette() */
#ra-palette-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--ra-z-max);
  background: rgba(0, 0, 0, .45);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 12vh;
  animation: ra-fade-in var(--ra-motion) var(--ra-ease);
}
#ra-palette {
  width: min(520px, 92vw);
  background: var(--ra-surface-1);
  border: var(--ra-border-w) solid var(--ra-border-strong);
  border-radius: var(--ra-radius-lg);
  box-shadow: var(--ra-shadow-2);
  overflow: hidden;
  font-family: var(--ra-font-body);
  animation: ra-rise calc(var(--ra-motion) * 2) var(--ra-ease);
}
#ra-palette input {
  width: 100%;
  border: none;
  outline: none;
  background: var(--ra-surface-2);
  color: var(--ra-text);
  padding: 12px 14px;
  font-size: var(--ra-fs-lg);
  font-family: inherit;
}
#ra-palette .ra-pal-list { max-height: 40vh; overflow-y: auto; }
#ra-palette .ra-pal-item {
  padding: 9px 14px;
  font-size: var(--ra-fs-md);
  color: var(--ra-text-dim);
  cursor: pointer;
}
#ra-palette .ra-pal-item.sel { background: var(--ra-accent-bg); color: var(--ra-accent); }
/* #206: the field wrapper and the key hints are plain until a palette style (kit/features/palskin.json) shows them */
#ra-palette .ra-pal-field { display: block; }
#ra-palette .ra-pal-hints { display: none; }

/* seasonal accents + confetti */
body[data-ra-season="tet"] {
  --ra-accent: #f5c518;          /* gold */
  --ra-accent-strong: #e11d48;   /* red */
  --ra-accent-bg: #3a0d14;
  --ra-accent-border: #a3324b;
}
body[data-ra-season="newyear"] {
  --ra-accent: #ffd700;          /* gold sparkle */
  --ra-accent-strong: #7c3aed;   /* violet */
  --ra-accent-bg: #1a0f3a;
  --ra-accent-border: #6d28d9;
}
body[data-ra-season="christmas"] {
  --ra-accent: #e11d48;          /* red */
  --ra-accent-strong: #16a34a;   /* green */
  --ra-accent-bg: #0d2b16;
  --ra-accent-border: #166534;
}
#ra-confetti { position: fixed; inset: 0; pointer-events: none; z-index: var(--ra-z-max); overflow: hidden; }
#ra-confetti i {
  position: absolute;
  top: -14px;
  width: 8px;
  height: 14px;
  border-radius: 2px;
  animation: ra-confetti-fall 3.2s linear forwards;
}
@keyframes ra-confetti-fall { to { transform: translateY(105vh) rotate(720deg); opacity: .75; } }

/* ═══ v18 primitives — Signature Moments round 1 ═══ */

/* spotlight — cursor-tracked glow, JS writes --mx/--my (ra-ui.js initSignatureFx) */
.ra-spotlight { position: relative; overflow: hidden; }
.ra-spotlight::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(320px circle at var(--mx, 50%) var(--my, 50%), var(--ra-accent-border), transparent 70%);
  opacity: 0;
  transition: opacity var(--ra-motion) var(--ra-ease);
  pointer-events: none;
}
.ra-spotlight:hover::before, .ra-spotlight:focus-within::before { opacity: .55; }

/* animated checkmark draw-in — RAUI.checkmark(el) injects this SVG */
.ra-check-svg { width: 1.6em; height: 1.6em; vertical-align: -.3em; overflow: visible; }
.ra-check-svg circle, .ra-check-svg path {
  fill: none;
  stroke: var(--ra-ok);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ra-check-svg circle { stroke-dasharray: 80; stroke-dashoffset: 80; animation: ra-check-circle var(--ra-motion-slow) var(--ra-ease) forwards; }
.ra-check-svg path   { stroke-dasharray: 24; stroke-dashoffset: 24; animation: ra-check-mark var(--ra-motion-slow) var(--ra-ease) .12s forwards; }
@keyframes ra-check-circle { to { stroke-dashoffset: 0; } }
@keyframes ra-check-mark   { to { stroke-dashoffset: 0; } }

/* nudge — single-shot attention wiggle for new/unread badges (RAUI.nudge(el) to retrigger) */
@keyframes ra-nudge {
  0%, 100% { transform: none; }
  20% { transform: rotate(-8deg); }
  40% { transform: rotate(7deg); }
  60% { transform: rotate(-5deg); }
  80% { transform: rotate(3deg); }
}
.ra-nudge { animation: ra-nudge var(--ra-motion-slow) var(--ra-ease) 1; transform-origin: 50% 100%; }

/* magnetic — button pulls toward cursor on hover (JS writes translate via ra-ui.js) */
.ra-magnetic { transition: transform var(--ra-motion) var(--ra-spring, var(--ra-ease)); will-change: transform; }

/* ambient backdrop drift — themes opt in per body.t-<id> rule (Glass/Arcade/Cyber);
   duration derives from --ra-motion so it goes instant under 0-motion themes/prefs
   without any extra selector (20-40s at default .15s-.3s motion bases). */
@keyframes ra-drift {
  0%   { background-position: 0% 50%; }
  50%  { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

/* ═══ v19 primitives — Signature Moments round 2 ═══ */

/* aurora/mesh backdrop — opt-in body/container class, theme-aware via color-mix,
   distinct from Glass's fixed diagonal / Terminal's scanlines (blended organic blobs) */
.ra-aurora-bg {
  background-image:
    radial-gradient(38% 42% at 15% 20%, color-mix(in srgb, var(--ra-accent) 38%, transparent), transparent 70%),
    radial-gradient(34% 38% at 82% 15%, color-mix(in srgb, var(--ra-ok) 30%, transparent), transparent 70%),
    radial-gradient(40% 45% at 70% 82%, color-mix(in srgb, var(--ra-purple) 30%, transparent), transparent 70%),
    radial-gradient(30% 34% at 18% 85%, color-mix(in srgb, var(--ra-accent-strong) 28%, transparent), transparent 70%),
    var(--ra-bg);
  background-size: 180% 180%, 160% 160%, 190% 190%, 150% 150%, 100% 100%;
  background-repeat: no-repeat;
  animation: ra-aurora var(--ra-aurora-dur, calc(var(--ra-motion, .15s) * 160)) ease-in-out infinite alternate;
}
@keyframes ra-aurora {
  0%   { background-position: 0% 0%, 100% 0%, 100% 100%, 0% 100%, 0 0; }
  100% { background-position: 12% 8%, 88% 10%, 86% 90%, 10% 92%, 0 0; }
}
body.ra-fx-aurora-off .ra-aurora-bg { background-image: none !important; animation: none !important; background-color: var(--ra-bg); }

/* ── RAUI.makeResizer — draggable divider between two flex panes ──
   A thin flex-shrink:0 bar dropped between two panels in a row layout;
   the hit area is widened past its visible width via ::after so a 4px
   line is still easy to grab. Double-click resets to the CSS default. */
.ra-resize-handle {
  width: 5px;
  flex-shrink: 0;
  cursor: col-resize;
  position: relative;
  background: transparent;
  transition: background var(--ra-motion, .15s);
}
.ra-resize-handle::after {
  content: '';
  position: absolute;
  top: 0; bottom: 0;
  left: -4px; right: -4px;
}
.ra-resize-handle:hover,
body.ra-resizing .ra-resize-handle { background: var(--ra-accent-border, var(--ra-accent)); }
body.ra-resizing { cursor: col-resize !important; user-select: none; }
body.ra-resizing * { user-select: none !important; }

/* grain/noise overlay — SVG feTurbulence, low opacity so smooth gradients stop
   reading as sterile/AI-generated. Host element needs position:relative (set here). */
.ra-grain { position: relative; }
.ra-grain::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: var(--ra-grain-opacity, .05);
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* animated gradient text — moving gradient clipped to text (hero numbers/headings) */
.ra-gradient-text {
  background: linear-gradient(90deg, var(--ra-accent), var(--ra-purple), var(--ra-accent-strong), var(--ra-accent));
  background-size: 300% auto;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: ra-gradient-shift calc(var(--ra-motion, .15s) * 80) linear infinite;
}
@keyframes ra-gradient-shift { to { background-position: 300% center; } }
body.ra-fx-gradient-text-off .ra-gradient-text {
  animation: none !important;
  background: none !important;
  -webkit-background-clip: initial !important;
  background-clip: initial !important;
  -webkit-text-fill-color: initial !important;
  color: var(--ra-text) !important;
}

/* ripple-on-click — expanding circle from the click point (--rx/--ry via ra-ui.js) */
.ra-ripple { position: relative; overflow: hidden; }
.ra-ripple::after {
  content: '';
  position: absolute;
  left: var(--rx, 50%);
  top: var(--ry, 50%);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--ra-accent-border), transparent 70%);
  transform: translate(-50%, -50%) scale(0);
  opacity: 0;
  pointer-events: none;
}
.ra-ripple.ra-rippling::after {
  animation: ra-ripple-fx var(--ra-motion-slow) var(--ra-ease);
}
@keyframes ra-ripple-fx {
  0%   { transform: translate(-50%, -50%) scale(0);  opacity: .6; }
  100% { transform: translate(-50%, -50%) scale(18); opacity: 0; }
}

/* idle-icon breathing — one consistent "alive" language (extends ra-badge-live's pulse) */
@keyframes ra-breathe {
  0%, 100% { opacity: .55; transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.06); }
}
.ra-breathe, .ra-empty .ra-empty-icon { animation: ra-breathe 2.4s var(--ra-ease) infinite; }

/* ═══ v20 — Achievement / milestone unlock (RAUI.achievement) ═══ */
.ra-achievement-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--ra-z-max);
  background: rgba(0, 0, 0, .6);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  animation: ra-fade-in calc(var(--ra-motion) * 1.5) var(--ra-ease);
}
.ra-achievement {
  position: relative;
  overflow: hidden;
  background: var(--ra-surface-1);
  border: var(--ra-border-w) solid var(--ra-accent-border);
  border-radius: var(--ra-radius-lg);
  padding: 28px 40px;
  text-align: center;
  color: var(--ra-text);
  font-family: var(--ra-font-body);
  box-shadow: var(--ra-shadow-2);
  cursor: default;
  animation: ra-medal-pop var(--ra-motion-slow) var(--ra-spring, var(--ra-ease));
}
.ra-achievement-medal {
  font-size: 48px;
  display: block;
  margin-bottom: 8px;
  animation: ra-breathe 2.4s var(--ra-ease) infinite;
}
.ra-achievement-title { font-size: var(--ra-fs-lg); color: var(--ra-accent); font-weight: 700; letter-spacing: .04em; }
.ra-achievement-sub   { font-size: var(--ra-fs-sm); color: var(--ra-text-dim); margin-top: 4px; }
.ra-achievement::before {
  content: '';
  position: absolute;
  top: 0;
  left: -60%;
  width: 40%;
  height: 100%;
  background: linear-gradient(120deg, transparent, rgba(255, 255, 255, .35), transparent);
  transform: skewX(-20deg);
  animation: ra-shine-sweep calc(var(--ra-motion-slow) * 2) var(--ra-ease) .3s;
}
@keyframes ra-medal-pop { 0% { transform: scale(.4); opacity: 0; } 60% { transform: scale(1.06); opacity: 1; } 100% { transform: scale(1); } }
@keyframes ra-shine-sweep { to { left: 130%; } }

/* ═══ v21 — Bento grid utility + FLIP (structural, built last per todo.md) ═══ */

/* .ra-bento — CSS Grid bento layout; cells opt into span-2/span-row-2.
   .ra-bento-cell uses subgrid so a cell's own header/body/footer rows line
   up with the parent grid's row tracks even when the cell spans 2 rows. */
.ra-bento {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  grid-auto-rows: 110px;
  gap: var(--ra-space-4);
}
.ra-bento-span-2     { grid-column: span 2; }
.ra-bento-span-row-2 {
  grid-row: span 2;
  display: grid;
  grid-template-rows: subgrid;
}
@supports not (grid-template-rows: subgrid) {
  .ra-bento-span-row-2 { display: block; }   /* graceful degrade — Firefox <71 / old Safari */
}

/* RAUI.flip(fromEl, toEl) drives the transform inline — no dedicated class
   needed beyond marking the transitioning element so consumers can target it */
.ra-flip-active { will-change: transform, opacity; }

/* ═══ v22 primitives — Signature Moments round 3, part A/B (native CSS wins + surface fx) ═══ */

/* .ra-scroll-reveal — scroll-driven entrance (no JS/IntersectionObserver).
   Stable animation-timeline: view() in Chrome 130+/Safari 18+/Firefox 130+;
   falls back to a normal on-load rise for browsers without it. Chrome 145's
   declarative animation-trigger layers on top where supported (progressive
   enhancement — harmless no-op elsewhere). */
.ra-scroll-reveal {
  animation: ra-rise var(--ra-motion-slow) var(--ra-ease) both;
}
@supports (animation-timeline: view()) {
  .ra-scroll-reveal {
    animation: ra-rise linear both;
    animation-timeline: view();
    animation-range: entry 0% cover 30%;
  }
}
@supports (animation-trigger: --ra-trigger(view())) {
  .ra-scroll-reveal { animation-trigger: --ra-trigger(view()); }
}

/* .ra-discrete-enter — @starting-style + allow-discrete opt-in for elements
   that toggle via [hidden] or .ra-hidden instead of being created/destroyed
   (the kit's own modal/toast stay on the JS-driven keyframe approach —
   this is for consumer-owned show/hide elements that want the native path). */
.ra-discrete-enter {
  opacity: 1;
  transition: opacity var(--ra-motion-slow) var(--ra-ease), display var(--ra-motion-slow) allow-discrete, overlay var(--ra-motion-slow) allow-discrete;
}
.ra-discrete-enter[hidden], .ra-discrete-enter.ra-hidden { opacity: 0; display: none; }
@starting-style {
  .ra-discrete-enter:not([hidden]):not(.ra-hidden) { opacity: 0; }
}

/* CSS Anchor Positioning progressive enhancement for data-ra-tip — flips the
   tooltip to stay in-viewport near screen edges; the existing absolute
   ::after positioning (ra-ui.css layer 3) keeps working as the fallback. */
@supports (anchor-name: --ra-a) {
  [data-ra-tip] { anchor-name: --ra-tip-anchor; }
  [data-ra-tip]:hover::after, [data-ra-tip]:focus-visible::after {
    position: fixed;
    position-anchor: --ra-tip-anchor;
    position-area: top;
    position-try-fallbacks: flip-block;
    bottom: auto;
    left: auto;
    transform: none;
    margin-bottom: 6px;
  }
}

/* .ra-tilt — 3D perspective tilt-on-hover, cursor-follow depth (JS writes
   --tx/--ty rotation via ra-ui.js initSignatureFx, same delegated pointermove) */
.ra-tilt {
  transform: perspective(600px) rotateX(var(--ty, 0deg)) rotateY(var(--tx, 0deg));
  transition: transform var(--ra-motion) var(--ra-spring, var(--ra-ease));
  will-change: transform;
}

/* .ra-liquid-glass — refractive distortion via feDisplacementMap, layered
   over the existing backdrop-filter blur (2026's "liquid glass" evolution
   of glassmorphism). Best on Glass/Cyber/dark surfaces. */
.ra-liquid-glass {
  position: relative;
  backdrop-filter: blur(14px) saturate(1.3) url(#ra-liquid-glass-distort);
  -webkit-backdrop-filter: blur(14px) saturate(1.3);
}

/* .ra-border-glow — animated spectral gradient border sweep */
.ra-border-glow {
  position: relative;
  border: 1px solid transparent;
  background-clip: padding-box;
}
.ra-border-glow::before {
  content: '';
  position: absolute;
  inset: -1px;
  z-index: -1;
  border-radius: inherit;
  background: conic-gradient(from var(--ra-glow-angle, 0deg), var(--ra-accent), var(--ra-purple), var(--ra-ok), var(--ra-accent));
  animation: ra-border-glow-spin calc(var(--ra-motion, .15s) * 40) linear infinite;
}
@keyframes ra-border-glow-spin { to { --ra-glow-angle: 360deg; } }
@property --ra-glow-angle {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

/* ═══ v23 primitives — Signature Moments round 3, part C/D (typography + buttons/cursor) ═══ */

/* .ra-kinetic-text — weight/width shift on hover via a variable font axis;
   letter-spacing is the fallback for the kit's default non-variable mono font */
.ra-kinetic-text {
  transition: font-variation-settings var(--ra-motion) var(--ra-ease), letter-spacing var(--ra-motion) var(--ra-ease);
  font-variation-settings: 'wght' 400;
}
.ra-kinetic-text:hover { font-variation-settings: 'wght' 700; letter-spacing: .01em; }
@supports not (font-variation-settings: 'wght' 400) {
  .ra-kinetic-text:hover { letter-spacing: .05em; }
}

/* .ra-text-wipe — clip-path mask wipe reveal on load */
@keyframes ra-text-wipe { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
.ra-text-wipe { animation: ra-text-wipe var(--ra-motion-slow) var(--ra-ease) both; }

/* cursor-glow — page-level halo following the pointer, RAUI.enableCursorGlow() */
#ra-cursor-glow {
  position: fixed;
  top: 0;
  left: 0;
  width: 280px;
  height: 280px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--ra-accent-border), transparent 70%);
  transform: translate(-50%, -50%);
  pointer-events: none;
  z-index: var(--ra-z-max);
  opacity: 0;
  transition: opacity var(--ra-motion) var(--ra-ease);
  mix-blend-mode: screen;
}
body[data-ra-cursor-glow="1"] #ra-cursor-glow { opacity: .5; }

/* .ra-blob-btn — liquid/blob morph wobble on press */
@keyframes ra-blob {
  0%, 100% { border-radius: 42% 58% 60% 40% / 44% 40% 60% 56%; }
  50%      { border-radius: 58% 42% 40% 60% / 56% 60% 40% 44%; }
}
.ra-blob-btn:active { animation: ra-blob var(--ra-motion-slow) var(--ra-ease); }

/* .ra-border-spin — thin conic ring, hover-only (button variant of v22's
   always-on .ra-border-glow; reuses the same --ra-glow-angle/@property) */
.ra-border-spin { position: relative; }
.ra-border-spin::after {
  content: '';
  position: absolute;
  inset: -2px;
  z-index: -1;
  border-radius: inherit;
  background: conic-gradient(from var(--ra-glow-angle, 0deg), var(--ra-accent), transparent 30%, transparent 70%, var(--ra-accent));
  opacity: 0;
  transition: opacity var(--ra-motion) var(--ra-ease);
  animation: ra-border-glow-spin calc(var(--ra-motion, .15s) * 40) linear infinite;
}
.ra-border-spin:hover::after { opacity: 1; }

/* icon morph — hamburger <-> X, sun <-> moon (pure CSS, no icon asset needed) */
.ra-icon-burger { position: relative; width: 20px; height: 16px; display: inline-block; }
.ra-icon-burger span, .ra-icon-burger::before, .ra-icon-burger::after {
  content: '';
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  background: currentColor;
  border-radius: 2px;
  transition: transform var(--ra-motion) var(--ra-ease), opacity var(--ra-motion) var(--ra-ease), top var(--ra-motion) var(--ra-ease);
}
.ra-icon-burger::before { top: 0; }
.ra-icon-burger span { top: 7px; }
.ra-icon-burger::after { top: 14px; }
.ra-icon-burger.open::before { top: 7px; transform: rotate(45deg); }
.ra-icon-burger.open span { opacity: 0; }
.ra-icon-burger.open::after { top: 7px; transform: rotate(-45deg); }

.ra-icon-sunmoon {
  position: relative;
  width: 18px;
  height: 18px;
  display: inline-block;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 3px transparent;
  transition: transform var(--ra-motion-slow) var(--ra-spring, var(--ra-ease)), box-shadow var(--ra-motion-slow) var(--ra-ease);
  transform: scale(1) rotate(0deg);
}
.ra-icon-sunmoon::before {
  content: '';
  position: absolute;
  inset: -5px;
  border-radius: inherit;
  box-shadow: 0 -9px 0 -8px currentColor, 0 9px 0 -8px currentColor, -9px 0 0 -8px currentColor, 9px 0 0 -8px currentColor,
              -6.3px -6.3px 0 -8px currentColor, 6.3px -6.3px 0 -8px currentColor, -6.3px 6.3px 0 -8px currentColor, 6.3px 6.3px 0 -8px currentColor;
  opacity: 1;
  transition: opacity var(--ra-motion) var(--ra-ease);
}
.ra-icon-sunmoon.dark { transform: scale(.85) rotate(-40deg); box-shadow: -6px -3px 0 3px var(--ra-bg); }
.ra-icon-sunmoon.dark::before { opacity: 0; }

/* ═══ v24 primitives — Signature Moments round 3, part E/F (loading/feedback + celebration/theme fx) ═══ */

/* .ra-typing — typing-indicator dots */
.ra-typing { display: inline-flex; gap: 4px; align-items: center; }
.ra-typing span { width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: .4; animation: ra-typing-bounce 1s var(--ra-ease) infinite; }
.ra-typing span:nth-child(2) { animation-delay: .15s; }
.ra-typing span:nth-child(3) { animation-delay: .3s; }
@keyframes ra-typing-bounce { 0%, 60%, 100% { transform: translateY(0); opacity: .4; } 30% { transform: translateY(-4px); opacity: 1; } }

/* .ra-ring — radial/circular progress ring, RAUI.ringSet(el, pct) drives --ra-ring-pct.
   @property makes the conic-gradient's percentage animatable via a plain transition. */
@property --ra-ring-pct { syntax: '<number>'; inherits: true; initial-value: 0; }
.ra-ring {
  --ra-ring-pct: 0;
  position: relative;
  display: inline-flex;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: conic-gradient(var(--ra-progress-fill) calc(var(--ra-ring-pct) * 1%), var(--ra-progress-track) 0);
  transition: --ra-ring-pct var(--ra-motion-slow) var(--ra-ease);
}
.ra-ring::before {
  content: '';
  position: absolute;
  inset: 15%;
  border-radius: 50%;
  background: var(--ra-card-bg);
}

/* toast stack — drag-to-dismiss physics wired in ra-ui.js RAUI.toast() */
.ra-toast { touch-action: pan-y; }

/* .ra-ring-bell — notification bell shake/ring, RAUI.ringBell(el) retriggers */
@keyframes ra-bell-ring {
  0%, 100% { transform: rotate(0); }
  15% { transform: rotate(18deg); }
  30% { transform: rotate(-14deg); }
  45% { transform: rotate(10deg); }
  60% { transform: rotate(-6deg); }
  75% { transform: rotate(3deg); }
}
.ra-ring-bell { display: inline-block; transform-origin: 50% 0; animation: ra-bell-ring var(--ra-motion-slow) var(--ra-ease) 1; }

/* .ra-glitch — Cyber-only RGB-split flicker on hover (no extra markup needed) */
@keyframes ra-glitch {
  0%, 100% { clip-path: inset(0 0 0 0); transform: translate(0, 0); }
  20% { clip-path: inset(10% 0 60% 0); transform: translate(-2px, 1px); }
  40% { clip-path: inset(60% 0 10% 0); transform: translate(2px, -1px); }
  60% { clip-path: inset(30% 0 40% 0); transform: translate(-1px, 2px); }
  80% { clip-path: inset(50% 0 20% 0); transform: translate(1px, -2px); }
}
body.t-cyber .ra-glitch:hover {
  animation: ra-glitch calc(var(--ra-motion, .15s) * 3) steps(2, jump-none) infinite;
  text-shadow: -2px 0 var(--ra-danger), 2px 0 var(--ra-info);
}

/* Terminal-only CRT power-on boot flicker — RAUI.crtBoot(), one-shot on load.
   Fixed duration by design (like the scramble effect): a boot moment, not a
   loop, so it plays despite Terminal's --ra-motion:0s (same exception the
   round-2 scramble effect already established). */
@keyframes ra-crt-boot {
  0% { opacity: 0; transform: scaleY(.02); filter: brightness(3); }
  6% { opacity: 1; transform: scaleY(1.02); }
  8% { transform: scaleY(.98); }
  10% { transform: scaleY(1); filter: brightness(1.4); }
  100% { filter: brightness(1); }
}
body.t-terminal.ra-crt-booting { animation: ra-crt-boot .5s steps(6, end); }

/* ═══ v25 primitives — Signature Moments round 3, part G (structural, last) ═══ */

/* .ra-flip-card — 3D front/back flip. Markup:
   <div class="ra-flip-card"><div class="ra-flip-card-inner">
     <div class="ra-flip-card-front ra-card">…</div>
     <div class="ra-flip-card-back ra-card">…</div>
   </div></div>  — toggle .flipped on the outer element */
.ra-flip-card { perspective: 1000px; }
.ra-flip-card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  transition: transform var(--ra-motion-slow) var(--ra-spring, var(--ra-ease));
  transform-style: preserve-3d;
}
.ra-flip-card.flipped .ra-flip-card-inner { transform: rotateY(180deg); }
.ra-flip-card-front, .ra-flip-card-back {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  border-radius: inherit;
}
.ra-flip-card-back { transform: rotateY(180deg); }

/* .ra-masonry — broken/asymmetric grid via CSS columns (broad support,
   no JS layout needed); pair with RAUI.stagger() on the children for a
   staggered entrance instead of popping in as one block */
.ra-masonry { columns: 3 220px; column-gap: var(--ra-space-4); }
.ra-masonry > * { break-inside: avoid; margin-bottom: var(--ra-space-4); }

/* ═══ v32 primitives — material textures + depth/lighting ═══ */

/* material textures — opt-in, layered as background-image so they compose
   with any existing surface color (never use the `background` shorthand here) */
.ra-tex-metal   { background-image: repeating-linear-gradient(100deg, rgba(255, 255, 255, .07) 0 2px, rgba(0, 0, 0, .05) 2px 4px); }
.ra-tex-circuit {
  background-image:
    linear-gradient(90deg, rgba(46, 214, 255, .1) 1px, transparent 1px),
    linear-gradient(0deg, rgba(46, 214, 255, .1) 1px, transparent 1px);
  background-size: 16px 16px;
}
.ra-tex-canvas {
  background-image:
    repeating-linear-gradient(45deg, rgba(0, 0, 0, .035) 0 2px, transparent 2px 4px),
    repeating-linear-gradient(-45deg, rgba(0, 0, 0, .035) 0 2px, transparent 2px 4px);
}
.ra-tex-marble {
  background-image:
    linear-gradient(120deg, transparent 40%, rgba(255, 255, 255, .16) 41%, transparent 43%),
    linear-gradient(200deg, transparent 60%, rgba(0, 0, 0, .08) 61%, transparent 64%),
    linear-gradient(35deg, transparent 75%, rgba(255, 255, 255, .1) 76%, transparent 78%);
}
.ra-tex-grunge, .ra-tex-paper { position: relative; }
.ra-tex-grunge::after, .ra-tex-paper::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
.ra-tex-grunge::after { opacity: .12; mix-blend-mode: multiply; }
.ra-tex-paper::after  { opacity: .06; mix-blend-mode: overlay; }

/* layered parallax tilt — .ra-tilt-deep pairs with the existing .ra-tilt
   pointermove (--tx/--ty); the pseudo-layer floats opposite the card for a
   fake-depth parallax instead of a single flat rotate */
.ra-tilt-deep { transform-style: preserve-3d; position: relative; }
.ra-tilt-deep::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  transform: translateZ(24px);
  background: radial-gradient(circle at var(--mx, 50%) var(--my, 50%), rgba(255, 255, 255, .1), transparent 60%);
}

/* 3D press — translateZ depth instead of flat scale */
.ra-press-3d { transform-style: preserve-3d; transition: transform var(--ra-motion) var(--ra-spring, var(--ra-ease)); }
.ra-press-3d:active { transform: translateZ(-6px) scale(.97); }

/* isometric utility — perspective(1000px) container + rotateX/rotateZ tile,
   the standard CSS-isometric-projection recipe */
.ra-isometric { perspective: 1000px; }
.ra-isometric-tile { transform: rotateX(60deg) rotateZ(45deg); transform-style: preserve-3d; }

/* inverted skeuomorphism — subtle inner-stroke edge-light, single directional
   light source (the 2026 successor to flat dual-shadow neumorphism) */
.ra-inset-glow { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .16), inset 0 -1px 0 rgba(0, 0, 0, .28); }

/* ambient occlusion contact shadow — reads as "resting on a surface"
   instead of a flat offset box-shadow */
.ra-float { position: relative; }
.ra-float::after {
  content: '';
  position: absolute;
  left: 10%;
  right: 10%;
  bottom: -8px;
  height: 10px;
  background: radial-gradient(ellipse at center, rgba(0, 0, 0, .28), transparent 70%);
  filter: blur(4px);
  z-index: -1;
}

/* chromatic/prism edge glint — thin rotating rainbow border, real-glass
   light-catching illusion (masked to a 1px ring so it never fills the card) */
@keyframes ra-prism-shift { to { filter: hue-rotate(360deg); } }
.ra-prism-edge { position: relative; }
.ra-prism-edge::before {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(120deg, #ff6b6b, #ffd93d, #6bffb8, #6bc4ff, #c46bff, #ff6b6b);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: .55;
  animation: ra-prism-shift calc(var(--ra-motion, .15s) * 60) linear infinite;
  pointer-events: none;
}

/* .ra-cast-shadow — participates in dynamic directional shadow-casting;
   JS (initDepthFx) sets --sx/--sy from cursor position each frame */
.ra-cast-shadow { box-shadow: var(--sx, 0px) var(--sy, 4px) 18px rgba(0, 0, 0, .35); transition: box-shadow var(--ra-motion) var(--ra-ease); }

/* ═══ v33 primitives — compositional 3D + gamification + theme tools ═══ */

/* .ra-deck — card-deck fan (toast/notification stacks, any card collection) */
.ra-deck { position: relative; }
.ra-deck > * { position: absolute; inset: 0; transform-origin: bottom center; transition: transform var(--ra-motion-slow) var(--ra-spring, var(--ra-ease)); }
.ra-deck > *:nth-child(1) { transform: rotate(-6deg) translateY(4px); z-index: 1; }
.ra-deck > *:nth-child(2) { transform: rotate(-2deg) translateY(2px); z-index: 2; }
.ra-deck > *:nth-child(3) { transform: rotate(2deg) translateY(2px); z-index: 3; }
.ra-deck > *:nth-child(4) { transform: rotate(6deg) translateY(4px); z-index: 4; }
.ra-deck > *:nth-child(n+5) { transform: rotate(8deg) translateY(6px); z-index: 5; }

/* .ra-page-turn — modal variant, opens like a book page on a hinge */
@keyframes ra-page-turn { from { transform: rotateY(-100deg); opacity: 0; } to { transform: rotateY(0); opacity: 1; } }
.ra-modal.ra-page-turn { transform-origin: left center; transform-style: preserve-3d; animation: ra-page-turn var(--ra-motion-slow) var(--ra-ease); }

/* .ra-diorama — recessed shadow-box frame, content pushed forward in Z */
.ra-diorama {
  position: relative;
  padding: 20px;
  background: var(--ra-surface-2);
  box-shadow: inset 0 0 24px rgba(0, 0, 0, .4), var(--ra-shadow-2);
  border-radius: var(--ra-radius-lg);
  perspective: 600px;
}
.ra-diorama > * { position: relative; transform: translateZ(20px); }

/* .ra-chrome-text — liquid-metal beveled specular text (Y2K "chrome" look) */
.ra-chrome-text {
  background: linear-gradient(180deg, #fff 0%, #b8b8b8 45%, #6b6b6b 50%, #fff 55%, #8a8a8a 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: 0 1px 0 rgba(255, 255, 255, .5);
  font-weight: 800;
}

/* .ra-cube-spin — 3D cube loader, alt to the flat ra-spin (kept animating
   under reduced-motion like the other spinners — conveys state, not decoration) */
.ra-cube-spin { width: 22px; height: 22px; position: relative; display: inline-block; transform-style: preserve-3d; animation: ra-cube-spin 1.3s linear infinite; }
.ra-cube-spin i { position: absolute; inset: 0; background: var(--ra-accent); opacity: .72; }
.ra-cube-spin i:nth-child(1) { transform: translateZ(11px); }
.ra-cube-spin i:nth-child(2) { transform: rotateY(90deg) translateZ(11px); }
.ra-cube-spin i:nth-child(3) { transform: rotateY(180deg) translateZ(11px); }
.ra-cube-spin i:nth-child(4) { transform: rotateY(-90deg) translateZ(11px); }
@keyframes ra-cube-spin { to { transform: rotateX(360deg) rotateY(360deg); } }

/* .ra-toggle-3d — deeper rocker-switch shadow variant of .ra-toggle */
.ra-toggle-3d i { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), inset 0 -2px 3px rgba(0, 0, 0, .3); }
.ra-toggle-3d i::after { box-shadow: 0 2px 3px rgba(0, 0, 0, .4), inset 0 1px 0 rgba(255, 255, 255, .5); }

/* achievement rarity tiers (v33) — layered onto the existing .ra-achievement */
.ra-achievement.tier-bronze { border-color: #cd7f32; }
.ra-achievement.tier-silver { border-color: #c0c0c0; }
.ra-achievement.tier-gold   { border-color: #ffd700; box-shadow: 0 0 30px rgba(255, 215, 0, .4), var(--ra-shadow-2); }

/* .ra-xp-bar — continuous leveling meter alongside the discrete achievement pops */
.ra-xp-bar { height: 10px; border-radius: var(--ra-radius-pill); background: var(--ra-surface-2); overflow: hidden; position: relative; }
.ra-xp-bar > .ra-xp-fill { height: 100%; background: linear-gradient(90deg, var(--ra-accent), var(--ra-accent-strong)); border-radius: var(--ra-radius-pill); transition: width var(--ra-motion-slow) var(--ra-ease); position: relative; overflow: hidden; }
.ra-xp-bar > .ra-xp-fill::after { content: ''; position: absolute; inset: 0; transform: translateX(-100%); background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .4), transparent); animation: ra-shimmer 1.8s infinite; }

/* ═══ v34 primitives — physics + weather/atmosphere + streak-health overlay ═══ */

/* weather decoration (RAUI.weatherFx) — static opt-in, no live-data wiring
   (consumers pass their own condition, e.g. from a weather tracker) */
@keyframes ra-rain-fall { to { transform: translateY(110vh); } }
@keyframes ra-snow-fall { to { transform: translate(20px, 110vh); } }

/* streak-health ambient overlay — RAUI.healthTint(pct) sets --ra-health-tint;
   a separate fixed layer so it composes with any theme's own !important bg */
#ra-health-overlay {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background: var(--ra-health-tint, transparent);
  transition: background 1s ease;
}

/* ═══ v35 primitives — retro chrome + big systems ═══ */

/* CRT power-off — inverse of ra-crt-boot, same Terminal/Pip-Boy "boot moment"
   exception (fixed duration despite those themes' 0-motion default) */
@keyframes ra-crt-shutdown { 0% { transform: scaleY(1); opacity: 1; } 60% { transform: scaleY(.02); opacity: 1; } 100% { transform: scaleY(.02) scaleX(0); opacity: 0; } }
body.ra-crt-shutting-down { animation: ra-crt-shutdown .4s steps(6, end) forwards; }

/* themed context menu — RAUI.contextMenu(items, x, y) */
.ra-context-menu {
  position: fixed;
  z-index: var(--ra-z-max);
  background: var(--ra-surface-1);
  border: var(--ra-border-w) solid var(--ra-border-strong);
  border-radius: var(--ra-radius-sm);
  box-shadow: var(--ra-shadow-2);
  min-width: 160px;
  padding: 4px;
  font-family: var(--ra-font-body);
  font-size: var(--ra-fs-md);
  animation: ra-fade-in var(--ra-motion) var(--ra-ease);
}
.ra-ctx-item { padding: 6px 10px; border-radius: var(--ra-radius-sm); cursor: pointer; color: var(--ra-text); }
.ra-ctx-item:hover { background: var(--ra-accent-bg); color: var(--ra-accent); }
.ra-ctx-sep { height: 1px; background: var(--ra-divider); margin: 4px 2px; }

/* .ra-window — draggable/resizable window chrome for the OS-skin themes.
   Markup: <div class="ra-window"><div class="ra-window-titlebar">…
   <div class="ra-window-controls">…</div></div><div class="ra-window-body">…</div></div>
   RAUI.makeWindow(el) wires up drag + minimize/close. */
.ra-window {
  position: absolute;
  background: var(--ra-surface-1);
  border: var(--ra-border-w) solid var(--ra-border-strong);
  border-radius: var(--ra-radius-md);
  box-shadow: var(--ra-shadow-2);
  overflow: hidden;
  min-width: 200px;
  min-height: 120px;
  resize: both;
}
.ra-window-titlebar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 4px 8px;
  background: var(--ra-surface-2);
  cursor: move;
  font-size: var(--ra-fs-sm);
  font-weight: 700;
  user-select: none;
}
.ra-window-controls { display: flex; gap: 4px; }
.ra-window-btn {
  width: 16px;
  height: 16px;
  border-radius: 3px;
  border: var(--ra-border-w) solid var(--ra-border-strong);
  background: var(--ra-surface-1);
  cursor: pointer;
  font-size: 9px;
  line-height: 14px;
  text-align: center;
  padding: 0;
}
.ra-window-body { padding: 10px; overflow: auto; height: calc(100% - 30px); }

/* .ra-grip — grabbable affordance (title bars, reorderable rows) */
.ra-grip {
  display: inline-block;
  width: 14px;
  height: 20px;
  background-image: radial-gradient(circle, currentColor 1px, transparent 1.5px);
  background-size: 5px 5px;
  opacity: .4;
  cursor: grab;
}
.ra-grip:active { cursor: grabbing; }

/* idle screensaver — RAUI.enableScreensaver() */
@keyframes ra-screensaver-fall { to { transform: translateY(110vh); } }
@keyframes ra-dvd-bounce {
  0%   { top: 10%; left: 10%; }
  25%  { top: 70%; left: 80%; }
  50%  { top: 20%; left: 60%; }
  75%  { top: 80%; left: 15%; }
  100% { top: 40%; left: 40%; }
}

/* .ra-receipt — thermal-printer-style monospace export layout */
.ra-receipt { font-family: 'Courier New', monospace; width: 280px; background: #fff; color: #000; padding: 12px; font-size: 11px; line-height: 1.5; }
.ra-receipt hr { border: none; border-top: 1px dashed #000; margin: 6px 0; }

/* .ra-trophy-shelf — persistent display of unlocked achievement medals
   (display component only — consumer supplies the unlocked-items list;
   the kit doesn't persist which milestones were already hit) */
.ra-trophy-shelf {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  padding: 12px;
  background: linear-gradient(180deg, var(--ra-surface-2), var(--ra-surface-1));
  border-radius: var(--ra-radius-md);
  border: var(--ra-border-w) solid var(--ra-border);
}
.ra-trophy { display: flex; flex-direction: column; align-items: center; gap: 4px; font-size: 28px; filter: drop-shadow(0 3px 4px rgba(0, 0, 0, .3)); }
.ra-trophy-label { font-size: var(--ra-fs-xs); color: var(--ra-text-dim); }

/* ═══ v36 — true canvas lava-lamp blob physics (was CSS-approximated in v19's
   .ra-aurora-bg; RAUI.lavaLamp() replaces the approximation with a real
   per-frame canvas simulation using the standard "gooey filter" metaball
   technique: overlapping blurred circles + high contrast to fuse edges) ═══ */
.ra-lava-lamp { position: relative; overflow: hidden; }
.ra-lava-lamp canvas { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }

/* reduced motion: kill all kit-driven animation (spinner kept — it conveys state) */
@media (prefers-reduced-motion: reduce) {
  :root:not(.ra-fx-ignore-rm) { --ra-motion: 0s; }
  body[data-ra-hover="shift"] button:not([data-ra-nofx]):hover,
  body[data-ra-hover="shift"] button:not([data-ra-nofx]):active,
  body:not([data-ra-hover="shift"]) button:not([data-ra-nofx]):active:not(:disabled) {
    transform: none;
  }
  .ra-badge-live::before,
  .ra-skeleton::after,
  .ra-progress.indeterminate > .ra-progress-fill,
  .ra-flash-ok, .ra-flash-error,
  #ra-settings-overlay, #ra-settings-panel, .ra-toast,
  [data-ra-tip]::after, .ra-input-error,
  .ra-modal-overlay, .ra-modal, #ra-palette-overlay, #ra-palette,
  #ra-confetti i,
  .ra-check-svg circle, .ra-check-svg path, .ra-nudge,
  .ra-aurora-bg, .ra-gradient-text, .ra-ripple.ra-rippling::after,
  .ra-breathe, .ra-empty .ra-empty-icon,
  .ra-achievement-overlay, .ra-achievement, .ra-achievement-medal, .ra-achievement::before,
  .ra-scroll-reveal, .ra-border-glow::before {
    animation: none !important;
  }
  .ra-tilt { transform: none !important; }
  .ra-scroll-reveal { opacity: 1 !important; }
  .ra-typing span, .ra-ring-bell, body.t-cyber .ra-glitch:hover, body.t-terminal.ra-crt-booting,
  .ra-prism-edge::before {
    animation: none !important;
  }
  .ra-tilt-deep, .ra-press-3d:active { transform: none !important; }
  .ra-spotlight::before { display: none; }
  .ra-magnetic { transform: none !important; }
}

/* ═══ Universal settings FAB + panel (auto-injected by ra-ui.js on
       standalone, non-host pages) ═══ */
#ra-settings-fab {
  position: fixed;
  right: calc(16px + env(safe-area-inset-right, 0px));
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  z-index: var(--ra-z-fab);
  width: 44px;
  height: 44px;
  border-radius: var(--ra-radius-pill);
  border: var(--ra-border-w) solid var(--ra-border-strong);
  background: var(--ra-surface-1);
  color: var(--ra-text);
  font-size: 20px;
  cursor: pointer;
  box-shadow: var(--ra-shadow-1);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform calc(var(--ra-motion) * 2) var(--ra-ease), box-shadow var(--ra-motion) var(--ra-ease);
}
#ra-settings-fab.open { transform: rotate(90deg); transition-timing-function: var(--ra-spring, var(--ra-ease)); }

/* ═══ Scroll-to-top FAB (RAUI.initScrollTopFab) — opt-in per consumer page,
       generalized from the Gademy Jira board's standalone `.totop` button ═══ */
.ra-fab-top {
  position: fixed;
  right: calc(16px + env(safe-area-inset-right, 0px));
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  z-index: var(--ra-z-fab);
  width: 44px;
  height: 44px;
  border-radius: var(--ra-radius-pill);
  border: var(--ra-border-w) solid var(--ra-border-strong);
  background: var(--ra-surface-1);
  color: var(--ra-accent);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  box-shadow: var(--ra-shadow-1);
  display: none;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: transform calc(var(--ra-motion) * 1.5) var(--ra-ease), opacity var(--ra-motion-slow) var(--ra-ease);
}
.ra-fab-top.show { display: flex; opacity: 1; animation: ra-medal-pop calc(var(--ra-motion) * 3) var(--ra-spring, var(--ra-ease)); }
.ra-fab-top:hover { transform: translateY(-3px); box-shadow: var(--ra-shadow-2); }
.ra-fab-top:active { transform: scale(.94); }
/* stacked above the universal settings FAB when both share a page (set by
   RAUI.initScrollTopFab, which detects #ra-settings-fab at call time) */
.ra-fab-top.ra-fab-top--stacked { bottom: calc(70px + env(safe-area-inset-bottom, 0px)); }
/* opts.corner — lets a second instance (e.g. a modal pane's own scroll FAB)
   coexist with the window one instead of overlapping it */
.ra-fab-top.ra-fab-top--bl { right: auto; left: calc(16px + env(safe-area-inset-left, 0px)); }
.ra-fab-top.ra-fab-top--tr { bottom: auto; top: calc(16px + env(safe-area-inset-top, 0px)); }
.ra-fab-top.ra-fab-top--tl { bottom: auto; top: calc(16px + env(safe-area-inset-top, 0px)); right: auto; left: calc(16px + env(safe-area-inset-left, 0px)); }
@media (prefers-reduced-motion: reduce) { .ra-fab-top.show { animation: none; } }

#ra-settings-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--ra-z-overlay);
  background: rgba(0, 0, 0, .55);
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  padding: 18px;
  animation: ra-fade-in calc(var(--ra-motion) * 1.5) var(--ra-ease);
}
#ra-settings-panel {
  animation: ra-slide-up calc(var(--ra-motion) * 2) var(--ra-spring, var(--ra-ease));
  background: var(--ra-surface-1);
  border: var(--ra-border-w) solid var(--ra-border);
  border-radius: var(--ra-radius-lg);
  box-shadow: var(--ra-shadow-2);
  padding: 16px;
  width: min(600px, 94vw);
  max-height: 84vh;
  overflow-y: auto;
  font-family: var(--ra-font-body);
  color: var(--ra-text);
}
#ra-settings-panel .ra-sp-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
  font-size: var(--ra-fs-lg);
  font-weight: 700;
  color: var(--ra-accent);
}
#ra-settings-panel .ra-sp-close {
  background: none;
  border: none;
  color: var(--ra-text-dim);
  font-size: 18px;
  cursor: pointer;
}
#ra-settings-panel .ra-sp-sec {
  margin-bottom: 14px;
}
#ra-settings-panel .ra-sp-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

/* ═══ Hotkey engine (hotkeys-spec.md) ═══ */
#ra-hint-overlay { position: fixed; inset: 0; top: 0; left: 0; width: 0; height: 0; z-index: var(--ra-z-overlay); pointer-events: none; }
.ra-hint-badge {
  position: absolute;
  /* left/top are set to the target's horizontal CENTER + BOTTOM edge
     (ra-ui.js buildHintDom) — reverted here 2026-07-27 (user request) back
     from v76's top-left corner. translate(-50%, ...) centers the badge
     horizontally on the icon; the -75% Y component pulls it up so 75%
     overlaps the icon's bottom and 25% pokes out below, avoiding the
     notification-count badge that lives at the icon's top-right
     (.tab/.pin-slot/.ibtn-slot .badge). */
  transform: translate(-50%, -75%);
  background: var(--ra-accent);
  color: var(--ra-bg);
  font: 700 11px/1 var(--ra-font-mono, monospace);
  padding: 2px 5px;
  border-radius: var(--ra-radius-sm, 4px);
  box-shadow: var(--ra-shadow-1);
  pointer-events: none;
}
#ra-hk-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--ra-z-overlay);
  background: rgba(0, 0, 0, .55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px;
}
#ra-hk-panel {
  background: var(--ra-surface-1);
  border: var(--ra-border-w) solid var(--ra-border);
  border-radius: var(--ra-radius-lg);
  box-shadow: var(--ra-shadow-2);
  padding: 16px;
  width: min(440px, 94vw);
  max-height: 84vh;
  overflow-y: auto;
  font-family: var(--ra-font-body);
  color: var(--ra-text);
}
.ra-hk-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 4px 0;
  border-bottom: 1px solid var(--ra-divider, var(--ra-border));
}
.ra-hk-label { font-size: var(--ra-fs-sm, 12px); color: var(--ra-text-dim); }
.ra-hk-key {
  min-width: 26px;
  text-align: center;
  background: var(--ra-surface-2, var(--ra-bg));
  border: 1px solid var(--ra-border);
  border-radius: 4px;
  padding: 2px 6px;
  font: 700 11px var(--ra-font-mono, monospace);
  color: var(--ra-accent);
  cursor: pointer;
}
.ra-hk-key-static { cursor: default; }
.ra-hk-remove { background: none; border: none; color: var(--ra-text-faint); cursor: pointer; font-size: 12px; }
.ra-hk-empty { color: var(--ra-text-faint); font-size: var(--ra-fs-sm, 12px); padding: 4px 0; }
.ra-hk-addform { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin-top: 8px; }
.ra-hk-addform select { flex: 1; min-width: 140px; background: var(--ra-surface-2, var(--ra-bg)); color: var(--ra-text); border: 1px solid var(--ra-border); border-radius: 4px; padding: 4px 6px; font-size: var(--ra-fs-sm, 12px); }
.ra-hk-addform input { width: 48px; background: var(--ra-surface-2, var(--ra-bg)); color: var(--ra-text); border: 1px solid var(--ra-border); border-radius: 4px; padding: 4px 6px; font-size: var(--ra-fs-sm, 12px); text-align: center; }
.ra-hint-flash { outline: 2px solid var(--ra-accent); outline-offset: 2px; transition: outline-color .9s var(--ra-ease); border-radius: var(--ra-radius-base, 8px); }

/* ═══ Theme debug mode (RAUI.themeDebug) ═══ */
body.ra-debug [data-ra-debug="themed"] {
  outline: 1px dashed rgba(34, 197, 94, .55) !important;
  outline-offset: -1px;
}
body.ra-debug [data-ra-debug="hardcoded"] {
  outline: 2px solid #ff3355 !important;
  outline-offset: -1px;
}
#ra-debug-hud {
  position: fixed;
  right: calc(12px + env(safe-area-inset-right, 0px));
  bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  z-index: var(--ra-z-max);
  background: #111;
  color: #eee;
  border: 1px solid #ff3355;
  border-radius: 8px;
  padding: 10px 12px;
  font: 11px/1.6 monospace;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .5);
  max-width: 260px;
}

/* ═══ Notch — single diagonal corner cut (v45, generalized v46) ═══
   Technical/panel look (sci-fi HUD, blueprint schematic, cut-metal) as an
   alternative to uniform border-radius. clip-path clips the whole painted
   box (bg + border + content) so the cut edge itself has no border stroke —
   that's expected, not a bug: the abrupt bg-color edge reads as intentional
   on a filled card/button. Size via --ra-notch (default 12px); corner via
   modifier class, default (.ra-notch alone) cuts top-right.
   v46 (dashboard-ui-polish-plan.md "Global work" step 1): gated behind
   --ra-notch-friendly so a theme-level flag disables the cut instead of a
   per-theme body-class override. Shadow-only "soft UI" silhouettes (no
   border stroke, e.g. Neumorph) can't carry it — clip-path clips the box's
   own shadow too, leaving a dead flat patch — those themes set
   --ra-notch-friendly:0 in their own CSS; the calc() collapses the cut
   distance to 0 so the polygon degenerates to a plain rect. Also added the
   app-level opt-out (body.ra-fx-notch-off, see RAUI.setFx) so any consumer
   wiring this to a Settings toggle gets it for free. */
:root { --ra-notch-friendly: 1; }
.ra-notch, .ra-notch-tr {
  clip-path: polygon(0 0, calc(100% - var(--ra-notch, 12px) * var(--ra-notch-friendly, 1)) 0, 100% calc(var(--ra-notch, 12px) * var(--ra-notch-friendly, 1)), 100% 100%, 0 100%);
}
.ra-notch-tl {
  clip-path: polygon(calc(var(--ra-notch, 12px) * var(--ra-notch-friendly, 1)) 0, 100% 0, 100% 100%, 0 100%, 0 calc(var(--ra-notch, 12px) * var(--ra-notch-friendly, 1)));
}
.ra-notch-br {
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--ra-notch, 12px) * var(--ra-notch-friendly, 1)), calc(100% - var(--ra-notch, 12px) * var(--ra-notch-friendly, 1)) 100%, 0 100%);
}
.ra-notch-bl {
  clip-path: polygon(0 0, 100% 0, 100% 100%, calc(var(--ra-notch, 12px) * var(--ra-notch-friendly, 1)) 100%, 0 calc(100% - var(--ra-notch, 12px) * var(--ra-notch-friendly, 1)));
}
body.ra-fx-notch-off .ra-notch,
body.ra-fx-notch-off .ra-notch-tr,
body.ra-fx-notch-off .ra-notch-tl,
body.ra-fx-notch-off .ra-notch-br,
body.ra-fx-notch-off .ra-notch-bl { clip-path: none; }

/* ═══ v51 — Ambient layer (idle/at-rest motion, distinct from the
   hover/click/transition primitives above). All LOW amplitude, SLOW
   (4-8s baseline cycle unless noted), opt-in classes, inherit
   prefers-reduced-motion via the block below. ═══ */

/* hearth anchor — small always-present warm glow, never fully still (a
   cozy constant amid everything else that's data-driven) */
.ra-hearth {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--ra-warn, #f59e0b);
  box-shadow: 0 0 6px 1px var(--ra-warn, #f59e0b);
  animation: ra-hearth-flicker 5s ease-in-out infinite;
}
@keyframes ra-hearth-flicker {
  0%, 100% { opacity: .55; box-shadow: 0 0 4px 0px var(--ra-warn, #f59e0b); }
  30%      { opacity: .9;  box-shadow: 0 0 8px 2px var(--ra-warn, #f59e0b); }
  55%      { opacity: .7;  box-shadow: 0 0 5px 1px var(--ra-warn, #f59e0b); }
  78%      { opacity: .85; box-shadow: 0 0 7px 2px var(--ra-warn, #f59e0b); }
}

/* EKG activity line — flat baseline ripple, RAUI.ekgSpike() overlays a
   real spike keyframe when genuine backend activity happens (fits a
   health-tracking dashboard's own vocabulary). Default is a compact
   inline widget (sits in normal flow, e.g. in a topbar) so it can never
   be hidden behind a fixed bottom-nav/FAB — .ra-ekg-line-fixed opts back
   into the old full-width screen-edge overlay if a consumer wants that. */
.ra-ekg-line {
  display: inline-block;
  width: 46px; height: 16px;
  vertical-align: middle;
  pointer-events: none;
  overflow: hidden;
  opacity: .7;
}
.ra-ekg-line-fixed {
  display: block;
  position: fixed; left: 0; right: 0; bottom: 0;
  width: auto; height: 18px;
  z-index: 2;
  opacity: .35;
}
.ra-ekg-line svg { width: 200%; height: 100%; animation: ra-ekg-scroll 6s linear infinite; }
.ra-ekg-line path { fill: none; stroke: var(--ra-ok, #22c55e); stroke-width: 1.5; }
@keyframes ra-ekg-scroll { to { transform: translateX(-50%); } }
.ra-ekg-line.ra-ekg-spike path { stroke: var(--ra-accent, #6366f1); }

/* radar-ping — one expanding ring emanating from an element (freshness /
   connection indicator), distinct from a generic loading spinner */
.ra-radar-ping {
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 1px solid var(--ra-ok, #22c55e);
  animation: ra-radar-ping-fx 1.6s var(--ra-ease) forwards;
  pointer-events: none;
}
@keyframes ra-radar-ping-fx {
  0%   { transform: scale(.4); opacity: .7; }
  100% { transform: scale(1.8); opacity: 0; }
}

/* freshness bar — thin progress fill, JS drives width over the poll
   interval and resets it each cycle; a visual heartbeat independent of
   whether the data itself changed */
.ra-freshness-track {
  position: relative;
  width: 100%; height: 2px;
  background: var(--ra-divider, rgba(255,255,255,.08));
  overflow: hidden;
}
.ra-freshness-fill {
  height: 100%;
  width: 0%;
  background: var(--ra-accent);
  transition: width linear;
}

/* crowd-life — a brief exhale passes through a grid at staggered random
   moments, one card at a time, unpredictable, never simultaneous.
   v53: intensified amplitude + added a glow pulse per user request for
   more perceptible motion ("more animations everywhere") — was tuned too
   subtle in v51/v52 to actually register at a glance. */
@keyframes ra-crowd-exhale {
  0%, 100% { transform: scale(1) translateY(0); box-shadow: none; }
  50%      { transform: scale(.94) translateY(1px); box-shadow: 0 0 0 1px var(--ra-accent-border, transparent) inset; }
}
.ra-crowd-exhale-fx { animation: ra-crowd-exhale 1.1s var(--ra-ease) 1; }

/* dust motes — near-invisible drift across genuinely empty/idle panels */
.ra-dust-mote {
  position: absolute;
  width: 2px; height: 2px;
  border-radius: 50%;
  background: var(--ra-text-faint);
  opacity: 0;
  animation: ra-dust-drift 14s linear infinite;
}
@keyframes ra-dust-drift {
  0%   { opacity: 0; transform: translate(0, 0); }
  10%  { opacity: .25; }
  90%  { opacity: .25; }
  100% { opacity: 0; transform: translate(14px, -22px); }
}

/* heat shimmer — real weather tie: only applied when it's actually hot
   (wired by the consumer alongside RAUI.weatherFx). BUG FIX (same class of
   bug as RAUI.enableTimeLighting, see ra-ui.js comment): the original
   version animated `filter` directly on body, which makes body the
   containing block for every `position:fixed` descendant (nav, settings
   panel, modals) and breaks their viewport-relative positioning the whole
   time it's hot. Rewritten to animate a `::after` pseudo-element instead —
   a pseudo-element's own `position:fixed` box has no effect on its
   ancestor's other (real) fixed-positioned children, so this is safe. */
@keyframes ra-heat-shimmer-pulse {
  0%, 100% { opacity: .4; }
  50%      { opacity: 1; }
}
body.ra-heat-shimmer::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  background: rgba(255, 140, 60, .05);
  mix-blend-mode: soft-light;
  animation: ra-heat-shimmer-pulse 5s ease-in-out infinite;
}

/* windy sway — real weather tie: subtle rotation on opted-in elements only
   when the live tracker reports actual wind */
@keyframes ra-sway {
  0%, 100% { transform: rotate(-.4deg); }
  50%      { transform: rotate(.4deg); }
}
body.ra-windy .ra-sway { animation: ra-sway 3.4s ease-in-out infinite; transform-origin: 50% 100%; }

/* rare-surprise silhouette — a tiny drifting shape, scheduled rarely by
   RAUI.rareSurprise() so it reads as a genuine surprise, not a loop */
.ra-drift-silhouette {
  position: fixed;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  font-size: 14px;
  animation: ra-silhouette-drift 9s linear forwards;
}
@keyframes ra-silhouette-drift {
  0%   { opacity: 0; transform: translate(-20px, 0); }
  8%   { opacity: .5; }
  92%  { opacity: .5; }
  100% { opacity: 0; transform: translate(340px, -18px); }
}

/* sleep-quality-driven boot — one-time slower/softer ease-in applied to
   the whole page for the session, wired by the consumer from real Health
   data (poor sleep the night before -> calmer entrance, not a hard rule) */
@keyframes ra-sleep-boot { from { opacity: 0; filter: brightness(.9); } to { opacity: 1; filter: brightness(1); } }
body.ra-sleep-soft-boot { animation: ra-sleep-boot 2.2s ease-out; }

/* location-driven ambient tint — Home/Office/Away, JS sets --ra-loc-tint
   from real location data; deliberately subtle, atmospheric not decorative */
body { background-image: radial-gradient(140% 140% at 50% -10%, var(--ra-loc-tint, transparent), transparent 60%); }

/* whale-song pulse — a much slower tier (vs the 4-8s guideline above) for
   exactly one "big picture" element, applied alongside .ra-breathe */
.ra-whale-pulse { animation-duration: 220s !important; }
.ra-whale-pulse.ra-border-glow::before, .ra-whale-pulse .ra-breathe, .ra-whale-pulse.ra-breathe {
  animation-duration: 220s !important;
}

/* entropy/neglect — overdue items slowly desaturate the longer they sit;
   JS sets --ra-entropy (0=fresh, 1=long overdue) per element */
.ra-entropy { filter: saturate(calc(1 - (var(--ra-entropy, 0) * .55))) opacity(calc(1 - (var(--ra-entropy, 0) * .2))); transition: filter 1.2s ease; }

/* ═══ v56 — new signature ambient components (user explicitly asked for
   NEW component types, not more coverage of existing ones) ═══ */

/* .ra-flame — organic flickering flame, RAUI.flameSet(el, intensity 0-1)
   drives both size and vividness. Deliberately NOT a symmetric pulse —
   two independently-timed layers (different durations/eases) so the
   flicker reads as natural randomness, not a clean geometric loop.
   Intensity is meant to map to something real (a streak length, a level
   of activity) — bigger/steadier flame = more of it, dim grayed-out ember
   = none, same "true not decorative" principle as the rest of this layer. */
.ra-flame {
  position: relative;
  display: inline-block;
  width: 14px; height: 18px;
  vertical-align: middle;
  transform: scale(var(--ra-flame-scale, .55));
  transform-origin: 50% 100%;
  filter: grayscale(calc(1 - var(--ra-flame-i, 0))) brightness(calc(.6 + .4 * var(--ra-flame-i, 0)));
  transition: transform .6s var(--ra-ease), filter .6s var(--ra-ease);
}
.ra-flame::before, .ra-flame::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  border-radius: 50% 50% 50% 50% / 62% 62% 38% 38%;
  transform: translateX(-50%);
}
.ra-flame::before {
  width: 100%; height: 100%;
  background: radial-gradient(circle at 50% 72%, #ffb703, #fb8500 55%, #d00000 92%);
  animation: ra-flame-flicker-a 1.7s ease-in-out infinite;
}
.ra-flame::after {
  width: 54%; height: 62%;
  background: radial-gradient(circle at 50% 78%, #fff3b0, #ffd166 72%);
  animation: ra-flame-flicker-b 1.15s ease-in-out infinite;
}
@keyframes ra-flame-flicker-a {
  0%, 100% { transform: translateX(-50%) scale(1, 1) rotate(0deg); }
  22%      { transform: translateX(-53%) scale(.93, 1.06) rotate(-3deg); }
  48%      { transform: translateX(-47%) scale(1.06, .94) rotate(2deg); }
  74%      { transform: translateX(-51%) scale(.97, 1.03) rotate(-2deg); }
}
@keyframes ra-flame-flicker-b {
  0%, 100% { transform: translateX(-50%) scaleY(1); opacity: .9; }
  35%      { transform: translateX(-46%) scaleY(1.1); opacity: 1; }
  65%      { transform: translateX(-54%) scaleY(.9); opacity: .82; }
}

@media (prefers-reduced-motion: reduce) {
  .ra-flame::before, .ra-flame::after { animation: none !important; }

  .ra-hearth, .ra-ekg-line svg, .ra-ekg-line.ra-ekg-spike path,
  .ra-radar-ping, .ra-crowd-exhale-fx, .ra-dust-mote,
  body.ra-heat-shimmer::after, body.ra-windy .ra-sway,
  .ra-drift-silhouette, body.ra-sleep-soft-boot {
    animation: none !important;
  }
}

/* ═══ v107 — Web Interface Guidelines audit fixes (audits/2026-09-30-web-interface-guidelines.md) ═══ */
/* touch: no double-tap-zoom delay on controls; deliberate (no) tap flash — :active/:focus-visible already give feedback */
button, .ra-btn, .ra-tab, .ra-pill, select, summary, label, [role="button"],
input[type="checkbox"], input[type="radio"], input[type="range"] { touch-action: manipulation; }
button, .ra-btn, .ra-tab, [role="button"] { -webkit-tap-highlight-color: transparent; }
/* scroll chaining: overlays must not scroll the page behind them */
.ra-modal, .ra-modal-overlay, #ra-palette, #ra-palette-overlay, #ra-settings-panel,
.ra-context-menu, .ra-window { overscroll-behavior: contain; }
/* numbers line up in columns and counters don't jitter */
.ra-table td, .ra-table th, .ra-tabular { font-variant-numeric: tabular-nums; }
/* headings don't leave a one-word widow */
h1, h2, h3, h4, .ra-h { text-wrap: balance; }
/* command palette: its input drops its own outline, so the container shows focus */
#ra-palette:focus-within { outline: 2px solid var(--ra-accent); outline-offset: 1px; }
/* reduced motion: decorative loops/entrances not covered by the blocks above (spinner .ra-busy stays — it conveys state) */
@media (prefers-reduced-motion: reduce) {
  .ra-drop-target, .ra-drop-settle, .ra-text-wipe, .ra-border-spin::after,
  .ra-modal.ra-page-turn, .ra-cube-spin, .ra-xp-bar > .ra-xp-fill::after,
  .ra-context-menu, body.ra-crt-shutting-down { animation: none !important; }
}

/* ═══ FX layer (kit v120) — per-theme entrance + hover animation and theme-switch
   transition. JS stamps the active theme's profile on the page:
   body[data-ra-enter], body[data-ra-hover-anim], html[data-ra-vt]. Everything
   here uses the INDIVIDUAL transform properties (translate/scale/rotate) so it
   composes with — never overwrites — a theme's own `transform`, and is
   switched off by body.ra-fx-enter-anim-off / ra-fx-hover-anim-off, by
   --ra-motion: 0s, and by prefers-reduced-motion. ═══ */
@keyframes ra-e-rise    { from { opacity: 0; translate: 0 calc(12px * var(--ra-fx-amp, 1)); } }
@keyframes ra-e-pop     { from { opacity: 0; scale: calc(1 - .1 * var(--ra-fx-amp, 1)); } 60% { scale: calc(1 + .035 * var(--ra-fx-amp, 1)); opacity: 1; } }
@keyframes ra-e-slide   { from { opacity: 0; translate: calc(-18px * var(--ra-fx-amp, 1)) 0; } }
@keyframes ra-e-drop    { from { opacity: 0; translate: 0 calc(-22px * var(--ra-fx-amp, 1)); } 60% { translate: 0 calc(5px * var(--ra-fx-amp, 1)); opacity: 1; } 80% { translate: 0 calc(-2px * var(--ra-fx-amp, 1)); } }
@keyframes ra-e-flip    { from { opacity: 0; scale: 1 .05; } 55% { scale: 1 1.06; opacity: 1; } }
@keyframes ra-e-unfold  { from { opacity: 0; scale: 1 calc(1 - .45 * var(--ra-fx-amp, 1)); translate: 0 calc(-10px * var(--ra-fx-amp, 1)); } }
@keyframes ra-e-blur    { from { opacity: 0; filter: blur(calc(7px * var(--ra-fx-amp, 1))); } }
@keyframes ra-e-glitch  { 0% { opacity: 0; translate: -7px 0; filter: hue-rotate(90deg); } 18% { opacity: 1; translate: 6px 0; } 32% { translate: -4px 0; filter: hue-rotate(-60deg); } 50% { translate: 3px 0; } 70% { translate: -1px 0; filter: none; } 100% { translate: 0 0; } }
@keyframes ra-e-type    { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes ra-e-flicker { 0% { opacity: 0; } 8% { opacity: 1; } 16% { opacity: .15; } 30% { opacity: .9; } 42% { opacity: .3; } 58% { opacity: 1; } 70% { opacity: .6; } 100% { opacity: 1; } }
body[data-ra-enter="rise"]    { --ra-ek: ra-e-rise; }
body[data-ra-enter="pop"]     { --ra-ek: ra-e-pop; }
body[data-ra-enter="slide"]   { --ra-ek: ra-e-slide; }
body[data-ra-enter="drop"]    { --ra-ek: ra-e-drop; }
body[data-ra-enter="flip"]    { --ra-ek: ra-e-flip; }
body[data-ra-enter="unfold"]  { --ra-ek: ra-e-unfold; }
body[data-ra-enter="blur"]    { --ra-ek: ra-e-blur; }
body[data-ra-enter="glitch"]  { --ra-ek: ra-e-glitch; }
body[data-ra-enter="type"]    { --ra-ek: ra-e-type; --ra-etim: steps(14, end); }
body[data-ra-enter="flicker"] { --ra-ek: ra-e-flicker; --ra-etim: steps(1, end); }
/* the whole panel on tab switch */
body[data-ra-enter]:not(.ra-fx-enter-anim-off) .tab-panel.active {
  animation: var(--ra-ek, ra-e-rise) calc(var(--ra-motion, .15s) * 3 / var(--ra-fx-speed, 1)) var(--ra-etim, var(--ra-ease, ease)) backwards;
}
/* every list item / card as it renders or re-renders (filter, refresh), lightly staggered */
body[data-ra-enter]:not(.ra-fx-enter-anim-off) :is(.todo-row.ra-card, .proj-card, .win-card, .hab-card, .hab-cat-card, .topic-card, .goal-mission-row, .hot-card, .pin-mirror-card, .ra-enter) {
  animation: var(--ra-ek, ra-e-rise) calc(var(--ra-motion, .15s) * 2.4 / var(--ra-fx-speed, 1)) var(--ra-etim, var(--ra-ease, ease)) calc(var(--ra-i, 0) * 28ms / var(--ra-fx-speed, 1)) backwards;
}
body[data-ra-enter] :is(.todo-row.ra-card, .proj-card, .win-card, .hab-card, .hab-cat-card, .topic-card, .goal-mission-row, .hot-card, .pin-mirror-card, .ra-enter):nth-child(2)  { --ra-i: 1; }
body[data-ra-enter] :is(.todo-row.ra-card, .proj-card, .win-card, .hab-card, .hab-cat-card, .topic-card, .goal-mission-row, .hot-card, .pin-mirror-card, .ra-enter):nth-child(3)  { --ra-i: 2; }
body[data-ra-enter] :is(.todo-row.ra-card, .proj-card, .win-card, .hab-card, .hab-cat-card, .topic-card, .goal-mission-row, .hot-card, .pin-mirror-card, .ra-enter):nth-child(4)  { --ra-i: 3; }
body[data-ra-enter] :is(.todo-row.ra-card, .proj-card, .win-card, .hab-card, .hab-cat-card, .topic-card, .goal-mission-row, .hot-card, .pin-mirror-card, .ra-enter):nth-child(5)  { --ra-i: 4; }
body[data-ra-enter] :is(.todo-row.ra-card, .proj-card, .win-card, .hab-card, .hab-cat-card, .topic-card, .goal-mission-row, .hot-card, .pin-mirror-card, .ra-enter):nth-child(6)  { --ra-i: 5; }
body[data-ra-enter] :is(.todo-row.ra-card, .proj-card, .win-card, .hab-card, .hab-cat-card, .topic-card, .goal-mission-row, .hot-card, .pin-mirror-card, .ra-enter):nth-child(7)  { --ra-i: 6; }
body[data-ra-enter] :is(.todo-row.ra-card, .proj-card, .win-card, .hab-card, .hab-cat-card, .topic-card, .goal-mission-row, .hot-card, .pin-mirror-card, .ra-enter):nth-child(8)  { --ra-i: 7; }
body[data-ra-enter] :is(.todo-row.ra-card, .proj-card, .win-card, .hab-card, .hab-cat-card, .topic-card, .goal-mission-row, .hot-card, .pin-mirror-card, .ra-enter):nth-child(n+9) { --ra-i: 8; }

/* hover micro-animation (fine pointers only) */
@keyframes ra-h-bob    { 40% { translate: 0 calc(-3px * var(--ra-fx-amp, 1)); } }
@keyframes ra-h-jelly  { 25% { scale: calc(1 + .1 * var(--ra-fx-amp, 1)) calc(1 - .1 * var(--ra-fx-amp, 1)); } 50% { scale: calc(1 - .06 * var(--ra-fx-amp, 1)) calc(1 + .07 * var(--ra-fx-amp, 1)); } 75% { scale: calc(1 + .03 * var(--ra-fx-amp, 1)) calc(1 - .02 * var(--ra-fx-amp, 1)); } }
@keyframes ra-h-pulse  { 0% { outline: 2px solid color-mix(in srgb, var(--ra-accent) 70%, transparent); outline-offset: 0; } 100% { outline: 2px solid transparent; outline-offset: calc(7px * var(--ra-fx-amp, 1)); } }
@keyframes ra-h-glitch { 0% { translate: 0 0; } 20% { translate: 2px 0; filter: hue-rotate(60deg); } 40% { translate: -2px 1px; } 60% { translate: 1px -1px; filter: hue-rotate(-40deg); } 100% { translate: 0 0; filter: none; } }
@keyframes ra-h-pixel  { 50% { translate: 0 calc(-2px * var(--ra-fx-amp, 1)); } }
@keyframes ra-h-tilt   { from { rotate: calc(-4deg * var(--ra-fx-amp, 1)); } }
@keyframes ra-h-shake  { 0%,100% { translate: 0 0; } 15% { translate: calc(-3px * var(--ra-fx-amp, 1)) calc(1px * var(--ra-fx-amp, 1)); } 30% { translate: calc(3px * var(--ra-fx-amp, 1)) calc(-1px * var(--ra-fx-amp, 1)); } 45% { translate: calc(-2px * var(--ra-fx-amp, 1)) 0; } 60% { translate: calc(2px * var(--ra-fx-amp, 1)) 0; } 80% { translate: calc(-1px * var(--ra-fx-amp, 1)) 0; } }
@keyframes ra-h-flip   { 0% { transform: perspective(300px) rotateX(0); } 45% { transform: perspective(300px) rotateX(calc(-80deg * var(--ra-fx-amp, 1) / 1.6)); } 55% { transform: perspective(300px) rotateX(calc(80deg * var(--ra-fx-amp, 1) / 1.6)); } 100% { transform: perspective(300px) rotateX(0); } }
@media (hover: hover) {
  body[data-ra-hover-anim]:not(.ra-fx-hover-anim-off) :is(.ra-btn, .ra-tab, .tab, .todos-subtab-btn, .idea-filter-pill, .mini-btn, .ra-pill, .dock-tab):hover:not(:disabled) {
    animation: var(--ra-hk, none) calc((var(--ra-motion, .15s) * 2.4 + .08s) / var(--ra-fx-speed, 1)) var(--ra-ease, ease-out);
  }
  body[data-ra-hover-anim="bob"]   { --ra-hk: ra-h-bob; }
  body[data-ra-hover-anim="jelly"] { --ra-hk: ra-h-jelly; }
  body[data-ra-hover-anim="pulse"] { --ra-hk: ra-h-pulse; }
  body[data-ra-hover-anim="glitch"]{ --ra-hk: ra-h-glitch; }
  body[data-ra-hover-anim="pixel"] { --ra-hk: ra-h-pixel; }
  body[data-ra-hover-anim="tilt"]  { --ra-hk: ra-h-tilt; }
  body[data-ra-hover-anim="shake"] { --ra-hk: ra-h-shake; }
  body[data-ra-hover-anim="flip"]  { --ra-hk: ra-h-flip; }
  body[data-ra-hover-anim="flip"] :is(.ra-btn, .ra-tab, .tab, .todos-subtab-btn):hover { animation-timing-function: steps(4, end); }
  body[data-ra-hover-anim="pixel"] :is(.ra-btn, .ra-tab, .tab, .todos-subtab-btn):hover { animation-timing-function: steps(2, end); }
}

/* theme-switch transitions (View Transitions API; the incoming theme chooses) */
html[data-ra-vt]::view-transition-old(root), html[data-ra-vt]::view-transition-new(root) { animation-duration: .5s; }
@keyframes ra-vt-iris   { from { clip-path: circle(0 at var(--vt-x, 50%) var(--vt-y, 50%)); } to { clip-path: circle(150% at var(--vt-x, 50%) var(--vt-y, 50%)); } }
@keyframes ra-vt-wipe   { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes ra-vt-scan   { from { clip-path: inset(0 0 100% 0); filter: brightness(2.2) contrast(1.4); } to { clip-path: inset(0 0 0 0); filter: none; } }
@keyframes ra-vt-glitch-in  { 0% { opacity: 0; translate: -14px 0; filter: hue-rotate(120deg) saturate(2); } 20% { opacity: 1; translate: 10px 0; } 40% { translate: -6px 0; filter: hue-rotate(-80deg); } 60% { translate: 4px 0; } 80% { translate: -1px 0; filter: none; } 100% { translate: 0 0; } }
@keyframes ra-vt-glitch-out { 0% { opacity: 1; } 30% { translate: 8px 0; filter: hue-rotate(90deg); } 60% { translate: -10px 0; opacity: .6; } 100% { opacity: 0; translate: 0 0; } }
@keyframes ra-vt-pixel  { 0% { opacity: 0; filter: blur(8px) contrast(1.6); scale: 1.03; } 100% { opacity: 1; filter: none; scale: 1; } }
@keyframes ra-vt-flip-in  { from { transform: perspective(1500px) rotateY(75deg); opacity: 0; } to { transform: perspective(1500px) rotateY(0); opacity: 1; } }
@keyframes ra-vt-flip-out { from { transform: perspective(1500px) rotateY(0); opacity: 1; } to { transform: perspective(1500px) rotateY(-75deg); opacity: 0; } }
@keyframes ra-vt-zoom   { from { opacity: 0; scale: 1.14; filter: blur(4px); } to { opacity: 1; scale: 1; filter: none; } }
@keyframes ra-vt-zoom-out { to { opacity: 0; scale: .93; } }
@keyframes ra-vt-drop   { 0% { opacity: 0; translate: 0 -60px; } 60% { opacity: 1; translate: 0 8px; } 80% { translate: 0 -3px; } 100% { translate: 0 0; } }
html[data-ra-vt="iris"]::view-transition-old(root), html[data-ra-vt="wipe"]::view-transition-old(root), html[data-ra-vt="scan"]::view-transition-old(root),
html[data-ra-vt="pixel"]::view-transition-old(root), html[data-ra-vt="drop"]::view-transition-old(root) { animation: none; z-index: 1; }
html[data-ra-vt="iris"]::view-transition-new(root)  { animation: ra-vt-iris .65s cubic-bezier(.3, .7, .2, 1); z-index: 2; }
html[data-ra-vt="wipe"]::view-transition-new(root)  { animation: ra-vt-wipe .55s cubic-bezier(.6, 0, .2, 1); z-index: 2; }
html[data-ra-vt="scan"]::view-transition-new(root)  { animation: ra-vt-scan .6s steps(24, end); z-index: 2; }
html[data-ra-vt="glitch"]::view-transition-old(root){ animation: ra-vt-glitch-out .3s steps(6, end) both; }
html[data-ra-vt="glitch"]::view-transition-new(root){ animation: ra-vt-glitch-in .5s steps(9, end) .1s backwards; }
html[data-ra-vt="pixel"]::view-transition-new(root) { animation: ra-vt-pixel .5s steps(6, end); z-index: 2; }
html[data-ra-vt="flip"]::view-transition-old(root)  { animation: ra-vt-flip-out .3s ease-in both; }
html[data-ra-vt="flip"]::view-transition-new(root)  { animation: ra-vt-flip-in .4s ease-out .25s backwards; }
html[data-ra-vt="zoom"]::view-transition-old(root)  { animation: ra-vt-zoom-out .3s ease-in both; }
html[data-ra-vt="zoom"]::view-transition-new(root)  { animation: ra-vt-zoom .5s ease-out; }
html[data-ra-vt="drop"]::view-transition-new(root)  { animation: ra-vt-drop .6s ease-out; z-index: 2; }
/* v164: curtain (opens from the centre), blinds (slats open), warp (blurred zoom through) */
@property --ra-vt-o { syntax: '<percentage>'; inherits: false; initial-value: 0%; }
@keyframes ra-vt-curtain { from { clip-path: inset(0 50% 0 50%); } to { clip-path: inset(0 0 0 0); } }
@keyframes ra-vt-blinds  { from { --ra-vt-o: 0%; } to { --ra-vt-o: 101%; } }
@keyframes ra-vt-warp-in  { from { opacity: 0; scale: 1.28; filter: blur(10px) brightness(1.5); rotate: 1.2deg; } to { opacity: 1; scale: 1; filter: none; rotate: 0deg; } }
@keyframes ra-vt-warp-out { from { opacity: 1; scale: 1; filter: none; } to { opacity: 0; scale: .86; filter: blur(8px); } }
html[data-ra-vt="curtain"]::view-transition-old(root), html[data-ra-vt="blinds"]::view-transition-old(root) { animation: none; z-index: 1; }
html[data-ra-vt="curtain"]::view-transition-new(root) { animation: ra-vt-curtain .7s cubic-bezier(.6, 0, .2, 1); z-index: 2; }
html[data-ra-vt="blinds"]::view-transition-new(root)  { animation: ra-vt-blinds .7s ease-in-out; z-index: 2; -webkit-mask-image: linear-gradient(180deg, #000 var(--ra-vt-o), transparent var(--ra-vt-o)); mask-image: linear-gradient(180deg, #000 var(--ra-vt-o), transparent var(--ra-vt-o)); -webkit-mask-size: 100% 46px; mask-size: 100% 46px; }
html[data-ra-vt="warp"]::view-transition-old(root) { animation: ra-vt-warp-out .35s ease-in both; }
html[data-ra-vt="warp"]::view-transition-new(root) { animation: ra-vt-warp-in .6s ease-out .15s backwards; }

/* v343 (#198): CRT power-on (a bright line opens to the full picture), ink wash (a blurred ink bloom spreads from the pointer), cartridge swap (the old theme is pulled down and out, the new one is pushed in from below) */
@keyframes ra-vt-crt-on  { 0% { clip-path: inset(49.6% 0 49.6% 0); filter: brightness(3) contrast(1.6); } 45% { clip-path: inset(49.6% 0 49.6% 0); filter: brightness(2.4); } 70% { clip-path: inset(0 0 0 0); filter: brightness(1.8) contrast(1.2); } 100% { clip-path: inset(0 0 0 0); filter: none; } }
@keyframes ra-vt-crt-off { from { opacity: 1; } to { opacity: 0; } }
@keyframes ra-vt-ink     { from { clip-path: circle(0 at var(--vt-x, 50%) var(--vt-y, 50%)); filter: blur(14px) contrast(1.5) saturate(.4); } 60% { filter: blur(6px) contrast(1.2); } to { clip-path: circle(155% at var(--vt-x, 50%) var(--vt-y, 50%)); filter: none; } }
@keyframes ra-vt-cart-out { from { translate: 0 0; } to { translate: 0 18%; opacity: .2; } }
@keyframes ra-vt-cart-in  { 0% { translate: 0 100%; } 78% { translate: 0 -2.5%; } 100% { translate: 0 0; } }
html[data-ra-vt="crt-on"]::view-transition-old(root) { animation: ra-vt-crt-off .12s linear both; }
html[data-ra-vt="crt-on"]::view-transition-new(root) { animation: ra-vt-crt-on .62s steps(14, end) .08s backwards; z-index: 2; }
html[data-ra-vt="inkwash"]::view-transition-old(root) { animation: none; z-index: 1; }
html[data-ra-vt="inkwash"]::view-transition-new(root) { animation: ra-vt-ink .85s cubic-bezier(.3, .6, .2, 1); z-index: 2; }
html[data-ra-vt="cartridge"]::view-transition-old(root) { animation: ra-vt-cart-out .35s ease-in both; }
html[data-ra-vt="cartridge"]::view-transition-new(root) { animation: ra-vt-cart-in .55s cubic-bezier(.3, .8, .3, 1) .2s backwards; z-index: 2; }

@media (prefers-reduced-motion: reduce) {
  body[data-ra-enter]:not(.ra-fx-ignore-rm) .tab-panel.active,
  body[data-ra-enter]:not(.ra-fx-ignore-rm) :is(.todo-row.ra-card, .proj-card, .win-card, .hab-card, .hab-cat-card, .topic-card, .goal-mission-row, .hot-card, .pin-mirror-card, .ra-enter),
  body[data-ra-hover-anim]:not(.ra-fx-ignore-rm) :is(.ra-btn, .ra-tab, .tab, .todos-subtab-btn, .idea-filter-pill, .mini-btn, .ra-pill, .dock-tab):hover { animation: none !important; }
}

/* theme-picker filter (v131) — search, category chips, count; token-only so it follows every theme */
.ra-tf { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; width: 100%; margin: 0 0 8px; }
.ra-tf .ra-tf-q { flex: 1 1 150px; min-width: 0; }
.ra-tf-count { font-size: 11px; color: var(--ra-text-dim); white-space: nowrap; }
.ra-tf-chips { display: flex; flex-wrap: wrap; gap: 4px; width: 100%; }
.ra-tf-chip { font: inherit; font-size: 11px; line-height: 1.2; padding: 3px 9px; border-radius: 999px; border: 1px solid var(--ra-border); background: transparent; color: var(--ra-text-mid); cursor: pointer; }
.ra-tf-chip:hover { border-color: var(--ra-accent-border); color: var(--ra-text-bright); }
.ra-tf-chip.active { background: var(--ra-accent-bg); border-color: var(--ra-accent-border); color: var(--ra-text-bright); }
.ra-tf-empty { width: 100%; font-size: 12px; color: var(--ra-text-dim); padding: 6px 2px; }
.ra-tf-group { flex: 0 0 100%; width: 100%; display: flex; align-items: baseline; gap: 6px; margin: 10px 0 2px; font-size: 11px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--ra-text-dim); border-bottom: 1px solid var(--ra-border); padding-bottom: 3px; }
.ra-tf-cap { flex: 1 1 100%; width: 100%; min-height: 2.6em; margin: 4px 0 2px; font-size: 12px; line-height: 1.4; color: var(--ra-text-mid); }
.ra-tf-cap:empty { display: none; }
.ra-tf-cap b { color: var(--ra-text); font-weight: 600; }
.ra-tf-group:first-child { margin-top: 0; }
.ra-tf-group > span { font-weight: 400; letter-spacing: 0; opacity: .75; }

/* v133: tidy picker — equal-width tiles in an auto-fill grid, names truncate, compact headings, quieter chips.
   Beats consumer .sp-btn/.ra-btn padding and min-height; the font still follows the consumer's text-scale vars. */
.ra-tgrid { display: grid !important; width: 100%; flex: 1 1 100%; box-sizing: border-box; grid-template-columns: repeat(auto-fill, minmax(calc(188px * var(--ra-fs-scale, 1)), 1fr)); gap: 6px !important; align-items: stretch; }
.ra-tgrid > button { display: flex; align-items: center; width: 100%; min-width: 0; min-height: 0 !important; margin: 0 !important; padding: 7px 9px !important; font-size: calc(11.5px * var(--fsc, 1) * var(--ra-fs-scale, 1)) !important; line-height: 1.25; text-align: start; overflow: hidden; }
.ra-tgrid > button .ra-sw { flex: none; }
.ra-tgrid > button .ra-tn { min-width: 0; flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ra-tgrid > .ra-tf-group { grid-column: 1 / -1; }
/* theme previews in the picker (v157): .ra-th is empty until the Previews chip loads themes/thumbs.json */
.ra-th { display: none; }
.ra-tgrid.ra-th-on > button { flex-direction: column; align-items: stretch; gap: 5px; }
.ra-tgrid.ra-th-on .ra-th { display: block; width: 100%; height: auto; aspect-ratio: 200 / 120; object-fit: cover; border-radius: var(--ra-radius-sm, 4px); background: var(--ra-surface-2); border: 1px solid var(--ra-border); }
.ra-tgrid.ra-th-on .ra-sw { display: none; }
.ra-ti, .ra-td { display: none; }
.ra-tr { display: contents; }
.ra-tgrid.ra-th-on > button { position: relative; }
.ra-tgrid.ra-th-on .ra-tr { display: flex; align-items: center; gap: 6px; width: 100%; min-width: 0; }
.ra-tgrid.ra-th-on .ra-tr .ra-tn { flex: 1 1 auto; }
.ra-tgrid.ra-th-on .ra-td { display: block; font-size: .76em; line-height: 1.4; color: var(--ra-text-dim); text-align: start; white-space: normal; overflow-wrap: anywhere; }
.ra-tgrid.ra-th-on .ra-ti { display: inline-flex; flex: none; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 50%; border: 1px solid var(--ra-border); color: var(--ra-text); font-size: 14px; line-height: 1; cursor: pointer; }
.ra-tgrid.ra-th-on .ra-ti:hover, .ra-tgrid.ra-th-on .ra-ti:focus-visible { background: var(--ra-accent-bg); border-color: var(--ra-accent-border); outline: none; }
#ra-theme-note { position: fixed; inset: 0; z-index: 100000; background: rgba(0, 0, 0, .35); display: flex; align-items: center; justify-content: center; padding: 16px; }

.ra-tnote { width: min(680px, 100%); max-height: min(86vh, 760px); overflow: auto; padding: 14px 16px; box-shadow: 0 14px 40px rgba(0, 0, 0, .45); font-size: 12.5px; line-height: 1.45; margin: 0; }
#ra-theme-note .ra-tnote { background: var(--ra-bg) !important; background-image: none !important; backdrop-filter: none !important; opacity: 1 !important; }
.ra-tnote-img { display: block; width: 100%; height: auto; aspect-ratio: 200 / 120; object-fit: cover; border-radius: var(--ra-radius-sm, 6px); border: 1px solid var(--ra-border); margin: 4px 0 10px; }
.ra-tnote-img[hidden] { display: none; }
.ra-tnote-h { display: flex; justify-content: space-between; align-items: center; gap: 8px; font-size: 1.25em; margin-bottom: 4px; }
.ra-tnote-d { margin: 0 0 8px; color: var(--ra-text-mid, var(--ra-text-dim)); }
.ra-tnote-r { padding: 7px 0; border-top: 1px solid var(--ra-divider, var(--ra-border)); display: grid; gap: 2px; }
.ra-tnote-r > b { font-size: .95em; }
.ra-tnote-s { justify-self: start; font-size: .78em; padding: 0 8px; border-radius: 999px; border: 1px solid var(--ra-border); color: var(--ra-text-dim); }
.ra-tnote-s[data-s="measured"] { color: var(--ra-ok); border-color: var(--ra-ok-border, var(--ra-border)); }
.ra-tnote-s[data-s="open"], .ra-tnote-s[data-s="not done"] { color: var(--ra-warn); border-color: var(--ra-warn-border, var(--ra-border)); }
.ra-tnote-f { margin-top: 8px; font-size: .8em; color: var(--ra-text-faint, var(--ra-text-dim)); }

.ra-tf-prev.active { background: var(--ra-accent-bg); border-color: var(--ra-accent-border); color: var(--ra-text-bright); }
.ra-tgrid .ra-sw { width: 7px; height: 7px; margin-inline-end: 2px; }
.ra-tgrid .ra-sw:last-of-type { margin-inline-end: 6px; }
.ra-tf { margin-bottom: 10px; gap: 8px; }
.ra-tf-chips { gap: 5px; }
.ra-tf-chip[data-chip="palette"] { margin-inline-start: 10px; }
.ra-tf-chip { white-space: nowrap; }
@media (max-width: 560px) { .ra-tgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .ra-tgrid > button { padding: 7px 7px !important; } .ra-tgrid > button .ra-sw { width: 6px; height: 6px; margin-inline-end: 1px; } }

/* v138: built-in settings sheet is tabbed — pinned head + tab row, fixed height so switching tabs doesn't jump */
#ra-settings-panel { height: min(84vh, 680px); }
#ra-settings-panel .ra-sp-top { position: sticky; top: -16px; z-index: 3; background: var(--ra-surface-1); margin: -16px -16px 12px; padding: 16px 16px 0; border-radius: var(--ra-radius-lg) var(--ra-radius-lg) 0 0; }
#ra-settings-panel .ra-sp-top .ra-sp-head { margin-bottom: 8px; }

/* v154 favourite themes */
.ra-tgrid .ra-fav .ra-tn::after { content: " \2605"; color: var(--ra-warn); }
.ra-tf-favbtn { background: none; border: var(--ra-border-w) solid var(--ra-border-strong); color: var(--ra-text-mid); border-radius: var(--ra-radius-pill); padding: 2px 10px; cursor: pointer; font: inherit; font-size: var(--ra-fs-sm); touch-action: manipulation; }
.ra-tf-favbtn:hover { color: var(--ra-text-bright); border-color: var(--ra-accent); }
.ra-tf-favbtn.on { color: var(--ra-warn); border-color: var(--ra-warn); }

/* print (v187): always light and plain — the theme's colours, backdrop, ornaments and effects stay on screen */
@media print {
  html, body { background: #fff !important; color: #000 !important; filter: none !important; }
  #ra-backdrop, #ra-tune-grain, #ra-settings-fab, .ra-toast, .ra-nudge { display: none !important; }
  body *, body *::before, body *::after { animation: none !important; transition: none !important; text-shadow: none !important; backdrop-filter: none !important; }
  .ra-card, .ra-modal, .ra-window, .ra-panel, .ra-table { background: #fff !important; background-image: none !important; color: #000 !important; box-shadow: none !important; border: 1px solid #888 !important; border-radius: 0 !important; }
  .ra-btn, .ra-tab { display: none !important; }
  a { color: #000 !important; text-decoration: underline !important; }
}
