/* Hill Country Dairies: site styles. Values come from tokens.css only.
   Order: base, layout, type, buttons, header, hero, sections, components,
   footer, motion, placeholders. */

/* ================= Base ================= */
*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; scroll-padding-top: var(--header-h); }
body {
  margin: 0;
  background: var(--white);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}
img, picture, video, svg { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; }
button { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; border-radius: var(--r-sm); }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: var(--space-4); top: calc(-1 * var(--space-8));
  z-index: 100; padding: var(--space-3) var(--space-4);
  background: var(--ink); color: var(--white); border-radius: var(--r-sm);
}
.skip-link:focus { top: var(--space-4); }

/* Text selection follows the ground it sits on. Explicit selectors per
   ground rather than a variable swap, because browsers disagree on where
   ::selection reads custom properties from. */
::selection { background: var(--select-bg); color: var(--select-fg); text-shadow: none; }
:is(.section--ink, .section--green-night, .hero, .page-hero--photo, .media-slot, .site-footer) ::selection {
  background: var(--select-bg-dark); color: var(--select-fg-dark);
}
.section--red ::selection { background: var(--select-bg-red); color: var(--select-fg-red); }

/* ================= Layout ================= */
.container { width: min(100% - 2 * var(--gutter), var(--container)); margin-inline: auto; }
/* Opaque by default, so each section fully covers what scrolls under it. */
.section { position: relative; padding-block: var(--space-section); background: var(--white); }
.section--paper { background: var(--paper); }
.section--ink { background: var(--ink); color: var(--on-dark); }
.section--red { background: var(--red); color: var(--on-dark); }
.section--green-night { background: var(--green-night); color: var(--on-dark); }
.section--tight { padding-block: var(--space-8); }
.section__head { display: grid; gap: var(--space-4); max-width: 52rem; margin-bottom: var(--space-7); }
.section__head--center { margin-inline: auto; text-align: center; justify-items: center; }
.section__head--split {
  max-width: none; grid-template-columns: 1fr auto; align-items: end; gap: var(--space-5);
}
@media (max-width: 760px) { .section__head--split { grid-template-columns: 1fr; } }
.stack > * + * { margin-top: var(--space-4); }

/* ================= Type ================= */
h1, h2, h3, h4, .display {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  text-transform: uppercase;
  letter-spacing: var(--track-display);
  color: var(--text-strong);
  line-height: var(--lh-heading);
  text-wrap: balance;
}
:is(.section--ink, .section--red, .section--green-night) :is(h1, h2, h3, h4) { color: var(--white); }
h1, .h1 { font-size: var(--fs-h1); line-height: var(--lh-display); }
h2, .h2 { font-size: var(--fs-h2); line-height: var(--lh-display); }
h3, .h3 { font-size: var(--fs-h3); }
h4, .h4 { font-size: var(--fs-h4); }
p { margin: 0; }
.lead { font-size: var(--fs-lead); line-height: 1.5; max-width: var(--measure); }
.eyebrow {
  font-family: var(--font-body); font-size: var(--fs-eyebrow); font-weight: var(--weight-semi);
  letter-spacing: var(--track-eyebrow); text-transform: uppercase; color: var(--red);
}
:is(.section--ink, .section--red, .section--green-night) .eyebrow { color: var(--on-dark-muted); }
.small { font-size: var(--fs-small); }
.muted { color: var(--muted); }

/* ================= Buttons ================= */
.btn {
  --btn-bg: var(--red); --btn-fg: var(--white); --btn-bd: var(--red);
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: var(--tap); padding: var(--space-3) var(--space-5);
  border: 1.5px solid var(--btn-bd); border-radius: var(--r-pill);
  background: var(--btn-bg); color: var(--btn-fg);
  font-family: var(--font-body); font-size: var(--fs-small); font-weight: var(--weight-semi);
  letter-spacing: 0.02em; text-decoration: none; white-space: nowrap; cursor: pointer;
  position: relative; isolation: isolate; overflow: hidden;
  --btn-wipe: var(--green);
  transition: transform var(--dur-hover) var(--ease-hover);
}
/* Green wipe: on hover or keyboard focus, field green slides in from the
   left over red (and light) buttons, fading up as it goes; on leave it
   retracts the way it came, right to left. Anchored on the left both ways so
   the return is the same move in reverse. The layer sits under the label.
   Outline and ghost buttons set no wipe and keep their own hover. */
.btn::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--btn-wipe);
  transform: scaleX(0); transform-origin: left center; opacity: 0;
  transition: transform var(--dur-wipe) var(--ease-wipe),
              opacity var(--dur-wipe-fade) var(--ease-wipe);
}
.btn:focus-visible::before { transform: scaleX(1); opacity: 1; }
.btn:focus-visible { transform: translateY(var(--lift)); --btn-bd: var(--btn-wipe); }
.btn:active { transform: none; }
.btn--outline { --btn-bg: transparent; --btn-fg: var(--ink); --btn-bd: var(--ink); --btn-wipe: transparent; }
.btn--light { --btn-bg: var(--white); --btn-fg: var(--ink); --btn-bd: var(--white); }
.btn--light:focus-visible { --btn-fg: var(--white); }
.btn--ghost-light { --btn-bg: transparent; --btn-fg: var(--white); --btn-bd: var(--on-dark-line); --btn-wipe: transparent; }
/* Hover states only where a pointer can hover, so a tap on a phone does not
   leave a button, card or link stuck in its hover look. */
@media (hover: hover) {
  .btn:hover::before { transform: scaleX(1); opacity: 1; }
  .btn:hover { transform: translateY(var(--lift)); --btn-bd: var(--btn-wipe); }
  .btn--outline:hover { --btn-bg: var(--ink); --btn-fg: var(--white); --btn-bd: var(--ink); }
  .btn--light:hover { --btn-fg: var(--white); }
  .btn--ghost-light:hover { --btn-bg: var(--white); --btn-fg: var(--ink); --btn-bd: var(--white); }
  .link-arrow:hover::after { transform: translateX(4px); }
  .crumbs a:hover { text-decoration: underline; }
  a.card:hover { transform: translateY(var(--lift)); box-shadow: var(--shadow-card); }
  a.card:hover .card__media img { transform: scale(var(--zoom)); }
  .branches a:hover::after { transform: translateX(4px); }
  .icon-btn:hover { transform: translateY(var(--lift)); border-color: var(--ink); }
  .footer__social a:hover { background: var(--red); border-color: var(--red); color: var(--white); }
  .footer__col a:hover { color: var(--white); }
  .gate__link:hover { text-decoration: underline; text-underline-offset: 4px; }
}
.btn__icon { width: 1em; height: 1em; flex: none; }
.btn-row { display: flex; flex-wrap: wrap; gap: var(--space-3); }

