/* Header */
.app-header {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-lg) var(--space-main) var(--space-md);
}

.header__back {
  width: 44px;
  height: 44px;
  border-radius: var(--radius-full);
  border: none;
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text);
  transition: background-color var(--duration-fast) var(--easing-standard);
}

.header__back:hover {
  background: var(--color-secondary-container);
}

.header__titles {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.header__title {
  font-size: var(--font-size-headline-lg-mobile);
  line-height: var(--line-height-headline-lg-mobile);
  font-weight: var(--font-weight-headline-lg);
  color: var(--color-primary);
}

.header__subtitle {
  font-size: var(--font-size-body-md);
  line-height: var(--line-height-body-md);
  color: var(--color-text-variant);
}

/* Bottom navigation */
.bottom-nav {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  display: flex;
  justify-content: space-around;
  align-items: center;
  padding: var(--space-md) var(--space-main) var(--space-lg);
  background: var(--color-bg-alt);
  z-index: 50;
}

.bottom-nav__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-width: 44px;
  min-height: 44px;
  padding: var(--space-sm);
  color: var(--color-text-variant);
  opacity: 0.4;
  transition: opacity var(--duration-base) var(--easing-standard), transform var(--duration-base) var(--easing-standard);
}

.bottom-nav__item:hover,
.bottom-nav__item--active {
  opacity: 1;
}

.bottom-nav__item--active {
  color: var(--color-primary);
  transform: scale(1.1);
}

.bottom-nav__item--active::after {
  content: '';
  width: 4px;
  height: 4px;
  border-radius: var(--radius-full);
  background: var(--color-secondary);
}

.bottom-nav__label {
  font-size: var(--font-size-caption);
  line-height: var(--line-height-caption);
}

/* Build marker (see APP_VERSION/BUILD_TIME in config.js) — lives in the nav
   bar specifically because `.bottom-nav` is `position: fixed`, so this stays
   on screen regardless of scroll position, unlike its previous home-only
   spot (which Home's own CTA-visibility safety net routinely scrolled out of
   view — found 2026-07-26, see CHANGELOG). Centered under the tab row
   (moved from the top-right corner 2026-07-27 — read as a stray label up
   there, and "by AgeAi" reads more like a footer credit centered under
   everything). Direction-agnostic `left: 50%` + transform, no inset-inline
   needed since centering doesn't depend on RTL/LTR. */
.bottom-nav__version {
  position: absolute;
  bottom: 4px;
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  font-size: 9px;
  color: var(--color-text-variant);
  opacity: 0.4;
  pointer-events: none;
}

.bottom-nav__version-mark {
  vertical-align: -1.5px;
}

/* Buttons */
.btn {
  min-height: 44px;
  padding-inline: var(--space-lg);
  border-radius: var(--radius-full);
  border: none;
  font-size: var(--font-size-label-md);
  line-height: var(--line-height-label-md);
  font-weight: var(--font-weight-label-md);
  letter-spacing: 0.05em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  transition: transform var(--duration-fast) var(--easing-standard);
}

.btn:active:not(:disabled) {
  transform: scale(0.98);
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn--primary {
  background: var(--color-primary);
  color: var(--color-on-primary);
  height: 56px;
  width: 100%;
}

/* Hairline pill, not bare text. DESIGN_SYSTEM.md specified a plain text
   button whose only affordance was `hover → primary` — but this app ships to
   touch devices first, where hover does not exist, so on a real phone the
   secondary action read as a caption rather than a control (reported from a
   device 2026-07-29 about Home's "Show Another"). The outline is the same
   quiet-control language already used by .browse-search, .browse-sort and
   .segmented-control, so this adds no new visual vocabulary, and it stays
   clearly subordinate to the solid-filled 56px primary CTA above it. */
.btn--secondary {
  background: transparent;
  color: var(--color-text-variant);
  min-height: 44px;
  border: 1px solid var(--color-border);
}

.btn--secondary:hover:not(:disabled) {
  color: var(--color-primary);
  border-color: var(--color-primary);
}

/* Press fill — the touch-device counterpart to the hover state above. */
.btn--secondary:active:not(:disabled) {
  background: var(--color-bg-alt);
  color: var(--color-primary);
}

/* Second step of a tap-to-arm delete confirmation (Child Setup) — replaces
   window.confirm(), a raw unstyled OS dialog with no RTL/theme awareness
   that broke the app's own visual language for its one destructive action. */
.btn--danger {
  background: var(--color-error);
  color: var(--color-on-primary);
  min-height: 44px;
}

/* Card */
.card {
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--color-bg-alt);
  display: flex;
  flex-direction: column;
}

.card--interactive {
  border: none;
  padding: 0;
  text-align: start;
  width: 100%;
  transition: transform var(--duration-fast) var(--easing-standard);
}

/* Same tap language as .btn (DESIGN_SYSTEM.md: active:scale-[0.98], "a
   slight compress, not just a color change") — every other tappable card
   in the app (Home hero, Saved grid, Child Setup list) used this component
   and had zero press feedback beyond the browser default. */
