/* The one stylesheet of the app. The layout is one column that fits a phone first. */

/* The server holds the typeface file, because the security policy permits no outside source. */
@font-face {
  font-family: 'Plus Jakarta Sans';
  src: url('/fonts/plus-jakarta-sans.woff2') format('woff2');
  font-weight: 200 800;
  font-display: swap;
}

/* The app has one set of colours. The page is a soft grey-green that is not white, so it is
   calm by day and by night. */
:root {
  color-scheme: light;
  --text: #1d2523;
  --muted: #55605c;
  --page: #e1e5e2;
  --field: #eef0ee;
  --line: #c2c9c5;
  --accent: #2b4a52;
  --on-accent: #eef1ef;
  --danger: #8c2e27;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  font: 17px/1.55 'Plus Jakarta Sans', system-ui, sans-serif;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0 auto;
  /* The top padding keeps text below the strip that iOS blurs. */
  padding: 30px 20px 56px;
  max-width: 38rem;
  color: var(--text);
  background: var(--page);
}

/* The navigation is a row of links on a wide screen and a menu button on a narrow screen. */
nav {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 24px;
}

nav a {
  color: var(--text);
  text-decoration: none;
}

nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* The mark of the site. The file is a mask, and the background gives the colour. */
.logo {
  display: block;
  width: 34px;
  aspect-ratio: 58 / 53;
  background: var(--accent);
  -webkit-mask: url('/logo.svg') center / contain no-repeat;
  mask: url('/logo.svg') center / contain no-repeat;
}

/* The sign-in page and the enrolment page show a large mark in the centre, above the button. */
.logo.large {
  width: 72px;
  margin: 24px auto 40px;
}

/* The mark in the top row of a wide screen opens the first page. */
.home {
  display: flex;
  align-items: center;
  min-height: 46px;
  margin-right: 14px;
}

.drawer-top {
  display: flex;
  align-items: center;
}

/* A wide screen shows the links in the top row, and it has no menu button. */
.links {
  display: flex;
  gap: 28px;
}

.links a {
  display: inline-flex;
  align-items: center;
  min-height: 46px;
  font-weight: 500;
}

.menu-button {
  display: none;
  width: 46px;
  padding: 0;
  color: var(--text);
  background: transparent;
  border-color: var(--muted);
}

/* A narrow screen shows the menu button, and the links are in the panel. */
@media (max-width: 40rem) {
  .links,
  .home {
    display: none;
  }

  /* The menu button is at the top right corner of the page, and of the panel. */
  .menu-button {
    display: flex;
    margin-left: auto;
  }

  body {
    position: relative;
  }

  nav {
    position: absolute;
    top: 30px;
    right: 20px;
    margin: 0;
  }

  /* The heading of the page shares the top row with the menu button. */
  nav + main h1 {
    min-height: 46px;
    padding: 6px 60px 0 0;
  }
}

/* The panel of the menu comes in from the right edge and covers a part of the page. */
.drawer {
  position: fixed;
  inset: 0 0 0 auto;
  width: min(80vw, 19rem);
  height: 100dvh;
  max-height: none;
  margin: 0;
  /* The top padding puts the close button at the place of the menu button. */
  padding: 30px 20px;
  overflow-y: auto;
  color: var(--text);
  background: var(--page);
  border: 0;
  border-left: 1px solid var(--line);
  translate: 100% 0;
  transition:
    translate 0.2s ease-out,
    overlay 0.2s allow-discrete,
    display 0.2s allow-discrete;
}

.drawer:popover-open {
  translate: 0 0;
}

@starting-style {
  .drawer:popover-open {
    translate: 100% 0;
  }
}

/* The rest of the page is dim while the panel is open. A press on it closes the panel. */
.drawer::backdrop {
  background: rgb(20 26 24 / 0.35);
}

@media (prefers-reduced-motion: reduce) {
  .drawer {
    transition: none;
  }
}

.drawer ul {
  margin-top: 16px;
  border-top: 1px solid var(--line);
}

.drawer li {
  border-bottom: 1px solid var(--line);
}

/* The whole row of a link is the tap target. */
.drawer li a {
  display: flex;
  align-items: center;
  min-height: 56px;
  font-size: 1.1rem;
  font-weight: 500;
}

