@charset "utf-8";

/* ==========================================================================
   Locus — the whole design system, one file.

   Ground is the briefed beige. Every other colour is sampled from the bakery's
   own logotype — the chocolate brown of the script and the gold of the wheat
   ear — so the site and the shop sign agree. The recurring device is the
   "record rule": a hairline with tick marks and data sitting on it, borrowed
   from a survey drawing, used for anything the bakery is stating as fact.
   ========================================================================== */

/* ------------------------------------------------------------------ fonts */

/*
 * Vollkorn for display. The name means "wholegrain", and it was drawn as a
 * sturdy bread-and-butter text face — a real connection to the subject rather
 * than a face picked for looking expensive. It also keeps this off the small
 * set of serifs every warm-brand site has converged on.
 */
@font-face {
  font-family: 'Vollkorn';
  src: url('../fonts/vollkorn-latin.woff2') format('woff2');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Vollkorn';
  src: url('../fonts/vollkorn-latin-ext.woff2') format('woff2');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Karla';
  src: url('../fonts/karla-latin.woff2') format('woff2');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Karla';
  src: url('../fonts/karla-latin-ext.woff2') format('woff2');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ------------------------------------------------------------------ tokens */

:root {
  /* Ground stays the briefed beige. Everything else is sampled straight from
     the bakery's own logotype: the chocolate brown of the script and the gold
     of the wheat ear above the L. */
  --linen: #e9e2d3;
  --linen-deep: #ded4bd;
  --flour: #f8f4ec;
  --bark: #2a1a12;
  --bark-soft: #574438;
  --brand: #472920;
  --gold: #b8862b;
  --gold-bright: #e3af37;
  --crust: #7a4420;
  /* Secondary text. It has to clear 4.5:1 on the *darkest* ground it ever sits
     on, which is --linen-deep inside a sunken band, not the page linen. The
     previous #6b5a4c passed on linen at 5.10 and quietly failed at 4.47 there,
     across every label, caption and table header on the site. */
  --slate: #635240;
  --rule: rgba(42, 26, 18, 0.15);
  --rule-firm: rgba(42, 26, 18, 0.32);

  --display: 'Vollkorn', Georgia, 'Times New Roman', serif;
  --text: 'Karla', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --measure: 64ch;
  --page: 1240px;
  --gut: clamp(1.25rem, 4vw, 3.5rem);

  --s1: 0.5rem;
  --s2: 0.875rem;
  --s3: 1.375rem;
  --s4: 2.25rem;
  --s5: 3.5rem;
  --s6: 5.5rem;
  --s7: 8rem;

  --ease: cubic-bezier(0.22, 0.68, 0.24, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ------------------------------------------------------------------- reset */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--linen);
  color: var(--bark);
  font-family: var(--text);
  font-size: 17px;
  line-height: 1.62;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}

img,
svg {
  max-width: 100%;
  height: auto;
  display: block;
}

h1,
h2,
h3,
h4,
p,
figure,
dl,
dd,
ul,
ol {
  margin: 0;
}

ul,
ol {
  padding: 0;
  list-style: none;
}

a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
}

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

table {
  border-collapse: collapse;
  width: 100%;
}

/* ------------------------------------------------------------- typography */

h1,
h2,
h3,
.display {
  font-family: var(--display);
  font-optical-sizing: auto;
  font-weight: 400;
  line-height: 1.04;
  letter-spacing: -0.014em;
  text-wrap: balance;
}

.t-hero {
  font-size: clamp(2.85rem, 6.4vw, 5.2rem);
  line-height: 0.98;
  letter-spacing: -0.022em;
}

.t-page {
  font-size: clamp(2.4rem, 5.2vw, 4rem);
  line-height: 1;
}

.t-section {
  font-size: clamp(1.75rem, 3vw, 2.5rem);
}

.t-item {
  font-size: 1.4rem;
  line-height: 1.14;
}

.lede {
  font-size: clamp(1.12rem, 1.5vw, 1.32rem);
  line-height: 1.55;
  color: var(--bark-soft);
  max-width: 52ch;
}

.prose p + p {
  margin-top: 1.15em;
}

.prose {
  max-width: var(--measure);
  color: var(--bark-soft);
}

.quiet {
  color: var(--slate);
  font-size: 0.86rem;
  line-height: 1.5;
}

.num {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* ---------------------------------------------------------------- shell */

.wrap {
  width: 100%;
  max-width: var(--page);
  margin-inline: auto;
  padding-inline: var(--gut);
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--bark);
  color: var(--flour);
  padding: 0.7rem 1.1rem;
  z-index: 50;
}
.skip:focus {
  left: 0;
}

.notice {
  background: var(--slate);
  color: #eef1ec;
  font-size: 0.8rem;
  letter-spacing: 0.005em;
}
.notice p {
  padding-block: 0.55rem;
  margin: 0;
}

/* header ------------------------------------------------------------- */

.masthead {
  border-bottom: 1px solid var(--rule);
  background: var(--linen);
  position: sticky;
  top: 0;
  z-index: 30;
}

.masthead__in {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  flex-wrap: wrap;
  padding-block: 1.1rem;
}

.wordmark {
  display: block;
  line-height: 0;
  flex: 0 0 auto;
}