.link-arrow {
  position: relative; display: inline-flex; align-items: center; gap: var(--space-2);
  font-weight: var(--weight-semi); font-size: var(--fs-small); text-decoration: none; color: var(--red);
}
.link-arrow::after { content: "\2192"; transition: transform var(--dur-hover) var(--ease-hover); }

/* Nav hover: the link grows 1.2x and turns barn red, then a faint red glow
   builds over --dur-glow for as long as the pointer stays. The glow is a
   transparent copy of the label (data-text) behind it that carries the
   text-shadow and fades in by opacity, so only transform and opacity
   animate. Leaving undoes both quickly. */
.roll, .roll__in { display: inline-block; }
.roll__in, .header__phone-label { position: relative; isolation: isolate; }
.roll__in::after, .header__phone-label::after {
  content: attr(data-text); position: absolute; inset: 0; z-index: -1;
  color: transparent; text-shadow: var(--nav-glow); pointer-events: none;
  opacity: 0; transition: opacity var(--dur-hover) var(--ease-hover);
}
.nav-list > li > a, .header__login, .header__phone {
  transition: transform var(--dur-hover) var(--ease-hover);
}
@media (hover: hover) {
  .nav-list > li > a:hover, .header__login:hover, .header__phone:hover {
    transform: scale(var(--nav-grow));
    color: var(--red);
  }
  :is(.nav-list > li > a, .header__login):hover .roll__in::after,
  .header__phone:hover .header__phone-label::after {
    opacity: 1; transition: opacity var(--dur-glow) var(--ease-glow) var(--dur-hover);
  }
}
.nav-list > li > a:focus-visible, .header__login:focus-visible, .header__phone:focus-visible { color: var(--red); }

/* ================= Header ================= */
.site-header {
  position: sticky; top: 0; z-index: 50;
  height: var(--header-h);
  color: var(--ink);
}
/* Two layers behind the bar: ::before is the solid white of inner pages,
   ::after the frost (blur and shadow) once the page scrolls. They crossfade
   by opacity only. */
.site-header::before, .site-header::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  transition: opacity var(--dur-header) var(--ease-enter);
}
.site-header::before { background: var(--white); }
.site-header::after {
  background: var(--frost);
  -webkit-backdrop-filter: var(--frost-filter);
  backdrop-filter: var(--frost-filter);
  box-shadow: var(--shadow-header);
  opacity: 0;
}
.site-header.is-scrolled::before { opacity: 0; }
.site-header.is-scrolled::after { opacity: 1; }
/* Home: header floats over the hero and reads white until the page scrolls. */
.site-header--overlay { position: fixed; inset-inline: 0; color: var(--white); }
.site-header--overlay::before { opacity: 0; }
.site-header--overlay.is-scrolled { color: var(--ink); }
.site-header--overlay:not(.is-scrolled) .btn--outline { --btn-fg: var(--white); --btn-bd: var(--on-dark-line); }
.site-header--overlay:not(.is-scrolled) .btn--outline:hover { --btn-bg: var(--white); --btn-fg: var(--ink); --btn-bd: var(--white); }

.header__bar {
  height: 100%; display: flex; align-items: center; gap: var(--space-5);
}
.header__logo { flex: none; display: block; width: var(--logo-w); }
.header__logo img { width: 100%; height: auto; }
/* Logo hover, matched to the nav: grows 1.2x at hover speed, then a faint
   red glow builds over --dur-glow while the pointer stays. The glow is a
   blurred layer behind the mark fading in (opacity only), so the client's
   logo itself is never recoloured. Leaving undoes both quickly. */
.header__logo {
  position: relative; isolation: isolate; transform-origin: left top;
  transition: transform var(--dur-hover) var(--ease-hover);
}
.header__logo::before {
  content: ""; position: absolute; inset: 12%; z-index: -1; border-radius: var(--r-round);
  background: var(--logo-glow); filter: blur(var(--blur-frost));
  opacity: 0; transition: opacity var(--dur-hover) var(--ease-hover);
}
@media (hover: hover) {
  .header__logo:hover { transform: scale(var(--nav-grow)); }
  .header__logo:hover::before { opacity: 1; transition: opacity var(--dur-glow) var(--ease-glow) var(--dur-hover); }
}
.header__nav { margin-inline: auto; }
.nav-list { display: flex; gap: var(--space-5); list-style: none; margin: 0; padding: 0; }
.nav-list > li > a {
  position: relative; display: inline-flex; align-items: center; min-height: var(--tap);
  font-size: var(--fs-small); font-weight: var(--weight-medium); text-decoration: none;
}
.nav-list > li > a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 10px; height: 1.5px;
  background: currentColor; transform: scaleX(0); transform-origin: right;
  transition: transform var(--dur-hover) var(--ease-hover);
}
.nav-list > li > a:hover::after, .nav-list > li > a[aria-current]::after { transform: scaleX(1); transform-origin: left; }
/* Nav dropdowns (Locations, About, Resources). The label still links to the
   section index; hovering the item, focusing into it, or the caret button
   opens a white panel of its pages. It fades and drops 4px; under reduced
   motion it just appears. A transparent band above the panel bridges the
   gap so the pointer can travel down without the menu closing. */
