/* ══════════════════════════════════════════════════════════════════════
   Recipe library + detail/print + add/edit form page layout
   (Phase 3.1 / 3.2 / 4.1).

   Shared, reusable design-system components (.card, .tag, .elev-*,
   .chip-checkbox, .filter-chip-group, .plate, .no-print,
   .seg/.seg-opt/.radio) live in static/css/base.css alongside the rest of
   the ported "Classical" system - see that file's header comment for why.
   This file holds layout that is specific to these screens only (sidebar
   width, the card grid, the photo placeholder/empty states, the detail
   screen's own shell, and the add/edit form's shell further below) - not
   literal mockup classes, just each page's shell, in the same spirit as
   base.css's .container note.
   ══════════════════════════════════════════════════════════════════════ */

.library-layout {
  max-width: 1280px;
  margin: 0 auto;
  /* Horizontal padding matches .nav's own (var(--space-4), 18.4px) rather
     than var(--space-6) (27.6px) - every custom page-shell class had drifted
     9.2px wider than the nav bar above it, making the content look
     misaligned against it. .container-based pages (login/register/family)
     already matched the nav; this brings the 6 custom shells (this one,
     .recipe-detail, .recipe-form, .dashboard-layout, .planner-layout,
     .shopping-layout) into line with them. Vertical padding is unrelated
     and stays as-is. */
  padding: var(--space-8) var(--space-4);
  display: flex;
  gap: var(--space-8);
}

.library-sidebar {
  width: 220px;
  flex: none;
}

/* The sidebar's only direct child is the filter <form> (library.html) -
   the individual .card-wrapped filter groups (Search, plus one per
   `filter_groups` entry) are its grandchildren, so a `gap` declared on
   `.library-sidebar` itself (the previous version of this rule) never
   applied between them: the cards rendered with 0px between them, merging
   into one block instead of the intended visually-separated cards.
   Verified in a real browser before/after this fix. */
.library-sidebar form {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

.library-sidebar h6 {
  margin: 0 0 var(--space-2);
}

.library-content {
  flex: 1;
  min-width: 0;
}

/* Phase 11.13: the "Sort" <select> (3 options: Title (A-Z)/Newest
   first/Oldest first) is a short-enum dropdown, not free text - per
   ui-design-principles.md §3 it has no reason to stretch to the shared
   `.input { width: 100% }` rule's full-width default, same reasoning as
   base.css's `.role-select`/`.invite-role-select`. Scoped to this page
   (not widening `.role-select` itself) per the project convention of
   never widening a shared class for one page's needs - the widest option
   text here ("Newest first"/"Oldest first", 12 characters) is a different
   length than either of those, so it gets its own cap rather than reusing
   theirs. max-width (not width) so it can still shrink narrower on a
   small viewport. Verified against the actual rendered width live, not
   just the CSS value - see this phase's Playwright check. */
.sort-select { max-width: 18ch; }

.library-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: var(--space-4);
  gap: var(--space-3);
}

.library-header h1 {
  margin: 0;
}

.library-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--space-5);
}

/* Phase 11.7 (design_answers_11.6-11.8/DESIGN_ANSWERS.md, "11.7 - Option
   2a"): .recipe-card is now a plain <div>, not the <a> it used to be -
   the whole card is still one navigation target (.recipe-card-link
   below wraps the photo+body exactly as the old outer <a> did), but the
   hover-revealed "Add to Plan" trigger needs to sit *outside* that link
   (nesting a <button> inside an <a> is invalid HTML and produces real
   click-conflict bugs - see _library_results.html's own comment). This
   card is therefore the positioning context for that trigger's overlay
   (position: absolute, same top:8px/right:8px .dashboard-card-overlay
   the editor dashboard already uses for its own Edit/Delete corner
   actions - reused here rather than re-invented) - see
   .recipe-card:hover/:focus-within .dashboard-card-overlay further
   down. */
.recipe-card {
  position: relative;
  padding: 0;
  overflow: hidden;
}

.recipe-card:hover { border-color: var(--color-accent); }

