/*
 * Matplan — mobile first, and meant literally.
 *
 * Three of the four screens are used standing up: at the counter with wet
 * hands, in a shop with a trolley in one hand, at the table planning the week.
 * So: one column, large type, generous tap targets, and nothing that depends on
 * hover — a hover affordance on a touch screen is an affordance that does not
 * exist.
 *
 * Colours follow the device. A kitchen at 18:00 in November is dark and a shop
 * is fluorescent; neither is a preference we should override.
 */

:root {
  color-scheme: light dark;

  --bg: #fbfaf7;
  --surface: #ffffff;
  --border: #e2ddd3;
  --text: #1c1a17;
  --muted: #6b655c;
  --accent: #146b4a;
  --accent-text: #ffffff;
  --danger: #a3261c;
  --warning-bg: #fdf3d8;

  --radius: 12px;
  --tap: 48px;              /* never smaller: a thumb is about 45px */
  --gap: 1rem;
  --measure: 34rem;         /* one comfortable column */
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #16150f;
    --surface: #211f18;
    --border: #383429;
    --text: #f0ece2;
    --muted: #a49c8c;
    --accent: #4fbf8b;
    --accent-text: #0d1a13;
    --danger: #ef8279;
    --warning-bg: #2f2a16;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font: 1.05rem/1.55 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  /* Safe areas, because this is used full-screen on a phone. */
  padding: env(safe-area-inset-top) env(safe-area-inset-right)
           env(safe-area-inset-bottom) env(safe-area-inset-left);
}

main {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 1.5rem 1.15rem 5rem;
}

h1 { font-size: 1.6rem; line-height: 1.2; margin: 0 0 0.25rem; }
h2 { font-size: 1.2rem; margin: 2rem 0 0.5rem; }
p  { margin: 0 0 1rem; }
a  { color: var(--accent); }

.lead { color: var(--muted); margin-bottom: 2rem; }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.15rem;
  margin-bottom: var(--gap);
}
/* The first thing in a card never adds space above itself — the padding is
   already there. This used to be `style="margin-top:0"` on twenty-two headings,
   which is the same rule written twenty-two times, and it is written here now
   because the Content-Security-Policy forbids style attributes: `style-src
   'self'` with no 'unsafe-inline' is what makes the policy worth having, and
   every inline style is a reason to weaken it. */
.card > :first-child { margin-top: 0; }

label {
  display: block;
  font-weight: 600;
  margin-bottom: 0.4rem;
}

input[type="email"],
input[type="text"],
input[type="number"],
select,
textarea {
  width: 100%;
  min-height: var(--tap);
  padding: 0.6rem 0.75rem;
  font: inherit;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

/* 16px minimum, or iOS zooms the whole page on focus. */
input, select, textarea { font-size: max(1rem, 16px); }

button, .button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: var(--tap);
  width: 100%;
  padding: 0.7rem 1.1rem;
  font: inherit;
  font-weight: 600;
  color: var(--accent-text);
  background: var(--accent);
  border: 1px solid transparent;
  border-radius: var(--radius);
  text-decoration: none;
  cursor: pointer;
}

button.secondary, .button.secondary {
  color: var(--text);
  background: transparent;
  border-color: var(--border);
}

.notice, .error {
  padding: 0.85rem 1rem;
  border-radius: var(--radius);
  margin-bottom: var(--gap);
  background: var(--warning-bg);
  border: 1px solid var(--border);
}
.error { color: var(--danger); }

.muted { color: var(--muted); font-size: 0.92rem; }

/* The magic link, shown on screen only when mail is not configured. */
.devlink {
  display: block;
  word-break: break-all;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.85rem;
}

.sitehead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--gap);
  max-width: var(--measure);
  margin: 0 auto;
  padding: 1rem 1.15rem 0;
}
.sitehead .brand { font-weight: 700; text-decoration: none; color: var(--text); }
.sitehead form { display: inline; }
.sitehead button { width: auto; min-height: 2.2rem; padding: 0.25rem 0.7rem; font-size: 0.9rem; }