.nav-item { position: relative; display: flex; align-items: center; gap: var(--space-1); }
/* The label grows leftward on hover so it never runs into its caret. */
.nav-item > a { transform-origin: right center; }
.nav-caret {
  display: inline-grid; place-items: center; width: var(--space-4); min-height: var(--tap);
  padding: 0; border: 0; background: none; color: inherit; cursor: pointer;
}
.nav-caret::before {
  content: ""; width: 6px; height: 6px; margin-top: calc(-1 * var(--space-1));
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg); transition: transform var(--dur-hover) var(--ease-hover);
}
.nav-menu {
  position: absolute; top: 100%; left: 50%; z-index: 60;
  min-width: 13rem; margin: 0; padding: var(--space-2); list-style: none;
  background: var(--white); color: var(--ink); border-radius: var(--r-md); box-shadow: var(--shadow-card);
  opacity: 0; visibility: hidden; transform: translate(-50%, -4px);
  transition: opacity var(--dur-hover) var(--ease-hover), transform var(--dur-hover) var(--ease-hover), visibility 0s linear var(--dur-hover);
}
.nav-menu::before { content: ""; position: absolute; inset: calc(-1 * var(--space-3)) 0 100%; }
.nav-item:hover .nav-menu, .nav-item:focus-within .nav-menu, .nav-item.is-open .nav-menu {
  opacity: 1; visibility: visible; transform: translate(-50%, 0);
  transition: opacity var(--dur-hover) var(--ease-enter), transform var(--dur-hover) var(--ease-enter), visibility 0s;
}
.nav-item.is-dismissed .nav-menu { opacity: 0; visibility: hidden; transform: translate(-50%, -4px); }
.nav-item:hover .nav-caret::before, .nav-item:focus-within .nav-caret::before, .nav-item.is-open .nav-caret::before { transform: translateY(3px) rotate(225deg); }
.nav-menu a {
  display: block; padding: var(--space-2) var(--space-3); border-radius: var(--r-sm);
  font-size: var(--fs-small); font-weight: var(--weight-medium); text-decoration: none; white-space: nowrap;
}
.nav-menu a:hover, .nav-menu a:focus-visible { background: var(--red-tint); color: var(--red-deep); }
@media (prefers-reduced-motion: reduce) {
  .nav-menu, .nav-item:hover .nav-menu, .nav-item:focus-within .nav-menu, .nav-item.is-open .nav-menu { transform: translate(-50%, 0); transition: none; }
}
.header__actions { display: flex; align-items: center; gap: var(--space-4); flex: none; }
.header__phone, .header__login {
  display: inline-flex; align-items: center; min-height: var(--tap);
  font-size: var(--fs-small); font-weight: var(--weight-semi); text-decoration: none; white-space: nowrap;
}
/* Grows leftward into open space so it never crowds Customer Login. */
.header__phone { transform-origin: right center; justify-content: center; min-width: var(--tap); }
.header__phone svg { width: 14px; height: 14px; margin-right: var(--space-2); }
.menu-toggle {
  display: none; align-items: center; justify-content: center;
  width: var(--tap); height: var(--tap); padding: 0; border: 0; background: none; cursor: pointer;
}
.menu-toggle__bars, .menu-toggle__bars::before, .menu-toggle__bars::after {
  display: block; width: 22px; height: 2px; background: currentColor; border-radius: var(--r-xs);
  transition: transform var(--dur-hover) var(--ease-hover), opacity var(--dur-hover) var(--ease-hover);
}
.menu-toggle__bars { position: relative; }
.menu-toggle__bars::before, .menu-toggle__bars::after { content: ""; position: absolute; left: 0; }
.menu-toggle__bars::before { transform: translateY(-7px); }
.menu-toggle__bars::after { transform: translateY(7px); }
.menu-open .menu-toggle__bars { background: transparent; }
.menu-open .menu-toggle__bars::before { transform: rotate(45deg); }
.menu-open .menu-toggle__bars::after { transform: rotate(-45deg); }

@media (max-width: 1080px) {
  .header__nav, .header__login, .header__phone-label { display: none; }
  .header__phone svg { width: var(--space-5); height: var(--space-5); margin-right: 0; }
  .menu-toggle { display: inline-flex; }
  .header__actions { margin-left: auto; gap: var(--space-2); }
}
@media (max-width: 520px) {
  .header__actions .btn { display: none; }
  .header__logo { width: var(--logo-w-sm); }
}

/* Mobile menu panel */
.mobile-nav {
  position: fixed; inset: var(--header-h) 0 0 0; z-index: 49;
  overflow-y: auto; padding: var(--space-6) var(--gutter) var(--space-8);
  background: var(--white); color: var(--ink);
  opacity: 0; visibility: hidden; transform: translateY(-8px);
  transition: opacity var(--dur-hover) var(--ease-hover), transform var(--dur-hover) var(--ease-hover), visibility 0s linear var(--dur-hover);
}
.menu-open .mobile-nav { opacity: 1; visibility: visible; transform: none; transition-delay: 0s; }
.menu-open .site-header { background: var(--white); color: var(--ink); }
.mobile-nav__list { list-style: none; margin: 0; padding: 0; border-top: var(--border); }
.mobile-nav__list > li { border-bottom: var(--border); }
.mobile-nav__list > li > a {
  display: flex; align-items: center; min-height: 56px;
  font-family: var(--font-display); font-weight: var(--weight-bold); font-size: var(--fs-h4);
  text-transform: uppercase; text-decoration: none;
}
.mobile-nav__sub { list-style: none; margin: 0 0 var(--space-4); padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-1) var(--space-4); }
.mobile-nav__sub a { display: flex; align-items: center; min-height: var(--tap); font-size: var(--fs-small); text-decoration: none; color: var(--body); }
.mobile-nav__actions { display: grid; gap: var(--space-3); margin-bottom: var(--space-6); }
.mobile-nav__actions .btn { width: 100%; }
@media (min-width: 1081px) { .mobile-nav { display: none; } }

/* ================= Hero (home) ================= */
.hero {
  position: relative; isolation: isolate;
  min-height: max(100svh, 560px);
  display: grid; align-items: end;
  color: var(--white);
  background: var(--ink);
}
.hero__media { position: absolute; inset: 0; z-index: -1; overflow: hidden; }
.hero__media picture, .hero__media img, .hero__media video { width: 100%; height: 100%; object-fit: cover; object-position: 62% 70%; }
.hero__media::after { content: ""; position: absolute; inset: 0; background: var(--scrim); }
.hero__content {
  padding-top: calc(var(--header-h) + var(--space-8));
  padding-bottom: clamp(var(--space-7), 8svh, var(--space-8) * 1.5);
  display: grid; gap: var(--space-5); justify-items: start;
}
.hero__content > * { max-width: 46rem; }
.hero__title { font-size: var(--fs-hero); line-height: var(--lh-display); color: var(--white); }
.hero__title sup { font-size: 0.28em; vertical-align: top; position: relative; top: 0.35em; letter-spacing: 0; }
.hero__lead { font-size: var(--fs-lead); color: var(--on-dark); max-width: 34rem; line-height: 1.5; font-weight: var(--weight-medium); }
.hero__tag { position: absolute; right: var(--gutter); bottom: var(--space-5); }
@media (max-width: 760px) { .hero__tag { left: var(--gutter); right: auto; top: calc(var(--header-h) + var(--space-3)); bottom: auto; } }

/* ================= Inner page hero ================= */
.page-hero { position: relative; isolation: isolate; background: var(--paper); padding-block: var(--space-8) var(--space-7); }
.page-hero--photo { color: var(--white); background: var(--ink); min-height: clamp(360px, 52svh, 560px); display: grid; align-items: end; }
.page-hero--photo .page-hero__media { position: absolute; inset: 0; z-index: -1; }
.page-hero--photo .page-hero__media picture, .page-hero--photo .page-hero__media img { width: 100%; height: 100%; object-fit: cover; }
.page-hero--photo .page-hero__media::after { content: ""; position: absolute; inset: 0; background: var(--scrim); }
.page-hero--photo h1 { color: var(--white); }
.page-hero--photo .lead { color: var(--on-dark); }
.page-hero__inner { display: grid; gap: var(--space-4); }
.crumbs { display: flex; flex-wrap: wrap; gap: var(--space-2); list-style: none; margin: 0; padding: 0; font-size: var(--fs-small); color: var(--muted); }
.page-hero--photo .crumbs { color: var(--on-dark-muted); }
.crumbs li + li::before { content: "/"; margin-right: var(--space-2); opacity: 0.6; }
.crumbs a { position: relative; text-decoration: none; }

