/* ============================================================
   FromFresh — Global Styles
   Mobile/tablet first. Max usable width ~768px.
   ============================================================ */

/* --- Bootstrap overrides --- */
:root {
    --bs-primary:   var(--ff-primary);
    --bs-secondary: var(--ff-secondary);
    --bs-body-bg:   var(--ff-bg);
    --bs-body-color: var(--ff-text);

    /* Mobile breakpoint tokens. CSS @media queries can't read var(...), so the
       literal values are used in the @media rules below — keep these in sync.
       Anything that needs the value in JS or inline CSS can reference these. */
    --ff-mobile-small:  320px;
    --ff-mobile-medium: 375px;
    --ff-mobile-large:  425px;
}

/* --- Base --- */
*, *::before, *::after { box-sizing: border-box; }

html, body {
    height: 100%;
    margin: 0;
    font-family: Calibri, 'Helvetica Neue', Helvetica, Arial, sans-serif;
    background-color: var(--ff-bg);
    color: var(--ff-text);
    -webkit-tap-highlight-color: transparent;
}

/* --- App shell --- */
.ff-shell {
    display: flex;
    flex-direction: column;
    height: 100dvh;
    max-width: 768px;
    margin: 0 auto;
    position: relative;
    background: var(--ff-bg);
}

/* --- Top header --- */
.ff-header {
    position: fixed;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 100%;
    max-width: 768px;
    height: var(--ff-header-h);
    /* Grow into the iPhone notch / status-bar area when standalone (env() is 0 elsewhere). */
    height: calc(var(--ff-header-h) + env(safe-area-inset-top));
    background: var(--ff-primary);
    color: #fff;
    display: flex;
    align-items: center;
    padding: 0 1rem;
    padding-top: env(safe-area-inset-top);
    z-index: 100;
    box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}

.ff-header-brand {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    font-size: 2.25rem;
    font-weight: 900;
    letter-spacing: -0.3px;
    color: #fff;
    text-decoration: none;
    white-space: nowrap;
}

.ff-header-brand span {
    color: var(--ff-primary-pale);
}

.ff-header-brand span.ff-header-beta {
    color: rgba(255, 255, 255, 0.45);
    font-size: 0.95rem;
    font-weight: 600;
    letter-spacing: 0;
    vertical-align: middle;
}

.ff-header-premium {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: #fff8d6;
    background: linear-gradient(135deg, #d4a017 0%, #b8860b 60%, #9a6f00 100%);
    border: 1px solid #ffe066;
    border-radius: 20px;
    padding: 3px 9px;
    white-space: nowrap;
    box-shadow: 0 1px 4px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,230,100,0.3);
}

@media (max-width: 375px) { /* --ff-mobile-medium */
    .ff-header-premium-label { display: none; }
    .ff-header-premium { min-height: calc(0.7rem * 1.5 + 6px); }
}

.ff-header-premium .ff-star {
    margin: 1px 0 0 1px;
}

.ff-header-logout {
    margin-left: auto;
    background: none;
    border: none;
    color: rgba(255,255,255,0.75);
    font-size: 1.1rem;
    padding: 6px 8px;
    cursor: pointer;
    border-radius: 6px;
    transition: color 0.15s, background 0.15s;
}

.ff-header-logout:hover {
    color: #fff;
    background: rgba(255,255,255,0.12);
}

/* --- Page content --- */
.ff-content {
    margin-top: var(--ff-header-h);
    margin-top: calc(var(--ff-header-h) + env(safe-area-inset-top));
    margin-bottom: var(--ff-bottom-nav-h);
    margin-bottom: calc(var(--ff-bottom-nav-h) + env(safe-area-inset-bottom));
    overflow-y: auto;
    flex: 1;
    padding: 1rem;
    width: 100%;
    max-width: 650px;
    margin-inline: auto;
}

@media (max-width: 320px) { /* --ff-mobile-medium */
    .ff-content {
        padding: 0.5rem;
    }
}

/* --- Bottom navigation --- */
.ff-bottom-nav {
    position: fixed;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 100%;
    max-width: 768px;
    height: var(--ff-bottom-nav-h);
    /* Grow into the iPhone home-indicator area when standalone (env() is 0 elsewhere). */
    height: calc(var(--ff-bottom-nav-h) + env(safe-area-inset-bottom));
    background: var(--ff-surface);
    border-top: 1px solid var(--ff-border);
    display: flex;
    align-items: center;
    justify-content: space-around;
    z-index: 100;
    padding-bottom: env(safe-area-inset-bottom);
}

.ff-nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    flex: 1;
    height: 100%;
    color: var(--ff-muted);
    text-decoration: none;
    font-size: 0.65rem;
    font-weight: 500;
    transition: color 0.15s ease;
    cursor: pointer;
    border: none;
    background: none;
    padding: 0;
}

.ff-nav-item i, .ff-nav-item svg {
    font-size: 1.4rem;
}

.ff-nav-item.active {
    color: var(--ff-primary);
}

.ff-nav-item:active {
    color: var(--ff-primary-dark);
}

/* --- Cards --- */
.ff-card {
    background: var(--ff-surface);
    border-radius: 12px;
    padding: 0.35rem;
    margin-bottom: 0.625rem;
    box-shadow: 0 1px 4px rgba(0,0,0,0.07);
    display: flex;
    align-items: center;
    gap: 0.75rem;
    /* Clips the action slide panel + hint animation so buttons don't escape
       past the right edge into the page background. box-shadow renders
       outside the element box, so the card shadow is unaffected. */
    overflow: hidden;
}

.ff-card-icon {
    width: 44px;
    height: 44px;
    border-radius: 10px;
    background: var(--ff-bg);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.3rem;
    flex-shrink: 0;
    border-left: 4px solid transparent;
}

