.resize-observer[data-v-b329ee4c]{position:absolute;top:0;left:0;z-index:-1;width:100%;height:100%;border:none;background-color:transparent;pointer-events:none;display:block;overflow:hidden;opacity:0}.resize-observer[data-v-b329ee4c] object{display:block;position:absolute;top:0;left:0;height:100%;width:100%;overflow:hidden;pointer-events:none;z-index:-1}.v-popper__popper{z-index:10000;top:0;left:0;outline:none}.v-popper__popper.v-popper__popper--hidden{visibility:hidden;opacity:0;transition:opacity .15s,visibility .15s;pointer-events:none}.v-popper__popper.v-popper__popper--shown{visibility:visible;opacity:1;transition:opacity .15s}.v-popper__popper.v-popper__popper--skip-transition,.v-popper__popper.v-popper__popper--skip-transition>.v-popper__wrapper{transition:none!important}.v-popper__backdrop{position:absolute;top:0;left:0;width:100%;height:100%;display:none}.v-popper__inner{position:relative;box-sizing:border-box;overflow-y:auto}.v-popper__inner>div{position:relative;z-index:1;max-width:inherit;max-height:inherit}.v-popper__arrow-container{position:absolute;width:10px;height:10px}.v-popper__popper--arrow-overflow .v-popper__arrow-container,.v-popper__popper--no-positioning .v-popper__arrow-container{display:none}.v-popper__arrow-inner,.v-popper__arrow-outer{border-style:solid;position:absolute;top:0;left:0;width:0;height:0}.v-popper__arrow-inner{visibility:hidden;border-width:7px}.v-popper__arrow-outer{border-width:6px}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-inner{left:-2px}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-outer,.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-outer{left:-1px}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-outer{border-bottom-width:0;border-left-color:transparent!important;border-right-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-inner{top:-2px}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-container{top:0}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-outer{border-top-width:0;border-left-color:transparent!important;border-right-color:transparent!important;border-top-color:transparent!important}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-inner{top:-4px}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-outer{top:-6px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-inner{top:-2px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-outer,.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-outer{top:-1px}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-outer{border-left-width:0;border-left-color:transparent!important;border-top-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-inner{left:-4px}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-outer{left:-6px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-container{right:-10px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-outer{border-right-width:0;border-top-color:transparent!important;border-right-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-inner{left:-2px}.v-popper--theme-tooltip .v-popper__inner{background:rgba(0,0,0,.8);color:#fff;border-radius:6px;padding:7px 12px 6px}.v-popper--theme-tooltip .v-popper__arrow-outer{border-color:#000c}.v-popper--theme-dropdown .v-popper__inner{background:#fff;color:#000;border-radius:6px;border:1px solid #ddd;box-shadow:0 6px 30px #0000001a}.v-popper--theme-dropdown .v-popper__arrow-inner{visibility:visible;border-color:#fff}.v-popper--theme-dropdown .v-popper__arrow-outer{border-color:#ddd}

.auth-modal-backdrop[data-v-86f63bbc] {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(4px);
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.auth-modal[data-v-86f63bbc] {
  position: relative;
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border-subtle);
  border-radius: 16px;
  padding: 2rem;
  width: 100%;
  max-width: 380px;
  color: var(--color-text-primary);
}
.auth-modal__close[data-v-86f63bbc] {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  background: transparent;
  border: none;
  color: var(--color-text-muted);
  font-size: 1.5rem;
  cursor: pointer;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
}
.auth-modal__close[data-v-86f63bbc]:hover {
  background: var(--color-bg-subtle);
  color: var(--color-text-primary);
}
.auth-modal__title[data-v-86f63bbc] {
  margin: 0 0 0.25rem;
  font-size: 1.4rem;
  font-weight: 700;
}
.auth-modal__subtitle[data-v-86f63bbc] {
  margin: 0 0 1.25rem;
  font-size: 0.85rem;
  color: var(--color-text-secondary);
  line-height: 1.4;
}
.auth-modal__form[data-v-86f63bbc] {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}
.auth-modal__field[data-v-86f63bbc] {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  font-size: 0.85rem;
}
.auth-modal__field span[data-v-86f63bbc] {
  color: var(--color-text-secondary);
  font-weight: 500;
}
.auth-modal__field input[data-v-86f63bbc] {
  padding: 0.65rem 0.75rem;
  background: var(--color-bg-base);
  border: 1px solid var(--color-border-subtle);
  border-radius: 8px;
  color: var(--color-text-primary);
  font-size: 0.95rem;
}
.auth-modal__field input[data-v-86f63bbc]:focus {
  outline: 2px solid var(--color-active);
  outline-offset: -1px;
  border-color: var(--color-active);
}
.auth-modal__error[data-v-86f63bbc] {
  margin: 0;
  font-size: 0.8rem;
  color: var(--color-danger, #e54b4b);
}
.auth-modal__submit[data-v-86f63bbc] {
  margin-top: 0.5rem;
  padding: 0.75rem;
  background: var(--color-active);
  border: none;
  border-radius: 8px;
  color: var(--color-bg-base);
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease;
}
.auth-modal__submit[data-v-86f63bbc]:hover:not(:disabled) {
  background: var(--color-accent, var(--color-active));
}
.auth-modal__submit[data-v-86f63bbc]:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.auth-modal__toggle[data-v-86f63bbc] {
  margin-top: 1.25rem;
  width: 100%;
  background: transparent;
  border: none;
  color: var(--color-text-secondary);
  font-size: 0.85rem;
  cursor: pointer;
}
.auth-modal__toggle span[data-v-86f63bbc] {
  color: var(--color-active);
  font-weight: 600;
  text-decoration: underline;
}
.auth-modal__toggle[data-v-86f63bbc]:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.toast-stack[data-v-f83319a5] {
  position: fixed; bottom: calc(env(safe-area-inset-bottom, 0) + 80px);
  left: 50%; transform: translateX(-50%);
  z-index: 100; display: flex; flex-direction: column; gap: 8px;
  pointer-events: none;
}
.toast[data-v-f83319a5] {
  pointer-events: auto;
  display: inline-flex; align-items: center; gap: 12px;
  padding: 12px 16px; border-radius: var(--radius-pill);
  background: var(--text); color: var(--surface);
  font-size: 13px; line-height: 1.3;
  box-shadow: 0 8px 20px rgba(28, 26, 23, 0.12);
  max-width: 90vw;
}
.tone-good[data-v-f83319a5] { background: var(--text);
}
.tone-warn[data-v-f83319a5] { background: var(--warning); color: #fff;
}
.tone-bad[data-v-f83319a5]  { background: var(--danger); color: #fff;
}
.msg[data-v-f83319a5] { flex: 1;
}
.action[data-v-f83319a5] {
  background: transparent; border: 0;
  color: var(--primary); font-weight: 500; cursor: pointer; font: inherit;
  text-transform: uppercase; letter-spacing: 0.04em; font-size: 11px;
}
.toast-enter-active[data-v-f83319a5], .toast-leave-active[data-v-f83319a5] { transition: opacity .2s, transform .2s;
}
.toast-enter-from[data-v-f83319a5], .toast-leave-to[data-v-f83319a5] { opacity: 0; transform: translateY(20px);
}

.backdrop[data-v-e6be2153] {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: flex-end;
  backdrop-filter: blur(2px);
}
.backdrop.warm[data-v-e6be2153] { background: rgba(28, 26, 23, 0.45);
}
.backdrop.deep[data-v-e6be2153] { background: rgba(28, 26, 23, 0.85);
}
.backdrop.center[data-v-e6be2153] { align-items: center; justify-content: center; padding: 20px;
}
.sheet[data-v-e6be2153] {
  width: 100%; background: var(--bg); max-height: 86%; overflow-y: auto;
  padding: 14px 0 22px;
  border-radius: 22px 22px 0 0;
}
.sheet.center[data-v-e6be2153] {
  width: 100%; max-width: 360px; padding: 18px;
  border-radius: 20px;
}
.grip[data-v-e6be2153] {
  width: 36px; height: 4px; background: var(--border-strong);
  border-radius: 999px; margin: 0 auto 14px;
}
.head[data-v-e6be2153] {
  padding: 0 20px 12px;
  display: flex; justify-content: space-between; align-items: baseline;
  border-bottom: 1px solid var(--border-soft);
  margin-bottom: 12px;
}
.title[data-v-e6be2153] { font-family: var(--font-display); font-weight: 380; font-size: 18px; color: var(--text);
}
.close[data-v-e6be2153] {
  background: transparent; border: 0; padding: 2px 4px;
  font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.08em;
  color: var(--text-secondary); cursor: pointer;
}
.body[data-v-e6be2153] { padding: 0 20px;
}
.sheet-enter-active[data-v-e6be2153], .sheet-leave-active[data-v-e6be2153] { transition: opacity .2s ease;
}
.sheet-enter-from[data-v-e6be2153], .sheet-leave-to[data-v-e6be2153] { opacity: 0;
}
.sheet-enter-active .sheet[data-v-e6be2153]:not(.center), .sheet-leave-active .sheet[data-v-e6be2153]:not(.center) {
  transition: transform .25s ease;
}
.sheet-enter-from .sheet[data-v-e6be2153]:not(.center), .sheet-leave-to .sheet[data-v-e6be2153]:not(.center) {
  transform: translateY(100%);
}

.btn[data-v-8581ee2a] {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 8px; font-family: var(--font-body); font-weight: 500;
  border: 1px solid transparent; border-radius: var(--radius-pill);
  cursor: pointer; transition: background .15s, border-color .15s, color .15s;
  white-space: nowrap; line-height: 1;
}
.btn.block[data-v-8581ee2a] { width: 100%;
}
.btn.disabled[data-v-8581ee2a] { cursor: not-allowed; opacity: .55;
}
.size-sm[data-v-8581ee2a] { height: 32px; padding: 0 12px; font-size: 12px;
}
.size-md[data-v-8581ee2a] { height: 38px; padding: 0 14px; font-size: 13px;
}
.size-lg[data-v-8581ee2a] { height: 44px; padding: 0 18px; font-size: 14px;
}
.tone-primary[data-v-8581ee2a] { background: var(--primary); color: var(--text-on-primary);
}
.tone-primary[data-v-8581ee2a]:hover:not(.disabled) { background: var(--primary-hover);
}
.tone-neutral[data-v-8581ee2a] { background: var(--surface); color: var(--text-secondary); border-color: var(--border-strong);
}
.tone-neutral[data-v-8581ee2a]:hover:not(.disabled) { color: var(--text); border-color: var(--text-secondary);
}
.tone-danger[data-v-8581ee2a] { background: var(--danger); color: #fff;
}
.tone-danger[data-v-8581ee2a]:hover:not(.disabled) { filter: brightness(0.93);
}
.tone-ghost[data-v-8581ee2a] { background: transparent; color: var(--text-secondary);
}
.tone-ghost[data-v-8581ee2a]:hover:not(.disabled) { color: var(--text); background: var(--surface-alt);
}
.btn.outlined[data-v-8581ee2a] { background: transparent;
}
.btn.outlined.tone-primary[data-v-8581ee2a] { color: var(--primary); border-color: var(--primary);
}
.btn.outlined.tone-primary[data-v-8581ee2a]:hover:not(.disabled) { background: var(--primary-softer);
}
.btn.outlined.tone-danger[data-v-8581ee2a] { color: var(--danger); border-color: var(--danger);
}
.btn.outlined.tone-neutral[data-v-8581ee2a] { color: var(--text-secondary); border-color: var(--border-strong);
}
.dot-loader[data-v-8581ee2a] { display: inline-flex; gap: 3px;
}
.dot-loader span[data-v-8581ee2a] {
  width: 4px; height: 4px; border-radius: 50%; background: currentColor;
  animation: bounce-8581ee2a 1.4s infinite ease-in-out both;
}
.dot-loader span[data-v-8581ee2a]:nth-child(1) { animation-delay: -0.32s;
}
.dot-loader span[data-v-8581ee2a]:nth-child(2) { animation-delay: -0.16s;
}
@keyframes bounce-8581ee2a {
0%, 80%, 100% { transform: scale(0);
}
40% { transform: scale(1);
}
}

.body[data-v-ae31b8ce] {
  font-size: 13px; color: var(--text-secondary); line-height: 1.5;
  margin-bottom: 14px;
}
.actions[data-v-ae31b8ce] { display: flex; gap: 8px;
}

.ug-overlay[data-v-f00669c6] {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 24px;
}
.ug-card[data-v-f00669c6] {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-soft);
  max-width: 440px;
  width: 100%;
  padding: 28px 28px 22px;
}
.ug-title[data-v-f00669c6] {
  font-family: var(--font-display, inherit);
  font-size: 22px;
  margin: 0 0 8px;
  letter-spacing: -0.01em;
}
.ug-sub[data-v-f00669c6] {
  font-size: 14px;
  color: var(--text-secondary);
  margin: 0 0 18px;
  line-height: 1.5;
}
.ug-feats[data-v-f00669c6] {
  list-style: none;
  padding: 0;
  margin: 0 0 22px;
  font-size: 13px;
  color: var(--text-secondary);
}
.ug-feats li[data-v-f00669c6] {
  padding: 4px 0 4px 18px;
  position: relative;
}
.ug-feats li[data-v-f00669c6]::before {
  content: '';
  position: absolute;
  left: 0;
  top: 12px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--primary);
}
.ug-actions[data-v-f00669c6] {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
}
.ug-btn-secondary[data-v-f00669c6],
.ug-btn-primary[data-v-f00669c6] {
  font-family: inherit;
  font-size: 13px;
  letter-spacing: 0.06em;
  padding: 10px 18px;
  border: 1px solid var(--border-soft);
  background: transparent;
  color: var(--text);
  cursor: pointer;
}
.ug-btn-primary[data-v-f00669c6] {
  background: var(--primary);
  color: var(--bg);
  border-color: var(--primary);
}
.ug-btn-secondary[data-v-f00669c6]:hover { border-color: var(--border-strong);
}
.ug-btn-primary[data-v-f00669c6]:hover { filter: brightness(1.05);
}

.force-update-overlay[data-v-fd73ef2a] {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.85);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  z-index: 9999;
}
.force-update-card[data-v-fd73ef2a] {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-large, 16px);
  padding: var(--space-6);
  max-width: 400px;
  width: 100%;
  text-align: center;
}
.force-update-title[data-v-fd73ef2a] {
  margin: 0 0 var(--space-3);
  font-size: var(--font-size-l);
  color: var(--text);
}
.force-update-body[data-v-fd73ef2a] {
  margin: 0 0 var(--space-5);
  font-size: var(--font-size-s);
  color: var(--text-secondary);
  line-height: 1.5;
}
.force-update-cta[data-v-fd73ef2a] {
  background: var(--primary);
  color: #fff;
  border: none;
  border-radius: var(--radius-medium);
  padding: var(--space-3) var(--space-5);
  font-size: var(--font-size-m);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  width: 100%;
}
.force-update-cta[data-v-fd73ef2a]:hover { opacity: 0.9;
}

.sync-fail[data-v-ac8c7176] {
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + 10px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 999;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  background: color-mix(in srgb, var(--danger) 10%, var(--surface));
  border: 1px solid var(--danger);
  border-radius: var(--radius-pill);
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--danger);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
  pointer-events: none;
}
.dot[data-v-ac8c7176] {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--danger);
}
.rfade-enter-active[data-v-ac8c7176], .rfade-leave-active[data-v-ac8c7176] {
  transition: opacity 200ms ease, transform 200ms ease;
}
.rfade-enter-from[data-v-ac8c7176], .rfade-leave-to[data-v-ac8c7176] {
  opacity: 0;
  transform: translate(-50%, -4px);
}

.app[data-v-d04e8762] {
  height: 100vh;
  width: 100vw;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  font-weight: 500;
}
.app__body[data-v-d04e8762] {
  flex: 1;
  min-height: 0;
  overflow: hidden;
}
.app__viewport[data-v-d04e8762] {
  height: 100%;
  width: 100%;
  min-height: 0;
  min-width: 0;
  /* Hard ceiling: the shell + its scrolling panels live entirely within the
     viewport — nothing grows the page itself. */
  max-height: 100vh;
  max-width: 100vw;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.app__viewport[data-v-d04e8762] > * {
  flex: 1;
  min-height: 0;
}

/* Legacy default for BARE headings only. A classed heading (.ins-heading,
   .rule-detail__title, …) is an intentional design decision and must own
   its own color/size — this global used to clobber all of them (white text,
   forced margin, 0.9em) and every component had to fight it with scoped
   overrides. Restricting to h3:not([class]) lets classed headings style
   themselves without a specificity war. */
[data-v-d04e8762] h3:not([class]){
  margin: 1.5em 0 0 0;
  padding: 0 !important;
  color: var(--color-text-primary);
  font-size: 0.9em;
  font-family: var(--font-title);
}
:root {
  /* Strictly Monochromatic (Pure Grayscale) */
  --neutral-0: #ffffff;
  --neutral-50: #fafafa;
  --neutral-100: #f5f5f5;
  --neutral-200: #e5e5e5;
  --neutral-300: #d4d4d4;
  --neutral-400: #a3a3a3;
  --neutral-500: #737373;
  --neutral-600: #404040;
  --neutral-700: #303030;
  --neutral-750: #202020;
  --neutral-800: #101010;
  --neutral-900: #000000;

  /* Functional Colors (Exceptions - Only for signals/charts) */

  /* Success / Protein / Bio-Positive */
  --emerald-50: #ecfdf5;
  --emerald-400: #34d399;
  --emerald-500: #10b981;
  --emerald-600: #059669;

  /* Info / Carbs / Chart Tendency */
  --sky-50: #ecfdf5;
  --sky-400: #38eff8;
  --sky-500: #0ee9e5;
  --sky-600: #00acb5;
  --sky-1000: #092c2e;

  /* Accent color */
  /* --purp-50: #f4ecfd;
  --purp-400: #c793ff;
  --purp-500: #7f0ee9;
  --purp-600: #6400b5; */

  /* Warning / Fat */
  --amber-50: #f2e9da;
  --amber-400: #fbbf24;
  --amber-500: #f59e0b;
  --amber-600: #d97706;
  --amber-1000: #27160b;

  /* Error / Danger */
  --rose-50: #fff1f2;
  --rose-400: #fb7185;
  --rose-500: #f43f5e;
  --rose-600: #e11d48;

  /* ============================================================
     Earthy / Parchment palette (active theme primitives)
     ============================================================ */

  /* Parchment / warm neutral scale (used by both light & dark) */
  --parch-0: #ffffff;
  --parch-50: #fbf8f3;
  --parch-100: #f5efe4;
  --parch-200: #ebe3d3;
  --parch-300: #d9cdb5;
  --parch-400: #b8a98a;
  --parch-500: #928876;
  --parch-600: #6e6557;
  --parch-700: #5a5249;
  --parch-800: #2e2922;
  --parch-900: #1c1a17;
  --parch-1000: #0f0d0a;

  /* Umber (inky dark surfaces, neutral) */
  --umber-900: #0c0c0c;
  --umber-800: #131313;
  --umber-750: #191919;
  --umber-700: #252525;
  --umber-600: #383838;

  /* Terracotta (accent / danger) */
  --terra-50: #fbeee6;
  --terra-100: #f4d8c6;
  --terra-400: #d98a64;
  --terra-500: #c4633c;
  --terra-600: #a14e2c;
  --terra-1000: #2a1308;

  /* Olive (success / lower-tendency) */
  --olive-50: #eef2e3;
  --olive-400: #8aaa68;
  --olive-500: #6b8a4e;
  --olive-600: #557040;
  --olive-1000: #1a2210;

  /* Ochre (warning) */
  --ochre-50: #f7ecd6;
  --ochre-400: #d4a05a;
  --ochre-500: #b8853a;
  --ochre-600: #946828;
  --ochre-1000: #261a09;

  /* ============================================================
     Severity tokens — single source of truth for interaction
     severity colors. Components reference these (or the `.sev-strip--<x>`
     utility classes in main.css) instead of hardcoded hex fallbacks.
     Resolves against theme-level `--color-*` tokens applied on
     .theme-light / .theme-dark.
     ============================================================ */
  --sev-critical: var(--color-danger, #e54b4b);
  --sev-warning:  var(--color-warning, #e0a23a);
  --sev-benefit:  var(--color-success, #4ca767);
  --sev-info:     var(--color-info, #4a8fc2);
}
:root {
  /* Font Family - macOS System Font Stack */
  --font-sans:
    -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
    "Helvetica Neue", Arial, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --font-title: "Fraunces", Georgia, serif;
  --font-ai-response: "Fraunces", Georgia, serif; /* Font Sizes */
  --size-xs: 0.75rem; /* 12px */
  --size-s: 0.875rem; /* 14px */
  --size-m: 1rem; /* 16px */
  --size-l: 1.125rem; /* 18px */
  --size-xl: 1.25rem; /* 20px */
  --size-2xl: 1.5rem; /* 24px */
  --size-3xl: 1.875rem; /* 30px */
  --size-4xl: 2.25rem; /* 36px */

  /* Font Weights */
  --weight-light: 300;
  --weight-normal: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  /* Line Heights */
  --leading-tight: 1.25;
  --leading-normal: 1.5;
  --leading-relaxed: 1.625;
}
.theme-light {
  color-scheme: light;

  /* Backgrounds */
  --color-bg-base: var(--parch-50);
  --color-bg-subtle: var(--parch-100);
  --color-bg-elevated: var(--parch-0);
  --color-bg-disabled: var(--parch-200);
  --color-bg-active: var(--parch-200);

  /* Text */
  --color-text-primary: var(--parch-900);
  --color-text-secondary: var(--parch-700);
  --color-text-muted: var(--parch-500);
  --color-text-inverted: var(--parch-50);
  --color-text-active: var(--terra-600);

  /* Numbers */
  --color-metric-primary: var(--terra-600);
  --color-metric-secondary: var(--parch-700);

  /* Borders / Dividers */
  --color-border-subtle: var(--parch-200);
  --color-border-default: var(--parch-300);
  --color-border-strong: var(--parch-400);
  --color-active: var(--terra-500);

  /* Shadows */
  --shadow-large: 3px 6px 15px rgba(40, 30, 20, 0.12);

  /* Semantic / Functional */
  --color-accent: var(--terra-500);
  --color-accent-hover: var(--terra-600);

  /* Biological Exceptions (Only for signals) */
  --color-success: var(--olive-500);
  --color-warning: var(--ochre-500);
  --color-danger: var(--terra-600);

  /* Legacy / Specific Macros */
  --color-macro-carbs: var(--terra-500);

  /* Chart Tendencies */
  --chart-line-higher: var(--terra-500);
  --chart-fill-higher: color-mix(in srgb, var(--terra-500), transparent 88%);
  --chart-grad-higher-0: var(--terra-400);
  --chart-grad-higher-1: var(--terra-600);

  --chart-line-lower: var(--olive-500);
  --chart-fill-lower: color-mix(in srgb, var(--olive-500), transparent 88%);
  --chart-grad-lower-0: var(--olive-400);
  --chart-grad-lower-1: var(--olive-600);

  --chart-line-neutral: var(--parch-400);
  --chart-fill-neutral: color-mix(in srgb, var(--parch-400), transparent 88%);
  --chart-grad-neutral-0: var(--parch-300);
  --chart-grad-neutral-1: var(--parch-500);
}
.theme-dark {
  color-scheme: dark;

  /* Backgrounds */
  --color-bg-base: var(--umber-900);
  --color-bg-subtle: var(--umber-800);
  --color-bg-elevated: var(--umber-750);
  --color-bg-active: var(--umber-700);
  --color-bg-disabled: var(--terra-1000);

  /* Text */
  --color-text-primary: var(--parch-100);
  --color-text-secondary: var(--parch-300);
  --color-text-muted: var(--parch-500);
  --color-text-inverted: var(--umber-900);
  --color-text-active: var(--terra-400);

  /* Numbers */
  --color-metric-primary: var(--terra-400);
  --color-metric-secondary: var(--parch-300);

  /* Borders / Dividers */
  --color-border-subtle: var(--umber-800);
  --color-border-default: var(--umber-700);
  --color-border-strong: var(--umber-600);
  --color-active: var(--terra-500);

  /* Shadows */
  --shadow-large: 3px 6px 10px rgba(0, 0, 0, 0.45);

  /* Semantic / Functional */
  --color-accent: var(--terra-500);
  --color-accent-hover: var(--terra-400);

  /* Biological Exceptions (Only for signals) */
  --color-success: var(--olive-400);
  --color-warning: var(--ochre-400);
  --color-danger: var(--terra-400);

  /* Legacy / Specific Macros */
  --color-macro-carbs: var(--terra-400);

  /* Chart Tendencies */
  --chart-line-higher: var(--terra-400);
  --chart-fill-higher: color-mix(in srgb, var(--terra-400), transparent 88%);
  --chart-grad-higher-0: var(--terra-400);
  --chart-grad-higher-1: var(--terra-600);

  --chart-line-lower: var(--olive-400);
  --chart-fill-lower: color-mix(in srgb, var(--olive-400), transparent 88%);
  --chart-grad-lower-0: var(--olive-600);
  --chart-grad-lower-1: var(--olive-400);

  --chart-line-neutral: var(--parch-500);
  --chart-fill-neutral: color-mix(in srgb, var(--umber-700), transparent 88%);
  --chart-grad-neutral-0: var(--parch-500);
  --chart-grad-neutral-1: var(--parch-500);
}
/* Global Base Styles */
:root {
  /* Default to dark theme if no class is present, or just use variables directly */
  /* For now, we expect .theme-dark or .theme-light on the root element */

  /* Max readable width for centered content pages (Home, Health History, …). */
  --content-width: 800px;
}
/* Centered, capped content column. Apply to a page's root content wrapper. */
.content-page {
  width: 100%;
  max-width: var(--content-width);
  margin-inline: auto;
}
/* Shared page heading (serif title + muted subtitle). */
.page-intro {
  margin-bottom: 1.75rem;
}
.page-intro__title {
  font-family: var(--font-title);
  font-weight: 450;
  font-size: 1.9rem;
  color: var(--color-text-primary);
  margin: 0 0 0.4rem;
}
.page-intro__sub {
  color: var(--color-text-secondary);
  max-width: 54ch;
  line-height: 1.5;
}
body {
  font-family: var(--font-sans);
  background-color: var(--color-bg-subtle);
  color: var(--color-text-primary);
  margin: 0;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  user-select: none;
  -webkit-user-select: none;
}
/* Allow text selection in inputs and text areas */
input,
textarea,
[contenteditable] {
  user-select: text;
  -webkit-user-select: text;
}
/* Utility to explicitly enable selection */
.selectable {
  user-select: text;
  -webkit-user-select: text;
}
/* Global text-selection highlight — terracotta accent with legible white text. */
::selection {
  background: var(--color-accent);
  color: #fff;
}
::-moz-selection {
  background: var(--color-accent);
  color: #fff;
}
/* OpenMoji line-art rendered as a currentColor mask, so the (self-hosted,
   stroke-bumped) black SVG paints in the surrounding text color — theme-aware
   monochrome line glyph. Icon URL comes in via the `--omoji` custom property;
   size is set by the host element. */
.omoji-mask {
  background-color: var(--color-accent);
  -webkit-mask-image: var(--omoji);
  mask-image: var(--omoji);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
* {
  box-sizing: border-box;
}
/* Accessibility: respect reduced motion */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
/* ============================================================
   Shared utility classes — pulled out of per-component scoped
   styles to remove duplication. Keep additions here narrow and
   well-named; this isn't a Tailwind layer.
   ============================================================ */
/* Section eyebrow / micro-title (replaces the 8+ hand-rolled blocks). */
.tk-section-title {
  margin: 0;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}
/* Brief flash on a recently-scrolled-to reference row. */
@keyframes tk-ref-flash {
  0% {
    background: color-mix(in srgb, var(--sev-benefit) 18%, transparent);
  }
  100% {
    background: transparent;
  }
}
.tk-ref-flash {
  animation: tk-ref-flash 1.2s ease-out;
}
/* Severity-tinted left strip — apply with .sev-strip + .sev-strip--<severity>. */
.sev-strip {
  border-left-width: 3px;
  border-left-style: solid;
}
.sev-strip--critical {
  border-left-color: var(--sev-critical);
}
.sev-strip--warning {
  border-left-color: var(--sev-warning);
}
.sev-strip--benefit {
  border-left-color: var(--sev-benefit);
}
.sev-strip--info {
  border-left-color: var(--sev-info);
}
/* ============================================================
   Inspector design system — sections render as elevated cards
   that echo the dashboard gauge (apps/lab/src/components/dashboard).
   Card surface + canonical eyebrow + mono micro-text + tinted
   sub-rows (state by tint + number color, NOT a left rail).
   Applied across SignalInspectorPanel and every child context /
   section so the inspector reads as one family with the grid.
   ============================================================ */
/* Section shell — mirrors .gauge / .cc on the dashboard. */
.ins-card {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  padding: 1.25rem 1.5rem;
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border-subtle);
  border-radius: 15px;
}
/* Section heading — the SAME treatment as a dashboard card label
   (.cc__label / .gauge__label): 1.2rem bold, primary, sentence case.
   NOT an uppercase eyebrow — that pattern only belongs on .dash__zone-title,
   which groups cards rather than titling one. Replaces the half-dozen
   hand-rolled 0.6–0.78rem heading variants. */
.ins-heading {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--color-text-primary);
  margin-bottom: 0.5em;
}
/* Mono micro-text — units, times, peak/avg stats (copies .cc__unit /
   .cc__stats). */
.ins-meta {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  color: var(--color-text-muted);
}
/* Sub-item row inside a card. State = subtle bg tint + colored value,
   no 3px severity rail. */
.ins-row {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.5rem 0.65rem;
  border-radius: 8px;
  background: var(--color-bg-base);
  border: 1px solid var(--color-border-subtle);
}
.ins-row--pos {
  background: color-mix(in srgb, var(--color-success) 5%, var(--color-bg-base));
}
.ins-row--neg {
  background: color-mix(in srgb, var(--color-danger) 5%, var(--color-bg-base));
}
.ins-row--critical {
  background: color-mix(in srgb, var(--color-danger) 6%, var(--color-bg-base));
}
.ins-row--warning {
  background: color-mix(in srgb, var(--color-warning) 6%, var(--color-bg-base));
}
.ins-row--win,
.ins-row--benefit {
  background: color-mix(in srgb, var(--color-success) 6%, var(--color-bg-base));
}
.ins-row--info {
  background: color-mix(
    in srgb,
    var(--color-info, #4a8fc2) 6%,
    var(--color-bg-base)
  );
}
.ins-row--inactive {
  opacity: 0.55;
}
/* Floating Vue Tooltip Overrides */
.v-popper--theme-tooltip .v-popper__inner {
  background: var(--color-bg-base) !important;
  color: var(--color-text-primary) !important;
  border: 1px solid var(--color-border-subtle) !important;
  font-family: inherit !important;
  font-weight: 600 !important;
  border-radius: 8px !important;
  padding: 8px 12px !important;
  font-size: 0.85rem !important;
  line-height: 1.4 !important;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4) !important;
  backdrop-filter: blur(8px) !important;
  max-width: 240px !important;
}
.v-popper--theme-tooltip .v-popper__arrow-outer,
.v-popper--theme-tooltip .v-popper__arrow-inner {
  visibility: hidden !important;
}
/* Splitpanes theme overrides */
.splitpanes__splitter {
  transition: background 0.15s ease;
}
.splitpanes__splitter:hover {
  background: var(--color-border-default);
}
.splitpanes--horizontal > .splitpanes__splitter {
  height: 6px;
  cursor: row-resize;
}
.splitpanes--vertical > .splitpanes__splitter {
  width: 6px;
  cursor: col-resize;
}
/* Unified Modal Styles */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
}
.modal-content {
  width: 100%;
  background: var(--color-bg-base);
  border: 1px solid var(--color-border-subtle);
  border-radius: 24px;
  box-shadow: var(--shadow-large);
  position: relative;
  display: flex;
  flex-direction: column;
  max-height: 90vh;
  overflow: hidden;
  color: var(--color-text-primary);
  transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
.modal-header {
  padding: 2.5rem 2.5rem 1rem 2.5rem;
  flex-shrink: 0;
}
.modal-title {
  font-size: 1.8rem;
  font-weight: 800;
  margin: 0;
  letter-spacing: -0.02em;
  color: var(--color-text-primary);
}
.modal-body {
  padding: 1rem 2.5rem 2.5rem 2.5rem;
  overflow-y: auto;
  flex: 1;
}
.modal-close-btn {
  position: absolute;
  top: 1.5rem;
  right: 1.5rem;
  background: var(--color-bg-subtle);
  border: none;
  color: var(--color-text-secondary);
  font-size: 1.1rem;
  cursor: pointer;
  padding: 0.5rem;
  border-radius: 50%;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s;
  z-index: 10;
}
.modal-close-btn:hover {
  background: var(--color-bg-elevated);
  color: var(--color-text-primary);
  transform: rotate(90deg);
}
/* Transition: Fade */
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
@media (max-width: 640px) {
  .modal-overlay {
    padding: 0;
  }
  .modal-content {
    height: 100vh;
    max-height: 100vh;
    border-radius: 0;
  }
  .modal-header {
    padding: 1.5rem;
  }
  .modal-body {
    padding: 1.5rem;
  }
}
/* Shared monitor-band hover popover styles. Used by:
 *   - SignalChart.vue (per-row monitor bands on the studio chart list)
 *   - SignalInspectorPanel.vue (overlay bands on the inspector hero)
 *
 * Typography mirrors TimelineView.vue's vis-timeline item tooltip
 * (.tooltip-time / .tooltip-main / .tooltip-params) — small muted time,
 * bold title, divider before description, divider before label/value
 * row — so every hover in the app reads as one design language.
 *
 * Lives outside any scoped component block on purpose: floating-vue
 * teleports the popper into a portal, and scoped data-v-* attribute
 * selectors don't reliably cascade across the teleport boundary. Global
 * (unscoped) rules apply regardless of which component slotted the
 * content. */

.monitor-popover {
  display: flex;
  flex-direction: column;
  max-width: 280px;
  padding: 0.85rem 1rem;
}
.monitor-popover__time {
  display: block;
  font-weight: 500;
  color: var(--color-text-muted);
  font-size: 0.75rem;
  margin-bottom: 4px;
}
.monitor-popover__title {
  font-weight: 700;
  color: var(--color-text-primary);
  margin-bottom: 4px;
}
.monitor-popover__desc {
  font-size: 0.8rem;
  color: var(--color-text-secondary);
  line-height: 1.5;
  margin-top: 8px;
  padding-top: 6px;
  border-top: 1px solid var(--color-border-subtle);
}
.monitor-popover__param {
  font-size: 0.75rem;
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 8px;
  padding-top: 6px;
  border-top: 1px solid var(--color-border-subtle);
}
.monitor-popover__param-label {
  color: var(--color-text-secondary);
  font-weight: 500;
}
.monitor-popover__param-value {
  color: var(--color-text-secondary);
  font-weight: 700;
  font-family: var(--font-mono);
}
.monitor-popover__param-number {
  color: var(--color-metric-secondary);
}
.monitor-popover__param-unit {
  color: var(--color-text-muted);
  margin-left: 0.25em;
}

/* Floating Vue dropdown popper CONTAINER, themed to our design tokens. The
 * monitor bands use VDropdown's default `dropdown` theme; floating-vue's stock
 * container colors don't match. Global (was previously an unscoped block inside
 * SignalChart.vue, which no longer mounts) so any monitor popover — dashboard
 * ComponentCard, inspector, etc. — gets the themed container. Content padding is
 * handled by .monitor-popover above, so the inner padding is zeroed here. */
.v-popper--theme-dropdown .v-popper__inner {
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border-subtle);
  color: var(--color-text-primary);
  border-radius: 12px;
  box-shadow: var(--shadow-large);
  padding: 0;
}
.v-popper--theme-dropdown .v-popper__arrow-inner {
  border-color: var(--color-bg-elevated);
}
.v-popper--theme-dropdown .v-popper__arrow-outer {
  border-color: var(--color-border-subtle);
}
/* Reusable "lift" hover for clickable cards across the app.
 *
 * Apply `class="card-hover"` to any card/tile/button that should respond to
 * hover with a classy, subtle lift: a small scale-up, an upward nudge, and a
 * soft drop shadow that eases in. Pairs with whatever border/background the
 * component already owns — this utility only touches transform + box-shadow, so
 * it composes cleanly. Keep it as the LAST class so its transition wins.
 *
 * Honors prefers-reduced-motion (no transform, no transition).
 */
.card-hover {
  transition:
    transform 0.18s cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 0.18s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}
.card-hover:hover {
  transform: translateY(-3px) scale(1.012);
  box-shadow: 0 12px 28px -10px color-mix(in srgb, var(--color-text-primary) 22%, transparent);
}
/* Press feedback — settle back down a touch, faster, so a click feels tactile. */
.card-hover:active {
  transform: translateY(-1px) scale(1.004);
  transition-duration: 0.09s;
}

@media (prefers-reduced-motion: reduce) {
  .card-hover,
  .card-hover:hover,
  .card-hover:active {
    transform: none;
    box-shadow: none;
    transition: none;
  }
}
/* Shared timeline item-detail tooltip — used by the horizontal (vis-timeline
 * `title` HTML) and the vertical (agenda floating-vue popover). Markup comes
 * from src/utils/itemTooltip.ts. Global (unscoped) so both render paths match. */

/* The tooltip card. Horizontal: the `.item-tip` div (vis inner is neutralized).
 * Agenda: the floating-vue popper inner IS the card (no nested wrapper), so
 * there's only ever one box. `!important` beats the `tooltip` inner styling that
 * `$extend: 'tooltip'` drags in via the inherited theme class. */
.item-tip,
.v-popper--theme-item-detail .v-popper__inner {
  background: var(--color-bg-base) !important;
  color: var(--color-text-primary);
  border: 1px solid var(--color-border-subtle) !important;
  font-family: inherit;
  font-weight: 600;
  border-radius: 8px !important;
  padding: 8px 12px !important;
  font-size: 0.85rem;
  box-shadow: var(--shadow-large) !important;
  max-width: 280px;
}
.v-popper--theme-item-detail .v-popper__arrow-container {
  display: none;
}

.item-tip__time {
  display: block;
  font-weight: 500;
  color: var(--color-text-muted);
  font-size: 0.75rem;
  margin-bottom: 4px;
}

.item-tip__main {
  display: flex;
  align-items: center;
  gap: 6px;
  font-weight: 700;
  color: var(--color-text-primary);
}

.item-tip__main .ti-omoji {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
}

.item-tip__dur {
  font-weight: 500;
  color: var(--color-text-muted);
}

.item-tip__disabled {
  font-size: 0.7rem;
  color: var(--color-warning);
  text-transform: uppercase;
}

/* Params */
.item-tip__params {
  margin-top: 8px;
  padding-top: 6px;
  border-top: 1px solid var(--color-border-subtle);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.item-tip__param {
  font-size: 0.75rem;
  display: flex;
  justify-content: space-between;
  gap: 12px;
}
.item-tip__param-label {
  color: var(--color-text-secondary);
  font-weight: 500;
}
.item-tip__param-value {
  color: var(--color-text-secondary);
  font-weight: 700;
  font-family: var(--font-mono);
}
.item-tip__param-number {
  color: var(--color-metric-secondary);
}
.item-tip__param-unit {
  color: var(--color-text-muted);
  margin-left: 0.25em;
}

/* Fired-rule interaction rows */
.item-tip__interactions {
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--color-border-subtle);
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.item-tip__irow {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  font-size: 0.8rem;
  min-width: 0;
}
.item-tip__ititle {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
  white-space: normal;
  line-height: 1.3;
}
.item-tip__iicon {
  display: inline-flex;
  width: 16px;
  height: 16px;
  border-radius: 8px;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 0.7rem;
  color: #fff;
  flex-shrink: 0;
}
.item-tip__irow--critical .item-tip__iicon { background: var(--sev-critical); }
.item-tip__irow--warning .item-tip__iicon { background: var(--sev-warning); }
.item-tip__irow--benefit .item-tip__iicon { background: var(--sev-benefit); }
.item-tip__irow--info .item-tip__iicon { background: var(--sev-info); }
/*
 * Tracker design system — global CSS ported from the former tracker app for
 * the tracker→lab merge (Phase 1, docs/shared/2026-07-21-tracker-lab-merge-plan.md).
 *
 * Import order mirrors tracker's cascade exactly: colors → themes →
 * primitives → app, then the element-level globals that lived at the top
 * of tracker's style.css (its own rules always came after its @imports).
 *
 * De-confliction contract (docs/shared/2026-07-21-tracker-lab-css-deconfliction.md):
 *   - Token definitions (:root and html[data-theme="dark"]) stay UNscoped —
 *     the tracker/lab custom-property namespaces are disjoint (sole
 *     collision, --font-mono, is de-duped in themes.css: lab's
 *     variables/typography.css owns it).
 *   - Every rule that APPLIES styles (elements, generic classes) is scoped
 *     under `.trk`, the root class carried by migrated tracker screens.
 *   - `.pk-*` primitives are already namespaced — unscoped by design.
 *   - floating-vue overrides were NOT ported; lab's skin is canonical.
 *
 * This barrel must load AFTER lab's main.css (see src/main.ts).
 */
/*
 * Raw color palette.
 * Theme-independent. Never reference these directly from components —
 * map them to semantic tokens in themes.css instead.
 */
:root {
  /* Neutrals — pure grayscale, no tint */
  --palette-white: #ffffff;
  --palette-black: #000000;
  --palette-gray-50: #fafafa;
  --palette-gray-100: #f5f5f5;
  --palette-gray-200: #e5e5e5;
  --palette-gray-300: #d4d4d4;
  --palette-gray-400: #a3a3a3;
  --palette-gray-500: #737373;
  --palette-gray-600: #525252;
  --palette-gray-700: #404040;
  --palette-gray-800: #262626;
  --palette-gray-900: #171717;
  --palette-gray-950: #0a0a0a;

  /* Brand (indigo) */
  --palette-indigo-300: #a5b4fc;
  --palette-indigo-400: #818cf8;
  --palette-indigo-500: #6366f1;
  --palette-indigo-600: #4f46e5;
  --palette-indigo-700: #4338ca;

  /* Blue — calories */
  --palette-blue-300: #93c5fd;
  --palette-blue-400: #60a5fa;
  --palette-blue-500: #4ea3ff;
  --palette-blue-600: #2563eb;
  --palette-blue-700: #1d4ed8;

  /* Green — protein / primary (terminal) */
  --palette-green-300: #86fbad;
  --palette-green-400: #5bf591;
  --palette-green-500: #3fb26a;
  --palette-green-600: #2d8a51;
  --palette-green-700: #1f6b3e;

  /* Orange / amber — fat / warning */
  --palette-amber-300: #f3d08a;
  --palette-amber-400: #eac574;
  --palette-amber-500: #e6b855;
  --palette-amber-600: #c49840;
  --palette-orange-500: #f97316;

  /* Red — danger */
  --palette-red-300: #ffb3b3;
  --palette-red-400: #ff8a8a;
  --palette-red-500: #ff5a5a;
  --palette-red-600: #e04545;
  --palette-red-700: #b91c1c;

  /* Aqua — carbs (bright teal) */
  --palette-aqua-300: #a7fbf8;
  --palette-aqua-400: #62f9f4;
  --palette-aqua-500: #2dd4cf;
  --palette-aqua-600: #1ba8a3;

  /* Slate — terminal neutrals (replaces blue-tinted gray for dark mode) */
  --palette-slate-950: #05080a;
  --palette-slate-900: #0a0f12;
  --palette-slate-850: #0d1318;
  --palette-slate-800: #111a20;
  --palette-slate-700: #1a2630;
  --palette-slate-600: #24333e;
  --palette-slate-500: #2e3a43;
  --palette-slate-400: #355046;
  --palette-slate-300: #4f7266;
  --palette-slate-200: #9ab9a8;
  --palette-slate-100: #d8f5de;

  /* Accents (dashboard series) */
  --palette-sky-500: #0ea5e9;
  --palette-violet-500: #8b5cf6;
  --palette-pink-500: #ec4899;
  --palette-teal-500: #14b8a6;
  --palette-lime-500: #84cc16;
  --palette-rose-500: #e11d48;
  --palette-cyan-500: #06b6d4;

  /* Symptom severity heatmap (0 = green, 10 = red) */
  --palette-sev-0: #22c55e;
  --palette-sev-1: #fde047;
  --palette-sev-2: #fcd34d;
  --palette-sev-3: #fbbf24;
  --palette-sev-4: #f59e0b;
  --palette-sev-5: #fb923c;
  --palette-sev-6: #f97316;
  --palette-sev-7: #ea580c;
  --palette-sev-8: #f87171;
  --palette-sev-9: #ef4444;
  --palette-sev-10: #dc2626;

  /* --------------------------------------------------------------------
   * Protokol brand palette — parchment / ink / umber.
   * Canonical values from apps/marketing/src/assets/styles.css.
   * The semantic layer in themes.css maps onto these for the light theme.
   * Dark theme keeps the terminal aesthetic for now; rebrand deferred
   * to Phase 6 (see plans/brand-unification.md).
   * --------------------------------------------------------------------*/

  /* Parchment surfaces — warm off-white, slightly cooler in shadows */
  --palette-parchment-0: #fbf8f3;   /* primary bg */
  --palette-parchment-100: #f5efe4; /* recessed/banded bg */
  --palette-panel-warm: #f8f3e8;    /* warm card — Otto callouts, unlogged states */

  /* Ink — sepia-shifted blacks for body text */
  --palette-ink-900: #1c1a17;       /* primary text */
  --palette-ink-700: #5a5249;       /* secondary text */
  --palette-ink-500: #928876;       /* tertiary text / labels */

  /* Hairlines — semi-transparent ink for borders + dividers.
     line-strong (0.22) matches the mockup's input-border weight; the old
     0.16 reads too thin on parchment. */
  --palette-line-soft: rgba(40, 30, 20, 0.10);
  --palette-line-strong: rgba(40, 30, 20, 0.22);

  /* Umber / terra — primary accent */
  --palette-umber-500: #c4633c;                     /* primary action */
  --palette-umber-700: #a14e2c;                     /* hover/press, italic serif accent */
  --palette-umber-soft: #ecd5c4;                    /* opaque tinted bg (cards, chips) */
  --palette-umber-softer: rgba(196, 99, 60, 0.08);  /* ℞ tile bg, sparkline fill */

  /* Brand-tuned status — mockup-canonical values */
  --palette-warn-500: #c97b3a;
  --palette-good-500: #6b8a4f;
  --palette-neg-500: #a14e2c;
  --palette-bad-500: #c4453c;   /* danger red — distinct from neg-500 (which serves accent-deep) */

  /* Macro tinted variants for warm-bg surfaces (food rows, allocator segments) */
  --palette-macro-protein-dark: #3d9e5e;
  --palette-macro-fat-dark:     #a5832b;
  --palette-macro-carbs-dark:   #3aa6a3;

  /* Compound class — Cardio/Resistance/HIIT live on the terracotta ramp; Recovery is sage */
  --palette-class-cardio:     #c4633c;
  --palette-class-resistance: #a14e2c;
  --palette-class-hiit:       #a8431f;
  --palette-class-recovery:   #6b8a4f;

  /* Parchment — deepest warm surface (mockup panelDeep) */
  --palette-parchment-200: #efe7d8;
}
/*
 * Semantic design tokens + light/dark themes.
 * Components reference only these variables — never palette-* directly.
 *
 * Theme selector: `html[data-theme="dark"]` (set pre-paint by
 * public/theme-init.js and kept in sync by App.vue's theme watchEffect,
 * which writes BOTH `data-theme` and lab's `.theme-*` class from the ui
 * store). Defaults to light.
 *
 * Aesthetic (light, current default): Protokol brand —
 *   parchment surfaces (#fbf8f3), ink text (#1c1a17), umber accent (#c4633c).
 *   Fraunces (serif) for display, Inter for body, JetBrains Mono for data.
 *
 * Aesthetic (dark, legacy): terminal / reticle — deep slate + phosphor green.
 *   Will be re-skinned to a parchment-noir variant in Phase 6 of
 *   plans/brand-unification.md.
 */
:root {
  /* ---- Typography contract ------------------------------------------
   * Three font slots, loaded statically via index.html Google Fonts link:
   *   --font-display → h1-h6 (applied globally in style.css). Serif, Fraunces.
   *   --font-body    → paragraphs, labels, buttons, inputs, nav (inherits from body).
   *                    Sans, Inter.
   *   --font-mono    → numeric data, table cells, chart axes, timestamps
   *                    (applied via class selector list in style.css). JetBrains Mono.
   *
   * Components should NOT set font-family directly. To promote a new
   * numeric readout to mono, add its class to the selector list in
   * style.css rather than scoping font-family to the component.
   */
  --font-display: "Fraunces", "Tiempos", Georgia, serif;
  --font-body:
    "Inter", system-ui, -apple-system, Helvetica, Arial, sans-serif;
  /* --font-mono is intentionally NOT defined here — lab's
     assets/css/variables/typography.css owns the single (byte-identical)
     definition. De-duped during the tracker→lab CSS merge. */

  --font-weight-light: 400;
  --font-weight-medium: 500;
  --font-weight-bold: 700;

  --font-size-xs: 0.72rem;
  --font-size-s: 0.85rem;
  --font-size-m: 0.95rem;
  --font-size-l: 1.15rem;
  --font-size-xl: 1.5rem;

  /* ---- Letter-spacing ----------------------------------------------- */
  --tracking-tight: -0.01em;
  --tracking-normal: 0;
  --tracking-wide: 0.03em;
  --tracking-wider: 0.08em;
  --tracking-widest: 0.14em;

  /* ---- Spacing scale ------------------------------------------------
   * Base = 4px. Components should reference these instead of raw rem so
   * density changes are one-place edits.
   */
  --space-1: 0.25rem; /* 4  */
  --space-2: 0.5rem; /* 8  */
  --space-3: 0.75rem; /* 12 */
  --space-4: 1rem; /* 16 */
  --space-5: 1.25rem; /* 20 */
  --space-6: 1.5rem; /* 24 */
  --space-8: 2rem; /* 32 */
  --space-10: 2.5rem; /* 40 */
  --space-12: 3rem; /* 48 */

  /* ---- Motion ------------------------------------------------------- */
  --transition-fast: 100ms;
  --transition-base: 150ms;
  --transition-slow: 250ms;

  /* ---- Controls (buttons / inputs) ---------------------------------- */
  --control-height-sm: 28px;
  --control-height-md: 36px;
  --control-height-lg: 44px;
  --control-pad-x-sm: 0.5rem;
  --control-pad-x-md: 0.75rem;

  /* ---- Radius — Protokol Clinic·Warm scale --------------------------
   * Mockup-canonical sizes. Inputs + ℞ small tile sit at 8px; tile cards
   * (StatTile, QuickLog, CompoundRow) sit at 14px; hero + meal cards sit
   * at 18px. Pills go all-the-way round at 999px. */
  --radius-small: 8px;
  --radius-medium: 14px;
  --radius-large: 18px;
  --radius-pill: 999px;

  /* ---- Macro accents (same hue in both themes) ----------------------- */
  --color-cal: var(--text);
  --color-cal-strong: var(--text);
  --color-protein: var(--palette-green-400);
  --color-fat: var(--palette-amber-500);
  --color-carbs: var(--palette-aqua-400);
  --color-carbs-strong: var(--palette-aqua-500);

  /* Macro dark variants — for chips/labels on warm parchment surfaces. */
  --color-protein-dark: var(--palette-macro-protein-dark);
  --color-fat-dark:     var(--palette-macro-fat-dark);
  --color-carbs-dark:   var(--palette-macro-carbs-dark);

  /* Compound classes — exercise icons, class labels */
  --color-class-cardio:     var(--palette-class-cardio);
  --color-class-resistance: var(--palette-class-resistance);
  --color-class-hiit:       var(--palette-class-hiit);
  --color-class-recovery:   var(--palette-class-recovery);

  /* Dashboard series accents */
  --color-waist: var(--palette-blue-400);
  --color-score: var(--palette-green-400);
  --color-dose: var(--palette-amber-500);
  --color-weight: var(--palette-green-400);

  /* Symptom rotation (8 colors) */
  --color-symptom-1: var(--palette-green-400);
  --color-symptom-2: var(--palette-amber-500);
  --color-symptom-3: var(--palette-blue-500);
  --color-symptom-4: var(--palette-red-500);
  --color-symptom-5: var(--palette-violet-500);
  --color-symptom-6: var(--palette-lime-500);
  --color-symptom-7: var(--palette-pink-500);
  --color-symptom-8: var(--palette-teal-500);

  /* ---- Light theme (default) — Protokol brand: parchment + umber --- */
  /* Surfaces */
  --bg: var(--palette-parchment-0);             /* #fbf8f3 */
  --surface: var(--palette-white);              /* #ffffff cards / panels */
  --surface-alt: var(--palette-parchment-100);  /* #f5efe4 recessed bands */
  --surface-warm: var(--palette-panel-warm);    /* #f8f3e8 Otto callouts, unlogged */
  --surface-deep: var(--palette-parchment-200); /* #efe7d8 deepest warm — sparingly */
  --surface-raised: var(--palette-white);
  --border: transparent;
  --border-strong: var(--palette-line-strong);  /* rgba ink, 22% */
  --border-soft: var(--palette-line-soft);      /* rgba ink, 10% */

  /* Text */
  --text: var(--palette-ink-900);               /* #1c1a17 */
  --text-primary: var(--palette-ink-900);
  --text-secondary: var(--palette-ink-700);     /* #5a5249 */
  --text-tertiary: var(--palette-ink-500);      /* #928876 */
  --text-on-primary: var(--palette-white);      /* text on umber fills */
  --text-disabled: var(--palette-ink-500);
  --text-max-contrast: #000;

  /* Brand — umber / terra */
  --primary: var(--palette-umber-500);          /* #c4633c */
  --primary-hover: var(--palette-umber-700);    /* #a14e2c */
  --primary-dim: var(--palette-umber-700);
  --primary-deep: var(--palette-umber-700);     /* italic serif accent, ℞ glyph */
  --primary-soft: var(--palette-umber-soft);    /* opaque tinted bg */
  --primary-softer: var(--palette-umber-softer);/* ℞ tile bg, sparkline fill */
  --primary-soft-strong: rgba(196, 99, 60, 0.20);
  --primary-ring: rgba(196, 99, 60, 0.30);
  --primary-focus: rgba(196, 99, 60, 0.18);

  /* Status — brand-tuned warm tones (lower contrast than stock) */
  --success: var(--palette-good-500);           /* #6b8a4f */
  --success-soft: rgba(107, 138, 79, 0.14);
  --danger: var(--palette-bad-500);             /* #c4453c — mockup-canonical, distinct from neg-500 */
  --danger-soft: rgba(196, 69, 60, 0.10);
  --warning: var(--palette-warn-500);           /* #c97b3a */

  /* Overlays / shadows — warm shadow tone to match parchment surfaces */
  --overlay: rgba(40, 30, 20, 0.45);
  --shadow-s: 0 1px 4px rgba(40, 30, 20, 0.08);
  --shadow-m: 0 8px 24px rgba(40, 30, 20, 0.10);
  --shadow-l: 0 24px 60px rgba(40, 30, 20, 0.12);

  /* Chart helpers */
  --chart-grid: var(--palette-line-soft);
  --chart-axis: var(--palette-ink-500);

  /* Tinted surfaces (carbs) — kept aqua because the macro chart language
     is non-brand and we don't want to recolor all the existing data viz
     in this pass. Phase 1.3 may revisit. */
  --tint-carbs-soft: rgba(98, 249, 244, 0.1);
  --tint-carbs-softer: rgba(98, 249, 244, 0.05);
  --tint-carbs-softest: rgba(98, 249, 244, 0.025);
  --tint-carbs-border: rgba(98, 249, 244, 0.3);

  /* Target line on progress tracks */
  --track-target-line: rgba(255, 255, 255, 0.8);
  --track-target-halo: rgba(40, 30, 20, 0.25);
}
/* ---- Dark theme — terminal / reticle ------------------------------- */
html[data-theme="dark"] {
  --bg: var(--palette-slate-950); /* #05080a */
  --surface: var(--palette-slate-850); /* #0a0f12 */
  --surface-alt: var(--palette-slate-800); /* #0d1318 */
  --surface-warm: var(--palette-slate-800); /* dark stub — Phase 6 reskin */
  --surface-raised: var(--palette-slate-700); /* #111a20 */
  --border: transparent; /* #1a2630 */
  --border-strong: var(--palette-slate-600); /* #24333e */
  --border-soft: #0f1920;

  --text: var(--palette-slate-100); /* #d8f5de */
  --text-primary: var(--palette-slate-100);
  --text-secondary: var(--palette-slate-200); /* #9ab9a8 */
  --text-tertiary: var(--palette-slate-300); /* #4f7266 */
  --text-on-primary: var(
    --palette-slate-950
  ); /* green buttons → near-black text */
  --text-disabled: var(--palette-slate-400); /* #355046 */
  --text-max-contrast: #fff;

  /* Brand — terminal phosphor */
  --primary: var(--palette-green-400); /* #5bf591 */
  --primary-hover: var(--palette-green-300); /* #86fbad */
  --primary-dim: var(--palette-green-500); /* #3fb26a */
  --primary-deep: var(--palette-green-500);  /* dark stub for italic accent */
  --primary-soft: rgba(91, 245, 145, 0.1);
  --primary-softer: rgba(91, 245, 145, 0.05);
  --primary-soft-strong: rgba(91, 245, 145, 0.18);
  --primary-ring: rgba(91, 245, 145, 0.35);
  --primary-focus: rgba(91, 245, 145, 0.22);

  --success: var(--palette-green-400);
  --danger: var(--palette-red-500);
  --danger-soft: rgba(255, 90, 90, 0.1);
  --warning: var(--palette-amber-500);

  --overlay: rgba(0, 0, 0, 0.65);
  --shadow-s: 0 1px 4px rgba(0, 0, 0, 0.5);
  --shadow-m: 0 8px 24px rgba(0, 0, 0, 0.5);
  --shadow-l: 0 40px 80px rgba(0, 0, 0, 0.5), 0 0 60px rgba(91, 245, 145, 0.06);

  --chart-grid: var(--palette-slate-700);
  --chart-axis: var(--palette-slate-300);

  --tint-carbs-soft: rgba(98, 249, 244, 0.16);
  --tint-carbs-softer: rgba(98, 249, 244, 0.09);
  --tint-carbs-softest: rgba(98, 249, 244, 0.04);
  --tint-carbs-border: rgba(98, 249, 244, 0.35);

  --track-target-line: rgba(216, 245, 222, 0.6);
  --track-target-halo: rgba(0, 0, 0, 0.6);

  /* Dashboard series — dark mode tuned */
  --color-cal: var(--text);
  --color-protein: var(--palette-green-400);
  --color-fat: var(--palette-amber-500);
  --color-carbs: var(--palette-aqua-400);
  --color-waist: var(--palette-blue-500);
  --color-score: var(--palette-green-400);
  --color-weight: var(--palette-green-400);
}
/*
 * Brand primitives — the Clinic·Warm utility class library.
 * Spec: docs/mobile-design-language.md
 *
 * Three categories:
 *   1. Typography utilities (.pk-serif, .pk-it, .pk-mono, .pk-mono-inline)
 *   2. Layout primitives (.pk-card, .pk-card-tile, .pk-card-warm, .pk-section-label)
 *   3. Controls (.pk-btn-primary, .pk-btn-ghost, .pk-pill, .pk-tap)
 *
 * Components consume these classes directly. Avoid duplicating the rules
 * inline — if a component needs a one-off variant, extend with a scoped
 * class that builds on the primitive (e.g. .stat-tile composes pk-card-tile).
 */
/* ─────────────────────────────────────────────────────────────
 * Typography
 * ─────────────────────────────────────────────────────────────*/
.pk-serif {
  font-family: var(--font-display);
  font-weight: 380;
  letter-spacing: -0.018em;
  font-feature-settings: "ss01";
  color: var(--text);
}
.pk-it {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  color: var(--primary-deep);
}
/* Micro-label — section prefixes, units, axis ticks. Uppercase + tracked. */
.pk-mono {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  font-weight: 400;
  line-height: 1.2;
}
/* Inline numeric data — sits in body text, sized to match parent. */
.pk-mono-inline {
  font-family: var(--font-mono);
  font-size: inherit;
  letter-spacing: 0.02em;
}
/* Section header label with the editorial numbered prefix. Usage:
   <div class="pk-section-label">01 / Weight</div>                       */
.pk-section-label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  margin-bottom: 4px;
}
/* ─────────────────────────────────────────────────────────────
 * Cards
 * ─────────────────────────────────────────────────────────────*/
.pk-card {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: 18px;
  padding: 20px;
}
/* Tile — smaller, denser. StatTile, QuickLogCard, CompoundRow. */
.pk-card-tile {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: 14px;
  padding: 16px 16px 18px;
}
/* Warm — Otto callouts, unlogged quick-log cards. The "needs attention
   or is anthropomorphic" surface. */
.pk-card-warm {
  background: var(--surface-warm);
  border: 1px solid var(--primary-soft);
  border-radius: 18px;
  padding: 18px;
}
/* ─────────────────────────────────────────────────────────────
 * Pills (chips, status, scores)
 * ─────────────────────────────────────────────────────────────*/
.pk-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  line-height: 1;
}
.pk-pill-good {
  background: rgba(107, 138, 79, 0.14);
  color: var(--success);
}
.pk-pill-accent {
  background: var(--primary-softer);
  color: var(--primary);
}
.pk-pill-warn {
  background: rgba(201, 123, 58, 0.12);
  color: var(--warning);
}
/* ─────────────────────────────────────────────────────────────
 * Buttons
 * ─────────────────────────────────────────────────────────────*/
.pk-btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 36px;
  padding: 0 14px;
  border: 0;
  border-radius: 999px;
  background: var(--primary);
  color: #ffffff;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.15s ease, opacity 0.12s ease;
}
.pk-btn-primary:hover { background: var(--primary-hover); }
.pk-btn-primary:active { opacity: 0.65; }
.pk-btn-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 36px;
  padding: 0 14px;
  background: transparent;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  color: var(--text-secondary);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 400;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease, opacity 0.12s ease;
}
.pk-btn-ghost:hover { color: var(--text); border-color: var(--text-secondary); }
.pk-btn-ghost:active { opacity: 0.65; }
/* Section-header action chip — small uppercase mono pill outlined in umber. */
.pk-btn-chip {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--primary);
  padding: 6px 12px;
  border: 1px solid var(--primary);
  background: transparent;
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, opacity 0.12s ease;
}
.pk-btn-chip:hover { background: var(--primary-softer); }
.pk-btn-chip:active { opacity: 0.65; }
/* Floating action button (mobile). Position with the consumer's wrapper. */
.pk-fab {
  width: 56px;
  height: 56px;
  border: 0;
  border-radius: 50%;
  background: var(--primary);
  color: #ffffff;
  font-size: 28px;
  font-weight: 300;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.15s ease, opacity 0.12s ease;
  box-shadow:
    0 8px 24px rgba(196, 99, 60, 0.32),
    0 2px 4px rgba(40, 30, 20, 0.20);
}
.pk-fab:hover { background: var(--primary-hover); }
.pk-fab:active { opacity: 0.65; }
/* ─────────────────────────────────────────────────────────────
 * Inputs
 * ─────────────────────────────────────────────────────────────*/
.pk-input {
  height: 32px;
  padding: 0 10px;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--bg);
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text);
  outline: none;
  transition: border-color 0.15s ease;
}
.pk-input:focus { border-color: var(--primary); }
/* Numeric variant — mono, right-aligned. */
.pk-input-num {
  font-family: var(--font-mono);
  text-align: right;
}
/* ─────────────────────────────────────────────────────────────
 * Tap feedback (global active opacity for press-state)
 * ─────────────────────────────────────────────────────────────*/
