/*
 * The hub's stylesheet: the app's visual system (docs/features/design-system/
 * visual-system.md) carried over to the web. Every page on hub.rewindpix.com
 * links this one file, including the recipe pages that api/recipe.js renders,
 * so the site has one set of tokens and components.
 *
 * Tokens mirror lib/theme/rp_colors.dart, rp_layout.dart and
 * rp_typography.dart. Keep them in step when the app's change.
 *
 * Rules carried over from the app:
 * - Two themes, following the device (prefers-color-scheme).
 * - Square corners, no shadows. Cards are one step off the canvas with a 1px
 *   divider border.
 * - Orange marks what's active. The primary button is ink on orange.
 * - Archivo Expanded for page titles and film names, Inter for everything
 *   else. Michroma for the grey mark boxes (base film, process, ISO). Space
 *   Mono only for codes on black (edge print).
 * - Type sizes from the app's scale: 44, 28, 20, 16, 13, 11.
 *
 * Layout: one column on phones, two on screens 880px and wider. Pages set
 * the grid with .split; everything else stacks. The gallery's grids fill
 * as many 240px columns as fit, four at the widest.
 */

:root {
  color-scheme: light dark;

  /* Shared by both themes (RpPalette). */
  --accent: #f1542c;
  --on-accent: #1a1a1a;
  --yellow: #f0c417;
  --photo: #000000;
  --edge-print: #8a8a8a;
  --on-photo: #f1eee5;
  --on-photo-muted: #9ea3ac;

  /* Light theme (RpColors.light). */
  --canvas: #f1eee5;
  --raised: #faf8f3;
  --text: #1a1a1a;
  --muted: #5e6675;
  --disabled: #a9a59b;
  --line: #8c877c;
  --divider: #ddd8cc;
  --track: #ddd8cc;
  --active: #c9330d;
  --danger: #bf1f3f;
  --success: #17714a;

  --font-display: 'Archivo', 'Arial Black', sans-serif;
  --font-text: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: 'Space Mono', ui-monospace, monospace;

  /* RpSpace. The gutter is 20 on phones and 32 on wide screens. */
  --gutter: 20px;
  --card-pad: 16px;

  /* RpStroke. */
  --hairline: 1px;
  --control: 1.5px;
  --focus: 2px;

  /* RpMotion.tap and RpMotion.snap. */
  --tap: 90ms;
  --snap: cubic-bezier(0.2, 0.8, 0.2, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --canvas: #1a1a1a;
    --raised: #222222;
    --text: #f1eee5;
    --muted: #9ea3ac;
    --disabled: #5f6167;
    --line: #6e727b;
    --divider: #2e2e2e;
    --track: #3a3a3a;
    --active: #f1542c;
    --danger: #ff6b7f;
    --success: #2bb673;
  }
}

@media (min-width: 880px) {
  :root {
    --gutter: 32px;
    --card-pad: 24px;
  }
}

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  background: var(--canvas);
  color: var(--text);
  font-family: var(--font-text);
  font-size: 16px;
  line-height: 1.5;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
}

a {
  color: inherit;
}

:focus-visible {
  outline: var(--focus) solid var(--active);
  outline-offset: 2px;
}

/* Headings take focus from script when a view changes, for screen
 * readers; they aren't controls, so no ring. */
[tabindex='-1']:focus {
  outline: none;
}