.ff-card-icon-pantry  { background: #FEF0D8; border-left-color: #D89030; }
.ff-card-icon-fridge  { background: #D8EFF8; border-left-color: #58AED6; }
.ff-card-icon-freezer { background: #EAE4F8; border-left-color: #9C82D4; }
.ff-card-icon-spices  { background: #DCF1DD; border-left-color: #5DAE74; }

.ff-card-body {
    flex: 1;
    min-width: 0;
}

.ff-card-title {
    font-weight: 600;
    font-size: 0.95rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin: 0 0 2px;
    text-transform: capitalize;
}

.ff-card-meta {
    font-size: 0.78rem;
    color: var(--ff-muted);
    margin: 0;
    line-height: normal;
}

.ff-card-right {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    flex-shrink: 0;
}

/* --- Badges --- */
.ff-badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 20px;
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.3px;
}

.ff-badge-pantry       { background: #FEF0D8; color: #8A5010; }
.ff-badge-fridge       { background: #D8EFF8; color: #1E6A8A; }
.ff-badge-freezer      { background: #EAE4F8; color: #5030A0; }
.ff-badge-missing      { background: #FDE8E8; color: #A02828; }
.ff-badge-insufficient { background: #FEF0D8; color: #8A5010; }

.ff-card-missing {
    opacity: 0.7;
    border: 1.5px dashed var(--ff-border);
    background: var(--ff-bg);
    box-shadow: none;
}

/* Missing-item card has no right column or bin button — title is allowed to
   wrap so unrecognised phrases don't truncate, and the badge sits inline below. */
.ff-card-missing .ff-card-title {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
}
.ff-card-missing .ff-badge-missing {
    margin-top: 0.25rem;
}

/* --- Expiry labels --- */
.ff-expiry {
    font-size: 0.72rem;
    font-weight: 600;
}
.ff-expiry-ok      { color: var(--ff-muted); }
.ff-expiry-soon    { color: var(--ff-warning); }
.ff-expiry-expired { color: var(--ff-danger); }

/* --- Filter tabs --- */
.ff-filter-bar {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 1rem;
    overflow-x: auto;
    padding-bottom: 2px;
    scrollbar-width: none;
}
.ff-filter-bar::-webkit-scrollbar { display: none; }

.ff-filter-btn {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 16px;
    border-radius: 20px;
    border: 1.5px solid var(--ff-border);
    background: var(--ff-surface);
    color: var(--ff-muted);
    font-size: 0.82rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.15s ease;
    white-space: nowrap;
}

/* Pin :hover/:focus/:active to the inactive look so the only visual states
   are on (.active) and off — no Bootstrap focus ring or hover tint leaking
   through after a click. */
.ff-filter-btn:hover,
.ff-filter-btn:focus,
.ff-filter-btn:focus-visible,
.ff-filter-btn:active {
    background: var(--ff-surface);
    border-color: var(--ff-border);
    color: var(--ff-muted);
    box-shadow: none;
    outline: none;
}

.ff-filter-btn.active,
.ff-filter-btn.active:hover,
.ff-filter-btn.active:focus,
.ff-filter-btn.active:focus-visible,
.ff-filter-btn.active:active {
    background: var(--ff-primary);
    border-color: var(--ff-primary);
    color: #fff;
    box-shadow: none;
    outline: none;
}

.ff-form-control {
    background-color: var(--ff-surface);
}

/* --- Search --- */
.ff-search-row {
    display: flex;
    align-items: stretch;
    gap: 0.625rem;
    margin-bottom: 1rem;
}

.ff-search-wrap {
    position: relative;
    flex: 1;
    min-width: 0;
}

.ff-plus-btn {
    flex-shrink: 0;
    border: none;
    border-radius: 10px;
    background: #E9ECEF;
    color: var(--ff-muted);
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.1s ease;
}

    .ff-plus-btn .fa-plus {
        margin-top: 2px;
    }

.ff-plus-btn:hover,
.ff-plus-btn:focus,
.ff-plus-btn:active { background: var(--ff-border); color: var(--ff-muted); }
.ff-plus-btn:active { transform: scale(0.95); }

.ff-plus-btn-md { width: 44px; font-size: 1.1rem; }
.ff-plus-btn-sm { width: 40px; height: 40px; font-size: 1rem; }

/* Stacked +/bin actions inside a pantry card */
.ff-card-actions {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    flex-shrink: 0;
    margin-left: 0.375rem;
}
.ff-card-actions .ff-plus-btn,
.ff-card-actions .ff-bin-btn {
    width: 40px;
    height: 24px;
    margin: 0;
    font-size: 0.8rem;
}

/* --- Sheet sizing ---
   Sheets default to content-sized height. ffSheets.measure() promotes them
   to fullscreen via .ff-sheet-fullscreen when natural content > 50dvh. */
.ff-sheet-fullscreen {
    --bs-offcanvas-height: 100dvh;
}

/* --- Shared sheet base ---
   Shell + header + flex-column body with a single .ff-sheet-scroll region
   and a sticky .ff-sheet-footer pinned to the bottom. Used by every sheet
   (AddPantryItemSheet, CookRecipeSheet, AddShoppingToPantrySheet,
   VoiceCaptureSheet). Each sheet must wrap its body content in a single
   .ff-sheet-scroll div so the footer can stay anchored. */
.ff-sheet {
    --bs-offcanvas-height: auto;
    border-radius: 20px 20px 0 0;
    max-height: 100dvh;
    overflow: hidden;
    padding-bottom: env(safe-area-inset-bottom);
    transition: transform 0.4s cubic-bezier(0.32, 0.72, 0, 1) !important;
}

.ff-sheet .offcanvas-header {
    border-bottom: 1px solid var(--ff-border);
    padding: 1rem 1.5rem;
    max-width: 450px;
    margin-inline: auto;
    width: 100%;
}

/* Body becomes a flex column so the scroll area and sticky footer can
   share its height. min-height: 0 is the standard fix that lets the
   scrolling child actually shrink (otherwise flex items default to their
   intrinsic content height and the scroll never engages). */
.ff-sheet .offcanvas-body {
    overflow: hidden;
    padding: 0;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* Single scrollable region — every sheet wraps its content in one of these.
   flex-basis: auto so the scroll area matches its content's height when the
   sheet is auto-sized, and grows to fill the remaining space when fullscreen. */
.ff-sheet-scroll {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 1.5rem;
    max-width: 450px;
    margin-inline: auto;
    width: 100%;
}

/* The sheet itself sits on --ff-bg (via --bs-body-bg), so fields use the
   lighter --ff-surface (white) to read as distinct, tappable pills. */
.ff-sheet .form-control,
.ff-sheet .input-group-text,
.ff-sheet .ff-date-btn {
    background-color: var(--ff-surface);
}

/* Sticky footer — flex-shrink: 0 keeps the button row visible no matter how
   long the scroll area gets. Surface background + top border + soft shadow
   visually detach it from the content above. */
.ff-sheet-footer {
    flex-shrink: 0;
    display: flex;
    gap: 0.75rem;
    justify-content: flex-end;
    padding: 0.875rem 1.25rem calc(0.875rem + env(safe-area-inset-bottom));
    background: var(--ff-surface);
    border-top: 1px solid var(--ff-border);
    box-shadow: 0 -2px 10px rgba(0,0,0,0.05);
}

.ff-search-icon {
    position: absolute;
    left: 0.875rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--ff-muted);
    font-size: 0.9rem;
    pointer-events: none;
}

.ff-search {
    width: 100%;
    padding: 0.65rem 2.5rem 0.65rem 2.5rem;
    border: 1.5px solid var(--ff-border);
    border-radius: 10px;
    background: var(--ff-surface);
    font-size: 0.9rem;
    color: var(--ff-text);
    outline: none;
    transition: border-color 0.15s ease;
    -webkit-appearance: none;
}

.ff-search:focus {
    border-color: var(--ff-primary);
}

.ff-search::placeholder { color: var(--ff-muted); }

/* hide browser's native clear button */
.ff-search::-webkit-search-cancel-button { display: none; }

.ff-search-clear {
    position: absolute;
    right: 0.75rem;
    top: 50%;
    transform: translateY(-50%);
    background: none;
    border: none;
    color: var(--ff-muted);
    font-size: 0.9rem;
    cursor: pointer;
    padding: 0.25rem;
    line-height: 1;
}

/* --- Card action buttons --- */
.ff-card > .ff-plus-btn {
    margin-left: 0.5rem;
}

/* Standalone add-to-pantry button used on individual shopping list cards.
   Matches the iOS-style rounded square the user specified — intentionally
   more prominent than the stacked ff-card-actions pair on pantry cards. */
.ff-add-btn {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border: none;
    border-radius: 12px;
    background: var(--ff-bg);
    color: var(--ff-muted);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
    cursor: pointer;
    margin-left: 0.5rem;
    transition: background 0.15s ease, transform 0.1s ease;
}
.ff-add-btn:hover  { background: var(--ff-border); }
.ff-add-btn:active { transform: scale(0.95); }

.ff-bin-btn {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border: none;
    border-radius: 10px;
    background: #FDE8E8;
    color: var(--ff-danger);
    font-size: 0.9rem;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    margin-left: 0.375rem;
    transition: background 0.15s ease, transform 0.1s ease;
}

    .ff-bin-btn .fa-trash-can{
        margin-top: 2px;
    }

.ff-bin-btn:hover,
.ff-bin-btn:focus,
.ff-bin-btn:active { background: #F8CCCC; color: var(--ff-danger); }
.ff-bin-btn:active { transform: scale(0.95); }

.ff-cal-btn {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border: none;
    border-radius: 10px;
    background: #D8EFF8;
    color: #58AED6;
    font-size: 0.9rem;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    margin-left: 0.375rem;
    transition: background 0.15s ease, transform 0.1s ease;
}
.ff-cal-btn:hover,
.ff-cal-btn:focus,
.ff-cal-btn:active { background: #BFE3F1; color: #58AED6; }
.ff-cal-btn:active { transform: scale(0.95); }
.ff-cal-btn-sm { width: 40px; height: 24px; font-size: 0.8rem; margin-left: 0; }
.ff-card-grouped-row .ff-cal-btn { margin-left: 0; }

/* Row wrapper that groups the calendar button and the clone/bin action stack into
   a single flex child of .ff-card, preventing the card's gap from separating them. */
.ff-card-actions-group {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 0.375rem;
    flex-shrink: 0;
}
.ff-card-actions-group .ff-card-actions,
.ff-card-actions-group .ff-cal-btn,
.ff-card-actions-group .ff-bin-btn-inline { margin: 0; }

/* Wrapper that groups card action buttons (e.g. calendar + bin) as a single flex
   child of .ff-card, so the card's own gap doesn't push them apart. Below the
   Mobile Medium breakpoint the wrapper stacks the buttons vertically in the
   same compact pill shape used by the Pantry page's .ff-card-actions. */
.ff-card-actions-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 0.1875rem;
    flex-shrink: 0;
}
.ff-card-actions-row .ff-cal-btn,
.ff-card-actions-row .ff-qty-btn,
.ff-card-actions-row .ff-bin-btn { margin-left: 0; }

@media (max-width: 375px) {
    .ff-card-actions-row {
        flex-direction: column;
        gap: 4px;
    }
    .ff-card-actions-row .ff-cal-btn,
    .ff-card-actions-row .ff-qty-btn,
    .ff-card-actions-row .ff-bin-btn {
        width: 40px;
        height: 24px;
        font-size: 0.8rem;
    }
}

/* Inline quantity edit button. Mirrors .ff-cal-btn shape & size with a green
   tint so the three action buttons (cal / qty / bin) stay visually distinct. */
.ff-qty-btn {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border: none;
    border-radius: 10px;
    background: #DCEFD8;
    color: #5BAE58;
    font-size: 0.9rem;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    margin-left: 0.375rem;
    transition: background 0.15s ease, transform 0.1s ease;
}
.ff-qty-btn:hover,
.ff-qty-btn:focus,
.ff-qty-btn:active { background: #C5E5BD; color: #5BAE58; }
.ff-qty-btn:active { transform: scale(0.95); }
.ff-qty-btn-sm     { width: 40px; height: 24px; font-size: 0.8rem; margin-left: 0; }

/* Inline number input shown in the card meta line while editing quantity.
   Sized so it doesn't push the card height around when toggling between
   display and edit states. */
.ff-card-meta-editing {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    margin: 0;
}
.ff-qty-input {
    width: 5rem;
    padding: 0.125rem 0.375rem;
    border: 1px solid var(--ff-border);
    border-radius: 6px;
    background: var(--ff-surface);
    color: var(--ff-text);
    font-size: 0.9rem;
    /* hide spinner arrows — they don't fit visually and take up width */
    -moz-appearance: textfield;
}
.ff-qty-input::-webkit-outer-spin-button,
.ff-qty-input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
.ff-qty-input-unit {
    color: var(--ff-muted);
    font-size: 0.9rem;
}

/* --- Grouped pantry card (same food, multiple expiry dates) --- */
.ff-card-grouped {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
}
.ff-card-grouped-header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}
.ff-card-grouped-rows {
    margin-top: 0.5rem;
    padding-top: 0.4rem;
    border-top: 1px dashed var(--ff-border);
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}
.ff-card-grouped-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.15rem 0 0.15rem 56px;
    font-size: 0.78rem;
    color: var(--ff-muted);
}

.ff-card-grouped-qty {
    flex: 1;
    color: var(--ff-muted);
}
.ff-bin-btn-inline {
    width: 40px;
    height: 24px;
    margin: 0 0 0 auto;
    font-size: 0.8rem;
}

/* --- Section heading --- */
.ff-section-label {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: var(--ff-muted);
    margin: 1rem 0 0.5rem;
}

/* --- Loading spinner --- */
.ff-loading {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 3rem 1rem;
    color: var(--ff-primary);
}
.ff-loading .spinner-border {
    width: 2.5rem;
    height: 2.5rem;
    border-width: 0.3em;
}

/* --- Empty state --- */
.ff-empty {
    text-align: center;
    padding: 3rem 1rem;
    color: var(--ff-muted);
}
.ff-empty-icon { font-size: 3rem; margin-bottom: 0.5rem; }
.ff-empty-text { font-size: 0.9rem; }
.ff-empty-retry {
    margin-top: 1rem;
    border: 1px solid var(--ff-border);
    background: transparent;
    color: var(--ff-text-muted);
    font-size: 0.85rem;
    padding: 0.45rem 1rem;
    border-radius: 8px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    transition: border-color 0.15s ease, color 0.15s ease;
}
.ff-empty-retry:hover { border-color: var(--ff-primary); color: var(--ff-primary); }

/* --- Bottom-nav voice button ---
   Sits in the middle slot of the bottom nav (between Shopping and Recipes).
   The inner circle is raised above the nav strip so it reads as a primary
   action regardless of which page is active. The transparent outer button
   keeps the flex slot the same width as the surrounding nav items so they
   stay evenly spaced. */
.ff-nav-voice {
    flex: 1;
    height: 100%;
    background: none;
    border: none;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}

.ff-nav-voice-btn {
    width: 70px;
    height: 70px;
    border-radius: 50%;
    background: var(--ff-primary);
    color: #fff;
    font-size: 1.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    /* 4px ring in the nav's own surface colour fakes a notch where the button
       punches through the top of the nav bar. */
    border: 4px solid var(--ff-surface);
    box-shadow: 0 4px 14px rgba(0,0,0,0.22);
    /* Same raise as before; the larger diameter carries the bottom edge down to
       roughly the baseline of the adjacent icon labels. */
    transform: translateY(-18px);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.ff-nav-voice:hover  .ff-nav-voice-btn,
.ff-nav-voice:focus  .ff-nav-voice-btn,
.ff-nav-voice:focus-visible .ff-nav-voice-btn {
    transform: translateY(-18px) scale(1.06);
    box-shadow: 0 6px 18px rgba(0,0,0,0.28);
}
.ff-nav-voice:active .ff-nav-voice-btn {
    transform: translateY(-18px) scale(0.94);
}

/* --- Cook pill (Recipe page, above Ingredients/Steps tabs) --- */
/* Padding/font sized to match .ff-segmented-btn so the pill lines up with the
   inner buttons of the segmented control directly below it. */
.ff-cook-pill {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: 100%;
    margin: 0.75rem 0;
    padding: 7px 14px;
    border: none;
    border-radius: 999px;
    background: var(--ff-primary);
    color: #fff;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(0,0,0,0.15);
    transition: box-shadow 0.15s ease, transform 0.05s ease;
}
.ff-cook-pill:hover  { box-shadow: 0 2px 8px rgba(0,0,0,0.22); }
.ff-cook-pill:active { transform: scale(0.99); }

/* --- Cook confirmation sheet ---
   Shell + header + body layout comes from the shared .ff-sheet base. The
   classes below style only the cook-specific content (intro, ingredient
   rows, footnote). */
.ff-cook-intro {
    color: var(--ff-text);
    font-size: 0.95rem;
    margin: 0;
}
.ff-cook-empty {
    color: var(--ff-text-muted);
    text-align: center;
    margin: 1rem 0;
}
.ff-cook-list {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    margin: 1rem 0;
}
.ff-cook-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.55rem 0.75rem;
    border: 1px solid var(--ff-border);
    border-radius: 10px;
    background: var(--ff-surface);
}
.ff-cook-row-missing { opacity: 0.6; }
.ff-cook-row-short   { border-color: var(--ff-warning, #d9822b); }
.ff-cook-emoji { font-size: 1.4rem; line-height: 1; }
.ff-cook-body { flex: 1; min-width: 0; }
.ff-cook-name {
    margin: 0;
    font-weight: 600;
    color: var(--ff-text);
    font-size: 0.95rem;
}
.ff-cook-meta {
    margin: 0.1rem 0 0 0;
    color: var(--ff-text-muted);
    font-size: 0.82rem;
}
.ff-cook-footnote {
    color: var(--ff-text-muted);
    font-size: 0.8rem;
    margin: 0.25rem 0 0 0;
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

/* --- Date picker button --- */
.ff-date-btn {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.65rem 0.875rem;
    border: 1.5px solid var(--ff-border);
    border-radius: 10px;
    background: var(--ff-surface);
    color: var(--ff-text);
    font-size: 0.9rem;
    text-align: left;
    cursor: pointer;
    transition: border-color 0.15s ease;
}
.ff-date-btn:not(:disabled):hover,
.ff-date-btn:not(:disabled):focus { border-color: var(--ff-primary); outline: none; }
.ff-date-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.ff-date-btn i { color: var(--ff-muted); flex-shrink: 0; }
.ff-date-btn > span:not(.ff-date-clear) { flex: 1; }
.ff-date-clear {
    color: var(--ff-muted);
    font-size: 0.85rem;
    line-height: 1;
    cursor: pointer;
    flex-shrink: 0;
}

/* --- Voice input --- */
@keyframes ff-pulse {
    0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(255,77,77,0.5); }
    50%       { opacity: 0.85; box-shadow: 0 0 0 14px rgba(255,77,77,0); }
}

.ff-voice-panel {
    text-align: center;
    padding: 0.5rem 0rem;
}

.ff-voice-panel .ff-voice-label {
    margin: 0.75rem 0.0rem 0.25rem 0.0rem;
}

.ff-voice-icon {
    font-size: 2.5rem;
    margin-bottom: 0.75rem;
    color: var(--ff-primary);
}

/* centre mic — idle/paused start/resume button */
.ff-voice-record-btn {
    width: 88px;
    height: 88px;
    border-radius: 50%;
    border: none;
    background: var(--ff-primary);
    color: #fff;
    font-size: 2rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: transform 0.15s ease, background 0.15s ease;
    box-shadow: 0 4px 18px rgba(0,0,0,0.18);
}

.ff-voice-record-btn .fa-microphone{
    margin-left: 2px;
}

.ff-voice-record-btn:hover  { transform: scale(1.06); }
.ff-voice-record-btn:active { transform: scale(0.95); }

/* three-button row shown while listening */
.ff-voice-controls {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.75rem;
    margin-bottom: 1rem;
    /* Reserve room for the mic indicator's pulse box-shadow (extends 14px),
       which would otherwise be clipped by the scroll container above. */
    padding: 1rem 0;
}

/* pulsing mic indicator in centre — non-interactive */
.ff-voice-mic-indicator {
    width: 88px;
    height: 88px;
    border-radius: 50%;
    background: var(--ff-primary);
    color: #fff;
    font-size: 2rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 18px rgba(0,0,0,0.18);
    animation: ff-pulse 1.4s ease-in-out infinite;
    pointer-events: none;
}
.ff-voice-mic-indicator-paused {
    animation: none;
    opacity: 0.4;
}

/* flanking action buttons */
.ff-voice-ctrl-btn {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    border: none;
    background: #E9ECEF;
    color: var(--ff-text);
    font-size: 1.2rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(0,0,0,0.10);
    transition: transform 0.15s ease, background 0.15s ease, opacity 0.15s ease;
}
.ff-voice-ctrl-btn:hover  { background: var(--ff-border); transform: scale(1.06); }
.ff-voice-ctrl-btn:active { transform: scale(0.95); }
.ff-voice-ctrl-btn:disabled { opacity: 0.35; cursor: not-allowed; transform: none; }
.ff-voice-ctrl-btn-send { background: var(--ff-primary); color: #fff; }
.ff-voice-ctrl-btn-send:hover { background: var(--ff-primary-dark); }
.ff-voice-label {
    display: block;
    font-size: 0.85rem;
    color: var(--ff-muted);
    margin-bottom: 0.875rem;
}
.ff-voice-transcript {
    background: var(--ff-bg);
    border-radius: 10px;
    padding: 0.75rem 1rem;
    font-size: 0.9rem;
    color: var(--ff-text);
    text-align: left;
    min-height: 60px;
    margin: 0;
    word-break: break-word;
}
.ff-voice-interim { color: var(--ff-muted); }
.ff-voice-transcript-paused { opacity: 0.5; }

.ff-voice-missing { padding: 1.75rem 1.25rem; text-align: center; }
.ff-voice-missing-icon {
    font-size: 2.5rem;
    color: var(--ff-primary);
    margin-bottom: 0.75rem;
}
.ff-voice-missing-title {
    font-weight: 600;
    font-size: 1rem;
    margin: 0 0 0.625rem;
    color: var(--ff-text);
}
.ff-voice-missing-list {
    display: inline-block;
    text-align: left;
    margin: 0 auto 0.875rem;
    padding-left: 1.25rem;
    font-size: 0.9rem;
    color: var(--ff-text);
}
.ff-voice-missing-list li { margin-bottom: 0.25rem; }
.ff-voice-missing-text {
    font-size: 0.88rem;
    color: var(--ff-muted);
    margin: 0;
    line-height: 1.45;
}

.ff-voice-error { padding: 2rem 1.25rem; }
.ff-voice-error-icon {
    font-size: 2.75rem;
    color: var(--ff-danger);
    margin-bottom: 0.75rem;
}
.ff-voice-error-title {
    font-weight: 600;
    font-size: 1rem;
    margin: 0 0 0.375rem;
    color: var(--ff-text);
}
.ff-voice-error-text {
    font-size: 0.88rem;
    color: var(--ff-muted);
    margin: 0;
}

.ff-parsed-header {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--ff-muted);
    margin-bottom: 0.5rem;
}

/* --- Blazor error --- */
#blazor-error-ui {
    background: #b32121;
    color: white;
    padding: 0.75rem 1rem;
    position: fixed;
    bottom: var(--ff-bottom-nav-h);
    width: 100%;
    text-align: center;
    z-index: 200;
    display: none;
}
#blazor-error-ui.blazor-error-boundary { display: block; }

/* --- Misc --- */
.valid.modified:not([type=checkbox]) { outline: 1px solid #26b050; }
.invalid { outline: 1px solid #e50000; }
.validation-message { color: #e50000; }

/* --- Login screen --- */
.ff-login-screen {
    position: fixed;
    inset: 0;
    background: var(--ff-bg);
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 1.5rem 1.25rem 2rem;
    z-index: 200;
    overflow-y: auto;
}

.ff-login-card {
    width: 100%;
    max-width: 420px;
    background: var(--ff-surface);
    border-radius: 16px;
    padding: 1.75rem 1.5rem 1.75rem;
    box-shadow: 0 10px 30px rgba(0,0,0,0.08);
    margin-top: 1rem;
}

.ff-login-brand {
    text-align: center;
    font-size: 2.25rem;
    font-weight: 900;
    letter-spacing: -0.3px;
    color: var(--ff-primary);
    margin-bottom: 0.25rem;
}
.ff-login-brand span { color: var(--ff-primary-pale); }

.ff-login-tagline {
    text-align: center;
    color: var(--ff-muted);
    font-size: 0.9rem;
    margin: 0 0 1.25rem;
}

.ff-login-tabs {
    display: flex;
    gap: 0.25rem;
    background: var(--ff-bg);
    border-radius: 10px;
    padding: 4px;
    margin-bottom: 0;
}

.ff-login-tab {
    flex: 1;
    border: none;
    background: transparent;
    color: var(--ff-primary);
    font-size: 0.88rem;
    font-weight: 600;
    padding: 0.55rem 0.5rem;
    border-radius: 8px;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}

.ff-login-tab-active {
    background: var(--ff-surface);
    color: var(--ff-primary);
    box-shadow: 0 1px 3px rgba(0,0,0,0.08);
}

/* Collapsible form panel */
.ff-login-form-panel {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.3s ease;
}

.ff-login-form-panel-open {
    grid-template-rows: 1fr;
}

.ff-login-form-inner {
    overflow: hidden;
    padding-top: 0;
    transition: padding-top 0.3s ease;
}

.ff-login-form-panel-open .ff-login-form-inner {
    padding-top: 1.25rem;
}

.ff-login-form {
    display: flex;
    flex-direction: column;
    gap: 0.875rem;
}

/* Marketing steps */
.ff-login-steps {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-top: 1.25rem;
}

.ff-login-step {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    background: var(--ff-bg);
    border-radius: 12px;
    padding: 0.75rem 0.875rem;
}

.ff-login-step-num {
    flex-shrink: 0;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--ff-primary);
    color: #fff;
    font-size: 0.78rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-top: 1px;
}

.ff-login-step-text {
    font-size: 0.875rem;
    color: var(--ff-text);
    line-height: 1.45;
}

.ff-login-step-icon {
    color: var(--ff-danger);
    font-size: 0.8rem;
}

.ff-login-field {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.ff-login-field label {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--ff-text);
}

.ff-login-optional {
    color: var(--ff-muted);
    font-weight: 400;
    font-size: 0.75rem;
}

.ff-login-input {
    width: 100%;
    border: 1.5px solid var(--ff-border);
    border-radius: 10px;
    padding: 0.65rem 0.8rem;
    font-size: 1rem;
    background: var(--ff-bg);
    color: var(--ff-text);
    transition: border-color 0.15s ease;
}

.ff-login-input:focus {
    outline: none;
    border-color: var(--ff-primary);
}

.ff-login-input:disabled {
    opacity: 0.6;
}

.ff-login-hint {
    font-size: 0.75rem;
    color: var(--ff-muted);
    margin: -0.25rem 0 0;
}

.ff-login-errors {
    background: #FDE8E8;
    border: 1px solid #F4B5B5;
    color: #8A1F1F;
    border-radius: 10px;
    padding: 0.6rem 0.75rem;
    font-size: 0.82rem;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
}

.ff-login-submit {
    margin-top: 0.5rem;
    border: none;
    background: var(--ff-primary);
    color: #fff;
    font-weight: 700;
    font-size: 1rem;
    padding: 0.75rem 1rem;
    border-radius: 10px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    transition: background 0.15s ease, transform 0.1s ease;
}

.ff-login-submit:hover:not(:disabled) { background: var(--ff-primary-dark); }
.ff-login-submit:active:not(:disabled) { transform: scale(0.99); }
.ff-login-submit:disabled { opacity: 0.65; cursor: not-allowed; }

.ff-login-dev {
    margin-top: 0.75rem;
    width: 100%;
    border: 1px dashed var(--ff-border);
    background: transparent;
    color: var(--ff-text-muted);
    font-size: 0.8rem;
    padding: 0.45rem 1rem;
    border-radius: 8px;
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease;
}

.ff-login-dev:hover:not(:disabled) { border-color: var(--ff-primary); color: var(--ff-primary); }
.ff-login-dev:disabled { opacity: 0.5; cursor: not-allowed; }

.ff-login-dev-premium:hover:not(:disabled) { border-color: #b8860b; color: #b8860b; }

/* ============================================================
   Recipes
   ============================================================ */

/* --- Servings stepper --- */
.ff-servings-row {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    margin-bottom: 1rem;
}

.ff-servings-label {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--ff-text);
}

.ff-servings-suffix {
    font-size: 0.85rem;
    color: var(--ff-muted);
}

.ff-stepper {
    display: inline-flex;
    align-items: center;
    background: var(--ff-surface);
    border: 1.5px solid var(--ff-border);
    border-radius: 22px;
    padding: 3px;
    gap: 0.25rem;
}

.ff-stepper-btn {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    border: none;
    background: var(--ff-primary);
    color: #fff;
    font-size: 0.75rem;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.1s ease;
}
.ff-stepper-btn:hover:not(:disabled)  { background: var(--ff-primary-dark); }
.ff-stepper-btn:active:not(:disabled) { transform: scale(0.92); }
.ff-stepper-btn:disabled              { background: var(--ff-border); cursor: not-allowed; }

.ff-stepper-value {
    min-width: 1.6rem;
    text-align: center;
    font-weight: 700;
    font-size: 0.95rem;
    color: var(--ff-text);
    font-variant-numeric: tabular-nums;
}

/* --- Recipe list card (clickable) --- */
.ff-recipe-card {
    position: relative;
    width: 100%;
    background: var(--ff-surface);
    border: none;
    border-radius: 12px;
    padding: 0.625rem 0.75rem;
    margin-bottom: 0.625rem;
    box-shadow: 0 1px 4px rgba(0,0,0,0.07);
    display: flex;
    align-items: center;
    gap: 0.75rem;
    text-align: left;
    cursor: pointer;
    transition: transform 0.05s ease, box-shadow 0.15s ease;
    color: inherit;
}

.ff-recipe-card:hover { box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
.ff-recipe-card:active { transform: scale(0.995); }

.ff-recipe-card-thumb {
    width: 72px;
    height: 72px;
    border-radius: 10px;
    overflow: visible; /* badge overlaps the corner — clipping is on the children */
    flex-shrink: 0;
    background: var(--ff-bg);
    position: relative;
}

.ff-recipe-card-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    border-radius: 10px;
}

.ff-recipe-card-thumb-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--ff-muted);
    font-size: 1.5rem;
    background: linear-gradient(135deg, #FEF0D8 0%, #D8EFF8 100%);
    border-radius: 10px;
}

.ff-recipe-card-body {
    flex: 1;
    min-width: 0;
    /* Stop body text running under the absolute-positioned heart (top-right)
       or the nutrition-tag chips (bottom-right). Heart: 32 px wide at
       right: 6px → occupies ~26 px of content area; 30 px right clears it.
       Tags sit at bottom: 6px so we don't need extra bottom padding — the
       card's own padding (10px) and the tags' height (~20px) mean they won't
       overlap the badge row in normal cases. */
    padding-right: 30px;
}

.ff-recipe-makeable-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-top: 4px;
    padding: 2px 8px;
    border-radius: 20px;
    background: #DCF1DD;
    color: #1F6F2A;
    font-size: 0.7rem;
    font-weight: 600;
}

.ff-recipe-almost-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-top: 4px;
    padding: 2px 8px;
    border-radius: 20px;
    background: #FEF0D8;
    color: #8A5010;
    font-size: 0.7rem;
    font-weight: 600;
}

.ff-recipe-partial-hint {
    display: inline-block;
    margin-top: 4px;
    font-size: 0.72rem;
    color: var(--ff-muted);
}

/* --- Recipe nutrition tags (calorie / protein) ---
   Anchored to the card's top-right corner. Deliberately a different shape &
   treatment from the solid status pills below: small outlined chips on the
   card surface, so the user reads them as a glanceable numeric badge rather
   than a state indicator. The icon disambiguates what the value means
   (flame = kcal, dumbbell = grams of protein). */
.ff-recipe-tags {
    position: absolute;
    bottom: 6px;
    right: 6px;
    display: flex;
    gap: 4px;
    pointer-events: none; /* let clicks fall through to the card button */
    z-index: 1;
}

.ff-recipe-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 1px 8px;
    border-radius: 12px;
    border: 1px solid currentColor;
    background: var(--ff-surface);
    font-size: 0.68rem;
    font-weight: 700;
    line-height: 1.4;
}

.ff-recipe-tag-lowcal    { color: var(--ff-secondary); }
.ff-recipe-tag-hiprotein { color: var(--ff-danger); }

/* --- Recipe favourite heart ---
   Pinned to the top-right corner of the card (position: absolute anchors to
   the card's position: relative context). Nutrition tags now occupy the
   bottom-right, so neither element collides. Empty heart at rest, filled red
   when favourited. Tapping it toggles favourite only — the markup stops the
   click from bubbling to the card. */
.ff-recipe-fav {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 32px;
    height: 32px;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: var(--ff-muted);
    font-size: 1.05rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: color 0.12s ease, background 0.12s ease, transform 0.08s ease;
    z-index: 1;
}

.ff-recipe-fav:hover { background: rgba(0,0,0,0.05); color: var(--ff-danger); }
.ff-recipe-fav:active { transform: scale(0.9); }
.ff-recipe-fav.active { color: var(--ff-danger); }

/* Fridgeful built-in recipe badge — overlaid on the top-left corner of the
   recipe thumbnail. Two-tone monogram: capital F is white, lowercase f is the
   logo's pale-teal accent matching "ful" in the header wordmark. Thumb is the
   position:relative context; its overflow is visible so the badge can
   protrude slightly beyond the rounded corner. */
.ff-recipe-builtin-badge {
    position: absolute;
    top: 4px;
    left: 6px;
    border-radius: 50%;
    font-size: 1rem;
    line-height: 1.2;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    letter-spacing: -0.03em;
    user-select: none;
    z-index: 1;
}

.ff-recipe-builtin-badge span:first-child { color: #fff; }
.ff-recipe-builtin-badge span:last-child  { color: var(--ff-primary-pale); font-size: 15px; }

/* Detail-page header heart uses the same base size as ff-recipe-close,
   which is the sibling button it sits next to in the title row. The base
   .ff-recipe-fav is position:absolute (it pins to a card corner on the list
   page); here it's a normal flex child in the title row, so reset to static
   and clear the corner offsets, and stop it from shrinking like its siblings.
   Unlike the list-page heart (transparent over the thumbnail), the header
   heart always shows a grey circle. It lives at the end of the servings row;
   margin-left:auto pushes it to the far right, away from the stepper. */
.ff-recipe-fav-header {
    position: static;
    top: auto;
    right: auto;
    flex-shrink: 0;
    margin-left: auto;
    width: 36px;
    height: 36px;
    background: var(--ff-surface);
    line-height: 1;
}

/* Always-on circle means hover/focus just deepen the grey rather than fading
   one in — and we suppress the UA focus ring (the stray orange outline) in
   favour of that subtle background shift. --ff-border (not --ff-bg, which is
   the page colour and would make the circle vanish) is the darker shade. */
/* Grow the whole button (circle + heart together) on hover so the heart never
   spills past its circle, and darken the circle. transform-origin:center keeps
   the growth even — scaling the icon alone let it drift out of the container. */
.ff-recipe-fav-header {
    transform-origin: center center;
}

.ff-recipe-fav-header:hover,
.ff-recipe-fav-header:focus,
.ff-recipe-fav-header:focus-visible {
    background: var(--ff-border);
    transform: scale(1.12);
    outline: none;
}

/* FontAwesome's heart glyph carries extra space below its lower point, so
   flex centring leaves it sitting a hair high — nudge it down to optically
   centre it in the circle. */
.ff-recipe-fav-header i {
    display: block;
    line-height: 1;
    transform: translateY(1.5px);
}

/* Optional count pill inside the "Favourites" filter chip. Sized to match
   .ff-segmented-pill so it reads as the same kind of in-control counter. */
.ff-filter-btn-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.25rem;
    padding: 0 0.4rem;
    margin-left: 0.35rem;
    border-radius: 999px;
    background: rgba(0,0,0,0.08);
    color: inherit;
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1.4;
}

.ff-filter-btn.active .ff-filter-btn-count {
    background: rgba(255,255,255,0.25);
}

/* On very narrow phones (< 375 px) collapse the Low calorie / High protein
   chip labels down to icon-only so all three chips fit on one row without
   horizontal scrolling. The Favourites label is intentionally left intact
   because it has the count badge alongside it and benefits from the context. */
@media (max-width: 375px) { /* --ff-mobile-medium */
    .ff-filter-label,
    .ff-tag-label {
        display: none;
    }
}

/* --- Recipe detail page --- */
.ff-recipe-hero {
    position: relative;
    width: 100%;
    height: 220px;
    border-radius: 12px;
    overflow: hidden;
    margin-bottom: 0.875rem;
    background: var(--ff-bg);
}

.ff-recipe-hero img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.ff-recipe-hero-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 3rem;
    color: var(--ff-muted);
    background: linear-gradient(135deg, #FEF0D8 0%, #D8EFF8 100%);
}

/* --- Recipe nutrition (kcal + macro split bar) --- */
.ff-recipe-kcal {
    text-align: center;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--ff-muted);
    margin: 0 0 0.5rem;
}

.ff-macro-bar {
    display: flex;
    width: 100%;
    height: 6px;
    border-radius: 3px;
    overflow: hidden;
    background: var(--ff-border);
    margin-bottom: 0.4rem;
}

.ff-macro-seg { height: 100%; }
.ff-macro-carbs   { background: var(--ff-warning); }
.ff-macro-fat     { background: var(--ff-primary-light); }
.ff-macro-protein { background: var(--ff-danger);  }

.ff-macro-legend {
    display: flex;
    justify-content: space-between;
    margin-bottom: 0.9rem;
    font-size: 0.85rem;
    font-weight: 600;
    font-style: italic;
}

.ff-macro-label { display: inline-flex; align-items: center; gap: 0.3rem; }
.ff-macro-carbs-label   { color: var(--ff-warning); }
.ff-macro-fat-label     { color: var(--ff-primary-light); }
.ff-macro-protein-label { color: var(--ff-danger); }

.ff-macro-meta {
    color: var(--ff-muted);
    font-style: normal;
    font-weight: 500;
    font-size: 0.78rem;
    margin-left: 0.15rem;
}

.ff-recipe-title-block { margin-bottom: 1rem; }

.ff-recipe-title-row {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    margin-bottom: 0.15rem;
}

.ff-recipe-title-row .ff-recipe-title {
    flex: 1;
    margin-bottom: 0;
}

.ff-recipe-close {
    flex-shrink: 0;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: none;
    background: var(--ff-surface);
    color: var(--ff-muted);
    font-size: 0.95rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 1px 4px rgba(0,0,0,0.08);
    transition: background 0.15s ease, color 0.15s ease;
}

.ff-recipe-close:hover {
    background: var(--ff-bg);
    color: var(--ff-text);
}

.ff-recipe-title {
    font-size: 1.5rem;
    font-weight: 700;
    margin: 0 0 0.25rem;
    color: var(--ff-text);
}

.ff-recipe-meta {
    margin: 0 0 0.15rem;
    color: var(--ff-text);
    font-size: 0.95rem;
    font-weight: 600;
}

.ff-recipe-description {
    margin: 0;
    color: var(--ff-muted);
    font-size: 0.85rem;
    line-height: 1.4;
}

/* --- Segmented control (Ingredients / Steps) --- */
.ff-segmented {
    display: flex;
    gap: 0;
    margin-bottom: 1rem;
    background: var(--ff-bg);
    border: 1.5px solid var(--ff-border);
    border-radius: 22px;
    padding: 3px;
}

.ff-segmented-btn {
    flex: 1;
    padding: 7px 14px;
    border-radius: 18px;
    border: none;
    background: transparent;
    color: var(--ff-muted);
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.15s ease;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}

.ff-segmented-btn:first-child {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    border-right: 1.5px solid var(--ff-border);
}

.ff-segmented-btn:first-child.active {
    border-right-color: rgba(255, 255, 255, 0.2);
}

.ff-segmented-btn:last-child {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}

.ff-segmented-btn.active {
    background: var(--ff-primary);
    color: #fff;
    box-shadow: 0 1px 3px rgba(0,0,0,0.15);
}

.ff-segmented-pill {
    background: rgba(255, 255, 255, 0.25);
    color: inherit;
    padding: 1px 7px;
    border-radius: 10px;
    font-size: 0.65rem;
    font-weight: 700;
}

.ff-segmented-btn:not(.active) .ff-segmented-pill {
    background: #FDE8E8;
    color: #A02828;
}

/* --- Ingredient rows --- */
.ff-ingredient-list { display: flex; flex-direction: column; gap: 0.5rem; }

.ff-ingredient-row {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.625rem 0.75rem;
    background: var(--ff-surface);
    border-radius: 10px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.05);
}

.ff-ingredient-emoji {
    font-size: 1.4rem;
    width: 32px;
    text-align: center;
    flex-shrink: 0;
}

.ff-ingredient-body { flex: 1; min-width: 0; }

.ff-ingredient-name {
    margin: 0;
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--ff-text);
}

.ff-ingredient-notes {
    margin: 0;
    font-size: 0.75rem;
    color: var(--ff-muted);
}

.ff-ingredient-qty {
    font-size: 0.85rem;
    color: var(--ff-text);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}

.ff-ingredient-missing,
.ff-ingredient-insufficient { opacity: 0.6; }
.ff-ingredient-missing .ff-ingredient-name,
.ff-ingredient-insufficient .ff-ingredient-name { text-decoration: line-through; }

/* Non-required spices: dimmed by default to signal "the recipe still works
   without these". Cumulative with .ff-ingredient-missing/insufficient when
   stacked, which is fine — both push opacity in the same direction. */
.ff-ingredient-optional { opacity: 0.55; }

/* --- Recipe steps --- */
.ff-step-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
}

.ff-step-row {
    display: flex;
    gap: 0.75rem;
    padding: 0.75rem 0.875rem;
    background: var(--ff-surface);
    border-radius: 10px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.05);
}

.ff-step-number {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--ff-primary);
    color: #fff;
    font-weight: 700;
    font-size: 0.85rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

.ff-step-instruction {
    margin: 0;
    font-size: 0.9rem;
    line-height: 1.45;
    color: var(--ff-text);
    flex: 1;
}

/* Process-step component rows on the recipe view */
.ff-step-component {
    align-items: flex-start;
}

.ff-step-component-body {
    flex: 1;
    min-width: 0;
}

.ff-step-component-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    cursor: pointer;
    user-select: none;
    padding: 0.1rem 0;
}

.ff-step-component-title {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--ff-text);
    line-height: 1.45;
}

