/*
 * components.css — mobile-first component layer for the client reskin.
 *
 * Built from the patterns that repeat across Jenny's mockups (docs/mockups/).
 * Consumes tokens.css; load that first.
 *
 * THIS FILE CHANGES NOTHING ON ITS OWN. Every selector is a `.ds-` class that
 * does not exist anywhere in the codebase (verified 2026-08-06). There are no
 * element selectors and no overrides of existing classes, so nothing renders
 * differently until a screen is deliberately rewritten to use these. That is
 * the point: the design system ships inert, and risk is taken one screen at a
 * time rather than all at once.
 *
 * Mobile-first: base styles are the phone; `min-width` queries add larger
 * screens. Do not add `max-width` queries here — style.css already has 80 of
 * them and that is the problem this layer exists to escape.
 *
 * Added 2026-08-06.
 *
 * 2026-09-03: the `.ds-sheet*` modal moved to components/modal.css, which grew
 * it into the popup component (`.ds-modal*`). It was unused here, so this is a
 * move rather than a deprecation — there is one modal component, not two.
 */


/* ===========================================================================
 * Layout
 * ======================================================================== */

.ds-page {
    background: var(--ds-bg);
    padding: var(--ds-gutter);
    font-family: var(--ds-font);
    color: var(--ds-text);
    font-size: var(--ds-size-body);
    line-height: var(--ds-leading-normal);
}

.ds-container {
    width: 100%;
    max-width: var(--ds-page-max);
    margin-inline: auto;
}

/* Vertical rhythm. `.ds-stack > * + *` avoids margin collapse surprises. */
.ds-stack > * + * {
    margin-top: var(--ds-space-4);
}

.ds-stack-sm > * + * {
    margin-top: var(--ds-space-2);
}


/* ===========================================================================
 * Type
 * ======================================================================== */

.ds-display {
    font-size: var(--ds-size-display);
    font-weight: var(--ds-weight-bold);
    line-height: var(--ds-leading-tight);
    color: var(--ds-text);
    margin: 0;
}

.ds-h1 {
    font-size: var(--ds-size-h1);
    font-weight: var(--ds-weight-bold);
    line-height: var(--ds-leading-tight);
    color: var(--ds-text);
    margin: 0;
}

.ds-h2 {
    font-size: var(--ds-size-h2);
    font-weight: var(--ds-weight-bold);
    line-height: var(--ds-leading-snug);
    color: var(--ds-text);
    margin: 0;
}

.ds-h3 {
    font-size: var(--ds-size-h3);
    font-weight: var(--ds-weight-semibold);
    line-height: var(--ds-leading-snug);
    color: var(--ds-text);
    margin: 0;
}

/* "TODAY'S PLAN", "THIS WEEK" */
.ds-label {
    font-size: var(--ds-size-label);
    font-weight: var(--ds-weight-bold);
    letter-spacing: var(--ds-tracking-label);
    text-transform: uppercase;
    color: var(--ds-text);
    margin: 0;
}

.ds-muted  { color: var(--ds-text-muted); }
.ds-subtle { color: var(--ds-text-subtle); }
.ds-sm     { font-size: var(--ds-size-sm); }
.ds-xs     { font-size: var(--ds-size-xs); }


/* ===========================================================================
 * Card
 * ======================================================================== */

.ds-card {
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    box-shadow: var(--ds-shadow-md);
    padding: var(--ds-space-4);
    overflow: hidden;
}

.ds-card-flush {
    padding: 0;
}

/*
 * Meal cards on Food Log carry a coloured left bar identifying the meal.
 * Set --ds-accent per card: style="--ds-accent: var(--ds-amber)".
 */
.ds-card-accent {
    border-left: 4px solid var(--ds-accent, var(--ds-teal));
}

/* The teal→blue gradient panel used for Daily Progress. */
.ds-card-gradient {
    background: var(--ds-gradient);
    border: 0;
    color: var(--ds-text-invert);
}

.ds-card-gradient .ds-h2,
.ds-card-gradient .ds-label {
    color: var(--ds-text-invert);
}


/* ===========================================================================
 * Buttons
 *
 * min-height is the 44px floor. Buttons are inline-flex so the label centres
 * — foundation.css deliberately avoids min-height on inline-block anchors for
 * exactly this reason, and these classes solve it properly.
 * ======================================================================== */

