@import url('https://fonts.googleapis.com/css2?family=Google+Sans:ital,wght@0,400..700;1,400..700&display=swap');
@import 'tokens.css';

* { box-sizing: border-box; }

/* Every layout rule below sets display, which outranks the UA's [hidden] rule.
   Without this, setting element.hidden does nothing. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--color-base);
  color: var(--color-text);
  font-family: var(--font-body);
  -webkit-tap-highlight-color: transparent;
}

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  padding-bottom: env(safe-area-inset-bottom);
}

h1, h2, h3 {
  font-family: var(--font-heading);
  font-weight: 600;
  margin: 0 0 var(--space-3);
}

p { margin: 0 0 var(--space-3); line-height: 1.5; }

a { color: inherit; }

button {
  font-family: var(--font-body);
  cursor: pointer;
}

/* The focus ring was paprika red, which measures 2.79 against the dark green
   background -- under the 3:1 a focus indicator needs -- and disappears
   completely when the focused thing is itself a paprika button. Text colour
   flips with the theme and clears 8.7 against the page in both. */
:focus-visible {
  outline: 3px solid var(--color-text);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* App shell */

.app-header {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  background: var(--color-chrome);
}

.app-header img {
  height: 32px;
}

main {
  flex: 1;
  padding: var(--space-4);
  padding-bottom: calc(var(--nav-height) + var(--space-5));
  max-width: 640px;
  width: 100%;
  margin: 0 auto;
}


.empty-state {
  text-align: center;
  padding: var(--space-6) var(--space-4);
  color: var(--color-text);
  opacity: 0.75;
}

/* Bottom nav */

.bottom-nav {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  height: var(--nav-height);
  padding-bottom: env(safe-area-inset-bottom);
  background: var(--color-chrome);
  border-top: 1px solid var(--color-border);
}

.bottom-nav button {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  min-width: var(--tap-target);
  min-height: var(--tap-target);
  background: none;
  border: none;
  color: var(--color-chrome-text);
  opacity: 0.75;
  font-size: 0.75rem;
  font-family: var(--font-body);
}

.bottom-nav button[aria-current="page"] {
  opacity: 1;
  font-weight: 600;
}

.bottom-nav button svg {
  width: 24px;
  height: 24px;
}

/* Buttons */

/* Deepened fill so white text clears AA at 5.02, with the lighter brand red as
   the rim. Both are needed and neither is enough alone: white on the light red
   only reaches 3.46, while the deepened red only reaches 1.93 against the dark
   green page -- so the button would blend into the background in dark mode.
   The rim measures 3.46 against that page, which is what identifies the button
   as a button. */
.btn-primary {
  background: var(--color-action-strong);
  color: #FFFFFF;
  border: 2px solid var(--color-action-rim);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-5);
  font-weight: 600;
  min-height: var(--tap-target);
  font-size: 1rem;
}

.btn-secondary {
  background: transparent;
  color: var(--color-primary);
  border: 2px solid var(--color-primary);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-5);
  font-weight: 600;
  min-height: var(--tap-target);
  font-size: 1rem;
}

.btn-block { width: 100%; }

/* Boot splash */

.boot {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  background: #2F4A3E;
  color: #FAF3E7;
}

/* Auth */

#auth-view {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  background: #2F4A3E;
  min-height: 100vh;
}

.auth-card {
  width: 100%;
  max-width: 400px;
}

.auth-logo {
  display: block;
  width: 160px;
  margin: 0 auto var(--space-5);
}

.segmented {
  display: flex;
  background: rgba(250, 243, 231, 0.12);
  border-radius: var(--radius-md);
  padding: var(--space-1);
  margin-bottom: var(--space-5);
}

.segmented button {
  flex: 1;
  min-height: var(--tap-target);
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: #FAF3E7;
  font-weight: 600;
  font-size: 1rem;
}

.segmented button[aria-selected="true"] {
  background: #FAF3E7;
  color: #2F4A3E;
}

#auth-form label {
  display: block;
  margin-bottom: var(--space-2);
  color: #FAF3E7;
  font-weight: 500;
}

