/* Wilson Valley Mercantile - site theme.
   Palette is IMPORTED from mail_render.py at build time and written into
   :root below, so the site and the newsletter cannot drift apart. Do not
   hand-edit the colour values here; change mail_render and rebuild.

   THE THEME, 16 September 2026: the same treatment the two brochure sites
   took the same night, on this site's own palette - [stated] John: "Then it
   just need to go to the .com site", then "I meant Wilson valley.com".
   Inter for body and interface, a serif for display headings, a sticky
   header with the seal as a badge beside the name, a full-bleed hero that
   still never crops the rainbow, pill buttons, a footer on paper. The
   section kickers, the show rows, the menu chat's markup, the age gate and
   the hidden override are as they were. Spec: "Evans Sites Rebuild". */
:root {
  --sans: Inter, system-ui, -apple-system, "Segoe UI", sans-serif;
  --display: "Source Serif 4", Georgia, "Iowan Old Style", serif;
  --shell: 1180px;
}
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 18px;
  line-height: 1.6;
}
img { max-width: 100%; height: auto; display: block; }

/* ---------- hidden means hidden ----------
   THE BUG THIS EXISTS TO KILL, reported by John on 8 Sept: "news is not 4
   aritcles still full list".

   The browser's own [hidden]{display:none} is the weakest rule there is, so
   ANY selector here that sets display beats it. Three things were quietly
   broken by that and only one of them had been noticed:

     ul.shows li            display:flex   -> a finished show never rolled
                                              off, and the home page showed
                                              all ten rows instead of five
     section.news article   display:grid   -> News showed all twelve
     .agegate               display:flex   -> THE AGE PANEL SHOWED EVERY
                                              TIME, even to a browser that
                                              had already answered

   Every one of those is a script setting el.hidden and a stylesheet
   ignoring it. One rule, once, rather than a display:none on each -- the
   next feature that hides something would hit this again otherwise. */
[hidden] { display: none !important; }
a { color: var(--red); }
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible {
  outline: 3px solid var(--red);
  outline-offset: 2px;
}
.wrap { max-width: 68ch; margin: 0 auto; padding: 0 20px; }
.wide { max-width: 90ch; }
.shell { max-width: var(--shell); margin: 0 auto; padding: 0 22px; }

/* ---------- buttons ---------- */
.btn {
  display: inline-block; font-family: var(--sans); font-size: 14px;
  font-weight: 600; letter-spacing: .02em; padding: 12px 22px;
  border-radius: 999px; text-decoration: none; line-height: 1.2;
  border: 1px solid transparent; white-space: nowrap;
}
.btn.solid { background: var(--red); color: #fff; }
.btn.solid:hover { background: var(--ink); }
.btn.ghost { border-color: var(--ink); color: var(--ink); }

/* ---------- header ----------
   Sticky, paper at 92% with a blur, one hairline under it. The seal is
   152 by 139 at heart and reads as a badge, so it sits beside the name;
   the lasso on the two brochure sites is a wordmark and stands alone.
   Ten frozen names do not fit beside the seal and the phone until about
   1600px, so under that the nav takes a row of its own, one line, centred;
   below 1100px it folds behind a Menu toggle - a checkbox and a label, no
   script. */
header.top {
  position: sticky; top: 0; z-index: 10;
  background: rgba(255, 255, 255, .92);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--rule);
}
.bar { display: flex; align-items: center; gap: 22px; min-height: 82px; }
.lockup {
  display: flex; align-items: center; gap: 12px; flex: 0 0 auto;
  margin-right: auto; text-decoration: none; color: var(--ink);
}
.lockup img { width: auto; height: 48px; display: block; }
.lockup .name {
  font-family: var(--display); font-size: 21px; font-weight: 600;
  letter-spacing: .02em; line-height: 1.1; display: flex; flex-direction: column;
}
.lockup .place {
  font-family: var(--sans); font-size: 10.5px; font-weight: 600;
  letter-spacing: .22em; text-transform: uppercase; color: var(--mute);
  margin-top: 4px;
}
nav.site ul {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 2px 18px;
}
nav.site a {
  display: block; padding: 6px 0;
  font-size: 12.5px; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; text-decoration: none; color: var(--ink);
  border-bottom: 2px solid transparent;
}
nav.site a:hover { color: var(--red); }
nav.site a[aria-current="page"] { color: var(--red); border-bottom-color: var(--red); }
.callpill { display: inline-flex; align-items: center; flex: 0 0 auto;
  background: var(--red); border-radius: 999px; }