/* The actual navigation target - everything a click on the photo or the
   title/meta/tags below should do. Deliberately still one single link
   (not two, one per section) so keyboard/screen-reader users get one tab
   stop and one accessible name for "go to this recipe", exactly as
   before this phase's restructuring. */
.recipe-card-link {
  display: block;
  text-decoration: none;
  color: inherit;
}

/* Phase 11.7: the hover/focus-revealed corner trigger - a sibling of
   .recipe-card-link (not nested inside it, see .recipe-card's own
   comment above), reusing recipes.css's own .dashboard-card-overlay/
   .dashboard-card-action pattern verbatim for the visual + the
   always-visible-under-720px behavior (that mobile rule is declared
   unconditionally on .dashboard-card-overlay itself further down, so it
   already applies here with no changes). Only the *hover trigger*
   selector needs a library-card-specific counterpart, since the
   existing one is scoped to .dashboard-card:hover/:focus-within. */
.recipe-card:hover .dashboard-card-overlay,
.recipe-card:focus-within .dashboard-card-overlay {
  opacity: 1;
}

.recipe-card-photo {
  width: 100%;
  height: 160px;
  object-fit: cover;
  display: block;
}

.recipe-card-photo-placeholder {
  width: 100%;
  height: 160px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-surface);
  background-image: repeating-linear-gradient(
    45deg,
    color-mix(in srgb, var(--color-text) 6%, transparent),
    color-mix(in srgb, var(--color-text) 6%, transparent) 10px,
    transparent 10px,
    transparent 20px
  );
  color: color-mix(in srgb, var(--color-text) 45%, transparent);
  font-size: 14px;
  text-align: center;
  padding: var(--space-2);
}

.recipe-card-body {
  padding: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.recipe-card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 2px;
}

.library-empty {
  border: 1px dashed var(--color-divider);
  border-radius: var(--radius-md);
  padding: var(--space-8);
  text-align: center;
  /* 78%, not 60% (~4.4:1, under even the old 4.5:1 AA floor) - this is a
     real message the user needs to read ("No recipes match your
     filters"), same "muted text meant as information" role as
     base.css's .text-muted, bumped to the same value for the same
     reason (ui-design-principles.md §1). */
  color: color-mix(in srgb, var(--color-text) 78%, transparent);
}

/* Phase 10.7: pagination sentinel (_library_results.html). Not scoped to
   the mobile breakpoint below - the "render all 109+ recipes at once" bug
   this replaces exists at every viewport width, so real pagination +
   infinite scroll apply everywhere; only the filter-sidebar collapse
   further down is mobile-only (see this file's header comment on that
   rule for why). */
.library-load-more {
  margin-top: var(--space-6);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}

.library-load-more-link {
  max-width: 320px;
}

/* Inserted by static/js/library_infinite_scroll.js while a next-page
   fetch is in flight - same "muted text meant as real information" role
   (and same 78%-opacity token) as .library-empty above, per
   ui-design-principles.md §1's "target >=5.5:1, don't just clear the
   4.5:1 floor" guidance for text a user is actually meant to read. */
.library-load-more-status {
  margin: 0;
  font-size: 14px;
  color: color-mix(in srgb, var(--color-text) 78%, transparent);
}

/* Mobile filter-collapse toggle (Phase 10.7). Hidden by default at every
   width and revealed only by static/js/library_filter_toggle.js adding
   `.js-enabled` once it has confirmed both the button and #library-sidebar
   exist - so a page with JS disabled/failed never shows a button that
   does nothing on click (see library.html's comment on this element for
   the full rationale). The `@media` guard below is what keeps this
   mobile-only even when JS *does* run: on desktop `.js-enabled` alone has
   no effect, since the rule that actually shows the button only exists
   inside this query. */
.library-filter-toggle {
  display: none;
}