#auth-form input {
  width: 100%;
  min-height: var(--tap-target);
  padding: var(--space-3);
  margin-bottom: var(--space-4);
  border: 2px solid transparent;
  border-radius: var(--radius-sm);
  background: #FAF3E7;
  color: #2F4A3E;
  font-size: 1rem;
  font-family: var(--font-body);
}

#auth-form input:focus-visible {
  border-color: var(--color-accent);
  outline: none;
}

.hint {
  opacity: 0.8;
  font-size: 0.875rem;
}

.favorites-modes {
  display: flex;
  gap: var(--space-1);
  padding: var(--space-1);
  border: 1px solid var(--color-control-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  margin-bottom: var(--space-5);
}

.favorites-modes button {
  flex: 1;
  min-height: var(--tap-target);
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-text);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 1rem;
}

.favorites-modes button[aria-selected="true"] {
  background: var(--color-primary);
  color: var(--color-text-on-primary);
}

.invite-result {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-control-border);
  background: var(--color-surface);
}

.invite-result code {
  font-family: var(--font-body);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: 0.03em;
}

/* Both of these belong to the auth card and nowhere else: the cream is for its
   fixed green background, and the negative margin tucks a hint under the input
   above it. Loose in the app they made hints invisible on a light page and made
   this one land on top of the button it explains. */
#auth-view .hint {
  color: #FAF3E7;
  margin-top: calc(var(--space-2) * -1);
}

.error,
.success {
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  font-size: 0.9375rem;
  margin-bottom: var(--space-4);
}

.error {
  background: #FBE4DE;
  color: #8A2A12;
}

.success {
  background: #FAF3E7;
  color: #2F4A3E;
}

/* Auth: forgot-password and recovery states */

.auth-title {
  font-family: var(--font-heading);
  font-size: 1.25rem;
  color: #FAF3E7;
  margin: 0 0 var(--space-2);
}

.auth-intro {
  margin: 0 0 var(--space-4);
}

.link-btn {
  display: block;
  width: 100%;
  min-height: var(--tap-target);
  margin-top: var(--space-2);
  padding: var(--space-2);
  background: none;
  border: none;
  color: #FAF3E7;
  font-family: var(--font-body);
  font-size: 0.9375rem;
  text-decoration: underline;
  cursor: pointer;
}

/* Sections */

.section-heading {
  font-size: 1.0625rem;
  margin: var(--space-5) 0 var(--space-3);
}

/* Ontdek wants every section snug against the one before it -- confirmed by
   measuring the shipped app, not assumed: every section there already sits
   in its own <section>, so ":first-of-type" (relative to each heading's own
   unique parent) trivially matched all of them and zeroed every one, which
   is what its dense chip-and-list layout was built for. Voorraad used to get
   the same treatment, back when it was the same kind of dense chip-and-list
   layout; now that "Toevoegen" is a tile grid and "In huis" a full pill
   list, snug reads as cramped instead -- confirmed on a real 390px viewport,
   where the frequent-chips row all but touched the "Toevoegen" heading
   beneath it -- so Voorraad keeps the base rule's margin-top like
   Favorieten and Account do. */
#tab-ontdek .section-heading {
  margin-top: 0;
}

/* Chips */

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.chip {
  min-height: var(--tap-target);
  padding: var(--space-2) var(--space-4);
  border: 2px solid var(--color-control-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: 0.9375rem;
}

.chip.is-selected,
.chip[aria-pressed="true"] {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-text-on-primary);
}

.chip:disabled { opacity: 0.5; }

/* Photo scan */

.scan-preview {
  margin: var(--space-3) 0;
}

.scan-preview img {
  width: 100%;
  max-height: 320px;
  object-fit: cover;
  border-radius: var(--radius-md);
  margin-bottom: var(--space-3);
  background: var(--color-control-border);
}

#scan-result {
  margin-top: var(--space-3);
}

#scan-chips {
  margin-bottom: var(--space-3);
}

/* Tapped away rather than deleted: it stays on screen so a mistake costs one
   more tap, not another photo. */
#scan-chips .chip[aria-pressed="false"] {
  opacity: 0.45;
  text-decoration: line-through;
}

/* Categories: a 2-column tile grid. Adding is the most-repeated action on
   this tab, so it gets the largest tap targets and sits above the fold;
   opening a tile spans it across the full row via the native [open]
   attribute, no JS needed to drive the layout. */