.pk-tap {
  transition: opacity 0.12s ease;
  cursor: pointer;
}
.pk-tap:active { opacity: 0.65; }
/* ─────────────────────────────────────────────────────────────
 * Section layout helper
 * ─────────────────────────────────────────────────────────────*/
.pk-section {
  padding: 0 20px;
  margin-top: 28px;
}
.pk-section-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 14px;
}
/* ─────────────────────────────────────────────────────────────
 * Avatar circle (umber bg, white serif initial)
 * ─────────────────────────────────────────────────────────────*/
.pk-avatar {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--primary);
  color: #ffffff;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
/*
 * Shared utility classes + base form-control styling (tracker design system).
 * Imported after themes.css so component-scoped styles can still override
 * via Vue's scoped-selector specificity boost.
 *
 * Every rule is scoped under `.trk` — the root class carried by migrated
 * tracker screens/overlays — so tracker's element-level and generic-class
 * styling can't leak into lab surfaces (see
 * docs/shared/2026-07-21-tracker-lab-css-deconfliction.md).
 *
 * Goal: one place to edit button / input / field / focus-ring treatment
 * so Dashboard, Log, Settings, etc. can't drift apart. Components should
 * use these classes (or the token set in themes.css) rather than
 * redefining their own button / input rules.
 */