.callpill .call { border-radius: 999px 0 0 999px; padding-right: 10px; }
.callpill:hover .call { background: var(--ink); }
.callpill:hover { background: var(--ink); }
.callnote { color: #fff; font-family: var(--sans); font-size: 11px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; padding: 0 16px 0 0; white-space: nowrap; }
.call { flex: 0 0 auto; }
.menu-toggle { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.menu-label {
  display: none; font-size: 13px; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; cursor: pointer; padding: 8px 0;
}
.menu-toggle:focus-visible + .menu-label { outline: 2px solid var(--red); outline-offset: 2px; }
@media (max-width: 1599px) {
  .bar { flex-wrap: wrap; gap: 8px 18px; padding-top: 12px; padding-bottom: 10px; }
  nav.site { flex-basis: 100%; order: 9; }
  nav.site ul { justify-content: center; gap: 2px 20px; }
}
@media (max-width: 1099px) {
  .bar { gap: 12px 18px; padding-bottom: 12px; }
  .menu-label { display: inline-block; }
  nav.site { display: none; padding: 8px 0 6px; border-top: 1px solid var(--rule); }
  nav.site ul { flex-direction: column; gap: 4px; justify-content: flex-start; }
  nav.site a { padding: 8px 0; }
  .menu-toggle:checked ~ nav.site { display: block; }
}
@media (max-width: 519px) {
  .lockup img { width: auto; height: 40px; }
  .lockup .name { font-size: 17px; }
  .lockup .place { display: none; }
  .call { font-size: 13px; padding: 10px 16px; }
  .callpill .call { padding-right: 8px; }
  .callnote { font-size: 10px; padding-right: 12px; }
}

/* ---------- hero ----------
   2:1 crop John chose: WHOLE FRAME, never cropped to a height. See build.py
   HERO_ALT. Full bleed now, so the height follows the width at 2:1 and
   nothing is cut; on a wide screen the title and line sit bottom-left over
   a scrim, on a phone the picture is too shallow for that and they sit
   under it as before. */
.hero { margin: 0; position: relative; background: var(--cream); }
.hero img {
  width: 100%; max-width: none; margin: 0; display: block;
  aspect-ratio: 2 / 1;
}
.hero-copy { text-align: center; padding: 30px 20px 6px; }
.hero-copy h1 {
  font-family: var(--display); font-size: clamp(30px, 4.6vw, 60px);
  line-height: 1.06; letter-spacing: -.015em; margin: 0 0 12px; text-wrap: balance;
}
.hero-copy p { font-size: 19px; color: var(--mute); margin: 0 auto; max-width: 46ch; }
@media (min-width: 760px) {
  .hero::after {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(to bottom, rgba(28, 20, 15, .04) 0%, rgba(28, 20, 15, .22) 55%, rgba(28, 20, 15, .72) 100%);
  }
  .hero-copy {
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
    text-align: left; padding-bottom: 48px; color: #fff;
  }
  .hero-copy h1 { color: #fff; max-width: 18ch; text-shadow: 0 1px 2px rgba(0, 0, 0, .35); }
  .hero-copy p { color: #fff; opacity: .95; margin: 0; max-width: 48ch; font-size: 21px; }
}

/* ---------- generic sections ---------- */
main { padding-bottom: 0; }
section { padding-top: 34px; }
.sec { padding: 40px 0 56px; }
.sec.paper { background: var(--paper); border-top: 1px solid var(--rule); }
.sec > .wrap > section:first-child, .sec > .wrap > .home-cols > section { padding-top: 0; }
/* h1.page: a page's first h2, promoted at build time, styled as it was. See build.py promote_h1. */
h2, h1.page {
  font-family: var(--sans); font-size: 12.5px; font-weight: 700; letter-spacing: .15em;
  text-transform: uppercase; color: var(--red);
  margin: 0 0 14px; padding-bottom: 7px; border-bottom: 1px solid var(--rule);
}
h3 { font-family: var(--display); font-size: 22px; font-weight: 600; line-height: 1.2; margin: 0 0 6px; }
p { margin: 0 0 15px; }
.lede { font-size: 20px; line-height: 1.45; }
/* The certification line on /spirits/: the seal is drawn small beside the
   sentence that carries its subject. Decorative, so the words do the work. */
.certline { display: flex; align-items: center; gap: 12px; margin: 0 0 18px; }
.certline img { width: 44px; height: 50px; flex: none; }
.sign { font-style: italic; color: var(--mute); }
/* The lasso mark under the About letter: a link to the ranch's site,
   drawn small so it reads as a signature rather than a second masthead. */
.ranchlink { margin: 22px 0 0; text-align: center; }
.ranchlink img { width: 240px; max-width: 60%; height: auto; display: block; margin: 0 auto; }

/* ---------- events ---------- */
.month {
  font-size: 12px; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: var(--mute);
  margin: 30px 0 8px; padding-bottom: 6px; border-bottom: 1px solid var(--rule);
}
ul.shows { list-style: none; margin: 0; padding: 0; }
ul.shows li {
  display: flex; gap: 16px; align-items: baseline;
  padding: 13px 0; border-bottom: 1px solid var(--rule);
}
ul.shows .when {
  flex: 0 0 4.2em; font-variant-numeric: tabular-nums;
  font-size: 13px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--red); line-height: 1.35;
}
ul.shows .who { flex: 1 1 auto; }
ul.shows .who .nm { font-size: 19px; }
ul.shows .who .tm { font-size: 14px; color: var(--mute); }

/* The steak RSVP fields, revealed when Steak RSVP is what they picked. */
.field.steak fieldset {
  border: 1px solid var(--rule); border-radius: 2px; padding: 14px 16px 16px;
  margin: 0;
}
.field.steak legend { font-size: 13px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--red);
  padding: 0 6px; }
.field.steak label { display: block; margin: 10px 0 4px; }
.field.steak label:first-of-type { margin-top: 0; }
.field.steak select, .field.steak input { width: 100%; }

.legal { font-size: 12px; color: var(--mute); margin: 14px 0 0; }

/* ---------- the age gate ----------
   A SELF-DECLARATION PANEL, not verification. See the note above AGE_MIN in
   build.py. The class lands on <html> from a script in the head, so the page
   behind it never paints. <noscript> hides the content and explains why, so
   it fails closed rather than quietly letting everyone through. */
.gated .gated-hide { display: none; }
/* The overlay is fixed and opaque, but the page behind it can still
   be scrolled with a wheel or a swipe. Stop that too. */
.gated body { overflow: hidden; }
.agegate-noscript { display: none; padding: 40px 20px; max-width: 40em;
  margin: 0 auto; }
.agegate {
  position: fixed; inset: 0; z-index: 1000; overflow-y: auto;
  background: var(--cream); display: flex; align-items: center;
  justify-content: center; padding: 24px;
}
.agegate-box { max-width: 26em; text-align: center; }
.agegate-box img { width: 78px; height: auto; margin: 0 auto 18px;
  display: block; }
.agegate-box h2 { margin: 0 0 8px; }
.agegate-box p { color: var(--mute); margin: 0 0 22px; }
.agegate-row { display: flex; gap: 12px; justify-content: center;
  flex-wrap: wrap; }
.agegate-row button {
  font: inherit; cursor: pointer; padding: 12px 22px; border-radius: 2px;
  border: 1px solid var(--red); background: var(--red); color: var(--cream);
}
.agegate-row button[data-age="no"] { background: transparent;
  color: var(--red); }
.agegate-row button:focus-visible { outline: 2px solid var(--ink);
  outline-offset: 2px; }
.agegate-sorry { margin-top: 4px; }

/* ---------- a photograph with the copy ----------
   JOHN, 8 Sept: "the site is boring it needs pictures with the copy".

   One optional photograph per page, from assets/pages/<slug>.jpg. Wide and
   shallow so it sits WITH the words rather than pushing them off the screen
   -- a full-bleed photo on a phone means scrolling past a picture to reach
   the copy, which is the opposite of the ask. */
.pagepic { margin: 0 0 20px; }
.pagepic img {
  display: block; width: 100%; height: auto; max-height: 340px;
  object-fit: cover; border-radius: 2px; background: var(--paper);
}
/* A portrait photograph is shown whole: same height cap, centred, paper
   either side. The centre band of a tall frame is a guess and it was wrong
   on the cigars. */
.pagepic img.tall { width: auto; max-width: 100%; margin: 0 auto; }
.menu .pagepic { margin: 18px 0 0; }
@media (max-width: 620px) {
  .pagepic img { max-height: 220px; }
}

/* The ranch mark at the top of the beef panel is a PNG with a WHITE
   background, and the page is cream -- so it sat in a visible white box.
   JOHN, 8 Sept: "Evans ranch logo on beef page. need to remove the
   background. it looks odd white on cream."

   multiply rather than a re-cut PNG: that image is base64 inside
   menu-source.html, which belongs to the menu chat and is never edited
   here. Multiply drops pure white to nothing against any backdrop, so the
   mark keeps working if the page colour ever changes and the fix survives
   the next menu handover. */
.menu img.ranchmark { mix-blend-mode: multiply; }

/* ---------- the flyer on the row, and the row to the Facebook event ------
   JOHN, 8 Sept: "can we have the flyers show up when you hover over the
   event?/click to open the event on fb?"

   Hover is here, but the thumbnail is on the row at ALL TIMES and only grows
   on hover. A phone has no hover and half the readers are on one, so nothing
   is reachable by hovering alone. :focus-within does the same for a keyboard.

   Both are optional: a night with no flyer has no thumbnail, a night with no
   Facebook event is not a link, and neither leaves a hole. */
ul.shows li { position: relative; }
ul.shows .who .ev { color: inherit; text-decoration: none; }
ul.shows .who .ev:hover .nm,
ul.shows .who .ev:focus .nm { color: var(--red); }
ul.shows .flyer { flex: 0 0 auto; align-self: center; line-height: 0; }
ul.shows .flyer a { display: block; line-height: 0; }
ul.shows .flyer img {
  width: 64px; height: 64px; object-fit: cover; border-radius: 2px;
  background: var(--paper); display: block;
}
/* The grown preview is taken OUT of the row rather than stretching it --
   a row that changes height on hover shoves the whole list about. */
ul.shows li:hover .flyer img,
ul.shows li:focus-within .flyer img {
  position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  width: min(340px, 62vw); height: auto; z-index: 20;
  box-shadow: 0 6px 28px rgba(0, 0, 0, .3);
}
@media (hover: none) {
  /* No hover to grow it with, so leave the thumbnail alone rather than
     letting a stray :hover state strand a preview over the list. */
  ul.shows li:hover .flyer img { position: static; transform: none;
    width: 64px; height: 64px; box-shadow: none; }
}
.empty { color: var(--mute); font-style: italic; }

/* ---------- notes / callouts ---------- */
.note {
  background: var(--paper); border-left: 3px solid var(--red);
  padding: 14px 18px; margin: 0 0 14px; font-size: 16px;
}
.note p:last-child { margin-bottom: 0; }

/* ---------- form ---------- */
form.rsvp { margin-top: 6px; }
.field { margin-bottom: 18px; }
.field label {
  display: block; font-size: 12px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--mute); margin-bottom: 6px;
}
.field input, .field select, .field textarea {
  width: 100%; padding: 11px 12px;
  font-family: var(--sans); font-size: 17px; color: var(--ink);
  background: var(--paper); border: 1px solid var(--rule); border-radius: 2px;
}
.field textarea { min-height: 170px; resize: vertical; }
.field .hint { font-size: 14px; color: var(--mute); margin: 6px 0 0; }
button.send {
  appearance: none; border: 0; border-radius: 999px; cursor: pointer;
  background: var(--red); color: #fff;
  font-family: var(--sans); font-size: 14px; font-weight: 600;
  letter-spacing: .04em; padding: 14px 30px;
}
button.send:hover { background: var(--ink); }
/* The honeypot. Hidden from people every way a person could be looking,
   still a real focusable field in the DOM for anything filling the form
   blind. Not display:none - some bots skip those. */
.hp {
  position: absolute; left: -9999px; width: 1px; height: 1px;
  overflow: hidden;
}

/* ---------- footer ----------
   On paper, in columns: the signup left, the address, phone, hours and the
   social row right, the affiliations and the legal line across the foot.
   The markup is unchanged; the grid places what was already there. */
footer.site {
  background: var(--paper); border-top: 1px solid var(--rule);
  margin-top: 0; padding: 56px 0 28px;
  text-align: left; font-size: 15.5px; color: var(--mute);
}
footer.site a { color: var(--red); }
footer.site .rows { margin-bottom: 10px; }
footer.site .rows p { margin: 0 0 6px; }
footer.site .social a { margin: 0 12px 0 0; }
.fgrid { display: grid; gap: 26px; }
@media (min-width: 760px) {
  .fgrid { grid-template-columns: 1.2fr 1fr; gap: 20px 48px; }
  .fgrid .signup { grid-column: 1; grid-row: 1 / 4; margin: 0; }
  .fgrid .rows, .fgrid .social, .fgrid .alllinks { grid-column: 2; margin: 0; }
  .fgrid .affil, .fgrid .legal { grid-column: 1 / -1; }
}
/* the linktree's way in from the site side - quieter than the social
   row above it, since a visitor here already has the nav. */
footer.site .alllinks { margin: 10px 0 0; font-size: 14px; }

/* ---------- affiliations ----------
   Two lines, kept apart on purpose. The first is a claim about the whiskey
   and carries its own subject; the second is a fact about the business. They
   are not badges and are deliberately not rendered as a row of logos, which
   would flatten an audited certification and a trade subscription into the
   same thing. */
.signup-names { display: flex; gap: 8px; margin: 8px auto 0; max-width: 34rem; }
.signup-names input { flex: 1 1 0; min-width: 0; font-family: var(--sans); font-size: 15px;
  padding: 9px 14px; background: var(--cream); border: 1px solid var(--rule); border-radius: 999px; }

footer.site .affil {
  margin: 18px 0 0; padding-top: 14px; max-width: 62ch;
  border-top: 1px solid var(--rule);
}
footer.site .affil p { margin: 0; }
footer.site .affil .cert {
  font-size: 13px; letter-spacing: .04em; color: var(--ink);
}
footer.site .affil .orgs {
  font-size: 12px; line-height: 1.7; color: var(--mute); padding-top: 4px;
}

@media (max-width: 480px) {
  body { font-size: 16px; }
  .hero-copy h1 { font-size: 27px; }
  ul.shows li { gap: 12px; }
  ul.shows .when { flex-basis: 3.9em; }
}
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ---------- newsletter signup (footer, every page) ---------- */
.signup { max-width: 52ch; margin: 0 0 24px; text-align: left; }
.signup label {
  display: block; font-size: 12px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--mute); margin-bottom: 8px;
}
.signup-row { display: flex; gap: 8px; }
.signup-row input {
  flex: 1 1 auto; min-width: 0; padding: 11px 14px;
  font-family: var(--sans); font-size: 16px; color: var(--ink);
  background: var(--cream); border: 1px solid var(--rule); border-radius: 999px;
}
.signup-row button {
  flex: 0 0 auto; appearance: none; border: 0; border-radius: 999px;
  cursor: pointer; background: var(--red); color: #fff;
  font-family: var(--sans); font-size: 14px; font-weight: 600;
  letter-spacing: .04em; padding: 0 20px;
}
.signup-row button:hover { background: var(--ink); }
.signup .problem { color: var(--red); font-size: 14px; margin: 8px 0 0; }