[hidden] {
  display: none !important;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ---------------------------------------------------------------------------
 * Shell: header, page body, footer. The header carries the site's name in
 * the text face (the app doesn't use the wordmark).
 */

.site-header {
  border-bottom: var(--hairline) solid var(--divider);
}

.site-header-inner,
.site-footer-inner,
.page {
  width: 100%;
  max-width: 1264px;
  margin: 0 auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}

.site-header-inner {
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.site-name {
  font-weight: 600;
  font-size: 16px;
  text-decoration: none;
}

.site-name span {
  color: var(--muted);
  font-weight: 400;
}

.page {
  flex: 1;
  padding-top: 32px;
  padding-bottom: 48px;
}

.site-footer {
  border-top: var(--hairline) solid var(--divider);
}

.site-footer-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 24px;
  padding-top: 16px;
  padding-bottom: 24px;
  font-size: 13px;
  line-height: 18px;
  color: var(--muted);
}

.site-footer a {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  color: var(--muted);
  text-decoration: none;
}

.site-footer a:hover {
  color: var(--text);
}

/* Two columns on wide screens: the page's title on the left, the thing to
 * do on the right. One column, in source order, on phones. */
.split {
  display: grid;
  gap: 24px;
}

@media (min-width: 880px) {
  .page {
    padding-top: 64px;
    padding-bottom: 80px;
  }

  .split {
    grid-template-columns: minmax(0, 1fr) minmax(0, 440px);
    gap: 64px;
    align-items: start;
  }
}

/* Single-column pages (reset password, recipe not found) keep a readable
 * width on wide screens. */
.narrow {
  max-width: 440px;
}

.stack {
  display: grid;
  gap: 16px;
  align-content: start;
}

/* ---------------------------------------------------------------------------
 * Type. Titles are sentence case.
 */

.page-title {
  font-family: var(--font-display);
  font-stretch: 125%;
  font-variation-settings: 'wdth' 125;
  font-weight: 800;
  font-size: 28px;
  line-height: 34px;
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
}

@media (min-width: 880px) {
  .page-title {
    font-size: 44px;
    line-height: 50px;
  }
}

.title {
  font-size: 20px;
  line-height: 26px;
  font-weight: 600;
}

.body {
  font-size: 16px;
  line-height: 24px;
}

.caption {
  font-size: 13px;
  line-height: 18px;
  color: var(--muted);
}

.label {
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
}

.lede {
  margin-top: 12px;
  color: var(--muted);
  font-size: 16px;
  line-height: 24px;
  overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------------------
 * Surfaces
 */

.card {
  background: var(--raised);
  border: var(--hairline) solid var(--divider);
  padding: var(--card-pad);
}

.card > .title {
  margin-bottom: 16px;
}

/* Rows, as in Settings: a card of rows split by hairlines. */
.rows {
  background: var(--raised);
  border: var(--hairline) solid var(--divider);
}

.row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 56px;
  padding: 12px var(--card-pad);
}

.row + .row {
  border-top: var(--hairline) solid var(--divider);
}

.row-main {
  flex: 1;
  min-width: 0;
}

.row-main .caption {
  overflow-wrap: anywhere;
}

button.row {
  width: 100%;
  background: none;
  border: 0;
  border-top: var(--hairline) solid var(--divider);
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

button.row:first-child {
  border-top: 0;
}

a.row-link {
  border-top: var(--hairline) solid var(--divider);
  color: var(--text);
  text-decoration: none;
}

/* A row that goes somewhere: a chevron at the end, as in Settings. */
a.row-link::after {
  content: '';
  margin-left: auto;
  width: 8px;
  height: 8px;
  border-top: 2px solid var(--muted);
  border-right: 2px solid var(--muted);
  transform: rotate(45deg);
}

a.row-link:hover,
button.row:hover {
  background: color-mix(in srgb, var(--text) 4%, transparent);
}

.row-danger {
  color: var(--danger) !important;
}

/* A person's initial in a circle. Orange is the signed-in account (the
 * header, /account); everyone else sits on the raised surface. */
.avatar {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--raised);
  border: var(--hairline) solid var(--line);
  color: var(--text);
  display: grid;
  place-items: center;
  font-weight: 600;
  font-size: 16px;
  line-height: 1;
  text-transform: uppercase;
  text-decoration: none;
}

.avatar-accent {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

/* The PRO tag: ink on orange, like Settings. */
.tag {
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 6px;
  font-size: 11px;
  line-height: 14px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}

.tag-pro {
  background: var(--accent);
  color: var(--on-accent);
}

/* Chips: recipe tags. Drawn at 36, square, with a control outline. */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 36px;
  padding: 0 12px;
  border: var(--control) solid var(--line);
  color: var(--text);
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
  text-decoration: none;
  overflow-wrap: anywhere;
  transition: border-color var(--tap) var(--snap);
}

a.chip:hover {
  border-color: var(--text);
}

/* The current filter: orange, like a selected chip in the app. */
.chip-on,
a.chip-on:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

.chip-count {
  color: var(--muted);
  font-weight: 400;
}

/* ---------------------------------------------------------------------------
 * Buttons. 52 high at the default text size, square, Inter 600 16.
 */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 52px;
  padding: 12px 20px;
  border: var(--control) solid transparent;
  border-radius: 0;
  background: none;
  color: var(--text);
  font-family: var(--font-text);
  font-size: 16px;
  line-height: 22px;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--tap) var(--snap),
    border-color var(--tap) var(--snap), transform var(--tap) var(--snap);
}

.btn:active:not(:disabled) {
  transform: scale(0.985);
}

.btn:disabled {
  cursor: not-allowed;
}

.btn-block {
  display: flex;
  width: 100%;
}

.btn-primary {
  background: var(--accent);
  color: var(--on-accent);
}