.ff-step-chevron {
    font-size: 0.75rem;
    color: var(--ff-muted);
    flex-shrink: 0;
}

.ff-step-instruction-expanded {
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--ff-border);
}

.ff-recipe-empty-tab {
    text-align: center;
    color: var(--ff-muted);
    padding: 1.5rem 0;
    font-size: 0.85rem;
}

/* --- Shopping list ---------------------------------------------------------
   The shopping page reuses the pantry's card chrome (.ff-card, .ff-card-icon,
   .ff-card-icon-*) so locations look familiar. Only the right-hand "Need X g"
   pill and the small summary line above the list are new. */
.ff-shopping-summary {
    font-size: 0.85rem;
    color: var(--ff-muted);
    margin: 0 0 0.5rem;
}

/* Primary quantity pill — emphasises the shortfall (what to buy). The
   accent colour reuses --ff-primary so it ties back to the brand. */
.ff-shopping-need {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 3px 10px;
    border-radius: 14px;
    background: var(--ff-primary);
    color: #fff;
    font-size: 0.78rem;
    font-weight: 700;
    line-height: 1.3;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* "Need" rendered without a number — used for ingredients flagged as
   "to taste" (e.g. salt) when the user has zero in stock. The outlined
   treatment signals the qualitative-not-quantitative nature. */
.ff-shopping-need-totaste {
    background: transparent;
    color: var(--ff-primary);
    border: 1.5px solid var(--ff-primary);
}

/* Smaller line under the need-pill showing existing stock when the user
   has SOME but not enough. Hidden when pantry is empty so we don't say
   "Have 0". */
.ff-shopping-have {
    font-size: 0.7rem;
    color: var(--ff-muted);
    line-height: 1.3;
    font-variant-numeric: tabular-nums;
}

/* --- Card actions slide panel ------------------------------------------------
   <CardActions> renders this. A chevron toggle sits on the right of the card;
   tapping it slides the actions panel in over the card body. The panel has a
   gradient on its left edge so the body text underneath fades through softly
   rather than meeting a hard edge. */
.ff-actions {
    position: relative;
    flex-shrink: 0;
    display: flex;
    align-items: center;
}

.ff-actions-toggle {
    width: 28px;
    height: 40px;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--ff-muted);
    font-size: 0.95rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    z-index: 2;
    transition: color 0.15s ease;
}
.ff-actions-toggle:hover,
.ff-actions-toggle:focus,
.ff-actions-toggle:active { color: var(--ff-muted); background: transparent; box-shadow: none; outline: none; }

