/*
 * Stylesheet for the generated ingredient pages (PLAN-INGREDIENT-PAGES
 * A1-A4, B1).
 *
 * A hand-written file, not a generated one: nothing in it depends on the
 * catalog, so there is nothing for `scripts/ingredients.ts` to derive. It
 * lives here, in `public/`, rather than in `src/styles.css` for the same
 * reason the generator writes plain strings instead of importing a templating
 * library — a page in `public/` is copied to `dist/` verbatim, with no build
 * step, so it cannot link an asset that only exists after Vite hashes it. One
 * small stylesheet shared by ~2,900 pages costs one request, which a browser
 * caches after the first ingredient page; inlining it per page would have
 * cost that many copies of the same rules instead.
 *
 * The palette restates the app's dark tokens (see `src/styles.css`'s own
 * note) rather than importing either stylesheet: this file has to stand alone
 * under a plain `<link>` with no build step to reconcile it against a second
 * copy of the same variables. It restates them *exactly* — the same `oklch()`
 * values, not hex approximations of them. The first version of this file
 * carried `#171717` where the site says `oklch(0.145 0 0)` and `#c7c7c7`
 * where it says `oklch(0.78 0 0)`; near-misses like those are what make a
 * page feel like a different site rather than a different section.
 *
 * The fonts are restated the same way, for the same reason: this file cannot
 * import `src/styles.css`'s own `@font-face` rules, so it declares its own
 * against the same self-hosted files in `public/fonts/` (already shipped for
 * the five hand-written pages) rather than falling back to the system stack —
 * a system font here read as a different site from the one either side of it.
 *
 * ## Where the accent goes, and where it does not
 *
 * `src/styles.css` states the rule these pages have to live by: `--wort` is
 * "the page's one accent, which it already spends on figures that matter".
 * Links there are `--copper`, a near-white, underlined.
 *
 * This file's first version invented an `--accent: #ffca5a` and painted every
 * link on every one of ~2,900 pages with it. On a leaf carrying a breadcrumb,
 * a source link, a dozen substitutes and a call to action, that is a page of
 * yellow with prose in the gaps — the accent stops marking anything, because
 * a colour that is on everything distinguishes nothing.
 *
 * So: links are `--copper`, the site's own treatment, and the studio control
 * is `.btn-solid` — also `--copper`, because that is what the homepage's
 * primary button is. Figures are set apart by mono and by contrast rather
 * than by hue, which keeps a specification table calm at ten rows.
 *
 * The result is a palette with no hue in it at all, and `--wort` and `--hop`
 * are deliberately not declared below so that nothing here can reach for one
 * without adding it back on purpose. That is not a compromise: it is what the
 * studio does on the same material. `detail-panel.tsx` draws an entry's
 * provenance, stock and id in greys and tells the two provenances apart by
 * filling one badge and outlining the other. A page whose job is to be read
 * does not need a colour to hold attention, and the accent stays available to
 * the surfaces that have a figure worth shouting about.
 */

@font-face {
  font-family: "Inter Variable";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/inter-latin-wght.woff2") format("woff2-variations");
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F,
    U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/plex-mono-latin-400.woff2") format("woff2");
}

:root {
  color-scheme: dark;

  /* The top safe-area inset — 0 unless the page is an installed window; see
     the display-mode rule below. */
  --safe-top: 0px;

  /* App `.dark` tokens, restated so these pages do not import the SPA —
     the same values `src/styles.css` carries, so a reader crossing from the
     homepage to a malt page crosses no seam. */
  --paper: oklch(0.145 0 0);
  --paper-raised: oklch(0.205 0 0);
  --paper-band: oklch(0.18 0 0);
  --ink: oklch(0.985 0 0);
  --ink-2: oklch(0.78 0 0);
  --ink-3: oklch(0.708 0 0);
  --rule: oklch(1 0 0 / 12%);
  --rule-strong: oklch(1 0 0 / 18%);
  --copper: oklch(0.922 0 0);
  --copper-hover: oklch(1 0 0);
  --on-solid: oklch(0.205 0 0);
  /* The app's `--secondary`, which is what fills a `<Badge variant="secondary">`. */
  --chip: oklch(0.269 0 0);
  --shadow: 0 1px 2px rgb(0 0 0 / 40%), 0 18px 40px -18px rgb(0 0 0 / 70%);
  --radius: 0.625rem;

  --font-sans:
    "Inter Variable", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
}