.btn-primary:hover:not(:disabled) {
  background: color-mix(in srgb, var(--accent) 88%, #000);
}

.btn-primary:disabled {
  background: var(--divider);
  color: var(--disabled);
}

.btn-primary[aria-busy='true']:disabled {
  background: var(--accent);
  color: var(--on-accent);
}

.btn-secondary {
  border-color: var(--line);
}

.btn-secondary:hover:not(:disabled) {
  border-color: var(--text);
}

.btn-secondary:disabled {
  color: var(--disabled);
  border-color: var(--divider);
}

/* The text button: an underlined label, as the app's "Cancel". */
.btn-text {
  min-height: 48px;
  padding: 8px 12px;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.btn-text:hover:not(:disabled) {
  color: var(--active);
}

.btn-text.muted {
  color: var(--muted);
  font-weight: 400;
}

.btn-icon {
  width: 20px;
  height: 20px;
  flex: none;
}

.btn-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.center {
  display: flex;
  justify-content: center;
}

/* Waiting lines instead of a spinner: three short lines with a lit segment
 * drifting along them. Shown inside a busy button. */
.waiting {
  display: none;
  flex-direction: column;
  gap: 3px;
  width: 16px;
}

[aria-busy='true'] > .waiting {
  display: inline-flex;
}

.waiting i {
  display: block;
  height: 2px;
  background: linear-gradient(
      90deg,
      transparent 0 35%,
      currentColor 35% 65%,
      transparent 65%
    )
    0 0 / 300% 100%,
    color-mix(in srgb, currentColor 35%, transparent);
  animation: waiting 1.1s linear infinite;
}

.waiting i:nth-child(2) {
  animation-delay: -0.36s;
}

.waiting i:nth-child(3) {
  animation-delay: -0.72s;
}

@keyframes waiting {
  from {
    background-position: 100% 0, 0 0;
  }
  to {
    background-position: 0% 0, 0 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .waiting i {
    animation: none;
  }

  .btn {
    transition: none;
  }
}

/* ---------------------------------------------------------------------------
 * Fields: label above, 52 high, control outline, focus in orange.
 */

.field {
  display: grid;
  gap: 8px;
}

.field + .field {
  margin-top: 16px;
}

.field label {
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
}

.input-wrap {
  position: relative;
}

.input {
  display: block;
  width: 100%;
  height: 52px;
  padding: 0 16px;
  background: transparent;
  border: var(--control) solid var(--line);
  border-radius: 0;
  color: var(--text);
  font-family: var(--font-text);
  font-size: 16px;
  line-height: 24px;
  outline: none;
  -webkit-appearance: none;
  appearance: none;
}

.input:focus {
  border-color: var(--active);
  box-shadow: inset 0 0 0 0.5px var(--active);
}

.input[aria-invalid='true'] {
  border-color: var(--danger);
}

.input-wrap .input {
  padding-right: 52px;
}

.input-code {
  text-transform: uppercase;
  letter-spacing: 0.12em;
}

/* Show/hide password, inside the field on the right. 48 hit area. */
.reveal {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 48px;
  height: 48px;
  display: grid;
  place-items: center;
  background: none;
  border: 0;
  color: var(--muted);
  cursor: pointer;
}

.reveal:hover {
  color: var(--text);
}

.reveal svg {
  width: 24px;
  height: 24px;
}

.reveal .icon-hide,
.reveal[aria-pressed='true'] .icon-show {
  display: none;
}

.reveal[aria-pressed='true'] .icon-hide {
  display: block;
}

.field-error {
  font-size: 13px;
  line-height: 18px;
  color: var(--danger);
}

.form-actions {
  display: grid;
  gap: 4px;
  margin-top: 24px;
}

.form-actions .btn-block + .center {
  margin-top: 4px;
}

/* "—— or ——" between the providers and the email form. */
.or {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 24px 0;
  font-size: 13px;
  line-height: 18px;
  color: var(--muted);
}

.or::before,
.or::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--divider);
}

/* A note with a tone marker: a small square in the tone's colour, then the
 * words. Status, not instructions. */
.note {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 16px;
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
  overflow-wrap: anywhere;
}

.note::before {
  content: '';
  flex: none;
  width: 10px;
  height: 10px;
  transform: translateY(1px);
  background: var(--accent);
}

.note.error::before {
  background: var(--danger);
}

.note.success::before {
  background: var(--success);
}

.note.warning::before {
  background: var(--yellow);
}

/* Recipe page, gallery, comments and account: see the end of this file. */

/* The mode switch under the auth form ("Create account" / "Sign in
 * instead"), set off by a hairline. */
.card-footer {
  margin-top: 24px;
  padding-top: 8px;
  border-top: var(--hairline) solid var(--divider);
}

/* A card straight under a page title. */
.after-title {
  margin-top: 24px;
}

/* Auth forms sit straight on the canvas on phones, as the app's sign-in and
 * reset screens do; on wide screens they get a card beside the title. */
@media (max-width: 879px) {
  .card-on-wide {
    background: none;
    border: 0;
    padding: 0;
  }
}

/* ===========================================================================
 * The community hub (1.2.0 redesign, docs/features/hub/community.md)
 * ======================================================================== */

/* ---------------------------------------------------------------------------
 * Header: site name, sections, then search and the account. Phones keep the
 * name, a search icon and the account; the sections move to the footer row
 * of links.
 */

.site-header-inner {
  gap: 32px;
}

.site-nav {
  display: flex;
  gap: 28px;
  align-self: stretch;
}

.site-nav a {
  display: flex;
  align-items: center;
  border-top: 3px solid transparent;
  border-bottom: 3px solid transparent;
  color: var(--muted);
  font-weight: 600;
  text-decoration: none;
}

.site-nav a:hover {
  color: var(--text);
}

/* The tab indicator: an orange bar under the current section. */
.site-nav a[aria-current='page'] {
  color: var(--text);
  border-bottom-color: var(--accent);
}

.header-end {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 16px;
}

.header-icon {
  display: none;
  width: 44px;
  height: 44px;
  place-items: center;
  color: var(--text);
}

.header-account {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.header-account.avatar {
  display: grid;
  min-height: 0;
  text-decoration: none;
}

@media (max-width: 719px) {
  .site-nav,
  .header-search {
    display: none;
  }

  .header-icon {
    display: grid;
  }

  .header-end {
    gap: 4px;
  }
}

/* ---------------------------------------------------------------------------
 * Search
 */

.search-field {
  display: flex;
  align-items: center;
  gap: 12px;
  height: 52px;
  padding: 0 16px;
  border: var(--control) solid var(--line);
  color: var(--muted);
  max-width: 640px;
}

.search-field:focus-within {
  border-color: var(--active);
}

.search-field input {
  flex: 1;
  min-width: 0;
  height: 100%;
  background: none;
  border: 0;
  outline: none;
  color: var(--text);
  font: 400 16px/24px var(--font-text);
}

.search-field input::placeholder {
  color: var(--muted);
}

.search-field input::-webkit-search-cancel-button {
  filter: grayscale(1);
}

.search-field-compact {
  height: 44px;
  width: 260px;
  padding: 0 12px;
}

/* ---------------------------------------------------------------------------
 * Page rhythm and headings
 */

.stack-lg {
  display: grid;
  gap: 40px;
}

.stack-xl {
  display: grid;
  gap: 56px;
}

.intro {
  display: grid;
  gap: 24px;
}

.section-title,
.section-title-small,
.film-name {
  font-family: var(--font-display);
  font-stretch: 125%;
  font-variation-settings: 'wdth' 125;
  font-weight: 800;
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
}

.section-title {
  font-size: 28px;
  line-height: 34px;
}

.section-title-small {
  font-size: 20px;
  line-height: 24px;
}

.shelf-heading,
.section-heading {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 20px;
}

.shelf-heading {
  justify-content: space-between;
}

.text-link {
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.text-link:hover {
  color: var(--active);
}

.empty {
  color: var(--muted);
}

.pager {
  display: flex;
  justify-content: center;
  padding-top: 16px;
}

.pager > [aria-busy='true'] {
  cursor: progress;
  opacity: 0.6;
}

.stack > .section-heading {
  margin-bottom: 0;
}

/* ---------------------------------------------------------------------------
 * Film cards: photo first, the star on it, then name, base film and who.
 */

.film-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
  gap: 32px 24px;
}

@media (max-width: 559px) {
  .intro .chips {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    margin-right: calc(var(--gutter) * -1);
    padding-right: var(--gutter);
  }

  .intro .chip {
    flex: none;
    overflow-wrap: normal;
    white-space: nowrap;
  }

  .film-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 24px 12px;
  }
}

.film {
  display: grid;
  gap: 12px;
  align-content: start;
  min-width: 0;
}

.film-frame {
  position: relative;
}

.film-photo {
  display: block;
  aspect-ratio: 3 / 2;
  background: var(--photo);
  overflow: hidden;
}

.film-photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* No photo: the name, small, on black. */
.film-photo-empty {
  display: grid;
  place-items: center;
  padding: 12px;
  color: var(--on-photo-muted);
  font-family: var(--font-display);
  font-stretch: 125%;
  font-weight: 800;
  font-size: 13px;
  text-decoration: none;
  text-align: center;
  overflow-wrap: anywhere;
}

/* The favourite star sits on the photo, on a dark backing so it reads over
 * any picture. Filled when the film is a favourite. */
.star {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  background: rgba(26, 26, 26, 0.7);
  border: 0;
  color: var(--on-photo);
  cursor: pointer;
}

.star[aria-pressed='true'] path,
.btn-square[aria-pressed='true'] path {
  fill: currentColor;
}

.film-meta {
  display: grid;
  gap: 6px;
  min-width: 0;
}

.film-name {
  font-size: 20px;
  line-height: 24px;
}

.film-name a {
  text-decoration: none;
}

.film-name a:hover {
  color: var(--active);
}

@media (max-width: 559px) {
  .film-name {
    font-size: 16px;
    line-height: 20px;
  }

  .star {
    top: 0;
    right: 0;
  }
}

.marks {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* Spec marks: Michroma capitals in a grey box, as on the app's film page. */
.mark {
  font-family: 'Michroma', var(--font-text);
  font-size: 11px;
  line-height: 14px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border: var(--hairline) solid var(--line);
  padding: 2px 6px;
  color: var(--muted);
}

/* ---------------------------------------------------------------------------
 * A film's page
 */

.recipe-page {
  display: grid;
  gap: 64px;
}

.recipe-top {
  display: grid;
  gap: 24px;
  align-items: start;
}

.recipe-photo {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  background: var(--photo);
}

.recipe-photo-empty {
  display: grid;
  place-items: center;
  color: var(--on-photo-muted);
  font-family: var(--font-display);
  font-stretch: 125%;
  font-weight: 800;
  font-size: 28px;
}

.recipe-details {
  display: grid;
  gap: 24px;
  align-content: start;
  min-width: 0;
}

.recipe-title {
  display: grid;
  gap: 10px;
}

.byline {
  display: flex;
  align-items: center;
  gap: 12px;
}

.byline-name {
  font-weight: 600;
}

.byline-name a {
  text-decoration: none;
}

.byline-name a:hover {
  color: var(--active);
}

.description {
  color: var(--muted);
  max-width: 52ch;
  white-space: pre-line;
  overflow-wrap: anywhere;
}

.recipe-actions {
  display: flex;
  gap: 12px;
}

.recipe-open {
  flex: 1;
}

.btn-square {
  flex: none;
  width: 52px;
  padding: 0;
  position: relative;
}

/* The code beside its QR code on black. */
.code-box {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 16px;
  background: var(--photo);
  color: var(--on-photo-muted);
}

.qr {
  flex: none;
  display: block;
}

.code-text {
  display: grid;
  gap: 6px;
  min-width: 0;
}

.code-label {
  font-size: 11px;
  line-height: 14px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.code-big {
  font-family: var(--font-mono);
  font-size: 28px;
  line-height: 34px;
  letter-spacing: 0.12em;
  color: var(--on-photo);
  -webkit-user-select: all;
  user-select: all;
}

.store-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0 20px;
  font-size: 13px;
}

.store-links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--on-photo-muted);
}

