/* Display serif for headings - added 2026-09-16 (Tier 1 "wow" pass).
   @import so no template had to change for the demo. If this stays, move it
   to a <link rel="preconnect"> + <link> in the four templates, which starts
   the font download earlier than @import can. display=swap so text never
   waits on the font. Body copy stays on the system sans - Cormorant is too
   thin below ~18px. */
@import url("https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@500;600&display=swap");

/* St. Augustine Wedding Guide - generated pages (vendor listings + category indexes).
 *
 * This IS the approved design from design/mockup.css (2026-09-07): cream + sand
 * ground, navy ink, terracotta accent. Adopted 2026-09-10.
 *
 * WHY THIS FILE EXISTS: tools/listing_template.html was originally wired to
 * /assets/site.css - the coming-soon page's provisional teal palette - so the
 * first generated listing came out in the wrong colors entirely. The mockups in
 * design/ are the design of record; site.css is still what index.html (the
 * coming-soon page) uses, and the two do NOT match. Unifying them is Corey's
 * call and is not done here.
 *
 * Keep this in sync with design/mockup.css. Mockup-only rules (the placeholder
 * banner, the bracketed field-placeholder style) are dropped - nothing on a real
 * page should ever render a bracketed placeholder.
 */

/* Design mockup stylesheet - St. Augustine Wedding Guide
   Placeholder/testing only, not the production stylesheet. */

:root {
  --cream:        #FAF6ED;
  --sand:         #EDE1C9;
  --sand-line:    #DDCBA6;
  --navy:         #16303F;
  --navy-soft:    #2C4A5C;
  --terracotta:   #A85236;
  --terracotta-lt:#D98B65;
  --charcoal:     #322E28;
  --charcoal-soft:#5B564C;
  --white:        #FFFFFF;
  --radius:       6px;
  --serif: "Cormorant Garamond", Georgia, "Iowan Old Style", "Palatino Linotype", serif;
  --sans: -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--cream);
  color: var(--charcoal);
  font-family: var(--sans);
  line-height: 1.55;
}

.wrap {
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 24px;
}



.brand {
  font-family: var(--serif);
  font-size: 22px;
  color: var(--navy);
  text-decoration: none;
  font-weight: 700;
}

.brand span { color: var(--terracotta); }

nav.breadcrumb {
  font-size: 13px;
  color: var(--charcoal-soft);
  margin: 18px 0 0;
}

nav.breadcrumb a {
  color: var(--navy-soft);
  /* Underlined, not colour-only. Lighthouse 2026-09-18 flagged "links rely on
     colour to be distinguishable": navy-soft beside charcoal-soft text is not
     enough of a difference on its own. */
  text-decoration: underline;
  text-decoration-color: var(--sand-line);
  text-underline-offset: 3px;
}

nav.breadcrumb a:hover { text-decoration: underline; }

/* Page head */
.page-head {
  padding: 28px 0 20px;
}

h1 {
  font-family: var(--serif);
  color: var(--navy);
  font-size: 34px;
  margin: 0 0 8px;
}

.result-count {
  color: var(--charcoal-soft);
  font-size: 15px;
  margin: 0 0 10px;
}

.ranking-disclosure {
  display: inline-block;
  background: var(--sand);
  border: 1px solid var(--sand-line);
  color: var(--navy);
  font-size: 13.5px;
  padding: 8px 14px;
  border-radius: var(--radius);
}

/* Filter row */
.filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  padding: 18px 0;
  border-bottom: 1px solid var(--sand-line);
  margin-bottom: 24px;
}

.filter-pill {
  background: var(--white);
  border: 1px solid var(--sand-line);
  color: var(--navy);
  font-size: 13.5px;
  padding: 8px 14px;
  border-radius: 999px;
  cursor: pointer;
}

.filter-pill:hover { border-color: var(--terracotta-lt); }

/* Vendor cards */
.card-grid {
  display: grid;
  /* min(300px, 100%) not a bare 300px. A bare 300px minimum track does not
     shrink below 300px, so on a 320px phone - where .wrap leaves 272px - the
     grid was 28px wider than the page and scrolled it sideways. Inherited
     from design/mockup.css, which has no media queries at all. Found and
     fixed 2026-09-15 while fixing the centring; nobody had looked at a 320px
     screen, only 390px. */
  grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
  gap: 22px;
  margin-bottom: 40px;
}

.vendor-card {
  background: var(--white);
  border: 1px solid var(--sand-line);
  border-radius: var(--radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.vendor-photo {
  aspect-ratio: 3 / 2;
  background: linear-gradient(135deg, var(--sand) 0%, var(--sand-line) 100%);
  /* .vendor-card is a column flexbox, so this cell is a flex item and gets
     min-height:auto - its content's intrinsic height, which silently beats
     the 3/2 above. A 640x800 portrait lead photo rendered 563px tall in a
     450px-wide card instead of 300px. overflow:hidden makes the automatic
     minimum size 0 and hands the aspect-ratio back. Same reason
     .gallery-photo carries it. Found 2026-09-12. */
  overflow: hidden;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--charcoal-soft);
  font-size: 12.5px;
  letter-spacing: 0.03em;
}

.vendor-body { padding: 16px 18px 18px; }

.vendor-name {
  font-family: var(--serif);
  font-size: 19px;
  color: var(--navy);
  margin: 0 0 4px;
}

.vendor-meta {
  font-size: 13.5px;
  color: var(--charcoal-soft);
  margin: 0 0 8px;
}

.vendor-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 10px;
}