@media (max-width: 720px) {
  .library-layout {
    flex-direction: column;
  }
  .library-sidebar {
    width: 100%;
  }
  .library-filter-toggle.js-enabled {
    display: flex;
    width: 100%;
    /* No margin-bottom here - `.library-layout`'s own `gap: var(--space-8)`
       (declared once, above, for every flex child in both its row/desktop
       and stacked/mobile arrangements) already spaces this from the
       sidebar below it. An earlier version of this rule added its own
       margin-bottom on top of that - measured live at 50.6px total
       (space-8's 36.8px + a stray space-3's 13.8px stacking, not either
       value alone) before this fix, well past what was intended. */
  }
  /* Only takes effect once library_filter_toggle.js has actually added
     this class (see its own header comment) - the sidebar renders fully
     expanded, with no class at all, until then. */
  .library-sidebar.is-collapsed {
    display: none;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   Recipe detail / print view (Phase 3.2). Mirrors the mockup's #detail
   screen: photo "plate", title/kicker/facet chips/meta, two-column
   ingredients/steps, nutrition + notes. The .plate photo mat and the
   .card/.tag/.hr/.no-print primitives it builds on live in base.css -
   this file only holds this screen's own layout, same convention as the
   library grid above.
   ══════════════════════════════════════════════════════════════════════ */

.recipe-detail {
  max-width: 840px;
  margin: 0 auto;
  /* See .library-layout's comment above - same nav-alignment fix. */
  padding: var(--space-8) var(--space-4);
}

.recipe-detail-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: var(--space-4);
  /* var(--space-3) (13.8px), not var(--space-2) (9.2px) - "Back to
     Library" and "Print" are two distinct action buttons in a row, which
     ui-design-principles.md §4 sets a 12px floor for. */
  gap: var(--space-3);
}

/* Phase 11.7: groups "Add to Plan" + "Print" (frame 2d) so
   .recipe-detail-toolbar's own `justify-content: space-between` still
   splits exactly two flex children - "Back to Library" on the left,
   this whole cluster on the right - regardless of how many buttons end
   up in the cluster itself. Same var(--space-3)/12px-floor gap and
   wrapping as the toolbar's own rule, for the same reason. */
.recipe-detail-toolbar-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.recipe-detail-photo {
  width: 100%;
  height: 340px;
  object-fit: cover;
  display: block;
}

.recipe-detail-photo-placeholder {
  width: 100%;
  height: 340px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-surface);
  background-image: repeating-linear-gradient(
    45deg,
    color-mix(in srgb, var(--color-text) 6%, transparent),
    color-mix(in srgb, var(--color-text) 6%, transparent) 10px,
    transparent 10px,
    transparent 20px
  );
  color: color-mix(in srgb, var(--color-text) 45%, transparent);
  font-size: 14px;
  text-align: center;
  padding: var(--space-2);
}

.recipe-detail-header {
  margin-top: var(--space-5);
}

.recipe-detail-header h1 {
  margin: 4px 0 var(--space-2);
}

.recipe-detail-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: var(--space-3);
}

.recipe-detail-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6);
  font-size: 13px;
}

.recipe-detail-body {
  display: grid;
  grid-template-columns: 1fr 1.4fr;
  gap: var(--space-6);
}

.recipe-detail-body h4 {
  margin-top: 0;
}

.recipe-ingredient-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.recipe-ingredient-list li {
  font-size: 14px;
  display: flex;
  gap: 8px;
}

.recipe-ingredient-qty {
  color: var(--color-accent-700);
  font-variant-numeric: tabular-nums;
  min-width: 64px;
  flex: none;
}

.recipe-step-list {
  margin: 0;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.recipe-step-list li {
  font-size: 14px;
  line-height: 1.6;
}

.recipe-detail-extra {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6);
}

.recipe-detail-extra > * {
  flex: 1 1 260px;
  min-width: 0;
}

.recipe-nutrition-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13px;
}

.recipe-nutrition-list > div {
  display: flex;
  justify-content: space-between;
}

@media (max-width: 720px) {
  .recipe-detail-body {
    display: flex;
    flex-direction: column;
  }
}

/* — print polish specific to this screen: collapse the two-column
   ingredients/steps grid to one column and let the plate/photo shrink,
   so a printed page reads top-to-bottom rather than clipping the second
   column. Nav/toolbar hiding and the base page-background reset are
   handled globally in base.css's `.no-print` block. */