/* ---- Base form controls ------------------------------------------- *
 * Rules that apply even when a component forgets to add a class.
 * Intentionally omits height / padding — per-case sizing stays with the
 * component so scoped overrides don't fight a global size.
 */
.trk input[type="text"],
.trk input[type="number"],
.trk input[type="email"],
.trk input[type="password"],
.trk input[type="search"],
.trk input[type="time"],
.trk input[type="date"],
.trk input[type="url"],
.trk input[type="tel"],
.trk textarea,
.trk select {
  font-family: inherit;
  color: var(--text);
  background: var(--bg);
  /* --border resolves to transparent in the current theme; on parchment
     that produces invisible inputs. Use the explicit hairline. */
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-small);
  transition:
    border-color var(--transition-base),
    box-shadow var(--transition-base);
}
/* ---- Focus ring --------------------------------------------------- *
 * Single rule for every text-entry control. Buttons use focus-visible
 * so mouse clicks don't show a lingering ring.
 */
.trk input[type="text"]:focus,
.trk input[type="number"]:focus,
.trk input[type="email"]:focus,
.trk input[type="password"]:focus,
.trk input[type="search"]:focus,
.trk input[type="time"]:focus,
.trk input[type="date"]:focus,
.trk input[type="url"]:focus,
.trk input[type="tel"]:focus,
.trk textarea:focus,
.trk select:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-focus);
}
/* Button base — inherit font, nothing else. Pill shape is opt-in via
 * the .btn-* / .pk-pill classes below; <button> on its own has no
 * radius so chevrons, row taps, day cells etc. don't get a 999px
 * default they then have to override. */