.badge {
  font-size: 11.5px;
  padding: 3px 9px;
  border-radius: 999px;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.badge.preferred { background: #E7EEE9; color: #2E5B41; }
.badge.verified  { background: #EAF1F5; color: var(--navy-soft); }
.badge.response  { background: var(--sand); color: #8C4229; }
/* Rule #14 fix 2026-09-10: --terracotta #A85236 on --sand #EDE1C9 is 4.13:1,
   which fails 4.5:1 for badge-sized text. #8C4229 is 5.54:1 on the same ground.
   Carried over from design/mockup.css - fix it there too if the mockup is reused. */

.vendor-cta {
  display: inline-block;
  margin-top: 6px;
  background: var(--navy);
  color: var(--cream);
  font-size: 13.5px;
  font-weight: 600;
  padding: 9px 16px;
  border-radius: var(--radius);
  text-decoration: none;
  border: none;
  cursor: pointer;
}

.vendor-cta:hover { background: var(--navy-soft); }

.last-verified {
  font-size: 12px;
  color: var(--charcoal-soft);
  margin-top: 8px;
}

/* Editorial section */
.editorial {
  background: var(--white);
  border: 1px solid var(--sand-line);
  border-radius: var(--radius);
  padding: 28px 32px;
  margin-bottom: 40px;
}

.editorial h2 {
  font-family: var(--serif);
  color: var(--navy);
  font-size: 24px;
  margin-top: 0;
}

.editorial p { color: var(--charcoal); }

.field-placeholder {
  display: block;
  background: repeating-linear-gradient(
    135deg, var(--sand) 0px, var(--sand) 10px, var(--cream) 10px, var(--cream) 20px
  );
  border: 1px dashed var(--sand-line);
  border-radius: var(--radius);
  padding: 14px 16px;
  color: var(--charcoal-soft);
  font-size: 13.5px;
  font-style: italic;
}

/* FAQ */
.faq { margin-bottom: 40px; }

.faq h2 {
  font-family: var(--serif);
  color: var(--navy);
  font-size: 24px;
}

.faq-item {
  border-bottom: 1px solid var(--sand-line);
  padding: 14px 0;
}

.faq-item h3 {
  font-size: 16px;
  color: var(--navy);
  margin: 0 0 6px;
}

.faq-item p {
  margin: 0;
  color: var(--charcoal-soft);
  font-size: 14.5px;
}

/* Footer links */
footer.site-footer {
  border-top: 1px solid var(--sand-line);
  padding: 28px 0 50px;
}

footer.site-footer h4 {
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--charcoal-soft);
  margin-bottom: 10px;
}

.link-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  padding: 0;
  margin: 0 0 24px;
  list-style: none;
}

.link-list a {
  color: var(--navy-soft);
  text-decoration: none;
  font-size: 14px;
}

.link-list a:hover { text-decoration: underline; }

/* Vendor profile page specifics */
.profile-hero {
  padding: 30px 0 10px;
}

.profile-name {
  font-family: var(--serif);
  color: var(--navy);
  font-size: 36px;
  margin: 0 0 6px;
}

.profile-tagline {
  color: var(--charcoal-soft);
  font-size: 15px;
  margin: 0 0 16px;
}

/* ---- Profile gallery -------------------------------------------------
   Mobile first, rewritten 2026-09-11. This was a fixed 4-column grid and
   guide.css had NO media queries at all, so on a phone six photos rendered
   as thumbnail-sized cells - on the page type most couples open on a phone.
   Phones now get a swipe strip (scroll-snap, the next photo peeking at the
   edge to signal it scrolls); 700px and up gets a 3-up grid. Both open the
   lightbox in assets/gallery.js. */
.profile-gallery {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 76%;
  gap: 10px;
  margin: 20px 0 8px;
  padding-bottom: 6px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.profile-gallery::-webkit-scrollbar { display: none; }

.gallery-photo {
  margin: 0;
  scroll-snap-align: start;
  aspect-ratio: 4 / 5;
  background: linear-gradient(135deg, var(--sand) 0%, var(--sand-line) 100%);
  border-radius: var(--radius);
  overflow: hidden;
  /* kept so an empty .gallery-photo still reads as a placeholder cell,
     the way design/vendor-profile.html uses it */
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--charcoal-soft);
  font-size: 12px;
  letter-spacing: 0.02em;
}

.gallery-photo a {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: var(--radius);
  cursor: zoom-in;
}

.gallery-photo a:focus-visible {
  outline: 3px solid var(--navy);
  outline-offset: 2px;
}

/* Phones only - the grid below makes it self-evident on a wider screen. */
.gallery-hint {
  font-size: 12px;
  color: var(--charcoal-soft);
  margin: 0 0 4px;
}

@media (min-width: 700px) {
  .profile-gallery {
    grid-auto-flow: row;
    grid-template-columns: repeat(3, 1fr);
    grid-auto-columns: auto;
    overflow-x: visible;
    scroll-snap-type: none;
    padding-bottom: 0;
  }

  .gallery-photo { aspect-ratio: 3 / 2; }
  .gallery-hint { display: none; }
}

/* ---------------------------------------------------------------------------
   Video - one embedded film above the gallery. Added 2026-09-16.
   The poster is a plain <a> to the watch page; assets/video.js swaps in the
   iframe on click. aspect-ratio on both the facade and the player is what
   stops the page jumping when that swap happens.
   --------------------------------------------------------------------------- */
.profile-video {
  margin: 20px 0 8px;
}

.video-facade {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--navy);
}

.video-facade img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.video-facade:focus-visible {
  outline: 3px solid var(--navy);
  outline-offset: 2px;
}

/* Play control: an opaque navy disc with a CSS border triangle, so contrast
   does not depend on whatever the poster frame happens to be, and no glyph
   character is needed (Rule #15). 64px, comfortably over the 44px tap minimum. */
.video-play {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 64px;
  height: 64px;
  margin: -32px 0 0 -32px;
  border-radius: 50%;
  background: var(--navy);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.35);
  transition: transform 120ms ease, background 120ms ease;
}