@media print {
  .recipe-detail {
    max-width: none;
    padding: 0;
  }
  .recipe-detail-body {
    display: block;
  }
  .recipe-detail-body > div {
    margin-bottom: var(--space-4);
  }
  .recipe-detail-photo,
  .recipe-detail-photo-placeholder {
    height: 200px;
  }
  .plate {
    border-width: 2px;
  }
  /* On screen, .recipe-step-list's own 20px padding-left (above) is
     topped up by .recipe-detail's ~18.4px page padding (--space-4),
     which is enough room for the browser's default <ol> marker box even
     at two-digit step numbers. .recipe-detail's padding drops to 0 in
     print (above), so the list's own padding is all that's left - and
     20px isn't enough: step "10." was printing as "0.", "16." as "6.",
     confirmed in Chromium/Firefox/WebKit screenshots and a real PDF.
     30px fits two-digit markers with room to spare. */
  .recipe-step-list {
    padding-left: 30px;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   Add/Edit recipe form (Phase 4.1). Mirrors the mockup's Add/Edit Recipe
   Form screen (README.md screen 5): centered column, max-width 760px,
   sections separated by hairline rules. Tag-facet controls use base.css's
   newly-ported .seg/.seg-opt (single-select: meal type/season/cuisine/
   category) and Phase 3.1's existing .chip-checkbox (multi-select
   dietary tags) rather than the mockup's onClick-driven .tag.chip spans
   - see base.css's header comment for why.
   ══════════════════════════════════════════════════════════════════════ */

.recipe-form {
  max-width: 760px;
  margin: 0 auto;
  /* See .library-layout's comment above - same nav-alignment fix. */
  padding: var(--space-8) var(--space-4);
}

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

.recipe-form-header {
  display: grid;
  grid-template-columns: 1fr 220px;
  gap: var(--space-5);
}

.recipe-form-times {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
}

.recipe-form-facets {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* Matches base.css's `.field > label` exactly - these facet labels ("Meal
   Type", "Season", ...) are field labels too, they just aren't inside a
   `.field` div so they don't pick that rule up. Both were 12px / weight 400
   / 70% opacity; both were bumped to body size at full brightness in the
   same sweep, per ui-design-principles.md §1 (and §6's "treat a deviation
   found anywhere as worth a global sweep"). Keep the two in step. */
.recipe-form-facet > label {
  display: block;
  font-size: 15px;
  font-weight: 600;
  margin-bottom: 6px;
  color: var(--color-text);
}

/* The mockup's own .seg is a single-row segmented control (border-collapsed,
   no wrap) sized for a couple of options - it was built there for a
   2-option Viewer/Editor toggle, see base.css's header comment. Cuisine
   (12 options) and Category (11) need to wrap onto multiple lines at this
   page's 760px width, so this page overrides flex-wrap rather than
   changing the shared component's own default behavior. */
.recipe-form-facet .seg {
  flex-wrap: wrap;
}

.recipe-form-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.recipe-form-section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.recipe-form-section-header h5 {
  margin: 0;
}

/* var(--space-3) (13.8px), not var(--space-2) (9.2px) - these are
   repeated formset rows (ui-design-principles.md §4's 12px-between-rows
   floor), not controls within a single row. */
#ingredient-rows,
#step-rows {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* Quantity/unit were 70px/100px when the shared input rule used 6px 10px
   padding. base.css now uses 8px 12px (see the touch-target/iOS-zoom note
   there), which took 4px of usable text width out of each of these two
   fixed columns - measured, not guessed: the quantity input's inner width
   went 48px -> 44px. +4px each restores exactly that, and the 1fr name
   column absorbs the 8px. The two other columns are wide enough that the
   same 4px doesn't matter. */
.ingredient-row {
  display: grid;
  grid-template-columns: 74px 104px 1fr 170px 36px;
  gap: var(--space-2);
  align-items: start;
}

.step-row {
  display: flex;
  gap: var(--space-2);
  align-items: flex-start;
}

.step-row-number {
  padding-top: 8px;
  font-size: 13px;
  min-width: 18px;
  flex: none;
}

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

/* Remove-row control: a formset DELETE checkbox hidden inside a
   button-styled label, same hidden-input-drives-visual-state approach as
   .chip-checkbox above. Checking it (by clicking the button) both flags
   the row for deletion on submit AND hides the row immediately via
   :has() - no JS needed for the remove interaction itself, only for
   cloning new rows (static/js/recipe_form.js) and keeping the Steps
   list's display-only numbering in sync afterward. */
.formset-remove-btn {
  position: relative;
}
.formset-remove-btn input[type="checkbox"] {
  position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none;
}
.ingredient-row:has(.formset-remove-btn input:checked),
.step-row:has(.formset-remove-btn input:checked) {
  display: none;
}

.recipe-form-nutrition {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-4);
}

.recipe-form-footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  margin-top: var(--space-2);
}

@media (max-width: 720px) {
  .recipe-form-header,
  .recipe-form-times,
  .recipe-form-nutrition {
    grid-template-columns: 1fr;
  }
  .ingredient-row {
    grid-template-columns: 1fr;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   Editor dashboard - "Manage Recipes" (Phase 4.2). Mirrors the mockup's
   Editor Dashboard screen (README.md screen 6): header (title + search +
   "+ Add Recipe"), responsive card grid (minmax(240px,1fr) - slightly
   narrower than the library's minmax(260px,1fr) per that screen's own
   spec), cards with a hover-revealed Edit/Delete overlay over the photo.
   Reuses .card/.tag/.elev-* from base.css; the photo-placeholder pattern
   is duplicated from .recipe-card-photo-placeholder above rather than
   shared, since this card's photo is a different fixed height (150px vs
   160px) per the mockup - same "not literal mockup classes, just this
   screen's own shell" convention as the rest of this file.

   The mockup's own `.hover-actions` class (used on this screen's Edit/
   Delete overlay) isn't defined anywhere in its styles.css export - only
   referenced via inline style on the .dc.html element - so
   .dashboard-card-overlay below is reconstructed from that inline style
   rather than ported verbatim.
   ══════════════════════════════════════════════════════════════════════ */

.dashboard-layout {
  max-width: 1280px;
  margin: 0 auto;
  /* See .library-layout's comment above - same nav-alignment fix. */
  padding: var(--space-8) var(--space-4);
}

.dashboard-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.dashboard-header h1 {
  margin: 0;
}

.dashboard-header-actions {
  display: flex;
  gap: var(--space-3);
  align-items: center;
}

.dashboard-search input {
  width: 220px;
}

.dashboard-count {
  margin: 0 0 var(--space-6);
}

.dashboard-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--space-5);
}

