/*
  一汁三菜 · ichiju.exped.nu

  Palette taken from traditional Japanese colour names, used restrainedly:
    kinari  生成り  unbleached cloth, the ground
    sumi    墨      ink, the text
    ai      藍      indigo, the one structural accent
    shu     朱      vermilion, used exactly once (the held-dish mark)
  The point is negative space (ma, 間), not decoration.
*/

/* Any rule here that sets `display` on an element the script hides would beat
   the browser's own `[hidden] { display: none }`, which is only a UA style and
   loses on specificity. That is how the sign-in link stayed on screen while
   the script was hiding it. Settle it once, for everything. */
[hidden] { display: none !important; }

:root {
  --kinari:     #efe9dd;
  --kinari-deep:#e5ddcd;
  --washi:      #f7f3ea;
  --sumi:       #191712;
  --sumi-soft:  #55503f;
  --sumi-faint: #8c8571;
  --ai:         #24405c;
  --ai-soft:    #35597d;
  --shu:        #a83b24;
  --rule:       #cfc4ac;
  --shadow:     rgba(25, 23, 18, .10);
}

/* Dark mode only on a real screen. On a phone this page gets used standing in
   a supermarket under bright strip lighting, where a dark page is the hardest
   thing to read: the screen is dimmer than everything around it and every
   reflection lands on top of the text. So below 46 rem the light palette wins,
   whatever the phone is set to. */
@media (prefers-color-scheme: dark) and (min-width: 46.01rem) {
  :root {
    --kinari:     #16151a;
    --kinari-deep:#100f13;
    --washi:      #1e1d23;
    --sumi:       #ece7dc;
    --sumi-soft:  #b3ac9c;
    --sumi-faint: #7d7768;
    --ai:         #8fb0d0;
    --ai-soft:    #6f8fae;
    --shu:        #d4694c;
    --rule:       #34323a;
    --shadow:     rgba(0, 0, 0, .45);
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--kinari);
  color: var(--sumi);
  font-family: "Zen Kaku Gothic New", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 16px;
  line-height: 1.72;
  -webkit-font-smoothing: antialiased;
}

.ja, .ja-inline {
  font-family: "Shippori Mincho", "Yu Mincho", "Hiragino Mincho ProN", serif;
  font-feature-settings: "palt" 1;
}

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

/* ---------- masthead ---------- */

/* The tray is the point of the page, so the head above it stays small enough
   that a meal is visible without scrolling on an ordinary laptop. The long
   explanation lives in the colophon instead. */
.masthead {
  max-width: 46rem;
  margin: 0 auto;
  padding: clamp(1.6rem, 4vw, 2.8rem) 1.5rem 0;
  text-align: center;
}

.masthead h1 {
  margin: 0;
  font-weight: 400;
  font-size: clamp(2rem, 6vw, 3.1rem);
  letter-spacing: .16em;
  line-height: 1.15;
  text-indent: .16em;    /* balance the trailing letter-space */
}

.lede {
  margin: .7rem auto 0;
  max-width: 34rem;
  font-size: .88rem;
  color: var(--sumi-soft);
  text-wrap: pretty;
}

/* ---------- the tray ---------- */

main { padding: 0 1.5rem 5rem; }

/* ---------- the controls column beside the tray ---------- */

/* The tray stays centred on the page and the controls sit in the right
   gutter. The empty first column mirrors the controls column, which is what
   keeps the tray itself centred rather than merely offset. */
.layout {
  display: grid;
  grid-template-columns: 11rem minmax(0, 62rem) 11rem;
  justify-content: center;
  gap: clamp(1.5rem, 3vw, 3rem);
  align-items: start;
  margin: clamp(1.4rem, 3.5vw, 2.4rem) 0 0;
}
/* Both rows are pinned: the aside comes first in the markup but belongs in
   the last column, and sparse auto-placement would otherwise push the tray
   down to a second row rather than back-filling the column beside it. */