.ff-actions-panel {
    position: absolute;
    right: 100%;
    top: 50%;
    display: flex;
    align-items: center;
    gap: 0.375rem;
    padding: 4px 8px 4px 4px;
    background: var(--ff-surface);
    border-radius: 8px;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transform: translate(calc(100% + 28px), -50%);
    transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.18s ease;
    z-index: 1;
}

.ff-actions-open .ff-actions-panel {
    opacity: 1;
    pointer-events: auto;
    transform: translate(0, -50%);
}

/* The action buttons (.ff-cal-btn, .ff-plus-btn, .ff-bin-btn, .ff-qty-btn)
   each carry their own .375rem margin-left for legacy contexts. Inside the
   slide panel that stacks on top of the panel's `gap`, producing uneven
   spacing — zero them so `gap` is the single source of truth. */
.ff-actions-panel .ff-cal-btn,
.ff-actions-panel .ff-qty-btn,
.ff-actions-panel .ff-bin-btn,
.ff-actions-panel .ff-plus-btn { margin: 0; }

/* Thin variant for grouped-row contexts where vertical room is tight. Pair
   with Size="sm" on the action buttons (40x24) so the panel hugs the row
   without changing its height. */
.ff-actions-compact .ff-actions-toggle {
    height: 24px;
    /* width/font-size inherited so the chevron icon matches the regular toggle
       — only the click target shortens to keep the grouped row compact. */
}
.ff-actions-compact .ff-actions-panel {
    padding: 2px 6px 2px 4px;
    gap: 0.25rem;
}
/* PlusIconButton has no 40x24 variant — its sm is 40x40. Normalise it down to
   match cal/qty/bin (40x24) when used inside a compact panel. */