/* ================= Milk wave edge =================
   A still row of scallops on the top edge of a section, in that section's
   own colour, so it reads as the section "pouring" over the one above.
   Static by design: the Framer draft drifted it; we do not. */
.wave-top { --wave-color: var(--white); }
.wave-top::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 100%;
  height: var(--wave-r); background: var(--wave-color);
  -webkit-mask: radial-gradient(circle var(--wave-r) at 50% 100%, black 98%, transparent 100%) 0 0 / calc(var(--wave-r) * 2) var(--wave-r) repeat-x;
          mask: radial-gradient(circle var(--wave-r) at 50% 100%, black 98%, transparent 100%) 0 0 / calc(var(--wave-r) * 2) var(--wave-r) repeat-x;
  pointer-events: none;
}
.section--paper.wave-top { --wave-color: var(--paper); }
.section--ink.wave-top { --wave-color: var(--ink); }
.section--red.wave-top { --wave-color: var(--red); }
.section--green-night.wave-top { --wave-color: var(--green-night); }

/* ================= Definition band ================= */
/* Copy on the left, a delivery photo on the right. The photo drifts up as
   the band scrolls through (motion.js, [data-drift]). */
.definition { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); align-items: center; gap: var(--space-8); }
.definition__copy { display: grid; gap: var(--space-6); }
.definition__title { font-size: var(--fs-h1); line-height: var(--lh-display); }
.definition__title em { font-style: normal; color: var(--red); }
.definition__standard {
  max-width: var(--measure); border-top: 2px solid var(--ink); padding-top: var(--space-4);
  font-size: var(--fs-lead); line-height: 1.5; font-weight: var(--weight-medium); color: var(--ink);
}
/* A delivery photo; it drifts as a whole, so the rounding is on the image. */
.definition__media picture { display: block; }
.definition__media img { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--r-lg); }
@media (max-width: 760px) {
  .definition { grid-template-columns: 1fr; gap: var(--space-7); }
}

/* ================= Cards ================= */
.grid { display: grid; gap: var(--space-4); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--5 { grid-template-columns: repeat(5, 1fr); }
/* Six items: 6 across, then 3x2, then 2x3, so no row is ever left with one card. */
.grid--6 { grid-template-columns: repeat(6, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 1080px) { .grid--5, .grid--6 { grid-template-columns: repeat(3, 1fr); } .grid--4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 860px) { .grid--3, .grid--5 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .grid--3, .grid--5, .grid--4, .grid--2 { grid-template-columns: 1fr; } }
@media (max-width: 560px) { .grid--6 { grid-template-columns: repeat(2, 1fr); } }

.card {
  position: relative; display: flex; flex-direction: column;
  background: var(--white); border: var(--border); border-radius: var(--r-md); overflow: hidden;
  text-decoration: none; color: inherit;
  transition: transform var(--dur-hover) var(--ease-hover);
}
.card__media { position: relative; aspect-ratio: 4 / 3; overflow: hidden; background: var(--paper); }
.card__media--tall { aspect-ratio: 3 / 4; }
/* The <picture> wrapper must fill the tall frame, or the photo stops short
   and leaves a grey band under it. */
.card__media--tall > picture { display: block; height: 100%; }
.card__media--wide { aspect-ratio: 16 / 10; }
.card__media picture { width: 100%; height: 100%; }
.card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-zoom) var(--ease-enter); }
.card__media--contain img { object-fit: contain; padding: var(--space-5); }
.card__body { display: grid; gap: var(--space-2); padding: var(--space-5); flex: 1; align-content: start; }
.card__title { font-size: var(--fs-h4); line-height: var(--lh-heading); }
.card__more { margin-top: auto; padding-top: var(--space-3); }
.card__num {
  font-family: var(--font-display); font-weight: var(--weight-bold); font-size: var(--fs-small);
  color: var(--red); letter-spacing: var(--track-eyebrow);
}
.section--paper .card { border-color: transparent; }
/* A white card on a dark ground keeps light-ground type, or its text would
   inherit the section's white and vanish. */
:is(.section--ink, .section--red, .section--green-night) :is(.card, .matrix) { color: var(--text); border-color: transparent; }
:is(.section--ink, .section--red, .section--green-night) :is(.card, .matrix) :is(h1, h2, h3, h4) { color: var(--text-strong); }
:is(.section--ink, .section--red, .section--green-night) .card .eyebrow { color: var(--red); }

/* Pillars: bigger cards with a tag for the clip that will replace the photo */
.pillar .card__media { aspect-ratio: 4 / 5; }
.pillar .card__title { font-size: var(--fs-h3); }
/* One card per row on phones: portrait frames would make each card most of
   a screen tall, so they go landscape. */
@media (max-width: 560px) {
  .card__media--tall, .pillar .card__media { aspect-ratio: 4 / 3; }
}

/* ================= Texture pack =================
   Background layers a section can stack. Put .has-tex on the section and
   one empty <span class="tex tex--..." aria-hidden="true"></span> per layer
   as its first children; later layers paint over earlier ones, and all of
   them sit under the content. Pure CSS: visible with JS off, never moves.
   Only the sides are clipped, so the milk wave edge above it still shows. */
.has-tex { isolation: isolate; overflow-x: clip; }
.tex { position: absolute; inset: 0; z-index: -1; pointer-events: none; }

/* Flannel (.tex--flannel): buffalo check. The section ground is the light
   square and the ink is the dark one; a variant class picks the ink.
   --tex-alpha-flannel is its fade. */
.tex.tex--flannel {
  --tex-ink: var(--ink);
  background: var(--tex-ink); opacity: var(--tex-alpha-flannel);
  -webkit-mask: var(--tex-flannel-img) 0 0 / var(--tex-flannel-tile) repeat;
          mask: var(--tex-flannel-img) 0 0 / var(--tex-flannel-tile) repeat;
}
.tex--flannel.tex--field { --tex-ink: var(--green-field); }
@media (max-width: 520px) {
  .tex.tex--flannel { -webkit-mask-size: var(--tex-flannel-tile-sm); mask-size: var(--tex-flannel-tile-sm); }
}

/* Barn banner: the logo's barn scene pinned to the right edge at full
   section height, fading in from its left edge (--barn-fade). A tint on the
   same layer blends into the picture only, through --barn-blend, and keeps
   the fade because the mask covers both. */
.tex--barn {
  left: auto; aspect-ratio: var(--barn-ratio);
  background: var(--barn-tint), var(--barn-img) right bottom / cover no-repeat;
  background-blend-mode: var(--barn-blend);
  -webkit-mask: var(--barn-fade); mask: var(--barn-fade);
}
.tex--barn.tex--green { --barn-tint: linear-gradient(var(--green-tree), var(--green-tree)); --barn-blend: color; }
/* Narrow screens: the barn spans the section so the whole fade stays visible. */
@media (max-width: 760px) { .tex--barn { left: 0; aspect-ratio: auto; } }

