/* Value Introduction — the single first-launch screen. Centered corridor
   layout, one hero image, one headline, one CTA; mirrors .empty-state's
   "calm centered moment" pattern rather than inventing a new one. */
.page--onboarding-intro .page__content {
  padding-bottom: var(--space-main);
}

.onboarding-intro {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-lg);
  padding-top: var(--space-xl);
  text-align: center;
}

.onboarding-intro__hero {
  width: 100%;
  height: 32vh;
  min-height: 180px;
  border-radius: var(--radius-lg);
  background: var(--color-secondary-container);
  overflow: hidden;
}

.onboarding-intro__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.onboarding-intro__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.onboarding-intro__headline {
  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);
}

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

/* Quiet LunchMate brand signature above the headline. Deliberately not a
   header/nav bar — a small muted wordmark + top-view lunchbox glyph that
   gives brand recognition without competing with the "Today's Lunch"
   headline below it. Pinned to the physical top-left corner as a masthead
   (direction: ltr) in ALL locales: "LunchMate" is a Latin wordmark that
   reads left-to-right, so in the RTL (Hebrew) default it sits in the
   otherwise-empty left corner while the Hebrew headline holds the right —
   and glyph-before-word is the natural icon+wordmark lockup. In LTR this is
   unchanged (it was already left). Inline padding matches .app-header. */
.home-brand {
  display: flex;
  direction: ltr;
  align-items: center;
  gap: 7px;
  padding: var(--space-md) var(--space-main) 0;
  color: var(--color-text-variant);
}

/* Ambient background emblem — a large corner of the brand glyph, mostly
   bled off-screen via negative inset and cropped by `overflow: hidden`, sat
   behind everything via negative z-index. `.page--home` gets its own
   background + a positioned/z-indexed box so this stacks correctly (a
   negative z-index child would otherwise paint behind <body>'s own
   background and vanish). Gray, not the brand accent — this is background
   texture, not a UI signal. */
.page--home {
  position: relative;
  z-index: 0;
  background: var(--color-bg);
  overflow: hidden;
}

.home-watermark {
  position: absolute;
  z-index: -1;
  /* Physical left, not inline-start — pinned to the same physical corner as
     the LunchMate wordmark (.home-brand also hardcodes physical left in all
     locales), so the watermark and the logo read as one masthead group. */
  left: -110px;
  top: -100px;
  color: var(--color-border);
  opacity: 0.4;
  pointer-events: none;
}

.home-brand__glyph {
  flex-shrink: 0;
  /* Glyph line work reads a touch lighter than the wordmark so the mark
     stays quiet; the clay morsel inside keeps its full accent value. */
  opacity: 0.85;
}

.home-brand__word {
  font-size: var(--font-size-caption);
  line-height: 1;
  font-weight: 600;
  letter-spacing: 0.02em;
}

/* Header on Home specifically runs tighter than other screens — reclaims
   vertical space so "Pack This Lunch" lands in the first viewport. The brand
   line above now supplies the top breathing room, so the header's own top
   padding shrinks to keep the added height minimal. Other screens keep the
   default .app-header padding untouched. */
.page--home .app-header {
  padding-top: var(--space-sm);
  padding-bottom: var(--space-sm);
}