.tray-wrap { grid-column: 2; grid-row: 1; }
.controls  { grid-column: 3; grid-row: 1; }

/* The controls follow the tray down the page rather than scrolling away. */
.controls {
  position: sticky;
  top: 1.6rem;
  display: flex;
  flex-direction: column;
  gap: 1.4rem;
  min-width: 0;    /* a long recipe name wraps, it does not widen the column */
}

/* ---------- dietary choice ---------- */

.diet {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: .25rem;
}

.diet-opt {
  font: inherit;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .12rem;
  padding: .5rem .75rem .45rem;
  color: var(--sumi-faint);
  background: none;
  border: 1px solid transparent;
  border-radius: 2px;
  cursor: pointer;
  transition: color .18s ease, border-color .18s ease, background .18s ease;
}
.diet-opt .ja { font-size: .95rem; letter-spacing: .1em; line-height: 1.3; }
.diet-label { font-size: .68rem; letter-spacing: .1em; text-transform: uppercase; }

.diet-opt:hover { color: var(--sumi-soft); }
.diet-opt.is-on {
  color: var(--sumi);
  border-color: var(--rule);
  background: var(--washi);
}

.tray-wrap {
  position: relative;
  min-width: 0;
}

/* 献立 (kondate, "menu") set vertically beside the tray, the way a label is
   written on Japanese signage and menus. Decorative, so aria-hidden.
   It sits in the left gutter, opposite the controls. */
.tray-mark {
  position: absolute;
  top: .2rem; right: calc(100% + 1.1rem);
  margin: 0;
  writing-mode: vertical-rl;
  font-size: .95rem;
  letter-spacing: .34em;
  color: var(--sumi-faint);
  user-select: none;
}
@media (max-width: 92rem) { .tray-mark { display: none; } }

.tray {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1rem, 2.2vw, 1.8rem);
  padding: clamp(1.1rem, 2.6vw, 2rem);
  background: var(--washi);
  border: 1px solid var(--rule);
  border-radius: 3px;
  box-shadow: 0 1px 0 var(--rule), 0 18px 40px -32px var(--shadow);
  overflow: hidden;
}

/* 青海波 (seigaiha), the overlapping-wave pattern found on dishware and
   textiles. Kept near the threshold of visibility: it should read as texture
   in the tray, not as a graphic. */
.tray::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .3;
  background-image:
    radial-gradient(circle at 50% 100%, transparent 0 33%, var(--rule) 33% 34%, transparent 34% 50%, var(--rule) 50% 51%, transparent 51% 67%, var(--rule) 67% 68%, transparent 68%),
    radial-gradient(circle at 0    100%, transparent 0 33%, var(--rule) 33% 34%, transparent 34% 50%, var(--rule) 50% 51%, transparent 51% 67%, var(--rule) 67% 68%, transparent 68%),
    radial-gradient(circle at 100% 100%, transparent 0 33%, var(--rule) 33% 34%, transparent 34% 50%, var(--rule) 50% 51%, transparent 51% 67%, var(--rule) 67% 68%, transparent 68%);
  background-size: 56px 28px;
  background-position: 0 0, 0 0, 0 0;
  -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,.55), transparent 62%);
          mask-image: linear-gradient(to bottom, rgba(0,0,0,.55), transparent 62%);
}

.tray > * { position: relative; z-index: 1; }

/* traditional placement: rice front-left, soup front-right, main back-right */
.dish[data-slot="fukusai"]   { grid-area: 1 / 1; }
.dish[data-slot="fukufukusai"] { grid-area: 1 / 2; }
.dish[data-slot="shusai"]    { grid-area: 1 / 3; }
.dish[data-slot="gohan"]     { grid-area: 2 / 1; }
.dish[data-slot="konomono"]  { grid-area: 2 / 2; }
.dish[data-slot="shirumono"] { grid-area: 2 / 3; }