/* Three bars make the menu sign. The close button shows a cross. */
.bars,
.bars::before,
.bars::after {
  display: block;
  width: 20px;
  height: 2px;
  background: var(--text);
}

.bars {
  position: relative;
}

.bars::before,
.bars::after {
  content: '';
  position: absolute;
  left: 0;
}

.bars::before {
  top: -6px;
}

.bars::after {
  top: 6px;
}

.cross {
  background: transparent;
}

.cross::before {
  top: 0;
  rotate: 45deg;
}

.cross::after {
  top: 0;
  rotate: -45deg;
}

h1 {
  margin: 0 0 20px;
  font-size: 1.75rem;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.015em;
  overflow-wrap: anywhere;
}

h2 {
  margin: 32px 0 10px;
  font-size: 1rem;
  font-weight: 600;
}

a {
  color: var(--accent);
}

p[role='alert'] {
  margin: 0;
  color: var(--danger);
}

/* A control is at least 44 px high, so a finger can hit it. */
/* The 1rem font size stops the zoom that iOS does on a small input. */
input,
textarea,
button,
.button {
  font: inherit;
  font-size: 1rem;
  min-height: 46px;
  padding: 10px 14px;
  border: 1px solid transparent;
  border-radius: 2px;
}

input,
textarea {
  display: block;
  width: 100%;
  color: var(--text);
  background: var(--field);
  border-color: var(--line);
}

textarea {
  resize: vertical;
}

label {
  display: grid;
  gap: 6px;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--muted);
}

button,
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 500;
  color: var(--on-accent);
  background: var(--accent);
  text-decoration: none;
  cursor: pointer;
}

button:disabled {
  opacity: 0.6;
  cursor: default;
}

.ghost {
  color: var(--text);
  background: transparent;
  border-color: var(--muted);
}

/* A button that takes the full width of the column. */
.wide {
  width: 100%;
}

.danger {
  color: var(--danger);
  background: transparent;
  border-color: var(--danger);
}

/* A button changes its fill a little under a mouse pointer. A touch screen has no pointer. */
@media (hover: hover) {
  button:hover:not(:disabled),
  .button:hover {
    background: color-mix(in srgb, var(--accent) 88%, white);
  }

  .ghost:hover:not(:disabled) {
    background: color-mix(in srgb, var(--text) 7%, transparent);
  }

  .menu-button:hover:not(:disabled) {
    background: color-mix(in srgb, var(--text) 7%, transparent);
  }

  .more summary:hover,
  .icon:hover,
  .frame button:hover:not(:disabled) {
    background: color-mix(in srgb, var(--text) 7%, transparent);
  }

  .danger:hover:not(:disabled) {
    background: color-mix(in srgb, var(--danger) 9%, transparent);
  }
}

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

.stack {
  display: grid;
  gap: 18px;
  margin-bottom: 24px;
}

/* The ingredient rows of the recipe form. Each row holds a name, an amount and a button. */
.ingredients {
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

.ingredients legend {
  margin-bottom: 6px;
  padding: 0;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--muted);
}

/* All rows share one frame, as a small table. A line separates two rows and two cells. */
.frame {
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: 2px;
}

.frame input,
.frame button {
  background: transparent;
  border: 0;
  border-radius: 0;
}

/* The focus mark of a cell is inside the cell, so the next cell does not cover it. */
.frame :focus-visible {
  outline-offset: -2px;
}

.ingredient-row {
  display: flex;
  border-bottom: 1px solid var(--line);
}

.ingredient-row .suggest {
  flex: 1;
  min-width: 0;
}

.ingredient-row .amount {
  flex: 0 0 5.5rem;
  border-left: 1px solid var(--line);
}

/* The button with a cross removes the row. */
.ingredient-row .remove {
  flex: 0 0 46px;
  padding: 0;
  font-size: 1.2rem;
  color: var(--muted);
  border-left: 1px solid var(--line);
}

/* The last line of the frame adds a row. */
.frame .add {
  width: 100%;
  justify-content: flex-start;
  color: var(--accent);
}

.section {
  margin-top: 32px;
}

.actions {
  display: flex;
  gap: 10px;
}

/* A page heading with a button at its right end. */
.heading {
  display: flex;
  align-items: flex-start;
  gap: 4px;
}

.heading h1 {
  flex: 1;
  min-width: 0;
}