.home-suggestion {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.home-suggestion__hero {
  position: relative;
  width: 100%;
}

/* "New since your last visit" nudge (src/utils/whatsNew.js) — fixed above
   the bottom nav (same 120px clearance as NAV_CLEARANCE_PX in home.js),
   tap opens Browse, auto-dismisses after 5s either way. Solid secondary
   fill (not the quiet secondary-container pill) so it reads as a transient
   notice, distinct from the always-there streak badge. */
.whats-new-toast {
  position: fixed;
  left: 50%;
  bottom: 120px;
  transform: translateX(-50%);
  max-width: calc(100% - var(--space-lg) * 2);
  padding: var(--space-sm) var(--space-lg);
  border-radius: var(--radius-full);
  background: var(--color-secondary);
  color: var(--color-on-primary);
  font-size: var(--font-size-label-md);
  font-weight: 500;
  text-align: center;
  box-shadow: var(--shadow-md);
  z-index: 60;
  cursor: pointer;
  animation: whats-new-in var(--duration-slow) var(--easing-standard);
}

.whats-new-toast--out {
  animation: whats-new-out 200ms var(--easing-standard) forwards;
}

@keyframes whats-new-in {
  from { opacity: 0; transform: translateX(-50%) translateY(8px); }
  to { opacity: 1; transform: translateX(-50%) translateY(0); }
}

@keyframes whats-new-out {
  to { opacity: 0; transform: translateX(-50%) translateY(8px); }
}

@media (prefers-reduced-motion: reduce) {
  .whats-new-toast,
  .whats-new-toast--out {
    animation: none;
  }
}

/* Streak reinforcement pill (see src/utils/streak.js) — same pill language
   as the decision banner (secondary-container), so it reads as part of the
   existing system, not a new visual element bolted on. */
.home-streak {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px var(--space-md);
  border-radius: var(--radius-full);
  background: var(--color-secondary-container);
  color: var(--color-secondary);
  font-size: var(--font-size-label-md);
  font-weight: 500;
}

/* Save toggle — same bookmark metaphor as the Saved tab, floated over the
   hero so it stays out of the primary CTA's way. Logical inset so it sits
   correctly in both RTL and LTR without a mirrored override. */
.save-toggle {
  position: absolute;
  top: var(--space-md);
  inset-inline-end: var(--space-md);
  width: 44px;
  height: 44px;
  border-radius: var(--radius-full);
  border: none;
  background: rgba(255, 255, 255, 0.9);
  color: var(--color-text);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-md);
  transition: transform var(--duration-fast) var(--easing-standard);
}

.save-toggle:active {
  transform: scale(0.94);
}

.save-toggle--active {
  color: var(--color-primary);
}

.home-suggestion__description {
  font-size: var(--font-size-body-lg);
  line-height: var(--line-height-body-lg);
  color: var(--color-text-variant);
  text-align: center;
}

/* Actions: full-width stacked primary/secondary CTAs. Used for both the
   initial Pack/Show-Another pair and the post-decision Choose-another — the
   scroll-margin keeps whichever is showing clear of the fixed bottom nav
   when JS scrolls it into view for unusually tall content (e.g. longer
   localized strings wrapping onto an extra line). */
.home-suggestion__actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
  width: 100%;
  /* Matches NAV_CLEARANCE_PX in src/pages/home.js — bottom nav renders at
     112px tall (44px touch target + label + padding); small buffer added. */
  scroll-margin-bottom: 120px;
}

/* Only the primary CTA claims the full width. The secondary hugs its label
   so that, now that it carries a visible outline, it stays the lighter of
   the two instead of reading as a second full-width button competing with
   the decision. */
.home-suggestion__actions .btn--primary {
  width: 100%;
}

/* Fresh-reveal entrance — plays on first load and every "Show/Choose
   another" swap (a new element is mounted each time). Direction-agnostic
   (vertical only) so it reads correctly in both RTL and LTR. */
.home-suggestion--enter {
  animation: suggestion-in var(--duration-base) var(--easing-standard);
}

.home-suggestion--enter .card--hero .card__image {
  animation: hero-reveal var(--duration-slow) var(--easing-standard);
}

@keyframes suggestion-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes hero-reveal {
  from { opacity: 0; transform: scale(1.04); }
  to { opacity: 1; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .home-suggestion--enter,
  .home-suggestion--enter .card--hero .card__image {
    animation: none;
  }
}

.home-suggestion__decided {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  width: 100%;
}

/* The signature moment: "Pack This Today" resolves into this confirmation
   in place — same spot the parent just tapped, no scroll required to see
   it. Lightweight inline card, no modal; persists across refresh/return on
   the same day. */
.decision-banner {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  width: 100%;
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius);
  background: var(--color-secondary-container);
  animation: decision-banner-in var(--duration-slow) var(--easing-standard);
}

.decision-banner__check {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-size: 16px;
  font-weight: 700;
  animation: decision-check-pop var(--duration-slow) var(--easing-standard) 80ms both;
}

.decision-banner__text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  text-align: start;
}

.decision-banner__title {
  font-size: var(--font-size-body-lg);
  line-height: var(--line-height-body-lg);
  font-weight: var(--font-weight-label-md);
  color: var(--color-secondary);
}