.ds-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--ds-space-2);
    min-height: var(--ds-tap);
    padding: var(--ds-space-2) var(--ds-space-5);
    border: 1px solid transparent;
    border-radius: var(--ds-radius-pill);
    font-family: var(--ds-font);
    font-size: var(--ds-size-body);
    font-weight: var(--ds-weight-semibold);
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: opacity 0.15s ease, transform 0.1s ease;
}

.ds-btn:active {
    transform: scale(0.98);
}

.ds-btn:focus-visible {
    outline: 2px solid var(--ds-blue);
    outline-offset: 2px;
}

.ds-btn[disabled],
.ds-btn.is-disabled {
    opacity: 0.5;
    pointer-events: none;
}

/*
 * Solid pink, not the teal gradient this used to be.
 *
 * Changed 2026-09-03. Nothing referenced `.ds-btn` yet, so correcting it cost
 * nothing — and it mattered, because the shipped dashboard's primary action
 * (`.ds-hero-cta`, "Click here for more programs") is solid `--ds-pink`, and
 * Jenny's popup mockups draw every Save button pink. A design system whose
 * "primary" disagreed with the only primary button in the product would have
 * been inherited by every screen that opted in after this one.
 *
 * The teal gradient is still right for a *surface* — the Daily Calories card
 * uses it — so it keeps a variant rather than being deleted.
 */
.ds-btn-primary {
    background: var(--ds-pink);
    color: var(--ds-text-invert);
    box-shadow: 0 4px 14px rgba(236, 42, 107, 0.32);
}

.ds-btn-primary:hover,
.ds-btn-primary:focus-visible {
    background: var(--ds-pink-dark);
    color: var(--ds-text-invert);
    box-shadow: 0 8px 22px rgba(236, 42, 107, 0.42);
}

.ds-btn-gradient {
    background: var(--ds-gradient);
    color: var(--ds-text-invert);
}

.ds-btn-secondary {
    background: var(--ds-surface);
    border-color: var(--ds-border);
    color: var(--ds-text);
}

.ds-btn-ghost {
    background: transparent;
    color: var(--ds-blue);
}

.ds-btn-block {
    display: flex;
    width: 100%;
}

/* Circular icon button — the +/− steppers and chevrons. */
.ds-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--ds-tap);
    height: var(--ds-tap);
    padding: 0;
    border: 1px solid var(--ds-border);
    border-radius: 50%;
    background: var(--ds-surface);
    color: var(--ds-text);
    font-size: var(--ds-size-h2);
    line-height: 1;
    cursor: pointer;
}

.ds-icon-btn-primary {
    background: var(--ds-teal);
    border-color: var(--ds-teal);
    color: var(--ds-text-invert);
}


/* ===========================================================================
 * Chips and tags
 * ======================================================================== */

/* Selectable quantity chips — "4 fl oz", "8 fl oz". */
.ds-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: var(--ds-tap);
    padding: var(--ds-space-2) var(--ds-space-4);
    border: 1px solid transparent;
    border-radius: var(--ds-radius-pill);
    background: var(--ds-bg);
    color: var(--ds-text-muted);
    font-size: var(--ds-size-sm);
    font-weight: var(--ds-weight-medium);
    cursor: pointer;
}

.ds-chip.is-selected {
    background: var(--ds-surface);
    border-color: var(--ds-teal);
    color: var(--ds-teal-dark);
    font-weight: var(--ds-weight-semibold);
}

/* Non-interactive status pill — "I am fasting". Tinted via --ds-accent-tint. */
.ds-tag {
    display: inline-block;
    padding: var(--ds-space-1) var(--ds-space-3);
    border-radius: var(--ds-radius-pill);
    background: var(--ds-accent-tint, var(--ds-teal-tint));
    color: var(--ds-accent, var(--ds-teal-dark));
    font-size: var(--ds-size-xs);
    font-weight: var(--ds-weight-medium);
}


/* ===========================================================================
 * Search pill
 *
 * A 44px pill with a magnifier, wrapping a borderless input. Promoted here
 * from the Workouts popup's `.ds-media-search` (components/media-grid.css, PR
 * #408); both that popup (a <label class="ds-search"> around its input) and
 * the Recipes page (DataTables' `.dt-search`, given the class on init) use it.
 *
 *   <div class="ds-search"><label for="q">Search</label><input id="q" type="search" placeholder="Search…"></div>
 *
 * The label is for assistive tech only. The glyph is an inline SVG background,
 * not the icon font, so the pill does not depend on which icon CDN a page
 * loads. The input is `16px` absolute, not a token: below that iOS Safari zooms
 * on focus (foundation.css pins form controls to 16px under 768px for the same
 * reason — this matches it above 768 too, so the field does not change size at
 * the breakpoint). `input:focus` is listed so Bootstrap's `.form-control:focus`
 * ring (0,2,0) cannot outrank the reset.
 *
 * Added 2026-09-24 (Recipes R1).
 * ======================================================================== */