.wordmark img {
  width: clamp(140px, 16vw, 196px);
  height: auto;
  transition: transform 0.5s var(--ease);
}

.wordmark:hover img {
  transform: scale(1.03);
}

.wordmark--foot img {
  width: 190px;
}

.nav {
  display: flex;
  gap: clamp(0.9rem, 2.4vw, 2.1rem);
  align-items: baseline;
  font-size: 0.97rem;
}

.nav a {
  text-decoration: none;
  padding-block: 0.25rem;
  position: relative;
  color: var(--bark-soft);
  transition: color 0.22s var(--ease);
}

.nav a span {
  position: relative;
  display: inline-block;
}

/* the rule grows from the left on hover and sits permanently under the
   current page, so the same mark means the same thing either way */
.nav a span::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: -0.32em;
  height: 1.5px;
  width: 100%;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.32s var(--ease);
}

.nav a:hover {
  color: var(--bark);
}

.nav a:hover span::after,
.nav a:focus-visible span::after {
  transform: scaleX(1);
}

.nav a[aria-current='page'] {
  color: var(--brand);
}

.nav a[aria-current='page'] span::after {
  transform: scaleX(1);
  background: var(--brand);
}

/*
 * Scroll state on the header is deliberately paint-only — a shadow, a slightly
 * more opaque ground, and one transform on the wordmark. Transitioning padding
 * or the logo's width instead would relayout the sticky bar on every frame of
 * the animation, and would shift the page under the reader as it ran.
 */
.masthead {
  transition: box-shadow 0.35s var(--ease), background-color 0.35s var(--ease);
}

.masthead.is-stuck {
  box-shadow: 0 1px 0 var(--rule), 0 10px 26px -20px rgba(42, 26, 18, 0.65);
  background: color-mix(in srgb, var(--linen) 88%, #fff);
}

.wordmark {
  transform-origin: left center;
  transition: transform 0.35s var(--ease);
}

.masthead.is-stuck .wordmark {
  transform: scale(0.88);
}

/* ------------------------------------------------------- the record rule */

/*
 * The signature device. A hairline with a tick above each datum, like the
 * dimension line on a drawing. Used where the bakery is stating a fact.
 */
.record {
  display: grid;
  gap: 0;
  grid-template-columns: repeat(auto-fit, minmax(min(160px, 100%), 1fr));
}

/* The rule belongs to each datum, not to the block, so a set that wraps onto a
   second row gets a second rule instead of a row of orphaned tick marks. */
.record > div {
  position: relative;
  padding: 1.15rem 1rem 1rem 0;
  border-top: 1px solid var(--rule-firm);
}

.record > div::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 9px;
  background: var(--slate);
}

.record--tight {
  grid-template-columns: repeat(auto-fit, minmax(min(126px, 100%), 1fr));
}

/* Four facts in a 2x2 block. Three-up left the fourth alone on a second row
   under a rule a third the width of the one above it, which reads as a mistake
   rather than as a wrap. */
.record--pairs {
  grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr));
}

.record dt {
  font-size: 0.78rem;
  color: var(--slate);
  letter-spacing: 0.01em;
  margin-bottom: 0.15rem;
}

.record dd {
  font-size: 1.02rem;
  line-height: 1.32;
  color: var(--bark);
}

/* ---------------------------------------------------------------- plates */

/*
 * The photographs are cut out of their white studio background, so a loaf sits
 * directly on the page with a soft shadow cast from its own silhouette rather
 * than from a rectangle. The plate is only a consistent frame: one aspect
 * ratio so a focaccia slab and a boule keep the card grid on one baseline.
 */
.plate {
  position: relative;
  aspect-ratio: 4 / 3;
}

.plate img {
  position: absolute;
  inset: 4%;
  width: 92%;
  height: 92%;
  object-fit: contain;
  display: block;
  filter: drop-shadow(0 18px 22px rgba(58, 36, 20, 0.22));
  transition: transform 0.55s var(--ease), filter 0.55s var(--ease);
}

.plate--big {
  aspect-ratio: 5 / 4;
}

.plate--hero {
  aspect-ratio: 5 / 4;
}

.plate--hero img {
  inset: 2%;
  width: 96%;
  height: 96%;
  filter: drop-shadow(0 26px 34px rgba(58, 36, 20, 0.26));
}

/* ------------------------------------------------------------------ hero */

.hero {
  padding-block: clamp(var(--s5), 8vw, var(--s7)) var(--s6);
}

.hero__grid {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
}

.hero__say {
  max-width: 17ch;
}

.hero .lede {
  margin-top: var(--s3);
}

.hero .record {
  margin-top: var(--s4);
}

.hero__specimen {
  position: relative;
}

.hero__tag {
  margin-top: var(--s2);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s2);
  border-top: 1px solid var(--rule-firm);
  padding-top: 0.65rem;
  font-size: 0.9rem;
}

.hero__tag a {
  font-family: var(--display);
  font-size: 1.15rem;
  text-decoration: none;
  border-bottom: 1px solid var(--rule-firm);
}
.hero__tag a:hover {
  border-bottom-color: var(--crust);
  color: var(--crust);
}

/* ---------------------------------------------------------------- motion */