.video-play::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 0;
  height: 0;
  margin: -11px 0 0 -7px;
  border-style: solid;
  border-width: 11px 0 11px 20px;
  border-color: transparent transparent transparent var(--cream);
}

.video-facade:hover .video-play,
.video-facade:focus-visible .video-play {
  background: var(--navy-soft);
  transform: scale(1.06);
}

/* The iframe video.js swaps in, taking the facade's place exactly. */
.video-player {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 0;
  border-radius: var(--radius);
  background: var(--navy);
}

.video-caption {
  font-size: 13px;
  color: var(--charcoal-soft);
  margin: 8px 0 0;
}

.nap-block {
  background: var(--white);
  border: 1px solid var(--sand-line);
  border-radius: var(--radius);
  padding: 18px 22px;
  margin: 18px 0 32px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 14px;
}

.nap-block dt {
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--charcoal-soft);
  margin-bottom: 3px;
}

.nap-block dd {
  margin: 0;
  font-size: 14.5px;
  color: var(--navy);
  font-weight: 600;
}

.section-block {
  margin-bottom: 36px;
}

.section-block h2 {
  font-family: var(--serif);
  color: var(--navy);
  font-size: 22px;
  border-bottom: 2px solid var(--sand-line);
  padding-bottom: 8px;
  margin-bottom: 16px;
}

.credential-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.credential-list li {
  padding: 8px 0;
  border-bottom: 1px solid var(--sand-line);
  font-size: 14.5px;
  color: var(--charcoal);
}

.credential-list li:last-child { border-bottom: none; }

.review-card {
  background: var(--white);
  border: 1px solid var(--sand-line);
  border-radius: var(--radius);
  padding: 16px 20px;
  margin-bottom: 12px;
}

.review-stars { color: var(--terracotta); font-size: 14px; margin-bottom: 6px; }

.sameas-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.sameas-list a {
  font-size: 13px;
  color: var(--navy-soft);
  background: var(--sand);
  padding: 6px 12px;
  border-radius: 999px;
  text-decoration: none;
}

code.schema-note {
  background: var(--navy);
  color: var(--cream);
  font-size: 11.5px;
  padding: 2px 7px;
  border-radius: 3px;
  margin-left: 8px;
  font-family: monospace;
}

/* ---------------------------------------------------------------------------
   Additions beyond design/mockup.css, 2026-09-10.
   The mockup drew photo cells as empty placeholder blocks; real pages need
   rules for actual <img> content, plus a draft marker for listings that are
   built but not yet approved for publication.
   --------------------------------------------------------------------------- */

.gallery-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--radius);
  display: block;
}

.gallery-credit {
  font-size: 12px;
  color: var(--charcoal-soft);
  margin: 0 0 24px;
}

/* Draft marker. Deliberately loud - a page carrying this must never be live. */
.badge.draft {
  background: #F6ECD2;
  color: #6B4A00;
  border: 1px solid #E0CFA4;
}

.category-empty {
  color: var(--charcoal-soft);
  font-style: italic;
  padding: 24px 0 40px;
}

/* Brand mark - added with the logo, 2026-09-11.
   Deliberately inline-block and not flex: .brand contains a bare text node plus a
   <span>, and flex would turn those into two separate items with a gap between
   them, and would also break the ".brand span" terracotta rule below. */
.brand-mark {
  width: 28px;
  height: 28px;
  vertical-align: -6px;
  margin-right: 9px;
}

/* ---- Photo lightbox --------------------------------------------------
   Markup is built by assets/gallery.js, which uses a native <dialog> -
   that gives Esc-to-close and a real focus trap without hand-rolling one.
   Rule #15: the glyphs are CSS escapes, never literal unicode in HTML. */
dialog.lightbox {
  width: 100%;
  height: 100%;
  max-width: 100vw;
  max-height: 100vh;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  overflow: hidden;
}

dialog.lightbox::backdrop {
  background: rgba(22, 20, 17, 0.97);
}

/* The dark field is painted here, not left to ::backdrop alone. The
   dialog fills the viewport, so this covers the same area - and it renders
   in browsers that treat ::backdrop inconsistently (older Safari), where a
   see-through overlay would leave the page text legible behind the photo. */
.lightbox-inner {
  position: relative;
  background: rgba(22, 20, 17, 0.97);
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 16px;
}