/* On a narrow screen, the menu button of the site is at the right of this row. */
@media (max-width: 40rem) {
  nav + main .heading {
    padding-right: 54px;
  }

  nav + main .heading h1 {
    padding-right: 0;
  }
}

/* A button with three dots that opens a small menu for the rare actions of a page. The
   button has no outline, and the menu opens below it. */
.more {
  position: relative;
}

.more summary {
  width: 36px;
  padding: 0;
  list-style: none;
  background: transparent;
}

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

.more[open] summary {
  background: color-mix(in srgb, var(--text) 7%, transparent);
}

.dots,
.dots::before,
.dots::after {
  display: block;
  width: 4px;
  height: 4px;
  background: var(--text);
  border-radius: 50%;
}

.dots {
  position: relative;
}

.dots::before,
.dots::after {
  content: '';
  position: absolute;
  top: 0;
}

.dots::before {
  left: -8px;
}

.dots::after {
  left: 8px;
}

.more-menu {
  position: absolute;
  z-index: 1;
  right: 0;
  top: calc(100% + 4px);
  min-width: 12rem;
  background: var(--page);
  border: 1px solid var(--muted);
  border-radius: 2px;
}

.more-menu button {
  width: 100%;
  justify-content: flex-start;
  border: 0;
  border-radius: 0;
}

/* A question in the centre of the screen, above the page. The rest of the page is dim, and a
   press on it closes the question. */
.confirm {
  width: min(22rem, calc(100vw - 40px));
  padding: 24px 20px;
  color: var(--text);
  background: var(--page);
  border: 1px solid var(--line);
  border-radius: 2px;
}

.confirm::backdrop {
  background: rgb(20 26 24 / 0.35);
}

.confirm h2 {
  margin: 0 0 20px;
  font-size: 1.15rem;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

/* The search form of the recipe list. */
.filters {
  display: grid;
  gap: 18px;
}

/* A row with a field that takes the free width, and a button at its right. */
.bar {
  display: flex;
  gap: 10px;
}

.bar input,
.bar .suggest {
  flex: 1;
  min-width: 0;
}

/* A name field with the list of the known names that match the typed text. The list is
   directly below the field, and it has the width of the field. */
.suggest {
  position: relative;
}

.suggestions {
  position: absolute;
  z-index: 1;
  top: 100%;
  left: 0;
  right: 0;
  margin: 2px 0 0;
  padding: 0;
  list-style: none;
  /* A long list stays short, and the person moves in it. */
  max-height: 272px;
  overflow-y: auto;
  background: var(--field);
  border: 1px solid var(--muted);
  border-radius: 2px;
}

.suggestions li {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 8px 14px;
  cursor: pointer;
}

.suggestions li + li {
  border-top: 1px solid var(--line);
}

.suggestions li[aria-selected='true'] {
  background: color-mix(in srgb, var(--text) 9%, transparent);
}

@media (hover: hover) {
  .suggestions li:hover {
    background: color-mix(in srgb, var(--text) 9%, transparent);
  }
}

.bar .button,
.bar button {
  flex: none;
}

/* The search field shows the search sign at its left. */
.find {
  padding-left: 42px;
  background: var(--field) url('/search.svg') 14px center / 18px no-repeat;
  appearance: none;
}

/* A row of small choices that continues on the next line. A choice that is on has a fill. */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.filters + .chips {
  margin-top: 18px;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 38px;
  padding: 0 14px;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--text);
  text-decoration: none;
  border: 1px solid var(--muted);
  border-radius: 2px;
  cursor: pointer;
}

.chip.on {
  color: var(--on-accent);
  background: var(--accent);
  border-color: var(--accent);
}

/* A field that holds its choices as boxes, with a text field after them for the next choice.
   The frame has the look of a field, and an arrow at its right shows that it opens a list. */
.pills {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  min-height: 46px;
  padding: 6px 40px 6px 6px;
  background: var(--field) url('/chevron.svg') right 14px center / 14px no-repeat;
  border: 1px solid var(--line);
  border-radius: 2px;
  cursor: text;
}

.pills:focus-within {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.pills input {
  flex: 1 1 8.5rem;
  width: auto;
  min-width: 0;
  min-height: 32px;
  padding: 0 8px;
  background: transparent;
  border: 0;
  outline: none;
}

.pills .chip {
  min-height: 32px;
  padding: 0 10px;
}

/* The category part of the recipe form. */
.categories {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

.categories legend {
  margin-bottom: 6px;
  padding: 0;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--muted);
}

.rows {
  margin: 20px 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--line);
}

