/* Suppermode. Hand-written, no framework, no build step.

   Enamelware, not parchment. Cookbooks default to cream paper and terracotta,
   which is a picture of a cookbook rather than of cooking. A kitchen is also
   porcelain, cast iron, and the blue of a gas flame -- so the page is porcelain,
   the text is a deep slate-green black, and the one accent is flame blue, spent
   on the things you can act on.

   Newsreader is self-hosted rather than linked from a font CDN: this app has a
   privacy policy, and a page that phones a third party to render its own text
   makes that policy harder to keep. Variable, so one file covers every weight. */

@font-face {
  font-family: "Newsreader";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("fonts/newsreader-latin.0a301b6df4c7.woff2") format("woff2");
}

@font-face {
  font-family: "Newsreader";
  font-style: italic;
  font-weight: 300 700;
  font-display: swap;
  src: url("fonts/newsreader-latin-italic.6d201901085f.woff2") format("woff2");
}

:root {
  --ink: #15211c;
  --ink-soft: #4c5b54;
  --ink-faint: #5b6a62;
  --paper: #f3f6f3;
  --paper-raised: #ffffff;
  --rule: #dce4df;
  --accent: #1a56db;
  --accent-soft: #e7eeff;
  --danger: #9f2d2d;
  --measure: 42rem;
  --serif: "Newsreader", ui-serif, Georgia, serif;
  --sans: ui-sans-serif, system-ui, -apple-system, "Helvetica Neue", sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 18px/1.65 var(--serif);
  font-optical-sizing: auto;
  -webkit-text-size-adjust: 100%;
}

main {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 2rem 1.25rem 4rem;
}

h1, h2, h3 {
  font-family: var(--serif);
  line-height: 1.15;
  letter-spacing: -0.015em;
  font-weight: 600;
}

h1 { font-size: 2rem; margin: 0 0 0.5rem; }

/* Sentence case, not tracked-out capitals. A section label is a heading, and
   setting it in small caps says "label" without saying anything useful. */
h2 {
  font-size: 1.15rem;
  color: var(--ink-soft);
  margin: 2.75rem 0 0.75rem;
  font-weight: 500;
}

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }

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

.badge:focus-visible { outline-color: var(--paper); outline-offset: -5px; }

/* Header and footer */

.site-header {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: baseline;
  justify-content: space-between;
  max-width: var(--measure);
  margin: 0 auto;
  padding: 1.25rem;
  border-bottom: 1px solid var(--rule);
}

.wordmark {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.1rem;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-decoration: none;
}

.site-header nav { display: flex; gap: 1rem; align-items: center; font-size: 0.9rem; }

.site-footer {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 2rem 1.25rem 3rem;
  border-top: 1px solid var(--rule);
  display: flex;
  gap: 1.25rem;
  font-size: 0.85rem;
}

/* Controls */

/* The accent is spent here and on the things a cook changed. Those are the two
   kinds of thing on this site you can act on, so they look alike. */
.button {
  display: inline-block;
  background: var(--accent);
  color: #fff;
  padding: 0.6rem 1.15rem;
  border: 0;
  border-radius: 2px;
  font: 600 0.9rem/1 var(--sans);
  text-decoration: none;
  cursor: pointer;
}

.button:hover { background: var(--ink); }
.button--large { padding: 0.8rem 1.6rem; font-size: 1rem; }
.button--danger { background: var(--danger); }

.link-button {
  background: none;
  border: 0;
  padding: 0;
  color: var(--accent);
  font: inherit;
  font-size: 0.9rem;
  cursor: pointer;
  text-decoration: underline;
}

.inline-form { display: inline; }

input[type="text"], input[type="email"], input[type="password"],
input[type="search"], input[type="datetime-local"], select, textarea {
  width: 100%;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: var(--paper-raised);
  font: inherit;
  color: var(--ink);
}

textarea { resize: vertical; }

.field { margin: 0 0 1.1rem; }
.field label {
  display: block;
  font: 600 0.85rem/1.4 ui-sans-serif, system-ui, sans-serif;
  margin-bottom: 0.3rem;
}
.field small { display: block; color: var(--ink-faint); font-size: 0.8rem; margin-top: 0.25rem; }