.dish {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  min-width: 0;
}

.bowl {
  position: relative;
  width: clamp(4.4rem, 11vw, 7rem);
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  background: var(--kinari-deep);
  border: 1px solid var(--rule);
  display: grid;
  place-items: center;
  transition: transform .35s cubic-bezier(.2,.7,.3,1);
}

.dish.swapping .bowl { transform: scale(.94); }

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

.bowl-empty {
  width: 34%; height: 1px; background: var(--rule);
}
.bowl img:not([hidden]) + .bowl-empty { display: none; }

.slot-label {
  margin: .7rem 0 .1rem;
  display: flex;
  align-items: baseline;
  gap: .55rem;
  flex-wrap: wrap;
  justify-content: center;
}
.slot-label .ja { font-size: 1.12rem; letter-spacing: .08em; }
.romaji {
  font-size: .7rem;
  letter-spacing: .16em;
  text-transform: lowercase;
  color: var(--sumi-faint);
}

.dish-name {
  margin: .35rem 0 .5rem;
  font-size: .97rem;
  font-weight: 500;
  line-height: 1.45;
  text-wrap: balance;
}
.dish-name a { color: inherit; text-decoration-color: var(--rule); text-underline-offset: .22em; }
.dish-name a:hover,
.dish-name a:focus-visible { color: var(--ai); text-decoration-color: currentColor; }

.dish-name .placeholder {
  display: inline-block; width: 7rem; height: .8em;
  background: var(--kinari-deep); border-radius: 2px;
}

.slot-about {
  margin: 0;
  font-size: .8rem;
  line-height: 1.6;
  color: var(--sumi-faint);
  max-width: 20rem;
}

.dish.empty .dish-name { color: var(--sumi-faint); font-style: italic; }

/* the one vermilion mark: a dish held across rerolls */
.lock {
  position: absolute;
  top: -.35rem; right: 50%;
  transform: translateX(calc(clamp(4.4rem, 11vw, 7rem) / 2 - .35rem));
  width: 1.5rem; height: 1.5rem;
  padding: 0;
  border: 0; border-radius: 50%;
  background: transparent;
  cursor: pointer;
  display: grid; place-items: center;
  z-index: 2;
}
.lock-mark {
  width: .62rem; height: .62rem;
  border-radius: 50%;
  border: 1px solid var(--rule);
  background: var(--washi);
  transition: background .18s ease, border-color .18s ease, transform .18s ease;
}
.lock:hover .lock-mark { border-color: var(--sumi-faint); }
.lock[aria-pressed="true"] .lock-mark {
  background: var(--shu); border-color: var(--shu); transform: scale(1.15);
}
.lock:focus-visible { outline: 2px solid var(--ai); outline-offset: 2px; }

.tray-note {
  margin: 1.1rem auto 0;
  max-width: 38rem;
  text-align: center;
  font-size: .78rem;
  color: var(--sumi-faint);
}

/* ---------- the menu ----------
   On a desktop the menu is not a menu at all: its three parts simply stack in
   the controls column, the way they always did. Everything that turns it into
   a panel lives in the 46 rem block at the bottom, so nothing here has to be
   undone for the wide layout. */

.menu { display: flex; flex-direction: column; gap: 1.4rem; min-width: 0; }

.menu-toggle { display: none; }
.menu-scrim { display: none; }

/* ---------- searching for one dish ----------
   Deciding a meal from one dish outward, rather than taking what the tray
   offers. Sits between the dietary choice and the buttons because that is the
   order of the thought: what may be on the table, what I already want, and
   only then compose. */

/* `min-width: 0` on every box between the grid column and the text: a flex or
   grid item refuses to shrink below its content by default, so one long recipe
   name would otherwise widen the whole column instead of wrapping. */
.find { display: flex; flex-direction: column; gap: .4rem; min-width: 0; }

.find-label {
  font-size: .68rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--sumi-faint);
}

