
  /* Metric-matched fallback for the script wordmark — shared source, so the
     pre-swap paint matches the React pages instead of dropping to raw cursive. */
  @font-face{font-family:'Great Vibes Fallback';font-style:normal;font-weight:400;src:local('Snell Roundhand'),local('Apple Chancery'),local('Brush Script MT'),local('Lucida Handwriting');ascent-override:85.1%;descent-override:40.1%;line-gap-override:0%;size-adjust:100%;}
@font-face{font-family:'Playfair Display Fallback';font-style:normal;font-weight:400 900;src:local('Georgia');ascent-override:106.2%;descent-override:24.6%;line-gap-override:0%;size-adjust:101.9%;}
@font-face{font-family:'Playfair Display Fallback';font-style:italic;font-weight:400 900;src:local('Georgia Italic');ascent-override:106.2%;descent-override:24.6%;line-gap-override:0%;size-adjust:101.9%;}
@font-face{font-family:'Playfair Display Fallback';font-style:normal;font-weight:400 900;src:local('Times New Roman'),local('Liberation Serif'),local('Nimbus Roman');ascent-override:98.5%;descent-override:22.8%;line-gap-override:0%;size-adjust:109.9%;}
@font-face{font-family:'Playfair Display Fallback';font-style:italic;font-weight:400 900;src:local('Times New Roman Italic'),local('Liberation Serif Italic');ascent-override:98.5%;descent-override:22.8%;line-gap-override:0%;size-adjust:109.9%;}
@font-face{font-family:'Pinyon Script Fallback';font-style:normal;font-weight:400;src:local('Snell Roundhand'),local('Apple Chancery'),local('Brush Script MT'),local('Lucida Handwriting');ascent-override:86.3%;descent-override:38.4%;line-gap-override:0%;size-adjust:100%;}
  *,*::before,*::after { box-sizing:border-box; }
  body { margin:0; background:#FCF7D9; font-family:'Fraunces',Georgia,serif; color:#3D2B1F; -webkit-font-smoothing:antialiased; }

  /* ── THE BASE LINK COLOUR ────────────────────────────────────────────────────
     The brand link colour was only ever declared as .seo-band a, and plenty of
     links on these pages sit outside a band. Those inherited nothing, so they fell
     through to the user agent's own a:link, which is #0000EE on a cream editorial
     page. Three anchor classes are in that position today: .mj-cr2-stop on the
     crawl page, .mj-ke-slot in Keep Exploring, and .mj-ps-stamp on Joe's Picks.

     This is deliberately an UNSCOPED, single-element selector, specificity 0-0-1.
     That is the whole safety argument: it loses to every class rule in the sheet,
     so it cannot recolour a single link that any component already styles. It can
     only reach an anchor that nothing else colours, which is exactly the set that
     was falling back to blue, plus any bare link added here in future. Measured
     after adding it: 3 anchor classes changed, 38 did not.

     #5C3520 is the same value .seo-band a has always used, so a link inside a band
     and a link outside one are finally the same colour rather than two different
     answers to the same question. */
  a { color:#5C3520; }
  /* Website header + awning — single shared source (websiteHeader.ts). Injected
     verbatim here and in the React website header so the two never drift. */
  
/* Website header + awning — single source (base44/shared/websiteHeader.ts). */
/* position + z-index so the account dropdown paints OVER the page. Layout.jsx
   renders <main id="moj-scroll" class="relative"> immediately after this header;
   both were positioned at z-index:auto, so the later sibling won the paint order
   and covered everything the dropdown extended below the header. Raising the
   header lifts it above <main> and above the static awning too. 50 sits above the
   highest in-page z-index (40) and below the launch splash (9999). */
.mj-web-header{background:#3D2B1F;position:relative;z-index:50;}

/* Desktop row (≥1024px). The bar is the site's content measure, centered; the
   chocolate .mj-web-header around it stays full-bleed. Children are absolutely
   positioned at fixed offsets — see the geometry note at the top of this file. */
.mj-web-bar{position:relative;max-width:1200px;margin:0 auto;height:84px;box-sizing:border-box;}
.mj-web-bar > .mj-web-navgroup,
.mj-web-bar > .mj-web-logo,
.mj-web-bar > .mj-web-avatar-slot,
.mj-web-bar > .mj-web-search-btn,
.mj-web-bar > .mj-web-pill{position:absolute;top:50%;transform:translateY(-50%);}
/* Fixed left offsets */
/* The two groups. Each is a flex row that sizes to its own items, so a label
   getting longer or an item being added widens the group rather than overrunning a
   fixed slot into its neighbour. */
.mj-web-navgroup{display:flex;align-items:center;gap:34px;}
.mj-web-bar > .mj-web-navgroup--left{left:24px;}
/* Fixed right offsets */
.mj-web-bar > .mj-web-navgroup--right{right:190px;}
.mj-web-bar > .mj-web-avatar-slot{right:80px;}
.mj-web-bar > .mj-web-pill{right:24px;}
.mj-web-bar > .mj-web-search-btn{right:136px;}
/* Wordmark pinned to the bar's centre line, out of flow with both nav sides. */
.mj-web-bar > .mj-web-logo{left:50%;transform:translate(-50%,-50%);}

/* display:flex + align-items:center centres the text inside the 44px tap-target box
   that index.css forces onto every <a>. Without it the element box centres but the
   glyphs sit at the top of the box, which is what put the nav text off the avatar
   and pill centre line. Does not change font size. */
.mj-web-nav{color:#FCF7D9;font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-weight:500;font-size:16px;text-decoration:none;opacity:0.82;white-space:nowrap;line-height:1;display:flex;align-items:center;}
.mj-web-nav:hover{opacity:1;text-decoration:underline;}
.mj-web-logo{color:#FCF7D9;font-family:'Great Vibes', 'Great Vibes Fallback', cursive;font-size:30px;font-weight:400;text-decoration:none;line-height:1;letter-spacing:0.01em;white-space:nowrap;display:flex;align-items:center;}
/* The server-rendered slot, once filled client-side. Geometry is copied from the
   React control exactly: 28px circle + 4px gap + 12px chevron = 44px, the slot's
   own width — so filling a reserved slot cannot move anything. */
.mj-web-avatar-live{display:flex;align-items:center;gap:4px;background:transparent;border:none;padding:0;margin:0;color:#FCF7D9;opacity:0.85;cursor:pointer;min-height:unset;min-width:unset;height:auto;line-height:1;}
.mj-web-avatar-live:hover{opacity:1;}
.mj-web-avatar-img{width:28px;height:28px;border-radius:9999px;object-fit:cover;display:block;}
/* #B08968 / #FBEFC0 are --mj-mocha / --mj-gold at their light-theme values, the
   colours WebsiteAccountButton renders. Hardcoded, like every other colour in this
   file, so the server-rendered header cannot diverge with the viewer's theme. */
.mj-web-avatar-initial{width:28px;height:28px;border-radius:9999px;display:flex;align-items:center;justify-content:center;background:#B08968;color:#FBEFC0;font-family:'Fraunces',Georgia,serif;font-size:13px;font-weight:700;line-height:1;}
.mj-web-avatar-chev{display:block;}
.mj-web-avatar-menu{position:absolute;right:0;top:100%;margin-top:4px;width:192px;background:#FCF7D9;border:1px solid rgba(61,43,31,0.18);border-radius:12px;padding:4px 0;z-index:50;box-shadow:0 8px 24px rgba(61,43,31,0.18);}
.mj-web-avatar-menu a{display:block;padding:10px 16px;font-family:'Fraunces',Georgia,serif;font-size:12px;font-weight:600;color:#3D2B1F;text-decoration:none;}
.mj-web-avatar-menu a:hover{background:rgba(61,43,31,0.06);}
/* Log Out is a button, not a link — it clears local state before it navigates. Styled
   identically to the anchors so the row is indistinguishable, and given the same
   hairline separator the React menu draws above it. */
.mj-web-avatar-menu button{display:block;width:100%;text-align:left;padding:10px 16px;font-family:'Fraunces',Georgia,serif;font-size:12px;font-weight:600;color:#3D2B1F;background:none;border:none;cursor:pointer;min-height:unset;min-width:unset;}
.mj-web-avatar-menu button:hover{background:rgba(61,43,31,0.06);}
.mj-web-avatar-menu hr{border:none;border-top:1px solid rgba(61,43,31,0.14);margin:4px 0;}
/* The slot is already position:absolute (grouped rule above) and already
   establishes a stacking context via its transform, so it is the menu's containing
   block, and the menu rides with the header — which sits at z-index 50, above the
   awning and above <main>. */
/* Always present, fixed size, in both renderers and in every auth state. */
.mj-web-avatar-slot{width:44px;height:44px;display:flex;align-items:center;justify-content:center;flex-shrink:0;}
/* Outlined, not filled: a transparent circle with a 1px cream border and a cream
   icon, so it reads as available rather than as the loudest thing in the header.
   box-sizing:border-box keeps the border INSIDE the 44px box, so the header's
   geometry is unchanged. */
.mj-web-pill{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;width:44px;height:44px;background:transparent;color:#FCF7D9;border:1px solid #FCF7D9;border-radius:9999px;padding:0;text-decoration:none;line-height:1;flex-shrink:0;}
.mj-web-pill:hover{opacity:1;background:rgba(252,247,217,0.12);text-decoration:none;}
.mj-web-pill svg{display:block;}

/* Awning — directly under the nav. Same height / tooth width everywhere. */
/* An awning is two-tone, and which two tones is NOT a per-page choice: field = the
   band above, teeth = the band below (awningSeamPaint). The bare class is the
   chocolate-above case — the awning under the chocolate header — and reads as that
   header coming down with cream scallops hanging from it. Everything else picks a
   modifier, or better, calls awningSeamClass / bdAwning with its two bands. */
/* Every seam below is generated by awningPaintCss, so none of these colour pairs
   is written by hand. Class names read <band above>-to-<teeth>. */
.mj-web-awning{height:32px;flex-shrink:0;background-color:#604734;background-image:repeating-linear-gradient(90deg,#604734 0px,#604734 calc(32px * 0.875),#FCF7D9 calc(32px * 0.875),#FCF7D9 calc(32px * 1.75));}
.mj-web-awning--cream-to-chocolate{background-color:#FCF7D9;background-image:repeating-linear-gradient(90deg,#FCF7D9 0px,#FCF7D9 calc(32px * 0.875),#604734 calc(32px * 0.875),#604734 calc(32px * 1.75));}
.mj-web-awning--cream-to-blush{background-color:#FCF7D9;background-image:repeating-linear-gradient(90deg,#FCF7D9 0px,#FCF7D9 calc(32px * 0.875),#F3DAD3 calc(32px * 0.875),#F3DAD3 calc(32px * 1.75));}
.mj-web-awning--blush-to-cream{background-color:#F3DAD3;background-image:repeating-linear-gradient(90deg,#F3DAD3 0px,#F3DAD3 calc(32px * 0.875),#FCF7D9 calc(32px * 0.875),#FCF7D9 calc(32px * 1.75));}
.mj-web-awning--blush-to-chocolate{background-color:#F3DAD3;background-image:repeating-linear-gradient(90deg,#F3DAD3 0px,#F3DAD3 calc(32px * 0.875),#604734 calc(32px * 0.875),#604734 calc(32px * 1.75));}

/* ── SITEWIDE SEARCH ───────────────────────────────────────────────────────
   The button is a 34px icon square in the rail on desktop and sits beside the
   pill on mobile. The panel is a full-bleed chocolate band directly under the
   header row, with its contents on the same 1200px measure as everything else.

   TWO WAYS TO BE OPEN, one appearance. The server-rendered pages run no
   framework, so a checkbox before the panel opens it through a sibling selector;
   React sets .mj-web-search--open. Same rule, same result, which is what keeps
   one panel from becoming two.

   display:none rather than height:0 — a closed panel must not be tabbable, and a
   collapsed one still is. */
.mj-web-search-btn{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;width:34px;height:34px;min-width:0;min-height:0;padding:0;background:transparent;color:#FCF7D9;border:none;border-radius:9999px;cursor:pointer;line-height:1;opacity:0.82;flex-shrink:0;}
.mj-web-search-btn:hover{opacity:1;}
.mj-web-search-toggle{position:absolute;opacity:0;pointer-events:none;width:0;height:0;}
.mj-web-search{display:none;background:#3D2B1F;border-top:1px solid rgba(252,247,217,0.16);}
.mj-web-search-toggle:checked ~ .mj-web-search,
.mj-web-search--open{display:block;}
.mj-web-search-inner{max-width:1200px;margin:0 auto;padding:18px 24px 22px;box-sizing:border-box;}
.mj-web-search-input{display:block;width:100%;box-sizing:border-box;background:transparent;border:none;border-bottom:1px solid rgba(252,247,217,0.35);border-radius:0;color:#FCF7D9;font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-size:17px;line-height:1.4;padding:10px 2px;outline:none;min-height:44px;}
.mj-web-search-input::placeholder{color:rgba(252,247,217,0.5);}
.mj-web-search-input:focus{border-bottom-color:#FCF7D9;}
.mj-web-search-results{display:flex;flex-direction:column;}
.mj-web-search-label{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-size:11px;letter-spacing:0.18em;text-transform:uppercase;color:rgba(252,247,217,0.55);margin:18px 0 2px;}
.mj-web-search-row{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;color:#FCF7D9;font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-size:15px;text-decoration:none;padding:9px 2px;min-height:44px;box-sizing:border-box;border-bottom:1px solid rgba(252,247,217,0.10);}
.mj-web-search-row:last-child{border-bottom:none;}
.mj-web-search-row:hover{text-decoration:underline;}
.mj-web-search-row-sub{font-size:13px;color:rgba(252,247,217,0.6);}
.mj-web-search-note{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-size:14px;color:rgba(252,247,217,0.6);margin:14px 0 0;min-height:0;}
.mj-web-search-note:empty{display:none;}

/* Mobile (<1024px) */
.mj-web-mobile{display:none;}
.mj-web-mobile-top{display:flex;align-items:center;justify-content:space-between;width:100%;min-height:40px;}
/* min-height, not font-size: the wordmark stays exactly the size it is set to
   (WEBSITE_LOGO_FONT_SIZE_PX) and only its tap box grows to the 44px the rest of
   the site uses. It measured 30px, which made the one link present on every
   single page one of the smallest targets on the site. */
.mj-web-mobile-logo{color:#FCF7D9;font-family:'Great Vibes', 'Great Vibes Fallback', cursive;font-size:30px;font-weight:400;text-decoration:none;line-height:1;letter-spacing:0.01em;display:flex;align-items:center;min-height:44px;}
.mj-web-mobile-right{display:flex;align-items:center;gap:8px;}
.mj-web-mobile-hamburger{display:inline-flex;align-items:center;justify-content:center;padding:8px;background:transparent;color:#FCF7D9;border:none;border-radius:8px;cursor:pointer;line-height:1;}
/* ── THE MOBILE MENU ───────────────────────────────────────────────────────
   ONE MENU, ON EVERY WEBSITE PAGE. There used to be two, and which one you got
   depended on how the page was rendered:

     React pages      opened MobileHamburgerMenu — the APP's bottom sheet. Fraunces,
                      app tokens, a drag handle, an icon beside every row. It is the
                      app's menu and it looked like it, on the website.
     Server pages     had no JS, so the hamburger was a checkbox that revealed
                      .mj-web-mobile-nav: the four desktop links, wrapped, centred,
                      inline under the wordmark. Not a menu, a reflow.

   Both are gone. The panel below is defined once, here, and rendered by both
   sides from the same class names — React from state, the server from the same
   checkbox — so they cannot drift again. MobileHamburgerMenu is untouched and
   still the app's.

   THE 768-1023 LINK ROW IS GONE TOO. .mj-web-mobile-nav used to be display:flex
   above 768px, so a tablet got a permanent wrapped row of links under the
   wordmark — the second thing that made the header render differently depending
   on where you were. Below 1024px there is now exactly one nav: this panel.

   It is a PANEL UNDER THE HEADER, not a sheet rising from the bottom. A sheet is
   a touch idiom the app earns because it is an app; a website menu drops from the
   control that opened it. */
.mj-web-mobile-toggle{position:absolute;opacity:0;pointer-events:none;width:0;height:0;}

.mj-web-menu{display:none;position:absolute;top:100%;left:0;right:0;background:#FCF7D9;border-top:1px solid #3B2A1E;box-shadow:0 18px 40px rgba(59,42,30,0.18);max-height:calc(100vh - 84px);overflow-y:auto;-webkit-overflow-scrolling:touch;z-index:60;}
.mj-web-mobile-toggle:checked ~ .mj-web-menu{display:block;}
.mj-web-menu--open{display:block;}
.mj-web-menu-inner{max-width:1200px;margin:0 auto;padding:22px 24px 32px;box-sizing:border-box;}

/* The three things a visitor can CONTRIBUTE, as outlined pills — the website's own
   button, not a row with an icon in front of it. */
/* Two up from 360px — the width at which "Leave a Review" still fits a half column
   without wrapping — with the third spanning both. Below that they stack; a pill
   whose label wraps to two lines is worse than a third row. */
.mj-web-menu-actions{display:grid;grid-template-columns:1fr;gap:10px;margin:0 0 26px;}
@media(min-width:360px){.mj-web-menu-actions{grid-template-columns:1fr 1fr;}
  .mj-web-menu-action--wide{grid-column:1 / -1;}}
a.mj-web-menu-action{display:flex;align-items:center;justify-content:center;min-height:48px;padding:12px 10px;border:1px solid #3B2A1E;border-radius:2px;background:transparent;color:#3B2A1E;font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-size:12px;font-weight:700;letter-spacing:0.1em;text-transform:uppercase;text-decoration:none;text-align:center;line-height:1.2;white-space:nowrap;}
a.mj-web-menu-action:hover{background:#3B2A1E;color:#FCF7D9;}

.mj-web-menu-label{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-size:11px;font-weight:700;letter-spacing:0.16em;text-transform:uppercase;color:#8A6E52;margin:0 0 4px;}
.mj-web-menu-list{display:block;margin:0 0 26px;}
/* Playfair at reading size, one per line, a hairline between. No icons: the site
   does not use them anywhere else, and a column of them was most of what made the
   old sheet read as the app. */
a.mj-web-menu-link{display:flex;align-items:center;min-height:52px;font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-size:19px;font-weight:500;color:#3B2A1E;text-decoration:none;border-bottom:1px solid #D9C9A8;}
a.mj-web-menu-link:last-child{border-bottom:none;}
a.mj-web-menu-link:hover{color:#8A6E52;}

a.mj-web-menu-auth{display:flex;align-items:center;justify-content:center;min-height:52px;padding:14px 22px;border:1px solid #3B2A1E;border-radius:2px;background:#3B2A1E;color:#FCF7D9;font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-size:13px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;text-decoration:none;}
a.mj-web-menu-auth:hover{opacity:0.88;}

@media(min-width:1024px){.mj-web-mobile{display:none;}.mj-web-menu{display:none !important;}}
@media(max-width:1023px){
  .mj-web-bar{display:none;}
  .mj-web-mobile{display:flex;flex-direction:column;align-items:center;max-width:1200px;margin:0 auto;padding:10px 24px 8px;}
}


  /* Directory band system — shared with the React /states page (websiteBands.ts). */
  
/* Website band system — single source (base44/shared/websiteBands.ts).
   Chocolate / cream / blush only. No gold, no accent hue, no decorative motifs. */
.mj-bd-band{width:100%;}
.mj-bd-band--chocolate{background:#3D2B1F;color:#FCF7D9;}
.mj-bd-band--cream{background:#FCF7D9;color:#3D2B1F;}
.mj-bd-band--blush{background:#F3DAD3;color:#3D2B1F;}
.mj-bd-inner{width:100%;max-width:1200px;margin:0 auto;padding:clamp(48px,7vw,84px) 20px;box-sizing:border-box;}
.mj-bd-inner--tight{padding-top:clamp(34px,5vw,52px);padding-bottom:clamp(34px,5vw,52px);}
/* HALF THE HERO. The /states hero was clamp(48px,7vw,84px) top and bottom on a band
   carrying three lines, which put the first state card most of a screen down on a
   phone. This is that, halved. Its own class rather than a change to --tight, which
   the city page's CTA uses for a different job. */
.mj-bd-inner--herohalf{padding-top:clamp(24px,3.5vw,42px);padding-bottom:clamp(24px,3.5vw,42px);}
/* The city page's closing CTA. Its own top padding is zero: the band above it
   already ends on .mj-bd-inner's full bottom padding, and adding a second
   band's worth plus .seo-landing-cta's 32px margin left ~180px of empty cream
   between the last shop card and the button. */
.mj-bd-inner--cta{padding-top:0;padding-bottom:clamp(34px,5vw,52px);}

/* Hero */
.mj-bd-hero{text-align:center;}
.mj-bd-eyebrow{font-family:'Fraunces', Georgia, serif;text-transform:uppercase;font-size:11px;letter-spacing:0.28em;font-weight:600;margin:0 0 18px;color:rgba(252,247,217,0.78);}
.mj-bd-band--cream .mj-bd-eyebrow,.mj-bd-band--blush .mj-bd-eyebrow{color:rgba(61,43,31,0.68);}
/* Serif line + script word ON ONE LINE. The script word used to be rotated -5deg,
   pulled back with a negative left margin and lifted 0.10em off the baseline, so
   that "Coffee Shops in" and "Las Vegas" interlocked — which at hero size read as a
   word knocked out of alignment rather than as a flourish. It now sits square on the
   title's own baseline, in the script face, with ordinary word spacing.
   Note the removed transform is why this is display:inline again: an inline-block
   was only ever there to carry the rotation. */
.mj-bd-title{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-weight:700;font-size:clamp(2.4rem,7vw,4.4rem);line-height:1.04;letter-spacing:-0.01em;margin:0;color:inherit;}
.mj-bd-script{font-family:'Pinyon Script', 'Pinyon Script Fallback', cursive;font-weight:400;font-style:normal;display:inline;color:#FCF7D9;}
.mj-bd-band--cream .mj-bd-script,.mj-bd-band--blush .mj-bd-script{color:#3D2B1F;}
.mj-bd-band--chocolate .seo-breadcrumb,.mj-bd-band--chocolate .seo-breadcrumb a{color:rgba(252,247,217,0.78);}
.mj-bd-stats{font-family:'Fraunces', Georgia, serif;font-size:clamp(0.95rem,1.9vw,1.05rem);margin:22px 0 0;color:rgba(252,247,217,0.78);}
.mj-bd-band--cream .mj-bd-stats,.mj-bd-band--blush .mj-bd-stats{color:rgba(61,43,31,0.68);}

/* Featured state — blush band, no kicker line above the name. */
.mj-bd-feature-name{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-weight:700;font-size:clamp(2.6rem,8vw,4.8rem);line-height:1.02;letter-spacing:-0.015em;margin:0;color:#3D2B1F;}
.mj-bd-feature-meta{font-family:'Fraunces', Georgia, serif;font-size:clamp(0.95rem,1.9vw,1.05rem);color:rgba(61,43,31,0.68);margin:16px 0 0;}
.mj-bd-feature-link{font-family:'Fraunces', Georgia, serif;font-weight:600;font-size:14px;letter-spacing:0.04em;color:#3D2B1F;text-decoration:none;border-bottom:1px solid rgba(61,43,31,0.22);padding-bottom:2px;display:inline-block;margin-top:22px;}
.mj-bd-feature-link:hover{border-bottom-color:#3D2B1F;}

/* Region heading — script name, slight slant, hairline rule out to the count. */
.mj-bd-region-head{display:flex;align-items:baseline;gap:18px;margin:0 0 clamp(22px,3vw,32px);}
.mj-bd-region-name{font-family:'Pinyon Script', 'Pinyon Script Fallback', cursive;font-weight:400;font-size:clamp(2rem,4.5vw,3rem);line-height:1;color:#3D2B1F;display:inline-block;transform:rotate(-3deg);white-space:nowrap;}
.mj-bd-region-rule{flex:1;height:0;border-top:1px solid rgba(61,43,31,0.22);}
.mj-bd-region-count{font-family:'Fraunces', Georgia, serif;font-size:14px;color:rgba(61,43,31,0.68);white-space:nowrap;}

/* Cards — hairline border, flat fill, no shadow, no corner marks. */
.mj-bd-grid{display:grid;grid-template-columns:repeat(3,1fr);grid-auto-rows:1fr;gap:clamp(14px,2vw,20px);list-style:none;padding:0;margin:0;align-items:stretch;}
@media(max-width:1023px){.mj-bd-grid{grid-template-columns:repeat(2,1fr);}}
@media(max-width:767px){.mj-bd-grid{grid-template-columns:1fr;}}
.mj-bd-grid--one{grid-template-columns:1fr;}
@media(max-width:1023px){.mj-bd-grid--one{grid-template-columns:1fr;}}
/* Every card in a row is the same height. height:100% on the <a> alone was not
   enough — it resolves against the <li>, whose own height is only implied by the
   grid — so the <li> is a flex box and the card grows to fill it. Without this a
   card carrying a "Joe's pick" line stood taller than the two beside it.
   grid-auto-rows:1fr takes it further: every row in a band is the height of the
   tallest card in the band, so a trailing row of two pick-less states does not sit
   shorter than the three full rows above it.
   (This was li:not([hidden]) while the hub had a search that hid cards. Nothing
   hides a card now — every state renders, always — so the plain rule is correct.) */
.mj-bd-grid > li{display:flex;}
.mj-bd-card{display:flex;flex-direction:column;flex:1 1 auto;border:1px solid rgba(61,43,31,0.22);background:transparent;box-shadow:none;border-radius:2px;padding:clamp(16px,2.2vw,22px);text-decoration:none;color:#3D2B1F;box-sizing:border-box;}
.mj-bd-card:hover{border-color:#3D2B1F;}
.mj-bd-card-name{display:block;font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-weight:700;font-size:clamp(1.05rem,2.1vw,1.25rem);line-height:1.2;margin:0 0 8px;}
.mj-bd-card-meta{display:block;font-family:'Fraunces', Georgia, serif;font-size:14px;color:rgba(61,43,31,0.68);margin:0;}
.mj-bd-card-pick{display:block;font-family:'Fraunces', Georgia, serif;font-size:14px;font-style:italic;color:rgba(61,43,31,0.68);margin:6px 0 0;}
/* "Also in <State>" — the single-shop long tail as one comma-separated run of text
   links. Deliberately NOT rows: no arrows, no hairlines, no counts, because every
   city in it has exactly one shop. */
.mj-bd-alsoin-label{font-family:'Fraunces', Georgia, serif;text-transform:uppercase;font-size:11px;letter-spacing:0.28em;font-weight:600;color:rgba(61,43,31,0.68);margin:0 0 12px;}
.mj-bd-alsoin{font-family:'Fraunces', Georgia, serif;font-size:15px;line-height:2;color:rgba(61,43,31,0.68);margin:0;}
.mj-bd-alsoin a{color:#3D2B1F;text-decoration:none;border-bottom:1px solid transparent;}
.mj-bd-alsoin a:hover{border-bottom-color:#3D2B1F;}
/* State page city cards. Deliberately NOT the hub's tilted, fully-bordered card:
   the two levels looked identical, so a visitor could not tell whether they were on
   the hub or inside one state. These are flat and untilted with a single left rule,
   denser, and they sit in ONE continuous band rather than the hub's region groups. */
.mj-bd-citygrid{display:grid;grid-template-columns:repeat(3,1fr);gap:0 clamp(20px,3vw,36px);list-style:none;padding:0;margin:0;}
@media(max-width:1023px){.mj-bd-citygrid{grid-template-columns:repeat(2,1fr);}}
@media(max-width:767px){.mj-bd-citygrid{grid-template-columns:1fr;}}
.mj-bd-citycard{display:block;border:0;border-left:2px solid rgba(61,43,31,0.22);background:transparent;border-radius:0;padding:12px 0 12px 16px;margin:0 0 4px;text-decoration:none;color:#3D2B1F;}
.mj-bd-citycard:hover{border-left-color:#3D2B1F;}
.mj-bd-citycard-name{display:block;font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-weight:700;font-size:clamp(1rem,2vw,1.15rem);line-height:1.25;margin:0;}
.mj-bd-citycard-meta{display:block;font-family:'Fraunces', Georgia, serif;font-size:14px;color:rgba(61,43,31,0.68);margin:2px 0 0;}
.mj-bd-citycard-pick{display:block;font-family:'Fraunces', Georgia, serif;font-size:14px;font-style:italic;color:rgba(61,43,31,0.68);margin:2px 0 0;}

/* 8: "Also in <State>" as a collapsed disclosure. <details> keeps every link in the
   HTML at all times — nothing is hidden from crawlers that is hidden from people,
   and no JavaScript gates the content. */
.mj-bd-more{border-top:1px solid rgba(61,43,31,0.22);margin-top:clamp(28px,4vw,40px);padding-top:20px;}
.mj-bd-more > summary{font-family:'Fraunces', Georgia, serif;text-transform:uppercase;font-size:11px;letter-spacing:0.28em;font-weight:600;color:rgba(61,43,31,0.68);cursor:pointer;list-style:none;display:inline-block;padding:4px 0;}
.mj-bd-more > summary::-webkit-details-marker{display:none;}
.mj-bd-more > summary::after{content:' +';}
.mj-bd-more[open] > summary::after{content:' −';}
.mj-bd-more > summary:hover{color:#3D2B1F;}

/* A state we do not cover yet: same card box, muted, and NOT a link. statePage
   answers 503 for a state with no shops, so linking one would be a link to an
   error. It reads as a placeholder because it is one. */
.mj-bd-card--empty{border-style:dashed;color:rgba(61,43,31,0.68);}
.mj-bd-card--empty .mj-bd-card-name{font-weight:400;color:rgba(61,43,31,0.68);}
.mj-bd-card--empty .mj-bd-card-meta{font-style:italic;}

/* City page: the "Browse <State> shops" button. The compound selector is deliberate —
   seoPageLayout defines .seo-landing-cta AFTER this stylesheet is injected, so a
   single-class rule here would lose to its margin-top:32px at equal specificity.
   That 32px, stacked on two bands' worth of padding, was most of the dead space
   above the button. */
.seo-landing-cta.mj-bd-citycta{margin-top:0;margin-bottom:clamp(20px,3vw,32px);}
/* The quieter second line under that button: this page's link to its own state.
   The button now goes to the states hub (which is what a visitor at the bottom of a
   city list is usually reaching for), and this keeps the city -> state path — for a
   reader and for a crawler — without a second button competing with the first. */
.mj-bd-ctasub{font-family:'Fraunces', Georgia, serif;font-size:14px;margin:14px 0 0;}
.mj-bd-ctasub a{color:rgba(61,43,31,0.68);text-decoration:none;border-bottom:1px solid transparent;}
.mj-bd-ctasub a:hover{color:#3D2B1F;border-bottom-color:#3D2B1F;}
/* Name left, Joe's Pick badge hard right, on ONE line. baseline (not center) so a
   name that wraps to two lines keeps the badge level with the FIRST line. */
.mj-bd-shopcard-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin:0 0 6px;}
.mj-bd-shopcard-badge{flex-shrink:0;margin-left:auto;}
.mj-bd-noresult{font-family:'Fraunces', Georgia, serif;font-size:15px;color:rgba(61,43,31,0.68);text-align:center;margin:0;}

/* City page: one card per shop, full column width — never a shop's name, address
   and link split across three narrow columns that wrap mid-word. */
.mj-bd-shopcard{display:block;border:1px solid rgba(61,43,31,0.22);background:transparent;border-radius:2px;padding:clamp(18px,2.4vw,24px);text-decoration:none;color:#3D2B1F;margin:0 0 12px;box-sizing:border-box;width:100%;}
.mj-bd-shopcard:hover{border-color:#3D2B1F;}
.mj-bd-shopcard-name{display:block;font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-weight:700;font-size:clamp(1.15rem,2.4vw,1.4rem);line-height:1.2;margin:0;min-width:0;}
/* The meta line and Joe's stars share one row, his score pushed to the right edge
   by margin-left:auto so it lands there whether or not the shop has an address. The
   two are baseline-aligned, not centred, so the stars sit on the meta line's
   baseline rather than floating above a one-line meta and below a two-line one. */
.mj-bd-shopcard-subline{display:flex;align-items:baseline;justify-content:space-between;gap:12px;}
.mj-bd-shopcard-subline .mj-joes-rating{margin-left:auto;position:relative;top:2px;}
/* ONE meta line: street address, rating, review count, middot-separated. The
   address and the rating used to be two stacked lines of the same 14px grey, which
   read as a paragraph of small print under every name. */
.mj-bd-shopcard-meta{display:block;font-family:'Fraunces', Georgia, serif;font-size:14px;color:rgba(61,43,31,0.68);margin:0;min-width:0;}
.mj-bd-shopcard-drink{display:block;font-family:'Fraunces', Georgia, serif;font-size:14px;font-style:italic;color:rgba(61,43,31,0.68);margin:8px 0 0;}

/* ── Joe's picks, per state (/picks-by-state/:state) ──────────────────────
   A CARD, not a row. The page used to render each pick as a thin line with the
   Joe's Pick badge on the right — on a page where every shop is a pick, so the
   badge said nothing, and the review Joe actually wrote appeared nowhere. The
   review is the only thing that differs between two picks, so it is what the card
   is built around. The badge is gone from here (it stays on shop pages and on
   mixed lists, where it still carries information). */
/* align-items:start, NOT the grid's default stretch. A pick with no review text is
   a genuinely shorter card, and stretching it to match the one beside it turned the
   "no quote, no rule" case into exactly the empty block it was meant to avoid — a
   tall bordered box with a name at the top and a link at the bottom. Rows are
   allowed to be ragged; cards are not allowed to be hollow. */
/* NO align-items:start. That was the whole reason two cards in the same row stood
   at different heights — a grid item only stretches to the row's height under the
   default stretch, and start shrank each card to its own content, so a two-line
   quote beside a one-line quote drew one card visibly taller than its neighbour. The
   card is already flex-column with the "Read Joe's full review" link on margin-top:
   auto, so the extra height goes under the link, not into it. */
.mj-bd-pickgrid{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(14px,2vw,20px);list-style:none;padding:0;margin:0;}
@media(max-width:767px){.mj-bd-pickgrid{grid-template-columns:1fr;}}
.mj-bd-pickgrid > li{display:flex;}
/* The whole card is the link, so "Read Joe's full review" inside it is a span, not
   a nested anchor. margin-top:auto on that span pins it to the bottom edge, which
   is what keeps the row of links level across cards of different quote lengths. */
.mj-bd-pickcard{display:flex;flex-direction:column;flex:1 1 auto;background:#FCF7D9;border:1px solid rgba(61,43,31,0.22);border-radius:10px;padding:clamp(18px,2.4vw,24px);text-decoration:none;color:#3D2B1F;box-sizing:border-box;}
.mj-bd-pickcard:hover{border-color:#3D2B1F;}
.mj-bd-pickcard-city{font-family:'Fraunces', Georgia, serif;font-size:14px;font-weight:600;letter-spacing:0.18em;text-transform:uppercase;color:rgba(61,43,31,0.68);margin:0 0 6px;}
.mj-bd-pickcard-name{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-weight:700;font-size:clamp(1.15rem,2.2vw,1.35rem);line-height:1.2;margin:0;}
.mj-bd-pickcard-meta{display:flex;align-items:center;flex-wrap:wrap;gap:8px;font-family:'Fraunces', Georgia, serif;font-size:14px;color:rgba(61,43,31,0.68);margin:9px 0 0;}
.mj-bd-pickcard-drink{font-style:italic;}
.mj-bd-pickcard-rule{border:none;border-top:1px solid rgba(61,43,31,0.22);margin:16px 0;width:100%;}
.mj-bd-pickcard-quote{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-style:italic;font-size:16px;line-height:1.55;margin:0;}
.mj-bd-pickcard-link{font-family:'Fraunces', Georgia, serif;font-size:12px;font-weight:600;letter-spacing:0.05em;margin-top:auto;padding-top:18px;}

/* "More in <State>" — the closing link block. Script heading, then one row per
   link with its count hard right. Untilted, unlike the region headings on the hub:
   this one sits above a list whose rows it has to line up with. */
/* Playfair italic, not the Pinyon script. The script is the brand's display face and
   belongs on a page's own title; on a utility heading over two link rows it was
   larger and more decorative than the thing it introduced. Italic keeps it distinct
   from the row labels beneath without shouting. */
.mj-bd-morehead{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-style:italic;font-weight:700;font-size:clamp(1.35rem,2.6vw,1.7rem);line-height:1.15;color:#3D2B1F;margin:0 0 14px;}
.mj-bd-morelist{list-style:none;padding:0;margin:0;border-top:1px solid rgba(61,43,31,0.22);}
/* These are links and they were dressed as table rows: body weight, no underline, no
   arrow, and a hover that only dimmed them — which reads as going away, not as being
   clickable. The label is now bold, and the count carries the arrow every other
   "keep going" affordance on the site uses. The arrow is a CSS ::after on the count
   rather than markup so the React page and the server-rendered one cannot end up
   with different rows. */
.mj-bd-morerow{display:flex;align-items:baseline;justify-content:space-between;gap:16px;padding:14px 2px;border-bottom:1px solid rgba(61,43,31,0.22);font-family:'Fraunces', Georgia, serif;font-size:15px;color:#3D2B1F;text-decoration:none;}
/* Not bold. The block holds a single link out now, and a lone bold row read as a
   heading rather than as something to click. */
.mj-bd-morerow > span:first-child{font-weight:400;}
.mj-bd-morerow:hover > span:first-child,.mj-bd-morerow:focus-visible > span:first-child{text-decoration:underline;text-underline-offset:3px;}
.mj-bd-morerow-count{font-size:14px;color:rgba(61,43,31,0.68);white-space:nowrap;flex-shrink:0;transition:transform 160ms ease;}
.mj-bd-morerow-count::after{content:' →';}
.mj-bd-morerow:hover .mj-bd-morerow-count,.mj-bd-morerow:focus-visible .mj-bd-morerow-count{transform:translateX(3px);}
@media (prefers-reduced-motion:reduce){
  .mj-bd-morerow-count{transition:none;}
  .mj-bd-morerow:hover .mj-bd-morerow-count,.mj-bd-morerow:focus-visible .mj-bd-morerow-count{transform:none;}
}


  /* Footer — shared with the React footer (websiteFooter.ts). */
  
/* NOTHING BUT FOOTER BELOW THE FOOTER.
   On a page shorter than the viewport the footer ended partway down the screen and
   the rest was cream — a band of page background under a finished page, which reads
   as a rendering fault rather than as a design.
   THE FIX IS BACKGROUND PROPAGATION, not a layout change. With no background on
   <html>, the browser propagates <body>'s to the canvas, so cream painted the whole
   window however short the document was. Giving <html> the footer's own chocolate
   stops that propagation: <body> now paints only its own box, which ends at the
   footer, and everything below is chocolate — the footer, continued.
   It costs no flex wrapper, no min-height, and no change to how any page is built,
   and it is right at the top of the page too: overscrolling upward reveals the same
   chocolate the header is already painted in.
   WEBSITE ONLY BY CONSTRUCTION. This block ships with the footer, and the footer
   returns null in the installed app, so the app's own backgrounds are untouched. */
html{background:#3D2B1F;}
body{background:#FCF7D9;}
/* Website footer — single source (base44/shared/websiteFooter.ts). */
.mj-ft{width:100%;background:#3D2B1F;color:#FCF7D9;}
/* THE 32px OF AIR ABOVE THE FOOTER IS THE POINT. On a short page the footer's
   script wordmark landed a few pixels under the header's, and two Mocha Joe marks
   that close together read as one duplicated logo rather than as a header and a
   footer. Padding, not a margin, so it cannot collapse into whatever sits above. */
.mj-ft-inner{max-width:1200px;margin:0 auto;padding:40px 20px 28px;box-sizing:border-box;}
@media(max-width:767px){.mj-ft-inner{padding:32px 20px 24px;}}
.mj-ft-grid{display:grid;grid-template-columns:1fr;gap:28px;}
@media(min-width:768px){.mj-ft-grid{grid-template-columns:minmax(0,1fr) minmax(0,2fr);gap:48px;align-items:start;}}
/* THE WORDMARK, which is the one thing Great Vibes is for. Named through the
   constant rather than spelled out, so the gate can tell this apart from a
   headline that reached for the logo's face. */
.mj-ft-brand{font-family:'Great Vibes', 'Great Vibes Fallback', cursive;font-weight:400;color:#FCF7D9;font-size:2rem;line-height:1;margin:0;}
.mj-ft-tagline{font-family:'Fraunces',Georgia,serif;font-style:italic;color:#EBE3D5;font-size:1rem;line-height:1.5;margin:10px 0 0;max-width:20rem;opacity:0.85;}
/* TWO COLUMNS ON A PHONE, not one stack of twelve.
   Explore holds six links and spans both rows of the left column; Contribute and
   About sit stacked in the right one. Twelve links in a single column, each in a
   44px box, was a footer taller than most of the pages above it. */
.mj-ft-cols{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px;align-content:start;}
.mj-ft-cols > :nth-child(1){grid-column:1;grid-row:1 / span 2;}
.mj-ft-cols > :nth-child(2){grid-column:2;grid-row:1;}
.mj-ft-cols > :nth-child(3){grid-column:2;grid-row:2;}
/* Above 768px nothing about the desktop footer changes: three equal columns, each
   its own grid cell, exactly as before. */
@media(min-width:768px){
  .mj-ft-cols{grid-template-columns:repeat(3,minmax(0,1fr));gap:24px;}
  .mj-ft-cols > :nth-child(1),
  .mj-ft-cols > :nth-child(2),
  .mj-ft-cols > :nth-child(3){grid-column:auto;grid-row:auto;}
}
.mj-ft-heading{font-family:'Fraunces',Georgia,serif;font-weight:700;color:#FCF7D9;font-size:0.7rem;letter-spacing:0.16em;text-transform:uppercase;margin:0 0 12px;opacity:0.85;}
/* 10px group labels on a phone, in the muted tone rather than full cream: they
   are labels over the links, not links themselves. */
@media(max-width:767px){.mj-ft-heading{font-size:10px;color:#EBE3D5;opacity:0.7;margin:0 0 6px;}}
.mj-ft-col{display:flex;flex-direction:column;}
/* EVERY LINK IDENTICAL, and none of them underlined at rest. The underline is a
   hover affordance only; nothing here marks one link out from the others.

   THE ROW IS 44px BELOW 768px, WHERE THE FINGER IS. It used to be 37px there:
   14.5px of type at 1.6, plus 7px of padding either side, with min-height:unset
   cancelling the 44px floor in the rule above. Eleven links appear in this footer on
   all thirteen page types, so that one cancellation was 143 undersized targets. The
   height comes back as a box around the type; no font size moves. The phone footer
   stands 43px taller for it, which is the cost of the target and is paid in the one
   place on the page with room for it.

   ABOVE 768px IT STAYS COMPACT, deliberately. Measured: taking the desktop footer to
   44px rows as well grew it from 296px to 451px, half again as tall, to serve a
   pointer that hits a 23px row without trying. 44px is a finger measurement, and
   this is the line the server-rendered pages already draw in siteCss.ts, where the
   shop page's touch targets are scoped to this same breakpoint under a comment that
   says the same thing: nothing changes above it, where the pointer is. */
.mj-ft-link{color:#FCF7D9;font-family:'Fraunces',Georgia,serif;font-size:0.9rem;line-height:1.6;opacity:0.82;text-decoration:none;display:inline-flex;align-items:center;min-height:44px;transition:opacity .15s ease,color .15s ease;}
/* BLOCK LINKS WITH REAL PADDING, not a tall line-box. line-height 2.05 put the
   air inside the line, which sets the text loose in its own row; 1.6 with 7px of
   padding either side puts the same height around it instead, and the row reads
   tight while the tap target stays generous. */
@media(max-width:767px){.mj-ft-link{font-size:14.5px;line-height:1.6;min-height:44px;display:flex;align-items:center;padding:0;}}
@media(min-width:768px){.mj-ft-link{display:inline-block;min-height:0;}}
.mj-ft-link,.mj-ft-link:visited{text-decoration:none;}
.mj-ft-link:hover{opacity:1;text-decoration:underline;}
.mj-ft-bottom{border-top:1px solid rgba(245,239,230,0.12);margin-top:32px;padding-top:18px;display:flex;justify-content:center;align-items:center;flex-wrap:wrap;font-family:'Fraunces',Georgia,serif;font-size:0.78rem;color:#EBE3D5;opacity:0.7;}
/* THE LEGAL ROW, on a phone: copyright left, Privacy and Terms right, no rule
   above it. Separation is the 20px of space, which is the rule for this whole
   breakpoint. It wraps to two lines when the two halves cannot share one. */
@media(max-width:767px){
  .mj-ft-bottom{border-top:none;margin-top:20px;padding-top:0;justify-content:space-between;gap:6px 12px;font-size:11.5px;}
  .mj-ft-bottom .mj-ft-legal{gap:16px;}
}
/* Terms and Privacy were 16px tall — the two smallest targets on every page on
   the site. Same treatment as the column links, and the same breakpoint: box rather
   than type below 768px, unchanged above it. */
.mj-ft-bottom a{color:#EBE3D5;text-decoration:none;display:inline-flex;align-items:center;min-height:44px;}
@media(min-width:768px){.mj-ft-bottom a{display:inline;min-height:0;}}
.mj-ft-bottom a:hover{text-decoration:underline;}
/* SPACE, NOT A SYMBOL. The legal row read "© 2026 Mocha Joe · Terms · Privacy",
   and the middot was doing a job a gap does better: it is not read out usefully by
   a screen reader, it is one more mark in a row of three short words, and there is
   no symbol separator anywhere else on the website now. The rule that styled it is
   kept as the gap that replaced it. */
.mj-ft-legal{display:inline-flex;align-items:center;gap:22px;margin-left:22px;}

  
/* Joe's Picks Across States — single source (base44/shared/websitePickStars.ts). */
.mj-ps{width:100%;background:#FCF7D9;padding:clamp(44px,7vw,80px) 0 clamp(52px,8vw,92px);}
/* The heading keeps a readable measure; the star field's measure is DERIVED from the
   stamp: four stamps plus the three gaps between them, plus this padding. That is
   what pins the layout at four per row — widen it and a fifth creeps in, narrow it
   and the fourth drops to the next line. */
.mj-ps-head{max-width:720px;margin:0 auto;padding:0 16px;text-align:center;box-sizing:border-box;}
.mj-ps-inner{max-width:1166px;margin:0 auto;padding:0 16px;text-align:center;box-sizing:border-box;}
.mj-ps-eyebrow{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:0.22em;color:#8A6E52;margin:0;}
.mj-ps-title{margin:14px 0 0;line-height:1.2;}
.mj-ps-title-serif{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:900;color:#3B2A1E;font-size:clamp(1.9rem,5.2vw,2.9rem);letter-spacing:-0.01em;}
/* ONE ROW. The script word used to be rotated -5deg and pulled 0.2em up off the
   serif line's baseline, so "States" sat above and askew of "Joe's Picks Across" and
   the heading read as two half-lines. It now sits inline on the same baseline, in
   the same script face at the same size — only the tilt and the lift are gone.
   The title's line-height carries the script's taller ascenders. */
.mj-ps-title-script{display:inline;font-family:'Pinyon Script', 'Pinyon Script Fallback', cursive;color:#3B2A1E;font-size:clamp(2.6rem,7vw,4rem);margin-left:0.06em;}
.mj-ps-subline{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-size:15px;color:#8A6E52;margin:16px 0 0;}

/* Centred wrap, NOT a grid. Four per row comes from the measure above rather than
   from grid-template-columns, and the difference shows on the last row: a grid would
   park a trailing row of three in columns 1-3 and leave a hole on the right, where a
   centred wrap centres it under the rows above. The stamps do not tilt, so with equal
   boxes and equal gaps the columns still line up. */
.mj-ps-field{display:flex;flex-wrap:wrap;justify-content:center;align-items:flex-start;column-gap:18px;row-gap:30px;margin:clamp(30px,5vw,46px) auto 0;}
.mj-ps-stamp{display:block;text-decoration:none;line-height:0;flex:0 0 auto;}
/* Hover lightens the outline rather than fading the whole stamp, so the text stays
   at full contrast while the shape signals it is a control. */
.mj-ps-stamp .mj-ps-svg path{transition:stroke .15s ease;}
.mj-ps-stamp:hover{text-decoration:none;}
.mj-ps-stamp:hover .mj-ps-svg path{stroke:#A98A66;}
.mj-ps-svg{display:block;width:270px;max-width:100%;height:auto;overflow:visible;}
/* LINING figures for the count. Playfair Display's defaults are old-style — 6 and 8
   tall, 3/4/5/7/9 hanging below the baseline — so "8" and "9" in a two-digit count
   sat at visibly different heights. The baselines above are spaced to survive this
   rule being ignored; this is what makes the numerals line up when it is not. */
.mj-ps-count{font-variant-numeric:lining-nums;font-feature-settings:'lnum' 1;}

/* Below 768px the stamps step down so the set is not a long scroll, and the field
   stays at least two across at every phone width — never one per row. */
@media(max-width:767px){
  .mj-ps-field{column-gap:2px;row-gap:12px;}
  .mj-ps-svg{width:min(43vw,205px);}
}

  
/* Joe's Pick badge — single source (base44/shared/websitePickBadge.ts). */
.mj-pick-badge{display:inline-flex;align-items:center;gap:5px;background:transparent;border:1px solid #B08A3E;color:#7A5D28;border-radius:999px;padding:3px 12px;font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-weight:700;font-size:10px;text-transform:uppercase;letter-spacing:0.14em;line-height:1.1;white-space:nowrap;vertical-align:middle;box-sizing:border-box;}
/* No shadow. A warm glow under a hairline pill was the last of the gold badge's
   furniture; the outline is the whole mark now. */
.mj-pick-badge-star{display:block;flex-shrink:0;}
/* The badge sits inline beside the shop name, not in the meta row where it read as
   one more piece of grey caps. */
/* On a list card the pill is smaller so it never outweighs the shop name. The label
   cannot go below 10px and stay legible in caps at .14em, so the small variant gives
   back padding rather than type size. */
.mj-pick-badge--sm{gap:4px;padding:2px 9px;}
/* THE SAME PILL, INVERTED, for the one place it sits on a dark field: the collection
   grid card, where it lies over a photo under a chocolate scrim. Cocoa on that scrim
   is 1.59:1 — a pill you have to already know is there. Cream is 12.7:1. Nothing else
   changes: same shape, same weight, same star, so it is still one badge and not two.
   BRASS IS NOT USED HERE. On that scrim it measures 4.19:1 — under the 4.5 a label
   needs — where cream is 12.7:1. This is the one inversion, and it is a legibility
   floor rather than a second design. */
.mj-pick-badge--dark{border-color:#FCF7D9;color:#FCF7D9;}
.mj-pick-badge--dark .mj-pick-badge-star path{fill:#FCF7D9;}
.mj-pick-star{display:block;flex-shrink:0;}

  
.mj-star{display:block;flex-shrink:0;}
.mj-stars{display:inline-flex;align-items:center;gap:2px;vertical-align:middle;}

  
/* Joe's star rating. Single source (base44/shared/websiteJoesRating.ts). */
.mj-joes-rating{display:inline-flex;align-items:center;flex-shrink:0;line-height:1;vertical-align:middle;}
.mj-joes-rating svg{display:block;}

  
/* Opening hours block. Single source (base44/shared/websiteHours.ts). */
.mj-hours{display:block;}
.mj-hours-row{display:flex;align-items:baseline;gap:10px;line-height:1.6;}
.mj-hours-day{flex:0 0 auto;min-width:4.4em;font-variant-numeric:tabular-nums;}
.mj-hours-val{min-width:0;font-variant-numeric:tabular-nums;}
.mj-hours-raw{display:block;line-height:1.6;}

  
/* About. Single source (base44/shared/websiteAbout.ts). No band, no fill, no rule:
   every separation on this page is space. */
.mj-ab{width:100%;background:#FCF7D9;}

/* ── 1. HERO ────────────────────────────────────────────────────────────────
   A relative box the corner blocks are pinned into above 900px. The headline and
   the photo are the only things in normal flow, so with no photo the section is
   simply shorter — nothing reserves its space. */
.mj-ab-hero{position:relative;padding:clamp(28px,4vw,44px) 20px 0;}
.mj-ab-hero-in{max-width:1120px;margin:0 auto;position:relative;text-align:center;}

.mj-ab-h1{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:900;color:#3B2A1E;
  font-size:clamp(2.6rem,9vw,76px);line-height:0.95;letter-spacing:-0.01em;margin:0;}
/* The serif halves are uppercased HERE, not in the copy, so the accessible text
   stays the sentence "Hi, I'm Joe". */
.mj-ab-h1-serif{text-transform:uppercase;}
.mj-ab-h1-script{font-family:'Pinyon Script', 'Pinyon Script Fallback', cursive;font-weight:400;
  font-size:clamp(2.8rem,9.7vw,82px);text-transform:none;letter-spacing:0;}
/* Wraps after "HI," on a narrow screen. */
@media(max-width:699px){.mj-ab-h1-serif:first-child{display:block;}}

/* 280px square, top corners only, sitting 6px up into the headline's baseline and
   flush with the bottom of the section. */
.mj-ab-photo{display:block;width:280px;height:280px;object-fit:cover;
  margin:-6px auto 0;border-radius:8px 8px 0 0;}
@media(max-width:479px){.mj-ab-photo{width:min(280px,78vw);height:min(280px,78vw);}}

/* ── THE HERO META ──
   One line under the headline, centred with it, because it is a caption on a
   wordmark rather than something to read. What was here before was four blocks
   pinned to the corners of a photo that does not exist: above 900px they pointed
   at nothing and below it they stacked into a two-by-two grid of ragged capitals.
   The arrows went with them; an arrow needs something to point at. */
.mj-ab-meta{font-family:'Fraunces',Georgia,serif;font-size:13px;text-transform:uppercase;
  letter-spacing:0.16em;font-weight:600;color:#8A6E52;line-height:1.6;
  margin:22px auto 0;max-width:640px;text-wrap:balance;}

/* ── 2. INTRO ───────────────────────────────────────────────────────────── */
/* LEFT, NOT CENTRED. Four paragraphs of 16.5px prose on a 660px measure were set
   centred, which gives every line a different starting point and makes the reader
   find the left edge again on each one. Centring is for a line or two of display
   copy; this is the part of the page people actually read. The h2 goes left with
   it so the block has one edge rather than a centred heading over a left column. */
.mj-ab-intro{max-width:660px;margin:0 auto;padding:46px 20px 0;text-align:left;}
.mj-ab-h2{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:700;color:#3B2A1E;
  font-size:clamp(1.55rem,4.2vw,32px);line-height:1.15;margin:0;text-wrap:balance;}
.mj-ab-intro p{font-family:'Fraunces',Georgia,serif;color:#4A3728;font-size:16.5px;
  line-height:1.75;margin:0;text-wrap:pretty;}
.mj-ab-intro p:first-of-type{margin-top:16px;}
.mj-ab-intro p + p{margin-top:14px;}

/* ── 3. DIVIDER ─────────────────────────────────────────────────────────────
   Full bleed, nowrap, pulled left so the first word is cut off by the viewport
   edge. No fill and no rotation: the crop IS the effect. */
.mj-ab-divider{margin:52px 0 0;overflow:hidden;white-space:nowrap;}
.mj-ab-divider span{display:inline-block;margin-left:-60px;
  font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:900;color:#3B2A1E;
  font-size:92px;line-height:1;letter-spacing:-0.015em;text-transform:uppercase;}
@media(max-width:899px){.mj-ab-divider span{font-size:60px;margin-left:-40px;}}
@media(max-width:599px){.mj-ab-divider span{font-size:40px;margin-left:-26px;}}

/* ── 4. METHOD ──────────────────────────────────────────────────────────── */
.mj-ab-method{max-width:900px;margin:0 auto;padding:32px 20px 0;
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:30px 40px;}
@media(max-width:699px){.mj-ab-method{grid-template-columns:minmax(0,1fr);}}
.mj-ab-m-label{font-family:'Fraunces',Georgia,serif;font-size:12px;font-weight:600;
  text-transform:uppercase;letter-spacing:0.18em;color:#7A5D28;margin:0;}
.mj-ab-m-body{font-family:'Fraunces',Georgia,serif;color:#4A3728;font-size:16px;
  line-height:1.7;margin:8px 0 0;}

/* ── 5. CLOSE ───────────────────────────────────────────────────────────── */
.mj-ab-close{max-width:660px;margin:0 auto;padding:64px 20px 48px;text-align:center;}
.mj-ab-sign{font-family:'Pinyon Script', 'Pinyon Script Fallback', cursive;color:#3B2A1E;font-size:42px;
  line-height:1.15;margin:0;}
.mj-ab-role{font-family:'Fraunces',Georgia,serif;font-size:14px;text-transform:uppercase;
  letter-spacing:0.16em;font-weight:600;color:#8A6E52;margin:8px 0 0;}
.mj-ab-links{display:flex;justify-content:center;align-items:center;flex-wrap:wrap;
  gap:30px;margin:34px 0 0;}
.mj-ab-links a{font-family:'Fraunces',Georgia,serif;font-size:15px;color:#3B2A1E;
  text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px;
  display:inline-flex;align-items:center;gap:6px;}
@media(max-width:599px){.mj-ab-links{flex-direction:column;gap:18px;}}

  
/* For Coffee Shops. Single source (base44/shared/websiteForShops.ts). */
.mj-fs{width:100%;background:#FCF7D9;color:#4A3728;
  font-family:'Fraunces',Georgia,serif;}
.mj-fs-in{max-width:1080px;margin:0 auto;padding:0 20px;}

.mj-fs-eyebrow{font-size:12px;text-transform:uppercase;letter-spacing:0.18em;
  font-weight:600;color:#8A6E52;margin:0 0 14px;}

/* ── HERO ──
   OFF CENTRE. It was a centred stack: eyebrow, headline, subtitle, finder, each
   one narrower than the last down the middle of the page. That shape is what
   reads as a template, and it also buried the one control the page exists for
   under three paragraphs of introduction.
   Two columns above 900px: the lockup holds the left, the finder is the object on
   the right. Below that they stack, still left-aligned, finder first after the
   copy. NO ROTATION anywhere on this page — tilted cards came off the crawls page
   in August for reading as scrapbook rather than editorial, and the stagger and
   the alternating fills below do that job without it. */
.mj-fs-hero{padding:clamp(28px,4vw,52px) 0 clamp(28px,4vw,44px);text-align:left;}
.mj-fs-hero-grid{display:grid;grid-template-columns:1fr;gap:34px;align-items:start;}
@media(min-width:900px){
  .mj-fs-hero-grid{grid-template-columns:minmax(0,1.02fr) minmax(0,0.98fr);gap:56px;
    align-items:center;}
}
.mj-fs-hero-rule{width:96px;height:1px;background:#D9C9A8;margin:26px 0 0;}
.mj-fs-h1{margin:0;color:#3B2A1E;line-height:1.04;}
.mj-fs-h1-serif{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:900;
  font-size:clamp(2rem,6.4vw,54px);letter-spacing:-0.01em;}
.mj-fs-h1-script{font-family:'Pinyon Script', 'Pinyon Script Fallback', cursive;font-weight:400;
  font-size:clamp(2.3rem,7.2vw,62px);}
.mj-fs-sub{max-width:470px;margin:22px 0 0;font-size:16px;line-height:1.7;
  color:#4A3728;}

/* THE FINDER. Rendered as a placeholder in both surfaces and filled by a script on
   the server page and by a React component in the SPA. It is allowed to be empty:
   with no JS the page still reads, and the closing links reach the same places. */
/* THE FINDER IS THE HERO OBJECT, so it is framed like one: the double hairline
   the crawl page already uses on its winner card, an ink rule outside and a
   rule-tone rule 7px inside it. Both surfaces render this class — the server
   emits the markup and the React route portals its own component into the same
   slot — so the frame lands on both without either knowing about the other. */
/* THE INSET IS PADDING ON THE FRAME, NOT MARGIN ON THE CHILDREN. A child-margin
   rule looked equivalent and was not: .mj-fs-results sets its own margin of
   10px 0 0 at the same specificity and later in the sheet, so the results list
   alone would have broken out to the frame edge while every sibling stayed inset.
   33px = the 7px to the inner hairline plus 26px inside it.
   (And the comment above nearly broke the build a second way: backticks in here
   end the template literal, which is what the note at the top of this CSS block
   has been warning about since the last two times it happened.) */
.mj-fs-finder{margin:0;text-align:left;position:relative;
  border:1px solid #3B2A1E;padding:33px 33px 31px;background:#FCF7D9;}
.mj-fs-finder::before{content:'';position:absolute;inset:7px;border:1px solid #D9C9A8;
  pointer-events:none;}
.mj-fs-finder label{display:block;font-size:11px;text-transform:uppercase;
  letter-spacing:0.2em;font-weight:600;color:#8A6E52;margin:0 0 14px;}
/* Playfair at 25px, not Fraunces at 17: this input is the page's headline act and
   it is set like one. The bottom rule is ink rather than rule-tone for the same
   reason — an empty field has to read as the thing to use. */
.mj-fs-finder input{width:100%;box-sizing:border-box;background:transparent;
  border:0;border-bottom:1px solid #3B2A1E;padding:8px 0 12px;font-size:25px;
  font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;
  color:#3B2A1E;outline:none;}
.mj-fs-finder input:focus{border-bottom-color:#3B2A1E;}
.mj-fs-finder input::placeholder{color:#8A6E52;opacity:1;}

/* THE CHIT AND THE SEAL, FLAT. Both were tilted in the mockup and both survive
   without it: the chit reads as a filing tag above the frame and the seal as a
   stamp on its corner. Neither is load-bearing — each is one element and can go. */
.mj-fs-chit{display:inline-block;background:#F5EDCE;border:1px solid #D9C9A8;
  padding:7px 14px;margin:0 0 -1px;font-size:11px;text-transform:uppercase;
  letter-spacing:0.18em;font-weight:600;color:#8A6E52;}
.mj-fs-seal{position:absolute;right:-18px;bottom:-18px;width:64px;height:64px;
  border:1px solid #D9C9A8;border-radius:50%;background:#FCF7D9;
  display:flex;align-items:center;justify-content:center;}
@media(max-width:899px){.mj-fs-seal{display:none;}}

/* THE MARQUEE. Full bleed, nowrap, pulled left so the first word is cut by the
   viewport edge. The crop IS the effect, which is why there is no fade and no
   animation: this is the About page's divider treatment, reused so the two pages
   read as one site. aria-hidden, because it is texture and a screen reader
   announcing "Claim Your Shop" six times is noise. */
.mj-fs-marquee{margin:0;overflow:hidden;white-space:nowrap;
  border-top:1px solid #D9C9A8;border-bottom:1px solid #D9C9A8;padding:14px 0;}
.mj-fs-marquee span{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;
  font-weight:900;color:#3B2A1E;font-size:clamp(1.9rem,6vw,58px);
  letter-spacing:-0.01em;margin-left:-0.4em;}
.mj-fs-hint{font-size:12px;color:#8A6E52;margin:8px 0 0;}
.mj-fs-results{list-style:none;margin:10px 0 0;padding:0;}
.mj-fs-results li{border-bottom:1px solid #D9C9A8;}
.mj-fs-results a{display:block;padding:11px 2px;text-decoration:none;color:#3B2A1E;}
.mj-fs-results a:hover,.mj-fs-results a:focus{background:#F5EDCE;}
.mj-fs-r-name{display:block;font-weight:700;font-size:15px;}
.mj-fs-r-sub{display:block;font-size:12px;color:#8A6E52;margin-top:2px;}

/* STEPS */
.mj-fs-sec{padding:clamp(30px,4vw,54px) 0;}
.mj-fs-h2{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:900;
  color:#3B2A1E;font-size:clamp(1.5rem,3.6vw,32px);line-height:1.12;margin:0 0 6px;}
.mj-fs-lede{font-size:15px;line-height:1.6;color:#8A6E52;margin:0 0 26px;max-width:640px;}
/* THREE CARDS, NOT THREE COLUMNS OF TEXT. They were bare divs in a grid, which is
   the most templated shape a three-up can take. Now each is a bordered card, the
   fills alternate deep cream and cream, and the middle one is outlined in ink and
   sits 34px lower than its neighbours.
   THE STAGGER IS THE WHOLE EFFECT, and it is margin, not rotation. It only applies
   where there are three columns to stagger; stacked on a phone the offsets would
   just be uneven gaps, so they are dropped there. */
.mj-fs-steps{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:26px;
  align-items:start;}
@media(max-width:767px){.mj-fs-steps{grid-template-columns:1fr;gap:22px;}}
.mj-fs-step{border:1px solid #D9C9A8;background:#F5EDCE;
  padding:28px 26px 30px;}
.mj-fs-step--2{background:#FCF7D9;border-color:#3B2A1E;}
@media(min-width:768px){
  .mj-fs-step--2{margin-top:34px;}
  .mj-fs-step--3{margin-top:12px;}
}
.mj-fs-step-n{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:900;
  font-size:42px;line-height:1;letter-spacing:0;color:#D9C9A8;margin:0 0 14px;}
.mj-fs-step-l{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:700;
  color:#3B2A1E;font-size:22px;margin:0 0 10px;}
.mj-fs-step-b{font-size:14px;line-height:1.65;margin:0;}

/* PLANS */
.mj-fs-plans{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px;
  align-items:start;}
@media(max-width:899px){.mj-fs-plans{grid-template-columns:1fr;}}
/* THE MIDDLE CARD LIFTS AND TAKES THE BRASS. Three equal boxes side by side make
   the reader compare by reading; one raised card in a different metal makes the
   recommendation before they start. Brass is not a new colour: it is the crawl
   page's winner marker and the pick badge's darker edge, which is exactly what it
   means here too. The lift is margin on the OUTER two, so the middle card keeps
   its place in the grid and nothing overlaps at a narrow width. */
.mj-fs-plan{border:1px solid #D9C9A8;border-radius:0;padding:26px 24px;
  background:#FCF7D9;}
.mj-fs-plan--rec{border-color:#B08A3E;background:#F5EDCE;
  padding:32px 24px;position:relative;}
@media(min-width:900px){
  .mj-fs-plans > .mj-fs-plan:not(.mj-fs-plan--rec){margin-top:26px;}
}
/* The tag sits ON the brass edge rather than inside the padding, so the card is
   labelled the way a stamped one is. */
.mj-fs-plan-tag{position:absolute;top:-11px;left:24px;background:#B08A3E;
  color:#FCF7D9;font-size:10px;text-transform:uppercase;letter-spacing:0.18em;
  font-weight:600;padding:5px 12px;margin:0;}
.mj-fs-plan-n{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:900;
  color:#3B2A1E;font-size:22px;margin:0;}
.mj-fs-plan-p{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:700;
  color:#3B2A1E;font-size:17px;margin:10px 0 2px;}
.mj-fs-plan-pn{font-size:12px;color:#8A6E52;margin:0 0 14px;}
.mj-fs-plan-bl{font-size:14px;line-height:1.6;margin:0 0 14px;color:#4A3728;}
.mj-fs-plan ul{list-style:none;margin:0;padding:0;}
.mj-fs-plan li{font-size:13.5px;line-height:1.55;padding:7px 0 7px 16px;
  position:relative;border-top:1px solid #D9C9A8;}
.mj-fs-plan li:before{content:'';position:absolute;left:0;top:14px;width:6px;
  height:1.5px;background:#8A6E52;}
.mj-fs-plan-cta{display:block;margin-top:18px;text-align:center;text-decoration:none;
  border:1.5px solid #3B2A1E;border-radius:3px;padding:10px 14px;font-size:13px;
  font-weight:700;letter-spacing:0.04em;text-transform:uppercase;color:#3B2A1E;}
.mj-fs-plan-cta:hover,.mj-fs-plan-cta:focus{background:#3B2A1E;color:#FCF7D9;}

/* TABLE */
.mj-fs-table-wrap{overflow-x:auto;}
.mj-fs-table{width:100%;border-collapse:collapse;min-width:560px;}
.mj-fs-table th,.mj-fs-table td{text-align:left;padding:12px 14px;
  border-bottom:1px solid #D9C9A8;font-size:13.5px;line-height:1.5;}
.mj-fs-table th{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:900;
  color:#3B2A1E;font-size:13px;text-transform:uppercase;letter-spacing:0.1em;}
.mj-fs-table td:first-child{font-weight:700;color:#3B2A1E;}
.mj-fs-note{font-size:13px;line-height:1.6;color:#8A6E52;margin:16px 0 0;
  max-width:720px;}

/* THE FAQ. The question rule's SELECTOR AND OPENING BRACE were lost to an edit.
   The file held a stray comment followed by a bare declaration list closed by a
   single brace, with nothing opening it. Two consequences, both silent: the dt
   questions on this page had no styling at all and fell back to the browser's,
   and the unmatched closing brace drove the stylesheet's brace depth negative,
   which broke criticalCssFor for EVERY rule after it in the sheet.
   scripts/check-css.mjs now fails on an unbalanced sheet. */
.mj-fs-faq dt{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:900;
  color:#3B2A1E;font-size:16px;margin:0 0 6px;}
.mj-fs-faq dd{margin:0 0 22px;font-size:14px;line-height:1.65;}

/* CLOSE */
/* ── THE CLOSE IS THE DARK STOP ──
   The page had none once the Joe's Picks band was removed, and a page that runs
   cream from the header to the footer has no rhythm at all. Rather than adding a
   band back, the section that was already last takes the chocolate: it is the one
   place where a reader has finished deciding, so it is the right place to be loud.
   FULL BLEED, and it runs straight into the footer, which is the same chocolate.
   That is deliberate: there is no seam between them because there is no edge to
   mark, and the bottom padding is what keeps the close from reading as the
   footer's first row. */
.mj-fs-close{background:#3D2B1F;text-align:center;
  padding:clamp(44px,5vw,72px) 20px clamp(52px,6vw,84px);}
.mj-fs-close .mj-fs-h2{color:#FCF7D9;}
.mj-fs-close p{max-width:520px;margin:14px auto 0;font-size:15.5px;line-height:1.7;
  color:#EBE3D5;}
/* The promise, in the pick's own gold and a size above the line before it. Playfair
   italic because it is a sentence somebody means, not a caption. */
.mj-fs-close .mj-fs-promise{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;
  font-style:italic;font-size:clamp(1.1rem,2.4vw,21px);line-height:1.4;
  color:#F2D06B;margin:22px auto 0;max-width:520px;}
.mj-fs-links{display:flex;flex-wrap:wrap;gap:10px 26px;justify-content:center;
  margin-top:30px;}
.mj-fs-links a{font-size:14px;font-weight:700;color:#FCF7D9;text-decoration:none;
  border-bottom:1px solid rgba(252,247,217,0.45);padding-bottom:3px;}
.mj-fs-links a:hover,.mj-fs-links a:focus{border-bottom-color:#FCF7D9;}

  
/* Paid placement block. Single source (base44/shared/websitePaidBlock.ts). */
.mj-pp{margin:0 0 26px;font-family:'Fraunces',Georgia,serif;}
.mj-pp-head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;
  margin:0 0 4px;}
.mj-pp-h{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:900;
  color:#3B2A1E;font-size:13px;text-transform:uppercase;letter-spacing:0.12em;
  margin:0;}
/* The disclosure sits ON the heading line, not hidden at the bottom of the block.
   Measured rather than eyeballed: see PP_MUTED above. */
.mj-pp-disc{font-size:11px;letter-spacing:0.08em;text-transform:uppercase;
  color:#7A5F45;margin:0;}
.mj-pp-list{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;
  margin:12px 0 0;}
@media(max-width:767px){.mj-pp-list{grid-template-columns:1fr;}}
.mj-pp-card{display:block;text-decoration:none;background:#F5EDCE;
  border:1px solid #D9C9A8;border-radius:4px;padding:14px 16px;color:#3B2A1E;}
.mj-pp-card:hover,.mj-pp-card:focus{border-color:#3B2A1E;}
.mj-pp-top{display:flex;align-items:baseline;justify-content:space-between;gap:10px;}
.mj-pp-name{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:900;
  font-size:16px;line-height:1.2;}
/* The label. Text, always, and never only a colour. */
.mj-pp-tag{flex:0 0 auto;font-size:10px;text-transform:uppercase;
  letter-spacing:0.14em;font-weight:700;color:#7A5F45;white-space:nowrap;}
.mj-pp-sub{display:block;font-size:12.5px;color:#7A5F45;margin-top:4px;}
/* Its own line, so a pick badge can never crowd the paid label on a narrow card. */
.mj-pp-pick{display:block;margin-top:8px;}

  
/* The crawls hub. Single source (base44/shared/websiteOnTheRoad.ts). */
.mj-otr{width:100%;background:#33241A;color:#F4EAD0;font-family:'Fraunces',Georgia,serif;
  padding:0 0 clamp(48px,6vw,84px);}
.mj-otr-in{max-width:960px;margin:0 auto;padding:0 20px;}
.mj-otr a{color:inherit;text-decoration:none;}

/* ── HEADER. Everything in this block starts at the same left edge. ────── */
.mj-otr-head{padding:clamp(28px,4vw,46px) 0 0;}
.mj-otr-crumbs{font-size:11px;line-height:1.5;color:rgba(244,234,208,0.72);margin:0 0 18px;}
.mj-otr-crumbs a:hover{text-decoration:underline;}
.mj-otr-slash{padding:0 7px;opacity:0.6;}
.mj-otr-eyebrow{font-size:11px;font-weight:600;letter-spacing:0.2em;text-transform:uppercase;
  color:#E9A8A0;margin:0 0 12px;}
.mj-otr-h1{margin:0;line-height:1.02;}
.mj-otr-h1-serif{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:700;font-size:clamp(2rem,5.4vw,44px);
  letter-spacing:-0.01em;color:#F4EAD0;}
.mj-otr-h1-script{font-family:'Pinyon Script', 'Pinyon Script Fallback', cursive;font-weight:400;font-size:clamp(2.5rem,7vw,56px);
  color:#F4EAD0;}
.mj-otr-intro{max-width:600px;font-size:15px;line-height:1.7;color:rgba(244,234,208,0.72);
  margin:16px 0 0;}
.mj-otr-rule{height:1px;background:rgba(244,234,208,0.20);margin:26px 0 22px;}
.mj-otr-counts{display:flex;flex-wrap:wrap;gap:44px;margin:0;}
.mj-otr-count{display:block;}
.mj-otr-count-n{display:block;font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:700;font-size:28px;
  line-height:1;color:#F4EAD0;}
.mj-otr-count-l{display:block;font-size:10px;font-weight:600;letter-spacing:0.18em;
  text-transform:uppercase;color:rgba(244,234,208,0.72);margin-top:7px;}

/* ── SECTIONS ─────────────────────────────────────────────────────────── */
.mj-otr-sec{padding:clamp(34px,4.4vw,54px) 0 0;}
.mj-otr-sec-eyebrow{font-size:10px;font-weight:600;letter-spacing:0.18em;
  text-transform:uppercase;color:#E9A8A0;margin:0 0 8px;}
.mj-otr-sec-note{font-size:13px;line-height:1.6;color:rgba(244,234,208,0.72);margin:0 0 24px;}

/* ── THE ROUTE LINE ───────────────────────────────────────────────────────
   A 28px rail, an 11px rose dot per route, and a 1px rose line at 35% joining
   them. The line is drawn BELOW each dot and suppressed on the last entry, so it
   ends after the last route rather than trailing into the section below. */
.mj-otr-trip{display:flex;gap:0;align-items:stretch;}
.mj-otr-rail{display:block;position:relative;flex:0 0 28px;width:28px;}
.mj-otr-dot{display:block;position:absolute;left:8px;top:6px;width:11px;height:11px;border-radius:50%;
  background:#E9A8A0;}
.mj-otr-rail::before{content:'';position:absolute;left:13px;top:23px;bottom:0;width:1px;
  background:rgba(233,168,160,0.35);}
.mj-otr-trip:last-child .mj-otr-rail::before{display:none;}
.mj-otr-tripbody{flex:1 1 auto;min-width:0;display:flex;gap:28px;align-items:flex-start;
  padding:0 0 34px;}
.mj-otr-triptext{display:block;flex:1 1 auto;min-width:0;}
/* EVERY ONE OF THESE IS A <span> INSIDE THE ENTRY'S <a>, because an anchor may not
   contain block elements and the whole entry is one link. So each has to be told it
   is a block: without it the subtitle and the facts line ran together on one line,
   which is how the counts ended up mid-sentence rather than centred below. */
.mj-otr-tripname{display:block;font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:700;font-size:clamp(1.3rem,3vw,26px);
  line-height:1.2;color:#F4EAD0;margin:0;}
.mj-otr-trip:hover .mj-otr-tripname{text-decoration:underline;}
.mj-otr-span{display:block;font-size:12px;font-weight:600;letter-spacing:0.16em;
  text-transform:uppercase;color:#E9A8A0;margin:9px 0 0;}
.mj-otr-tripsub{display:block;max-width:540px;font-size:15px;line-height:1.75;color:rgba(244,234,208,0.72);
  margin:12px 0 0;}
.mj-otr-tripfacts{display:block;font-size:12px;line-height:1.6;color:rgba(244,234,208,0.72);margin:16px 0 0;
  text-align:center;}
.mj-otr-tripmedia{display:block;flex:0 0 210px;width:210px;}
.mj-otr-tripmedia img{display:block;width:100%;height:230px;object-fit:cover;}

/* ── CITY CRAWL CARDS ─────────────────────────────────────────────────── */
.mj-otr-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:14px;}
.mj-otr-card{display:block;border:1px solid rgba(244,234,208,0.20);padding:20px;}
.mj-otr-card:hover{border-color:#E9A8A0;}
.mj-otr-cardname{display:block;font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:700;font-size:20px;line-height:1.25;
  color:#F4EAD0;margin:0;}
.mj-otr-cardplace{display:block;font-size:12px;font-weight:600;letter-spacing:0.16em;
  text-transform:uppercase;color:#E9A8A0;margin:9px 0 0;}
.mj-otr-cardstops{display:block;font-size:12px;line-height:1.6;color:rgba(244,234,208,0.72);
  margin:7px 0 0;}

.mj-otr-empty{font-size:15px;line-height:1.6;color:rgba(244,234,208,0.72);margin:0;
  padding:clamp(34px,4.4vw,54px) 0 0;}

@media(max-width:719px){
  .mj-otr-counts{gap:28px;}
  .mj-otr-tripbody{flex-direction:column;gap:18px;}
  .mj-otr-tripmedia{flex:0 0 auto;width:100%;}
  .mj-otr-tripmedia img{height:200px;}
  .mj-otr-grid{grid-template-columns:1fr;}
}

  
/* Chips and dot-leader rows. Single source (base44/shared/websiteBands.ts). */
.mj-bd-sec{padding:clamp(24px,3vw,36px) 0 0;}
.mj-bd-sec-h{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-weight:900;color:#3D2B1F;
  font-size:13px;text-transform:uppercase;letter-spacing:0.16em;margin:0 0 14px;}
.mj-bd-chips{display:flex;flex-wrap:wrap;gap:8px;margin:0;padding:0;list-style:none;}
.mj-bd-chip{display:inline-flex;align-items:center;min-height:44px;padding:0 16px;
  border:1px solid rgba(61,43,31,0.22);border-radius:999px;text-decoration:none;
  font-family:'Fraunces', Georgia, serif;font-size:14px;color:#3D2B1F;background:transparent;}
.mj-bd-chip:hover,.mj-bd-chip:focus-visible{border-color:#3D2B1F;}
.mj-bd-chip-n{font-size:12px;color:rgba(61,43,31,0.68);margin-left:7px;}

/* A dot leader is a flexible middle, not a row of typed periods: the dots are a
   repeating background on a span that grows, so the two ends stay put at every
   width and nothing has to be measured. */
.mj-bd-dots{margin:0;padding:0;list-style:none;}
.mj-bd-dotrow{display:flex;align-items:baseline;gap:8px;min-height:44px;
  padding:6px 0;text-decoration:none;color:#3D2B1F;
  border-top:1px solid rgba(61,43,31,0.22);font-family:'Fraunces', Georgia, serif;}
.mj-bd-dots > li:first-child .mj-bd-dotrow{border-top:none;}
.mj-bd-dotrow:hover .mj-bd-dot-n,.mj-bd-dotrow:focus-visible .mj-bd-dot-n{text-decoration:underline;}
.mj-bd-dot-n{flex:0 1 auto;min-width:0;font-size:16px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;}
.mj-bd-dot-fill{flex:1 1 auto;min-width:12px;align-self:flex-end;height:1px;
  margin-bottom:5px;background-image:radial-gradient(circle,rgba(61,43,31,0.68) 1px,transparent 1px);
  background-size:5px 2px;background-repeat:repeat-x;background-position:bottom;}
.mj-bd-dot-v{flex:0 0 auto;font-size:13px;color:rgba(61,43,31,0.68);white-space:nowrap;}

  
/* The /states hero filter. Cream on chocolate, one rule, no box. */
.mj-bd-find{max-width:420px;margin:22px auto 0;}
.mj-bd-find-input{width:100%;box-sizing:border-box;background:transparent;border:0;
  border-bottom:1px solid rgba(252,247,217,0.32);padding:10px 2px;font-family:'Fraunces', Georgia, serif;
  font-size:16px;color:#FCF7D9;outline:none;min-height:44px;}
.mj-bd-find-input::placeholder{color:rgba(252,247,217,0.78);}
.mj-bd-find-input:focus{border-bottom-color:#FCF7D9;}

  
/* Coffee crawl. Single source (base44/shared/websiteCrawl.ts). */
.mj-cr2{width:100%;background:#FCF7D9;}

/* ── THE STRIPES. One gradient, used by the hero panel and by the band that
   closes the page. The cream card sits on top, so the stripes only show as a
   border of them around it. ── */
/* THE STRIPES ARE GONE. They wrapped the hero card and closed the page as a second
   awning, under the header's own, and two rows of teeth around one card read as
   noise rather than as chrome. THE BORDER STAYS: .mj-cr2-frame below is the double
   hairline around the card and it is what was actually doing the work.
   The class names are kept so both renderers keep their hooks, and the hero keeps
   its padding so the card does not go flush to the page edge. */
.mj-cr2-stripes{background:none;}
.mj-cr2-hero{padding:26px 22px;}
.mj-cr2-tail{height:0;}

/* THE DOUBLE FRAME, used by the hero card and the winner card: an outer ink
   hairline with 7px of cream inside it, then an inner rule-tone hairline. */
.mj-cr2-frame{border:1px solid #3B2A1E;padding:7px;background:#FCF7D9;}
/* container-type so the heading below can size against THIS CARD rather than the
   viewport. The card's width is what the heading actually has to fit inside, and
   it is not a fixed fraction of the viewport: .mj-cr2-route caps at 900px, so a
   vw-based size keeps growing after the card has stopped. */
.mj-cr2-frame-in{border:1px solid #E3D9BC;padding:30px 26px;text-align:center;container-type:inline-size;}
@media(max-width:899px){.mj-cr2-frame-in{padding:22px 18px;}}

/* ── THE HEADING IS ONE LINE, AND THE FACES ARE THE OTHER WAY ROUND ──
   It used to stack: "The Best Coffee in" in the script face on its own line, then
   the city in Playfair 900 below it. The lead phrase is the generic half and it
   was getting the decorative face and its own line; the tail is the half that
   changes per page and it was getting the workhorse face.
   Now: the lead is Playfair, the tail is the script, and they sit on one line.
   NEVER WRAPS, so the size steps down with the viewport rather than breaking. The
   two clamps are kept in proportion, and the script runs larger because Great
   Vibes has a much smaller x-height than Playfair at the same pixel size. */
.mj-cr2-h1{margin:0;white-space:nowrap;}
.mj-cr2-script{font-family:'Pinyon Script', 'Pinyon Script Fallback', cursive;color:#3B2A1E;
  font-size:min(4.1cqi,44px);line-height:1.15;display:inline;}
.mj-cr2-display{display:inline;font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:900;
  color:#3B2A1E;font-size:min(3.17cqi,34px);line-height:1.15;letter-spacing:0.01em;
  margin-right:0.26em;}
.mj-cr2-meta{font-family:'Fraunces',Georgia,serif;font-size:14px;text-transform:uppercase;
  letter-spacing:0.2em;font-weight:600;color:#8A6E52;margin:14px 0 0;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;}
.mj-cr2-intro{font-family:'Fraunces',Georgia,serif;font-size:16px;line-height:1.65;color:#4A3728;
  max-width:600px;margin:16px auto 0;}
@media(max-width:899px){.mj-cr2-intro{max-width:none;}}

/* ── 2. WINNER ── heading on ONE line: the label in display, the crawl's name in
   the script face. ── */
.mj-cr2-winner-head{text-align:center;margin:36px 0 14px;padding:0 20px;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;}
/* THE SAME ORDER AS THE HERO, so the page has one heading idea rather than two.
   Playfair lead, script name. It used to be script lead then the city in Playfair
   caps, which put a small-caps shout in the middle of an editorial line. */
.mj-cr2-winner-head .mj-cr2-display{display:inline;font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;
  font-weight:900;font-size:clamp(15px,2.1vw,26px);letter-spacing:0.01em;color:#3B2A1E;
  margin-right:0.26em;}
.mj-cr2-winner-city{font-family:'Pinyon Script', 'Pinyon Script Fallback', cursive;font-size:clamp(20px,2.7vw,34px);
  line-height:1.15;color:#3B2A1E;}
.mj-cr2-winner{max-width:640px;margin:0 auto;padding:0 20px;}
.mj-cr2-winner .mj-cr2-frame-in{padding:28px 26px;}
.mj-cr2-winner-name{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:700;font-size:36px;
  line-height:1.15;color:#3B2A1E;margin:0;}
@media(max-width:599px){.mj-cr2-winner-name{font-size:28px;}}
.mj-cr2-winner-addr{font-family:'Fraunces',Georgia,serif;font-size:11px;text-transform:uppercase;
  letter-spacing:0.16em;font-weight:600;color:#8A6E52;margin:7px 0 0;}
.mj-cr2-winner-link{display:inline-block;margin:16px 0 0;font-family:'Fraunces',Georgia,serif;
  font-size:15px;color:#3B2A1E;text-decoration:underline;text-decoration-thickness:1px;
  text-underline-offset:3px;}

/* ── 3. STOPS ── thin lined boxes, no heading, no fill, no radius. ── */
.mj-cr2-stops{max-width:640px;margin:32px auto 0;padding:0 20px;}
.mj-cr2-stop{display:flex;align-items:center;gap:14px;border:1px solid #E3D9BC;
  padding:16px 18px;margin:10px 0 0;text-decoration:none;transition:border-color .15s ease;}
.mj-cr2-stop:first-child{margin-top:0;}
.mj-cr2-stop:hover{border-color:#3B2A1E;}
.mj-cr2-stop:hover .mj-cr2-stop-arrow{color:#3B2A1E;}
.mj-cr2-stop-body{flex:1;min-width:0;}
.mj-cr2-stop-n{font-family:'Fraunces',Georgia,serif;font-size:14px;text-transform:uppercase;
  letter-spacing:0.2em;font-weight:600;color:#8A6E52;margin:0;}
.mj-cr2-stop-name{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:700;font-size:23px;
  line-height:1.2;color:#3B2A1E;margin:2px 0 0;}
@media(max-width:599px){.mj-cr2-stop-name{font-size:20px;}}
.mj-cr2-stop-addr{font-family:'Fraunces',Georgia,serif;font-size:14px;text-transform:uppercase;
  letter-spacing:0.16em;font-weight:600;color:#8A6E52;margin:4px 0 0;}
.mj-cr2-stop-arrow{flex-shrink:0;color:#8A6E52;transition:color .15s ease;}

/* ── 4. ROUTE ── one ink frame, 3:1, nothing else. ── */
.mj-cr2-route{max-width:900px;margin:36px auto 0;padding:0 20px;}
.mj-cr2-route-head{font-family:'Pinyon Script', 'Pinyon Script Fallback', cursive;color:#3B2A1E;font-size:30px;
  line-height:1.1;text-align:center;margin:0 0 14px;}
.mj-cr2-route-frame{border:1px solid #3B2A1E;padding:7px;}
/* THE MAP'S BOX, AND WHY IT IS BUILT THIS WAY.
   The frame's only child is the map component's root. It gets the aspect ratio,
   and position:relative so the map's own div can be absolutely positioned
   against it. That last part is the fix: the map div used to be width:100% with
   height:100%, and a PERCENTAGE HEIGHT RESOLVED AGAINST A PARENT WHOSE HEIGHT
   COMES FROM aspect-ratio is not something every engine agrees on. Where it does
   not resolve, the height falls back to auto, the map div collapses to its
   borders, and MapKit renders into a box a couple of pixels tall. Measured here:
   295px tall when the parent height resolves, 2px when it does not.
   inset:0 against a positioned parent needs no percentage resolution at all.
   It also fixes a 2px overflow: width:100% plus a 1px border each side made the
   map div wider than the frame it sits in. */
.mj-cr2-route-frame > *{display:block;width:100%;aspect-ratio:3/1;position:relative;}
/* box-sizing so the map's own 1px border sits INSIDE the box inset:0 gives it.
   Without it the border adds 2px in each axis and the map overhangs the frame. */
.mj-cr2-route-frame > * > *:first-child{position:absolute;inset:0;width:auto;height:auto;box-sizing:border-box;}

/* ── 5. CLOSE ── two links, one row. ── */
.mj-cr2-close{display:flex;justify-content:center;align-items:center;flex-wrap:wrap;gap:26px;
  margin:28px 0 0;padding:0 20px 28px;}
.mj-cr2-close a{font-family:'Fraunces',Georgia,serif;font-size:11.5px;text-transform:uppercase;
  letter-spacing:0.16em;font-weight:600;color:#8A6E52;text-decoration:underline;
  text-decoration-thickness:1px;text-underline-offset:3px;white-space:nowrap;}
@media(max-width:599px){.mj-cr2-close{gap:14px;font-size:10.5px;}
  .mj-cr2-close a{font-size:10.5px;}}


  /* Full-bleed editorial bands (match the React website's band system). */
  .seo-band { width:100%; padding:56px 0; }
  .seo-band-inner { max-width:1280px; margin:0 auto; padding:0 24px; }
  .seo-band--cream { background:#FCF7D9; }
  .seo-band--blush { background:#F3DAD3; }
  .seo-band--chocolate { background:#3D2B1F; color:#F5EFE6; }

  /* Display headings. A Pinyon Script accent rule for a last-word flourish used
     to sit here and was removed: no page ever carried the class. */
  .seo-heading { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:700; color:#5C3520; font-size:clamp(2.1rem,5vw,3rem); line-height:1.1; margin:0 0 16px; letter-spacing:-0.01em; }
  .seo-band--chocolate .seo-heading { color:#F5EFE6; }
  .seo-sub { font-family:'Fraunces',serif; color:#604734; font-size:1.05rem; line-height:1.6; margin:0 0 24px; }
  .seo-band--chocolate .seo-sub { color:#EBE3D5; }
  .seo-section-title { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:600; color:#5C3520; font-size:1.5rem; margin:0 0 20px; }
  .seo-band--chocolate .seo-section-title { color:#F5EFE6; }

  /* Legacy bare headings inside a band (used until Steps 3-4 restructure each
     function's bodyContent into explicit bands). */
  .seo-band h1 { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:700; color:#5C3520; font-size:clamp(2.1rem,5vw,3rem); line-height:1.1; margin:0 0 12px; letter-spacing:-0.01em; }
  .seo-band h2 { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:600; color:#5C3520; font-size:1.5rem; margin:28px 0 14px; }
  .seo-band h3 { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:600; color:#3D2B1F; font-size:1.15rem; margin:0 0 6px; }
  .seo-band p { font-family:'Fraunces',serif; color:#4A3728; line-height:1.7; margin:0 0 10px; }
  .seo-band a { color:#5C3520; text-decoration:none; }
  .seo-band a:hover { text-decoration:underline; }
  .seo-band--chocolate h1, .seo-band--chocolate h2, .seo-band--chocolate h3 { color:#F5EFE6; }
  .seo-band--chocolate p { color:#EBE3D5; }

  .seo-breadcrumb { font-family:'Fraunces',serif; font-size:0.9em; margin:0 0 12px; color:#8a6454; }
  .seo-breadcrumb a { color:#8a6454; text-decoration:none; }
  .seo-breadcrumb a:hover { text-decoration:underline; }

  /* Shop detail: info grid, link pills, rating, Joe's review, reviews. */
  .seo-info-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:32px; }
  @media (max-width:1023px) { .seo-info-grid { grid-template-columns:1fr; gap:24px; } }
  .seo-info-item { font-family:'Fraunces',serif; color:#4A3728; line-height:1.7; }
  .seo-info-label { font-family:'Playfair Display','Playfair Display Fallback',serif; font-weight:600; color:#5C3520; font-size:0.78rem; text-transform:uppercase; letter-spacing:0.12em; margin:0 0 6px; }
  .seo-links { display:flex; flex-wrap:wrap; gap:10px; margin-top:8px; }
  .seo-link-pill { display:inline-block; padding:8px 16px; border:1px solid #C8A984; border-radius:999px; color:#5C3520; text-decoration:none; font-family:'Fraunces',serif; font-size:0.92rem; }
  .seo-link-pill:hover { background:#604734; color:#FCF7D9; text-decoration:none; }
  .seo-rating { font-family:'Fraunces',serif; font-size:1.1rem; color:#5C3520; margin:12px 0 0; }
  .seo-stars { color:#E9C36A; letter-spacing:2px; }

  .seo-joes { display:grid; grid-template-columns:380px 1fr; gap:48px; align-items:start; }
  @media (max-width:1023px) { .seo-joes { grid-template-columns:1fr; gap:24px; } }
  .seo-joes-media { aspect-ratio:9/16; max-height:480px; border-radius:12px; overflow:hidden; background:#4A3728; }
  .seo-joes-media img { width:100%; height:100%; object-fit:cover; display:block; }
  .seo-joes-verdict { font-family:'Playfair Display','Playfair Display Fallback',serif; font-style:italic; font-size:1.25rem; color:#F5EFE6; margin:0 0 16px; }
  .seo-joes-body { font-family:'Fraunces',serif; color:#EBE3D5; line-height:1.7; }

  .seo-reviews-grid { display:grid; grid-template-columns:1fr 1fr; gap:24px; }
  @media (max-width:1023px) { .seo-reviews-grid { grid-template-columns:1fr; } }

  /* Cards — city/state grid + review cards. */
  .seo-city-grid { list-style:none; padding:0; margin:0; display:grid; grid-template-columns:1fr; gap:10px 16px; }
  @media (min-width:768px) { .seo-city-grid { grid-template-columns:1fr 1fr; } }
  @media (min-width:1024px) { .seo-city-grid { grid-template-columns:1fr 1fr 1fr; } }
  .seo-city-grid li { margin:0; }
  .seo-card { display:block; height:100%; border:1px solid rgba(59,42,30,0.22); border-radius:12px; padding:16px 20px; text-decoration:none; background:#FBF6E3; color:#3D2B1F; transition:border-color .15s ease; }
  .seo-card:hover { border-color:rgba(59,42,30,0.4); text-decoration:none; }
  .seo-card-name { display:block; font-family:'Playfair Display','Playfair Display Fallback',serif; font-weight:600; color:#5C3520; font-size:1.05rem; line-height:1.3; }
  .seo-card-meta { display:block; color:#8a6454; font-size:0.88em; line-height:1.5; margin-top:3px; }
  .seo-shop-card { border:1px solid rgba(59,42,30,0.22); border-radius:12px; padding:20px; background:#FBF6E3; margin:0; }
  .seo-shop-card .reviewer { font-family:'Playfair Display','Playfair Display Fallback',serif; font-weight:600; color:#5C3520; font-size:1.1rem; }
  .seo-shop-card .meta { color:#8a6454; font-size:0.9rem; margin:6px 0; }
  .seo-shop-card p { color:#4A3728; line-height:1.7; margin:8px 0 0; }

  .seo-btn { display:inline-block; background:#604734; color:#FCF7D9; padding:12px 24px; border-radius:999px; text-decoration:none; font-family:'Fraunces',serif; font-weight:600; }
  .seo-btn:hover { text-decoration:none; background:#5C3520; }

  /* ── State/city landing redesign (server-rendered). No polka dots — one
     continuous cream #FCF7D9 field. Chocolate #3B2A1E, muted #6B5443/#8A6F5C,
     rules #D9C9A8/#C9B79A. Everything Playfair Display, no script/cursive. ── */
  .seo-landing { width:100%; background:#FCF7D9; padding:clamp(40px,7vw,72px) 16px clamp(56px,8vw,96px); }
  .seo-landing-inner { max-width:720px; margin:0 auto; }
  .seo-lcard { position:relative; background:#FCF7D9; border:1px solid rgba(59,42,30,0.22); border-radius:16px; padding:30px; text-align:center; }
  .seo-lcard-eyebrow { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:10px; text-transform:uppercase; letter-spacing:0.16em; font-weight:600; color:#8A6F5C; margin:0; }
  .seo-lcard-title { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:900; color:#3B2A1E; font-size:clamp(1.9rem,5vw,2.6rem); line-height:1.1; margin:10px 0 0; letter-spacing:-0.01em; }
  .seo-lcard-count { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:15px; color:#6B5443; margin:12px 0 0; line-height:1.5; }

  .seo-lsection { margin-top:28px; }
  .seo-lsection-head { display:flex; align-items:center; gap:16px; margin:0 0 16px; }
  .seo-lsection-head h2 { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:700; font-style:italic; color:#3B2A1E; font-size:1.25rem; margin:0; white-space:nowrap; }
  .seo-lsection-rule { flex:1; height:0; border:none; border-top:1px solid #C9B79A; margin:0; min-height:0; min-width:0; }

  /* ── The Crawls: a numbered single-column route index. NOT seo-lgrid — that is a
      three-across card grid, which squeezed each crawl's name, caption and stop
      count into a third of the width and wrapped captions one word per line. One
      crawl per row, full width; the caption gets everything between the name and
      the stop count. Matches the React /joes-picks route index exactly. ── */
  .seo-crawlindex { list-style:none; padding:0; margin:0; display:block; border-top:1px solid rgba(59,42,30,0.22); }
  /* The way out of this section to the crawls hub. Small, at the foot of the
     list, where somebody who has read it is already looking. */
  .seo-lsection-more { margin:14px 0 0; font-family:'Fraunces',Georgia,serif; font-size:13px; font-weight:600; }
  .seo-crawlindex li { margin:0; display:block; }
  a.seo-crawlrow { display:grid; grid-template-columns:44px minmax(0,1fr) auto 18px; align-items:center; gap:16px; padding:22px 4px; border-bottom:1px solid rgba(59,42,30,0.22); text-decoration:none; color:#3B2A1E; }
  a.seo-crawlrow:hover { text-decoration:none; color:#8A6E52; }
  .seo-crawlrow-num { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:15px; font-weight:600; color:rgba(59,42,30,0.5); letter-spacing:0.04em; }
  .seo-crawlrow-body { min-width:0; }
  .seo-crawlrow-name { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:700; color:inherit; font-size:clamp(1.05rem,2.4vw,1.3rem); line-height:1.2; margin:0; }
  .seo-crawlrow-cap { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-style:italic; color:rgba(59,42,30,0.7); font-size:clamp(0.85rem,2vw,1rem); line-height:1.4; margin:3px 0 0; }
  .seo-crawlrow-count { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:700; color:inherit; font-size:clamp(0.9rem,2vw,1.05rem); white-space:nowrap; text-align:right; }
  .seo-crawlrow-arrow { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; color:rgba(59,42,30,0.5); text-align:right; }

  .seo-lgrid { list-style:none; padding:0; margin:0; display:grid; grid-template-columns:1fr; gap:10px; }
  @media (min-width:768px) { .seo-lgrid { grid-template-columns:1fr 1fr; } }
  @media (min-width:1024px) { .seo-lgrid { grid-template-columns:1fr 1fr 1fr; } }
  .seo-lgrid li { margin:0; }
  a.seo-lcard-item { display:flex; align-items:center; gap:8px; background:#FCF7D9; border:none; border-bottom:1px solid rgba(59,42,30,0.14); border-radius:0; padding:10px 0; text-decoration:none; color:#3B2A1E; transition:color .15s ease; }
  a.seo-lcard-item:hover { color:#8A6E52; text-decoration:none; }
  .seo-lgrid li:last-child a.seo-lcard-item { border-bottom:none; }
  .seo-lcard-item-name { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:700; color:#3B2A1E; font-size:clamp(0.95rem,2vw,1.05rem); line-height:1.3; white-space:nowrap; }
  .seo-lcard-item-leader { flex:1; height:0; border-top:1px dotted rgba(59,42,30,0.4); }
  .seo-lcard-item-count { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; color:rgba(59,42,30,0.7); font-size:clamp(0.85rem,1.8vw,0.95rem); white-space:nowrap; }
  .seo-lsection-count { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; color:rgba(59,42,30,0.6); font-size:14px; white-space:nowrap; }

  .seo-landing-cta { text-align:center; margin-top:32px; }
  a.seo-browse-btn { display:inline-block; background:#3B2A1E; color:#FCF7D9; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:700; font-size:12px; text-transform:uppercase; letter-spacing:0.16em; padding:14px 38px; border-radius:999px; text-decoration:none; text-align:center; }
  a.seo-browse-btn:hover { background:#2a1d13; text-decoration:none; }

  .seo-nearby { margin-top:32px; display:grid; grid-template-columns:1fr; gap:20px; }
  @media (min-width:700px) { .seo-nearby { grid-template-columns:1fr 1fr 1fr; gap:32px; } }
  .seo-nearby-cell { border-top:1px solid #D9C9A8; padding-top:14px; }
  .seo-nearby-label { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:700; font-size:0.7rem; letter-spacing:0.14em; text-transform:uppercase; color:#3B2A1E; margin:0 0 6px; }
  a.seo-nearby-link { display:flex; align-items:center; justify-content:space-between; gap:8px; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:0.95rem; color:#3B2A1E; text-decoration:none; }
  a.seo-nearby-link:hover { text-decoration:underline; }

  /* ── Coffee crawl page (server-rendered). Continuous cream field, numbered
     chocolate stop circles, a centred Joe's-Pick-of-the-crawl line, and a linked
     stop list. Chocolate #3B2A1E, cream #FCF7D9, muted
     #6B5443 / #8A6F5C, rule #D9C9A8. Playfair Display throughout. ── */
  /* Joe's pick of the crawl. NOT a chocolate panel any more — a block that dark and
     that wide read as a second hero directly under the real one. It is a centred
     line on the open cream instead, on the same 680px measure as the stops list
     below. The butter star leads the name, the way it does in the Joe's Pick pill. */
  .seo-crawl-winner { max-width:680px; margin:28px auto 0; text-align:center; }
  .seo-crawl-winner-label { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:0.16em; color:#8A6E52; margin:0 0 6px; }
  .seo-crawl-winner-name { display:inline-flex; align-items:center; gap:8px; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:700; color:#3B2A1E; font-size:22px; text-decoration:none; }
  .seo-crawl-winner-name:hover { text-decoration:underline; }
  .seo-crawl-winner-loc { display:block; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; color:#8A6E52; font-size:14px; margin-top:4px; }
  .seo-crawl-stops { list-style:none; padding:0; margin:28px auto 0; max-width:680px; }
  .seo-crawl-stop { display:flex; align-items:flex-start; gap:16px; padding:18px 0; border-top:1px solid #D9C9A8; }
  .seo-crawl-stop:first-child { border-top:none; }
  .seo-crawl-num { flex-shrink:0; width:36px; height:36px; border-radius:50%; background:#3B2A1E; color:#FCF7D9; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:700; font-size:16px; display:flex; align-items:center; justify-content:center; }
  .seo-crawl-stop-body { flex:1; min-width:0; }
  .seo-crawl-stop-name { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:600; color:#3B2A1E; font-size:18px; line-height:1.3; text-decoration:none; }
  .seo-crawl-stop-name:hover { text-decoration:underline; }
  /* A POSITIONING slot only. The chip itself is the shared Joe's Pick badge
     (websitePickBadge.ts); this used to paint its own #FFE566 pill with different
     type and no star, which is how the crawl pages ended up marking a pick in a
     yellow that appears nowhere else on the site. */
  .seo-crawl-badge { display:inline-block; margin-left:8px; vertical-align:middle; }
  .seo-crawl-stop-loc { display:block; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; color:#8A6F5C; font-size:14px; margin-top:3px; }
  .seo-crawl-stop-note { display:block; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-style:italic; color:#6B5443; font-size:15px; line-height:1.5; margin-top:6px; }

  /* ── Joe's Reviews index (server-rendered joesReviewsPage). NO React twin: this
      page has no counterpart under src/, so nothing here needs to be shared and the
      CSS lives with the rest of the server-rendered pages.

      WHAT THIS REPLACED. A chocolate hero band, a three-way filter bar, and rows
      grouped under state headings with a per-state count. All three are gone: the
      band because the page body carries no chocolate and no awning motif, the
      filters because "All" and "Joe's Picks" both showed everything a sort could
      show, and the grouping because a state heading over one or two rows is a list
      of headings rather than a list of shops.

      PALETTE. #4A3626 is the darkest tone on this page and #3A2A1E is deliberately
      absent, as are the gold #E8CE6B and brass #B08A3E used elsewhere on the site.
      #5C4A38 body, #8A7355 muted, #8A6A4F pick meta, #B49B7A ornaments and the
      heavier hairlines, #C9B79A / #D8C6A6 the light ones, #A9906E arrows, #6B5238
      the active sort segment. ── */
  .seo-jr-page { width:100%; background:#FCF7D9; padding:40px 34px clamp(56px,8vw,96px); box-sizing:border-box; }
  .seo-jr-wrap { max-width:1000px; margin:0 auto; }

  /* ── Breadcrumb ── the same shape and position every other server-rendered page
     puts one in: top left of the measure, 11px uppercase, segments linked. It takes
     this page's muted tone rather than the shared .seo-breadcrumb colour, which is
     outside the palette this page is held to. ── */
  .seo-jr-crumbs { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:11px; letter-spacing:0.14em; text-transform:uppercase; color:#8A7355; margin:0 0 8px; line-height:1.4; }
  .seo-jr-crumbs a { color:#8A7355; text-decoration:none; border-bottom:1px solid transparent; }
  .seo-jr-crumbs a:hover { border-bottom-color:#8A7355; }
  .seo-jr-crumbs span { margin:0 8px; }

  /* ── Masthead ── no band, no fill, no box: the four corner ornaments are the
     only thing marking its edges, which is why they are positioned against this
     element and not drawn as a border. ── */
  /* ── Masthead ── No band, no fill, no box, and now no corner ornaments either.
     It does not need them: the chocolate header gives it a hard top edge and the
     find field's hairline gives it a hard bottom one, so the block is bounded by
     the page rather than by decoration drawn around it.
     THE BOTTOM PADDING IS DELIBERATELY SMALL. The four ornaments were 72px tall and
     the lower pair filled the space under the stats line; with them gone, a 40px
     bottom padding plus the find field's own 26px top margin left a 66px void that
     nothing occupied, against 30px between the field and the sort control and 34px
     between that and the grid. 10px brings the gap to 36px, which reads as one step
     more than the rhythm below it: enough to separate the page's identity from the
     tools under it, not enough to be a hole. The side padding no longer has to
     clear anything, so it now only holds the measure in from the edge. */
  .seo-jr-mast { position:relative; padding:44px 46px 10px; text-align:center; }

  .seo-jr-est { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:11px; letter-spacing:0.34em; text-transform:uppercase; color:#8A7355; margin:0 0 18px; line-height:1.2; }

  /* ONE LINE, NOT TWO. The heading used to be a two-part lockup: a display line
     reading "Coffee Shop Reviews" under a script line reading "Every Shop Joe Has
     Written About", with a visually-hidden colon between them so the accessible
     name joined the two in reading order, and an order swap so the DOM order and
     the painted order could differ. The display line is gone — the page says what
     it is in the browser title, the breadcrumb and the intro sentence, and repeating
     it as the largest type on the page was the third time in 40px of vertical space.
     With one child left there is nothing to order and nothing to hide, so the flex
     column now only centres. It is still the page's single h1; its accessible name
     is now "Joe's Coffee Reviews" — the keyword-carrying half of that sentence moved
     into the title tag, which is the line that has to win the click. */
  .seo-jr-h1 { display:flex; flex-direction:column; align-items:center; margin:0;
    font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:400; font-size:36px; line-height:1.25; color:#4A3626; }

  /* WIDER THAN THE OLD 560px. That measure was set for a two-clause sentence; the
     line under the masthead is now one clause of seventy-two characters and 560 broke
     it across two lines with four words on the second. 720 is still inside a
     comfortable measure for 16px and lets it sit on one line at desktop. */
  .seo-jr-intro { font-family:'Fraunces',Georgia,serif; font-size:16px; line-height:1.7; color:#5C4A38; max-width:720px; margin:20px auto 0; }
  .seo-jr-stats { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:14px; letter-spacing:0.24em; text-transform:uppercase; color:#8A7355; margin:20px 0 0; line-height:1.4; }

  /* ── Sort bar ── two segments sharing one border, so the seam between them is a
     single hairline rather than two touching ones. Outer corners fully rounded and
     inner corners square is what makes the pair read as one control. ── */
  /* ── FIND A SHOP ── A rule with words on it, not a control. It takes the full
     measure of the content below it so it reads as part of the page rather than a
     widget parked on top of one: transparent, no box, no icon, one hairline in the
     page's own rule tone, and the text centred on the same axis as the masthead.
     Structure is the website's editorial form field (transparent, borderless but
     for a bottom hairline, zero radius, Playfair); the colours are this page's,
     because the form module's near-black ink is outside the palette this page is
     held to. ── */
  .seo-jr-find { margin:26px 0 0; }
  .seo-jr-find-input { width:100%; box-sizing:border-box; height:44px; background:transparent; border:none; border-bottom:1px solid #B49B7A; border-radius:0; outline:none; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:16px; line-height:1.4; color:#4A3626; text-align:center; padding:0 4px; -webkit-appearance:none; appearance:none; }
  .seo-jr-find-input::placeholder { color:#8A7355; opacity:1; }
  .seo-jr-find-input:focus { border-bottom-color:#8A7355; }
  /* The one line a search with no hits gets. Same treatment as the page's
     no-reviews line, closer to the field it answers. */
  .seo-jr-nomatch { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-style:italic; font-size:15px; color:#5C4A38; text-align:center; margin:24px 0 0; }

  .seo-jr-sort { display:flex; justify-content:center; margin:30px 0 0; }
  /* 9px/22px keeps the visible pill at 33px, which the spec sets. The TOUCHABLE box
     is 44px, added by an overlay that sits outside the flow: growing the button
     itself would grow the pill with it. Each overlay spans only its own segment, so
     the two do not overlap where they meet. */
  .seo-jr-seg { position:relative; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:10.5px; letter-spacing:0.22em; text-transform:uppercase; padding:9px 22px; border:1px solid #B49B7A; background:transparent; color:#4A3626; cursor:pointer; line-height:1.2; }
  .seo-jr-seg::after { content:''; position:absolute; left:0; right:0; top:50%; transform:translateY(-50%); height:44px; }
  .seo-jr-seg:first-child { border-radius:999px 0 0 999px; }
  .seo-jr-seg:last-child { border-radius:0 999px 999px 0; border-left:none; }
  .seo-jr-seg[aria-pressed="true"] { background:#6B5238; color:#FCF7D9; }

  /* ── The list ── every review in one document. No page parameter, no load-more,
     no show/hide: the A-Z control reorders nodes that are already here. ── */
  .seo-jr-grid { display:grid; grid-template-columns:1fr 1fr; gap:14px; margin:34px 0 0; }

  a.seo-jr-box { display:flex; gap:12px; align-items:flex-start; border:1px solid #D8C6A6; border-radius:14px; padding:18px 20px; text-decoration:none; color:#4A3626; transition:border-color .15s ease; }
  a.seo-jr-box:hover { border-color:#B49B7A; }
  .seo-jr-box-body { flex:1; min-width:0; }
  .seo-jr-shop { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:700; font-size:20px; line-height:1.25; color:#4A3626; margin:0; }
  /* THE ONLY PLACE THE LOCATION APPEARS now that the state headings are gone, so it
     is rendered for every box rather than only when a city is known. */
  .seo-jr-meta { display:block; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:10.5px; letter-spacing:0.2em; text-transform:uppercase; color:#8A7355; margin:7px 0 0; line-height:1.5; }
  .seo-jr-meta--pick { color:#8A6A4F; }
  /* Two lines, cut by CSS. The stored note is never shortened server-side, so the
     clamp can never leave a visible ellipsis inside a sentence that still runs on;
     a stored trailing ellipsis is stripped before render for the same reason. */
  .seo-jr-note { display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-style:italic; font-size:16px; line-height:1.6; color:#5C4A38; margin:9px 0 0; }
  .seo-jr-arrow { flex-shrink:0; padding-top:5px; line-height:0; color:#A9906E; transition:color .15s ease; }
  a.seo-jr-box:hover .seo-jr-arrow { color:#4A3626; }

  .seo-jr-none { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-style:italic; font-size:15px; color:#5C4A38; text-align:center; margin:44px 0 0; }

  /* ── Closing ── two links and then the page stops. No band, no ornament. ── */
  .seo-jr-close { display:flex; justify-content:center; flex-wrap:wrap; gap:28px; margin:48px 0 0; }
  .seo-jr-close a { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:10.5px; letter-spacing:0.2em; text-transform:uppercase; color:#4A3626; text-decoration:none; border-bottom:1px solid #B49B7A; padding-bottom:3px; }

  @media (max-width: 899px) {
    .seo-jr-mast { padding:34px 34px 8px; }
  }
  @media (max-width: 767px) {
    .seo-jr-page { padding-left:20px; padding-right:20px; }
    .seo-jr-grid { grid-template-columns:1fr; }
  }
  /* THE ORNAMENTS COLLIDE WITH THE COPY at the narrow end, and only there. They sit
     at the masthead's corners while "MOCHA JOE, EST. 2026" and the stats line are
     centred, so on a wide masthead the glyphs are nowhere near them even though the
     text sits inside the ornament band vertically. Measured with ranges over the
     text nodes rather than block boxes, which span the full measure and overlap at
     every width whether or not anything is actually on top of anything: real
     collisions start at 375px (stats into both bottom corners) and get worse at
     320px (the eyebrow too). A third step in the ornament size plus vertical
     padding that clears it is what separates them.

     nowrap also means the display line can never wrap, so the only way it can fail
     is to overflow. Its floor is 17px and the side padding comes in here because
     the measured widths come from the FALLBACK face: the real Playfair Display 900
     is the wider of the two, and the headroom is for it.

     DO NOT RAISE THE 17px FLOOR WITHOUT RE-MEASURING ON A REAL DEVICE. Every width
     in the build harness was measured with Google Fonts blocked by the network
     policy, so the display line was laid out in the fallback face, which is the
     narrower one. 17px rather than 19px is the margin that buys, and it is not
     spare room: at 320px the fallback line measured 181px inside 236px, and
     Playfair Display 900 is wider than that. If it looks small on a phone, measure
     the real face first. */
  @media (max-width: 480px) {
    .seo-jr-mast { padding:48px 22px 10px; }
  }

  /* PART SEVEN: the meet connection, one line under the summary sentence. Accent
     tone, a step down in size, and it renders only when there is a connection, so a
     shop that hosts nothing reserves no space for the line it does not have. */
  .seo-shop-meet { font-family:'Fraunces',Georgia,serif; font-size:14px; line-height:1.6; color:#8A6A4F; margin:6px 0 0; }
  .seo-shop-meet-link { color:#8A6A4F; text-decoration:none; border-bottom:1px solid #B49B7A; padding-bottom:1px; }
  .seo-shop-meet-link:hover { color:#4A3626; }

  /* ── Shop page (server-rendered) — matches the React /shop/:id website branch.
      Chocolate #3B2A1E, cream #FCF7D9, muted #8A6E52, rule #E3D9BC.

      EXACTLY ONE HORIZONTAL RULE ON THE PAGE: the hairline between community
      reviews. There is none under the title, none above the facts, none above Joe's
      review, none beside the community heading and none above the footer links. The
      page used to carry five.

      TWO COLUMNS. Joe's review takes the measure; the facts a reader looks up rather
      than reads sit in a fixed 290px rail. From the Community and the footer actions
      run full width beneath both. Under 900px the rail drops below the main column at
      full width. ── */
  .seo-shop { width:100%; background:#FCF7D9; }
  /* ONE CENTRED MEASURE, 920px, 24px either side, at every width. It was 1100 with
     40px sides above 1139px and a separate narrow rule below it; one value needs no
     breakpoint, and it matches the React page exactly. */
  .seo-shop-inner { max-width:920px; margin:0 auto; padding:0 24px; box-sizing:border-box; }

  /* ── Title block — full width, no rule under it. ── */
  .seo-shop-header { width:100%; background:#FCF7D9; color:#3B2A1E; padding:32px 0 0; }
  .seo-shop-header-inner { max-width:920px; margin:0 auto; padding:0 24px; box-sizing:border-box; }
  /* NO overflow:hidden HERE ANY MORE. It clipped the crumb trail on a long shop
     name, and text-overflow:ellipsis never did anything about it: ellipsis applies
     to a block's own text, and the children of a flex container are flex items, so
     the trail was clipped with no ellipsis to show for it. It also clipped the
     transparent 44px tap target the crumbs now carry, which is the reason it had to
     go. Wrapping instead of clipping is what the phone breakpoint already did. */
  /* THE CRAWL'S ROUTE MAP. The frame is laid out at its final height through
     aspect-ratio before the image arrives, so nothing below it moves when it
     lands — the same reservation the shop map makes, and what makes
     loading="lazy" safe here. */
  .seo-crawl-map { margin: 28px 0; }
  .seo-crawl-map img { display:block; width:100%; height:auto; aspect-ratio: 2 / 1; object-fit:cover; border-radius:14px; border:1px solid #C8A984; box-sizing:border-box; background:#FBF6E3; }

  .seo-shop-crumbs { display:flex; flex-wrap:wrap; align-items:center; gap:0 20px; font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif; font-size:11px; font-weight:600; text-transform:uppercase; letter-spacing:0.14em; color:#8A6E52; margin:0 0 24px; line-height:1; }
  .seo-shop-crumbs a { color:#8A6E52; text-decoration:none; }
  .seo-shop-crumbs a:hover { text-decoration:underline; }
  /* .seo-crumb-sep is gone with the middot it styled; the row's own gap is the
     separation now. See websiteFooter.ts for the same change in the legal row. */
  /* Name and Joe's Pick badge share one line, badge to the right of the name. */
  .seo-shop-nameline { display:flex; align-items:center; flex-wrap:wrap; gap:14px; }
  /* A FLAT 36px. It was clamp(30px,4.5vw,46px), so on a desktop the shop's name
     outweighed everything under it and the title block read as a masthead. */
  .seo-shop-name { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:700; color:#3B2A1E; font-size:36px; line-height:1.08; margin:0; letter-spacing:-0.01em; text-align:left; }
  /* The one-sentence summary, BELOW the rating. It is the page's plain-language
     answer to what this place is, and it reads as a sentence rather than as a row of
     grey caps. */
  .seo-shop-summary { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:16px; color:#6B5443; margin:10px 0 0; line-height:1.5; }
  /* THE RATING LINE. Three states, the same three the React title block uses:
       3+ ratings : stars, the average, "· {n} reviews"
       1-2        : the count alone. An average of two is one person's view wearing
                    a number, and printing it makes it look surveyed.
       0          : nothing renders at all, and no space is reserved. */
  .seo-shop-rating { display:flex; align-items:center; gap:8px; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; color:#8A6E52; margin:10px 0 0; line-height:1; }
  .seo-shop-rating-avg { font-size:15px; color:#3B2A1E; }
  .seo-shop-rating-n { font-size:14px; color:#8A6E52; }
  /* Its own star class, NOT .seo-cr-stars: that one carries margin-left:auto to push
     a reviewer's stars to the right edge of a review row, and borrowing it shoved the
     whole rating line across the title block. */
  /* Layout only. The stars are SVG from the shared glyph now, so colour and size ride
     on the glyph itself — this used to set a text colour for U+2605 characters. */
  .seo-shop-rating-stars { display:inline-flex; align-items:center; white-space:nowrap; }

  /* ── ONE COLUMN. This page was two — Joe's review on the measure with the facts
      in a fixed 290px rail beside it — and the rail is gone. Address, hours and a
      list of link labels squeezed into 290px made both the hours table and the link
      list columns of stubs, beside a review that had lost a third of its measure.
      Everything now runs the full measure in reading order. ── */
  .seo-shop-strip { margin:18px 0 0; }
  .seo-shop-main { margin:16px 0 0; min-width:0; }

  /* ── Joe's review — A PANEL. It was a filled card with a floated square
      thumbnail, then no card at all, with the media full width at 16:9 above the
      text. It is now a bordered panel on the soft-cream surface one step lighter
      than the page: with the facts a bordered strip above it, an unbordered review
      between two bordered blocks read as a gap.

      THE HEADER IS AN EYEBROW, NOT A TITLE, and a pick's panel is outlined in brass
      with a 13px brass star. The 22px butter free-standing star is gone — the page
      is down to one warm accent and one star glyph, and that star was neither.

      TWO LAYOUTS, NOT ONE WITH A HOLE: with media, two columns and a fixed 220px
      4:5 crop on the right; without it, wider padding, a bigger quote and a 640px
      measure, with nothing reserved where the media would have been. ── */
  .seo-joes-card { border:1px solid #E3D9BC; border-radius:10px; padding:22px; background:#FBF6E3; color:#3B2A1E; margin:0; }
  .seo-joes-card--pick { border-color:#B08A3E; }
  .seo-joes-card--nomedia { padding:26px 30px; }
  .seo-joes-attr { display:flex; align-items:center; gap:8px; margin:0 0 16px; }
  .seo-joes-star { display:flex; align-items:center; flex-shrink:0; }
  .seo-joes-heading { font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif; font-size:11px; font-weight:600; text-transform:uppercase; letter-spacing:0.16em; color:#3B2A1E; margin:0; }
  .seo-joes-heading--pick { color:#7A5D28; }
  .seo-joes-meta { margin-left:auto; font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif; font-size:11px; font-weight:600; text-transform:uppercase; letter-spacing:0.14em; color:#8A6E52; margin-top:0; margin-bottom:0; margin-right:0; text-align:right; }
  .seo-joes-grid { display:flex; align-items:flex-start; gap:22px; }
  .seo-joes-text { flex:1 1 auto; min-width:0; }
  .seo-joes-media { flex:0 0 220px; width:220px; position:relative; aspect-ratio:4/5; border-radius:8px; overflow:hidden; background:#EDE3CC; margin:0; }
  .seo-joes-media img, .seo-joes-media video { width:100%; height:100%; object-fit:cover; display:block; }
  /* Playfair italic, no quotation marks, no script face. It is Joe's line, set as a
     line, not as a quotation. */
  .seo-joes-pullquote { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:26px; font-style:italic; font-weight:500; line-height:1.3; color:#3B2A1E; margin:0 0 16px; text-align:left; }
  .seo-joes-copy { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:16px; line-height:1.65; color:#3B2A1E; margin:0; text-align:left; }
  /* Watch on Instagram. A text link under the review, in the page's own ink and
     face, with the chevron as a character rather than an icon so the whole row is
     one text node and no asset loads for it. 44px of height for a thumb. */
  .seo-joes-reel { margin:10px 0 0; font-family:'Fraunces','Fraunces Fallback',Georgia,serif; font-size:15px; }
  .seo-joes-reel a { display:inline-flex; align-items:center; gap:4px; min-height:44px; color:#3B2A1E; font-weight:600; text-decoration:none; }
  .seo-joes-reel a:hover { color:#8A6E52; }
  /* The chevron is a LITERAL CHARACTER, not a CSS code-point escape. This whole
     sheet is a TS template literal, so the JS parser reads a backslash sequence
     before CSS ever sees it, and a backslash followed by digits is rejected as a
     legacy octal escape. Writing the character itself sidesteps the parser entirely.
     (This comment originally demonstrated the escape and broke the build with it.) */
  .seo-joes-reel a::after { content:'›'; font-size:17px; line-height:1; }
  .seo-joes-card--nomedia .seo-joes-pullquote { font-size:30px; max-width:640px; }
  .seo-joes-card--nomedia .seo-joes-copy { font-size:15.5px; line-height:1.7; max-width:640px; }
  @media (max-width:767px) {
    .seo-joes-grid { display:block; }
    .seo-joes-media { width:100%; aspect-ratio:16/9; margin-top:18px; }
    .seo-joes-pullquote, .seo-joes-card--nomedia .seo-joes-pullquote { font-size:22px; }
  }

  /* ── THE FACTS STRIP — full measure, two zones split by one divider: the facts on
      the left, the two things a reader acts on — directions and a phone call — on
      the right. It was a card in a 290px rail. ── */
  .seo-facts { display:flex; align-items:stretch; border:1px solid #E3D9BC; border-radius:10px; background:transparent; }
  .seo-facts-left { flex:1 1 auto; min-width:0; padding:16px 20px; }
  /* The divider is the right zone's own left border, so a strip with neither a phone
     nor directions has no dangling rule down its middle. */
  .seo-facts-right { flex:0 0 250px; width:250px; padding:16px 20px; border-left:1px solid #E3D9BC; display:flex; flex-direction:column; justify-content:center; gap:8px; box-sizing:border-box; }
  .seo-facts-block + .seo-facts-block { margin-top:16px; }
  /* The address is ONE line — street, city, state, ZIP — each piece printed once.
     See base44/shared/websiteAddress.ts. */
  .seo-facts-addr { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:14.5px; color:#3B2A1E; line-height:1.5; margin:0; }

  /* ── THE STATIC MAP, under the address. A picture of a map with one pin, wrapped in
      the Get Directions link, served by /functions/shopMapSnapshot.

      NO LIVE MAP HERE, EVER. This document is server-rendered and cached; a MapKit JS
      map would mean a script, a signed token fetch and a tile session on a page whose
      one coordinate is fixed and already known at render time.

      aspect-ratio RESERVES THE BOX before the image exists, so the facts under it do
      not move when it arrives. The ratio must stay in step with the size constants in
      base44/shared/staticMap.ts. ── */
  .seo-facts-map { display:block; box-sizing:border-box; width:100%; aspect-ratio:640/320; border:1px solid #E3D9BC; border-radius:2px; overflow:hidden; background:#F3ECD9; }
  .seo-facts-map img { display:block; width:100%; height:100%; object-fit:cover; }

  /* ── Hours: a <details> dropdown, closed by default, no JS.
      NO hours_confirmed GATE — that gate was deliberately removed from the website.
      If the shop has hours they render; only a shop with none at all renders nothing.

      THE SERVER PAGE DOES NOT CLAIM OPEN OR CLOSED, and has no status dot. This
      document is cached for an hour (Cache-Control: max-age=3600), so a rendered
      "Open Now" is wrong for up to an hour after closing. The React page computes it
      live against the shop's own timezone and shows the dot, the state and the next
      transition; here the summary is the word Hours and the week is one click
      away. ── */
  .seo-facts-hours { border:none; padding:0; margin:0; }
  .seo-facts-hours > summary { display:flex; align-items:center; justify-content:space-between; gap:10px; cursor:pointer; list-style:none; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:14.5px; font-weight:600; color:#3B2A1E; min-height:44px; }
  .seo-facts-hours > summary::-webkit-details-marker { display:none; }
  .seo-facts-chev { flex-shrink:0; color:#8A6E52; transition:transform .18s ease; }
  .seo-facts-hours[open] .seo-facts-chev { transform:rotate(180deg); }
  /* Day left, time right, on a 240px measure so the two columns stay a pair rather
     than drifting apart across a full-width strip. */
  .seo-facts-week { max-width:240px; padding:2px 0 4px; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:14px; color:#3B2A1E; }
  .seo-facts-day { display:flex; justify-content:space-between; gap:16px; padding:3px 0; }
  .seo-facts-day > span:last-child { color:#8A6E52; }

  /* Get Directions above Call, neither filled. The number lives INSIDE the label, so
     there is no bare phone line anywhere on the page. With no phone on record the
     Call button is not rendered and the zone centres Get Directions on its own —
     directions always resolve to something, so that button is always there. */
  a.seo-facts-btn { display:flex; align-items:center; justify-content:center; gap:7px; min-height:44px; background:transparent; color:#3B2A1E; font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif; font-size:11.5px; font-weight:600; text-transform:uppercase; letter-spacing:0.1em; padding:11px 14px; border-radius:999px; text-decoration:none; line-height:1; text-align:center; border:1px solid #E3D9BC; }
  a.seo-facts-btn--primary { border-color:#3B2A1E; }
  a.seo-facts-btn:hover { text-decoration:none; opacity:0.8; }
  .seo-dir-arrow { display:block; flex-shrink:0; }

  /* ONE INLINE ROW of external links, not a stacked list — a handful of short labels
     down the left of a full-width strip is a column of stubs. With none of them on
     record the row becomes an invitation to add them; never "No links yet." */
  .seo-facts-links { display:flex; flex-wrap:wrap; align-items:center; gap:16px; }
  a.seo-si-link { display:inline-flex; align-items:center; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:14px; font-weight:600; color:#3B2A1E; text-decoration:underline; text-decoration-thickness:1px; text-underline-offset:2px; }
  a.seo-si-own { color:#7A5D28; }

  /* Under 768px the zones stack, so the divider is a horizontal rule at the seam
     rather than a vertical one down a column that no longer exists. */
  @media (max-width:767px) {
    .seo-facts { display:block; }
    .seo-facts-right { width:auto; border-left:none; border-top:1px solid #E3D9BC; }
    .seo-facts-links { justify-content:center; }
  }

  /* ── From the Community — full measure. No rule beside the heading; the rating
      summary sits inline with it on the same baseline, under the same rule the title
      block uses: an average only at three ratings or more, the count alone below
      that, the heading alone at zero. ── */
  .seo-shop-community { margin:30px 0 0; }
  .seo-cr-head { display:flex; align-items:baseline; flex-wrap:wrap; gap:4px 12px; margin:0 0 18px; }
  .seo-cr-title { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-style:italic; font-weight:500; color:#3B2A1E; font-size:22px; line-height:1.2; margin:0; text-align:left; }
  .seo-cr-sum { display:inline-flex; align-items:center; gap:8px; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; }
  .seo-cr-sum-avg { font-size:14px; color:#3B2A1E; }
  .seo-cr-sum-n { font-size:14px; color:#8A6E52; }
  .seo-shop-community-empty { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-style:italic; color:#6B5443; font-size:15px; margin:0 0 18px; text-align:left; max-width:640px; }
  /* Reviews STACK at full width — no cards, no borders, no grid. THE PAGE'S ONE
     RULE is the hairline between them, and there is none above the first. */
  .seo-shop-community-list { display:block; }
  /* A 38px avatar in a fixed left column, then a content column on a 640px measure.
     THAT MEASURE IS LOAD-BEARING: it is what keeps a review's stars beside the name
     that gave them. They used to be pushed to the container's right edge, which
     across a full-width page put a rating a screen away from the reviewer. */
  .seo-cr-card { display:flex; align-items:flex-start; gap:14px; background:transparent; border:none; border-radius:0; padding:0; }
  .seo-cr-card + .seo-cr-card { border-top:1px solid #E3D9BC; margin-top:18px; padding-top:18px; }
  .seo-cr-avatar { flex:0 0 38px; width:38px; height:38px; border-radius:50%; background:#F5E3DC; color:#3B2A1E; display:flex; align-items:center; justify-content:center; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:700; font-size:16px; line-height:1; }
  .seo-cr-content { flex:1 1 auto; min-width:0; max-width:640px; }
  .seo-cr-line1 { display:flex; align-items:center; gap:10px; }
  .seo-cr-name { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:15px; font-weight:700; color:#3B2A1E; margin:0; }
  .seo-cr-meta { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:14px; color:#6B5443; margin:3px 0 0; }
  .seo-cr-stars { display:inline-flex; align-items:center; white-space:nowrap; flex-shrink:0; }
  .seo-cr-body { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:16px; line-height:1.65; color:#3B2A1E; margin:8px 0 0; overflow-wrap:anywhere; }
  @media (max-width:479px) { .seo-cr-line1 { flex-wrap:wrap; } }
  /* Chips, outlined. Six show; the rest sit in the same list behind a plain muted
     toggle that expands them in place rather than opening anything. */
  .seo-cr-chips { display:flex; flex-wrap:wrap; gap:8px; margin:12px 0 0; align-items:center; }
  .seo-cr-chip { display:inline-flex; align-items:center; border:1px solid #E3D9BC; border-radius:999px; padding:4px 12px; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:11.5px; color:#3B2A1E; background:transparent; line-height:1.3; }
  /* display:inline-flex outranks the UA's [hidden]{display:none}, so without this
     every chip past the sixth rendered anyway and the "+n more" toggle had nothing
     left to reveal. Same defect .seo-jr-state[hidden] had. */
  .seo-cr-chip[hidden] { display:none; }
  .seo-cr-more { background:none; border:none; padding:0; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:14px; color:#8A6E52; cursor:pointer; text-decoration:none; min-height:unset; }

  /* CENTRED outlined pill under the last review — never filled, never inside a
     bordered box. */
  .seo-shop-cta-wrap { text-align:center; margin:24px 0 0; }
  .seo-shop-cta { display:inline-flex; align-items:center; justify-content:center; min-height:44px; border:1px solid #3B2A1E; background:transparent; color:#3B2A1E; font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif; font-size:11px; font-weight:600; text-transform:uppercase; letter-spacing:0.14em; padding:10px 28px; border-radius:999px; text-decoration:none; line-height:1; }
  .seo-shop-cta:hover { text-decoration:none; opacity:0.8; }

  /* ── Footer actions, centred, 30px below the community section. NO RULE above
      them — the page's one rule is the hairline between reviews. ── */
  .seo-shop-foot { margin:30px 0 0; padding:0 0 64px; text-align:center; }
  /* ── WHAT'S IN THE CUP ──
     A two-column list, label left in the small caps the page already uses for a
     section label, value right in the reading face. NOT a bordered table: the
     facts card in the rail is the only bordered element on this page and a second
     one would make the page a form.
     grid rather than flex so every value starts on the same x whatever its label
     is, which is the whole reason a reader chose a table over the sentence. The
     label column is sized to the longest of the four labels (Chocolate) and does
     not move between shops, so two shop pages open the same shape. */
  .seo-shop-cup { margin:18px 0 0; }
  .seo-shop-cup-rows { margin:8px 0 0; display:grid; grid-template-columns:auto 1fr; gap:6px 18px; align-items:baseline; }
  .seo-shop-cup-row { display:contents; }
  .seo-shop-cup-rows dt { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:11px; text-transform:uppercase; letter-spacing:0.14em; color:#8A7355; white-space:nowrap; }
  .seo-shop-cup-rows dd { margin:0; font-family:'Playfair Display','Playfair Display Fallback',serif; font-size:15px; line-height:1.5; color:#3B2A1E; }
  @media(max-width:479px){
    /* One column under the label on a narrow phone. Nine characters of label plus
       "Colombia and Guatemala blend" does not fit 320px in two columns, and the
       value is what the reader came for, so the label gives up its column first. */
    .seo-shop-cup-rows { grid-template-columns:1fr; gap:2px 0; }
    .seo-shop-cup-row { display:block; margin:0 0 10px; }
    .seo-shop-cup-rows dd { margin:1px 0 0; }
  }

  /* ── UPDATED [MON YYYY] ──
     Above the two contextual links in the foot, quieter than both: it is provenance,
     not navigation. Same muted brown as the rest of the foot, no rule, no box. */
  .seo-shop-updated { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:11px; text-transform:uppercase; letter-spacing:0.14em; color:#8A7355; text-align:center; margin:0 0 12px; }

  .seo-shop-links { display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:8px 10px; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:12px; text-transform:uppercase; letter-spacing:0.08em; color:#6B5443; margin:0; }
  /* A VISIBLE 1px underline, so these read as clickable. The shell's own anchor rule
     sets text-decoration:none at the same specificity and, being later in the sheet,
     was winning, so the selector carries an explicit class instead of a bare tag. */
  .seo-shop-links a.seo-shop-link { color:#6B5443; text-decoration:underline; text-decoration-thickness:1px; text-underline-offset:3px; }
  .seo-shop-links a.seo-shop-link:hover { color:#3B2A1E; }
  /* "Own this shop? Claim it" — sentence case and smaller than the uppercase links
     above it, because it addresses one reader in a thousand and must not compete
     with the navigation that serves the rest. The link itself is underlined so it
     still reads as one. */
  .seo-shop-claim { font-family:'Fraunces',Georgia,serif; font-size:14px; line-height:1.6; color:#8a6454; margin:14px 0 0; }
  .seo-shop-claim a { position:relative; color:#6B5443; text-decoration:underline; text-decoration-thickness:1px; text-underline-offset:3px; }
  /* A 44px TAP TARGET without turning the link into a button. The pseudo-element is
     out of flow and paints nothing, so "Claim it" keeps the weight of an inline
     link in a sentence and still takes a thumb. An inline link in prose is exempt
     from the target-size rule, but this one is a call to action aimed at exactly
     the reader least likely to try twice. */
  .seo-shop-claim a::after { content:''; position:absolute; left:-6px; right:-6px; top:50%; transform:translateY(-50%); height:44px; }
  .seo-shop-claim a:hover { color:#3B2A1E; }

  /* Body — continuous cream. */
  .seo-shop-body { padding:0; }
  .seo-shop-label { font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif; font-size:11px; font-weight:600; text-transform:uppercase; letter-spacing:0.16em; color:#8A6E52; margin:0 0 12px; }
  .seo-shop-about-text { font-family:'Playfair Display','Playfair Display Fallback',serif; color:#3B2A1E; font-size:16px; line-height:1.7; margin:0 0 24px; }

  /* Menu spotlight — outlined pills with name + price. */
  .seo-shop-menu { margin:0 0 24px; }
  .seo-shop-drinks { display:flex; flex-wrap:wrap; gap:10px; }
  .seo-shop-drink { display:inline-flex; align-items:baseline; gap:6px; border:1px solid #3B2A1E; border-radius:999px; padding:8px 16px; font-family:'Playfair Display','Playfair Display Fallback',serif; color:#3B2A1E; font-size:14px; background:transparent; line-height:1.2; }
  .seo-shop-drink-name { font-weight:500; }
  /* .seo-shop-drink-sep is gone with the middot between a drink and its price. */
  .seo-shop-drink-price { font-weight:600; }
  .seo-shop-features { font-family:'Playfair Display','Playfair Display Fallback',serif; color:#6B5443; font-size:14px; line-height:1.6; margin:14px 0 0; }

  /* ── Touch targets on the server-rendered pages ──────────────────────────────
     The React side inherits a global min-height:44px rule for buttons and links
     from index.css. These pages do not load index.css at all, so every link here was
     as tall as its own line box: breadcrumbs at 11px, "Get Directions" at 23px,
     the "Leave a Review" pill at 35px, the Keep Exploring rows at 16px. Below
     768px they each get 44px of touchable height. Nothing changes above it,
     where the pointer is, and no type size moves at any width — the box grows
     around the text, the text stays put. */
  @media (max-width: 767px) {
    a.seo-si-link,
    .seo-shop-cta,
    .seo-shop-links a,
    .seo-browse-btn,
    .mj-bd-ctasub a { min-height:44px; display:inline-flex; align-items:center; }
    /* A Keep Exploring slot is a two-line block (label over description), so it
       takes the height and NOT the inline-flex above — that would lay its two
       paragraphs out side by side. It only ever needed the height. */
    .mj-ke-slot { min-height:44px; }
    .seo-browse-btn { justify-content:center; }
  }
  /* The rule that used to sit above these links now lives on .seo-shop-foot, which
     is the block they sit in — one rule, owned by the thing it closes. */
  .seo-shop-links { display:flex; flex-wrap:wrap; justify-content:center; gap:18px; font-family:'Playfair Display','Playfair Display Fallback',serif; font-size:14px; margin:0; }
  .seo-shop-links a { color:#3B2A1E; text-decoration:none; }
  .seo-shop-links a:hover { text-decoration:underline; }

  /* Community reviews — visible block, matches the React "From the Community". */
  /* No measure of its own any more — it sits inside .seo-shop-inner, which already
     owns the page's 1100px column and its gutters. It used to be a sibling of that
     wrapper and carried a duplicate copy of both. */
  .seo-shop-community { margin:56px 0 0; }
  .seo-shop-community-empty { font-family:'Playfair Display','Playfair Display Fallback',serif; font-style:italic; color:#8A6E52; font-size:15px; margin:0; }
  .seo-shop-community-grid { display:grid; grid-template-columns:1fr; gap:20px; }
  @media (min-width:1024px) { .seo-shop-community-grid { grid-template-columns:1fr 1fr; gap:24px; } }



  .ev-page { width:100%; background:#FCF7D9; padding:40px 24px clamp(56px,8vw,96px); box-sizing:border-box; }
  .ev-wrap { max-width:820px; margin:0 auto; }

  .ev-crumbs { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:11px; letter-spacing:0.14em; text-transform:uppercase; color:#8A7355; margin:0 0 16px; line-height:1.5; }
  .ev-crumbs a { color:#8A7355; text-decoration:none; border-bottom:1px solid transparent; }
  .ev-crumbs a:hover { border-bottom-color:#8A7355; }
  .ev-crumbs span { margin:0 8px; }

  .ev-head { margin:0 0 26px; }
  .ev-h1 { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:700; font-size:36px; line-height:1.15; color:#4A3626; margin:0; }
  /* ONE SENTENCE, AND NO STAT LINE. A count above a list the reader can already see
     describes something that is on screen. */
  .ev-lede { font-family:'Fraunces',Georgia,serif; font-size:16px; line-height:1.6; color:#5C4A38; max-width:620px; margin:14px 0 0; }

  /* ── City page: the meet list ──
     A rule above every entry and one closing the last, so the list reads as rows
     rather than as separated cards. */
  .ev-meets { border-bottom:1px solid #D8C6A6; }
  a.ev-meet { display:block; padding:20px 0; border-top:1px solid #D8C6A6; text-decoration:none; color:#4A3626; transition:color .15s ease; }
  a.ev-meet:hover .ev-meet-name { color:#8A6A4F; }
  /* Name left, recurrence right, ONE BASELINE. align-items:baseline rather than
     center, so a 24px name and an 11px caps line sit on the same line rather than
     being centred against each other. */
  .ev-meet-top { display:flex; align-items:baseline; justify-content:space-between; gap:18px; flex-wrap:wrap; }
  .ev-meet-name { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:700; font-size:24px; line-height:1.2; color:#4A3626; margin:0; transition:color .15s ease; }
  .ev-meet-when { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:14px; letter-spacing:0.18em; text-transform:uppercase; color:#8A6A4F; white-space:nowrap; }
  .ev-meet-where { display:block; font-family:'Fraunces',Georgia,serif; font-size:15.5px; line-height:1.6; color:#5C4A38; margin:8px 0 0; }

  /* ── Meet page: the detail row ── */
  .ev-details { display:grid; grid-template-columns:1fr 1fr; gap:30px; border-top:1px solid #D8C6A6; padding:22px 0 0; margin:0; }
  .ev-detail-label { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:10.5px; letter-spacing:0.2em; text-transform:uppercase; color:#8A7355; margin:0 0 7px; line-height:1.4; }
  .ev-detail-value { font-family:'Fraunces',Georgia,serif; font-size:16px; line-height:1.5; color:#4A3626; margin:0; }
  .ev-detail-address { font-family:'Fraunces',Georgia,serif; font-size:14px; line-height:1.5; color:#5C4A38; margin:5px 0 0; }
  .ev-venue-link { color:#4A3626; text-decoration:none; border-bottom:1px solid #B49B7A; padding-bottom:2px; }
  .ev-venue-link:hover { color:#8A6A4F; }

  .ev-actions { display:flex; align-items:center; justify-content:center; flex-wrap:wrap; gap:6px 24px; margin:18px 0 0; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:11px; letter-spacing:0.16em; text-transform:uppercase; line-height:1.6; }
  .ev-directions { color:#4A3626; text-decoration:none; border-bottom:1px solid #4A3626; padding-bottom:2px; }
  .ev-confirmed { color:#8A7355; }

  /* ── Part Six: the closing line ──
     56px above and 52px below, so it is not attached to whatever ended above it.
     The gaps are real spacer spans, not runs of non-breaking spaces, which is what
     lets them collapse at a breakpoint instead of being frozen into the text. */
  .ev-close { display:flex; align-items:baseline; justify-content:center; flex-wrap:wrap; row-gap:10px; margin:56px 0 52px; font-family:'Fraunces',Georgia,serif; font-size:15px; line-height:1.6; text-align:center; }
  .ev-close-text { color:#5C4A38; }
  .ev-close-cta { color:#4A3626; text-decoration:none; border-bottom:1px solid #4A3626; padding-bottom:3px; }
  .ev-close-index { color:#5C4A38; text-decoration:none; }
  .ev-close-index:hover { color:#4A3626; }
  /* .ev-close-dot is gone with the middots it styled. */
  .ev-gap-34 { display:inline-block; width:34px; }
  .ev-gap-26 { display:inline-block; width:26px; }

  @media (max-width: 767px) {
    .ev-details { grid-template-columns:1fr; gap:22px; }
  }
  @media (max-width: 699px) {
    /* THE SPACERS AND THE DOT COME OUT, and a real column-gap does their job.
       Measured: left in, each spacer and the middot is its own flex item and can
       wrap onto a line by itself, which put the row on four lines at 375px and five
       at 320px with a stranded middot among them. Three items and an 18px gap wrap
       into the two or three rows the spec asks for, and the gap is the same 18px the
       spacers were collapsing to. */
    .ev-gap-34, .ev-gap-26 { display:none; }
    .ev-close { column-gap:18px; }
    .ev-h1 { font-size:29px; }
  }
  @media (max-width: 639px) {
    .ev-page { padding-left:18px; padding-right:18px; }
    .ev-meet-name { font-size:21px; }
    .ev-meet-top { gap:6px; }
  }


/* Cars and Coffee pages — chocolate banner, cream body, hairline rules. Same
   vocabulary as statePage: no new colours, no decorative awnings. An awning renders
   only at a seam between two DIFFERENT coloured bands, and these pages have one
   chocolate banner above one cream body, which the shared header already handles. */
.mj-cc-banner{background:#3D2B1F;color:#FCF7D9;min-height:200px;box-sizing:border-box;padding:32px;display:flex;flex-direction:column;justify-content:center;}
.mj-cc-banner-in{max-width:1100px;margin:0 auto;width:100%;}
.mj-cc-crumbs{font-family:'Fraunces', Georgia, serif;font-size:11px;color:rgba(252,247,217,0.78);margin:0 0 14px;}
.mj-cc-crumbs a{color:rgba(252,247,217,0.78);text-decoration:none;border-bottom:1px solid transparent;}
.mj-cc-crumbs a:hover{border-bottom-color:rgba(252,247,217,0.78);}
.mj-cc-crumbs span{margin:0 6px;}
.mj-cc-eyebrow{font-family:'Fraunces', Georgia, serif;font-size:11px;letter-spacing:0.18em;text-transform:uppercase;color:rgba(252,247,217,0.78);margin:0 0 8px;}
.mj-cc-h1{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-size:38px;font-weight:700;line-height:1.05;color:#FCF7D9;margin:0;}
.mj-cc-stats{font-family:'Fraunces', Georgia, serif;font-size:14px;color:rgba(252,247,217,0.78);margin:10px 0 0;}

.mj-cc-sec{max-width:1100px;margin:0 auto;padding:34px 32px;box-sizing:border-box;}
.mj-cc-h2{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-size:22px;font-weight:700;color:#3D2B1F;margin:0 0 16px;}
.mj-cc-intro{font-family:'Fraunces', Georgia, serif;font-size:15px;line-height:1.6;color:rgba(61,43,31,0.68);margin:0 0 8px;max-width:70ch;}

/* ── HUB HERO ─────────────────────────────────────────────────────────────
   The headline is the site's mixed serif/script lockup, the same device
   MixedHeading draws on the React pages and splitTrailingScript draws on the
   other server pages: Playfair 900 upright, one word in Pinyon Script.
   The script word is set at 1.5em because Pinyon's cap height is roughly two
   thirds of Playfair's at the same font-size — matched optically, the two words
   read as one line rather than as a large word beside a small one. Its
   line-height is 0 so that larger size cannot open up the line box, and its
   vertical-align is baseline so the two sit on one baseline rather than on their
   own box edges. Neither is bigger than the 38px headline this replaces. */
.mj-cc-h1-mixed{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-size:38px;font-weight:900;line-height:1.05;letter-spacing:-0.01em;color:#FCF7D9;margin:0;}
.mj-cc-h1-script{font-family:'Pinyon Script', 'Pinyon Script Fallback', cursive;font-weight:400;font-size:1.5em;line-height:0;vertical-align:baseline;display:inline-block;}
.mj-cc-sub{font-family:'Fraunces', Georgia, serif;font-size:14px;color:rgba(252,247,217,0.78);margin:10px 0 0;}

/* ── MEET INDEX ───────────────────────────────────────────────────────────
   An editorial index, not cards. Every row is two columns: the name block on the
   left and the schedule/place on the right. The name block is the only one that
   grows, and min-width:0 is what lets it: without it a long venue name sets the
   column's minimum width to its own content and pushes the right column out of
   the row.

   NO INDEX NUMBER. It used to open every row with 01, 02, 03. Numbering earns
   its place when the order means something — a crawl's stops run in route order
   — and this is just every live meet, so the numbers only invited the reader to
   wonder what the ranking was. With them gone every name starts on the row's own
   left edge instead of 38px in.

   THE NAME WRAPS. It was nowrap with an ellipsis, so a long title was cut at
   whatever width that row's right column happened to leave — which is what made
   one row look shorter and set further left than its neighbours, since the right
   column is shrink-to-fit and "39 stops" is wider than "4 stops". Two lines of
   title is not a layout problem; a title cut at a different point on every row
   is. The venue line keeps its ellipsis: it is a secondary line and a second row
   of it would outweigh the name above it.

   ONE RULE PER ROW, on the top edge, plus one on the list's bottom edge. Drawn
   the other way round — a rule under every row plus one above the first — the
   last row's rule and the band's own bottom padding stack into a line floating
   above nothing. */
.mj-cc-index{list-style:none;margin:0;padding:0;border-bottom:1px solid rgba(61,43,31,0.22);}
.mj-cc-row{display:flex;align-items:flex-start;gap:16px;padding:20px 0;border-top:1px solid rgba(61,43,31,0.22);}
.mj-cc-body{flex:1 1 auto;min-width:0;}
.mj-cc-name{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-size:18px;font-weight:500;line-height:1.25;color:#3D2B1F;margin:0;overflow-wrap:anywhere;}
.mj-cc-name a{color:#3D2B1F;text-decoration:none;}
.mj-cc-name a:hover{text-decoration:underline;}
.mj-cc-venue{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-style:italic;font-size:14px;line-height:1.35;color:rgba(61,43,31,0.68);margin:3px 0 0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
/* The right column never shrinks below the width of its longest line, so the two
   columns keep a real gutter instead of the name running up against the
   schedule on the row with the longest title. */
.mj-cc-meta{flex:0 0 auto;text-align:right;}
.mj-cc-rec{font-family:'Fraunces', Georgia, serif;font-size:14px;font-weight:600;letter-spacing:0.14em;text-transform:uppercase;color:#3D2B1F;margin:0;white-space:nowrap;}
/* Plain text, not a link. See the comment on the row builder. */
.mj-cc-place{font-family:'Fraunces', Georgia, serif;font-size:14px;color:rgba(61,43,31,0.68);margin:4px 0 0;white-space:nowrap;}
/* The right column drops under the name block and left-aligns — flush with it,
   since there is no number column to clear any more. */
@media(max-width:767px){
  .mj-cc-row{flex-wrap:wrap;}
  .mj-cc-meta{flex:1 1 100%;text-align:left;margin-top:8px;}
  .mj-cc-place{white-space:normal;}
  .mj-cc-h1-mixed{font-size:32px;}
}
/* The band's own top padding is the air above the first rule — 40px desktop, 28px
   mobile — so the list needs no margin of its own and an empty list leaves no
   stranded gap. */
.mj-cc-sec--index{padding-top:40px;}
@media(max-width:767px){.mj-cc-sec--index{padding-top:28px;}}
.mj-cc-note{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-style:italic;font-size:16px;color:rgba(61,43,31,0.68);text-align:center;margin:32px 0;}

/* City index on the hub — no longer rendered there (the hub is one numbered index at
   every scale now, with each row's city linking to its own page), kept because the
   rules cost nothing and removing a shared block is its own change. */
.mj-cc-state{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-size:17px;font-weight:700;color:#3D2B1F;margin:26px 0 8px;padding-bottom:6px;border-bottom:1px solid rgba(61,43,31,0.22);}
.mj-cc-state:first-of-type{margin-top:0;}
.mj-cc-cities{list-style:none;margin:0;padding:0;column-count:3;column-gap:28px;}
.mj-cc-cities li{break-inside:avoid;margin:0 0 7px;}
.mj-cc-cities a{font-family:'Fraunces', Georgia, serif;font-size:14px;color:#3D2B1F;text-decoration:none;border-bottom:1px solid transparent;}
.mj-cc-cities a:hover{border-bottom-color:#3D2B1F;}
.mj-cc-count{font-family:'Fraunces', Georgia, serif;font-size:12px;color:rgba(61,43,31,0.68);}

/* Event cards */
.mj-cc-list{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(2,1fr);gap:16px;}
.mj-cc-card{border:1px solid rgba(61,43,31,0.22);padding:18px 20px;box-sizing:border-box;height:100%;}
.mj-cc-card-name{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-size:18px;font-weight:700;color:#3D2B1F;margin:0 0 6px;}
.mj-cc-card-name a{color:#3D2B1F;text-decoration:none;}
.mj-cc-card-name a:hover{text-decoration:underline;}
.mj-cc-when{font-family:'Fraunces', Georgia, serif;font-size:14px;color:#3D2B1F;margin:0 0 6px;}
.mj-cc-where{font-family:'Fraunces', Georgia, serif;font-size:14px;color:rgba(61,43,31,0.68);margin:0;line-height:1.5;}
.mj-cc-where a{color:#3D2B1F;text-decoration:none;border-bottom:1px solid rgba(61,43,31,0.22);}
.mj-cc-where a:hover{border-bottom-color:#3D2B1F;}
.mj-cc-athost{font-family:'Fraunces', Georgia, serif;font-size:11px;letter-spacing:0.1em;text-transform:uppercase;color:rgba(61,43,31,0.68);display:block;margin-top:8px;}

/* Event page blocks */
.mj-cc-block{border-top:1px solid rgba(61,43,31,0.22);padding-top:20px;margin-top:24px;}
.mj-cc-block:first-of-type{border-top:0;padding-top:0;margin-top:0;}
.mj-cc-dl{margin:0;font-family:'Fraunces', Georgia, serif;}
.mj-cc-dt{font-size:11px;letter-spacing:0.1em;text-transform:uppercase;color:rgba(61,43,31,0.68);margin:0 0 3px;}
.mj-cc-dd{font-size:15px;color:#3D2B1F;margin:0 0 14px;line-height:1.5;}
.mj-cc-link{font-family:'Fraunces', Georgia, serif;font-size:14px;font-weight:600;color:#3D2B1F;text-decoration:none;border-bottom:1px solid rgba(61,43,31,0.22);padding-bottom:2px;}
.mj-cc-link:hover{border-bottom-color:#3D2B1F;}
.mj-cc-confirmed{font-family:'Fraunces', Georgia, serif;font-size:12px;color:rgba(61,43,31,0.68);margin:28px 0 0;}
.mj-cc-claim{font-family:'Fraunces', Georgia, serif;font-size:14px;color:rgba(61,43,31,0.68);margin:10px 0 0;}
.mj-cc-claim a{color:#3D2B1F;}

@media(max-width:767px){
  .mj-cc-banner{padding:20px;}
  .mj-cc-h1{font-size:30px;}
  .mj-cc-sec{padding-left:20px;padding-right:20px;}
  .mj-cc-cities{column-count:1;}
  .mj-cc-list{grid-template-columns:1fr;}
}


/* Marquee — single source (base44/shared/websiteMarquee.ts). */
.mj-mq{overflow:hidden;width:100%;display:flex;align-items:center;box-sizing:border-box;}
.mj-mq-tilt{width:100%;display:flex;}
.mj-mq-track{display:flex;flex-wrap:nowrap;white-space:nowrap;will-change:transform;animation:mj-mq-scroll 42s linear infinite;}
.mj-mq-track > span{white-space:nowrap;}
@keyframes mj-mq-scroll{from{transform:translateX(0);}to{transform:translateX(-50%);}}
@media (prefers-reduced-motion:reduce){.mj-mq-track{animation:none;}}

/* CREAM, level, ruled, Fraunces — the homepage and Joe's Picks. */
.mj-mq--cream{height:48px;background:#FCF7D9;border-top:1px solid #3D2B1F;border-bottom:1px solid #3D2B1F;}
.mj-mq--cream .mj-mq-track > span{font-family:'Fraunces', Georgia, serif;text-transform:uppercase;font-size:14px;letter-spacing:0.2em;color:#3D2B1F;}
.mj-mq--tall{height:64px;}

/* BLUSH, level, Playfair — Cars and Coffee. No rules: the band is a solid colour
   between two others and its own edges are the divider. Flat 64px, not a vw clamp:
   the clamp only existed to hold the rotated text's vertical drift. */
.mj-mq--blush{height:64px;background:#F3DAD3;border:0;}
.mj-mq--blush .mj-mq-track > span{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;text-transform:uppercase;font-size:14px;letter-spacing:0.2em;font-weight:700;color:#3D2B1F;}
/* The tilt wrapper is kept as a plain full-width flex row. It used to be 108% wide
   at -4% so the rotated ends were cut off-screen rather than showing a wedge of bare
   background in the corners; level, it needs neither. */


/* Keep Exploring — single source (base44/shared/websiteExplore.ts). */
.mj-ke{max-width:1100px;margin:0 auto;}
.mj-ke-rule{border:none;border-top:1px solid #D9C9A8;width:100vw;max-width:100vw;margin:0 calc(50% - 50vw) 20px;}
.mj-ke-title{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-style:italic;font-weight:700;font-size:24px;color:#3B2A1E;margin:0 0 24px;text-align:left;}
.mj-ke-grid{display:grid;grid-template-columns:1fr;gap:24px;}
@media(min-width:700px){.mj-ke-grid{grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:40px;}}
.mj-ke-slot{text-decoration:none;display:block;}
.mj-ke-label{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:700;font-size:12px;letter-spacing:0.14em;text-transform:uppercase;margin:0;color:#3B2A1E;transition:opacity 160ms ease;}
.mj-ke-desc{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-size:15px;margin:6px 0 0;display:flex;align-items:center;justify-content:space-between;gap:8px;color:#3B2A1E;}
/* These are links, and until now they gave no sign of it — no underline, no colour
   change, nothing on hover. The label and the arrow are already chocolate on cream,
   so there is no darker to go: the affordance is an underline under the destination
   plus the arrow moving toward it, which is what a "keep reading" link does
   everywhere. The label dims slightly so the whole cell reacts as one target rather
   than only the line the cursor happens to be over.
   The arrow is an SVG in React (lucide) and a text glyph on the server pages, so the
   nudge is applied to the desc's LAST child either way. */
.mj-ke-desc > *:last-child{transition:transform 160ms ease;}
.mj-ke-slot:hover .mj-ke-desc > span:first-child,
.mj-ke-slot:focus-visible .mj-ke-desc > span:first-child{text-decoration:underline;text-underline-offset:3px;}
.mj-ke-slot:hover .mj-ke-desc > *:last-child,
.mj-ke-slot:focus-visible .mj-ke-desc > *:last-child{transform:translateX(3px);}
.mj-ke-slot:hover .mj-ke-label,
.mj-ke-slot:focus-visible .mj-ke-label{opacity:0.65;}
@media (prefers-reduced-motion:reduce){
  .mj-ke-desc > *:last-child{transition:none;}
  .mj-ke-slot:hover .mj-ke-desc > *:last-child,
  .mj-ke-slot:focus-visible .mj-ke-desc > *:last-child{transform:none;}
}


.mj-mv-head{font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:700;font-size:clamp(1.15rem,2.4vw,1.4rem);line-height:1.2;color:#3D2B1F;margin:0 0 6px;}
.mj-mv-note{font-family:'Fraunces',Georgia,serif;font-size:14px;font-style:italic;color:rgba(61,43,31,0.68);margin:0 0 20px;max-width:52ch;}
.mj-mv-list{list-style:none;margin:0;padding:0;}
.mj-mv-list li{margin:0 0 12px;}
.mj-mv-card{display:block;border:1px solid rgba(61,43,31,0.22);border-radius:2px;background:transparent;padding:clamp(16px,2.2vw,22px);text-decoration:none;color:#3D2B1F;box-sizing:border-box;width:100%;}
.mj-mv-card:hover{border-color:#3D2B1F;}
.mj-mv-eyebrow{display:block;font-family:'Fraunces',Georgia,serif;font-size:10px;font-weight:600;letter-spacing:0.18em;text-transform:uppercase;color:rgba(61,43,31,0.68);margin:0 0 6px;}
.mj-mv-name{display:block;font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif;font-weight:700;font-size:clamp(1.05rem,2.2vw,1.25rem);line-height:1.2;margin:0;}
.mj-mv-where{display:block;font-family:'Fraunces',Georgia,serif;font-size:14px;color:rgba(61,43,31,0.68);margin:6px 0 0;}
.mj-mv-rows{display:block;margin:10px 0 0;}
.mj-mv-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 10px;font-family:'Fraunces',Georgia,serif;font-size:14px;color:#3D2B1F;padding:7px 0;border-top:1px solid rgba(61,43,31,0.22);}
.mj-mv-row:first-child{border-top:none;}
.mj-mv-day{font-weight:600;min-width:6.5em;}
.mj-mv-time{color:rgba(61,43,31,0.68);}
.mj-mv-place{flex:1 1 12em;min-width:0;}


  .lr-page { width:100%; background:#FCF7D9; padding:40px 24px clamp(56px,8vw,96px); box-sizing:border-box; }
  .lr-wrap { max-width:1000px; margin:0 auto; }

  .lr-crumbs { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:11px; letter-spacing:0.14em; text-transform:uppercase; color:#8A7355; margin:0 0 14px; line-height:1.4; }
  .lr-crumbs a { color:#8A7355; text-decoration:none; border-bottom:1px solid transparent; }
  .lr-crumbs a:hover { border-bottom-color:#8A7355; }
  .lr-crumbs span { margin:0 8px; }

  /* TWO ENDS, NO DEAD COLUMN. The left column takes the space it needs and the right
     one takes only its own width, so nothing between them is empty. align-items:end
     is what bottom-aligns the stats and the button against the intro. */
  .lr-head { display:flex; align-items:flex-end; justify-content:space-between; gap:40px; }
  .lr-head-left { min-width:0; }
  .lr-head-right { flex-shrink:0; text-align:right; }

  .lr-eyebrow { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:11px; letter-spacing:0.3em; text-transform:uppercase; color:#8A7355; margin:0 0 14px; line-height:1.3; }
  /* ONE LINE, TWO FACES. The display half and the script half sit on one baseline;
     the script face runs larger because Pinyon's x-height is a fraction of Playfair's
     and matching the point size would make it read as small print. */
  .lr-h1 { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-weight:900; font-size:42px; line-height:1.05; letter-spacing:0.01em; color:#4A3626; margin:0; }
  .lr-h1-script { font-family:'Pinyon Script','Pinyon Script Fallback',cursive; font-weight:400; font-size:52px; color:#8A6A4F; line-height:1; }
  .lr-intro { font-family:'Fraunces',Georgia,serif; font-size:16px; line-height:1.65; color:#5C4A38; max-width:560px; margin:14px 0 0; }

  /* THE CITY LINKS RAN ON FROM ONE ANOTHER once the middots between them went.
     A gap is the separation now, which is also what the footer's legal row does. */
  .lr-browse-links { display:inline-flex; flex-wrap:wrap; gap:4px 18px; vertical-align:baseline; }
  .lr-stats { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:14px; letter-spacing:0.22em; text-transform:uppercase; color:#8A7355; margin:0 0 12px; line-height:1.4; white-space:nowrap; }
  .lr-btn { display:inline-flex; align-items:center; justify-content:center; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:10.5px; letter-spacing:0.24em; text-transform:uppercase; color:#4A3626; text-decoration:none; border:1px solid #B49B7A; border-radius:0; background:none; padding:10px 24px; cursor:pointer; white-space:nowrap; }

  /* A RULE REPLACEMENT, never a background. It is its own row and nothing is ever
     laid over it. */
  .lr-band { margin:28px 0 0; line-height:0; }

  .lr-utility { display:flex; align-items:baseline; justify-content:space-between; gap:24px; flex-wrap:wrap; margin:14px 0 0; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:10.5px; letter-spacing:0.2em; text-transform:uppercase; }
  .lr-browse { margin:0; color:#8A7355; }
  .lr-browse a { color:#4A3626; text-decoration:none; border-bottom:1px solid transparent; }
  .lr-browse a:hover { border-bottom-color:#4A3626; }
  /* THE SPACES AROUND THIS ARE LOAD-BEARING, in the markup rather than here. Inline
     elements with no whitespace between them offer the browser no break opportunity,
     so the four browse cities sat on one 348px line and overflowed a 320px viewport
     by 46px. The margin is smaller because the spaces now carry part of the gap. */
  /* .lr-dot is gone with the middots it styled; the rows below carry gaps. */
  .lr-sort { display:flex; align-items:baseline; }
  .lr-sort-btn { position:relative; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:10.5px; letter-spacing:0.2em; text-transform:uppercase; color:#8A7355; background:none; border:none; padding:0; cursor:pointer; line-height:1.4; }
  .lr-sort-btn[aria-pressed="true"] { color:#4A3626; border-bottom:1px solid #4A3626; }
  /* 44px of touchable height without moving the baseline the row is aligned on. */
  .lr-sort-btn::after { content:''; position:absolute; left:-6px; right:-6px; top:50%; transform:translateY(-50%); height:44px; }

  /* MASONRY, AND IT IS REQUIRED. Some reviews carry a photo and some do not, so a
     fixed row grid leaves a band of dead space under every short card in a row. CSS
     columns pack them instead. break-inside:avoid is what keeps a card whole. */
  .lr-grid { column-count:3; column-gap:18px; margin:26px 0 0; }
  .lr-card { display:block; break-inside:avoid; -webkit-column-break-inside:avoid; page-break-inside:avoid; background:#F7EFD0; border:none; border-radius:0; padding:18px; margin:0 0 18px; text-decoration:none; color:#4A3626; transition:background-color .15s ease; }
  .lr-card:hover { background:#F2E7C2; }

  /* ONE RATIO, NOT THE PHOTO'S OWN, and it is a deliberate trade rather than an
     oversight. Honouring each image's intrinsic ratio means either shipping its
     dimensions or letting height:auto resolve after the image loads, which reflows
     every card below it in the column. The spec asks for no reflow explicitly, and
     on a masonry layout a late reflow moves the whole column. 4:5 is the tall end of
     the permitted 1:1 to 4:5 band; object-fit:cover crops to it rather than
     distorting. The width and height attributes match it exactly, so the browser
     reserves the right box before the bytes arrive.

     WHAT IT WOULD TAKE TO DO THIS PROPERLY: the Review entity stores photo_url and
     nothing else about the file, so the intrinsic ratio is unknowable server-side.
     Per-photo ratios need the WIDTH AND HEIGHT CAPTURED AT UPLOAD and stored on the
     record; with those, each card can carry its own aspect-ratio clamped between 1:1
     and 4:5 and still reserve the correct box before the image arrives. Until that
     exists, a single ratio is the only version of this that does not reflow. Do not
     "fix" this by removing the ratio and letting height resolve on load. */
  .lr-photo { display:block; width:100%; height:auto; border-radius:0; object-fit:cover; margin:0 0 12px; aspect-ratio:4 / 5; }

  .lr-stars { display:inline-block; font-size:11px; letter-spacing:0.14em; line-height:1; }
  .lr-star-on { color:#8A6A4F; }
  .lr-star-off { color:#D8C6A6; }

  /* FOUR LINES, AND THE CLAMP IS A REQUIREMENT rather than a style. Every review
     here also lives on its shop page, which is the canonical home for that text;
     publishing it whole in two places is the duplicate content this cap avoids. */
  .lr-body { display:-webkit-box; -webkit-line-clamp:4; -webkit-box-orient:vertical; overflow:hidden; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-style:italic; font-size:16px; line-height:1.55; color:#4A3626; margin:10px 0 0; }
  .lr-shop { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:14px; font-weight:600; letter-spacing:0.18em; text-transform:uppercase; color:#4A3626; margin:12px 0 0; line-height:1.4; }
  .lr-arrow { color:#8A6A4F; }
  .lr-card:hover .lr-shop { color:#8A6A4F; }
  .lr-meta { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:14px; letter-spacing:0.18em; text-transform:uppercase; color:#8A7355; margin:6px 0 0; line-height:1.5; }

  .lr-more-row { text-align:center; margin:30px 0 0; }
  .lr-none { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-style:italic; font-size:15px; color:#5C4A38; text-align:center; margin:44px 0 0; }

  .lr-close { display:flex; justify-content:center; flex-wrap:wrap; gap:28px; margin:48px 0 0; }
  .lr-close a { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:10.5px; letter-spacing:0.2em; text-transform:uppercase; color:#4A3626; text-decoration:none; border-bottom:1px solid #B49B7A; padding-bottom:3px; }

  @media (max-width: 999px) { .lr-grid { column-count:2; } }
  @media (max-width: 899px) { .lr-grid { column-count:2; } }
  /* STACKED, BOTH ENDS LEFT ALIGNED. A right-aligned block under a left-aligned one
     reads as two unrelated columns that happened to collapse. */
  @media (max-width: 799px) {
    .lr-head { flex-direction:column; align-items:flex-start; gap:22px; }
    .lr-head-right { text-align:left; }
    .lr-h1 { font-size:34px; }
    .lr-h1-script { font-size:42px; }
  }
  @media (max-width: 639px) {
    .lr-page { padding-left:18px; padding-right:18px; }
    .lr-grid { column-count:1; }
    .lr-h1 { font-size:29px; }
    .lr-h1-script { font-size:36px; }
    .lr-utility { gap:12px; }
  }


  /* ── 1 + 2. HERO ─────────────────────────────────────────────────────── */
  .mj-c2-hero .mj-bd-inner { padding-top:18px; padding-bottom:30px; }
  .mj-c2-crumbs { font-family:'Fraunces',Georgia,serif; font-size:11px; color:rgba(252,247,217,0.72); margin:0 0 18px; text-align:left; }
  .mj-c2-crumbs a { color:rgba(252,247,217,0.72); text-decoration:none; }
  .mj-c2-crumbs a:hover { color:#FCF7D9; text-decoration:underline; }
  .mj-c2-crumb-sep { margin:0 7px; opacity:0.55; }
  /* ABOUT 240px, and it is a minimum rather than a height: a two-line local_intro
     on a narrow screen has to be able to make the band taller, and a band with a
     fixed height would clip it. */
  .mj-c2-herobody { min-height:186px; display:flex; flex-direction:column; align-items:center; justify-content:center; text-align:center; }
  .mj-c2-eyebrow { font-family:'Fraunces',Georgia,serif; font-size:11px; font-weight:600; letter-spacing:0.16em; text-transform:uppercase; color:#BD9442; margin:0 0 14px; }
  .mj-c2-h1 { margin:0; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:44px; font-weight:500; line-height:1.06; color:#FCF7D9; }
  .mj-c2-city { font-family:'Pinyon Script','Pinyon Script Fallback',cursive; font-size:52px; font-weight:400; line-height:1; }
  .mj-c2-herocol { max-width:620px; margin:18px auto 0; }
  .mj-c2-intro { font-family:'Fraunces',Georgia,serif; font-size:15px; line-height:1.6; color:#FCF7D9; margin:0; }
  .mj-c2-local { font-family:'Fraunces',Georgia,serif; font-size:14px; line-height:1.65; color:rgba(252,247,217,0.78); margin:10px 0 0; }

  /* ── 4. JOE'S PICK ───────────────────────────────────────────────────── */
  .mj-c2-pickinner { display:flex; gap:22px; align-items:stretch; text-align:left; }
  /* THE RAIL IS THE HEADING, turned. It is a real heading in the source, read in
     order by a screen reader, and rotated by CSS only — not an image, and not a
     string of one-letter spans. */
  .mj-c2-rail { flex:0 0 auto; margin:0; border-left:2px solid #B08A3E; padding-left:12px; display:flex; align-items:flex-start; }
  .mj-c2-rail span { display:block; writing-mode:vertical-rl; transform:rotate(180deg); font-family:'Fraunces',Georgia,serif; font-size:11px; font-weight:600; letter-spacing:0.16em; text-transform:uppercase; color:#715928; white-space:nowrap; }
  .mj-c2-pickmain { display:flex; gap:22px; align-items:flex-start; min-width:0; }
  .mj-c2-pickphoto { flex:0 0 auto; width:168px; height:168px; object-fit:cover; border-radius:2px; display:block; }
  .mj-c2-pickbody { min-width:0; }
  .mj-c2-pickname { margin:0; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:32px; font-weight:500; line-height:1.15; color:#3D2B1F; }
  .mj-c2-pickname a { color:inherit; text-decoration:none; }
  .mj-c2-pickname a:hover { text-decoration:underline; }
  .mj-c2-pickmeta { margin:8px 0 0; font-family:'Fraunces',Georgia,serif; font-size:12px; color:rgba(61,43,31,0.68); }
  .mj-c2-pickreview { margin:14px 0 0; max-width:560px; font-family:'Fraunces',Georgia,serif; font-size:15px; line-height:1.75; color:#3D2B1F; }
  .mj-c2-pickmore { margin:16px 0 0; }
  .mj-c2-pickmore a { font-family:'Fraunces',Georgia,serif; font-size:13px; font-weight:600; color:#3D2B1F; text-decoration:none; border-bottom:2px solid #B08A3E; padding-bottom:2px; }

  /* ── THE PAID BAND ───────────────────────────────────────────────────
     websitePaidBlock's markup, this page's type. The heading becomes the same
     brass eyebrow every other band on the page uses, and the disclosure becomes
     the page's small print instead of a second run of letterspaced capitals
     competing with it. */
  .mj-c2-paid .mj-pp-head { display:block; margin:0 0 12px; }
  .mj-c2-paid .mj-pp-h { font-family:'Fraunces',Georgia,serif; font-size:11px; font-weight:600; letter-spacing:0.16em; text-transform:uppercase; color:#715928; margin:0; }
  .mj-c2-paid .mj-pp-disc { font-family:'Fraunces',Georgia,serif; font-size:11px; letter-spacing:normal; text-transform:none; color:rgba(61,43,31,0.68); margin:4px 0 0; }

  /* ── 5. THE INDEX ────────────────────────────────────────────────────── */
  .mj-c2-indexhead { display:flex; align-items:baseline; justify-content:space-between; gap:20px; padding-bottom:12px; border-bottom:1px solid rgba(61,43,31,0.22); text-align:left; }
  .mj-c2-indexh { margin:0; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:26px; font-weight:500; line-height:1.2; color:#3D2B1F; }
  .mj-c2-indexloc { margin:0; flex:0 0 auto; font-family:'Fraunces',Georgia,serif; font-size:11px; font-weight:600; letter-spacing:0.16em; text-transform:uppercase; color:rgba(61,43,31,0.68); }
  .mj-c2-rows { list-style:none; margin:0; padding:0; }
  .mj-c2-row + .mj-c2-row { border-top:1px solid rgba(61,43,31,0.14); }
  .mj-c2-rowlink { display:flex; align-items:baseline; gap:16px; padding:15px 0; text-decoration:none; color:inherit; text-align:left; }
  .mj-c2-rowlink:hover .mj-c2-name { text-decoration:underline; }
  .mj-c2-num { flex:0 0 auto; min-width:28px; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:20px; font-weight:400; color:rgba(61,43,31,0.34); }
  .mj-c2-rowmain { flex:1 1 auto; min-width:0; }
  .mj-c2-name { display:block; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:20px; font-weight:500; line-height:1.25; color:#3D2B1F; }
  .mj-c2-pickmark { margin-left:10px; font-family:'Fraunces',Georgia,serif; font-size:11px; font-weight:600; letter-spacing:0.1em; text-transform:uppercase; color:#715928; white-space:nowrap; }
  .mj-c2-meta { display:block; margin-top:4px; font-family:'Fraunces',Georgia,serif; font-size:12px; line-height:1.5; color:rgba(61,43,31,0.68); }
  .mj-c2-rate { flex:0 0 auto; font-family:'Fraunces',Georgia,serif; font-size:13px; font-weight:600; color:#715928; white-space:nowrap; }

  /* ── 6. CRAWL AND COMMUNITY ──────────────────────────────────────────── */
  .mj-c2-ccgrid { display:grid; grid-template-columns:1.2fr 1fr; gap:44px; text-align:left; }
  .mj-c2-ccgrid--one { grid-template-columns:1fr; }
  /* The same eyebrow on a cream band. The modifier names the GROUND, not the
     colour: brass as type needs a different value on each, and a class called
     --light would read as "the light brass" and get used on the wrong band. */
  .mj-c2-eyebrow--onlight { color:#715928; margin-bottom:10px; }
  .mj-c2-colh { margin:0; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:26px; font-weight:500; line-height:1.2; color:#3D2B1F; }
  .mj-c2-route { display:flex; align-items:center; margin:14px 0 0; }
  .mj-c2-dot { width:7px; height:7px; border-radius:50%; background:#B08A3E; flex:0 0 auto; }
  .mj-c2-dotline { width:16px; height:1px; background:#B08A3E; flex:0 0 auto; }
  .mj-c2-dotmore { margin-left:6px; font-family:'Fraunces',Georgia,serif; font-size:11px; color:rgba(61,43,31,0.68); }
  .mj-c2-stops { margin:12px 0 0; font-family:'Fraunces',Georgia,serif; font-size:13px; line-height:1.6; color:rgba(61,43,31,0.68); }
  .mj-c2-morelink { margin:16px 0 0; }
  .mj-c2-morelink a { font-family:'Fraunces',Georgia,serif; font-size:13px; font-weight:600; color:#3D2B1F; text-decoration:none; border-bottom:2px solid #B08A3E; padding-bottom:2px; }
  .mj-c2-rev + .mj-c2-rev { margin-top:20px; }
  .mj-c2-revshop { margin:0; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:18px; font-weight:500; line-height:1.25; color:#3D2B1F; }
  .mj-c2-revshop a { color:inherit; text-decoration:none; }
  .mj-c2-revshop a:hover { text-decoration:underline; }
  .mj-c2-revbody { margin:6px 0 0; font-family:'Fraunces',Georgia,serif; font-size:14px; font-style:italic; line-height:1.6; color:#3D2B1F; }
  .mj-c2-revwho { margin:6px 0 0; font-family:'Fraunces',Georgia,serif; font-size:12px; color:rgba(61,43,31,0.68); }

  /* ── 7. FOOTER BAND ──────────────────────────────────────────────────── */
  .mj-c2-footgrid { display:grid; grid-template-columns:repeat(3,1fr); gap:40px; text-align:left; }
  .mj-c2-footlist { list-style:none; margin:0; padding:0; }
  .mj-c2-footlist li + li { margin-top:7px; }
  .mj-c2-footlist a, .mj-c2-footlink a { font-family:'Fraunces',Georgia,serif; font-size:14px; color:#FCF7D9; text-decoration:none; }
  .mj-c2-footlist a:hover, .mj-c2-footlink a:hover { text-decoration:underline; }
  .mj-c2-foottext { margin:0 0 10px; font-family:'Fraunces',Georgia,serif; font-size:14px; line-height:1.6; color:rgba(252,247,217,0.78); }
  .mj-c2-footlink a { border-bottom:2px solid #B08A3E; padding-bottom:2px; }

  /* ── NARROW ──────────────────────────────────────────────────────────── */
  @media (max-width: 760px) {
    .mj-c2-h1 { font-size:32px; }
    .mj-c2-city { font-size:38px; }
    .mj-c2-pickinner { flex-direction:column; gap:16px; }
    /* The rail turns back into a line of text: a vertical heading beside a column
       that is now the full width of the screen would leave it in a 20px gutter. */
    .mj-c2-rail { border-left:none; border-top:2px solid #B08A3E; padding:10px 0 0; }
    .mj-c2-rail span { writing-mode:horizontal-tb; transform:none; }
    .mj-c2-pickmain { flex-direction:column; }
    .mj-c2-ccgrid, .mj-c2-footgrid { grid-template-columns:1fr; gap:28px; }
    .mj-c2-indexhead { flex-direction:column; gap:6px; align-items:flex-start; }
  }


  .mj-s2 { max-width:720px; margin:0 auto; padding:0 20px; color:#3D2B1F; }
  /* 24 above, 20 below, and the hairline is the section's own top border, so the
     first section on the page does not draw one over nothing. */
  .mj-s2-sec { border-top:1px solid rgba(61,43,31,0.18); padding:24px 0 20px; }
  .mj-s2-sec--first { border-top:none; padding-top:20px; }

  .mj-s2-crumbs { font-family:'Fraunces',Georgia,serif; font-size:11px; color:rgba(61,43,31,0.70); margin:0 0 14px; }
  .mj-s2-crumbs a { color:rgba(61,43,31,0.70); text-decoration:none; }
  .mj-s2-crumbs a:hover { color:#3D2B1F; text-decoration:underline; }
  .mj-s2-slash { margin:0 7px; opacity:0.55; }
  .mj-s2-eyebrow { font-family:'Fraunces',Georgia,serif; font-size:11px; font-weight:600; letter-spacing:0.16em; text-transform:uppercase; color:#715928; margin:0 0 10px; }
  .mj-s2-h1 { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:38px; font-weight:500; line-height:1.14; margin:0; color:#3D2B1F; }
  /* THE PILL IS AN OUTLINE, and its WORDS are brass ink rather than the outline
     colour: #C9A94E is a mark and does not clear 4.5:1 as type on cream. */
  .mj-s2-pick { display:inline-block; vertical-align:middle; margin-left:12px; padding:5px 11px; border:1px solid #C9A94E; border-radius:999px; font-family:'Fraunces',Georgia,serif; font-size:11px; font-weight:600; letter-spacing:0.14em; text-transform:uppercase; color:#715928; white-space:nowrap; }
  .mj-s2-summary { max-width:640px; font-family:'Fraunces',Georgia,serif; font-size:16px; line-height:1.6; color:#3D2B1F; margin:14px 0 0; }

  /* ── ACTION ROW ──────────────────────────────────────────────────────── */
  .mj-s2-actions { display:flex; flex-wrap:wrap; gap:10px; margin:20px 0 0; }
  .mj-s2-btn { display:inline-flex; align-items:center; justify-content:center; height:42px; padding:0 18px; border:1px solid #3D2B1F; border-radius:2px; font-family:'Fraunces',Georgia,serif; font-size:11px; font-weight:600; letter-spacing:0.14em; text-transform:uppercase; color:#3D2B1F; text-decoration:none; background:transparent; }
  .mj-s2-btn:hover { background:rgba(61,43,31,0.06); }
  .mj-s2-btn--filled { background:#3D2B1F; color:#FCF7D9; }
  .mj-s2-btn--filled:hover { background:#2E1F16; }

  /* ── FACTS ROW ───────────────────────────────────────────────────────── */
  .mj-s2-facts { display:flex; gap:24px; align-items:flex-start; flex-wrap:wrap; }
  .mj-s2-map { position:relative; flex:0 0 auto; width:260px; height:118px; display:block; border:1px solid rgba(61,43,31,0.18); overflow:hidden; }
  .mj-s2-map img { display:block; width:100%; height:100%; object-fit:cover; }
  /* OUR OWN PIN, over Apple's picture. The snapshot is markerless on purpose so
     no Apple balloon can appear under this one, and the picture is NOT cropped at
     the bottom, so Apple's attribution stays visible — which is a term of use. */
  .mj-s2-pin { position:absolute; left:50%; top:50%; width:13px; height:13px; margin:-6.5px 0 0 -6.5px; border-radius:50%; background:#3D2B1F; border:2px solid #FCF7D9; box-shadow:0 1px 3px rgba(0,0,0,0.35); }
  .mj-s2-factcols { flex:1 1 300px; display:grid; gap:20px; }
  .mj-s2-factcols--1 { grid-template-columns:1fr; }
  .mj-s2-factcols--2 { grid-template-columns:repeat(2,1fr); }
  .mj-s2-factcols--3 { grid-template-columns:repeat(3,1fr); }
  .mj-s2-factcols--4 { grid-template-columns:repeat(2,1fr); }
  /* The quiet half of an In the Cup row: "Roaster" before "Coava", on one line. */
  .mj-s2-cuplabel { color:rgba(61,43,31,0.70); margin-right:8px; }
  .mj-s2-label { font-family:'Fraunces',Georgia,serif; font-size:11px; font-weight:600; letter-spacing:0.16em; text-transform:uppercase; color:#715928; margin:0 0 6px; }
  .mj-s2-factline { font-family:'Fraunces',Georgia,serif; font-size:14px; line-height:1.5; color:#3D2B1F; margin:0; }
  .mj-s2-hours summary { font-family:'Fraunces',Georgia,serif; font-size:14px; line-height:1.5; color:#3D2B1F; cursor:pointer; list-style:none; }
  .mj-s2-hours summary::-webkit-details-marker { display:none; }
  .mj-s2-hours summary::after { content:''; display:inline-block; width:6px; height:6px; margin-left:8px; border-right:1.5px solid rgba(61,43,31,0.70); border-bottom:1.5px solid rgba(61,43,31,0.70); transform:translateY(-2px) rotate(45deg); }
  .mj-s2-hours[open] summary::after { transform:translateY(1px) rotate(225deg); }
  .mj-s2-days { margin:8px 0 0; border-collapse:collapse; font-family:'Fraunces',Georgia,serif; font-size:13px; color:rgba(61,43,31,0.70); }
  .mj-s2-days th { text-align:left; font-weight:400; padding:2px 14px 2px 0; }
  .mj-s2-days td { padding:2px 0; }
  .mj-s2-chips { margin:0; display:flex; flex-wrap:wrap; gap:6px; }
  .mj-s2-chip { display:inline-block; padding:4px 10px; border:1px solid rgba(61,43,31,0.18); border-radius:999px; font-family:'Fraunces',Georgia,serif; font-size:12px; color:rgba(61,43,31,0.70); }

  /* ── JOE'S REVIEW ────────────────────────────────────────────────────── */
  .mj-s2-joe { display:flex; gap:24px; align-items:flex-start; }
  .mj-s2-joebody { flex:1 1 auto; min-width:0; max-width:680px; }
  .mj-s2-joemedia { flex:0 0 auto; width:200px; height:210px; object-fit:cover; display:block; }
  .mj-s2-joehead { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-style:italic; font-size:28px; font-weight:400; line-height:1.25; color:#3D2B1F; margin:0; }
  .mj-s2-joemeta { font-family:'Fraunces',Georgia,serif; font-size:12px; color:rgba(61,43,31,0.70); margin:8px 0 0; }
  .mj-s2-joetext { font-family:'Fraunces',Georgia,serif; font-size:16px; line-height:1.8; color:#3D2B1F; margin:14px 0 0; display:-webkit-box; -webkit-line-clamp:6; -webkit-box-orient:vertical; overflow:hidden; }
  /* A CHECKBOX, NOT A SCRIPT — the same pattern the header search panel uses, so
     this page stays scriptless and the expansion works with JS off. */
  .mj-s2-moretoggle { position:absolute; opacity:0; pointer-events:none; width:0; height:0; }
  .mj-s2-moretoggle:checked ~ .mj-s2-joetext { -webkit-line-clamp:unset; overflow:visible; }
  .mj-s2-morelabel { display:inline-block; margin-top:8px; font-family:'Fraunces',Georgia,serif; font-size:14px; font-weight:600; color:#3D2B1F; text-decoration:underline; cursor:pointer; }
  .mj-s2-more-shut { display:none; }
  .mj-s2-moretoggle:checked ~ .mj-s2-morelabel .mj-s2-more-open { display:none; }
  .mj-s2-moretoggle:checked ~ .mj-s2-morelabel .mj-s2-more-shut { display:inline; }

  /* ── ABOUT ───────────────────────────────────────────────────────────── */
  .mj-s2-sub { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:19px; font-weight:500; line-height:1.3; color:#3D2B1F; margin:16px 0 6px; }
  .mj-s2-sub:first-of-type { margin-top:0; }
  .mj-s2-para { max-width:680px; font-family:'Fraunces',Georgia,serif; font-size:16px; line-height:1.7; color:#3D2B1F; margin:0; }

  /* ── COMMUNITY ───────────────────────────────────────────────────────── */
  .mj-s2-h2 { font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:24px; font-weight:500; line-height:1.25; color:#3D2B1F; margin:0 0 16px; }
  .mj-s2-rev { max-width:720px; border:1px solid rgba(61,43,31,0.18); padding:18px; margin:0 0 14px; }
  .mj-s2-rev:last-child { margin-bottom:0; }
  .mj-s2-revtop { display:flex; align-items:center; gap:12px; }
  .mj-s2-avatar { flex:0 0 auto; width:40px; height:40px; border-radius:50%; background:#3D2B1F; color:#FCF7D9; display:flex; align-items:center; justify-content:center; font-family:'Playfair Display','Playfair Display Fallback',Georgia,serif; font-size:17px; }
  .mj-s2-revwho { flex:1 1 auto; min-width:0; }
  .mj-s2-revname { display:block; font-family:'Fraunces',Georgia,serif; font-size:15px; font-weight:600; color:#3D2B1F; }
  .mj-s2-revdrink { display:block; font-family:'Fraunces',Georgia,serif; font-size:13px; color:rgba(61,43,31,0.70); margin-top:2px; }
  .mj-s2-revright { flex:0 0 auto; text-align:right; }
  .mj-s2-stars { display:block; font-size:13px; color:#715928; letter-spacing:0.08em; }
  .mj-s2-revdate { display:block; font-family:'Fraunces',Georgia,serif; font-size:12px; color:rgba(61,43,31,0.70); margin-top:3px; }
  .mj-s2-revbody { max-width:680px; font-family:'Fraunces',Georgia,serif; font-size:16px; line-height:1.75; color:#3D2B1F; margin:14px 0 0; }
  .mj-s2-rev .mj-s2-chips { margin-top:12px; }

  /* ── LINK ROW ────────────────────────────────────────────────────────── */
  .mj-s2-links { display:flex; flex-wrap:wrap; justify-content:center; gap:30px; margin:0; }
  .mj-s2-links a { font-family:'Fraunces',Georgia,serif; font-size:11px; font-weight:600; letter-spacing:0.14em; text-transform:uppercase; color:#3D2B1F; text-decoration:none; }
  .mj-s2-links a:hover { text-decoration:underline; }
  .mj-s2-claim { text-align:center; margin:16px 0 0; font-family:'Fraunces',Georgia,serif; font-size:12px; }
  .mj-s2-claim a { color:rgba(61,43,31,0.70); }

  @media (max-width:720px) {
    .mj-s2-h1 { font-size:28px; }
    .mj-s2-joe { flex-direction:column; }
    .mj-s2-joemedia { width:100%; height:210px; }
    .mj-s2-factcols--2, .mj-s2-factcols--3, .mj-s2-factcols--4 { grid-template-columns:1fr; }
    .mj-s2-links { gap:18px; }
  }


.mj-sp-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;}
.mj-sp-banner{background:#3D2B1F;color:#FCF7D9;min-height:104px;box-sizing:border-box;padding:18px 32px;display:flex;flex-direction:column;justify-content:center;}
.mj-sp-banner-in{max-width:1100px;margin:0 auto;width:100%;}
.mj-sp-crumbs{font-family:'Fraunces', Georgia, serif;font-size:11px;color:rgba(252,247,217,0.78);margin:0 0 14px;}
.mj-sp-crumbs a{color:rgba(252,247,217,0.78);text-decoration:none;border-bottom:1px solid transparent;}
.mj-sp-crumbs a:hover{border-bottom-color:rgba(252,247,217,0.78);}
.mj-sp-crumbs span{margin:0 6px;}
.mj-sp-eyebrow{font-family:'Fraunces', Georgia, serif;font-size:11px;letter-spacing:0.18em;text-transform:uppercase;color:rgba(252,247,217,0.78);margin:0 0 8px;}
.mj-sp-h1{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-size:38px;font-weight:700;line-height:1.05;color:#FCF7D9;margin:0;}
.mj-sp-stats{font-family:'Fraunces', Georgia, serif;font-size:14px;color:rgba(252,247,217,0.78);margin:10px 0 0;}

/* Utility bar. Sticky, so the search stays reachable down a 300-row index. */
/* ON THE CREAM, not on a blush band. It is sticky, so it needs an OPAQUE
   background — rows scrolling under a transparent bar is the one thing worse than
   a coloured one — and its bottom hairline is now the only thing separating it
   from the list, which is why that rule stays. */
/* NO RULE UNDER THE BAR. One rule per section header is the whole rule budget on
   this page, and a hairline here made a second horizontal line 40px above the first
   section's own. The field is a pill on cream and reads as a control without being
   boxed in from below. */
.mj-sp-bar{position:sticky;top:0;z-index:20;background:#FCF7D9;padding:12px;}
/* The field is the whole bar. With the sort toggle gone the only other thing here is
   the match count, and sitting it alongside kept the field 12px short of full width
   for a label that is empty until you type. It goes underneath instead, where it
   reads as a result of the search rather than a control beside it. */
.mj-sp-bar-in{max-width:1100px;margin:0 auto;}
/* 44px tall and 16px of type, both deliberate. It measured 36px, and at 14px iOS
   Safari zooms the whole page the moment the field takes focus, which on a state
   page throws away the jump strip the field was meant to work alongside. Anything
   at 16px or above does not trigger it. */
/* A RULE WITH WORDS ON IT, not a pill. This was a full-width rounded box with a
   border and a cream fill, which is the one widget shape the rest of the website
   does not use: the homepage hero, the Joe's Reviews masthead and the editorial
   forms are all a line of type over a single hairline. Same treatment here, on the
   same measure as the content under it. */
.mj-sp-search{display:block;width:100%;min-width:0;height:44px;box-sizing:border-box;
  background:transparent;border:none;border-bottom:1px solid rgba(61,43,31,0.22);border-radius:0;
  outline:none;padding:0 2px;font-family:'Fraunces', Georgia, serif;font-size:16px;line-height:1.4;color:#3D2B1F;
  -webkit-appearance:none;appearance:none;}
.mj-sp-search::placeholder{color:rgba(61,43,31,0.68);opacity:1;}
.mj-sp-search:focus{border-bottom-color:#3D2B1F;}
.mj-sp-search::-webkit-search-cancel-button{-webkit-appearance:none;}

/* ── THE FILTER ACTUALLY HIDES THINGS NOW ─────────────────────────────────────
   The script sets row.hidden = true, and the UA stylesheet's [hidden]{display:none}
   is the WEAKEST rule in the cascade: .mj-sp-city sets display:flex and .mj-sp-shop
   sets display:block, so every author rule below beat it and nothing was ever
   hidden. The count said "2 matches" over a completely unfiltered list.

   This is an attribute selector on two attributes, specificity 0,2,0, so it beats
   both of those class rules on its own and needs no !important. It is keyed on
   data-mj-row and data-mj-head rather than on the class names, so a row that gets
   restyled or renamed later keeps working. */
[data-mj-row][hidden],[data-mj-head][hidden]{display:none;}
/* Start here is a curated shortcut, not a result set: it holds the six busiest
   cities and never changes with the query. Showing it unfiltered above filtered
   results is what made a search for a small city look broken. It stands down for
   the duration of a search and comes back when the field is cleared. */
[data-mj-start][hidden]{display:none;}
.mj-sp-count{display:block;font-family:'Fraunces', Georgia, serif;font-size:12px;color:rgba(61,43,31,0.68);margin:8px 0 0;min-height:15px;}

/* Sections */
/* WITH BOTH BANDS GONE the page is one cream field, so the sections are told
   apart by RULE AND RHYTHM instead of by colour: a hairline between each one, and
   a first section that opens tight under the sticky bar rather than dropping 34px
   of nothing. --flush drops the top rule where a section already follows one. */
.mj-sp-sec{background:#FCF7D9;color:#3D2B1F;padding:30px 32px;border-top:1px solid rgba(61,43,31,0.22);}
.mj-sp-sec--flush{border-top:0;padding-top:24px;}
/* The picksByState link closes the shop index. As its own padded band it left 76px
   of empty cream between the last shop row and Nearby States. */
.mj-sp-in{max-width:1100px;margin:0 auto;}
.mj-sp-head{display:flex;align-items:baseline;gap:12px;margin:0 0 14px;}
.mj-sp-head .mj-sp-cnt{margin-left:auto;}
.mj-sp-h2{font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-size:18px;font-weight:700;color:#3D2B1F;margin:0;white-space:nowrap;}
.mj-sp-cnt{font-family:'Fraunces', Georgia, serif;font-size:11px;color:rgba(61,43,31,0.68);white-space:nowrap;}


/* Jump strip + letter groups */
/* WRAPS. The strip is built by joining letters with a middot span and NO whitespace
   between the elements, and a line break can only happen at a break opportunity - a
   space. So twenty-six letters were one unbreakable 604px run that overflowed every
   phone. A flex row with wrap gives each item its own break opportunity without
   putting stray spaces into the markup. */
.mj-sp-jump{display:flex;flex-wrap:wrap;align-items:center;font-family:'Fraunces', Georgia, serif;font-size:12px;color:rgba(61,43,31,0.68);margin:0 0 16px;}
.mj-sp-jump a{color:rgba(61,43,31,0.68);text-decoration:none;}
.mj-sp-jump a:hover,.mj-sp-jump a:focus,.mj-sp-jump a[aria-current="true"]{color:#3D2B1F;border-bottom:1px solid rgba(61,43,31,0.22);}
.mj-sp-jump span{margin:0 5px;}
/* MULTI-COLUMN, not a grid — and that is a deliberate departure from the letter of
   the spec. A 3-column grid puts each full-width letter heading on its own row, so
   Nevada (16 cities across 14 letters) drew heading / one city / heading / one city
   straight down column 1 with two empty columns beside it. Measured: two distinct
   column positions used out of three. Multi-column flows the same headings and rows
   continuously down column 1, then 2, then 3 — the phone-book layout an A-Z index
   wants — and it still reads in alphabetical order. Column count and the 28px gutter
   are exactly as specified.

   ── THE BASELINE GRID ────────────────────────────────────────────────────────
   Every row is exactly ROW tall and every letter heading is an exact multiple of ROW,
   so every row in every column lands on the same rhythm measured from the top of the
   container. That is what makes the three columns read as one table rather than three
   lists that happen to sit side by side.

   THERE ARE TWO GRIDS, one per input device, and each is internally consistent.
   Above 1023px, where a pointer is: ROW = 27px, heading = 2xROW = 54px. At 1023px and
   below, where a finger is, and where this index already reflows to two columns and
   then one: ROW = 44px, heading = 1xROW = 44px. Both pairs are pinned in the rules
   below, and neither grid ever sees the other's numbers.

   A 27px ROW IS NOT A TAP TARGET, and these rows are the only way forward on a state
   page. On a phone the index is a single column, so every onward link on the page was
   a 27px sliver. There is no out-of-flow trick available: rows sit 27px apart, so a
   44px overlay on each would overlap its neighbours by 17px and a tap near a boundary
   would open the wrong city. The only honest fix is a taller row.

   The heading drops from 2xROW to 1xROW at the same breakpoint. At ROW = 27 a letter
   needs two rows of air to separate one group from the next; at ROW = 44 the rows
   carry that separation themselves, and an 88px heading would be a hole in the page.
   54px down to 44px also gives back ten pixels per letter against the seventeen each
   row costs.

   The phone page is taller for it. A state with 480 cities gains roughly 8,000px of
   single column. The jump strip and the search field above the grid are what make
   that length navigable, and both are on this page already. Above 1023px nothing
   moves: a four-column phone-book index at 27px is the right density for a mouse,
   and inflating it would have cost 202px on the fixture alone to serve a pointer
   that hits a 27px row without trying.

   It only works if both heights are PINNED. Left to a normal line-height a row is
   whatever the loaded face says it is, and one pixel of drift compounds down a
   60-row column. So the line-heights below are explicit and both pairs are pinned:
   content 16 + padding 10 + border 1 = 27, and content 16 + padding 27 + border 1
   = 44.

   Letter groups are wrapped in .mj-sp-grpwrap with break-inside:avoid so a heading
   can never be stranded at the foot of one column with its cities at the head of the
   next — which is what put Inglewood a row higher than Alhambra and Rancho
   Cucamonga. Every column now opens on a heading, at the same y. The 20px of air
   above each letter is the heading's own padding rather than a margin, because a
   margin at a column top is preserved by some engines and dropped by others, and a
   dropped margin is exactly the misalignment this is here to remove.

   When a group is genuinely taller than a column the browser breaks it anyway — it
   has no choice — and the grid still holds: the continuation starts at the column
   top and every row after it is still a multiple of ROW down. */
/* break-inside:avoid is what makes the letters read DOWN each column. Without it a
   group splits across the column break and the same letter appears twice, side by
   side, which reads as two different sections. */
.mj-sp-grpwrap{break-inside:avoid;}
.mj-sp-grp{font-family:'Fraunces', Georgia, serif;font-size:12px;line-height:15px;text-transform:uppercase;letter-spacing:0.14em;color:rgba(61,43,31,0.68);margin:0;padding:33px 0 6px;}

/* City index */
.mj-sp-cities{column-count:3;column-gap:28px;}
/* The star is explained once, under the grid it appears in, rather than by a tooltip
   nobody hovers. Only rendered when the state actually has a pick to mark. */
.mj-sp-legend{display:flex;align-items:center;gap:6px;font-family:'Fraunces', Georgia, serif;font-style:italic;font-size:12px;color:rgba(61,43,31,0.68);margin:18px 0 0;}
.mj-sp-city{display:flex;align-items:baseline;gap:8px;border-bottom:1px solid rgba(61,43,31,0.22);padding:5px 0;height:27px;box-sizing:border-box;line-height:16px;text-decoration:none;color:#3D2B1F;break-inside:avoid;}
.mj-sp-city-n{flex:1;min-width:0;font-family:'Fraunces', Georgia, serif;font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.mj-sp-city-c{flex:0 0 auto;font-family:'Fraunces', Georgia, serif;font-size:12px;color:rgba(61,43,31,0.68);}
.mj-sp-city:hover .mj-sp-city-n{text-decoration:underline;}

/* Shop index */
/* START HERE, the dot-leader block above the city index. */
.mj-sp-start{margin:0 0 4px;}
/* NEARBY STATES AS CHIPS, four of them. It was a line of up to six names separated
   by middots, which at six reads as a sentence nobody finishes. */
.mj-sp-nearchips{display:flex;flex-wrap:wrap;gap:8px;margin:10px 0 0;padding:0;list-style:none;}
/* THE COLLAPSED A-TO-Z. A <details> so the whole list stays in the HTML whether it
   is open or shut: a crawler reads it either way, and the reader is not handed six
   hundred rows they did not ask for. */
.mj-sp-az{border-top:1px solid rgba(61,43,31,0.22);}
.mj-sp-az > summary{display:flex;align-items:baseline;gap:12px;min-height:44px;
  padding:12px 0;cursor:pointer;list-style:none;font-family:'Fraunces', Georgia, serif;}
.mj-sp-az > summary::-webkit-details-marker{display:none;}
.mj-sp-az-l{flex:1 1 auto;min-width:0;font-family:'Playfair Display', 'Playfair Display Fallback', Georgia, serif;font-weight:700;
  font-size:17px;color:#3D2B1F;}
.mj-sp-az-n{flex:0 0 auto;font-size:13px;color:rgba(61,43,31,0.68);white-space:nowrap;}
/* TWO SPANS, not a ::after with an escape. A CSS escape inside a template literal
   is a legacy octal escape and does not compile, which the bundler caught; and the
   closed label has to be "Show 412" rather than a word, so the two states are two
   pieces of text and not one with a suffix. */
.mj-sp-az-hide{display:none;}
.mj-sp-az[open] .mj-sp-az-show{display:none;}
.mj-sp-az[open] .mj-sp-az-hide{display:inline;}
.mj-sp-shops{column-count:2;column-gap:28px;}
/* nowrap + ellipsis is what keeps a shop row exactly one ROW tall. At every width
   the page actually uses the names fit with room to spare — the ellipsis is the
   guarantee, not a routine truncation — and a row that wrapped would knock every
   row below it in that column off the shared rhythm. */
.mj-sp-shop{display:block;border-bottom:1px solid rgba(61,43,31,0.22);padding:6px 0;height:28px;box-sizing:border-box;line-height:16px;text-decoration:none;color:#3D2B1F;font-family:'Fraunces', Georgia, serif;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;break-inside:avoid;}
.mj-sp-shop:hover{text-decoration:underline;}
.mj-sp-shop-c{font-size:12px;color:rgba(61,43,31,0.68);}
/* Same construction, same fix as .mj-sp-jump above. */
.mj-sp-pages{display:flex;flex-wrap:wrap;align-items:center;font-family:'Fraunces', Georgia, serif;font-size:14px;color:rgba(61,43,31,0.68);margin:0 0 14px;}
/* No rule under a letter at rest - twenty-seven underlined letters read as one long
   broken line rather than as links. The rule appears on hover and focus, and stays on
   the letter you are actually reading, which is state rather than decoration. */
.mj-sp-pages a{color:#3D2B1F;text-decoration:none;border-bottom:1px solid transparent;padding-bottom:1px;}
.mj-sp-pages a:hover,.mj-sp-pages a:focus{border-bottom-color:rgba(61,43,31,0.22);}
.mj-sp-pages a[aria-current="page"]{border-bottom-color:#3D2B1F;font-weight:600;}
.mj-sp-pages span{margin:0 5px;}
/* websitePickBadge.ts sets .mj-pick-star{display:block} for the pill, which drops
   the star onto its own line inside a text row. Forced back inline here.

   vertical-align:middle, not a pixel nudge. An 11px inline-block sitting 1px below
   the baseline pushed the line box past 16px, so the six rows carrying a star stood
   a pixel or two taller than the rest — and every row under them in that column came
   off the shared rhythm. The rows now carry an explicit height so nothing inline can
   move them at all, and middle keeps the star centred inside that height rather than
   hanging off a baseline it no longer controls. */
.mj-sp-star{display:inline-block;vertical-align:middle;margin-left:5px;line-height:0;}
.mj-sp-star .mj-pick-star{display:inline-block;vertical-align:middle;}
.mj-sp-empty{font-family:'Fraunces', Georgia, serif;font-size:14px;font-style:italic;color:rgba(61,43,31,0.68);margin:8px 0 0;}
/* The one link from a state page to that state's picks page. A sentence rather
   than a button, because it sits under the star legend as the answer to it, and a
   pill there would read as a second navigation bar under an index. Underlined at
   rest: it is the only link in this block and nothing else marks it. */
.mj-sp-pickslink{font-family:'Fraunces', Georgia, serif;font-size:16px;margin:10px 0 0;}
.mj-sp-pickslink a{display:inline-flex;align-items:center;min-height:44px;color:#3D2B1F;text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px;}
.mj-sp-pickslink a:hover{text-decoration-thickness:2px;}

/* Nearby states */
.mj-sp-near{background:#FCF7D9;border-top:1px solid rgba(61,43,31,0.22);padding:22px 32px 34px;}
.mj-sp-near-l{font-family:'Fraunces', Georgia, serif;font-size:11px;text-transform:uppercase;letter-spacing:0.14em;color:rgba(61,43,31,0.68);margin:0 0 8px;}
.mj-sp-near-a{font-family:'Fraunces', Georgia, serif;font-size:14px;color:#3D2B1F;text-decoration:none;}
.mj-sp-near-a:hover{text-decoration:underline;}
.mj-sp-near p span{margin:0 5px;color:rgba(61,43,31,0.68);}

@media (min-width:1200px){
  .mj-sp-cities{column-count:4;}
}
@media (max-width:1023px){
  .mj-sp-cities{column-count:2;}
  .mj-sp-shops{column-count:1;}
  /* THE TOUCH GRID. ROW 27 and 28 become 44 and the heading 54 becomes 44, all
     together, because the rhythm only holds while the heading stays a whole multiple
     of the row. No type size moves: the box grows around the text. */
  .mj-sp-city{padding:13px 0 14px;height:44px;}
  .mj-sp-shop{padding:13px 0 14px;height:44px;}
  .mj-sp-grp{padding:23px 0 6px;}
}
@media (max-width:767px){
  .mj-sp-cities{column-count:1;}
  .mj-sp-banner{padding:20px;}
  .mj-sp-h1{font-size:30px;}
  .mj-sp-sec,.mj-sp-near{padding-left:20px;padding-right:20px;}
}


/* ── Breadcrumb tap targets, every page family ────────────────────────────────
   Crumb links measured 13px to 17px tall. They are the only up-level navigation on
   a server-rendered page, and there are seven different crumb components across the
   thirteen page types, so this is one rule rather than seven.

   A VISIBLE 44px BOX WOULD BE WRONG HERE, for two reasons. A crumb trail is a line
   of words under the masthead; a 44px row turns it into a toolbar and pushes the h1
   down on every page. And five of the seven mark hover with a 1px bottom border on
   the link itself, which in a 44px box detaches from the text and floats half an
   inch below it.

   So the target grows out of flow: a transparent ::after, centred on the link,
   44px tall, reaching 5px past the text on each side. Vertically it grows into the
   margin above and below the trail, where nothing else is clickable. Horizontally
   it cannot reach its neighbour, because every separator in these components
   carries 6px to 10px of margin and the overlay takes 5px of it. The link box
   itself does not move, so the hover border stays on the text where it belongs.

   position:relative is on the anchor and not the nav, so each overlay is measured
   from its own link.

   TWO OF THE SEVEN ARE CURRENTLY DEAD: no page emits .seo-breadcrumb or
   .mj-cc-crumbs today, though both have styles. They are listed here so that if
   either is ever rendered it arrives with the target already on it, rather than
   being the one crumb trail on the site that is 11px tall. */
.seo-breadcrumb a,
.seo-jr-crumbs a,
.seo-shop-crumbs a,
.ev-crumbs a,
.mj-cc-crumbs a,
.lr-crumbs a,
.mj-sp-crumbs a{position:relative;}
.seo-breadcrumb a::after,
.seo-jr-crumbs a::after,
.seo-shop-crumbs a::after,
.ev-crumbs a::after,
.mj-cc-crumbs a::after,
.lr-crumbs a::after,
.mj-sp-crumbs a::after{content:'';position:absolute;left:-5px;right:-5px;top:50%;height:44px;transform:translateY(-50%);}

/* ── The base link colour, on a dark ground ──────────────────────────────────
   BRAND_CSS sets a { color:#5C3520 } so a link that no component styles cannot
   fall back to the browser's blue. That value is right on cream and wrong on
   chocolate, where it is dark brown on dark brown. This is the other half of
   that rule rather than a new one.

   :where() IS DOING THE LOAD-BEARING WORK. A plain .mj-bd-band--chocolate a
   would be specificity 0-1-1, which beats the 0-1-0 of a component rule like
   .mj-bd-card{color:#3D2B1F} and would recolour every real link inside a
   chocolate band. Wrapping the ancestor in :where() drops it to 0-0-1: exactly
   the base rule it is correcting, and less than any class on the anchor. So it
   can only reach a link nothing else colours, which is the whole set it is for.
   It sits after the base rule, which is what settles the tie between them.

   #FCF7D9 rather than inherit. The base rule does not inherit on cream either:
   #5C3520 sits just off the body ink so a link reads as a link. On chocolate the
   band text is #F5EFE6 or the muted #EBE3D5, and the brightest cream sits just
   off both in the same way.

   THE LIST IS EVERY CONTAINER THAT PAINTS ITSELF DARK, found by sweeping the
   built sheet for a dark background rather than by memory: the header, the
   footer, both band systems, and the Cars and Coffee and state page banners.
   Add to it when a new dark surface appears. */
:where(.mj-web-header,
       .mj-ft,
       .mj-bd-band--chocolate,
       .seo-band--chocolate,
       .mj-cc-banner,
       .mj-sp-banner) a{color:#FCF7D9;}