/* ================= The stack =================
   A section marked .stack-under holds still once its bottom reaches the
   bottom of the screen, and the sections after it slide up over it (home:
   "Kitchens that can't run out" under the Texas map, Ian 2026-10-06).
   site.js turns it on (.is-stacking) and sets --stack-top to the height
   it must stick at; with JS off it scrolls normally. Plain CSS sticky:
   it answers the scroll and never moves on its own. */
.stack-under.is-stacking { position: sticky; top: var(--stack-top); z-index: 0; }
.stack-under.is-stacking ~ section { z-index: 1; }
@media (max-width: 760px) { .stack-under.is-stacking { position: relative; top: auto; } }

/* ================= Split (story teaser, location detail) ================= */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(var(--space-6), 5vw, var(--space-8)); align-items: center; }
.split__media { border-radius: var(--r-lg); overflow: hidden; aspect-ratio: 4 / 3.4; }
.split__media picture, .split__media img { width: 100%; height: 100%; object-fit: cover; }
.split--flip .split__media { order: 2; }
.split--top { align-items: start; }
@media (max-width: 860px) { .split { grid-template-columns: 1fr; } .split--flip .split__media { order: 0; } }

/* ================= Media slot (VSL and clips) =================
   Holds the poster today. A <video> with the same aspect ratio drops in
   later with no layout shift. */
.media-slot { position: relative; aspect-ratio: 16 / 9; border-radius: var(--r-lg); overflow: hidden; background: var(--ink); }
.media-slot picture, .media-slot img, .media-slot video { width: 100%; height: 100%; object-fit: cover; }
.media-slot::after { content: ""; position: absolute; inset: 0; background: var(--scrim-flat); }
.media-slot__overlay { position: absolute; inset: 0; z-index: 1; display: grid; place-items: center; align-content: center; gap: var(--space-4); }

/* ================= Testimonials (manual) ================= */
.quotes { position: relative; }
.quotes__track {
  display: grid; grid-auto-flow: column; grid-auto-columns: 100%;
  overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none;
  overscroll-behavior-x: contain;
}
.quotes__track::-webkit-scrollbar { display: none; }
.quote {
  margin: 0; scroll-snap-align: start; display: grid; gap: var(--space-5) var(--space-8);
  grid-template-columns: minmax(0, 56rem) var(--logo-quote-w); grid-template-areas: "text logo" "by logo";
  align-items: center; justify-content: space-between;
}
.quote__text { grid-area: text; }
.quote__by { grid-area: by; align-self: start; }
.quote__logo { grid-area: logo; transition: opacity var(--dur-logo-pop) var(--ease-enter), transform var(--dur-logo-pop) var(--ease-enter); }
.quote__logo img { display: block; width: 100%; height: auto; }
/* site.js marks the slider (.is-live) and the current slide (.is-current);
   the other slides' logos wait small and clear, so each pops in as its
   quote arrives. With JS off every logo simply shows. */
.quotes.is-live .quote:not(.is-current) .quote__logo { opacity: 0; transform: scale(var(--logo-pop)); }
@media (max-width: 760px) {
  .quote { grid-template-columns: 1fr; grid-template-areas: "logo" "text" "by"; }
  .quote__logo { width: var(--logo-quote-w); }
}
.quote__text { font-family: var(--font-display); font-weight: var(--weight-medium); font-size: var(--fs-h3); line-height: 1.15; color: var(--ink); text-transform: none; letter-spacing: 0; margin: 0; }
.quote__by { font-size: var(--fs-small); color: var(--muted); }
.quotes__controls { display: flex; align-items: center; gap: var(--space-4); margin-top: var(--space-6); }
.icon-btn {
  display: grid; place-items: center; width: var(--tap); height: var(--tap);
  border: var(--border); border-radius: var(--r-round); background: var(--white); cursor: pointer;
  transition: transform var(--dur-hover) var(--ease-hover);
}
.icon-btn svg { width: 16px; height: 16px; }
.dots { display: flex; }
.dots button {
  width: var(--tap); height: var(--tap); padding: 0; border: 0; background: none; cursor: pointer; position: relative;
}
.dots button::before {
  content: ""; position: absolute; left: var(--space-2); right: var(--space-2); top: 50%; height: 3px; border-radius: var(--r-xs);
  background: var(--line);
}
.dots button[aria-current="true"]::before { background: var(--red); }

/* ================= FAQ ================= */
.faq { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--space-7); align-items: start; }
.faq__col { border-top: var(--border); }
@media (max-width: 860px) {
  .faq { grid-template-columns: 1fr; }
  .faq__col + .faq__col { border-top: 0; }
}
.faq details { border-bottom: var(--border); }
.faq summary {
  display: flex; justify-content: space-between; align-items: center; gap: var(--space-4);
  min-height: 64px; padding-block: var(--space-4); cursor: pointer; list-style: none;
  font-weight: var(--weight-semi); color: var(--ink);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+"; flex: none; display: grid; place-items: center; width: 32px; height: 32px;
  border-radius: var(--r-round); border: var(--border); font-size: var(--fs-lead); line-height: 1;
  transition: transform var(--dur-hover) var(--ease-hover);
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq__answer { padding-bottom: var(--space-5); max-width: var(--measure); }

/* ================= Prose (placeholder body copy) ================= */
.prose { max-width: var(--measure); }
.prose > * + * { margin-top: var(--space-4); }
.prose h2 { font-size: var(--fs-h3); margin-top: var(--space-7); }
.prose > h2:first-child { margin-top: 0; }
.prose h3 { font-size: var(--fs-h4); margin-top: var(--space-6); }
.prose ul { padding-left: var(--space-5); }
.prose li + li { margin-top: var(--space-2); }
.story-photo { margin: var(--space-6) 0; }
/* Branch page: Location details on the left, a gray bar, and a live map
   of the branch filling the rest. Wider than the container, so the
   details sit nearer the left edge. */
.branch-detail {
  display: grid; grid-template-columns: minmax(0, var(--branch-info-w)) var(--branch-bar-w) minmax(0, 1fr);
  gap: var(--space-7); align-items: stretch;
  padding-inline: var(--branch-edge);
}
.branch-detail__bar { background: var(--branch-bar); border-radius: var(--r-xs); }
.branch-detail__map { min-height: var(--branch-map-h); border-radius: var(--r-lg); overflow: hidden; border: var(--border); background: var(--paper); }
.branch-detail__map iframe { display: block; width: 100%; height: 100%; min-height: var(--branch-map-h); border: 0; }
@media (max-width: 860px) {
  .branch-detail { grid-template-columns: 1fr; gap: var(--space-6); padding-inline: var(--gutter); }
  .branch-detail__bar { height: var(--branch-bar-w); }
}
/* Blog: topic filter chips, and posts set as readable prose. */
.chips { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-6); }
.chip {
  min-height: var(--tap); padding: var(--space-2) var(--space-4); border: var(--border); border-radius: var(--r-pill);
  background: var(--white); color: var(--ink); font: inherit; font-size: var(--fs-small); font-weight: var(--weight-semi); cursor: pointer;
}
.chip[aria-pressed="true"] { background: var(--ink); color: var(--white); border-color: var(--ink); }
.blog-card[hidden] { display: none; }
.blog-card .card__media { aspect-ratio: var(--blog-banner-ratio); }  /* show the whole title banner, never cropped */
.blog-card .eyebrow { margin-bottom: var(--space-1); }
.blog-post h2 { font-size: var(--fs-h4); margin-top: var(--space-6); }
/* Our Story: the team photo beside the story, holding in view as it reads. */
.story-photo--side { margin: 0; position: sticky; top: calc(var(--header-h) + var(--space-6)); }
@media (max-width: 860px) { .story-photo--side { position: static; } }
.story-photo img { display: block; width: 100%; height: auto; border-radius: var(--r-lg); }
.story-photo figcaption { margin-top: var(--space-2); font-size: var(--fs-small); color: var(--muted); }