.card--interactive:active {
  transform: scale(0.98);
}

.card--hero .card__image {
  /* Trimmed from 40vh, then again from 32vh/220 after a real 3-button-nav
     Android device still needed a small scroll on Home to reach the bottom
     nav (2026-07-27) — floor now 200px, still a real photo, not a thumbnail. */
  height: 28vh;
  min-height: 200px;
}

.card--hero .card__body {
  text-align: center;
  padding-top: var(--space-sm);
  padding-bottom: var(--space-sm);
}

.card__image {
  width: 100%;
  height: 180px;
  object-fit: cover;
}

.card__body {
  padding: var(--space-md);
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.card__title {
  font-size: var(--font-size-headline-lg-mobile);
  line-height: var(--line-height-headline-lg-mobile);
  color: var(--color-primary);
}

.card__subtitle {
  font-size: var(--font-size-body-lg);
  line-height: var(--line-height-body-lg);
  color: var(--color-text-variant);
}

/* Badge — min-height meets the 44px touch target from DESIGN_SYSTEM.md for
   interactive chips (Profile, Child Setup); display-only badges (tags on
   Lunchbox Details) get the same size for visual consistency across screens. */
.badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0 var(--space-md);
  border-radius: var(--radius-full);
  font-size: var(--font-size-label-md);
  line-height: var(--line-height-label-md);
  transition: transform var(--duration-fast) var(--easing-standard);
}

/* Same tap language as .btn — the age/preference chips in Child Setup are
   real buttons (see Badge.js: <button> whenever onClick is passed) and had
   no press feedback beyond the instant class swap on click. Harmless no-op
   on the display-only <span> variant (tags on Lunchbox Details), which
   isn't focusable/activatable. */
.badge:active {
  transform: scale(0.98);
}

.badge--neutral {
  background: var(--color-secondary-container);
  color: var(--color-secondary);
}

.badge--selected {
  background: var(--color-primary);
  color: var(--color-on-primary);
}

.badge--error {
  background: var(--color-error);
  color: var(--color-on-primary);
}

/* Text field (DESIGN_SYSTEM.md "Поля ввода": 44px min height, radius token, error state) */
.field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.field__label {
  font-size: var(--font-size-caption);
  color: var(--color-text-variant);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.field__input {
  min-height: 44px;
  padding-inline: var(--space-md);
  border-radius: var(--radius);
  border: 1px solid var(--color-border);
  background: var(--color-bg-alt);
  font-family: var(--font-family);
  font-size: var(--font-size-body-md);
  color: var(--color-text);
}

.field__input:focus {
  outline: none;
  border-color: var(--color-primary);
}

.field__input--error {
  border-color: var(--color-error);
}

.field__error {
  font-size: var(--font-size-caption);
  color: var(--color-error);
}

/* Recipe meta (time · ingredient count) */
.recipe-meta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  color: var(--color-text-variant);
  font-size: var(--font-size-body-md);
  line-height: var(--line-height-body-md);
}

.recipe-meta--start {
  justify-content: flex-start;
}

.recipe-meta__item {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.recipe-meta__dot {
  width: 3px;
  height: 3px;
  border-radius: var(--radius-full);
  background: var(--color-border);
}

/* Ingredient item */
.ingredient-item {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  font-size: var(--font-size-body-lg);
  line-height: var(--line-height-body-lg);
  color: var(--color-text-variant);
}

.ingredient-item__dot {
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  background: var(--color-secondary);
  flex-shrink: 0;
}

.ingredient-item__icon {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
}

/* Empty state — fills the remaining page height and centers vertically,
   so it reads as an intentional calm moment rather than orphaned text
   stuck under the header. */
.empty-state {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-md);
  padding: var(--space-xl) var(--space-main);
  text-align: center;
}

.empty-state__title {
  color: var(--color-primary);
  font-size: var(--font-size-headline-md);
  line-height: var(--line-height-headline-md);
  font-weight: var(--font-weight-headline-md);
}

.empty-state__message {
  color: var(--color-text-variant);
  font-size: var(--font-size-body-lg);
  line-height: var(--line-height-body-lg);
}

/* Caption-sized and dimmed — reads as a quiet aside under the action, never
   as a second message competing with .empty-state__message above it. */
.empty-state__footnote {
  color: var(--color-text-variant);
  font-size: var(--font-size-caption);
  line-height: var(--line-height-caption);
  opacity: 0.75;
}

/* Loading state */
.loading-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-xl) var(--space-main);
}

.loading-state__spinner {
  width: 24px;
  height: 24px;
  border-radius: var(--radius-full);
  border: 2px solid var(--color-secondary-container);
  border-top-color: var(--color-primary);
  animation: spin var(--duration-slow) linear infinite;
}

.loading-state__message {
  color: var(--color-text-variant);
  font-size: var(--font-size-body-md);
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.icon {
  flex-shrink: 0;
}