.decision-banner__subtitle {
  font-size: var(--font-size-label-md);
  line-height: var(--line-height-label-md);
  color: var(--color-text-variant);
}

@keyframes decision-banner-in {
  from { opacity: 0; transform: translateY(-6px) scale(0.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes decision-check-pop {
  from { opacity: 0; transform: scale(0.5); }
  to { opacity: 1; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .decision-banner,
  .decision-banner__check {
    animation: none;
  }
}

/* Browse — the full catalog as a scannable list: small thumbnail + name,
   not the large hero cards used on Home/Saved, so many ideas fit on screen
   at once. */
.page--browse .page__content {
  padding-bottom: 112px; /* clears fixed bottom nav (112px), same as Home/Saved/Profile */
}

.browse {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.browse-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
}

/* Small muted count pill — not the standard tappable `.badge` (44px touch
   target, meant for interactive chips), this is display-only so it stays
   genuinely small. */
.browse-count {
  padding: 2px var(--space-sm);
  border-radius: var(--radius-full);
  background: var(--color-secondary-container);
  color: var(--color-secondary);
  font-size: var(--font-size-caption);
  line-height: var(--line-height-caption);
}

/* Plain native <select> — the "simple sort" step before real filters. Kept
   small and unstyled-looking (no custom dropdown chrome) on purpose; only 3
   options doesn't earn a bespoke component yet. */
.browse-sort {
  /* 44px, not 36 — the project's own touch-target floor (CLAUDE.md), which
     this fell short of. */
  min-height: 44px;
  padding: 2px var(--space-md) 2px var(--space-sm);
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border);
  background: var(--color-bg-alt);
  color: var(--color-text-variant);
  font-family: var(--font-family);
  font-size: var(--font-size-caption);
}

/* Sticky so the field stays reachable while scrolling the 30+ item list
   below it — without this, scrolling down hides the only way to change or
   clear the search, and getting back to it means scrolling all the way up. */
.browse-search-bar {
  position: sticky;
  top: 0;
  z-index: 5;
  margin-inline: calc(-1 * var(--space-main));
  padding: var(--space-sm) var(--space-main);
  background: var(--color-bg);
  /* DESIGN_SYSTEM.md's shadow-sm is meant for exactly this — an element
     elevated over the content scrolling beneath it. Without it, the sticky
     bar had no visual separation from the list once scrolled: same
     background, no edge, just an abrupt stop. */
  box-shadow: var(--shadow-sm);
}

.browse-search {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  min-height: 44px;
  padding-inline: var(--space-md);
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border);
  background: var(--color-bg-alt);
  color: var(--color-text-variant);
  transition: border-color var(--duration-fast) var(--easing-standard), box-shadow var(--duration-fast) var(--easing-standard);
}

/* The input's own outline is suppressed below (inconsistent native ring
   across browsers) — without this, focusing the field left no visible
   focus indicator at all, a real gap for keyboard/switch-control use. */
.browse-search:focus-within {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 2px var(--color-secondary-container);
}

.browse-search__input {
  flex: 1;
  min-height: 44px;
  min-width: 0;
  border: none;
  background: transparent;
  font-family: var(--font-family);
  font-size: var(--font-size-body-md);
  color: var(--color-text);
}

.browse-search__input:focus {
  outline: none;
}

/* Hidden in favor of `.browse-search__clear` below — the native button's
   look is inconsistent across browsers and doesn't take `currentColor`. */
.browse-search__input::-webkit-search-cancel-button {
  -webkit-appearance: none;
}

/* Shown only once there's a query (`.browse-search__clear--visible`, toggled
   in browse.js) — otherwise it'd sit idle next to an empty field. 44px hit
   target per the project's touch-size rule, even though the visible icon is
   small. */
.browse-search__clear {
  display: none;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-inline-end: calc(-1 * var(--space-sm));
  border: none;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--color-text-variant);
}

.browse-search__clear--visible {
  display: flex;
}

.browse-search__clear:active {
  background: var(--color-secondary-container);
}

.browse-list__rows {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.browse-list__item {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  width: 100%;
  padding: var(--space-sm);
  border: none;
  border-radius: var(--radius);
  background: transparent;
  text-align: start;
  transition: background-color var(--duration-fast) var(--easing-standard), transform var(--duration-fast) var(--easing-standard);
}

/* :not(skeleton) — the loading placeholders reuse this class for shape, but
   they are inert <li>, not buttons. Without the guard they highlighted on
   hover and compressed on press like a real row, advertising a tap that
   does nothing. */
.browse-list__item:not(.browse-list__item--skeleton):hover {
  background: var(--color-bg-alt);
}

/* Same tap feedback language as the primary CTA (DESIGN_SYSTEM.md:
   active:scale-[0.98], "a slight compress, not just a color change") — the
   list rows only had the background flash, so they read as less responsive
   than every other tappable surface in the app. */
.browse-list__item:not(.browse-list__item--skeleton):active {
  background: var(--color-bg-alt);
  transform: scale(0.98);
}

/* Loading skeleton — same row shape as a real item, so the list doesn't
   visibly jump once data arrives, but inert (aria-hidden, no hover/active
   state) and quietly pulsing rather than a spinner unrelated to this
   screen's actual content shape. */
.browse-list__item--skeleton {
  background: transparent;
}

.browse-list__skeleton-line {
  width: 65%;
  height: 18px;
  border-radius: var(--radius-full);
  background: var(--color-secondary-container);
}

.browse-list__item--skeleton .browse-list__thumb,
.browse-list__skeleton-line {
  animation: skeleton-pulse 1.4s ease-in-out infinite;
}

.browse-list__item--skeleton:nth-child(2n) .browse-list__thumb,
.browse-list__item--skeleton:nth-child(2n) .browse-list__skeleton-line {
  animation-delay: 0.15s;
}

@keyframes skeleton-pulse {
  0%, 100% { opacity: 0.6; }
  50% { opacity: 0.3; }
}

@media (prefers-reduced-motion: reduce) {
  .browse-list__item--skeleton .browse-list__thumb,
  .browse-list__skeleton-line {
    animation: none;
    opacity: 0.45;
  }
}

.browse-list__thumb {
  flex-shrink: 0;
  width: 52px;
  height: 52px;
  border-radius: var(--radius);
  object-fit: cover;
  background: var(--color-secondary-container);
}

.browse-list__title {
  flex: 1;
  min-width: 0;
  /* 2-line clamp, not single-line ellipsis — Russian titles in particular
     ran well past one line's worth of characters and lost real words
     ("Сэндвич с творожным сыро…"), on a screen whose whole point is
     scanning by name. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  /* Progressive enhancement — balances the line break so the second line
     isn't a single orphaned word. Unsupported browsers just ignore it and
     keep the default break, no fallback needed. */
  text-wrap: pretty;
  font-size: var(--font-size-body-lg);
  line-height: var(--line-height-body-lg);
  color: var(--color-text);
}

/* "New" cue for ideas added in the last BROWSE_NEW_BADGE_DAYS (config.js) —
   shorter window than Home's badge (NEW_IDEA_WINDOW_DAYS) since this screen
   shows the whole catalog at once, where a 14-day window would tag too much
   of it. Same quiet chip treatment as .browse-count. */
.browse-list__new-badge {
  flex-shrink: 0;
  padding: 2px var(--space-sm);
  border-radius: var(--radius-full);
  background: var(--color-secondary-container);
  color: var(--color-secondary);
  font-size: var(--font-size-caption);
  line-height: var(--line-height-caption);
}

.browse-category-filter {
  /* Negative-margin-and-repad trick (same as .browse-search-bar above) so the
     row's edge fade (below) can bleed into the screen's own side padding
     instead of leaving a hard-edged gap before it. */
  margin-inline: calc(-1 * var(--space-main));
  padding-inline: var(--space-main);
  /* Edge fade — hints there's more to scroll without a visible arrow or
     "swipe" label (Section 9.F: no scroll cues as decoration; this is a
     functional affordance on the scrollable element itself, not add-on
     copy). Symmetric on both sides so it needs no RTL/LTR branching. */
  mask-image: linear-gradient(to right, transparent, black 20px, black calc(100% - 20px), transparent);
  -webkit-mask-image: linear-gradient(to right, transparent, black 20px, black calc(100% - 20px), transparent);
}

.browse-category-chips {
  display: flex;
  gap: var(--space-sm);
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scroll-behavior: smooth;
  /* Settle on a chip rather than stopping mid-scroll — same tactile intent
     as the rest of the app's `scale(0.98)` press feedback, applied to the
     row itself. `proximity`, not `mandatory`: a fast flick can still coast
     past a chip instead of fighting the user's momentum. */
  scroll-snap-type: x proximity;
  /* Scrollbar hidden — this list is short and horizontal (7 chips), a
     always-visible scrollbar reads as a stray UI line under a row that's
     already legible as scrollable from the trailing edge fade below.
     Content stays reachable via touch/swipe/keyboard; nothing is hidden
     from assistive tech, only the track's own paint. */
  scrollbar-width: none;
}

.browse-category-chips::-webkit-scrollbar {
  display: none;
}

.browse-category-chip {
  flex-shrink: 0;
  scroll-snap-align: start;
  display: flex;
  align-items: baseline;
  gap: 5px;
  padding: 8px 12px;
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border);
  background: var(--color-bg-alt);
  color: var(--color-text-variant);
  font-family: var(--font-family);
  font-size: var(--font-size-caption);
  white-space: nowrap;
  transition: border-color var(--duration-fast) var(--easing-standard), background-color var(--duration-fast) var(--easing-standard), color var(--duration-fast) var(--easing-standard), box-shadow var(--duration-fast) var(--easing-standard);
}

.browse-category-chip:active {
  transform: scale(0.98);
}

.browse-category-chip__count {
  opacity: 0.6;
  font-size: 11px;
}

.browse-category-chip--active {
  border-color: var(--color-primary);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-weight: var(--font-weight-label-md);
  /* Tinted shadow (never pure-black, matches --shadow-sm's own rgba base) —
     state reads through a touch of elevation, not color alone, same
     materiality principle as the rest of the app's active/selected chrome. */
  box-shadow: var(--shadow-sm);
}

.browse-category-chip--active .browse-category-chip__count {
  opacity: 0.75;
}

/* Single column of large cards, matching the approved Stitch Saved screen
   (docs/design/screens/05-saved.png) rather than a compact grid. */
.saved-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

.saved-card {
  position: relative;
}

.saved-list .card__image {
  height: 280px;
}

/* Delete affordance on Saved — a distinct trash icon rather than the
   bookmark metaphor, since these are already-saved items: tapping removes
   them from the list instead of toggling save state. Same floated-pill
   treatment as .save-toggle on Home for visual consistency. */
.saved-card__delete {
  position: absolute;
  top: var(--space-md);
  inset-inline-end: var(--space-md);
  width: 44px;
  height: 44px;
  border-radius: var(--radius-full);
  border: none;
  background: rgba(255, 255, 255, 0.9);
  color: var(--color-text);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-md);
  transition: transform var(--duration-fast) var(--easing-standard);
}