/* Min side: members and what they cannot eat. */

.rowhead {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  margin-bottom: 0.4rem;
}
.rowhead .muted { font-size: 0.85rem; }

ul.hensyn { list-style: none; margin: 0.5rem 0; padding: 0; }
ul.hensyn li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0;
  border-top: 1px solid var(--border);
}
ul.hensyn li:first-child { border-top: 0; }
ul.hensyn form { margin-left: auto; }

.tag {
  flex: none;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  background: var(--border);
  color: var(--muted);
}
/* A hard limit reads as a hard limit. An allergy shown the same weight as a
   dislike is an allergy somebody skims past. */
.tag.strict {
  background: var(--danger);
  color: #fff;
}

/* An inline destructive action. Still a real tap target — 44px of padded area
   around a small label, rather than a small label. */
button.linky {
  width: auto;
  min-height: auto;
  padding: 0.55rem 0.4rem;
  margin: -0.55rem 0;
  background: none;
  border: 0;
  color: var(--muted);
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: underline;
}

details { margin: 0.5rem 0; }
summary {
  min-height: var(--tap);
  display: flex;
  align-items: center;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
}
details[open] summary { margin-bottom: 0.5rem; }

/*
 * Seven destinations do not fit across a phone in one row — at 375px that is 53px
 * each, below a thumb and below legibility. A wrapping grid instead of a flex
 * row: four across on a phone, all seven on anything wider.
 */
nav.tabs {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.4rem;
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0.5rem 1.15rem 0;
}
@media (min-width: 44rem) {
  nav.tabs { grid-template-columns: repeat(8, 1fr); }
}
nav.tabs a {
  min-height: var(--tap);
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.95rem;
}
/* Seven labels at four columns: the longest must still fit without wrapping
   into a two-line tab that shoves the others out of alignment. */
nav.tabs a { font-size: 0.82rem; padding: 0 0.2rem; text-align: center; }
@media (min-width: 44rem) { nav.tabs a { font-size: 0.88rem; } }

nav.tabs a[aria-current="page"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-text);
}

/* Recipes. */

.actions { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-bottom: var(--gap); }
.actions > * { flex: 1 1 12rem; }
.actions form { display: flex; }
.actions form button { width: 100%; }

.searchbar { margin-bottom: var(--gap); }

ul.cards { list-style: none; margin: 0 0 1rem; padding: 0; }
ul.cards li { margin-bottom: 0.6rem; }
ul.cards a {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-height: var(--tap);
  padding: 0.85rem 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  text-decoration: none;
}
ul.cards .muted { font-size: 0.85rem; }

ul.ingredients { list-style: none; margin: 0.75rem 0 0; padding: 0; }
ul.ingredients li {
  display: flex;
  gap: 0.6rem;
  padding: 0.55rem 0;
  border-top: 1px solid var(--border);
}
ul.ingredients li:first-child { border-top: 0; }
/* The number in its own column, so the eye runs down the amounts rather than
   hunting for them inside a sentence. Tabular figures so they line up. */