/*
 * One system for everything that moves. An element marked [data-reveal] (or
 * .reveal inside the hero) starts slightly low and transparent and settles when
 * it first scrolls into view; a container marked [data-stagger] hands its
 * children an --i index so they arrive in sequence rather than as a block.
 *
 * Nothing loops, nothing moves without being scrolled to or pointed at, and the
 * whole system collapses to "already arrived" under prefers-reduced-motion.
 */
.js [data-reveal],
.js .hero .reveal {
  opacity: 0;
  transform: translate3d(0, 22px, 0);
  transition: opacity 0.72s var(--ease), transform 0.72s var(--ease);
  will-change: opacity, transform;
}

.js [data-reveal].is-in,
.js .hero.is-in .reveal {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* the hero arrives as one sequence rather than four separate entrances */
.js .hero .reveal:nth-child(1) { transition-delay: 0.05s; }
.js .hero .reveal:nth-child(2) { transition-delay: 0.14s; }
.js .hero .reveal:nth-child(3) { transition-delay: 0.23s; }
.js .hero .reveal:nth-child(4) { transition-delay: 0.32s; }

.js .hero__specimen {
  opacity: 0;
  transform: translate3d(0, 26px, 0) scale(0.965);
  transition: opacity 0.9s var(--ease), transform 0.9s var(--ease);
}

.js .hero.is-in .hero__specimen {
  opacity: 1;
  transform: none;
  transition-delay: 0.1s;
}

/* staggered children: cards, table rows, list items, chart rows */
.js [data-stagger] > * {
  opacity: 0;
  transform: translate3d(0, 16px, 0);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
  transition-delay: calc(var(--i, 0) * 55ms);
}

/* A group reveals its children together; a group taller than the screen has
   the script observe each child instead, and those carry .is-in themselves. */
.js [data-stagger].is-in > *,
.js .is-in [data-stagger] > *,
.js [data-reveal].is-in [data-stagger] > *,
.js [data-stagger] > .is-in {
  opacity: 1;
  transform: none;
}

.js table[data-stagger] > tbody > tr,
.js table[data-stagger] > thead > tr {
  opacity: 0;
  transform: translate3d(0, 12px, 0);
  transition: opacity 0.5s var(--ease), transform 0.5s var(--ease);
  transition-delay: calc(var(--i, 0) * 42ms);
}

.js table[data-stagger].is-in > tbody > tr,
.js table[data-stagger].is-in > thead > tr,
.js .is-in table[data-stagger] > tbody > tr,
.js .is-in table[data-stagger] > thead > tr,
.js table[data-stagger] > tbody > tr.is-in {
  opacity: 1;
  transform: none;
}

/* the parallax the hero photograph gets as the page scrolls */
.js [data-parallax] img {
  transform: translate3d(0, var(--shift, 0px), 0);
}

/* a number that counts up to its final value once it is on screen */
.count {
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------- sections */

.band {
  padding-block: clamp(var(--s5), 7vw, var(--s6));
}

.band--sunk {
  background: var(--linen-deep);
  border-block: 1px solid var(--rule);
}

.band__head {
  display: grid;
  gap: var(--s2);
  max-width: 60ch;
  margin-bottom: var(--s4);
}

.band__head p {
  color: var(--bark-soft);
}

/* ------------------------------------------------------------ bread cards */

.loaves {
  display: grid;
  gap: clamp(1.6rem, 3vw, 2.6rem) clamp(1.2rem, 2.4vw, 2rem);
  grid-template-columns: repeat(auto-fill, minmax(min(285px, 100%), 1fr));
}

.loaf {
  display: flex;
  flex-direction: column;
}

.loaf a.loaf__link {
  text-decoration: none;
  display: block;
}

.loaf a.loaf__link:hover .plate img,
.loaf a.loaf__link:focus-visible .plate img {
  transform: translateY(-10px) scale(1.045);
  filter: drop-shadow(0 30px 30px rgba(58, 36, 20, 0.28));
}

.loaf__name {
  margin-top: var(--s2);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.8rem;
}

.loaf a.loaf__link:hover .loaf__name h3 {
  color: var(--crust);
}

.loaf__price {
  font-family: var(--display);
  font-size: 1.25rem;
  white-space: nowrap;
}

.loaf__summary {
  margin-top: 0.45rem;
  color: var(--bark-soft);
  font-size: 0.96rem;
  line-height: 1.5;
}

.loaf__facts {
  margin-top: 0.7rem;
  padding-top: 0.55rem;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.1rem;
  font-size: 0.83rem;
  color: var(--slate);
}

/* ------------------------------------------------------------- the index */

.index {
  font-size: 0.95rem;
}

.index caption {
  text-align: left;
  color: var(--bark-soft);
  padding-bottom: var(--s2);
}

.index th {
  text-align: left;
  font-weight: 500;
  font-size: 0.78rem;
  color: var(--slate);
  padding: 0 0.9rem 0.55rem 0;
  border-bottom: 1px solid var(--rule-firm);
}

.index td {
  padding: 0.72rem 0.9rem 0.72rem 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: baseline;
}

.index tr:hover td {
  background: rgba(247, 243, 234, 0.65);
}

.index th:last-child,
.index td:last-child {
  padding-right: 0;
  text-align: right;
}

.index td.index__name a {
  font-family: var(--display);
  font-size: 1.12rem;
  text-decoration: none;
}

.index td.index__name a:hover {
  color: var(--crust);
  text-decoration: underline;
}

.index__thumb {
  width: 54px;
  padding-right: 0.7rem !important;
}

/* no tile behind these: the photographs are cut out, so any background shows
   as a pale rectangle around the loaf */
.index__thumb img {
  width: 54px;
  height: 42px;
  object-fit: contain;
  filter: drop-shadow(0 3px 4px rgba(58, 36, 20, 0.22));
}

.index__price {
  font-family: var(--display);
  font-size: 1.08rem;
}

@media (max-width: 720px) {
  .index__hide {
    display: none;
  }
}

/* -------------------------------------------------------- bread detail */

.spec {
  padding-block: clamp(var(--s4), 5vw, var(--s6)) var(--s5);
}

.spec__grid {
  display: grid;
  gap: clamp(1.8rem, 4vw, 3.5rem);
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: start;
}

.spec__price {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  margin-top: var(--s3);
}

.spec__price strong {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2rem, 3.4vw, 2.7rem);
  line-height: 1;
}

.spec__price span {
  color: var(--slate);
  font-size: 0.95rem;
}

.spec .record {
  margin-top: var(--s4);
}

.crumb-trail {
  font-size: 0.86rem;
  color: var(--slate);
  padding-top: var(--s3);
}
.crumb-trail a {
  color: var(--slate);
}

.cols {
  display: grid;
  gap: clamp(1.8rem, 4vw, 3.2rem);
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
}

.stack > * + * {
  margin-top: var(--s3);
}

.label {
  font-size: 0.78rem;
  color: var(--slate);
  border-top: 1px solid var(--rule-firm);
  padding-top: 0.5rem;
  margin-bottom: 0.7rem;
  display: block;
}

.listing li {
  padding: 0.32rem 0;
  border-bottom: 1px solid var(--rule);
  font-size: 0.95rem;
}
.listing li:last-child {
  border-bottom: 0;
}

.allergens li {
  color: var(--crust);
}

.nutrition th,
.nutrition td {
  padding: 0.55rem 0.6rem 0.55rem 0;
  border-bottom: 1px solid var(--rule);
  font-size: 0.95rem;
}

.nutrition thead th {
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--slate);
  border-bottom: 1px solid var(--rule-firm);
}