.rows li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 56px;
  padding: 4px 0;
  border-bottom: 1px solid var(--line);
}

/* The whole row of a link is the tap target. */
.rows li > a {
  flex: 1;
  min-width: 0;
  padding: 8px 0;
  color: var(--text);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.rows .title {
  display: block;
  font-weight: 500;
  line-height: 1.3;
}

/* The ingredient names of a recipe, on one line below its title. */
.rows .sub {
  display: block;
  font-size: 0.85rem;
  line-height: 1.4;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* A button in a heading row that shows a sign and no text. It has no outline. */
.icon {
  flex: none;
  width: 36px;
  padding: 0;
  background: transparent;
}

/* The sign of the edit action. The file is a mask, and the background gives the colour. */
.pencil {
  width: 20px;
  height: 20px;
  background: var(--text);
  -webkit-mask: url('/pencil.svg') center / contain no-repeat;
  mask: url('/pencil.svg') center / contain no-repeat;
}

/* The categories of a recipe, below its heading. Each box opens the list with that filter. */
.chips.small {
  gap: 6px;
  margin-top: -8px;
}

.chips.small .chip {
  min-height: 28px;
  padding: 0 10px;
  font-size: 0.85rem;
}

.recipe h2 {
  margin-top: 28px;
}

/* The ingredients of a recipe. The amounts are a column at the left, with the right edges in
   one line. The names are a second column. */
.amounts {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 6px 14px;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-wrap: anywhere;
}

.amounts li {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
}

.amounts .amount {
  max-width: 7rem;
  font-weight: 600;
  text-align: right;
}

/* A recipe with no amounts has one column of names. */
.amounts.none {
  grid-template-columns: 1fr;
}

/* The steps of a recipe. Each step has its number at the left. */
.steps {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
  overflow-wrap: anywhere;
}

.steps li {
  position: relative;
  padding: 0 0 14px 34px;
  counter-increment: step;
}

.steps li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0;
  font-weight: 600;
  color: var(--accent);
}

/* The bar and its panel are for a narrow screen only. */
.pin,
.sheet {
  display: none;
}

/* A wide screen shows the ingredients at the left of the steps. The ingredients stay in view
   while the steps move. A list that is higher than the screen moves by itself. */
@media (min-width: 40.01rem) {
  .columns {
    display: grid;
    grid-template-columns: 15rem 1fr;
    gap: 0 40px;
    align-items: start;
  }

  .columns .side {
    position: sticky;
    top: 0;
    max-height: 100dvh;
    padding-bottom: 20px;
    overflow-y: auto;
  }
}

@media (max-width: 40rem) {
  /* The bar is fixed at the top of the screen. Its text is below the strip that iOS blurs.
     The bar is not visible until the browser code adds the `on` class. */
  .pin {
    position: fixed;
    z-index: 2;
    inset: 0 0 auto;
    display: flex;
    justify-content: space-between;
    width: 100%;
    min-height: 64px;
    padding: 26px 20px 8px;
    font-weight: 600;
    color: var(--text);
    background: var(--page);
    border: 0;
    border-bottom: 1px solid var(--line);
    border-radius: 0;
    visibility: hidden;
  }

  .pin.on {
    visibility: visible;
  }

  .pin:focus-visible {
    outline-offset: -2px;
  }

  .chevron {
    width: 14px;
    height: 14px;
    background: url('/chevron.svg') center / contain no-repeat;
  }

  .chevron.up {
    rotate: 180deg;
  }

  /* The panel covers the bar and shows the ingredients above the steps. Its first row has
     the look of the bar, and a press on it closes the panel. */
  .sheet:popover-open {
    display: block;
  }

  .sheet {
    position: fixed;
    inset: 0 0 auto;
    width: 100%;
    max-width: none;
    max-height: 85dvh;
    margin: 0;
    padding: 0 0 20px;
    overflow-y: auto;
    color: var(--text);
    background: var(--page);
    border: 0;
    border-bottom: 1px solid var(--line);
  }

  .sheet .pin {
    position: sticky;
    top: 0;
  }

  .sheet .amounts {
    padding: 14px 20px 0;
  }

  .sheet::backdrop {
    background: rgb(20 26 24 / 0.35);
  }
}