/* A checkbox group: the fieldset names the question, so its default border and
   padding would draw a box around something that is not boxed elsewhere. The
   per-option labels sit beside their checkbox instead of above it, which is the
   one place .field label's display:block is wrong. */
.field-group { border: 0; padding: 0; margin: 0 0 1.1rem; min-inline-size: 0; }
.field-group legend {
  padding: 0;
  font: 600 0.85rem/1.4 ui-sans-serif, system-ui, sans-serif;
  margin-bottom: 0.3rem;
}
.field-group label {
  display: flex;
  gap: 0.45rem;
  align-items: baseline;
  font-weight: 400;
  margin-bottom: 0.35rem;
}

.error, .errors { color: var(--danger); font-size: 0.85rem; }
.errors { padding-left: 1.1rem; }

.stacked-form { max-width: 34rem; }

/* Authentication pages come from django-allauth, whose markup we do not own: no
   classes, bare labels and inputs, a <ul> of password rules. Styled by element
   inside the page rather than by class, which is the one situation that justifies it.
   Scoped to .auth-page so it cannot leak into forms we do write. */
/* The measure again, not a max-width on main: overriding main alone centres the
   form inside a wider header and footer, so the page reads as misaligned. */
.auth-page { --measure: 30rem; }
.auth-page h1 { font-size: 1.75rem; margin-bottom: 0.4rem; }
.auth-page form { margin-top: 1.5rem; }
.auth-page form p { margin: 0 0 1.1rem; }
.auth-page label { display: block; font-weight: 600; font-size: 0.9rem; margin-bottom: 0.3rem; }
.auth-page input[type="email"],
.auth-page input[type="text"],
.auth-page input[type="password"] { width: 100%; }
/* main, not the whole page: the site's own message list is a <ul> that
   base.html renders above <main>, inside this same body, and an unscoped
   rule sets a sign-out notice in password-help bullets. */
.auth-page main ul { padding-left: 1.1rem; color: var(--ink-faint); font-size: 0.88rem; }
.auth-page button[type="submit"] {
  background: var(--accent);
  color: #fff;
  padding: 0.6rem 1.15rem;
  border: 0;
  border-radius: 2px;
  font: 600 0.9rem/1 var(--sans);
  cursor: pointer;
}

.search { margin: 1.25rem 0 0.5rem; }

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

/* Messages */