.dashboard-card {
  padding: 0;
  overflow: hidden;
}

.dashboard-card-photo-wrap {
  position: relative;
}

.dashboard-card-photo {
  width: 100%;
  height: 150px;
  object-fit: cover;
  display: block;
}

.dashboard-card-photo-placeholder {
  width: 100%;
  height: 150px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-surface);
  background-image: repeating-linear-gradient(
    45deg,
    color-mix(in srgb, var(--color-text) 6%, transparent),
    color-mix(in srgb, var(--color-text) 6%, transparent) 10px,
    transparent 10px,
    transparent 20px
  );
  color: color-mix(in srgb, var(--color-text) 45%, transparent);
  font-size: 14px;
  text-align: center;
  padding: var(--space-2);
}

/* Hover-revealed per-card actions - opacity-driven (not display:none) so
   :focus-within still reveals it for keyboard users tabbing onto the
   Edit/Delete links, not just mouse hover. */
.dashboard-card-overlay {
  position: absolute;
  top: 8px;
  right: 8px;
  display: flex;
  /* 12px, not 6px - Edit/Delete is a button group, which
     ui-design-principles.md §4 sets a 12px floor for. */
  gap: 12px;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.dashboard-card:hover .dashboard-card-overlay,
.dashboard-card:focus-within .dashboard-card-overlay {
  opacity: 1;
}

/* 16px, not 14px - Edit/Delete are clickable links, in scope for
   ui-design-principles.md §1's interactive-text floor. Padding bumped from
   4px towards a real (if still compact) mobile touch target, per §3. */
.dashboard-card-action {
  background: var(--color-bg);
  padding: 8px var(--space-3);
  font-size: 16px;
}

.dashboard-card-body {
  padding: var(--space-3);
}

@media (max-width: 720px) {
  .dashboard-header {
    flex-direction: column;
    align-items: flex-start;
  }
  .dashboard-header-actions {
    width: 100%;
  }
  .dashboard-search {
    flex: 1;
  }
  .dashboard-search input {
    width: 100%;
  }
  /* Always-visible on touch (no hover) so Edit/Delete aren't unreachable
     on mobile - matches this file's other max-720px touch-friendliness
     passes (library sidebar stacking, form grids collapsing). */
  .dashboard-card-overlay {
    opacity: 1;
    position: static;
    justify-content: flex-end;
    padding: var(--space-2) var(--space-2) 0;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   Phase 11.7 (design_answers_11.6-11.8/DESIGN_ANSWERS.md, "11.7 - Option
   2a"): the quick-add-to-plan dialog shared by the library card's
   trigger above and the recipe detail page's own toolbar trigger
   (detail.html) - recipes/templates/recipes/_quick_add_dialog.html,
   wired up by static/js/quick_add.js.
   ══════════════════════════════════════════════════════════════════════ */

/* The "author rule beats the UA's own dialog:not([open]) { display: none }"
   fix this dialog needs is now centralized in base.css itself (2026-08-16
   - was duplicated per-file before, which is exactly how
   accounts/family_detail.html's #confirm-dialog shipped without it and
   was visibly stuck open) - nothing extra needed here for that. */

.quick-add-dialog {
  width: min(480px, 100%);
  max-height: min(85vh, 640px);
  overflow-y: auto;
}

.quick-add-dialog::backdrop {
  background: rgba(45, 43, 43, 0.5);
}

.quick-add-week-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.quick-add-week-nav .text-muted {
  font-size: 15px;
}

.quick-add-week-buttons {
  display: flex;
  gap: 12px;
}

.quick-add-days {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* Empty-day row: a full-width button, same shape/hover as
   .planner-assign-row (planner.css) - unselected state has no visible
   border so the list reads as plain rows until one is picked. */
.quick-add-day-row {
  width: 100%;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  text-align: left;
  padding: var(--space-2) var(--space-3);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 16px;
  cursor: pointer;
}

.quick-add-day-row:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }

.quick-add-day-row.is-selected {
  border-color: var(--color-accent);
  background: color-mix(in srgb, var(--color-accent) 12%, transparent);
}

/* A day the caller can't edit (Phase 9 Viewer) renders the same row
   shape as a plain, inert <div> - no hover/pointer, nothing to click. */
.quick-add-day-row-readonly {
  cursor: default;
}

.quick-add-day-label {
  min-width: 64px;
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
}

/* Review fix: this span renders inside .quick-add-day-row's actual
   <button> (buildEmptyDayRow in quick_add.js) as well as the inert
   readonly variant - ui-design-principles.md §1 puts clickable-control
   text at a 16px floor "no exceptions for secondary controls", so the
   base rule now matches .quick-add-day-row's own 16px; the readonly
   (Viewer, non-interactive) row alone keeps the smaller 15px below. */
.quick-add-day-summary {
  font-size: 16px;
}

.quick-add-day-row-readonly .quick-add-day-summary {
  font-size: 15px;
}

/* Occupied day: the row expands inline (per 2c's "Occupied day
   selected" frame) into its own bordered, tinted block holding the
   day's current dishes plus the Add-as-Nth-Dish/Replace-the-Whole-Day
   buttons - always expanded (there's no separate "select it first"
   step for an occupied day, unlike an empty one), so this is a plain
   <div>, not a <button>. */
.quick-add-day-occupied {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--color-accent) 12%, transparent);
}

.quick-add-day-occupied-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

.quick-add-day-occupied-titles {
  font-size: 15px;
}

.quick-add-day-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

/* Login shell (2e) - the day-picker above is replaced entirely by this
   app's existing nav login form pattern (templates/base.html), reusing
   .field for the two inputs so they match every other form in the app
   rather than inventing a second input treatment. */
.quick-add-login-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.quick-add-login-actions {
  justify-content: space-between;
  align-items: center;
}

.quick-add-login-buttons {
  display: flex;
  gap: var(--space-3);
}