.find-input {
  font: inherit;
  font-size: .88rem;
  width: 100%;
  padding: .55rem .6rem;
  color: var(--sumi);
  background: var(--washi);
  border: 1px solid var(--rule);
  border-radius: 2px;
}
.find-input::placeholder { color: var(--sumi-faint); }
.find-input:focus { border-color: var(--ai); }

.find-hint { margin: 0; font-size: .76rem; color: var(--sumi-faint); }

.find-results {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: var(--washi);
  max-height: 15rem;
  overflow-y: auto;
  /* Explicit, and not just tidiness: once one axis is not `visible` the other
     computes to `auto`, so the vertical scroller was quietly handing out a
     horizontal one too. This list only ever scrolls one way. */
  overflow-x: hidden;
  overscroll-behavior: contain;
}
.find-hit + .find-hit { border-top: 1px solid var(--rule); }

.find-pick {
  font: inherit;
  display: flex;
  align-items: center;
  gap: .6rem;
  width: 100%;
  min-width: 0;
  padding: .45rem .6rem;
  text-align: left;
  color: var(--sumi);
  background: none;
  border: 0;
  cursor: pointer;
}
.find-pick:hover { background: var(--kinari-deep); }

/* The picture. The names are Japanese, so this is often the faster read. */
.find-thumb {
  flex: 0 0 auto;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
  overflow: hidden;
  background: var(--kinari-deep);
  border: 1px solid var(--rule);
}
.find-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

.find-text { display: flex; flex-direction: column; gap: .05rem; min-width: 0; }
.find-name {
  font-size: .88rem;
  line-height: 1.35;
  /* "Chawanmushi (Japanese Savory Steamed Egg Custard)" has to be able to
     break, including mid-word if the column is genuinely that narrow */
  overflow-wrap: anywhere;
}
.find-role {
  font-size: .68rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--sumi-faint);
  overflow-wrap: anywhere;
}
/* Outside the diet: still pickable, but say so. A pin beats the filter. */
.find-pick.is-out .find-role { color: var(--shu); }

/* ---------- where a recipe opens ----------
   A phone-only control: on a desktop, signing in already sends the links to
   Mealie, so this would be a second way to say the same thing. It is unhidden
   in the 46 rem block at the bottom. */

.openin {
  display: none;
  flex-direction: column;
  gap: .3rem;
}
.openin-label {
  font-size: .68rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--sumi-faint);
}
.openin-opts {
  display: inline-flex;
  border: 1px solid var(--rule);
  border-radius: 2px;
  overflow: hidden;
  align-self: flex-start;
}
.openin-opt {
  font: inherit;
  font-size: .78rem;
  padding: .34rem .8rem;
  color: var(--sumi-faint);
  background: var(--washi);
  border: 0;
  cursor: pointer;
  transition: color .18s ease, background .18s ease;
}
.openin-opt + .openin-opt { border-left: 1px solid var(--rule); }
.openin-opt:hover { color: var(--sumi-soft); }
.openin-opt.is-on { color: var(--washi); background: var(--ai); }

/* ---------- actions ---------- */

.actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: .5rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--rule);
}

.btn-primary {
  font: inherit;
  font-size: .92rem;
  letter-spacing: .04em;
  padding: .78rem 1rem;
  color: var(--washi);
  background: var(--ai);
  border: 1px solid var(--ai);
  border-radius: 2px;
  cursor: pointer;
  transition: background .18s ease, transform .18s ease;
}
.btn-primary:hover { background: var(--ai-soft); }
.btn-primary:active { transform: translateY(1px); }
.btn-primary[disabled] { opacity: .55; cursor: default; }

.btn-quiet {
  font: inherit; font-size: .85rem;
  padding: .78rem 1rem;
  color: var(--sumi-soft);
  background: none; border: 0; border-bottom: 1px solid var(--rule);
  cursor: pointer;
}
.btn-quiet:hover { color: var(--sumi); border-color: var(--sumi-faint); }
a.btn-quiet { display: block; text-align: center; text-decoration: none; }
.btn-quiet[disabled] { opacity: .45; cursor: default; }