.lightbox-figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  max-width: 100%;
  max-height: 100%;
}

/* The source files are 800px on the long edge - capping here stops the
   browser upscaling them into a soft, obviously-stretched photo. */
.lightbox-img {
  max-width: min(100%, 800px);
  max-height: 82vh;
  width: auto;
  height: auto;
  display: block;
  border-radius: var(--radius);
  background: var(--charcoal);
}

.lightbox-caption {
  color: rgba(255, 255, 255, 0.88);
  font-family: var(--sans);
  font-size: 13px;
  letter-spacing: 0.03em;
  margin: 0;
  text-align: center;
}

.lightbox-close,
.lightbox-nav {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.28);
  background: rgba(0, 0, 0, 0.45);
  color: var(--white);
  font-family: var(--sans);
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

.lightbox-close:hover,
.lightbox-nav:hover {
  background: rgba(0, 0, 0, 0.75);
  border-color: rgba(255, 255, 255, 0.55);
}

.lightbox-close:focus-visible,
.lightbox-nav:focus-visible {
  outline: 3px solid var(--white);
  outline-offset: 2px;
}

.lightbox-close {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 2;
}

.lightbox-close::before {
  content: '\00D7';
  font-size: 26px;
}

.lightbox-prev::before { content: '\2039'; font-size: 30px; }
.lightbox-next::before { content: '\203A'; font-size: 30px; }

/* Phones: the arrows sit over the photo's lower corners so the image gets
   the full width, and swipe is the primary gesture anyway. */
@media (max-width: 699px) {
  .lightbox-inner { padding: 8px; }

  .lightbox-nav {
    position: absolute;
    bottom: 22px;
    z-index: 2;
  }

  .lightbox-prev { left: 18px; }
  .lightbox-next { right: 18px; }
}

/* ===========================================================================
   Homepage, 2026-09-11. Generated by tools/build_home.py.

   Mobile first, per project rule 7 - this file had zero media queries for its
   whole life until the gallery fix earlier today, and the homepage is the page
   every vendor Corey pitches will open, most of them on a phone.

   Contrast checked against Rule #14 before shipping. The one trap in this
   palette: terracotta #A85236 on sand #EDE1C9 is 4.13:1 and FAILS, which is
   why the terracotta status line sits on cream and nothing inside the sand
   vendor band is terracotta. Navy on sand is 10.61:1, charcoal-soft on sand
   is 5.63:1 - both fine.
   =========================================================================== */

/* Missing since guide.css was split off mockup.css on 2026-09-10: the header
   rule itself never came across, so every generated listing and category page
   has been rendering its header with no bottom rule and no padding - the brand
   sitting flush against the top of the viewport. Restored from
   design/mockup.css, which is the design of record. */
header.site-header {
  border-bottom: 1px solid var(--sand-line);
  padding: 20px 0;
}

/* Also missing: the vendor name on a category card is a link, and nothing ever
   styled it, so every card title has been rendering as a default blue
   underlined browser link instead of navy serif. */
.vendor-name a {
  color: inherit;
  text-decoration: none;
}

.vendor-name a:hover { text-decoration: underline; }

.vendor-name a:focus-visible {
  outline: 3px solid var(--navy);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Real photos in a category/homepage card cell. The mockup only ever drew an
   empty placeholder block here. */
.vendor-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ---- Hero ---------------------------------------------------------------- */
.home-hero {
  padding: 40px 0 34px;
  max-width: 34em;
}

.home-eyebrow {
  font-size: 12px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--charcoal-soft);
  margin: 0 0 18px;
}

.home-hero h1 {
  font-size: clamp(30px, 7vw, 46px);
  line-height: 1.12;
  letter-spacing: -0.015em;
  font-weight: 400;
  margin: 0 0 18px;
}

.home-lede {
  font-size: 17px;
  color: var(--charcoal-soft);
  margin: 0 0 22px;
}

.home-status {
  font-family: var(--serif);
  font-style: italic;
  font-size: 17px;
  color: var(--terracotta);
  margin: 0;
}

/* ---- Shared section furniture -------------------------------------------- */
.home-section {
  border-top: 1px solid var(--sand-line);
  padding-top: 30px;
  margin-bottom: 44px;
}

.home-section > h2 {
  font-family: var(--serif);
  font-weight: 400;
  color: var(--navy);
  font-size: 25px;
  margin: 0 0 6px;
}

.section-lead {
  color: var(--charcoal-soft);
  font-size: 15px;
  margin: 0 0 22px;
  max-width: 34em;
}

/* ---- Category grid ------------------------------------------------------- */
.category-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
}

.category-tile {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  background: var(--white);
  border: 1px solid var(--sand-line);
  border-radius: var(--radius);
  padding: 15px 17px;
  text-decoration: none;
  transition: border-color 0.12s ease, transform 0.12s ease;
}

.category-tile:hover {
  border-color: var(--terracotta-lt);
  transform: translateY(-1px);
}

.category-tile:focus-visible {
  outline: 3px solid var(--navy);
  outline-offset: 2px;
}

.tile-name {
  font-family: var(--serif);
  font-size: 17px;
  color: var(--navy);
}

.tile-count {
  font-size: 12.5px;
  color: var(--charcoal-soft);
  white-space: nowrap;
}