/* A page can only sit under the status bar as an installed, home-screen
   window. In a browser tab the browser's own chrome holds the status bar, and
   the in-app browsers inside Facebook and Instagram — iOS and Android alike —
   report the device's inset anyway, though they sit below their own toolbar,
   so a header that trusted it opened with an empty band above it. */
@media (display-mode: standalone), (display-mode: fullscreen) {
  :root {
    --safe-top: env(safe-area-inset-top, 0px);
  }
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  /* The site's body settings, not the browser's. 16px/1.5 against the
     homepage's 17px/1.65 was the second thing making these pages read as
     somebody else's. */
  font-size: 1.0625rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

a {
  color: var(--copper);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

a:hover {
  color: var(--copper-hover);
}

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

/*
 * ## The site header
 *
 * Restated from `src/styles.css`'s `.site-head`, for the reason at the top of
 * this file — a `public/` page has no build step and cannot link a hashed
 * stylesheet, so the rules are copied rather than shared.
 *
 * It is deliberately not the homepage's header: that one carries eleven
 * in-page anchors (`#studio`, `#water`, `#pricing`…) which mean nothing on a
 * malt page. This carries the mark and the one control, and leaves saying
 * where you are to the breadcrumb below it.
 */
.site-head {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  padding-top: var(--safe-top);
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

.head-inner {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  width: min(100% - 2.5rem, 66rem);
  margin-inline: auto;
  min-height: 4rem;
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  /* Never shrinks: `.wordmark-name` is `nowrap`, so with `min-width: 0` it
     would be squeezed below its own content and overflow its box rather than
     getting narrower. Same reasoning, and the same failure, as
     `src/styles.css` records for the homepage header. */
  flex: none;
  /* Holds the one control against the right edge. */
  margin-right: auto;
  color: var(--ink);
  text-decoration: none;
}

.wordmark-mark {
  display: inline-flex;
  flex-shrink: 0;
}

.wordmark-mark img {
  display: block;
  width: 2.6rem;
  height: auto;
}

.wordmark-name {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 0.9rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1;
  white-space: nowrap;
}

.head-actions {
  flex: none;
}

/*
 * The site's own button, restated. `--copper` and not `--wort`: the homepage's
 * `.btn-solid` is near-white, and the studio control on these pages is the
 * same control, so it is the same colour. (An earlier pass here made it wort
 * gold, which looked deliberate on one page and like a second brand beside
 * the real header on every other.)
 */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font-family: var(--font-sans);
  font-weight: 600;
  line-height: 1;
  border-radius: calc(var(--radius) - 2px);
  border: 1px solid transparent;
  text-decoration: none;
  transition:
    background-color 140ms ease,
    border-color 140ms ease,
    color 140ms ease;
}

.btn-solid {
  background: var(--copper);
  border-color: var(--copper);
  color: var(--on-solid);
}

.btn-solid:hover {
  background: var(--copper-hover);
  border-color: var(--copper-hover);
  color: var(--on-solid);
}

.btn-sm {
  padding: 0.55rem 0.9rem;
  font-size: 0.88rem;
}

.page {
  max-width: 44rem;
  margin: 0 auto;
  padding: 1.75rem 1.25rem 5rem;
}

/* Prose wants a shorter line than a specification table does. Holding
   paragraphs to their own measure lets `.page` stay wide enough for a `dl`
   with a long label and a long value on one row. */
p.description,
.related-note,
.provenance {
  max-width: 38rem;
}

/*
 * The breadcrumb, which now sits under the header rather than standing in for
 * one. It no longer repeats the brand — the wordmark above links home — so it
 * says only where in the estate this page is.
 */
.crumb {
  margin: 0 0 2rem;
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  letter-spacing: 0.02em;
  color: var(--ink-3);
}

.crumb a {
  color: var(--ink-2);
  text-decoration: none;
}

.crumb a:hover {
  color: var(--ink);
  text-decoration: underline;
}

/* The page's own name is the one crumb that is not a link. */
.crumb [aria-current="page"] {
  color: var(--ink-3);
}

/*
 * Small section labels — "DESCRIPTION", "SOURCE", the kind above the title.
 * Mono, uppercase and tracked, which is the idiom `src/styles.css` already
 * uses for a label that is not prose. Set smaller than the body, never
 * larger: caps, mono and tracking each add weight on their own.
 */
.kind {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
}

h1 {
  margin: 0.5rem 0 0.5rem;
  font-size: clamp(1.85rem, 3.4vw, 2.4rem);
  line-height: 1.15;
  letter-spacing: -0.015em;
}

.maker {
  margin: 0 0 1.5rem;
  color: var(--ink-2);
}

/*
 * Provenance, as the app draws it.
 *
 * `apps/web/src/components/ingredients/detail-panel.tsx` puts this on a
 * `<Badge>` in the entry's header — `secondary` (filled) for a spec sheet,
 * `outline` for a representative value — and leaves the sentence to a
 * `title` tooltip. This page cannot do the tooltip half: a `title` is
 * invisible on a phone and unreliable to a screen reader, and the sentence is
 * the substance of the claim rather than a nicety. So the badge is the app's,
 * and the explanation follows it as quiet prose.
 *
 * What it replaced was a bordered callout with a coloured left rule — a
 * component this design system does not have anywhere else, which read as a
 * warning banner rather than as a label on the entry. Filled against outline
 * is how the app tells these two apart, so it is how these pages do too.
 */
.provenance {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  margin: 0 0 2rem;
}

.provenance-note {
  font-size: 0.875rem;
  color: var(--ink-3);
}

/*
 * `badgeVariants` from `apps/web/src/components/ui/badge.tsx`, restated: a
 * bordered pill at `text-xs`, `font-medium`, `rounded-md`.
 */
.badge {
  display: inline-flex;
  align-items: center;
  flex: none;
  padding: 0.125rem 0.375rem;
  border: 1px solid transparent;
  border-radius: 0.375rem;
  font-size: 0.75rem;
  font-weight: 500;
  line-height: 1.35;
  white-space: nowrap;
}

/* `variant="secondary"`: filled, no border. */
.badge-spec-sheet {
  background: var(--chip);
  color: var(--ink);
}

/* `variant="outline"`: the border shows, the fill does not. */
.badge-representative {
  border-color: var(--rule);
  color: var(--ink);
}

h2 {
  margin: 2.5rem 0 0.75rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/*
 * The specification table. Values are mono and near-white against `--ink-3`
 * labels: at ten rows, contrast and family separate a figure from its name
 * more calmly than colour does, and the accent stays spent on the one
 * action at the foot of the page.
 */
dl.specs {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0;
  margin: 0;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--paper-raised);
  font-size: 0.875rem;
  overflow: hidden;
}

dl.specs dt,
dl.specs dd {
  padding: 0.55rem 1.1rem;
  border-top: 1px solid var(--rule);
}

/* The first row of each column carries the container's own edge instead. */
dl.specs dt:first-of-type,
dl.specs dt:first-of-type + dd {
  border-top: 0;
}

dl.specs dt {
  color: var(--ink-3);
}

dl.specs dd {
  margin: 0;
  text-align: right;
  font-family: var(--font-mono);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/*
 * The tag chips sit directly after the specification table, with no heading
 * of their own, so spacing is the only thing saying what they belong to.
 * At `margin: 0` they butted against the table's bottom edge and read as one
 * more row of it, while the next section — a full `h2` margin away — looked
 * unrelated to anything. They keep a smaller gap above than the section
 * below leaves, which puts them with the entry's figures where they belong.
 */
.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 1.25rem 0 0;
  padding: 0;
  list-style: none;
}

.tags li {
  padding: 0.2rem 0.65rem;
  border-radius: 999px;
  border: 1px solid var(--rule);
  background: var(--paper-band);
  font-size: 0.75rem;
  color: var(--ink-2);
}

/*
 * Related entries — substitutes, cultivar siblings, the yeast family. A
 * handful of links that belong to the sentence above them, so they stay
 * chips: inline, self-contained, obviously pressable.
 */
ul.related {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

ul.related a {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.4rem 0.75rem;
  border-radius: var(--radius);
  border: 1px solid var(--rule);
  background: var(--paper-raised);
  text-decoration: none;
  font-size: 0.875rem;
  color: var(--ink-2);
  transition:
    border-color 120ms ease,
    color 120ms ease,
    background-color 120ms ease;
}

ul.related a:hover {
  border-color: var(--rule-strong);
  background: var(--paper-band);
  color: var(--ink);
}

/*
 * Who banks it, above what they call it — "Also sold as" lists one strain
 * under several labs' names, so the lab is the discriminator and the name is
 * the detail. Set as a label rather than as prose so it cannot be misread as
 * part of the strain's own name.
 */
.related-meta {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}

ul.related a:hover .related-meta {
  color: var(--ink-2);
}

.related-name {
  line-height: 1.3;
}

.related-note {
  margin: 0 0 0.75rem;
  font-size: 0.875rem;
  color: var(--ink-3);
}

/*
 * The index pages (PLAN-INGREDIENT-PAGES B1): a front door at /ingredients
 * and one page per kind grouped by maker/lab/origin/type.
 *
 * These used to share `ul.related`'s chip styling, on the argument that both
 * are "a list of links to other ingredient pages". That holds for the six
 * substitutes on a leaf and breaks completely at the scale an index actually
 * runs to: Weyermann alone is a wall of ragged pills with no shared left
 * edge, which is the hardest possible shape to scan for a name you already
 * know. A column grid gives every entry the same starting x, so the eye runs
 * down one edge instead of hunting across three.
 */
ul.index-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

ul.index-list a {
  display: block;
  padding: 0.4rem 0.6rem;
  border-radius: 0.375rem;
  text-decoration: none;
  font-size: 0.9375rem;
  color: var(--ink-2);
  transition:
    background-color 120ms ease,
    color 120ms ease;
}

ul.index-list a:hover {
  background: var(--paper-raised);
  color: var(--ink);
}

.index-group h2 {
  margin-bottom: 0.5rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--rule);
  /* A maker's own name is content, not a label: it keeps its capitalisation,
     its sans face and a size that reads as a heading rather than a tag. */
  font-family: var(--font-sans);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: normal;
  text-transform: none;
  color: var(--ink);
}

.index-count {
  margin-left: 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--ink-3);
}

.index-group ul.index-list {
  margin-bottom: 2.5rem;
}

.kind-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1rem;
  margin-top: 2rem;
}