.tile-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
}

.category {
  grid-column: span 1;
  border: 2px solid var(--color-control-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  overflow: hidden;
}

.category[open] { grid-column: 1 / -1; }

.category summary {
  position: relative;
  min-height: 96px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-4);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 0.9375rem;
  cursor: pointer;
  list-style: none;
}

.category summary::-webkit-details-marker { display: none; }

.category summary svg {
  width: 26px;
  height: 26px;
  color: var(--color-primary);
}

.tile-count {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--color-accent);
  /* Hardcoded, not var(--color-primary): that token flips to cream in dark
     mode (for text on the dark chrome), which would put near-invisible
     cream text on this same yellow. The badge itself doesn't flip. */
  color: #2F4A3E;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.tile-count[hidden] { display: none; }

.category[open] summary {
  border-bottom: 1px solid var(--color-border);
}

.category .chip-row { padding: var(--space-4); }

/* Scan tile: same tile language as the categories, filled in the action
   colour so the alternate ("show me" instead of "tell me") input method
   still reads as the deliberate odd one out in the grid. */
.scan-tile {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  width: 100%;
  min-height: 96px;
  margin: var(--space-6) 0 var(--space-4);
  border: 2px solid var(--color-action-rim);
  border-radius: var(--radius-md);
  background: var(--color-action-strong);
  color: #FFFFFF;
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 0.9375rem;
  cursor: pointer;
  text-align: center;
}

.scan-tile svg { width: 22px; height: 22px; flex: none; }

#scan-input:focus-visible ~ .scan-tile {
  outline: 3px solid var(--color-text);
  outline-offset: 2px;
}

/* Inventory list */

.inventory-list {
  list-style: none;
  margin: var(--space-2) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.inventory-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--color-primary);
  color: var(--color-text-on-primary);
  font-size: 0.9375rem;
}

/* 44x44 of reachable area with a 32px circle painted inside it. The negative
   margin keeps the row exactly as tall as it was, so the thumb gets the target
   the spec asks for without the list growing. It measured 32x32 before -- on
   the control you press most often of all. */
.remove-btn {
  width: var(--tap-target);
  height: var(--tap-target);
  margin: calc((var(--tap-target) - 32px) / -2) 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  border: none;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(250, 243, 231, 0.2) 16px, transparent 16px);
  color: inherit;
  font-size: 1.25rem;
  line-height: 1;
}

/* Free text */

.freetext { margin-top: var(--space-5); }

.freetext label {
  display: block;
  margin-bottom: var(--space-2);
  font-size: 0.9375rem;
}

.freetext-row { display: flex; gap: var(--space-2); }

.freetext-row input {
  flex: 1;
  min-height: var(--tap-target);
  padding: var(--space-3);
  border: 2px solid var(--color-control-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: 1rem;
  font-family: var(--font-body);
}

/* Account */

.account-email {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
}

.setting-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: var(--tap-target);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-5);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
}

.setting-row input[type="checkbox"] {
  width: 44px;
  height: 26px;
  accent-color: var(--color-action);
}

/* Cooking mode -- fullscreen, above everything, nothing on screen but the step
   you are on. */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.cooking {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: flex;
  flex-direction: column;
  padding: var(--space-4);
  padding-bottom: calc(var(--space-4) + env(safe-area-inset-bottom));
  background: var(--color-base);
  overflow-y: auto;
}

.cooking-top {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-5);
}

.cooking-count {
  flex: 1;
  margin: 0;
  font-weight: 500;
  opacity: 0.75;
}

.cooking-icon {
  width: var(--tap-target);
  height: var(--tap-target);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  border: 1px solid var(--color-control-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
}

.cooking-icon svg { width: 22px; height: 22px; }

.cooking-icon[aria-pressed="true"] {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-text-on-primary);
}

/* The whole point of the screen: readable at arm's length with wet hands. */
.cooking-step {
  flex: 1;
  margin: 0;
  font-family: var(--font-heading);
  font-size: 1.5rem;
  font-weight: 500;
  line-height: 1.45;
}

.cooking-finish {
  margin-top: var(--space-5);
}

.cooking-finish h2 {
  font-size: 1.125rem;
}

.cook-used {
  list-style: none;
  margin: 0 0 var(--space-4);
  padding: 0;
}