/* ---- How this guide works ------------------------------------------------ */
.how-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
}

.how-item { border-top: 2px solid var(--sand-line); padding-top: 14px; }

.how-item h3 {
  font-family: var(--serif);
  font-weight: 400;
  color: var(--navy);
  font-size: 18px;
  margin: 0 0 6px;
}

.how-item p {
  margin: 0;
  font-size: 14.5px;
  color: var(--charcoal-soft);
}

/* ---- Vendor band --------------------------------------------------------- */
.vendor-band {
  background: var(--sand);
  border: 1px solid var(--sand-line);
  border-radius: var(--radius);
  padding: 28px 24px 30px;
  margin-bottom: 50px;
}

.vendor-band h2 {
  font-family: var(--serif);
  font-weight: 400;
  color: var(--navy);
  font-size: 24px;
  margin: 0 0 10px;
}

.vendor-band p {
  margin: 0 0 12px;
  color: var(--charcoal);
  font-size: 15px;
  max-width: 36em;
}

.band-note {
  font-size: 13.5px;
  /* charcoal-soft on sand is 5.63:1. Terracotta here would be 4.13:1 and fail. */
  color: var(--charcoal-soft) !important;
}

.band-cta {
  display: inline-block;
  margin-top: 6px;
  background: var(--navy);
  color: var(--cream);
  font-size: 15px;
  font-weight: 600;
  padding: 12px 22px;
  border-radius: var(--radius);
  text-decoration: none;
}

.band-cta:hover { background: var(--navy-soft); }

.band-cta:focus-visible {
  outline: 3px solid var(--navy);
  outline-offset: 3px;
}

/* ---- Wider screens ------------------------------------------------------- */
@media (min-width: 560px) {
  .category-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 820px) {
  .home-hero { padding: 60px 0 44px; }
  .category-grid { grid-template-columns: repeat(3, 1fr); gap: 12px; }
  .how-grid { grid-template-columns: repeat(3, 1fr); gap: 30px; }
  .vendor-band { padding: 36px 38px 40px; }
}

/* ---- Price callout in the homepage vendor band --------------------------- */
/* Navy on sand is 10.61:1. Terracotta here would be 4.13:1 and fail Rule #14. */
.band-price {
  font-family: var(--serif);
  font-size: 26px;
  color: var(--navy) !important;
  margin: 0 0 16px !important;
}

/* ===========================================================================
   /get-listed/ - the public vendor inquiry page, 2026-09-11.

   Built on guide.css rather than site.css so a vendor clicking through from
   the homepage lands on something that looks like the same site. site.css is
   a centred single-screen layout with no site header; this page needs the
   header and the wide ground.

   Form rules are scoped under .guide-form on purpose. guide.css is loaded by
   every listing and category page, and a bare `input`/`button` selector here
   would be a global style waiting to surprise somebody.
   =========================================================================== */
.lead-copy {
  font-size: 17px;
  color: var(--charcoal);
  max-width: 34em;
  margin: 0 0 22px;
}

.price-callout {
  background: var(--sand);
  border: 1px solid var(--sand-line);
  border-radius: var(--radius);
  padding: 20px 24px;
  margin: 0 0 34px;
  max-width: 34em;
}

.price-callout .amount {
  display: block;
  font-family: var(--serif);
  font-size: 32px;
  color: var(--navy);
  line-height: 1.1;
  margin-bottom: 6px;
}

.price-callout .terms {
  display: block;
  font-size: 14px;
  color: var(--charcoal-soft);
}

/* Numbered steps. The number is drawn by CSS so the markup stays a plain
   ordered list and a screen reader still hears "1, 2, 3". */
.step-list {
  list-style: none;
  counter-reset: step;
  padding: 0;
  margin: 0 0 40px;
  max-width: 34em;
}

.step-list li {
  counter-increment: step;
  position: relative;
  padding: 0 0 18px 46px;
  font-size: 15px;
  color: var(--charcoal);
}

.step-list li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: -2px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--navy);
  color: var(--cream);
  font-family: var(--serif);
  font-size: 15px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.step-list strong { color: var(--navy); }

/* ---- Scoped form -------------------------------------------------------- */
.guide-form {
  background: var(--white);
  border: 1px solid var(--sand-line);
  border-radius: var(--radius);
  padding: 26px 24px 28px;
  max-width: 34em;
  margin: 0 0 50px;
}

.guide-form h2 {
  font-family: var(--serif);
  font-weight: 400;
  color: var(--navy);
  font-size: 21px;
  margin: 0 0 6px;
}

.guide-form .form-note {
  font-size: 14px;
  color: var(--charcoal-soft);
  margin: 0 0 20px;
}

.guide-form label {
  display: block;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--charcoal-soft);
  margin-bottom: 6px;
}

.guide-form input[type="text"],
.guide-form input[type="email"],
.guide-form select {
  width: 100%;
  padding: 11px 12px;
  margin-bottom: 18px;
  font: inherit;
  font-size: 15px;
  color: var(--charcoal);
  background: var(--white);
  border: 1px solid var(--sand-line);
  border-radius: var(--radius);
}

.guide-form input:focus-visible,
.guide-form select:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 1px;
  border-color: var(--navy);
}