.ff-actions-compact .ff-plus-btn { height: 24px; width: 40px; font-size: 0.8rem; }

/* One-shot discoverability hint: panel springs in to the edge, then wobbles
   right→left a few times like a spring settling, holds, then slides out.
   All wobble values stay >= 0 so the panel never pushes deeper into the
   card body — the rest position (translate(0)) is the leftmost point.
   ease-out prevents the easing curve from overshooting the keyframe targets. */
@keyframes ff-actions-hint {
    0%   { transform: translate(calc(100% + 28px), -50%); opacity: 0; }
    10%  { transform: translate(calc(100% + 28px), -50%); opacity: 0; }
    26%  { transform: translate(0,   -50%);               opacity: 1; }
    36%  { transform: translate(14%, -50%);               opacity: 1; }
    46%  { transform: translate(0,   -50%);               opacity: 1; }
    54%  { transform: translate(7%,  -50%);               opacity: 1; }
    62%  { transform: translate(0,   -50%);               opacity: 1; }
    68%  { transform: translate(3%,  -50%);               opacity: 1; }
    74%  { transform: translate(0,   -50%);               opacity: 1; }
    85%  { transform: translate(0,   -50%);               opacity: 1; }
    100% { transform: translate(calc(100% + 28px), -50%); opacity: 0; }
}