.trk button {
  font-family: inherit;
}
.trk button:focus-visible {
  outline: 2px solid var(--primary-ring);
  outline-offset: 2px;
}
/* ---- Buttons ------------------------------------------------------ *
 * .btn-primary / .btn-secondary / .btn-text. Apply .sm for a compact
 * variant used in dense toolbars. Sentence-case + normal tracking — the
 * uppercase-tracked treatment is reserved for mono micro-labels.
 */
.trk .btn-primary,
.trk .btn-secondary,
.trk .btn-text {
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  padding: 0 16px;
  height: 36px;
  border-radius: 999px;
  cursor: pointer;
  transition:
    background var(--transition-base),
    color var(--transition-base),
    border-color var(--transition-base),
    opacity 0.12s ease;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  white-space: nowrap;
}
.trk .btn-primary:active:not(:disabled),
.trk .btn-secondary:active:not(:disabled),
.trk .btn-text:active:not(:disabled) { opacity: 0.65; }
.trk .btn-primary {
  background: var(--primary);
  color: var(--text-on-primary);
  border: 1px solid var(--primary);
}
.trk .btn-primary:hover:not(:disabled) {
  background: var(--primary-hover);
  border-color: var(--primary-hover);
}
.trk .btn-secondary {
  background: transparent;
  color: var(--text-secondary);
  border: 1px solid var(--border-strong);
}
.trk .btn-secondary:hover:not(:disabled) {
  border-color: var(--text-secondary);
  color: var(--text);
}
.trk .btn-text {
  background: transparent;
  color: var(--text-secondary);
  border: 1px solid transparent;
  font-weight: 400;
  padding: 0 var(--space-2);
}
.trk .btn-text:hover:not(:disabled) {
  color: var(--text);
}
.trk .btn-primary:disabled,
.trk .btn-secondary:disabled,
.trk .btn-text:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
.trk .btn-primary.sm,
.trk .btn-secondary.sm,
.trk .btn-text.sm {
  height: var(--control-height-sm);
  font-size: var(--font-size-xs);
  padding: 0 var(--space-3);
}
/* ---- List-extender buttons --------------------------------------- *
 * .btn-add        — sparse list "tray opener" (e.g. + Add exercise).
 *                   Full-width, dashed border, sentence-case, muted.
 *                   Low frequency: signals "this list is rarely added to."
 * .btn-add-icon   — frequent inline add (e.g. meal + buttons).
 *                   Small filled square. Higher visual weight because the
 *                   user reaches for it many times per session.
 */