/* Takes the place of "zet in agenda" when that is clicked, so the column never
   grows a second control competing with the first. Picking a day writes the
   event; there is nothing further to confirm. */
.planner-date {
  font: inherit;
  font-size: .88rem;
  padding: .55rem .6rem;
  color: var(--sumi);
  background: var(--washi);
  border: 1px solid var(--rule);
  border-radius: 2px;
  width: 100%;
  box-sizing: border-box;
}
.planner-date:focus { border-color: var(--ai); }
.planner-date[disabled] { opacity: .55; }

/* ---------- the question dialog ----------
   Small, centred, same paper and rule as the shopping list. It asks one thing
   and offers two answers, with the safe one on the left where a thumb lands. */
.ask-dialog {
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: var(--washi);
  color: var(--sumi);
  padding: 1.3rem 1.4rem 1.1rem;
  width: min(24rem, calc(100vw - 2.5rem));
  box-shadow: 0 24px 50px -30px var(--shadow);
}
.ask-dialog::backdrop { background: rgba(15, 20, 25, .55); }

.ask-title {
  margin: 0 0 .5rem;
  font-family: "Shippori Mincho", serif;
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: .04em;
}
.ask-body {
  margin: 0 0 1.2rem;
  font-size: .9rem;
  line-height: 1.6;
  color: var(--sumi-soft);
  text-wrap: pretty;
}
.ask-body strong { color: var(--sumi); font-weight: 500; }

.ask-foot { display: flex; gap: .6rem; justify-content: flex-end; }
.ask-foot .btn-quiet { padding: .6rem .9rem; }
.ask-foot .btn-primary { padding: .6rem 1.3rem; }

/* ---------- shopping list ----------
   Built for a phone held in one hand in a supermarket: full screen on small
   screens, big tap targets, and a line that strikes through when tapped. */
.shop-dialog {
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: var(--washi);
  color: var(--sumi);
  padding: 0;
  width: min(32rem, calc(100vw - 2rem));
  max-height: min(44rem, calc(100vh - 4rem));
  overflow: auto;
  overscroll-behavior: contain;
}
.shop-dialog::backdrop { background: rgba(15, 20, 25, .55); }

.shop-head {
  position: sticky;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem 1.2rem .9rem;
  background: var(--washi);
  border-bottom: 1px solid var(--rule);
}
.shop-head h2 { margin: 0; font-size: 1.05rem; letter-spacing: .02em; }
.shop-close {
  font: inherit; font-size: 1.5rem; line-height: 1;
  min-width: 2.75rem; min-height: 2.75rem;
  color: var(--sumi-faint);
  background: none; border: 0; cursor: pointer;
}
.shop-close:hover { color: var(--sumi); }

.shop-dishes {
  margin: 0;
  padding: .9rem 1.2rem 0;
  font-size: .78rem;
  line-height: 1.5;
  color: var(--sumi-faint);
}

.shop-list { list-style: none; margin: .6rem 0 0; padding: 0 1.2rem; }
.shop-item { border-bottom: 1px solid var(--rule); }
.shop-item:last-child { border-bottom: 0; }
.shop-item label {
  display: flex; align-items: center; gap: .8rem;
  padding: .7rem 0;                 /* a comfortable tap target */
  cursor: pointer;
}
.shop-item input { width: 1.15rem; height: 1.15rem; flex: 0 0 auto; accent-color: var(--ai); }
.shop-text { font-size: .95rem; line-height: 1.35; }
.shop-item.done .shop-text { text-decoration: line-through; color: var(--sumi-faint); }
.shop-subhead {
  padding: 1.4rem 0 .5rem;
  font-size: .7rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--sumi-faint);
  border-bottom: 1px solid var(--rule);
}
.shop-item-note {
  display: block;
  padding: 0 0 .7rem 1.95rem;
  font-size: .74rem;
  color: var(--sumi-faint);
}