/* ---------- the linktree (/links/) ---------- */
/* Almost everyone who lands here arrives from a phone bio and is going to
   tap, not read. Rows the size of the show list, one per line, whole row
   underlined on hover -- not a bulleted list of small text. */
ul.links { list-style: none; margin: 0; padding: 0; }
ul.links li { border-bottom: 1px solid var(--rule); }
ul.links a {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px; padding: 15px 2px; font-size: 19px;
  text-decoration: none; color: var(--ink);
}
/* The rows are ink like the show list, so something has to say "tap me".
   A red chevron does it without eleven red lines down the page. */
ul.links a::after { content: "\203A"; color: var(--red); font-size: 22px; }
ul.links a:hover { color: var(--red); background: var(--paper); }

/* ---------- the home page's two columns ----------
   JOHN, 8 Sept: "make it a 1x2 solumn. coming up and News". One column on a
   phone, where two would give each about 20 characters a line. */
.home-cols { display: grid; gap: 34px; }
@media (min-width: 760px) {
  .home-cols { grid-template-columns: 1fr 1fr; gap: 40px; }
}

/* ---------- the news block (home) ---------- */
/* Same weight as a section body, not a page of headlines. The heading is
   the post's own title, so it stays smaller than a section rule. */
section.news article { padding: 0 0 18px; }
section.news article:last-child { padding-bottom: 0; }
section.news article h3 { font-size: 19px; font-weight: 400; margin: 0 0 4px; }
section.news article p { margin: 0; color: var(--mute); }