.trk .btn-add {
  width: 100%;
  padding: 12px;
  background: transparent;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-medium);
  color: var(--text-secondary);
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  transition:
    color var(--transition-base),
    border-color var(--transition-base),
    background var(--transition-base);
}
.trk .btn-add:hover:not(:disabled) {
  color: var(--primary);
  border-color: var(--primary);
  background: var(--primary-softer);
}
.trk .btn-add:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
.trk .btn-add-icon {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-small);
  background: var(--primary);
  color: var(--text-on-primary);
  border: none;
  font-size: var(--font-size-l);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background var(--transition-base);
}
.trk .btn-add-icon:hover:not(:disabled) { background: var(--primary-hover); }
.trk .btn-add-icon:disabled { opacity: 0.55; cursor: not-allowed; }
/* ---- Eyebrow label ------------------------------------------------ *
 * Small uppercase caption with a leading dash. Use for grouping labels
 * above section headings. The brand voice for this is mono — NOT display
 * serif. Serif eyebrow would compete with the title below.
 */
.trk .eyebrow {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 400;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
}
.trk .eyebrow::before {
  content: "";
  width: 20px;
  height: 1px;
  background: currentColor;
  opacity: 0.4;
}
/* ---- Field pattern ----------------------------------------------- *
 * Wraps a label + single control. Use consistently on Settings forms
 * so spacing, label color, and hint text match across pages.
 */