.shop-note {
  margin: 0;
  padding: 1rem 1.2rem 0;
  font-size: .72rem;
  line-height: 1.5;
  color: var(--sumi-faint);
}
.shop-foot {
  position: sticky; bottom: 0;
  padding: .9rem 1.2rem 1.1rem;
  background: var(--washi);
  border-top: 1px solid var(--rule);
  margin-top: 1rem;
}
.shop-foot .btn-quiet { width: 100%; }

.whoami {
  margin: 0;
  font-size: .72rem;
  letter-spacing: .04em;
  color: var(--sumi-faint);
}
.btn-quiet[disabled]:hover { color: var(--sumi-soft); border-color: var(--rule); }

:focus-visible { outline: 2px solid var(--ai); outline-offset: 3px; }

.status {
  margin: 0;
  font-size: .78rem;
  line-height: 1.45;
  color: var(--sumi-faint);
  min-height: 1.4em;
}
.status.error { color: var(--shu); }

/* ---------- colophon ---------- */

.colophon {
  max-width: 38rem;
  margin: clamp(3rem, 8vw, 5.5rem) auto 0;
  padding-top: 2.4rem;
  border-top: 1px solid var(--rule);
  color: var(--sumi-soft);
}
.colophon h2 {
  margin: 0 0 1rem;
  font-family: "Shippori Mincho", serif;
  font-size: 1.02rem;
  font-weight: 600;
  letter-spacing: .06em;
  color: var(--sumi);
}
.colophon p { margin: 0 0 1rem; font-size: .9rem; text-wrap: pretty; }

/* The tagging note. Sits under the colophon, in the space that was blank
   between the tray and the footer, so that adding a recipe later does not mean
   going back to the README to remember what it needs. */
.howto { margin-top: clamp(2rem, 5vw, 3rem); }
.howto-list {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: .35rem 1.2rem;
  margin: 0 0 1.2rem;
  font-size: .9rem;
}
.howto-list dt { color: var(--sumi); }
.howto-list dd { margin: 0; }
.howto code {
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: .84em;
  padding: .1rem .3rem;
  border-radius: 3px;
  background: var(--kinari-deep);
  color: var(--sumi);
}

footer {
  max-width: 38rem;
  margin: 0 auto;
  padding: 2.5rem 1.5rem 4rem;
  text-align: center;
  font-size: .8rem;
  color: var(--sumi-faint);
}
footer a { color: inherit; }

/* Narrow enough that a side column would squeeze the tray: the controls go
   back above it, laid out across instead of down. */
@media (max-width: 64rem) {
  .layout { grid-template-columns: minmax(0, 1fr); gap: 1.4rem; }
  .tray-wrap, .controls { grid-column: 1; grid-row: auto; }
  .controls { position: static; gap: 1rem; }
  .diet { flex-direction: row; justify-content: center; flex-wrap: wrap; gap: .4rem; }
  .diet-opt { align-items: center; padding: .5rem 1rem .45rem; }
  /* The controls run across the page here, so these two centre with them
     rather than stretching over the full width. */
  .menu { gap: 1rem; }
  .find { width: 100%; max-width: 26rem; margin: 0 auto; }
  .find-label, .find-hint { text-align: center; }
  .openin { align-items: center; }
  .actions {
    flex-direction: row; justify-content: center; align-items: center;
    flex-wrap: wrap; gap: 1rem;
    padding-top: 1.1rem;
  }
  .btn-primary { padding: .78rem 2.1rem; }
  .status { text-align: center; }
  .planner-date { width: auto; }
}

/* Below three columns the tray arrangement cannot hold, so it becomes an
   ordinary list and the note about placement is withdrawn rather than left
   describing something the reader cannot see. */