.nutrition tbody th {
  font-weight: 400;
  text-align: left;
  color: var(--bark-soft);
}

.nutrition td {
  text-align: right;
  padding-right: 0;
}

.nutrition thead th:not(:first-child) {
  text-align: right;
  padding-right: 0;
}

.nutrition tr.is-energy th,
.nutrition tr.is-energy td {
  font-size: 1.02rem;
  color: var(--bark);
}

/* ----------------------------------------------------------------- shelf */

.shelf-figure {
  padding-block: var(--s5) 0;
}

.shelf {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: clamp(0.5rem, 2vw, 2rem);
  border-bottom: 2px solid var(--rule-firm);
  padding-bottom: 0.4rem;
}

.shelf li {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.shelf img {
  max-height: clamp(70px, 11vw, 150px);
  width: auto;
  max-width: 100%;
  transition: transform 0.25s cubic-bezier(0.2, 0.7, 0.3, 1);
  transform-origin: bottom center;
}

.shelf a:hover img {
  transform: translateY(-5px);
}

.shelf-figure figcaption {
  padding-top: 0.6rem;
}

@media (prefers-reduced-motion: reduce) {
  .shelf a:hover img {
    transform: none;
  }
}

/* ------------------------------------------------------------ bake chart */

.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.chart {
  font-size: 0.95rem;
}

.chart caption {
  text-align: left;
  padding-bottom: var(--s2);
  max-width: 60ch;
}

.chart th {
  text-align: left;
  font-weight: 400;
}

.chart thead th {
  font-size: 0.78rem;
  color: var(--slate);
  padding-bottom: 0.55rem;
  border-bottom: 1px solid var(--rule-firm);
}

.chart tbody th {
  font-family: var(--display);
  font-size: 1.05rem;
  padding: 0.6rem 1rem 0.6rem 0;
  border-bottom: 1px solid var(--rule);
}

.chart tbody th a {
  text-decoration: none;
}
.chart tbody th a:hover {
  color: var(--crust);
  text-decoration: underline;
}

.chart td {
  border-bottom: 1px solid var(--rule);
  text-align: center;
  width: 8%;
}

.chart thead th:not(:first-child) {
  text-align: center;
}

.chart td.on::after {
  content: '';
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--crust);
  vertical-align: middle;
}

.chart tr:hover td,
.chart tr:hover th {
  background: rgba(247, 243, 234, 0.6);
}

@media (max-width: 620px) {
  .chart {
    font-size: 0.85rem;
  }
  .chart tbody th {
    font-size: 0.95rem;
    padding-right: 0.4rem;
  }
}

/* ---------------------------------------------------------------- hours */

.hours td,
.hours th {
  padding: 0.5rem 0.6rem 0.5rem 0;
  border-bottom: 1px solid var(--rule);
  font-size: 0.97rem;
}
.hours th {
  text-align: left;
  font-weight: 400;
  color: var(--bark-soft);
}
.hours td {
  text-align: right;
  padding-right: 0;
}
/*
 * "Closed" was the faintest text on the site at 2.3:1, which is exactly
 * backwards: which day the stall is shut is the single most useful fact on the
 * page. It is now legible, and the de-emphasis is carried by the italic and by
 * the word itself rather than by making it hard to read.
 */