.cook-used label {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--tap-target);
  border-bottom: 1px solid var(--color-border);
}

.cook-used input {
  width: 22px;
  height: 22px;
  accent-color: var(--color-action);
}

.cooking-nav {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-5);
}

.cooking-nav button {
  flex: 1;
  min-height: 56px;
  font-size: 1.0625rem;
}

.cooking-nav button:disabled { opacity: 0.4; }

/* Recipe detail */

.detail {
  padding: var(--space-4);
  padding-bottom: calc(var(--nav-height) + var(--space-6));
}

.back-btn {
  min-height: var(--tap-target);
  margin-bottom: var(--space-3);
  padding: 0 var(--space-3) 0 0;
  background: none;
  border: none;
  color: inherit;
  font-size: 0.9375rem;
  font-weight: 500;
}

.back-btn::before {
  content: '←';
  margin-right: var(--space-2);
}

/* The card's small label is not enough on its own: the spec wants this to be
   unmissable when you open a recipe nobody has ever cooked. */
.ai-banner {
  margin: 0 0 var(--space-4);
  padding: var(--space-3);
  border-radius: var(--radius-md);
  border-left: 4px solid var(--color-action);
  background: var(--color-surface);
  font-size: 0.9375rem;
  font-weight: 500;
}

.detail-image {
  width: 100%;
  height: 200px;
  object-fit: cover;
  border-radius: var(--radius-md);
  background: var(--color-border);
  margin-bottom: var(--space-4);
}

.detail-illustration {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 4rem;
  line-height: 1;
  background: var(--color-base);
  border: 1px solid var(--color-control-border);
}

/* The zero-top-margin rule for a first heading is meant for the tab panels; in
   the detail these headings follow content and need their spacing back. */
.detail .section-heading:first-of-type { margin-top: var(--space-5); }

.portions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-bottom: var(--space-2);
}

/* Not the auth screen's .segmented: those colours are fixed to cream-on-green
   and this control sits on the page background. Same reasoning behind
   .favorites-modes below. */
.portion-stepper {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1);
  border: 1px solid var(--color-control-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}

.portion-stepper button {
  min-width: var(--tap-target);
  min-height: var(--tap-target);
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1;
}

.portion-stepper button:disabled {
  opacity: 0.35;
}

.portion-stepper button:not(:disabled):hover,
.portion-stepper button:not(:disabled):active {
  background: var(--color-primary);
  color: var(--color-text-on-primary);
}

#portion-count {
  min-width: 1.5em;
  text-align: center;
  font-weight: 600;
}

.detail-ingredients {
  list-style: none;
  margin: 0 0 var(--space-4);
  padding: 0;
}

.detail-ingredients li {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--color-border);
}

.detail-amount {
  flex: none;
  opacity: 0.75;
}

.missing-flag {
  display: inline-block;
  padding: 1px var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--color-accent);
  color: #2F4A3E;
  font-size: 0.6875rem;
  font-weight: 500;
  white-space: nowrap;
}

/* Sits under the ingredient it belongs to, so it reads as an aside rather than
   as another thing to buy. */
.swaps-row {
  display: block;
  padding: 0 0 var(--space-3);
  border-bottom: 1px solid var(--color-border);
}

.swaps {
  list-style: none;
  margin: 0;
  padding: 0 0 0 var(--space-3);
  border-left: 2px solid var(--color-border);
  font-size: 0.875rem;
}

.swaps li {
  margin-top: var(--space-2);
  line-height: 1.45;
  opacity: 0.85;
}

.swaps li.is-in-stock { opacity: 1; }

.swap-flag {
  display: inline-block;
  white-space: nowrap;
  padding: 1px var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--color-primary);
  color: var(--color-text-on-primary);
  font-size: 0.6875rem;
  font-weight: 500;
}

.detail-steps {
  margin: 0;
  padding-left: var(--space-5);
}

.detail-steps li {
  margin-bottom: var(--space-3);
  padding-left: var(--space-1);
  line-height: 1.55;
}

.nutrition {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0;
  margin: 0 0 var(--space-3);
}

.nutrition dt,
.nutrition dd {
  margin: 0;
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--color-border);
}

.nutrition dd {
  text-align: right;
  font-weight: 600;
}