.saved-card__delete:active {
  transform: scale(0.94);
}

.preference-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

.child-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.profile-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.child-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

.child-form__actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
}

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

/* Child summary row — one glance at who/age/preference, tap to edit via
   the existing Child Setup form. Subtle card, not a heavy outlined button. */
.profile-child-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  width: 100%;
  padding: var(--space-md);
  border: none;
  border-radius: var(--radius);
  background: var(--color-bg-alt);
  box-shadow: var(--shadow-sm);
  text-align: start;
  transition: transform var(--duration-fast) var(--easing-standard);
}

.profile-child-card:active {
  transform: scale(0.98);
}

.profile-child-card__info {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.profile-child-card__name {
  font-size: var(--font-size-body-lg);
  line-height: var(--line-height-body-lg);
  font-weight: var(--font-weight-label-md);
  color: var(--color-text);
}

.profile-child-card__meta {
  font-size: var(--font-size-label-md);
  line-height: var(--line-height-label-md);
  color: var(--color-text-variant);
}

.profile-child-card__edit {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  flex-shrink: 0;
  font-size: var(--font-size-label-md);
  color: var(--color-text-variant);
}

/* Legal links (disclaimer, privacy) — quiet rows, same card surface as the
   child summary above so the section reads as part of Profile, not a footer. */
.profile-links {
  display: flex;
  flex-direction: column;
  border-radius: var(--radius);
  background: var(--color-bg-alt);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

.profile-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  min-height: 44px;
  padding: var(--space-md);
  color: var(--color-text);
  font-size: var(--font-size-body-md);
  line-height: var(--line-height-body-md);
  text-decoration: none;
}

.profile-link + .profile-link {
  border-top: 1px solid var(--color-border);
}

.profile-link svg {
  flex-shrink: 0;
  color: var(--color-text-variant);
}

/* Language segmented control — one grouped control instead of three
   unrelated pills; current language reads as clearly selected. */
.segmented-control {
  display: flex;
  gap: 4px;
  padding: 4px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background: var(--color-bg-alt);
}

.segmented-control__option {
  flex: 1;
  min-height: 44px;
  border: none;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--color-text-variant);
  font-size: var(--font-size-label-md);
  line-height: var(--line-height-label-md);
  font-weight: var(--font-weight-label-md);
  transition: background-color var(--duration-fast) var(--easing-standard), color var(--duration-fast) var(--easing-standard), transform var(--duration-fast) var(--easing-standard);
}