.hours .is-shut th,
.hours .is-shut td {
  color: var(--slate);
  font-style: italic;
}

.contact-list {
  font-size: 1.05rem;
}
.contact-list li {
  padding: 0.45rem 0;
  border-bottom: 1px solid var(--rule);
}
.contact-list a {
  text-decoration-color: var(--rule-firm);
}
.contact-list a:hover {
  color: var(--crust);
}

/* ---------------------------------------------------------------- pager */

.pager {
  display: flex;
  justify-content: space-between;
  gap: var(--s3);
  border-top: 1px solid var(--rule-firm);
  padding-top: var(--s3);
  margin-top: var(--s5);
  font-size: 0.95rem;
}

.pager a {
  text-decoration: none;
  max-width: 46%;
}

.pager span {
  display: block;
  color: var(--slate);
  font-size: 0.78rem;
}

.pager strong {
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.15rem;
}

.pager a:hover strong {
  color: var(--crust);
}

.pager .is-end {
  text-align: right;
}

/* --------------------------------------------------------------- footer */

.foot {
  background: var(--bark);
  color: #ddd5c7;
  padding-block: var(--s5) var(--s4);
  margin-top: var(--s6);
}

.foot__grid {
  display: grid;
  gap: var(--s4) var(--s3);
  grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr));
}

.foot h2 {
  font-family: var(--text);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gold-bright);
  margin-bottom: 0.9rem;
}

.foot__list li {
  padding: 0.24rem 0;
  font-size: 0.95rem;
  line-height: 1.45;
}

.foot__list strong {
  font-weight: 600;
  color: #f3ecdd;
}

/*
 * Footer links get the same growing rule the main navigation uses, in gold
 * against the dark ground, rather than a default browser underline. The rule
 * is on the label so it tracks the text rather than the list item.
 */
.foot__link {
  display: inline-block;
  text-decoration: none;
  color: #e8e0d1;
  transition: color 0.22s var(--ease);
}

.foot__link span {
  position: relative;
  display: inline-block;
}

.foot__link span::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: -0.22em;
  height: 1.5px;
  width: 100%;
  background: var(--gold-bright);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s var(--ease);
}

.foot__link:hover,
.foot__link:focus-visible {
  color: #fff8ea;
}

.foot__link:hover span::after,
.foot__link:focus-visible span::after {
  transform: scaleX(1);
}

.foot :focus-visible {
  outline-color: var(--gold-bright);
}

.foot .quiet {
  color: #a2968a;
}

.foot__base {
  margin-top: var(--s5);
  padding-top: var(--s3);
  border-top: 1px solid rgba(236, 229, 215, 0.15);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3) var(--s4);
  align-items: center;
  justify-content: space-between;
  font-size: 0.8rem;
  color: #9c9084;
}

.foot__legal {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.5rem;
  max-width: 62ch;
}

/* ------------------------------------------------------- the maker's mark */

/*
 * The studio credit is a stamp, the kind pressed into the top of a loaf. It is
 * the only circular thing on the site and the only element that tilts, because
 * a signature should not look like part of the furniture it is signing.
 * Hovering presses it: it straightens, sinks a little, and the gold comes up.
 */
.maker {
  display: inline-flex;
  align-items: center;
  gap: 0.85rem;
  text-decoration: none;
  color: #9c9084;
  flex: 0 0 auto;
  transition: color 0.3s var(--ease);
}

.maker__prefix {
  font-size: 0.74rem;
  letter-spacing: 0.04em;
  text-align: right;
  transition: color 0.3s var(--ease);
}

.maker__stamp {
  display: block;
  width: 94px;
  height: 94px;
  flex: 0 0 auto;
}

.maker__stamp svg {
  width: 100%;
  height: 100%;
  overflow: visible;
  transform: rotate(-7deg);
  transform-origin: center;
  transition: transform 0.45s var(--ease-out);
}

.maker__ring {
  fill: none;
  stroke: var(--gold-bright);
  stroke-width: 1.6;
  opacity: 0.45;
  transition: opacity 0.3s var(--ease);
}

.maker__ring--inner {
  stroke-width: 0.7;
  stroke-dasharray: 2 4;
  stroke-linecap: round;
  opacity: 0.35;
}

.maker__arc {
  font-family: var(--text);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.2em;
  fill: var(--gold-bright);
  opacity: 0.85;
  transition: opacity 0.3s var(--ease);
}

/* Sized to stay within the ring on its own line: 6.4px with this tracking runs
   about 66 units wide, and the circle is roughly 82 units across there. */
.maker__craft {
  font-family: var(--text);
  font-size: 6.4px;
  font-weight: 600;
  letter-spacing: 0.15em;
  fill: var(--gold-bright);
  opacity: 0.78;
  transition: opacity 0.3s var(--ease);
}

.maker__wheat {
  fill: var(--gold-bright);
  stroke: var(--gold-bright);
  stroke-width: 0;
  opacity: 0.75;
  transition: opacity 0.3s var(--ease);
}