/* A fixed two-column grid rather than a wrapping row: with labels of very
   different lengths, wrapping produced one full-width button, then another,
   then two side by side. */
.detail-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.detail-actions button {
  min-width: 0;
  padding: var(--space-2);
  font-size: 0.9375rem;
}

#fav-toggle[aria-pressed="true"] {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-text-on-primary);
}

.swap-use {
  padding: 0;
  font-size: 0.8125rem;
  min-height: 0;
}

.shopping-list {
  list-style: none;
  margin: 0 0 var(--space-4);
  padding: 0;
}

.shopping-list label {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--tap-target);
  border-bottom: 1px solid var(--color-border);
}

.shopping-list input {
  width: 22px;
  height: 22px;
  accent-color: var(--color-action);
}

/* Stats */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--space-2);
  margin: 0 0 var(--space-5);
}

.stat {
  padding: var(--space-3);
  border: 1px solid var(--color-control-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}

.stat dt {
  font-size: 0.75rem;
  opacity: 0.75;
  margin-bottom: var(--space-1);
}

.stat dd {
  margin: 0;
  font-family: var(--font-heading);
  font-size: 1.125rem;
  font-weight: 600;
}

/* Only for cooked_recipes rows written before the recipe-snapshot column
   existed -- too little data for a tile, so it spans the grid as a plain row
   instead of leaving a half-empty card next to it. */
.cooked-fallback {
  grid-column: 1 / -1;
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--color-border);
}

.cooked-fallback time {
  flex: none;
  opacity: 0.75;
  font-size: 0.875rem;
}

/* Discover -- pantry mirror */

.pantry { margin-bottom: var(--space-4); }

.pantry-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin: 0;
  font-weight: 500;
}

/* Editing here is editing the real inventory, so it reuses In huis's own
   pill styling (.inventory-list/.inventory-item) rather than a second look
   for the same data -- collapsed by default, "Aanpassen" reveals it. */
#pantry-chips { margin-top: var(--space-3); }

.link-inline {
  min-height: var(--tap-target);
  padding: 0 var(--space-2);
  background: none;
  border: none;
  /* Paprika red is the only brand colour that fails AA on the dark green
     background, so the underline carries the affordance instead. */
  color: currentColor;
  font-family: var(--font-body);
  font-size: 0.9375rem;
  font-weight: 500;
  text-decoration: underline;
}

/* Discover */

/* Filters default to collapsed: they stay on "Alles" far more often than
   not, so the summary line stands in for them and the results start
   sooner. The summary line updates live from the chip state below. */
.filters-disclosure {
  border: 1px solid var(--color-control-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  margin-bottom: var(--space-4);
  overflow: hidden;
}

.filters-disclosure summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  min-height: var(--tap-target);
  padding: var(--space-3) var(--space-4);
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}

.filters-disclosure summary::-webkit-details-marker { display: none; }

.filters-disclosure summary .chev {
  flex: none;
  opacity: 0.65;
  font-weight: 400;
  font-size: 0.875rem;
  text-decoration: underline;
}

.filters-disclosure[open] summary { border-bottom: 1px solid var(--color-border); }

.filters-disclosure .filters { padding: var(--space-4); margin-bottom: 0; }