/* ================= Forms ================= */
.form { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
.form__full { grid-column: 1 / -1; }
.field { display: grid; gap: var(--space-2); }
.field label { font-size: var(--fs-small); font-weight: var(--weight-semi); color: var(--ink); }
.field input, .field select, .field textarea {
  width: 100%; min-height: var(--tap); padding: var(--space-3) var(--space-4);
  border: var(--border); border-radius: var(--r-sm); background: var(--white);
  font: inherit; color: var(--ink);
}
.field textarea { min-height: 120px; resize: vertical; }
.form .btn { font-size: var(--fs-body); }
.section--ink .field label { color: var(--white); }
@media (max-width: 560px) { .form { grid-template-columns: 1fr; } }

/* ================= CTA band ================= */
.cta { display: grid; grid-template-columns: 1.1fr 1fr; gap: clamp(var(--space-6), 5vw, var(--space-8)); align-items: start; }
.cta__phone { display: inline-flex; align-items: center; min-height: var(--tap); font-family: var(--font-display); font-weight: var(--weight-bold); font-size: var(--fs-h2); line-height: 1; letter-spacing: var(--track-display); color: var(--white); text-decoration: none; }
@media (max-width: 860px) { .cta { grid-template-columns: 1fr; } }

/* ================= Footer ================= */
/* The CTA band and the footer share the ink ground, so their paddings read
   as one gap; both are halved so the footer columns sit closer to the CTA. */
.section--cta { padding-bottom: calc(var(--space-section) / 2); }
.site-footer { position: relative; background: var(--ink); color: var(--on-dark-muted); padding-top: var(--space-6); overflow: hidden; }
/* Texas behind the footer: faint red border, fainter fill. Sits on the
   right behind the link columns; its south tucks behind the wordmark. */
.footer__texas {
  position: absolute; z-index: 0; pointer-events: none;
  top: 0; right: max(var(--gutter), (100% - var(--container)) / 2);
  width: min(69vw, 60rem); height: auto;
}
.footer__texas path { fill: var(--texas-fill); stroke: var(--texas-line); stroke-width: 1.5; stroke-linejoin: round; }
.site-footer > .container { position: relative; z-index: 1; }
/* Social icons under Customer Login. Faint like the Texas outline: a thin
   red ring, muted glyph; hover fills barn red. They live in the brand
   column's spare height, so the footer does not grow on desktop. */
.footer__social { display: flex; gap: var(--space-2); list-style: none; margin: 0; padding: 0; }
.footer__social a {
  display: grid; place-items: center; width: var(--tap); height: var(--tap);
  border: 1px solid var(--texas-line); border-radius: var(--r-round); color: var(--on-dark-muted);
}
.footer__social a:focus-visible { background: var(--red); border-color: var(--red); color: var(--white); }
.footer__social svg { width: 18px; height: 18px; fill: currentColor; }
.footer__top { display: grid; grid-template-columns: 1.3fr repeat(4, 1fr); gap: var(--space-6); }
.footer__brand { display: grid; gap: var(--space-4); align-content: start; }
.footer__brand img { width: 140px; }
.footer__col h2 { font-family: var(--font-body); font-size: var(--fs-eyebrow); font-weight: var(--weight-semi); letter-spacing: var(--track-eyebrow); color: var(--white); margin-bottom: var(--space-3); }
.footer__col ul { list-style: none; margin: 0; padding: 0; }
.footer__col a { display: inline-flex; align-items: center; min-height: var(--tap); min-width: var(--tap); font-size: var(--fs-small); text-decoration: none; }
.footer__phone { position: relative; color: var(--white); font-weight: var(--weight-semi); text-decoration: none; }
.footer__wordmark {
  margin-top: var(--space-8);
  font-family: var(--font-display); font-weight: var(--weight-bold); text-transform: uppercase;
  /* Sized to the container so it always fits: 12 condensed caps span about 5.3em. */
  font-size: min(calc((100vw - 2 * var(--gutter)) / 5.4), calc(var(--container) / 5.4));
  line-height: 0.8; letter-spacing: var(--track-display); color: var(--white);
  white-space: nowrap; user-select: none;
}
.footer__bottom { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-3); padding-block: var(--space-5); border-top: 1px solid var(--on-dark-line); margin-top: var(--space-5); font-size: var(--fs-small); }
.footer__bottom a { position: relative; text-decoration: none; }
.details dd a { position: relative; }
/* Small inline links keep their look but get a 44px hit area: an invisible
   layer grown out to --tap in each direction the link is shorter than it. */
:is(.crumbs a, .footer__bottom a, .footer__phone, .link-arrow, .details dd a)::before {
  content: ""; position: absolute;
  inset: min(0px, (100% - var(--tap)) / 2);
}
@media (max-width: 1080px) { .footer__top { grid-template-columns: 1fr 1fr 1fr; } .footer__brand { grid-column: 1 / -1; } }
@media (max-width: 560px) { .footer__top { grid-template-columns: 1fr 1fr; } }

/* ================= Motion =================
   Start states are applied by motion.js adding .m-ready, so with JS off or
   motion reduced every element is simply visible. Only transform and opacity
   animate. Each entrance plays once. */
.m-ready[data-reveal] { opacity: 0; transform: translateY(var(--rise-reveal)); }
.m-ready[data-reveal="left"] { transform: translateX(calc(var(--rise-reveal) * -2)); }
.m-ready[data-reveal="right"] { transform: translateX(calc(var(--rise-reveal) * 2)); }
/* Once cards stack, a sideways start would push past the screen edge and let
   the page pan sideways; they rise instead. */