.guide-form button {
  width: 100%;
  padding: 14px 16px;
  font: inherit;
  font-size: 13px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--cream);
  background: var(--navy);
  border: 1px solid var(--navy);
  border-radius: var(--radius);
  cursor: pointer;
}

.guide-form button:hover { background: var(--navy-soft); border-color: var(--navy-soft); }

.guide-form button:focus-visible {
  outline: 3px solid var(--navy);
  outline-offset: 3px;
}

/* Netlify honeypot - off-screen rather than display:none, which some bots
   detect and some screen readers skip entirely. */
.guide-form .hp { position: absolute; left: -9999px; }

@media (min-width: 820px) {
  .guide-form { padding: 30px 32px 34px; }
}

/* ===========================================================================
   Centring fix, 2026-09-15. Corey: "it doesn't seem to be centered, it seems
   to be all kind of tilted to the left."

   He was right, and .wrap was not the problem - that is 1080px with margin
   auto and centres correctly. The tilt came from what I put INSIDE it:

     .wrap content column ....... 1032px, centred
     .home-hero, .section-lead .. 544px (34em), LEFT aligned inside it
                                  = 488px of dead space beside the largest
                                    type on the page

     .card-grid ................. repeat(auto-fill, minmax(300px, 1fr))
                                  = 3 tracks of 344px at that width, and
                                    auto-fill KEEPS the empty ones, so the
                                    single McKarls card sat in track 1 with
                                    688px of nothing to its right

   The 34em cap itself is right - a 1032px line of body text is unreadable.
   The mistake was capping the width and then not re-centring what was left.

   Scoped to `main.wrap.home` so the category and listing pages, which are
   left-aligned by the design of record (design/category-page.html), are not
   dragged into this.
   =========================================================================== */

.home .home-hero {
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}

.home .home-section > h2,
.home .section-lead {
  text-align: center;
}

.home .section-lead {
  margin-left: auto;
  margin-right: auto;
}

/* auto-FIT, not auto-fill: auto-fit collapses the empty tracks to zero width,
   and the capped 360px max stops a lone card stretching to a 1032px slab.
   justify-content then centres whatever tracks survive - so one card sits in
   the middle, two sit as a centred pair, three fill the row. */
.home .card-grid {
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 360px));
  justify-content: center;
}

/* The CTA band is a call to action, not reading copy - centre it. */
.home .vendor-band { text-align: center; }

.home .vendor-band p {
  margin-left: auto;
  margin-right: auto;
}

/* ---- /get-listed/ -------------------------------------------------------
   Same disease, different cure. This page is one column of reading copy and
   a form, with no wide grid that needs the full 1080px - so the whole column
   narrows and centres, and the text stays LEFT aligned inside it. Centred
   body copy and centred form labels are harder to read, and this is the page
   that has to convert a vendor. */
.wrap-narrow { max-width: 780px; }

.wrap-narrow .price-callout,
.wrap-narrow .step-list,
.wrap-narrow .guide-form,
.wrap-narrow .lead-copy,
.wrap-narrow .section-lead { max-width: none; }

/* ===========================================================================
   CATEGORY PAGES - "bolder" pass, 2026-09-18. Corey: the pages look "made in
   the 80s." They did, because the category page quietly opted out of every
   strong move the homepage already makes. This block brings those moves over;
   it adds no colour, font or primitive the site did not already own:
     - the display serif at hero weight and scale (homepage h1)
     - the fort mark hanging off the head, drawing itself (homepage .hero-mark)
     - sand-line rules as structure instead of white boxes (.home-section)
     - the sand band + navy button for the empty state (.vendor-band)
   Replaces the 2026-09-15 phone-width patch for the old boxed .editorial,
   which no longer exists.
   Everything is scoped to body.category. Left-aligned on purpose - the design
   of record (design/category-page.html) left-aligns category pages; only the
   homepage is centred.
   =========================================================================== */

/* ---- Head ---------------------------------------------------------------- */
.category .page-head {
  position: relative;
  overflow: hidden;                 /* the mark bleeds off, never over the header rule */
  padding: 44px 0 34px;
  margin-bottom: 36px;
  border-bottom: 1px solid var(--sand-line);
}

.category .page-head h1 {
  position: relative;               /* above the mark */
  font-weight: 400;
  font-size: clamp(36px, 8vw, 60px);
  line-height: 1.05;
  letter-spacing: -0.02em;
  max-width: 11em;
  text-wrap: balance;
  margin: 0;
}

.category .result-count {
  position: relative;
  font-family: var(--serif);
  font-style: italic;
  font-size: 19px;
  color: var(--terracotta);         /* 4.94:1 on cream */
  margin: 14px 0 0;
}

.category .head-mark {
  position: absolute;
  right: -2%;
  top: 50%;
  width: min(44vw, 300px);
  height: auto;
  transform: translateY(-50%);
  color: var(--navy);
  opacity: 0.08;
  pointer-events: none;
}

.category .head-mark path {
  stroke-dasharray: 470;
  stroke-dashoffset: 470;
  animation: draw-mark 2.4s cubic-bezier(0.65, 0, 0.35, 1) 0.2s forwards;
}

/* ---- Editorial: reading copy, not a card --------------------------------- */
.category .editorial {
  background: none;
  border: 0;
  border-radius: 0;
  padding: 0;
  max-width: 38em;
  margin: 0 0 56px;
}