.maker__wheat path:first-child {
  fill: none;
  stroke-width: 1.5;
}

.maker:hover,
.maker:focus-visible {
  color: #f3ecdd;
}

.maker:hover .maker__stamp svg,
.maker:focus-visible .maker__stamp svg {
  transform: rotate(0deg) scale(0.955);
}

.maker:hover .maker__ring,
.maker:focus-visible .maker__ring,
.maker:hover .maker__arc,
.maker:focus-visible .maker__arc,
.maker:hover .maker__wheat,
.maker:focus-visible .maker__wheat,
.maker:hover .maker__craft,
.maker:focus-visible .maker__craft {
  opacity: 1;
}

@media (max-width: 620px) {
  .foot__base {
    justify-content: flex-start;
  }
  .maker {
    margin-top: var(--s2);
  }
}

/* ------------------------------------------------------------------- 404 */

.lost {
  padding-block: var(--s7);
  text-align: center;
}
.lost .lede {
  margin: var(--s3) auto 0;
}
.lost .plate {
  max-width: 340px;
  margin: var(--s5) auto 0;
}

/* -------------------------------------------------------------- narrow */

@media (max-width: 900px) {
  .hero__grid,
  .spec__grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .hero__say {
    max-width: 14ch;
  }
  .hero__specimen {
    order: -1;
  }
}

@media (max-width: 560px) {
  body {
    font-size: 16px;
  }
  .masthead {
    position: static;
  }
  .masthead__in {
    padding-block: 0.9rem;
  }
  .nav {
    width: 100%;
    justify-content: space-between;
    gap: 0.6rem;
  }
  .hero__say {
    max-width: none;
  }
  .hero__tag {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.35rem;
  }
}

@media print {
  .masthead,
  .foot,
  .notice,
  .cookies,
  .pager {
    display: none;
  }
  body {
    background: #fff;
  }
  /*
   * Anything not yet scrolled to is still transparent, and printing does not
   * scroll. Without this, printing a bread page loses the nutrition table
   * entirely — on the one page a person is most likely to print, because it
   * carries the allergens.
   */
  [data-reveal],
  [data-stagger],
  [data-stagger] > *,
  .reveal,
  table[data-stagger] > tbody > tr,
  table[data-stagger] > thead > tr,
  .hero__specimen {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}


/* ------------------------------------------------------- reduced motion */

/*
 * One switch for the whole system. Everything that would move is declared
 * already-arrived, and the transitions are removed rather than shortened so
 * nothing animates on class changes either.
 */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  .cookies {
    transform: none !important;
    transition: none !important;
  }
  .js [data-reveal],
  .js [data-reveal].is-in,
  .js .hero .reveal,
  .js .hero.is-in .reveal,
  .js .hero__specimen,
  .js .hero.is-in .hero__specimen,
  .js [data-stagger] > *,
  .js [data-stagger] > .is-in,
  .js table[data-stagger] > tbody > tr,
  .js table[data-stagger] > thead > tr {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .js [data-parallax] img {
    transform: none !important;
  }
  .plate img,
  .shelf img,
  .shot img,
  .wordmark,
  .wordmark img,
  .button,
  .masthead {
    transition: none !important;
  }
  .loaf a.loaf__link:hover .plate img,
  .shelf a:hover img,
  .shot__product:hover img,
  .masthead.is-stuck .wordmark {
    transform: none !important;
  }
  .lightbox,
  .lightbox__inner figure {
    transition: none !important;
  }
  .maker__stamp svg {
    transition: none !important;
  }
  .maker:hover .maker__stamp svg,
  .maker:focus-visible .maker__stamp svg {
    transform: rotate(-7deg) !important;
  }
}

/* --------------------------------------------------------------- buttons */

.button {
  display: inline-block;
  background: var(--brand);
  color: var(--flour);
  text-decoration: none;
  padding: 0.72rem 1.5rem;
  border-radius: 2px;
  font-size: 0.97rem;
  position: relative;
  overflow: hidden;
  transition: background-color 0.3s var(--ease), transform 0.3s var(--ease);
}

/* a band of the brand gold sweeps across on hover, once */
/* The gold wipe is a positioned pseudo-element, so it paints above normal
   inline content. The label therefore has to be a real element with its own
   stacking position, or the button reads as a blank gold slab on hover. */
.button::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--gold);
  transform: translateX(-101%);
  transition: transform 0.42s var(--ease);
  z-index: 0;
}

.button > span {
  position: relative;
  z-index: 1;
}

.button:hover::before,
.button:focus-visible::before {
  transform: translateX(0);
}

.button:hover,
.button:focus-visible {
  color: var(--bark);
  transform: translateY(-2px);
}

.hero__cta {
  margin-top: var(--s4);
}

.page-head {
  padding-block: clamp(2.6rem, 6vw, 5rem) 0;
}

/* A section following a page heading needs the same air as one following a
   band; without it the Kontakt labels sat straight under the lede. */
.page-head + section {
  padding-top: var(--s5);
}

/* ----------------------------------------------------------------- chips */

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: var(--s4);
}