.trk .field {
  margin-bottom: var(--space-3);
}
.trk .field > label {
  display: block;
  margin-bottom: var(--space-1);
  font-size: var(--font-size-s);
  font-weight: var(--font-weight-medium);
  color: var(--text-secondary);
}
.trk .field-hint {
  margin: var(--space-1) 0 0;
  font-size: var(--font-size-xs);
  color: var(--text-secondary);
}
/* ---- Status text ------------------------------------------------ */
.trk .error {
  color: var(--danger);
  font-size: var(--font-size-s);
  margin: 0;
}
.trk .success {
  color: var(--success);
  font-size: var(--font-size-s);
  margin: 0;
}
/* Mobile-only page-title hide. The rest of the v1 "tile flush" rule was
 * removed during the parchment rebrand — the design language now uses
 * 14/18px radii and explicit section gutters on every viewport. */
@media (max-width: 768px) {
  /* Page titles ("Daily Log", "Dashboard", "Settings") are redundant on
     mobile where the bottom nav already labels the current page. */
  .trk .page-title {
    display: none !important;
  }
}
/* ---- Auth pages -------------------------------------------------- *
 * Login / register / forgot-password / reset / start all share the
 * same .auth-page > .auth-card shell.
 *
 * Brand split: display serif (Fraunces) is for the h1 only. Labels,
 * buttons, links, and inputs use body sans (Inter) — applying serif
 * everywhere on auth was a terminal-aesthetic affordance that doesn't
 * fit the Clinic·Warm voice.
 */