.ds-search {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--ds-space-2);
    min-height: var(--ds-tap);
    margin: 0;
    padding: 0 var(--ds-space-4) 0 44px;
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-pill);
    background: var(--ds-surface);
    color: var(--ds-text-muted);
    font-weight: var(--ds-weight-regular);
}

.ds-search::before {
    content: "";
    position: absolute;
    top: 50%;
    left: var(--ds-space-4);
    width: 18px;
    height: 18px;
    transform: translateY(-50%);
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-4-4'/%3E%3C/svg%3E") center / contain no-repeat;
    pointer-events: none;
}

.ds-search:focus-within {
    border-color: var(--ds-teal);
    outline: 2px solid var(--ds-teal);
    outline-offset: 1px;
}

.ds-search label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

.ds-search input,
.ds-search input:focus {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
    height: 42px;
    min-height: 0;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    outline: 0;
    box-shadow: none;
    background: transparent;
    color: var(--ds-text);
    font-family: var(--ds-font);
    font-size: 16px;
    line-height: 1.5;
    -webkit-appearance: none;
    appearance: none;
}

.ds-search input::placeholder {
    color: var(--ds-text-muted);
    opacity: 1;
}

/* The browser's own clear button on type=search would sit inside the pill. */
.ds-search input::-webkit-search-decoration,
.ds-search input::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
}


/* ===========================================================================
 * List rows
 *
 * The task lists on Home: pastel icon chip, title, subtitle, trailing status.
 * ======================================================================== */

.ds-row {
    display: flex;
    align-items: center;
    gap: var(--ds-space-3);
    min-height: var(--ds-tap);
    padding: var(--ds-space-3) 0;
    border-bottom: 1px solid var(--ds-divider);
    text-decoration: none;
    color: inherit;
}

.ds-row:last-child {
    border-bottom: 0;
}

.ds-row-body {
    flex: 1;
    min-width: 0;   /* lets long titles ellipsis instead of forcing overflow */
}

.ds-row-title {
    font-size: var(--ds-size-h3);
    font-weight: var(--ds-weight-semibold);
    color: var(--ds-text);
}

.ds-row-sub {
    font-size: var(--ds-size-sm);
    color: var(--ds-text-muted);
}

.ds-row-trail {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    color: var(--ds-text-subtle);
}

/* Pastel circular icon container. Tint via --ds-accent-tint / --ds-accent. */
.ds-icon-chip {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--ds-accent-tint, var(--ds-teal-tint));
    color: var(--ds-accent, var(--ds-teal));
    font-size: var(--ds-size-h3);
}


/* ===========================================================================
 * Stats
 *
 * The kcal / carbs / fat / protein strip on Food Log, and the metric column
 * on Daily Progress. Scrolls rather than overflowing on narrow screens.
 * ======================================================================== */

.ds-stats {
    display: flex;
    align-items: stretch;
    gap: var(--ds-space-3);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.ds-stat {
    flex: 1 0 auto;
    min-width: 0;
    text-align: center;
}

.ds-stat + .ds-stat {
    border-left: 1px solid var(--ds-divider);
    padding-left: var(--ds-space-3);
}

.ds-stat-value {
    display: block;
    font-size: var(--ds-size-h2);
    font-weight: var(--ds-weight-bold);
    color: var(--ds-text);
    line-height: var(--ds-leading-tight);
}

.ds-stat-label {
    display: block;
    font-size: var(--ds-size-xs);
    color: var(--ds-text-muted);
}


/* ===========================================================================
 * Progress bar
 * ======================================================================== */

.ds-progress {
    height: 6px;
    border-radius: var(--ds-radius-pill);
    background: var(--ds-divider);
    overflow: hidden;
}

.ds-progress-fill {
    display: block;
    height: 100%;
    width: 0;
    border-radius: inherit;
    background: var(--ds-gradient);
    transition: width 0.3s ease;
}


/* ===========================================================================
 * Larger screens
 *
 * The only breakpoint this layer needs so far. Phones get the base styles;
 * tablets and up get a contained page width. The modal component and its
 * own breakpoint moved to components/modal.css on 2026-09-03.
 * ======================================================================== */

@media (min-width: 768px) {

    .ds-page {
        padding: var(--ds-space-6);
    }
}