.ff-actions-hint:not(.ff-actions-open) .ff-actions-panel {
    animation: ff-actions-hint 2.4s ease-out 0.4s 1;
}

/* Soft fade between the body text and the leftmost button so the panel doesn't
   meet the underlying content with a hard edge. Sits just to the LEFT of the
   panel and slides with it. */
.ff-actions-panel::before {
    content: '';
    position: absolute;
    right: 100%;
    top: 0;
    bottom: 0;
    width: 24px;
    background: linear-gradient(to right, transparent, var(--ff-surface));
    pointer-events: none;
}

/* When the panel is closed, hide the trailing fade too so it isn't smeared
   off-screen during the slide-out. */
.ff-actions:not(.ff-actions-open) .ff-actions-panel::before { opacity: 0; }

/* ============================================================
   Settings — Premium banner
   ============================================================ */

.ff-premium-banner {
    background: linear-gradient(135deg, #7a5c00 0%, #b8860b 35%, #d4a017 60%, #b8860b 80%, #7a5c00 100%);
    border-radius: 14px;
    padding: 1.25rem 1.25rem 1rem;
    margin-bottom: 1rem;
    box-shadow: 0 4px 16px rgba(180, 130, 0, 0.35), inset 0 1px 0 rgba(255,230,100,0.25);
    color: #fff5cc;
    position: relative;
    overflow: hidden;
}

.ff-premium-banner::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(255,230,100,0.08) 0%, transparent 60%);
    pointer-events: none;
}