/* The line under the cards pointing at /styles: a gap that says it follows
   the cards rather than belonging to the last one. */
.styles-pointer {
  margin-top: 1.75rem;
}

.kind-card {
  padding: 1.25rem 1.4rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--paper-raised);
  transition: border-color 120ms ease;
}

.kind-card:hover {
  border-color: var(--rule-strong);
}

.kind-card h2 {
  margin: 0 0 0.375rem;
  font-family: var(--font-sans);
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: normal;
  text-transform: none;
  color: var(--ink);
}

.kind-card h2 a {
  text-decoration: none;
  color: inherit;
}

.kind-card h2 a:hover {
  text-decoration: underline;
}

.kind-card p {
  margin: 0;
  color: var(--ink-2);
  font-size: 0.9375rem;
}

.source a {
  font-size: 0.9375rem;
}

.pdf-note {
  color: var(--ink-3);
  font-size: 0.8125rem;
}

p.description {
  color: var(--ink-2);
}

/*
 * The style pages (PLAN-STYLE-PAGES). Three flavor wheels side by side where
 * they fit and stacked where they do not; each one is a band ring and its
 * labels, drawn in the same greys as the rest of the estate. The ring is ink
 * at low alpha, the app radar's `foreground/15`, and the grid is the rule.
 */