.amount {
  flex: none;
  min-width: 4.5rem;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.scaler { display: flex; align-items: flex-end; gap: 0.6rem; flex-wrap: wrap; }
.scaler label { flex: 1 1 100%; margin-bottom: 0; }
.scaler input { flex: 1 1 6rem; }
.scaler button { flex: 0 0 auto; width: auto; }

textarea { min-height: 8rem; resize: vertical; line-height: 1.5; }

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

/* KI and usage. */

.stats { display: flex; flex-wrap: wrap; gap: 1.25rem; margin-bottom: 0.5rem; }
.stats > div { display: flex; flex-direction: column; }
.stat { font-size: 1.5rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.stats .muted { font-size: 0.85rem; }

/* Tables scroll inside their card rather than making the page scroll sideways,
   which on a phone is the difference between usable and not. */
.card table { width: 100%; border-collapse: collapse; display: block; overflow-x: auto; }
.card th, .card td {
  text-align: left;
  padding: 0.5rem 0.6rem 0.5rem 0;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.card th { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); }
.card td:last-child, .card th:last-child { text-align: right; padding-right: 0; font-variant-numeric: tabular-nums; }

/* Plan quota. A bar, because "83 %" means more next to a bar than alone. */

.quota { margin: 0.9rem 0; }
.quota-head { display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem; }
.quota-pct { font-weight: 700; font-variant-numeric: tabular-nums; }
.quota .muted { font-size: 0.82rem; margin: 0.25rem 0 0; }

.meter {
  height: 0.6rem;
  margin-top: 0.35rem;
  background: var(--border);
  border-radius: 999px;
  overflow: hidden;
}
.meter span {
  display: block;
  height: 100%;
  background: var(--accent);
  border-radius: 999px;
}
/* Colour only near the top. A bar that reddens at 40% teaches people to ignore
   it, which is the opposite of what a quota warning is for. */
.meter span.mid { background: #b07d18; }
.meter span.high { background: var(--danger); }
/* How full the bar is, in steps of five.
   A width has to come from the data, and the obvious way to write that is a
   style attribute — which is the one thing `style-src 'self'` refuses. Nor is a
   custom property a way round it: `style="--fill: 42%"` is still a style
   attribute. So the value is rounded to a step and named as a class.
   Five points is not a loss: the exact number is printed beside the bar, and a
   quota meter is read as "nearly full" or "plenty left" rather than measured. */
.meter span.w0 { width: 0%; }
.meter span.w5 { width: 5%; }
.meter span.w10 { width: 10%; }
.meter span.w15 { width: 15%; }
.meter span.w20 { width: 20%; }
.meter span.w25 { width: 25%; }
.meter span.w30 { width: 30%; }
.meter span.w35 { width: 35%; }
.meter span.w40 { width: 40%; }
.meter span.w45 { width: 45%; }
.meter span.w50 { width: 50%; }
.meter span.w55 { width: 55%; }
.meter span.w60 { width: 60%; }
.meter span.w65 { width: 65%; }
.meter span.w70 { width: 70%; }
.meter span.w75 { width: 75%; }
.meter span.w80 { width: 80%; }
.meter span.w85 { width: 85%; }
.meter span.w90 { width: 90%; }
.meter span.w95 { width: 95%; }
.meter span.w100 { width: 100%; }

code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.9em; }

/* Planlegg. */

.weeknav { display: flex; align-items: center; gap: 0.6rem; margin-bottom: var(--gap); }
.weeknav .button { flex: 0 0 auto; width: auto; padding: 0.5rem 0.9rem; }
.weeklabel { flex: 1; text-align: center; font-weight: 600; }

.card.day .dish { font-size: 1.1rem; font-weight: 600; margin: 0.2rem 0 0.3rem; }
.card.day form { display: inline; }

/* A flagged suggestion has to look different from three feet away, because that
   is the distance at which someone decides whether to read it. */
.card.flagged { border-color: var(--danger); border-width: 2px; }

label.check {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  min-height: var(--tap);
  font-weight: 400;
  cursor: pointer;
}
label.check input[type="checkbox"] {
  flex: none;
  width: 1.4rem;
  height: 1.4rem;
  margin-top: 0.15rem;
  accent-color: var(--accent);
}

/* Handle. The one screen used with a trolley in one hand and gloves on. */

ul.shoplist { list-style: none; margin: 0; padding: 0; }
ul.shoplist li { border-top: 1px solid var(--border); }
ul.shoplist li:first-child { border-top: 0; }
ul.shoplist form { display: block; }

/* The whole row is the tap target, not a checkbox inside it. */
button.tick {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  width: 100%;
  min-height: 3.4rem;
  padding: 0.6rem 0;
  background: none;
  border: 0;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.tick .box {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.9rem;
  height: 1.9rem;
  border: 2px solid var(--border);
  border-radius: 7px;
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--accent-text);
}
.tick .what { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem; }
.tick .name { font-size: 1.05rem; }
.tick .muted { font-size: 0.8rem; width: 100%; }

/* Ticked lines stay visible but recede — crossing them out is how you see what
   is left without losing your place. */
ul.shoplist li.done .tick { color: var(--muted); }
ul.shoplist li.done .name { text-decoration: line-through; }
ul.shoplist li.done .box { background: var(--accent); border-color: var(--accent); }

/* Lag mat. Read from a step back, with wet hands. */

h1.cook { font-size: 1.9rem; }
.card.today .dish { font-size: 1.35rem; font-weight: 700; margin: 0.2rem 0 0.8rem; }

ul.ingredients.cook li { font-size: 1.15rem; padding: 0.7rem 0; }
ul.ingredients.cook .amount { min-width: 5.5rem; }

.card.step { display: flex; gap: 0.9rem; align-items: flex-start; }
.card.step p { font-size: 1.15rem; line-height: 1.55; margin: 0; }
.stepno {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-text);
  font-weight: 700;
}

fieldset { border: 0; padding: 0; margin: 0.6rem 0; }
legend { font-weight: 600; padding: 0; margin-bottom: 0.2rem; }

.photos { display: grid; grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); gap: 0.6rem; }
.photos figure { margin: 0; }
.photos img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius);
  background: var(--border);
}
.photos figcaption { text-align: center; }