.segmented-control__option:active {
  transform: scale(0.98);
}

.segmented-control__option--active {
  background: var(--color-primary);
  color: var(--color-on-primary);
}

/* Lunchbox contents — the core "what I'll pack" list. Shared by Home and Details. */
.lunchbox-contents {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  width: 100%;
}

.lunchbox-contents__row {
  display: flex;
  align-items: center;
  gap: var(--space-gutter);
  padding: var(--space-sm) 0;
  border-bottom: 1px solid var(--color-border);
}

.lunchbox-contents__row:last-child {
  border-bottom: none;
}

.lunchbox-contents__emoji {
  font-size: 24px;
  line-height: 1;
  flex-shrink: 0;
}

.lunchbox-contents__slot {
  font-size: var(--font-size-label-md);
  color: var(--color-text-variant);
  min-width: 84px;
  flex-shrink: 0;
}

.lunchbox-contents__value-wrap {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.lunchbox-contents__value {
  font-size: var(--font-size-body-md);
  line-height: var(--line-height-body-md);
  color: var(--color-text);
  font-weight: 500;
}

/* Optional one-liner on `main` only, Details screen only — for the handful
   of ideas that need an actual cooking action (fry an egg, melt cheese),
   not the full catalog. Not a recipe step list: still one line, still
   about assembling the box, never rewritten as ingredients/times/servings. */
.lunchbox-contents__hint {
  font-size: var(--font-size-caption);
  line-height: 1.3;
  color: var(--color-text-variant);
}

.lunchbox-contents__hint::before {
  content: '💡 ';
}

/* Compact "what's inside" — Home only. Chips scan in ~1s instead of a
   5-row table; the full labeled list stays on Lunchbox Details. */
.lunchbox-contents--compact {
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-sm);
}