.store-links a:hover {
  color: var(--on-photo);
}

.recipe-lower {
  display: grid;
  gap: 48px;
  align-items: start;
}

.recipe-aside {
  display: grid;
  gap: 40px;
  min-width: 0;
}

.aside-section {
  display: grid;
  gap: 16px;
}

.aside-section .section-title,
.aside-section .section-title-small {
  margin: 0;
}

/* Remixes and more by the author: a small photo and the name. */
.mini {
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
}

.mini img,
.mini-empty {
  flex: none;
  width: 96px;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  background: var(--photo);
}

.mini > span:last-child {
  display: grid;
}

.mini-name {
  font-weight: 600;
  overflow-wrap: anywhere;
}

.mini:hover .mini-name {
  color: var(--active);
}

@media (min-width: 880px) {
  .recipe-top {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 48px;
  }

  .recipe-photo {
    position: sticky;
    top: 32px;
  }

  .recipe-lower {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }

  .recipe-lower-single {
    grid-template-columns: minmax(0, 1fr);
    max-width: 576px;
  }
}

/* Phones: the photo runs edge to edge, the QR code goes (it is for a phone
 * to scan), and the actions pin to the bottom of the screen like the app's
 * film page. */
@media (max-width: 879px) {
  .recipe-photo {
    margin: -32px calc(var(--gutter) * -1) 0;
    width: calc(100% + var(--gutter) * 2);
  }

  .qr {
    display: none;
  }

  .recipe-actions {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 10;
    padding: 12px var(--gutter) calc(12px + env(safe-area-inset-bottom));
    background: var(--canvas);
    border-top: var(--hairline) solid var(--divider);
  }

  .recipe-page {
    padding-bottom: 76px;
  }

  /* Four controls in a phone's width: the label stays on one line. */
  .recipe-actions {
    gap: 8px;
  }

  .recipe-actions .btn-square {
    width: 48px;
  }

  .recipe-open {
    padding: 0 12px;
    white-space: nowrap;
  }

  .recipe-actions .btn-square:first-of-type {
    order: -1;
  }
}