input[type="file"] {
  width: 100%;
  min-height: var(--tap);
  padding: 0.6rem 0.75rem;
  font: inherit;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.steprow { display: flex; gap: 0.9rem; align-items: flex-start; margin-bottom: 0.9rem; }
.steprow p { margin: 0; }

.muted.warn { color: var(--danger); font-weight: 600; }

/* A code is read off one screen and typed into another, often without glasses. */
input.code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 1.4rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-align: center;
}

/* The queue. */
.card.queued .scaler { margin-top: 0.5rem; }
.queueactions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.9rem;
  margin-top: 0.6rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--border);
}
.queueactions form { display: inline; }
.queueactions .linky { padding: 0.5rem 0.2rem; margin: -0.5rem 0; }

/* Row actions under a catalogue entry. */
.rowactions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  padding: 0.1rem 1rem 0.6rem;
}
.rowactions form { display: inline; }
.rowactions .linky { padding: 0.5rem 0.2rem; margin: -0.5rem 0; }
ul.cards li { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); }
ul.cards a { border: 0; background: none; }

/* A queue entry with no recipe behind it is not a link. */
.cardtext {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.85rem 1rem;
}

/* Inventory: confidence is shown by weight, because it is a guess either way. */
ul.hensyn li .name { font-weight: 600; }
li.conf-usikker .name { font-weight: 400; }
li.conf-gammel { opacity: 0.55; }
li.conf-gammel .name { font-weight: 400; text-decoration: line-through; }

/* The assistant thread. */
.card.sagt { background: var(--bg); border-style: dashed; }
.card.sagt p { margin: 0; font-weight: 600; }
.card.svar p:last-child { margin-bottom: 0; }

/* What it did, above what it said: the actions are the part worth checking. */
ul.gjorde {
  list-style: none;
  margin: 0 0 0.9rem;
  padding: 0 0 0.7rem;
  border-bottom: 1px solid var(--border);
}
ul.gjorde li {
  padding: 0.2rem 0 0.2rem 1.4rem;
  font-size: 0.9rem;
  color: var(--muted);
  position: relative;
}
ul.gjorde li::before {
  content: '→';
  position: absolute;
  left: 0;
  color: var(--accent);
}

/* A command meant to be copied and run somewhere else. */
code.cmd {
  display: block;
  padding: 0.7rem 0.85rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 0.95rem;
  user-select: all;
  overflow-x: auto;
}

/* One person's verdict, in a box of its own so several fit on a phone. */
fieldset.rating {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.75rem 0.9rem;
  margin: 0.7rem 0;
}
fieldset.rating legend { padding: 0 0.4rem; font-size: 0.9rem; }
fieldset.rating input[type="number"] { max-width: 6rem; }