.filters {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.filter { min-width: 0; }

.filter label,
.filter > span:first-child {
  display: block;
  margin-bottom: var(--space-2);
  font-size: 0.875rem;
  font-weight: 500;
}

.discover-actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.discover-status {
  margin: 0 0 var(--space-4);
}

.recipe-list {
  list-style: none;
  margin: 0 0 var(--space-5);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.recipe-card {
  display: flex;
  width: 100%;
  gap: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  border: 1px solid var(--color-control-border);
  color: inherit;
  font-family: var(--font-body);
  text-align: left;
  /* Not a <button> any more (a heart button lives inside it on Ontdek, and
     buttons cannot nest) -- cursor: pointer came free from the button reset
     before, now it needs saying explicitly. */
  cursor: pointer;
}

/* Discover results only: two columns of shorter cards fit more matches
   above the fold than one column of wide rows. Side dishes and favourites
   keep the wide .recipe-list layout, where a single line of context matters
   more than density. */
.recipe-grid {
  list-style: none;
  margin: 0 0 var(--space-5);
  padding: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  /* auto-rows: 1fr on an intrinsically-sized grid resolves every row to the
     tallest row's content height, so a two-line badge on one card no longer
     leaves its row-mate shorter. */
  grid-auto-rows: 1fr;
  gap: var(--space-3);
}

.recipe-grid .recipe-card {
  /* grid-auto-rows: 1fr on .recipe-grid equalises the <li> row height, but
     this button is a plain block child of it -- without height: 100% it
     still sizes to its own content and leaves the taller neighbour's row
     looking uneven. */
  height: 100%;
  position: relative;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-2);
}

/* Ontdek only -- filled once bewaard, outlined otherwise. 44x44 tap target
   (this app's touch-target floor everywhere else), the visible white-backed
   circle inside it stays small so it doesn't swallow half the thumbnail. */
.recipe-heart {
  position: absolute;
  top: 0;
  right: 0;
  width: 44px;
  height: 44px;
  padding: 0;
  border: none;
  background: none;
  display: flex;
  align-items: center;
  justify-content: center;
}

.recipe-heart-dot {
  width: 28px;
  height: 28px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.85);
  display: flex;
  align-items: center;
  justify-content: center;
}

.recipe-heart-dot svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: #2F4A3E;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.recipe-heart.is-saved .recipe-heart-dot svg {
  fill: #2F4A3E;
}

/* Same round-badge shape as a Voorraad category tile's .tile-count, own
   colours: herb green fixed rather than var(--color-primary), which flips
   to cream in dark mode and would turn this into a cream-on-cream badge. */
.recipe-count {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border-radius: 999px;
  background: #2F4A3E;
  color: #FFFFFF;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.recipe-grid .recipe-image { width: 100%; height: 96px; }
.recipe-grid .recipe-illustration { font-size: 2rem; }
.recipe-grid .recipe-title { font-size: 0.9375rem; }

.recipe-image {
  width: 88px;
  height: 88px;
  flex: none;
  object-fit: cover;
  border-radius: var(--radius-sm);
  background: var(--color-border);
}

.recipe-body {
  min-width: 0;
}

.recipe-title {
  font-family: var(--font-heading);
  font-size: 1rem;
  font-weight: 600;
  margin: 0 0 var(--space-1);
}

.recipe-meta {
  margin: 0;
  font-size: 0.875rem;
  opacity: 0.75;
}

.recipe-source {
  display: block;
  margin: var(--space-1) 0 0;
  font-size: 0.75rem;
  color: var(--color-action);
  text-decoration: none;
}

.recipe-source:hover,
.recipe-source:focus-visible {
  text-decoration: underline;
}

.source-line {
  margin: 0 0 var(--space-4);
  font-size: 0.875rem;
  opacity: 0.75;
}

.source-line a {
  color: var(--color-action);
}

/* Stands in for the photo a generated recipe has none of. */
.recipe-illustration {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2.5rem;
  line-height: 1;
  background: var(--color-base);
  border: 1px solid var(--color-control-border);
}

/* Herb green outline rather than a filled badge: it has to be readable at a
   glance without competing with the butter-yellow "bijna klaar" badge. */
.badge-ai {
  display: inline-block;
  margin: var(--space-2) 0 0;
  padding: 2px var(--space-2);
  border: 1px solid currentColor;
  border-radius: var(--radius-sm);
  font-size: 0.75rem;
  font-weight: 500;
  opacity: 0.85;
}

/* Butter yellow, so a near miss reads differently at a glance from a card in
   "klaar om te maken". */
.badge-missing {
  display: inline-block;
  margin: var(--space-2) 0 var(--space-1);
  padding: 2px var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--color-accent);
  color: #2F4A3E;
  font-size: 0.8125rem;
  font-weight: 600;
}

.recipe-missing {
  margin: 0;
  font-size: 0.875rem;
}

/* Toast */

.toast {
  position: fixed;
  left: 50%;
  bottom: calc(var(--nav-height) + var(--space-4));
  transform: translateX(-50%);
  z-index: 10;
  max-width: calc(100% - var(--space-6));
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--color-primary);
  color: var(--color-text-on-primary);
  font-size: 0.9375rem;
  text-align: center;
}