.chips a {
  text-decoration: none;
  font-size: 0.88rem;
  padding: 0.35rem 0.9rem;
  border: 1px solid var(--rule-firm);
  border-radius: 100px;
  color: var(--bark-soft);
  transition: background-color 0.25s var(--ease), color 0.25s var(--ease),
    border-color 0.25s var(--ease);
}

.chips a:hover,
.chips a:focus-visible {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--flour);
}

/* --------------------------------------------------------------- gallery */

/* 150px keeps two columns on a 390px phone. At 190px only one column fitted,
   which made the gallery one loaf per screen and fifty screens tall. */
.shots {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(150px, 100%), 1fr));
  gap: clamp(0.7rem, 2vw, 1.6rem);
  margin-top: var(--s5);
}

/* A fixed caption row clipped the longer bread names at narrow widths, so the
   row is auto and the label is allowed to wrap inside its own column. */
.shot {
  position: relative;
  aspect-ratio: 1 / 1;
  min-width: 0;
}

/* the whole tile is the link to the bread; the magnifier is the only other
   control, so a photograph is never a dead end */
.shot__product {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  text-decoration: none;
  border-radius: 3px;
}

.shot__product img {
  max-width: 86%;
  max-height: 86%;
  width: auto;
  height: auto;
  object-fit: contain;
  filter: drop-shadow(0 14px 18px rgba(58, 36, 20, 0.2));
  transition: transform 0.45s var(--ease), filter 0.45s var(--ease);
}

.shot__product:hover img,
.shot__product:focus-visible img {
  transform: translateY(-8px) scale(1.06);
  filter: drop-shadow(0 26px 26px rgba(58, 36, 20, 0.28));
}

.shot__zoom {
  position: absolute;
  right: 2px;
  bottom: 2px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--rule-firm);
  background: var(--flour);
  color: var(--brand);
  cursor: zoom-in;
  padding: 0;
  opacity: 0;
  transform: scale(0.9);
  transition: opacity 0.22s var(--ease), transform 0.22s var(--ease),
    background-color 0.22s var(--ease), color 0.22s var(--ease);
}

.shot__zoom::before {
  content: '⤢';
  font-size: 0.95rem;
  line-height: 1;
}

.shot:hover .shot__zoom,
.shot__zoom:focus-visible {
  opacity: 1;
  transform: none;
}

.shot__zoom:hover {
  background: var(--brand);
  color: var(--flour);
}

/* a pointer that cannot hover has nothing to reveal the control, so it stays */
@media (hover: none) {
  .shot__zoom {
    opacity: 1;
    transform: none;
  }
}

.shot-group {
  margin-top: var(--s5);
}

.shot-group__name {
  font-size: 1.5rem;
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  border-bottom: 1px solid var(--rule-firm);
  padding-bottom: 0.5rem;
}

.shot-group__name a {
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 0.22s var(--ease), border-color 0.22s var(--ease);
}

.shot-group__name a:hover,
.shot-group__name a:focus-visible {
  color: var(--crust);
  border-bottom-color: var(--crust);
}

.shot-group .shots {
  margin-top: var(--s3);
}

/* -------------------------------------------------------------- lightbox */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 80;
  /* light rather than dark: these are cut-outs shot on white, and a dark
     backdrop puts a visible halo around every edge. Cream also reads as the
     studio the photographs actually came from. */
  background: rgba(238, 232, 219, 0.975);
  backdrop-filter: blur(6px);
  display: grid;
  place-items: center;
  padding: clamp(1rem, 4vw, 3rem);
  opacity: 0;
  transition: opacity 0.32s var(--ease);
}

.lightbox[hidden] {
  display: none;
}

.lightbox.is-open {
  opacity: 1;
}

.lightbox__inner {
  position: relative;
  max-width: min(1100px, 100%);
  width: 100%;
}

.lightbox__inner figure {
  margin: 0;
  display: grid;
  place-items: center;
  transform: scale(0.94);
  opacity: 0;
  transition: transform 0.42s var(--ease-out), opacity 0.3s var(--ease);
}

.lightbox.is-open .lightbox__inner figure {
  transform: none;
  opacity: 1;
}

.lightbox img {
  max-height: min(72vh, 760px);
  width: auto;
  max-width: 100%;
  object-fit: contain;
  filter: drop-shadow(0 26px 34px rgba(58, 36, 20, 0.3));
}

.lightbox figcaption {
  margin-top: var(--s3);
  color: var(--bark);
  font-size: 0.95rem;
  text-align: center;
}

.lightbox figcaption .quiet {
  color: var(--slate);
}

.lightbox__nav,
.lightbox__close {
  position: absolute;
  appearance: none;
  border: 1px solid var(--rule-firm);
  background: var(--flour);
  color: var(--brand);
  width: 46px;
  height: 46px;
  border-radius: 50%;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background-color 0.25s var(--ease), transform 0.25s var(--ease),
    border-color 0.25s var(--ease);
}

.lightbox__nav:hover,
.lightbox__close:hover {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--flour);
  transform: scale(1.08);
}

.lightbox__nav::before,
.lightbox__close::before {
  font-size: 1.2rem;
  line-height: 1;
}

.lightbox__nav.is-prev {
  left: -4px;
  top: 42%;
}
.lightbox__nav.is-prev::before {
  content: '‹';
  font-size: 1.8rem;
  transform: translateY(-2px);
}