.ff-premium-banner-header {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    margin-bottom: 0.6rem;
}

.ff-premium-banner-title {
    font-size: 1rem;
    font-weight: 700;
    text-align: center;
    color: #fff8d6;
    text-shadow: 0 1px 3px rgba(0,0,0,0.3);
    line-height: 1.3;
}

.ff-premium-banner-star {
    font-size: 0.9rem;
    color: #ffe066;
    flex-shrink: 0;
    filter: drop-shadow(0 1px 2px rgba(0,0,0,0.25));
}

.ff-premium-banner-subtitle {
    font-size: 0.8rem;
    color: rgba(255,240,170,0.85);
    text-align: center;
    margin: 0 0 0.875rem;
}

.ff-premium-banner-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
}

.ff-premium-banner-list li {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    background: rgba(0,0,0,0.18);
    border: 1px solid rgba(255,220,80,0.2);
    border-radius: 10px;
    padding: 0.6rem 0.875rem;
}

.ff-premium-banner-list li > i {
    font-size: 1rem;
    color: #ffe066;
    flex-shrink: 0;
    margin-top: 0.15rem;
    filter: drop-shadow(0 1px 2px rgba(0,0,0,0.2));
}

.ff-premium-banner-list li > div {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.ff-premium-banner-list li strong {
    font-size: 0.88rem;
    font-weight: 700;
    color: #fff8d6;
    display: block;
}

.ff-premium-banner-list li span {
    font-size: 0.78rem;
    color: rgba(255,240,170,0.8);
    line-height: 1.35;
}

/* Non-premium variant — gold border, pale interior */
.ff-premium-banner-inactive {
    background: linear-gradient(135deg, #fdf8ec 0%, #fef4d8 100%);
    box-shadow: 0 2px 8px rgba(180,130,0,0.12);
    color: #6b4f00;
}

.ff-premium-banner-inactive::before { display: none; }

.ff-premium-banner-inactive .ff-premium-banner-title {
    color: #7a5800;
}

.ff-premium-banner-inactive .ff-premium-banner-subtitle {
    color: rgba(100, 70, 0, 0.65);
}

.ff-premium-banner-inactive .ff-premium-banner-star {
    color: #c8960a;
    filter: none;
}

.ff-premium-banner-inactive .ff-premium-banner-list li {
    background: rgba(180,130,0,0.06);
    border-color: rgba(180,130,0,0.18);
}

.ff-premium-banner-inactive .ff-premium-banner-list li > i {
    color: #b8860b;
    filter: none;
}

.ff-premium-banner-inactive .ff-premium-banner-list li strong {
    color: #6b4f00;
}

.ff-premium-banner-inactive .ff-premium-banner-list li span {
    color: rgba(100, 70, 0, 0.65);
}

.ff-premium-banner-inactive .ff-premium-coming-soon {
    color: rgba(100, 70, 0, 0.45);
}

.ff-premium-upgrade-footer {
    display: flex;
    justify-content: center;
    margin-top: 1rem;
}

.ff-premium-upgrade-btn {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.55rem 1.75rem;
    background: linear-gradient(135deg, #d4a017 0%, #b8860b 60%, #9a6f00 100%);
    color: #fff8d6;
    border: 1px solid #ffe066;
    border-radius: 20px;
    font-size: 0.85rem;
    font-weight: 700;
    cursor: pointer;
    box-shadow: 0 2px 6px rgba(0,0,0,0.18), inset 0 1px 0 rgba(255,230,100,0.25);
    transition: opacity 0.15s ease;
}

.ff-premium-upgrade-btn:hover  { opacity: 0.88; }
.ff-premium-upgrade-btn:active { opacity: 0.75; }

.ff-premium-coming-soon {
    font-size: 0.7rem;
    font-weight: 500;
    font-style: italic;
    color: rgba(255,240,170,0.65);
    vertical-align: middle;
}

/* Premium advert — reusable promo (PremiumAdvertCard) that slots between list
   items on the Pantry and Recipes pages. Shares the gold treatment of the
   Settings upgrade button but in a compact, full-width card shape that lines up
   with the surrounding .ff-card / .ff-recipe-card items. */
.ff-premium-advert {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    text-align: left;
    background: linear-gradient(135deg, #fdf8ec 0%, #fef4d8 100%);
    border: 1px solid rgba(180,130,0,0.18);
    border-radius: 12px;
    padding: 0.7rem 0.875rem;
    margin-bottom: 0.625rem;
    color: #6b4f00;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(180,130,0,0.12);
    transition: box-shadow 0.15s ease, transform 0.1s ease;
}

.ff-premium-advert:hover  { box-shadow: 0 3px 12px rgba(180,130,0,0.2); }
.ff-premium-advert:active { transform: scale(0.995); }

.ff-premium-advert-icon {
    width: 38px;
    height: 38px;
    border-radius: 9px;
    background: rgba(180,130,0,0.08);
    border: 1px solid rgba(180,130,0,0.18);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.ff-premium-advert-icon i {
    font-size: 1rem;
    color: #b8860b;
}

.ff-premium-advert-body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
}

.ff-premium-advert-title {
    font-size: 0.9rem;
    font-weight: 700;
    color: #7a5800;
}

.ff-premium-advert-subtitle {
    font-size: 0.76rem;
    color: rgba(100, 70, 0, 0.65);
    line-height: 1.3;
}

.ff-premium-advert-chevron {
    font-size: 0.85rem;
    color: rgba(100, 70, 0, 0.5);
    flex-shrink: 0;
}

/* ============================================================
   Settings page
   ============================================================ */

.ff-settings-section {
    background: var(--ff-surface);
    border-radius: 12px;
    padding: 1rem 1.25rem 1.25rem;
    margin-bottom: 1rem;
    box-shadow: 0 1px 4px rgba(0,0,0,0.07);
}

.ff-settings-section-title {
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--ff-muted);
    margin: 0 0 1rem;
}

/* Label + stepper on one row */
.ff-settings-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.25rem 0 0.625rem;
}

.ff-settings-label {
    font-size: 0.95rem;
    font-weight: 500;
    color: var(--ff-text);
}

.ff-settings-description {
    font-size: 0.8rem;
    color: var(--ff-muted);
    line-height: 1.45;
    margin: 0 0 1rem;
}

/* Divider between preference rows */
.ff-settings-divider {
    border: none;
    border-top: 1px solid var(--ff-border);
    margin: 0.75rem 0;
}

/* Toggle row — label+description on the left, switch on the right */
.ff-settings-toggle-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    padding: 0.25rem 0;
}

.ff-settings-switch .form-check-input {
    width: 2.75em;
    height: 1.5em;
    cursor: pointer;
    border-color: var(--ff-border);
    flex-shrink: 0;
}

.ff-settings-switch .form-check-input:checked {
    background-color: var(--ff-primary);
    border-color: var(--ff-primary);
}

.ff-settings-switch .form-check-input:focus {
    box-shadow: 0 0 0 0.2rem rgba(var(--ff-primary-rgb, 76, 175, 80), 0.25);
}

/* Feedback pill — success / error */
.ff-settings-feedback {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.82rem;
    font-weight: 500;
    padding: 0.375rem 0.875rem;
    border-radius: 8px;
    margin-bottom: 1rem;
}

.ff-settings-feedback-success {
    background: #E8F5EA;
    color: var(--ff-success);
}

.ff-settings-feedback-error {
    background: #FDE8E8;
    color: var(--ff-danger);
}

/* Save button row */
.ff-settings-footer {
    display: flex;
    justify-content: flex-end;
}

.ff-settings-save-btn {
    padding: 0.6rem 1.75rem;
    background: var(--ff-primary);
    color: #fff;
    border: none;
    border-radius: 10px;
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.1s ease;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.ff-settings-save-btn:hover  { background: var(--ff-primary-light); }
.ff-settings-save-btn:active { background: var(--ff-primary-dark); transform: scale(0.97); }
.ff-settings-save-btn:disabled { opacity: 0.6; cursor: not-allowed; transform: none; }

/* ============================================================
   Add recipe sheet (dev-only)
   ============================================================ */

/* The "Open Add Recipe sheet" launcher above the Recipes page. Re-uses the
   dashed dev-button look from the login screen so it reads as a dev tool. */
.ff-recipes-dev-btn {
    display: block;
    width: 100%;
    margin: 0 0 0.75rem;
    border: 1px dashed var(--ff-border);
    background: transparent;
    color: var(--ff-muted);
    padding: 0.55rem 0.75rem;
    font-weight: 600;
    font-size: 0.85rem;
    border-radius: 8px;
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease;
}
.ff-recipes-dev-btn:hover:not(:disabled) { border-color: var(--ff-primary); color: var(--ff-primary); }
.ff-recipes-dev-btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* Multi-input rows inside the recipe form. The .mb-3 field children are
   themselves flex items so they all share the row width evenly. */
.ff-recipe-form-row {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}
.ff-recipe-form-row > * { flex: 1 1 0; min-width: 0; }

/* Section wrapper for the dynamic ingredient/step lists. */
.ff-recipe-form-section { margin-top: 1.25rem; }

.ff-recipe-form-section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 0.5rem;
}

.ff-recipe-form-empty {
    color: var(--ff-muted);
    font-size: 0.85rem;
    font-style: italic;
    margin: 0.25rem 0;
}

/* One ingredient row: food autocomplete | qty+unit | notes | bin */
.ff-recipe-ingredient-row {
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1fr) auto;
    gap: 0.5rem;
    align-items: center;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--ff-border);
}
.ff-recipe-ingredient-row:last-child { border-bottom: none; }