@media (max-width: 46rem) {
  .tray { grid-template-columns: repeat(2, 1fr); }
  .dish { grid-area: auto !important; }
  .tray-note { display: none; }

  /* On a phone this page is for deciding what to eat and what to buy. Planning
     it into a calendar and signing in to do so are desk jobs, so they come off
     the screen entirely rather than sitting there as dead controls. */
  #ics, #signin, #whoami, #plan-date { display: none !important; }

  /* Same reasoning for the tagging note: it is there for the evening you add a
     recipe, not for the aisle. */
  .howto { display: none !important; }

  /* ---------- the menu, on a phone ----------
     Here the controls sit above the tray and push the meal off the screen, so
     the dietary choice, the search and the "openen in" toggle go behind one
     button and the tray comes straight into view. Deliberately NOT in the
     menu: "Stel opnieuw samen" and de boodschappenlijst. Those two are what
     you reach for without thinking, and a menu in front of them would be a
     tap you pay every time. */
  .menu { display: none; }

  .menu-toggle {
    display: grid;
    place-items: center;
    position: absolute;
    top: .9rem;
    left: .9rem;
    width: 2.75rem;
    height: 2.75rem;      /* a thumb target, not an icon */
    padding: 0;
    border: 1px solid var(--rule);
    border-radius: 2px;
    background: var(--washi);
    cursor: pointer;
    z-index: 30;
  }
  .masthead { position: relative; }

  /* three bars, drawn rather than shipped as an asset */
  .menu-bars,
  .menu-bars::before,
  .menu-bars::after {
    content: "";
    display: block;
    width: 1.05rem;
    height: 1px;
    background: var(--sumi);
  }
  .menu-bars { position: relative; }
  .menu-bars::before { position: absolute; top: -.32rem; }
  .menu-bars::after  { position: absolute; top:  .32rem; }

  body.menu-open .menu-bars { background: transparent; }
  body.menu-open .menu-bars::before { top: 0; transform: rotate(45deg); }
  body.menu-open .menu-bars::after  { top: 0; transform: rotate(-45deg); }

  body.menu-open .menu {
    display: flex;
    gap: 1.1rem;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 25;
    padding: 4.4rem 1.1rem 1.3rem;   /* clear of the button itself */
    max-height: 100dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--washi);
    border-bottom: 1px solid var(--rule);
    box-shadow: 0 18px 40px -26px var(--shadow);
  }
  body.menu-open .menu-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 24;
    background: rgba(15, 20, 25, .45);
  }
  /* the page behind it should not scroll away under the panel */
  body.menu-open { overflow: hidden; }

  /* in the panel the search is the thing you came for, so it goes full width */
  .menu .find { max-width: none; }
  .menu .find-results { max-height: 50vh; }
  .openin { display: flex; align-items: flex-start; }

  /* The shopping list takes the whole screen: it is the thing being read while
     walking around a shop. */
  .shop-dialog {
    width: 100vw;
    max-width: none;
    height: 100dvh;
    max-height: none;
    border: 0;
    border-radius: 0;
    margin: 0;
  }
  .shop-head { padding: 1.2rem 1.1rem 1rem; }
  .shop-head h2 { font-size: 1.15rem; }
  .shop-list { padding: 0 1.1rem; }
  .shop-text { font-size: 1.02rem; }
  .shop-item label { padding: .85rem 0; }
  .shop-foot { padding: 1rem 1.1rem calc(1rem + env(safe-area-inset-bottom)); }
}

@media (max-width: 26rem) {
  .tray { grid-template-columns: 1fr; }
  .dish { flex-direction: row; text-align: left; gap: 1rem; align-items: flex-start; }
  .dish > .bowl { flex: 0 0 auto; width: 4.6rem; }
  .slot-label { justify-content: flex-start; margin-top: .1rem; }
  .slot-about { max-width: none; }
  .lock { top: 0; right: auto; left: 3.3rem; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}