.trk .auth-card h1 {
  font-family: var(--font-display);
  font-weight: 380;
  letter-spacing: -0.018em;
  font-feature-settings: "ss01";
}
.trk .auth-card,
.trk .auth-card label,
.trk .auth-card button,
.trk .auth-card a,
.trk .auth-card .switch,
.trk .auth-card .divider,
.trk .auth-card .subtitle,
.trk .auth-card .hint,
.trk .auth-card .error,
.trk .auth-card input,
.trk .auth-card textarea,
.trk .auth-card select {
  font-family: var(--font-body);
}
/* Cross-page width invariant. !important beats each page's scoped
   .auth-card max-width (380px) since scoped attribute selectors
   out-specify a plain class selector. */
.trk .auth-card {
  max-width: 440px !important;
}
/* The submit button on auth pages — beef it up: real vertical padding,
   weight-500, full-width hero feel. */
.trk .auth-card .btn-primary[type="submit"] {
  padding: 12px 16px !important;
  height: auto !important;
  font-weight: 500 !important;
}
.trk .auth-brand-link {
  display: flex;
  justify-content: center;
  text-decoration: none;
  color: inherit;
}
/*
 * Tracker base element styling — the global rules that used to live at the
 * top level of tracker's style.css, scoped under `.trk` for the tracker→lab
 * merge (docs/shared/2026-07-21-tracker-lab-css-deconfliction.md).
 *
 * `.trk` is the root class carried by every migrated tracker screen/overlay.
 * The former `body { … }` rule becomes the `.trk` root rule (typographic
 * defaults + parchment background); element rules (`h1–h6`, `a`, form
 * controls, the mono-font class list) are prefixed so they can't restyle
 * lab surfaces.
 *
 * Deliberately NOT ported from tracker's style.css:
 *   - `.v-popper--theme-tooltip` / `.v-popper--theme-dropdown` overrides —
 *     lab's floating-vue skin (assets/css/main.css) is canonical; tooltips
 *     portal to <body> so scoping can't isolate two skins.
 *   - `#app { min-height: 100vh }` — lab's App.vue owns viewport sizing.
 */