/* ---------------------------------------------------------------------------
 * The recipe panel: the app's editor sliders, read-only.
 */

.recipe-panel {
  display: grid;
  gap: 20px;
  padding: 24px;
  background: var(--raised);
  border: var(--hairline) solid var(--divider);
}

.recipe-group {
  display: grid;
  gap: 20px;
}

.recipe-group[hidden] {
  display: none;
}

.recipe-group-title,
.recipe-subtitle {
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
  color: var(--muted);
}

.recipe-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
}

.recipe-row span:last-child {
  font-weight: 600;
  text-align: right;
  overflow-wrap: anywhere;
}

.slider {
  display: grid;
  gap: 10px;
}

.slider-row {
  display: flex;
  align-items: center;
  gap: 24px;
}

.slider-value {
  flex: none;
  width: 64px;
  height: 44px;
  display: grid;
  place-items: center;
  border: var(--hairline) solid var(--divider);
  background: var(--canvas);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.slider-value-default {
  color: var(--muted);
}

.slider-track {
  position: relative;
  flex: 1;
  height: 2px;
  margin: 0 11px;
  background: var(--track);
}

.slider-track i {
  position: absolute;
  top: -10px;
  width: 22px;
  height: 22px;
  margin-left: -11px;
  border-radius: 50%;
  background: var(--text);
}

/* ---------------------------------------------------------------------------
 * Comments
 */

.comments {
  display: grid;
  align-content: start;
  min-width: 0;
}

.composer {
  display: grid;
  gap: 12px;
  padding-bottom: 24px;
}

.composer-reply {
  padding: 12px 0 0;
}

.composer-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

.composer-actions .btn {
  min-width: 120px;
}

.textarea {
  height: auto;
  min-height: 88px;
  padding: 12px 16px;
  resize: vertical;
}

.comment-list {
  display: grid;
}

.comment-thread-wrap {
  border-top: var(--hairline) solid var(--divider);
  padding: 20px 0;
}

.comment {
  display: flex;
  gap: 12px;
  min-width: 0;
}

.comment-main {
  flex: 1;
  display: grid;
  gap: 6px;
  align-content: start;
  min-width: 0;
}

.comment-replies {
  display: grid;
}

.comment-replies .comment {
  padding-top: 12px;
}

.comment-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
}