.lunchbox-contents--compact .lunchbox-contents__row {
  flex: 0 0 auto;
  align-items: center;
  gap: 6px;
  padding: 4px var(--space-md);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background: var(--color-bg-alt);
}

.lunchbox-contents--compact .lunchbox-contents__emoji {
  font-size: 18px;
}

.lunchbox-contents--compact .lunchbox-contents__value {
  font-size: var(--font-size-label-md);
  line-height: var(--line-height-label-md);
}

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

.lunchbox-details {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

/* Positioning context for the floating .save-toggle over the photo — same
   role as .home-suggestion__hero on Home. */
.lunchbox-details__hero {
  position: relative;
}

.lunchbox-details__section {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  padding-top: var(--space-lg);
  border-top: 1px solid var(--color-border);
}

.lunchbox-details__section-title {
  font-size: var(--font-size-headline-md);
  line-height: var(--line-height-headline-md);
  font-weight: var(--font-weight-headline-md);
  color: var(--color-primary);
}

.lunchbox-details__ingredients {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.lunchbox-details__steps {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

.lunchbox-details__step {
  display: flex;
  gap: var(--space-main);
}

.lunchbox-details__step-number {
  font-size: var(--font-size-headline-lg);
  line-height: var(--line-height-body-lg);
  color: var(--color-border);
  width: 32px;
  flex-shrink: 0;
}

.lunchbox-details__step-text {
  font-size: var(--font-size-body-lg);
  line-height: var(--line-height-body-lg);
  color: var(--color-text);
  padding-top: 2px;
}