@media (max-width: 860px) {
  .m-ready[data-reveal="left"], .m-ready[data-reveal="right"] { transform: translateY(var(--rise-reveal)); }
}
.m-ready[data-reveal].is-in {
  opacity: 1; transform: none;
  transition: opacity var(--dur-reveal) var(--ease-enter), transform var(--dur-reveal) var(--ease-enter);
  transition-delay: calc(var(--i, 0) * var(--stagger));
}
/* Hero drop-in: content falls 30px into place after a short pause, once. */
.m-ready[data-hero-in] { opacity: 0; transform: translateY(calc(var(--drop-hero) * -1)); }
.m-ready[data-hero-in].is-in {
  opacity: 1; transform: none;
  transition: opacity var(--dur-hero) var(--ease-enter), transform var(--dur-hero) var(--ease-enter);
  transition-delay: calc(var(--delay-hero) + var(--i, 0) * var(--stagger));
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0.01ms !important; transition-delay: 0s !important; animation: none !important; scroll-behavior: auto !important; }
  .m-ready[data-reveal], .m-ready[data-hero-in] { opacity: 1; transform: none; }
  a.card:hover, .btn:hover, .icon-btn:hover { transform: none; }
  a.card:hover .card__media img { transform: none; }
}

/* Lenis */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }

/* ================= Placeholders =================
   Visible on purpose: the build must not hide what the client still owes.
   /ship fails while any of these remain. */
.ph {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-1) var(--space-3); border-radius: var(--r-pill);
  border: 1.5px dashed var(--red); background: var(--red-tint); color: var(--red);
  font-family: var(--font-body); font-size: var(--fs-eyebrow); font-weight: var(--weight-semi);
  letter-spacing: 0.04em; text-transform: none; line-height: 1.4;
  /* Wraps inside its box (long tokens break anywhere) so a placeholder never
     pushes a narrow card or a phone screen sideways. */
  max-width: 100%; overflow-wrap: anywhere;
}
.section--ink .ph, .section--red .ph, .hero .ph, .page-hero--photo .ph, .media-slot .ph, .card__media .ph, .gate .ph {
  border-color: var(--on-dark-line); background: var(--scrim-chip); color: var(--white);
  -webkit-backdrop-filter: blur(var(--blur-chip)); backdrop-filter: blur(var(--blur-chip));
}
/* Draft copy shows a dotted underline only when ?drafts is in the URL. */
.show-drafts [data-draft] { outline: 1.5px dotted var(--red); outline-offset: 4px; }

/* ================= Product list =================
   Category pages: a milk grid by pack size, then one card per group of the
   client's product list. /products/list/: the whole list in one table with
   a search box that product-search.js reveals. */
.matrix { overflow-x: auto; margin-bottom: var(--space-6); border: var(--border); border-radius: var(--r-md); background: var(--white); }
.matrix__table { width: 100%; border-collapse: collapse; font-size: var(--fs-small); }
.matrix__table th, .matrix__table td { padding: var(--space-3) var(--space-4); border-bottom: var(--border); text-align: center; white-space: nowrap; }
.matrix__table thead th { font-weight: var(--weight-semi); color: var(--muted); font-size: var(--fs-eyebrow); letter-spacing: var(--track-eyebrow); text-transform: uppercase; }
.matrix__table th[scope="row"], .matrix__table thead th:first-child { text-align: left; color: var(--ink); font-weight: var(--weight-semi); }
.matrix__table tbody tr:last-child > * { border-bottom: 0; }
/* On narrow screens the grid scrolls sideways; the product name stays put. */
.matrix__table th[scope="row"], .matrix__table thead th:first-child { position: sticky; left: 0; background: var(--white); }
.matrix__dot { display: inline-block; width: var(--space-3); height: var(--space-3); border-radius: 50%; background: var(--red); vertical-align: middle; }

/* Cards pack into columns, each sitting directly under the one above, so a
   short card never leaves a hole the height of its taller neighbour (Ian's
   gaps under Lactose Free and between Half & Half and Aerosols). Reading
   order runs down each column. */
.grid.plist-grid { display: block; column-count: var(--plist-cols); column-gap: var(--space-4); }
.plist-grid > .plist { break-inside: avoid; margin-bottom: var(--space-4); width: 100%; }
.plist-row { align-items: start; }
@media (max-width: 860px) { .grid.plist-grid { column-count: var(--plist-cols-md); } }
@media (max-width: 560px) { .grid.plist-grid { column-count: var(--plist-cols-sm); } }
.plist__items { list-style: none; margin: var(--space-2) 0 0; padding: 0; }
.plist__items li { display: grid; gap: var(--space-1); padding-block: var(--space-3); border-top: var(--border); }
.plist__items li:first-child { border-top: 0; }
.plist__name { color: var(--ink); font-weight: var(--weight-medium); }
/* Product names in capitals, as the client's list writes them. The data
   keeps its own case; badges stay as they are. */
.plist__name, .matrix__table th[scope="row"], .plist-table td:first-child { text-transform: uppercase; letter-spacing: var(--track-caps); }
.plist__name .plist__badge, .plist-table td:first-child .plist__badge { text-transform: none; letter-spacing: normal; }
.plist__size { font-size: var(--fs-small); color: var(--muted); }
.plist__badge {
  display: inline-block; margin-left: var(--space-2); padding: 0 var(--space-2); border-radius: var(--r-pill);
  background: var(--red-tint); color: var(--red); font-size: var(--fs-eyebrow); font-weight: var(--weight-semi); vertical-align: middle;
}

.plsearch { display: flex; flex-wrap: wrap; align-items: end; gap: var(--space-4); margin-bottom: var(--space-5); }
.plsearch__field { flex: 1 1 22rem; }
.plsearch__count { margin: 0; flex: 1 0 100%; order: 3; }
.plist-table { overflow-x: auto; border: var(--border); border-radius: var(--r-md); background: var(--white); }
.plist-table table { width: 100%; border-collapse: collapse; font-size: var(--fs-small); }
.plist-table th, .plist-table td { padding: var(--space-3) var(--space-4); border-bottom: var(--border); text-align: left; vertical-align: top; }
.plist-table thead th { position: sticky; top: 0; background: var(--paper); font-size: var(--fs-eyebrow); letter-spacing: var(--track-eyebrow); text-transform: uppercase; color: var(--muted); font-weight: var(--weight-semi); }
.plist-table td:first-child { color: var(--ink); font-weight: var(--weight-medium); }
.plist-table td a { color: var(--red); text-decoration: none; }
.plist-table td a:hover { text-decoration: underline; }
.plsearch__empty { padding: var(--space-5) var(--space-4); margin: 0; }

/* ================= Utilities ================= */
.mt-4 { margin-top: var(--space-4); }
.mt-6 { margin-top: var(--space-6); }
.hero .eyebrow { color: var(--on-dark-muted); }
.media-slot--fill { aspect-ratio: auto; height: 100%; }
.details dd { margin: 0; }
.details address { font-style: normal; }
.cta--form { grid-template-columns: 1.4fr 1fr; }
.cta__phone--ink { color: var(--ink); }
@media (max-width: 860px) { .cta--form { grid-template-columns: 1fr; } }
.media-slot__overlay .ph { text-align: center; max-width: 90%; }