.lightbox__nav.is-next {
  right: -4px;
  top: 42%;
}
.lightbox__nav.is-next::before {
  content: '›';
  font-size: 1.8rem;
  transform: translateY(-2px);
}

.lightbox__close {
  top: -10px;
  right: -4px;
}
.lightbox__close::before {
  content: '×';
  font-size: 1.6rem;
  transform: translateY(-2px);
}

@media (max-width: 620px) {
  .lightbox__nav.is-prev {
    left: 0;
    top: auto;
    bottom: -6px;
  }
  .lightbox__nav.is-next {
    right: 0;
    top: auto;
    bottom: -6px;
  }
  .lightbox img {
    max-height: 58vh;
  }
}

/* ------------------------------------------------------------------- map */

.map {
  background: #fff;
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: clamp(0.6rem, 2vw, 1.4rem);
  max-width: 760px;
}

.map img {
  width: 100%;
  height: auto;
  border-radius: 2px;
}

.map figcaption {
  padding-top: var(--s2);
  max-width: 56ch;
}

.lightbox__slot {
  display: grid;
  place-items: center;
  min-height: 40vh;
}


/* --------------------------------------------------------------- cookies */

/*
 * A notice, not a consent wall. The site sets no tracking cookies and has no
 * analytics, so this states that plainly and offers to remember the answer.
 * It sits at the bottom, never covers the page, and is only shown at all once
 * the script has confirmed the visitor has not already answered.
 */
.cookies {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  background: var(--bark);
  color: #e6ddcd;
  border-top: 2px solid var(--gold);
  box-shadow: 0 -14px 40px -24px rgba(0, 0, 0, 0.8);
  transform: translateY(101%);
  transition: transform 0.45s var(--ease-out);
}

.cookies[hidden] {
  display: none;
}

.cookies.is-in {
  transform: none;
}

.cookies__in {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3) var(--s4);
  padding-block: 1.1rem;
}

.cookies__text {
  flex: 1 1 34ch;
  min-width: 0;
}

.cookies h2 {
  font-family: var(--display);
  font-size: 1.15rem;
  font-weight: 500;
  color: #f4ecdd;
  margin-bottom: 0.2rem;
}

.cookies p {
  font-size: 0.88rem;
  line-height: 1.5;
  color: #b9ad9e;
  max-width: 68ch;
}

.cookies__actions {
  display: flex;
  align-items: center;
  gap: var(--s3);
  flex: 0 0 auto;
}

.button--sm {
  padding: 0.55rem 1.25rem;
  font-size: 0.92rem;
  border: 0;
  cursor: pointer;
  font-family: inherit;
  background: var(--gold);
  color: var(--bark);
}

.button--sm::before {
  background: var(--gold-bright);
}

.button--sm:hover,
.button--sm:focus-visible {
  color: var(--bark);
}

.cookies__decline {
  appearance: none;
  background: none;
  border: 0;
  padding: 0.55rem 0;
  font: inherit;
  font-size: 0.9rem;
  color: #b9ad9e;
  cursor: pointer;
  border-bottom: 1px solid transparent;
  transition: color 0.22s var(--ease), border-color 0.22s var(--ease);
}

.cookies__decline:hover,
.cookies__decline:focus-visible {
  color: #f4ecdd;
  border-bottom-color: var(--gold-bright);
}

.cookies :focus-visible {
  outline-color: var(--gold-bright);
}

@media (max-width: 620px) {
  .cookies__in {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s3);
    padding-block: 1rem;
  }
  /* the row layout's flex-basis is a width; once this stacks it would become a
     height and blow the notice up to half the screen */
  .cookies__text {
    flex: 0 0 auto;
  }
  .cookies__actions {
    width: 100%;
    justify-content: space-between;
  }
  .cookies p {
    font-size: 0.84rem;
  }
}

/* --------------------------------------------------- pointer target size */

/*
 * WCAG 2.2 asks for 24x24 CSS px on anything that is not inline in a sentence.
 * These four were 16-22px tall: footer links, gallery captions, the bake-chart
 * bread names and the breadcrumb. Padding is added rather than font size so
 * nothing about the type changes; the underline rules sit on the inner span,
 * so they stay tight against the text.
 */
.foot__link,
.chart tbody th a,
.crumb-trail a,
.chips a {
  padding-block: 0.3rem;
}

.foot__link,
.chart tbody th a,
.crumb-trail a {
  display: inline-block;
}

.chart tbody th a {
  text-decoration: none;
}

/* the shelf on the About page ---------------------------------------- */

@media (max-width: 640px) {
  /*
   * Six loaves across a 390px screen gives each about 55px, which is too small
   * to read as a photograph. Three at twice the size is the same idea, legibly.
   */
  .shelf li:nth-child(n + 4) {
    display: none;
  }
  .shelf img {
    max-height: 118px;
  }
}

/* the lightbox caption is the way from a photograph to its bread */
.lightbox__to-bread {
  color: var(--brand);
  text-decoration: none;
  border-bottom: 1px solid var(--rule-firm);
  transition: color 0.22s var(--ease), border-color 0.22s var(--ease);
}

.lightbox__to-bread:hover,
.lightbox__to-bread:focus-visible {
  color: var(--crust);
  border-bottom-color: var(--crust);
}