.ff-recipe-ingredient-qty {
    display: flex;
    align-items: center;
    gap: 0.35rem;
}
.ff-recipe-ingredient-unit {
    font-size: 0.78rem;
    color: var(--ff-muted);
    white-space: nowrap;
}

.ff-recipe-ingredient-notes { font-size: 0.85rem; }

/* Below 520px the columns get too cramped — switch to a two-row grid:
   row 1 = food picker | bin; row 2 = qty | notes. */
@media (max-width: 520px) {
    .ff-recipe-ingredient-row {
        grid-template-columns: minmax(0, 1fr) auto;
    }
    .ff-recipe-ingredient-qty,
    .ff-recipe-ingredient-notes {
        grid-column: span 2;
    }
}

/* Step row: number badge | textarea | bin. */
.ff-recipe-step-row {
    display: grid;
    grid-template-columns: 32px minmax(0, 1fr) auto;
    gap: 0.5rem;
    align-items: start;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--ff-border);
}
.ff-recipe-step-row:last-child { border-bottom: none; }

.ff-recipe-step-num {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--ff-primary);
    color: #fff;
    font-weight: 700;
    font-size: 0.85rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-top: 4px;
}

.ff-recipe-step-body {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    min-width: 0;
}

/* Step type toggle (Step / Component) in add/edit sheet */
.ff-step-type-toggle {
    display: flex;
    border-radius: 6px;
    overflow: hidden;
    border: 1px solid var(--ff-border);
    width: fit-content;
}

.ff-step-type-toggle button {
    flex: 1;
    padding: 0.2rem 0.65rem;
    border: none;
    background: transparent;
    font-size: 0.78rem;
    color: var(--ff-muted);
    cursor: pointer;
    white-space: nowrap;
}

.ff-step-type-toggle button + button {
    border-left: 1px solid var(--ff-border);
}

.ff-step-type-toggle button.active {
    background: var(--ff-primary);
    color: #fff;
}

.ff-step-component-picker {
    display: flex;
    align-items: stretch;
    gap: 0.375rem;
}

.ff-step-component-select {
    font-size: 0.875rem;
    flex: 1;
    min-width: 0;
}

.ff-step-rename-btn,
.ff-step-rename-save,
.ff-step-rename-cancel {
    flex-shrink: 0;
    border: 1px solid var(--ff-border);
    background: var(--ff-surface);
    color: var(--ff-muted);
    border-radius: 6px;
    padding: 0 0.55rem;
    font-size: 0.8rem;
    cursor: pointer;
}

.ff-step-rename-btn:hover {
    color: var(--ff-primary);
    border-color: var(--ff-primary);
}

.ff-step-rename-input {
    font-size: 0.875rem;
}

.ff-step-rename-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.375rem;
}

.ff-step-rename-actions button {
    padding: 0.25rem 0.75rem;
    font-size: 0.8rem;
}

.ff-step-rename-save {
    color: #fff;
    background: var(--ff-primary);
    border-color: var(--ff-primary);
}

/* Read-only preview of the selected component's instruction. */
.ff-step-component-preview {
    margin: 0;
    padding: 0.5rem 0.625rem;
    background: var(--ff-bg, #f6f7f9);
    border-left: 3px solid var(--ff-border);
    border-radius: 4px;
    font-size: 0.825rem;
    line-height: 1.45;
    color: var(--ff-muted);
    white-space: pre-wrap;
}

.ff-step-new-title {
    font-size: 0.875rem;
}

/* --- Hand-rolled UI components (Blazorise replacements) --- */

/* NumberInput: hide the native number spinners so it reads like Blazorise's
   plain numeric field (which rendered no stepper chrome). */
.ff-number::-webkit-outer-spin-button,
.ff-number::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
.ff-number {
    -moz-appearance: textfield;
}

/* Autocomplete: the menu is a Bootstrap .dropdown-menu anchored to the input,
   sized to the field width and scrollable for long result lists. */
.ff-autocomplete {
    position: relative;
}
.ff-autocomplete-menu {
    width: 100%;
    min-width: 0;
    max-height: 240px;
    overflow-y: auto;
}