.wheels {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 1rem;
  justify-content: space-between;
  margin-top: 1rem;
}

.wheel-figure {
  flex: 1 1 14rem;
  max-width: 19rem;
  margin: 0;
}

.wheel-figure figcaption {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--ink);
  text-align: center;
}

svg.wheel {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.wheel-grid {
  fill: none;
  stroke: var(--rule-strong);
  stroke-width: 1;
}

.wheel-band {
  fill: oklch(0.985 0 0 / 22%);
}

.wheel-labels {
  fill: var(--ink-3);
  font-family: var(--font-sans);
  font-size: 10px;
}

.wheel-sentence {
  margin: 0.25rem 0 0;
  font-size: 0.875rem;
  color: var(--ink-2);
  text-align: center;
}

/* The style index: number, name and two figures on one line, in columns
   that line up down the page, because a brewer scans it for a number. */
ul.style-list {
  margin: 0 0 2.5rem;
  padding: 0;
  list-style: none;
}

ul.style-list a {
  display: grid;
  grid-template-columns: 3rem 1fr auto;
  gap: 0.75rem;
  align-items: baseline;
  padding: 0.4rem 0.6rem;
  border-radius: 0.375rem;
  text-decoration: none;
  color: var(--ink-2);
  transition:
    background-color 120ms ease,
    color 120ms ease;
}

ul.style-list a:hover {
  background: var(--paper-raised);
  color: var(--ink);
}

.style-number,
.style-figures {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

.style-name {
  font-size: 0.9375rem;
}

/* The two hop lists on a style page, each under a small heading of its own. */
section h3 {
  margin: 1.5rem 0 0.25rem;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--ink);
}

p.attribution {
  margin-top: 3rem;
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
  font-size: 0.8125rem;
  color: var(--ink-3);
}

@media (max-width: 34rem) {
  .page {
    padding: 1.25rem 1rem 3.5rem;
  }

  /* On a phone the figures drop under the name rather than squeezing it. */
  ul.style-list a {
    grid-template-columns: 2.75rem 1fr;
  }

  .style-figures {
    grid-column: 2;
  }

  /* A label and its figure stop sharing a row when the row runs out of
     width: the value moves under its own label, still mono, still left of
     the reader's eye rather than pushed to a ragged right edge. */
  dl.specs {
    grid-template-columns: 1fr;
  }

  dl.specs dt {
    padding-bottom: 0;
    border-top: 1px solid var(--rule);
  }

  dl.specs dt:first-of-type + dd {
    border-top: 0;
  }

  dl.specs dd {
    padding-top: 0.15rem;
    text-align: left;
    border-top: 0;
  }
}

/*
 * Every transition this file declares, switched off — named individually
 * rather than swept with `* { transition: none !important }`, which the lint
 * rightly refuses. This block is last in the file, so at equal specificity it
 * wins on order and needs no `!important` at all.
 */
@media (prefers-reduced-motion: reduce) {
  .btn,
  .kind-card,
  ul.related a,
  ul.index-list a,
  ul.style-list a {
    transition: none;
  }
}