/* The photograph. News had none until 8 Sept -- news_items looked one up and
   then dropped it. A picture is the point of the block, so it leads the row
   rather than sitting under the words. */
section.news article { position: relative; }
section.news article img {
  display: block; width: 100%; height: auto; margin: 0 0 10px;
  border-radius: 2px; background: var(--paper);
  transition: transform .18s ease, box-shadow .18s ease;
}
/* Side by side only once there is REAL room. News shares the home page with
   Coming up now, so at 620px it is in a half-width column and a 180px
   picture beside a paragraph leaves neither of them readable. */
@media (min-width: 1000px) {
  section.news article:has(img) {
    display: grid; grid-template-columns: 150px 1fr;
    column-gap: 16px; align-items: start;
  }
  section.news article img { grid-row: 1 / span 2; margin: 0; }
}
/* JOHN, 8 Sept: "the images in news should enlarge when hovered."
   transform rather than width, so nothing under it moves -- a picture that
   reflows the column on hover makes the text jump as the pointer crosses
   it. Grows down and to the right from its own top-left corner, over the
   words it belongs to. */
@media (hover: hover) {
  section.news article:hover img,
  section.news article:focus-within img {
    transform: scale(2.1); transform-origin: left top; z-index: 30;
    position: relative; box-shadow: 0 6px 28px rgba(0, 0, 0, .32);
  }
}

/* the age panel's two buttons take the pill like every other button; the
   panel itself is as written above and the suite reads that block. */
.agegate-row button { border-radius: 999px; padding: 12px 24px; font-family: var(--sans); font-weight: 600; }
.agegate-box h2 { font-family: var(--display); font-size: 26px; letter-spacing: 0; text-transform: none; border: 0; padding: 0; color: var(--ink); }
ul.shows .who .nm, ul.links a { font-family: var(--display); }
section.news article h3 { font-family: var(--display); }