.messages { max-width: var(--measure); margin: 1rem auto 0; padding: 0 1.25rem; list-style: none; }
.message {
  padding: 0.6rem 0.9rem;
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  font-size: 0.9rem;
  margin-bottom: 0.5rem;
}
.message--error { border-color: var(--danger); background: #fbeaea; }

.empty { color: var(--ink-faint); font-style: italic; }
.reassurance { color: var(--ink-faint); font-size: 0.85rem; }

/* Landing.

   The page is wider than the app's reading measure, because its argument is made
   by two pictures rather than by prose. */

/* One variable, so the header, the page and the footer widen together and stay
   aligned with each other. */
.landing-page { --measure: 58rem; }

.landing-page h2 {
  font-size: clamp(1.35rem, 2.4vw, 1.65rem);
  color: var(--ink);
  font-weight: 500;
  letter-spacing: -0.02em;
  max-width: 28ch;
  margin: 4rem 0 0.9rem;
  text-wrap: balance;
}

/* The connect page is a how-to whose headings are the only thing dividing one
   assistant's steps from the other's. Present, but quieter than the landing
   page's, which are carrying an argument rather than signposting a procedure. */
.guide-page h2 {
  font-size: 1.3rem;
  color: var(--ink);
  font-weight: 600;
  margin: 3rem 0 0.75rem;
}

/* At the app's reading measure three claims fit two columns, which strands the
   third beside an empty cell. Three permissions read as a list anyway.

   Capped to the same measure as .wide: in one column the claim paragraphs
   otherwise run the full container while the prose around them stops at 56ch,
   which puts two line lengths on one page and reads as two designs. */
.guide-page .claims { grid-template-columns: 1fr; gap: 1.25rem; max-width: 56ch; }

/* A how-to's title should not be set at the landing page's volume. */
.guide-page .hero h1 { font-size: clamp(1.9rem, 4vw, 2.6rem); }

/* The card is its own heading, and sits inside the hero. */
.landing-page .card__title { font-size: 1.5rem; color: var(--ink); margin: 0; max-width: none; }

/* Landing and connect both link to a section by id, so the heading must not
   land under the top edge of the window. */
section[id] { scroll-margin-top: 1.5rem; }

.hero { padding: 1.5rem 0 0; }

.hero h1 {
  font-size: clamp(2.3rem, 6.4vw, 4.2rem);
  font-weight: 500;
  letter-spacing: -0.032em;
  line-height: 1.02;
  margin: 0 0 1.25rem;
  max-width: 21ch;
}

.hero__lede {
  font-size: 1.2rem;
  color: var(--ink-soft);
  max-width: 46ch;
  margin: 0 0 1.75rem;
}

/* Where it lives. App-store grammar, because that is the convention people already
   read as "this works inside a thing you have". Two lines, the assistant's name
   carrying the weight. */

.connect { display: flex; flex-wrap: wrap; gap: 0.75rem; margin: 0 0 1rem; }

.badge {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 12.5rem;
  padding: 0.65rem 1.25rem;
  background: var(--ink);
  color: var(--paper);
  border-radius: 6px;
  text-decoration: none;
  line-height: 1.15;
}

.badge:hover { background: #0d1613; }
.badge__lead { font: 500 0.72rem/1.2 var(--sans); opacity: 0.75; }
.badge__name { font: 600 1.25rem/1.2 var(--serif); letter-spacing: -0.015em; }

.connect__alt { font-size: 0.95rem; color: var(--ink-soft); margin: 0 0 1rem; }

.wide { max-width: 56ch; color: var(--ink-soft); }

/* What using it actually sounds like. Two turns, no interface chrome, because the
   point is that there is no interface. */

.exchange {
  margin: 1.5rem 0 0;
  display: grid;
  gap: 0.9rem;
  max-width: 44rem;
}

.exchange__said,
.exchange__did {
  margin: 0;
  padding: 0.95rem 1.2rem;
  border-radius: 10px;
  line-height: 1.5;
}

.exchange__said {
  background: var(--accent-soft);
  border: 1px solid #cddafc;
  justify-self: start;
  max-width: 34rem;
}

.exchange__did {
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  justify-self: end;
  max-width: 34rem;
  color: var(--ink-soft);
}

/* Connect page */

.address {
  display: inline-block;
  font: 0.95rem/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 0.5rem 0.8rem;
  word-break: break-all;
}

/* The literal scope string, beside the plain-English description of it. Set apart
   rather than folded into the sentence: it is the token a connector's own consent
   screen will show, so a reader can match one page to the other. */
.scope-name {
  font: 0.8rem/1.4 ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--ink-faint);
  white-space: nowrap;
}

.steps-guide { max-width: 52ch; padding-left: 1.3rem; }
.steps-guide li { margin-bottom: 0.6rem; }

/* A prompt to send to an assistant, set apart so it reads as something to copy
   rather than as the page talking. */
.prompt {
  max-width: 52ch;
  margin: 0.5rem 0 0;
  padding: 0.7rem 0.9rem;
  background: var(--paper-raised);
  border-left: 3px solid var(--rule);
  font-style: italic;
}

/* The card: a recipe with its cook notes beside it. This is the product, drawn
   rather than described -- the physical thing it replaces is an index card with
   years of pencil corrections down the side. */

.card {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  margin: 3rem 0 0;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 3px;
}

.card__recipe { padding: 1.9rem 1.9rem 2.1rem; }

.card__title {
  font-size: 1.5rem;
  margin: 0;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.card__version {
  display: block;
  color: var(--ink-faint);
  font-size: 0.92rem;
  font-style: italic;
  margin: 0.15rem 0 1.4rem;
}

.card__ingredients { list-style: none; padding: 0; margin: 0 0 1.4rem; }
.card__ingredients li { padding: 0.32rem 0; border-bottom: 1px dotted var(--rule); }
.card__steps { margin: 0; padding-left: 1.2rem; }
.card__steps li { margin-bottom: 0.55rem; }

/* A value that a cook changed. The margin note that changed it shares the colour;
   that is the whole link, and it survives every screen width. */
.changed {
  color: var(--accent);
  font-weight: 600;
  box-shadow: inset 0 -0.4em 0 var(--accent-soft);
}

.card__margin {
  border-left: 1px solid var(--rule);
  background: linear-gradient(180deg, var(--paper) 0%, var(--paper-raised) 100%);
  padding: 1.9rem 1.6rem;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.note { margin: 0; font-style: italic; color: var(--ink); line-height: 1.5; }

/* Sits at the foot of the margin, where a running total belongs on a card that
   has been written on for two years. */
.card__footnote {
  margin: auto 0 0;
  padding-top: 1.2rem;
  border-top: 1px solid var(--rule);
  color: var(--ink-faint);
  font-size: 0.9rem;
  line-height: 1.45;
}

.note__meta {
  display: block;
  font-style: normal;
  font-size: 0.82rem;
  color: var(--ink-faint);
  margin-top: 0.4rem;
}

/* The thread: what those notes accumulate into. Genuinely a sequence, so it is
   marked as one. */

.thread { list-style: none; padding: 0; margin: 1.5rem 0 0; }

.thread li {
  display: grid;
  grid-template-columns: 7.5rem 1fr;
  gap: 1.5rem;
  padding: 0 0 1.6rem;
  border-left: 2px solid var(--rule);
  margin-left: 0.4rem;
  padding-left: 1.6rem;
  position: relative;
}

.thread li:last-child { border-left-color: transparent; padding-bottom: 0; }

.thread li::before {
  content: "";
  position: absolute;
  left: -0.42rem;
  top: 0.45rem;
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 50%;
  background: var(--paper);
  border: 2px solid var(--rule);
}

.thread li.is-version::before { background: var(--accent); border-color: var(--accent); }

.thread__when {
  color: var(--ink-faint);
  font-size: 0.9rem;
  font-style: italic;
  padding-top: 0.1rem;
}

.thread__what { margin: 0; }
.thread__what strong { font-weight: 600; }

.thread li.is-cook .thread__what { color: var(--ink-soft); }

/* Closing points. Three short claims, no cards, no icons. */

.claims {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16.5rem, 1fr));
  grid-template-rows: auto auto;
  gap: 1.75rem 2.5rem;
  margin: 1.5rem 0 0;
  padding: 0;
  list-style: none;
}

.claims li {
  margin: 0;
  display: grid;
  grid-row: span 2;
  grid-template-rows: subgrid;
  gap: 0.3rem;
}
.claims h3 { font-size: 1.08rem; margin: 0; font-weight: 600; }
.claims p { margin: 0; color: var(--ink-soft); font-size: 0.97rem; }

.closing { margin: 3.5rem 0 0; padding: 2.25rem 0 0; border-top: 1px solid var(--rule); }
.closing p { margin: 0 0 1.25rem; font-size: 1.2rem; max-width: 46ch; text-wrap: balance; }

/* Below this the badges wrap one per row anyway, and a 12.5rem badge on a
   24rem screen leaves a ragged right edge. */
@media (max-width: 30rem) {
  .badge { flex: 1 1 12.5rem; }
}

@media (max-width: 40rem) {
  .card { grid-template-columns: 1fr; }
  .card__margin {
    border-left: 0;
    border-top: 1px solid var(--rule);
    background: var(--paper);
  }
  .thread li { grid-template-columns: 1fr; gap: 0.3rem; }
}

.how dl { margin: 0; }
.how dt {
  font: 600 1rem/1.4 ui-sans-serif, system-ui, sans-serif;
  margin-top: 1.25rem;
}
.how dd { margin: 0.2rem 0 0; color: var(--ink-soft); }

/* Cookbook list */

.recipe-list { list-style: none; padding: 0; margin: 0; }
.recipe-list__item {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1rem;
  align-items: baseline;
  justify-content: space-between;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--rule);
}
.recipe-list__title { font-size: 1.05rem; text-decoration: none; }
.recipe-list__title:hover { text-decoration: underline; }
.recipe-list__meta {
  font: 0.8rem/1.4 ui-sans-serif, system-ui, sans-serif;
  color: var(--ink-faint);
  white-space: nowrap;
}