.trk *,
.trk *::before,
.trk *::after {
  box-sizing: border-box;
}
/* Former `body` rule. `margin: 0` dropped (body-specific — lab's main.css
   already resets it). `user-select: text` added: lab's body sets
   user-select:none globally; tracker content stays selectable. */
.trk {
  font-family: var(--font-body);
  font-size: var(--font-size-m);
  /* Inter at 400 reads thin against the dark surfaces; 500 is the app's
     base text weight. Headings (Fraunces 380) and mono data cells set
     their own weights and are unaffected. */
  font-weight: 500;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  user-select: text;
  -webkit-user-select: text;
}
.trk h1, .trk h2, .trk h3, .trk h4, .trk h5, .trk h6 {
  margin: 0 0 0.5rem;
  font-family: var(--font-display);
  /* Fraunces brand-canonical weight 380 (variable axis). Heavier weights
     fight the soft serif character. Tracking + ss01 per the design doc. */
  font-weight: 380;
  font-feature-settings: "ss01";
  line-height: 1.18;
  letter-spacing: -0.018em;
}
.trk p {
  margin: 0;
}
/* The UA stylesheet gives form controls their own font-weight (400),
   line-height, letter-spacing, and color (buttontext) — so bare
   <button> rows silently drop the body's font-weight and theme color.
   `font: inherit` pulls the whole font shorthand (family, size, weight,
   line-height); components that declare their own still win. */
.trk input, .trk select, .trk button, .trk textarea {
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
}
.trk a {
  color: var(--primary);
  text-decoration: none;
}
/* ---- Monospace for numeric display & inputs -------------------------- */
/* Number inputs */
.trk input[type='number'] {
  font-family: var(--font-mono);
}
/* Stat cards / metric readouts */
.trk .stat-value,
.trk .logged-value,
.trk .macro-values,
.trk .total-cal {
  font-family: var(--font-mono);
}
/* Allocation (Settings) */
.trk .alloc-input,
.trk .alloc-computed,
.trk .alloc-detail,
.trk .alloc-unit {
  font-family: var(--font-mono);
}
/* Weekly budget strip */
.trk .wb-value,
.trk .wb-day-value,
.trk .wb-adj-values,
.trk .wb-adj-values > * {
  font-family: var(--font-mono);
}
/* Log-page food tables — numeric columns only */
.trk .meal-table td.col-num,
.trk .meal-table th.col-num,
.trk .meal-table td.col-srv,
.trk .meal-table th.col-srv,
.trk .meal-table tfoot td.col-num,
.trk .items-table td.col-num,
.trk .items-table th.col-num,
.trk .items-table td.col-srv,
.trk .items-table th.col-srv,
.trk .items-table td.col-srv input {
  font-family: var(--font-mono);
}
/* Dashboard log-history table — numeric columns only */
.trk .log-table td.lt-num,
.trk .log-table th.lt-num {
  font-family: var(--font-mono);
}
/* Inline numeric bits */
.trk .servings,
.trk .edit-input,
.trk .dot,
.trk .count,
.trk .day-cell,
.trk .month-label {
  font-family: var(--font-mono);
}
/* Score pill digits */
.trk .score-pill {
  font-family: var(--font-mono);
}