.category .editorial p {
  font-size: 17px;
  line-height: 1.7;
  color: var(--charcoal);
  margin: 0 0 1.1em;
}

/* The first paragraph is the lede: display serif, navy, with a terracotta
   drop cap. Cormorant is fine at this size - it is only too thin below ~18px. */
.category .editorial p:first-child {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(21px, 2.6vw, 25px);
  line-height: 1.45;
  color: var(--navy);
  margin-bottom: 1.2em;
}

.category .editorial p:first-child::first-letter {
  float: left;
  font-family: var(--serif);
  font-weight: 500;
  font-size: 3.4em;
  line-height: 0.82;
  color: var(--terracotta);
  padding: 0.06em 0.1em 0 0;
}

/* ---- Empty state: the homepage's vendor band, in the listings slot ------- */
.category .category-join {
  background: var(--sand);
  border: 1px solid var(--sand-line);
  border-radius: var(--radius);
  padding: 26px 24px 28px;
  margin: 0 0 60px;
  max-width: 38em;
}

.category .category-join p {
  font-family: var(--serif);
  font-size: 21px;
  line-height: 1.4;
  color: var(--navy);               /* 10.61:1 on sand */
  margin: 0 0 18px;
}

.category .category-join .band-cta { margin-top: 0; }

/* ---- FAQ: an editorial list, question left / answer right ---------------- */
.category .faq {
  margin: 0 0 70px;
}

.category .faq h2 {
  font-weight: 400;
  font-size: clamp(26px, 4.5vw, 36px);
  line-height: 1.15;
  letter-spacing: -0.01em;
  max-width: 16em;
  text-wrap: balance;
  margin: 0 0 22px;
}

.category .faq-item {
  border-bottom: 1px solid var(--sand-line);
  padding: 22px 0 24px;
}

.category .faq-item:first-of-type {
  border-top: 2px solid var(--navy);
}

.category .faq-item h3 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 21px;
  line-height: 1.3;
  color: var(--navy);
  margin: 0 0 8px;
  text-wrap: balance;
}

.category .faq-item p {
  font-size: 16px;
  line-height: 1.65;
  color: var(--charcoal-soft);      /* 6.76:1 on cream */
  margin: 0;
  max-width: 36em;
}

/* ---- Browser surfaces ---------------------------------------------------- */
.category ::selection {
  background: var(--sand);
  color: var(--navy);
}

/* ---- Wider screens ------------------------------------------------------- */
@media (min-width: 820px) {
  .category .page-head { padding: 70px 0 48px; margin-bottom: 52px; }
  .category .head-mark { right: -70px; width: 340px; opacity: 0.11; }   /* = homepage .hero-mark */

  .category .faq-item {
    display: grid;
    grid-template-columns: 5fr 7fr;
    gap: 40px;
    padding: 26px 0 28px;
  }
  .category .faq-item h3 { margin: 0; }

  .category .category-join { padding: 32px 36px 34px; }
}

/* ---- Phones -------------------------------------------------------------- */
@media (max-width: 480px) {
  /* Pull the mark up out of the heading's lines so it reads as a watermark,
     not as something printed over the words. */
  .category .head-mark { top: 8px; transform: none; width: 150px; opacity: 0.07; }
  .category .editorial p:first-child::first-letter { font-size: 3em; }
}

/* ===========================================================================
   MOTION - Tier 1 "wow" pass, 2026-09-16. Corey: "I also want to produce a
   wow factor... some moving parts." Everything below is native CSS - no
   library, no JS, nothing that can slow a page or break a crawler. Each
   piece is a progressive enhancement: a browser that lacks it shows the
   plain page, never a broken one.

     1. Cross-document view transitions - pages glide into each other
     2. The fort mark draws itself on the homepage
     3. Scroll reveals - tiles, cards and sections rise into place
     4. Hover micro-interactions - photos breathe, links underline
     5. Reduced-motion: all of it off for anyone who asked their OS for that

   Kill switch: delete this block. Nothing above it depends on it.
   =========================================================================== */

/* ---- 1. Page-to-page transitions --------------------------------------
   One rule opts every page linking guide.css into a cross-fade instead of a
   white blink. Chrome 126+, Safari 18.2+. Firefox has not shipped it and
   simply navigates normally. The header is named so it holds still while the
   content underneath it fades - the brand should feel like the fixed point. */
@view-transition { navigation: auto; }

::view-transition-old(root) { animation-duration: 0.22s; }
::view-transition-new(root) { animation-duration: 0.32s; }

header.site-header { view-transition-name: site-header; }

/* ---- 2. The fort mark draws itself ------------------------------------
   The brand path is 12 straight segments: four of 32 units and eight of
   ~41.2, so ~458 units of stroke in viewBox space. 470 as the dash length
   gives a little slack so the end of the stroke is never clipped.
   Homepage only (body.home) - a logo that redraws on every page hop would
   get old by the third click. */
@keyframes draw-mark {
  from { stroke-dashoffset: 470; }
  to   { stroke-dashoffset: 0; }
}

body.home .brand-mark path {
  stroke-dasharray: 470;
  stroke-dashoffset: 470;
  animation: draw-mark 1.1s cubic-bezier(0.65, 0, 0.35, 1) 0.15s forwards;
}