/* Recipe detail */

.recipe__meta, .recipe__facts {
  font: 0.85rem/1.5 ui-sans-serif, system-ui, sans-serif;
  color: var(--ink-faint);
}
.recipe__facts { display: flex; flex-wrap: wrap; gap: 1rem; }
.recipe__description { color: var(--ink-soft); }

.ingredients { list-style: none; padding: 0; margin: 0; }
.ingredients li { padding: 0.3rem 0; border-bottom: 1px dotted var(--rule); }
.steps { padding-left: 1.4rem; }
.steps li { margin-bottom: 0.7rem; }
.step__detail {
  display: inline-block;
  font: 0.78rem/1 ui-sans-serif, system-ui, sans-serif;
  color: var(--ink-faint);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 0.15rem 0.35rem;
  margin-left: 0.3rem;
}

.recipe__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  align-items: center;
  margin-top: 3rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule);
  font-size: 0.9rem;
}

/* Sharing */

.share p { color: var(--ink-soft); font-size: 0.95rem; }
.share__link { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 0.75rem; }
.share__link input { flex: 1 1 16rem; min-width: 0; font-family: var(--sans); font-size: 0.85rem; }
.shared__footer {
  margin-top: 3rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule);
  font: 0.85rem/1.5 var(--sans);
  color: var(--ink-faint);
}