.comment-name {
  font-weight: 600;
  text-decoration: none;
}

a.comment-name:hover {
  color: var(--active);
}

.comment-body {
  white-space: pre-line;
  overflow-wrap: anywhere;
}

.comment-deleted {
  color: var(--muted);
  font-style: italic;
}

.tag-outline {
  border: var(--hairline) solid var(--active);
  color: var(--active);
}

/* Reply: a text button, underlined, muted, with a 44px target. */
.link-button {
  justify-self: start;
  min-height: 44px;
  padding: 0;
  background: none;
  border: 0;
  color: var(--muted);
  font: 600 13px/18px var(--font-text);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.link-button:hover {
  color: var(--text);
}

/* The "…" in a comment's top right corner, apart from Reply. */
.comment-more {
  position: relative;
  flex: none;
  align-self: flex-start;
}

.icon-button {
  width: 44px;
  height: 44px;
  margin: -10px -10px 0 0;
  display: grid;
  place-items: center;
  background: none;
  border: 0;
  color: var(--muted);
  cursor: pointer;
}

.icon-button:hover {
  color: var(--text);
}

/* A menu under the button that opened it. */
.menu {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  z-index: 20;
  min-width: 180px;
  display: grid;
  background: var(--raised);
  border: var(--hairline) solid var(--divider);
}

.recipe-actions .menu {
  top: auto;
  bottom: calc(100% + 4px);
}

@media (min-width: 880px) {
  .recipe-actions {
    position: relative;
  }

  .recipe-actions .menu {
    top: calc(100% + 4px);
    bottom: auto;
  }
}

.menu-item {
  min-height: 48px;
  padding: 0 16px;
  background: none;
  border: 0;
  color: var(--text);
  font: 400 16px/24px var(--font-text);
  text-align: left;
  cursor: pointer;
}

.menu-item + .menu-item {
  border-top: var(--hairline) solid var(--divider);
}

.menu-item:hover {
  background: color-mix(in srgb, var(--text) 5%, transparent);
}

.menu-item-danger {
  color: var(--danger);
}

.dialog {
  width: min(440px, calc(100% - 40px));
  padding: 24px;
  margin: auto;
  background: var(--raised);
  color: var(--text);
  border: var(--hairline) solid var(--divider);
  border-radius: 12px 12px 0 0;
}

.dialog::backdrop {
  background: rgba(0, 0, 0, 0.6);
}

/* Toasts: ink on cream in the dark theme and the reverse in light, at the
 * bottom, above the pinned actions on phones. */
.toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  z-index: 30;
  max-width: calc(100% - 40px);
  padding: 12px 16px;
  background: var(--text);
  color: var(--canvas);
  font-weight: 600;
  transform: translate(-50%, 16px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 220ms var(--snap), transform 220ms var(--snap);
}

.toast-on {
  opacity: 1;
  transform: translate(-50%, 0);
}

@media (max-width: 879px) {
  .toast {
    bottom: 96px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .toast {
    transition: opacity 220ms linear;
    transform: translate(-50%, 0);
  }
}

/* ---------------------------------------------------------------------------
 * People
 */

.profile-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 24px 32px;
}

.avatar-large {
  width: 96px;
  height: 96px;
  font-size: 36px;
}

.profile-text {
  flex: 1 1 320px;
  display: grid;
  gap: 12px;
  min-width: 0;
}

.people {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
  gap: 12px 24px;
}

.person {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 68px;
  padding: 12px 16px;
  background: var(--raised);
  border: var(--hairline) solid var(--divider);
  text-decoration: none;
}

.person > span:last-child {
  display: grid;
}

.person-name {
  font-weight: 600;
}

.person:hover .person-name {
  color: var(--active);
}

/* ---------------------------------------------------------------------------
 * Guidelines
 */

.prose {
  max-width: 640px;
  display: grid;
  gap: 16px;
}

.prose .section-title-small {
  margin-top: 24px;
}

.prose a {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ---------------------------------------------------------------------------
 * Account: profile, recipes, favourites, replies, reports
 */

.account-hub {
  margin-top: 64px;
}

.account-section {
  display: grid;
  gap: 16px;
}

.account-section .section-heading {
  margin-bottom: 0;
}

.narrow-form {
  max-width: 576px;
}

.my-recipes {
  list-style: none;
}

.my-recipe {
  flex-wrap: wrap;
}

.my-recipe-thumb {
  flex: none;
  width: 72px;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  background: var(--photo);
}

.my-recipe-name {
  font-weight: 600;
  text-decoration: none;
}

.my-recipe-name:hover {
  color: var(--active);
}

.row-main .tag {
  margin-top: 4px;
}

/* A segmented control, as RpSegmentedControl: square, outlined, the chosen
 * segment in orange. */
.segmented {
  display: inline-flex;
  border: var(--control) solid var(--line);
}

.segment {
  min-width: 64px;
  min-height: 40px;
  padding: 0 12px;
  background: none;
  border: 0;
  color: var(--text);
  font: 600 13px/18px var(--font-text);
  cursor: pointer;
}

.segment + .segment {
  border-left: var(--control) solid var(--line);
}

.segment[aria-checked='true'] {
  background: var(--accent);
  color: var(--on-accent);
}

.segment:disabled {
  color: var(--disabled);
  cursor: not-allowed;
}

@media (max-width: 559px) {
  .my-recipe .segmented {
    width: 100%;
  }

  .my-recipe .segment {
    flex: 1;
  }
}

.activity {
  list-style: none;
  display: grid;
}

.activity-item {
  display: grid;
  gap: 4px;
  padding: 16px 0;
  border-top: var(--hairline) solid var(--divider);
}

.activity-item a {
  font-weight: 600;
  text-decoration: none;
}

.activity-item a:hover {
  color: var(--active);
}

.activity-body {
  color: var(--muted);
  white-space: pre-line;
  overflow-wrap: anywhere;
}

.btn-row-start {
  display: flex;
  gap: 12px;
  margin-top: 8px;
}

.btn-danger {
  color: var(--danger);
}

/* Where a slider's thumb sits, in whole percent (lib/recipe-panel.js). Classes,
 * because the pages' CSP allows no inline styles. */
.slider-track .p0 { left: 0%; }
.slider-track .p1 { left: 1%; }
.slider-track .p2 { left: 2%; }
.slider-track .p3 { left: 3%; }
.slider-track .p4 { left: 4%; }
.slider-track .p5 { left: 5%; }
.slider-track .p6 { left: 6%; }
.slider-track .p7 { left: 7%; }
.slider-track .p8 { left: 8%; }
.slider-track .p9 { left: 9%; }
.slider-track .p10 { left: 10%; }
.slider-track .p11 { left: 11%; }
.slider-track .p12 { left: 12%; }
.slider-track .p13 { left: 13%; }
.slider-track .p14 { left: 14%; }
.slider-track .p15 { left: 15%; }
.slider-track .p16 { left: 16%; }
.slider-track .p17 { left: 17%; }
.slider-track .p18 { left: 18%; }
.slider-track .p19 { left: 19%; }
.slider-track .p20 { left: 20%; }
.slider-track .p21 { left: 21%; }
.slider-track .p22 { left: 22%; }
.slider-track .p23 { left: 23%; }
.slider-track .p24 { left: 24%; }
.slider-track .p25 { left: 25%; }
.slider-track .p26 { left: 26%; }
.slider-track .p27 { left: 27%; }
.slider-track .p28 { left: 28%; }
.slider-track .p29 { left: 29%; }
.slider-track .p30 { left: 30%; }
.slider-track .p31 { left: 31%; }
.slider-track .p32 { left: 32%; }
.slider-track .p33 { left: 33%; }
.slider-track .p34 { left: 34%; }
.slider-track .p35 { left: 35%; }
.slider-track .p36 { left: 36%; }
.slider-track .p37 { left: 37%; }
.slider-track .p38 { left: 38%; }
.slider-track .p39 { left: 39%; }
.slider-track .p40 { left: 40%; }
.slider-track .p41 { left: 41%; }
.slider-track .p42 { left: 42%; }
.slider-track .p43 { left: 43%; }
.slider-track .p44 { left: 44%; }
.slider-track .p45 { left: 45%; }
.slider-track .p46 { left: 46%; }
.slider-track .p47 { left: 47%; }
.slider-track .p48 { left: 48%; }
.slider-track .p49 { left: 49%; }
.slider-track .p50 { left: 50%; }
.slider-track .p51 { left: 51%; }
.slider-track .p52 { left: 52%; }
.slider-track .p53 { left: 53%; }
.slider-track .p54 { left: 54%; }
.slider-track .p55 { left: 55%; }
.slider-track .p56 { left: 56%; }
.slider-track .p57 { left: 57%; }
.slider-track .p58 { left: 58%; }
.slider-track .p59 { left: 59%; }
.slider-track .p60 { left: 60%; }
.slider-track .p61 { left: 61%; }
.slider-track .p62 { left: 62%; }
.slider-track .p63 { left: 63%; }
.slider-track .p64 { left: 64%; }
.slider-track .p65 { left: 65%; }
.slider-track .p66 { left: 66%; }
.slider-track .p67 { left: 67%; }
.slider-track .p68 { left: 68%; }
.slider-track .p69 { left: 69%; }
.slider-track .p70 { left: 70%; }
.slider-track .p71 { left: 71%; }
.slider-track .p72 { left: 72%; }
.slider-track .p73 { left: 73%; }
.slider-track .p74 { left: 74%; }
.slider-track .p75 { left: 75%; }
.slider-track .p76 { left: 76%; }
.slider-track .p77 { left: 77%; }
.slider-track .p78 { left: 78%; }
.slider-track .p79 { left: 79%; }
.slider-track .p80 { left: 80%; }
.slider-track .p81 { left: 81%; }
.slider-track .p82 { left: 82%; }
.slider-track .p83 { left: 83%; }
.slider-track .p84 { left: 84%; }
.slider-track .p85 { left: 85%; }
.slider-track .p86 { left: 86%; }
.slider-track .p87 { left: 87%; }
.slider-track .p88 { left: 88%; }
.slider-track .p89 { left: 89%; }
.slider-track .p90 { left: 90%; }
.slider-track .p91 { left: 91%; }
.slider-track .p92 { left: 92%; }
.slider-track .p93 { left: 93%; }
.slider-track .p94 { left: 94%; }
.slider-track .p95 { left: 95%; }
.slider-track .p96 { left: 96%; }
.slider-track .p97 { left: 97%; }
.slider-track .p98 { left: 98%; }
.slider-track .p99 { left: 99%; }
.slider-track .p100 { left: 100%; }

/* ---------------------------------------------------------------------------
 * /account, signed in: your own profile page (as /u/<name>), then tabs.
 */

.profile-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

button.chip {
  background: none;
  cursor: pointer;
}

button.chip:hover {
  border-color: var(--text);
}

button.chip.chip-on {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

/* The "…" on your own film cards opens under the photo's corner. */
.film-frame .menu {
  top: 56px;
  right: 8px;
}

/* A choice in a menu: the current one is ticked. */
.menu-item[role='menuitemradio'] {
  display: flex;
  align-items: center;
  gap: 12px;
}

.menu-item[role='menuitemradio']::before {
  content: '';
  flex: none;
  width: 10px;
  height: 6px;
  border-left: 2px solid transparent;
  border-bottom: 2px solid transparent;
  transform: translateY(-2px) rotate(-45deg);
}

.menu-item[aria-checked='true']::before {
  border-color: var(--active);
}

.account-panel {
  max-width: 576px;
}

/* Publish, under a film that isn't public yet (cards on /account, and the
 * owner's own film page). */
.film-meta .btn-block {
  margin-top: 6px;
}

.recipe-publish {
  justify-self: start;
}