/* ================= Intro gate (home only) =================
   A full-screen first screen: logo, "Texas dairy since 1970.", the master
   line, and one button. With JS it is a fixed overlay the visitor enters
   through (click, scroll, swipe or keyboard); it lifts away like a curtain
   to reveal the hero. With JS off it is simply the first screen of the page
   and the button is an anchor to the hero. gate.js owns the behaviour. */
.gate {
  position: relative; isolation: isolate; overflow: hidden;
  min-height: 100svh; display: grid; place-items: center;
  background: var(--ink); color: var(--white); text-align: center;
}
html.gate-on { overflow: hidden; }
.gate-on .gate {
  position: fixed; inset: 0; z-index: 60;
  transition: transform var(--dur-gate) var(--ease-gate);
}
.gate-leaving .gate { transform: translateY(-100%); }
.gate__media { position: absolute; inset: 0; z-index: -1; }
.gate__media picture, .gate__media img, .gate__media video { width: 100%; height: 100%; object-fit: cover; object-position: 62% 70%; }
.gate__media::after { content: ""; position: absolute; inset: 0; background: var(--scrim-gate); }
.gate__content { display: grid; justify-items: center; gap: var(--space-5); padding-block: var(--space-8); }
.gate__logo { width: var(--logo-gate); }
.gate__kicker {
  font-family: var(--font-display); font-weight: var(--weight-bold);
  font-size: var(--fs-gate-kicker); line-height: 1.1; color: var(--kicker-color);
}
.gate__title {
  font-family: var(--font-display); font-weight: var(--weight-bold); text-transform: uppercase;
  font-size: var(--fs-gate); line-height: var(--lh-display); letter-spacing: var(--track-display);
  color: var(--white); max-width: 14ch; text-wrap: balance;
}
.gate__title sup { font-size: 0.24em; vertical-align: top; position: relative; top: 0.4em; letter-spacing: 0; }
.gate__enter { min-height: 56px; padding-inline: var(--space-7); font-size: var(--fs-body); margin-top: var(--space-3); }
.gate__corner {
  position: absolute; top: var(--space-5); right: var(--gutter);
  display: none; align-items: center; gap: var(--space-5);
}
.gate-on .gate__corner { display: flex; }
.gate__link {
  display: inline-flex; align-items: center; gap: var(--space-2); min-height: var(--tap);
  font-size: var(--fs-small); font-weight: var(--weight-semi); color: var(--white); text-decoration: none;
}
.gate__link svg { width: 14px; height: 14px; }
.m-ready[data-gate-in] { opacity: 0; transform: translateY(var(--rise-reveal)); }
.m-ready[data-gate-in].is-in {
  opacity: 1; transform: none;
  transition: opacity var(--dur-reveal) var(--ease-enter), transform var(--dur-reveal) var(--ease-enter);
  transition-delay: calc(var(--delay-gate) + var(--i, 0) * var(--stagger-gate));
}
@media (max-width: 760px) {
  .gate__corner { left: var(--gutter); justify-content: space-between; }
}
/* Short screens (a phone on its side): the gate is locked, so the button
   must fit. Smaller logo, one-line title, tighter gaps. */
@media (max-height: 560px) {
  .gate__content { gap: var(--space-3); padding-block: var(--space-5); }
  .gate__logo { width: min(var(--logo-gate), 56svh); }
  .gate__title { font-size: min(var(--fs-gate), 13svh); max-width: none; }
  .gate__enter { margin-top: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .gate-leaving .gate { transform: none; }
  .m-ready[data-gate-in] { opacity: 1; transform: none; }
}
.hero__media--hq img { object-position: 40% 60%; }
/* Black Rock Coffee Bar photo: keep the cafe sign and the HCD logo in frame
   wherever it is cropped (page hero, tall home card). */
img[src*="8-black-rock-coffee"] { object-position: 55% 55%; }
/* Page-hero photos sit in a <picture> that doesn't fill the banner, so the
   banner shows the photo's top edge and object-position has no effect.
   Fixed here for the coffee hero only (Round 2 scope). The same fix would
   help every photo page hero; Ian to decide. */
.page-hero__media picture:has(> img[src*="8-black-rock-coffee"]) { display: block; height: 100%; }
.gate .ph {
  border-color: var(--on-dark-line); background: rgb(18 18 18 / 0.45); color: var(--white);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
/* The HQ photo is bright on the left where the copy sits: add a side scrim. */
.hero__media--hq::after { background: var(--scrim-side), var(--scrim); }
/* Focus is moved to the hero title after the gate for keyboard and screen
   reader users; it is not an interactive control, so no ring. */
[tabindex="-1"]:focus { outline: none; }

/* Photo focus: keep the subject in frame when a photo is cropped to a wide
   or tall slot. Set per photo by PHOTO_FOCUS in tools/build_site.py. */
.focus-upper img { object-position: 50% 30%; }
.focus-low img { object-position: 50% 90%; }
.focus-faces img { object-position: 50% 40%; }
.focus-mid img { object-position: 50% 55%; }
/* Every photo's <picture> fills its frame (cards, page-hero banners, video
   slots), so the photo crops to the frame and its focus point applies.
   Before this, page-hero banners showed each photo's top edge. */
.card__media > picture,
.page-hero__media > picture,
.media-slot > picture { display: block; width: 100%; height: 100%; }

/* ================= WordPress =================
   Everything the static site does not need: admin bar offsets, the form notice,
   and link chips on category archives. */
.admin-bar .site-header { top: var(--admin-bar-h); }
.admin-bar .mobile-nav { top: calc(var(--header-h) + var(--admin-bar-h)); }
.gate-on .admin-bar .gate { top: var(--admin-bar-gate); }
.form__notice { padding: var(--space-3) var(--space-4); border: 1px solid var(--red); color: var(--red); }
a.chip { display: inline-flex; align-items: center; text-decoration: none; }
.chip[aria-current="page"] { background: var(--ink); color: var(--white); border-color: var(--ink); }
.search-form { margin-bottom: var(--space-6); }

/* Cookie acknowledgment. Below the header and mobile menu, so Customer Login is
   never covered; a small card, so it never spans the page. */
.cookie-notice {
  position: fixed; right: var(--gutter); bottom: var(--space-4); left: var(--gutter); z-index: 40;
  display: flex; align-items: center; gap: var(--space-4);
  max-width: var(--measure); margin-left: auto; padding: var(--space-4);
  background: var(--white); border: 1px solid var(--line); border-radius: var(--r-md);
  box-shadow: var(--shadow-card);
}
.cookie-notice[hidden] { display: none; }
.cookie-notice p { flex: 1; }
.cookie-notice a { text-decoration: underline; }
.cookie-notice .btn { flex: none; }
@media (max-width: 480px) {
  .cookie-notice { flex-direction: column; align-items: stretch; }
}