/* A large, faint copy of the mark behind the hero, drawing itself more slowly.
   This is the "motion in the hero" stand-in until there is a real photograph -
   and it stays useful after, as a watermark that ties the page to the brand. */
.hero-mark {
  position: absolute;
  top: 50%;
  right: -4%;
  width: min(52vw, 520px);
  height: auto;
  transform: translateY(-50%);
  opacity: 0.11;
  pointer-events: none;
  color: var(--navy);
}

.hero-mark path {
  stroke-dasharray: 470;
  stroke-dashoffset: 470;
  animation: draw-mark 2.4s cubic-bezier(0.65, 0, 0.35, 1) 0.3s forwards;
}

.home .home-hero {
  position: relative;
  /* the hero is centred and 34em wide; the mark hangs off the right edge of
     the full-width wrap, so the hero needs to be allowed to reach it */
  max-width: none;
}

.home .home-hero > :not(.hero-mark) {
  position: relative;
  /* rem, not em. On the 46px h1, 34em is 1564px - the cap did nothing and
     the heading ran the full 1032px wrap. Caught by measuring in Chrome
     2026-09-16, not by eye. */
  max-width: 34rem;
  margin-left: auto;
  margin-right: auto;
}

/* The mark hangs past the hero's right edge on purpose. Clip at the wrap so
   it can never push the page wider than the viewport - project rule 7, the
   page itself must never scroll sideways. overflow-x: clip does not create
   a scroll container the way hidden does, so sticky/anchors are unaffected;
   hidden is the fallback for browsers without clip. */
main.home {
  overflow-x: hidden;
  overflow-x: clip;
}

@media (max-width: 819px) {
  .hero-mark { width: 62vw; right: -8%; opacity: 0.08; }
}

/* ---- 3. Scroll reveals -------------------------------------------------
   Native scroll-driven animation: each element rises and fades in as it
   enters the viewport, driven by scroll position rather than a timer, so it
   is smooth at any scroll speed and costs no JavaScript. Chrome 115+, Edge,
   Safari 26+ (~83% of browsers). Firefox still has this behind a flag - the
   @supports guard means Firefox never hides anything; it just shows the
   page as it always has. Elements already in view on load sit at their end
   state, so nothing above the fold flickers. */
@keyframes rise-in {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: none; }
}

@supports (animation-timeline: view()) {
  .category-tile,
  .vendor-card,
  .how-item,
  .vendor-band,
  .home-section > h2,
  .section-lead,
  .section-block,
  .nap-block,
  .step-list li,
  .price-callout,
  .guide-form,
  .category .faq-item,
  .category .category-join {
    animation: rise-in linear both;
    animation-timeline: view();
    animation-range: entry 0% entry 38%;
  }

  /* The tile grid is the first thing under the hero. Give the tiles a
     slightly later finish than the cards so a row reads as a cascade rather
     than a wall arriving at once. */
  .category-tile { animation-range: entry 0% entry 50%; }
}

/* ---- 4. Micro-interactions --------------------------------------------- */
.vendor-photo { overflow: hidden; }

.vendor-photo img,
.gallery-photo img {
  transition: transform 0.7s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.vendor-card:hover .vendor-photo img,
.gallery-photo a:hover img {
  transform: scale(1.045);
}

.category-tile {
  transition: border-color 0.18s ease, transform 0.25s cubic-bezier(0.2, 0.7, 0.2, 1),
              box-shadow 0.25s ease;
}

.category-tile:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 26px -14px rgba(22, 48, 63, 0.35);
}

.vendor-card {
  transition: transform 0.25s cubic-bezier(0.2, 0.7, 0.2, 1), box-shadow 0.25s ease;
}

.vendor-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 30px -16px rgba(22, 48, 63, 0.4);
}

/* Links inside reading copy get a drawn underline instead of a browser one.
   Scoped to paragraphs so buttons, tiles and nav are untouched. */
.lead-copy a,
.section-lead a,
.category-empty a,
.vendor-band p a {
  color: var(--navy);
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size 0.3s ease;
}

.lead-copy a:hover,
.section-lead a:hover,
.category-empty a:hover,
.vendor-band p a:hover {
  background-size: 100% 1px;
}

.band-cta,
.vendor-cta,
.guide-form button {
  transition: background-color 0.18s ease, transform 0.18s ease;
}

.band-cta:hover,
.vendor-cta:hover { transform: translateY(-1px); }

/* ---- 5. Reduced motion --------------------------------------------------
   Anyone who set "reduce motion" in their OS gets the static page: no draw,
   no reveals, no transitions. This is an accessibility requirement, not a
   nicety - vestibular disorders are real and scroll-linked motion is the
   worst trigger. */
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }

  body.home .brand-mark path,
  .hero-mark path,
  .category .head-mark path {
    animation: none;
    stroke-dasharray: none;
    stroke-dashoffset: 0;
  }

  .category-tile, .vendor-card, .how-item, .vendor-band, .home-section > h2,
  .section-lead, .section-block, .nap-block, .step-list li, .price-callout,
  .guide-form, .category .faq-item, .category .category-join {
    animation: none;
  }

  .vendor-photo img, .gallery-photo img, .category-tile, .vendor-card,
  .band-cta, .vendor-cta { transition: none; }
}