/* Cooks */

.log-cook {
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 1.1rem;
  max-width: 34rem;
}

.cook-list { list-style: none; padding: 0; margin: 0; }
.cook {
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--rule);
}
.cook__date, .cook__version, .cook__rating {
  font: 0.78rem/1 ui-sans-serif, system-ui, sans-serif;
  color: var(--ink-faint);
  margin-right: 0.6rem;
}
.cook__version {
  background: var(--accent-soft);
  color: var(--accent);
  padding: 0.15rem 0.4rem;
  border-radius: 2px;
}
.cook__observations { margin: 0.4rem 0 0; }

/* Lineage: the screen the whole thesis rests on. */

.lineage { list-style: none; padding: 0; margin: 0; }
.lineage__step {
  position: relative;
  padding: 0 0 1.75rem 1.5rem;
  border-left: 2px solid var(--rule);
}
.lineage__step:last-child { border-left-color: transparent; }
.lineage__step::before {
  content: "";
  position: absolute;
  left: -6px;
  top: 0.45rem;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--rule);
}
.lineage__step--current::before { background: var(--accent); }
.lineage__label {
  display: flex;
  gap: 0.6rem;
  align-items: baseline;
  font: 0.85rem/1.4 ui-sans-serif, system-ui, sans-serif;
}
.lineage__date { color: var(--ink-faint); }
.lineage__badge {
  background: var(--accent);
  color: var(--paper);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.1rem 0.35rem;
  border-radius: 2px;
}
.lineage__title { margin: 0.2rem 0 0.15rem; font-weight: 600; }
.lineage__reason { margin: 0; color: var(--ink-soft); }
.lineage__reason--muted { color: var(--ink-faint); font-style: italic; }
.lineage__evidence {
  list-style: none;
  margin: 0.6rem 0 0;
  padding: 0.5rem 0.75rem;
  background: var(--accent-soft);
  border-radius: 2px;
  font-size: 0.9rem;
}
.lineage__evidence li + li { margin-top: 0.35rem; }

.danger { border-top: 1px solid var(--rule); margin-top: 3rem; padding-top: 1rem; }
.danger h2 { color: var(--danger); }

/* Pagination */

.pagination {
  display: flex;
  gap: 1rem;
  align-items: baseline;
  margin-top: 1.5rem;
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
  font: 0.85rem/1.4 ui-sans-serif, system-ui, sans-serif;
}
.pagination__status { color: var(--ink-faint); }
