:root{
    --ivory:#f7f2e9;
    --linen:#ede3d1;
    --beige:#c9ae8c;
    --stone:#96897a;
    --olive:#666b49;
    --olive-deep:#4d5138;
    --espresso:#3b2c1f;
    --charcoal:#241f19;
    --brass:#b3895a;

    --serif:"Fraunces", Georgia, serif;
    --sans:"Work Sans", -apple-system, sans-serif;
    --script:"Caveat", cursive;

    --edge:6vw;
    --radius:18px;
    --ease:cubic-bezier(.22,.61,.36,1);
  }

  *{margin:0;padding:0;box-sizing:border-box;}
  html{scroll-behavior:smooth;}
  body{
    background:var(--ivory);
    color:var(--espresso);
    font-family:var(--sans);
    font-weight:300;
    line-height:1.6;
    -webkit-font-smoothing:antialiased;
    overflow-x:clip;
  }
  img{display:block; max-width:100%;}
  a{color:inherit; text-decoration:none;}
  button{font-family:var(--sans); cursor:pointer;}
  ::selection{background:var(--beige); color:var(--charcoal);}

  h1,h2,h3,h4{
    font-family:var(--serif);
    font-weight:400;
    line-height:1.03;
    letter-spacing:-0.01em;
    color:var(--charcoal);
  }
  .eyebrow{
    font-family:var(--serif); font-style:italic; font-weight:400;
    font-size:0.92rem; letter-spacing:0.02em; color:var(--olive-deep);
  }
  .hand{font-family:var(--script); font-weight:600;}
  .wrap{max-width:1480px; margin:0 auto; padding:0 var(--edge);}
  section{position:relative;}

  .reveal{opacity:0; transform:translateY(34px); transition:opacity 1.1s var(--ease), transform 1.1s var(--ease);}
  @media (max-width:640px){
    .reveal{transform:translateY(18px);} /* subtler movement on small screens */
  }
  .reveal.in{opacity:1; transform:translateY(0);}

  /* word-by-word reveal */
  .word{display:inline-block; opacity:0; transform:translateY(14px); transition:opacity .6s var(--ease), transform .6s var(--ease);}
  .word-wrap.in .word{opacity:1; transform:translateY(0);}

  .btn{
    display:inline-flex; align-items:center; justify-content:center; gap:.6rem;
    padding:0.95rem 1.9rem;
    font-size:0.8rem; letter-spacing:0.07em; text-transform:uppercase;
    border-radius:999px; border:1px solid var(--espresso);
    transition:background .35s var(--ease), color .35s var(--ease), border-color .35s var(--ease), transform .25s var(--ease);
    white-space:nowrap;
  }
  .btn-solid{background:var(--espresso); color:var(--ivory);}
  .btn-solid:hover{background:var(--olive-deep); border-color:var(--olive-deep); transform:translateY(-2px);}
  .btn-outline{background:transparent; color:var(--espresso);}
  .btn-outline:hover{background:var(--espresso); color:var(--ivory); transform:translateY(-2px);}
  .btn-light{border-color:rgba(247,242,233,.75); color:var(--ivory);}
  .btn-light.btn-solid{background:var(--ivory); color:var(--charcoal); border-color:var(--ivory);}
  .btn-light.btn-solid:hover{background:transparent; color:var(--ivory);}
  .btn-sm{padding:0.6rem 1.2rem; font-size:0.72rem;}
  /* .add-link is normally a plain quiet text-link (see below), but a couple of
     CTAs combine it with .btn-solid for the actual "Add" action button —
     without this, .add-link's background:none/border:none would strip the
     solid fill and leave near-invisible text on a light background. */
  .btn-solid.add-link{background:var(--espresso); color:var(--ivory); border-color:var(--espresso);}
  .btn-solid.add-link:hover{background:var(--olive-deep); border-color:var(--olive-deep);}
  .btn:focus-visible{outline:2px solid var(--olive); outline-offset:3px;}
  .link-quiet{font-size:.85rem; letter-spacing:.03em; border-bottom:1px solid rgba(59,44,31,.4); padding-bottom:.3rem;}

  /* stamp / tape / polaroid imperfection details */
  .tape{
    position:absolute; width:64px; height:24px;
    background:rgba(201,174,140,.55);
    box-shadow:0 2px 5px rgba(0,0,0,.15);
    z-index:5;
  }
  /* .stamp removed — was only used by the hero "Est. South Florida" sticker,
     which has been removed. .polaroid removed — see "QUIET MOMENT —
     editorial photo treatment" below, which replaces the scrapbook/polaroid
     look with a refined single-image presentation for the "A Place at the
     Table" section. */

  /* ============ NAV ============ */
  header{
    position:fixed; top:0; left:0; right:0; z-index:70;
    display:flex; align-items:center; justify-content:space-between;
    padding:1.1rem var(--edge);
    background:linear-gradient(to bottom, rgba(36,31,25,0.4), rgba(36,31,25,0));
    transition:background .5s var(--ease), padding .5s var(--ease), box-shadow .5s var(--ease);
  }
  header.scrolled{background:rgba(247,242,233,0.94); backdrop-filter:blur(8px); padding:0.75rem var(--edge); box-shadow:0 1px 0 rgba(59,44,31,0.08);}
  /* Pages with no dark hero image behind the header (About, This Week's
     Table, Experiences, Market) — the header's default styling assumes a
     dark hero to sit over, which doesn't exist on these pages, so nav text
     would render light-on-light until the user scrolls past 40px. This
     class applies the correct dark-on-light styling from initial page
     load, independent of the scroll-based .scrolled toggle entirely, so
     there's no flash of low-contrast text and no risk of the scroll
     listener fighting a class set only in HTML. */
  body.no-hero header{background:rgba(247,242,233,0.94); backdrop-filter:blur(8px); box-shadow:0 1px 0 rgba(59,44,31,0.08);}
  body.no-hero nav.primary-nav a{color:var(--charcoal);}
  body.no-hero .cart-btn{color:var(--charcoal);}
  body.no-hero .nav-toggle .bar1,
  body.no-hero .nav-toggle .bar2,
  body.no-hero .nav-toggle .bar3{background:var(--charcoal);}
  .nav-left{display:flex; align-items:center; gap:.8rem;}
  .nav-left img{width:96px; height:96px; border-radius:50%; transition:width .5s var(--ease), height .5s var(--ease);}
  header.scrolled .nav-left img{width:80px; height:80px;}
  nav.primary-nav ul{display:flex; gap:1.5rem; list-style:none;}
  nav.primary-nav a{font-size:0.78rem; letter-spacing:0.06em; text-transform:uppercase; color:var(--ivory); position:relative; padding-bottom:3px; transition:color .5s var(--ease);}
  header.scrolled nav.primary-nav a{color:var(--charcoal);}
  nav.primary-nav a::after{content:""; position:absolute; left:0; right:0; bottom:0; height:1px; background:currentColor; transform:scaleX(0); transform-origin:left; transition:transform .25s ease;}
  nav.primary-nav a:hover::after{transform:scaleX(1);}
  .nav-right{display:flex; align-items:center; gap:1.3rem;}
  .cart-btn{position:relative; display:flex; align-items:center; gap:.5rem; color:var(--ivory); font-size:.78rem; letter-spacing:.05em; text-transform:uppercase; transition:color .5s var(--ease); background:none; border:none;}
  header.scrolled .cart-btn{color:var(--charcoal);}
  .cart-btn svg{width:19px; height:19px;}
  .cart-count{position:absolute; top:-7px; right:-10px; background:var(--olive-deep); color:var(--ivory); font-size:.62rem; width:16px; height:16px; border-radius:50%; display:flex; align-items:center; justify-content:center; transform:scale(0); transition:transform .35s var(--ease);}
  .cart-count.show{transform:scale(1);}
  .nav-toggle{
    display:none; position:relative; z-index:120;
    width:44px; height:44px; padding:0; align-items:center; justify-content:center;
  }

  /* ============ HERO — asymmetric, overlapping ============ */
  .hero{height:100svh; min-height:640px; position:relative; overflow:hidden;}
  .hero .img-wrap{position:absolute; inset:0; overflow:hidden;}
  .hero img{
    position:absolute; inset:-6% -6%; width:112%; height:112%; max-width:none; object-fit:cover;
    object-position:50% 52%; /* landscape "Pull up a chair" hero — centers the meals,
      olives, and BMW badge; the "Pull up a chair" card sits left, comfortably behind
      the dark gradient, while the hero-card text reads on the right */
    will-change:transform;
  }
  .hero::after{
    content:""; position:absolute; inset:0; z-index:1;
    background:
      linear-gradient(245deg, rgba(20,17,13,0.62) 0%, rgba(20,17,13,0.1) 45%, rgba(20,17,13,0.05) 100%),
      linear-gradient(to top, rgba(20,17,13,0.55) 0%, rgba(20,17,13,0) 38%);
  }
  .hero-card{
    position:absolute; z-index:2; right:var(--edge); left:auto; bottom:8vh;
    max-width:560px; color:var(--ivory); text-align:right;
    /* moved from left to right — the branded meal container in this photo sits
       left-of-center, and at typical desktop widths the source image displays
       at its full width with no horizontal cropping available (it's a portrait
       photo in a much wider viewport), so there's no object-position value that
       both keeps the container in frame AND clears a left-anchored text box.
       Moving the text to the side the container isn't on was the only way to
       satisfy "full container visible" and "text doesn't cover it" at once. */
  }
  .hero-card h1{font-size:clamp(3rem,8vw,6.6rem); color:var(--ivory); line-height:0.98;}
  /* Isabel's own handwritten "Slow days, shared." (drawn in Procreate),
     extracted to a transparent PNG and tinted to match --ivory so it reads
     as part of the same palette as the button/subtext beneath it — replaces
     the earlier Caveat-font live-text treatment entirely. The h1 wrapper
     keeps the image accessible (real alt text) and lets the image just
     scale to fill whatever width .hero-card allows at each breakpoint,
     rather than hard-coding a size that would need separate tuning per
     screen size the way the old clamp()'d font-size did. */
  .hero-card h1.hero-script{ margin:0; line-height:0; }
  /* NOTE: selector is `.hero-card .hero-script-img`, not just `.hero-script-img`
     — this image is nested inside .hero, and the generic `.hero img{...}` rule
     above (meant only for the big background photo, #hero-img) is a descendant
     selector that matches ANY <img> in .hero, including this one, at higher
     specificity than a single class would have. Without the extra `.hero-card`
     prefix here, that rule silently wins and forces this image to
     position:absolute/width:112%/max-width:none — which is what caused it to
     render huge, cropped by the viewport edge, and overlapping the subtext.
     Every property that other rule sets is explicitly reset below so there's
     no ambiguity regardless of source order. */
  .hero-card .hero-script-img{
    position:static; inset:auto; max-width:560px; object-fit:initial;
    object-position:initial; will-change:auto;
    display:block;
    /* sized directly with clamp() rather than width:100% of .hero-card — that
       parent only has a max-width (no explicit width), so a percentage width
       on the image would resolve against its shrink-to-fit box unpredictably.
       This mirrors how the old font-size was clamped, just in pixel terms. */
    width:clamp(280px, 44vw, 560px);
    height:auto;
    margin-left:auto; /* right-aligned on desktop, matching .hero-card's text-align:right */
    /* The old two-line text ("Slow days," / "shared") stood roughly 60px taller
       than this single-line image at the same width, which — since .hero-card
       is anchored by `bottom`, not `top` — meant the old headline's top edge
       sat noticeably higher above the branded food container in the photo.
       This margin restores that same clearance instead of letting the whole
       card (and the container behind it) sit lower now that the headline
       itself is shorter. */
    margin-bottom:clamp(1.75rem, 5vw, 3.5rem);
  }
  .hero-sub{margin-top:1.3rem; max-width:38ch; font-size:1.05rem; color:rgba(247,242,233,.9); margin-left:auto;}
  .hero-ctas{display:flex; gap:1rem; margin-top:2rem; flex-wrap:wrap; justify-content:flex-end;}

  /* ============ INTERLUDE (huge pull quote) ============ */
  .interlude{padding:14rem 0; text-align:center;}
  .interlude-inner{max-width:1000px; margin:0 auto;}
  .interlude h2{font-size:clamp(2.2rem,6vw,4.6rem); font-style:italic; font-weight:400; line-height:1.15;}

  /* ============ MEALS — weekly menu (categories + accordion) ============ */
  .meals{padding:4rem 0 10rem;}
  .meals-head{margin-bottom:5rem; max-width:640px;}
  /* Sizes swapped: "This Week's Table" is now the large display line and the
     menu date ("August 2nd Menu") sits under it as a smaller subheading. */
  .meals-head .eyebrow{display:block; margin-bottom:.4rem; font-size:clamp(2.6rem,7vw,5.5rem); line-height:1; color:var(--olive-deep);}
  .meals-head h2{font-size:clamp(1.4rem,3vw,2.4rem); line-height:1.1; color:var(--olive-deep); font-style:normal;}

  .add-link{
    background:none; border:none; font-size:.82rem; letter-spacing:.06em; text-transform:uppercase;
    border-bottom:1px solid var(--espresso); padding-bottom:.3rem; transition:opacity .3s var(--ease);
  }
  .add-link.added{color:var(--olive-deep); border-color:var(--olive-deep);}

  /* ============ HOW IT WORKS — horizontal filmstrip ============ */
  .how{background:var(--charcoal); color:var(--linen); padding:7rem 0;}
  .how-head{padding:0 var(--edge); margin-bottom:3rem; display:flex; justify-content:space-between; align-items:flex-end; gap:2rem; flex-wrap:wrap;}
  .how-head .eyebrow{color:var(--beige); display:block; margin-bottom:.5rem;}
  .how-head h2{color:var(--ivory); font-size:clamp(2.2rem,4.6vw,3.6rem);}
  .how-head p{color:var(--linen); opacity:.62; max-width:30ch; font-size:.92rem;}
  .filmstrip{
    display:flex; gap:1.4rem; overflow-x:auto; padding:0 var(--edge) 1rem;
    width:100%; max-width:100%;
    scroll-snap-type:x proximity;
    -webkit-overflow-scrolling:touch;
  }
  .filmstrip::-webkit-scrollbar{height:5px;}
  .filmstrip::-webkit-scrollbar-thumb{background:rgba(247,242,233,.25); border-radius:4px;}
  .film-frame{
    position:relative; flex:0 0 300px; scroll-snap-align:start;
    border-radius:var(--radius); overflow:hidden; aspect-ratio:3/4;
  }
  .film-frame img{width:100%; height:100%; object-fit:cover;}
  .film-frame::after{content:""; position:absolute; inset:0; background:linear-gradient(to top, rgba(20,17,13,.78), transparent 55%);}
  .film-cap{position:absolute; left:1.2rem; right:1.2rem; bottom:1.1rem; z-index:1;}
  .film-cap .num{font-family:var(--script); color:var(--beige); font-size:1.2rem;}
  .film-cap h4{color:var(--ivory); font-size:1.1rem; font-weight:400; margin-top:.15rem;}

  /* ============ ABOUT — asymmetric editorial ============ */
  .about{padding:12rem 0 10rem; overflow:visible;}
  .about-grid{display:grid; grid-template-columns:0.7fr 1.3fr; gap:7vw; align-items:start; position:relative;}
  .about-portrait-wrap{position:sticky; top:14vh;}
  .about-portrait{
    position:relative; aspect-ratio:4/5; border-radius:4px; transform:rotate(-3deg);
    background:linear-gradient(160deg, var(--linen), var(--beige));
    border:1px solid rgba(59,44,31,.15);
    overflow:hidden;
    box-shadow:0 30px 60px -20px rgba(36,31,25,.3);
  }
  .about-portrait img{width:100%; height:100%; object-fit:cover; display:block;}
  .about-portrait .tape{top:-14px; left:50%; transform:translateX(-50%) rotate(-2deg);}
  .about-copy{padding-top:1rem;}
  .about-copy .eyebrow{display:block; margin-bottom:1rem;}
  .about-copy h2{font-size:clamp(2.2rem,4.6vw,3.6rem); max-width:14ch; margin-bottom:2.4rem; color:var(--olive-deep);}
  .about-copy p{font-size:1.08rem; opacity:.85; max-width:52ch; margin-bottom:1.6rem;}
  .about-bigline{
    font-family:var(--serif); font-style:italic; font-weight:400;
    font-size:clamp(1.8rem,3.4vw,2.6rem); text-align:center; margin:4rem auto; max-width:16ch; line-height:1.25;
  }
  .signature-mark{
    width:110px; height:auto; display:block; margin-top:1.6rem;
  }

  /* .quiet-moment / .qm-* rules removed — that section moved to its own
     dedicated page, promise.html, with its own purpose-built styling. */

  /* ============ EXPERIENCES — bleed banner ============ */
  .experiences{padding:9rem 0;}
  .exp-grid{display:grid; grid-template-columns:1fr 1fr; gap:2rem; align-items:center;}
  .exp-frame{position:relative; aspect-ratio:4/5; border-radius:var(--radius); overflow:hidden;}
  .exp-frame img{width:100%; height:100%; object-fit:cover; object-position:50% 32%; transition:transform 1s var(--ease);}
  .experiences:hover .exp-frame img{transform:scale(1.04);}

  /* ---------- typewriter text overlay ----------
     Special Elite — a vintage typewriter face — reveals via the classic
     width + steps() technique: because it's a true monospace font, each
     step corresponds to exactly one character, so the animation is exact
     rather than an estimate (unlike the previous SVG stroke-length
     approach this replaced). A blinking caret plays the part of the
     typewriter's carriage while it "writes," then stops once the phrase
     is complete rather than blinking forever. Runs once, triggered by
     the same .reveal scroll-observer already powering the rest of the
     site. Positioned top-left so it's the first thing the eye catches
     on this image, ahead of the rest of the composition below it. */
  .exp-typewrite{
    position:absolute; top:calc(7% + 68px); left:7%; z-index:2; margin:0;
    font-family:"Special Elite", "Courier New", monospace;
    font-size:1.72rem; letter-spacing:.02em; color:#f5f1e8;
    text-shadow:0 2px 8px rgba(20,17,13,.45);
    white-space:nowrap; overflow:hidden;
    width:0; max-width:16ch;
    border-right:2px solid rgba(245,241,232,.85);
  }
  .exp-frame.reveal.in .exp-typewrite{
    animation:typewriteReveal 1.9s steps(16,end) .4s forwards,
               typewriteCaret .8s step-end .4s infinite;
  }
  @keyframes typewriteReveal{
    to{width:16ch;}
  }
  @keyframes typewriteCaret{
    50%{border-color:transparent;}
  }

  @media (prefers-reduced-motion: reduce){
    .exp-typewrite{
      width:16ch; border-right-color:transparent;
      animation:none !important;
    }
  }

  .exp-copy{background:var(--charcoal); color:var(--ivory); padding:5rem 4vw 5rem 6vw; border-radius:var(--radius); position:relative; z-index:1;}
  .exp-copy .eyebrow{color:var(--beige); display:block; margin-bottom:1rem;}
  .exp-copy h2{color:var(--olive); font-size:clamp(2rem,3.8vw,3rem); margin-bottom:1.4rem; max-width:14ch;}
  .exp-copy p{opacity:.82; font-size:1.02rem; max-width:36ch; margin-bottom:1.8rem;}

  /* ---------- Experiences waitlist form ----------
     Same light-pill-on-dark-card look as the newsletter/contact forms
     (.nl-form), rebuilt standalone here rather than reused directly since
     this one sits left-aligned inside .exp-copy instead of centered under
     a heading, and pairs an email field with the button on one row on
     wider screens instead of always stacking. */
  .exp-waitlist-form{display:flex; gap:.9rem; flex-wrap:wrap; max-width:420px;}
  .exp-waitlist-form input{
    flex:1 1 200px; min-width:0;
    background:rgba(247,242,233,.1); border:1px solid rgba(247,242,233,.4); border-radius:999px;
    outline:none; color:var(--ivory); font-family:var(--sans); font-size:1rem; padding:.85rem 1.3rem;
  }
  .exp-waitlist-form input::placeholder{color:rgba(247,242,233,.55);}
  .exp-waitlist-form button{flex:0 0 auto;}
  .exp-waitlist-form.has-error input{border-color:#f3b8ab;}
  .exp-wl-error{display:none; margin-top:1rem; font-size:.82rem; color:#f3b8ab;}
  .exp-wl-note{margin-top:.2rem; font-size:1.02rem; opacity:.9; max-width:36ch;}

  /* ============ MARKET — offset gallery ============ */
  .market{padding:9rem 0;}
  /* Market header now uses real Fraunces type (matching "This Week's Table" on the
     weekly-menu page) instead of the old handwritten PNG — big italic eyebrow +
     smaller subheading — so the whole site reads with one consistent aesthetic. */
  .market-head{margin-bottom:4rem;}
  .market-head .eyebrow{display:block; margin-bottom:.4rem; font-size:clamp(2.6rem,7vw,5.5rem); line-height:1; color:var(--olive-deep);}
  .market-head h2{font-size:clamp(1.4rem,3vw,2.4rem); line-height:1.1; color:var(--olive-deep); font-style:normal;}

  .market-showcase{display:flex; flex-direction:column; gap:1.75rem;}
  .market-row-top{display:grid; grid-template-columns:1.6fr 1fr; gap:1.75rem;}
  /* widths matched to each photo's own orientation rather than forced into
     equal thirds — a landscape shot needs more width than a square or
     portrait one to read at a comparable scale */
  .market-row-bottom{display:grid; grid-template-columns:1.3fr 1fr .9fr; gap:1.75rem; align-items:start;}

  .market-card .frame{
    position:relative; border-radius:var(--radius); overflow:hidden;
    background:var(--linen);
    transition:transform .4s var(--ease), box-shadow .5s var(--ease);
    box-shadow:0 1px 2px rgba(59,44,31,.05);
  }
  /* each aspect-ratio is matched to that photo's actual source dimensions —
     see the comment on .market-ritual below for why this replaced a single
     shared ratio across every card */
  .market-hero .frame{aspect-ratio:5/4;}     /* source 1.25 */
  .market-tall .frame{aspect-ratio:2/3;}     /* source 0.665 */
  .market-ritual .frame{aspect-ratio:3/2;}   /* source 1.504 — this is the fix: it was
    previously forced into a 4:5 portrait frame meant for the cap and socks shots,
    which are a completely different orientation, and lost most of its content to cropping */
  .market-socks .frame{aspect-ratio:1/1;}    /* source 1.0, exact match */
  .market-cap-card .frame{aspect-ratio:2/3;} /* source 0.666 */

  .market-card .frame img{
    width:100%; height:100%; object-fit:cover; display:block;
    transition:transform .8s var(--ease);
  }
  .market-card:hover .frame{
    box-shadow:0 26px 50px -20px rgba(36,31,25,.28);
  }
  .market-card:hover .frame img{transform:scale(1.06);}

  /* ---------- add to order: an expanding pill, not a standard e-commerce CTA ----------
     A plus icon by default; on hover it expands into a pill revealing an
     "Add" label, so the action is unambiguous without resorting to a flat
     rectangular button. On confirmation it morphs into a checkmark rather
     than swapping to text — reuses the site's existing .add-link cart
     handler (see script.js), which was made to only toggle a class for
     this button rather than overwrite its icon content the way it does
     for ordinary text buttons. */
  .market-add{
    position:absolute; top:1.1rem; right:1.1rem; z-index:2;
    height:38px; min-width:38px; border-radius:999px; border:none; padding:0;
    background:rgba(247,242,233,.94); color:var(--olive-deep);
    display:flex; align-items:center; justify-content:center;
    opacity:0;
    transition:opacity .3s ease, background .3s ease, padding .35s var(--ease);
    cursor:pointer; overflow:hidden;
  }
  .market-card:hover .market-add, .market-add:focus-visible{
    opacity:1;
  }
  .market-add-icon, .market-add-check{
    width:16px; height:16px; flex-shrink:0;
    transition:opacity .3s ease, transform .3s var(--ease), margin-left .3s var(--ease);
  }
  .market-add-check{margin-left:-16px; opacity:0; transform:scale(.5);}
  .market-add-label{
    max-width:0; opacity:0; overflow:hidden; white-space:nowrap;
    font-size:.72rem; letter-spacing:.06em; text-transform:uppercase;
    transition:max-width .35s var(--ease), opacity .3s var(--ease), margin-left .35s var(--ease);
    margin-left:0;
  }
  .market-add:hover{padding:0 1.1rem;}
  .market-add:hover .market-add-label{max-width:50px; opacity:1; margin-left:.45rem;}
  .market-add.added{background:var(--olive-deep); color:var(--ivory); padding:0 1.1rem;}
  .market-add.added .market-add-label{max-width:50px; opacity:1; margin-left:.45rem;}
  .market-add.added .market-add-icon{opacity:0; transform:scale(.5); margin-left:-16px;}
  .market-add.added .market-add-check{opacity:1; transform:scale(1); margin-left:0;}

  /* ---------- sold-out / unavailable market items ----------
     No Add button at all (removed in the markup), a "Sold out" badge, a muted
     photo, and no hover lift/zoom — so it reads clearly as not purchasable. */
  .market-soldout{
    position:absolute; top:1.1rem; left:1.1rem; z-index:2;
    background:var(--olive-deep); color:var(--ivory);
    font-size:.68rem; letter-spacing:.09em; text-transform:uppercase;
    padding:.4rem .85rem; border-radius:999px;
    box-shadow:0 2px 8px rgba(36,31,25,.18);
  }
  .market-card.is-unavailable .frame img{filter:grayscale(38%); opacity:.62;}
  .market-card.is-unavailable:hover .frame{box-shadow:0 1px 2px rgba(59,44,31,.05);}
  .market-card.is-unavailable:hover .frame img{transform:none;}
  .market-card.is-unavailable .price{opacity:.5;}
  .market-card.is-unavailable .market-name-img{opacity:.55;}

  .market-card .info{
    padding-top:1rem; display:flex; justify-content:space-between; align-items:baseline;
  }
  /* Product names in the site's serif (Fraunces), matching the rest of the site. */
  .market-card h3{font-family:var(--serif); font-weight:400; font-size:clamp(1.3rem,2vw,1.7rem); color:var(--olive-deep); line-height:1.15;}
  .market-card.is-unavailable h3{opacity:.55;}
  /* Each product name as Isabel's own handwriting, same extraction/tinting
     approach as .market-heading-img above. Sized by HEIGHT (not width) so all
     five — despite very different word lengths/aspect ratios — read at a
     consistent visual weight next to the price, matching how the uniform
     font-size:1.15rem text they replace used to line up card to card. */
  .market-name-img{display:block; height:clamp(44px, 6.4vw, 64px); width:auto;}
  /* The Olive Hour / Lucky Fish / The Fisherman's Cap read visibly smaller than
     Market Socks and The Ritual at the shared size above (shorter words, or
     more letterforms crammed into the same clamp()'d height), so these three
     get a dedicated bump rather than resizing everything again. */
  .market-name-img-lg{height:clamp(42px, 6vw, 60px);}
  /* The Ritual / Market Socks read visually heavier than the other names at
     the shared height above — their letterforms are compact with little
     ascender/descender reach, so they fill more of the clamp()'d box than
     e.g. Lucky Fish's tall loop does. This trims their rendered height
     directly rather than resizing the source art (resizing the PNG only
     changes its aspect ratio / displayed width — height is always fixed by
     the clamp() above regardless of the file's own pixel dimensions). */
  .market-name-img-sm{height:clamp(37px, 5.4vw, 53px);}
  .market-card .price{font-family:var(--serif); font-style:italic; color:var(--olive-deep); font-size:.98rem;}
  .market-desc{margin-top:.4rem; font-size:.86rem; opacity:.65; max-width:32ch; line-height:1.5;}

  @media (max-width:900px){
    .market-row-top{grid-template-columns:1fr;}
    .market-row-bottom{grid-template-columns:1fr 1fr;}
    .market-ritual{grid-column:1 / -1;} /* the landscape shot keeps full width even in the 2-col tablet layout */
  }
  @media (max-width:560px){
    .market-row-bottom{grid-template-columns:1fr;}
    .market-ritual{grid-column:auto;}
    .market-add{opacity:1; transform:none; padding:0 1.1rem; height:44px;} /* no hover on touch — show the expanded pill plainly (accessible tap height) instead of hiding the label behind a gesture that doesn't exist there */
    .market-add-label{max-width:50px; opacity:1; margin-left:.45rem;}
  }
  @media (prefers-reduced-motion: reduce){
    .market-card .frame{transition:none !important; transform:none !important;}
  }

  /* ============ NEWSLETTER ============ */
  .newsletter{background:var(--olive-deep); color:var(--ivory); padding:9rem 0; text-align:center;}
  .newsletter .eyebrow{color:var(--beige); display:block; margin-bottom:1rem;}
  .newsletter h2{color:var(--ivory); font-size:clamp(2.4rem,6vw,4.2rem); max-width:18ch; margin:0 auto 2.4rem; line-height:1;}
  .nl-form{display:flex; flex-direction:column; gap:1.1rem; max-width:400px; margin:0 auto;}
  .nl-form input{width:100%; background:rgba(247,242,233,.1); border:1px solid rgba(247,242,233,.4); border-radius:999px; outline:none; color:var(--ivory); font-family:var(--sans); font-size:1rem; padding:.85rem 1.3rem;}
  .nl-form input::placeholder{color:rgba(247,242,233,.55);}
  /* textarea (the "Your message" field) reuses the input's look, but a
     999px pill radius reads oddly on a multi-line box — a smaller radius
     matching the site's usual --radius keeps it in the same family without
     looking like an overstretched pill. */
  .nl-form textarea{width:100%; background:rgba(247,242,233,.1); border:1px solid rgba(247,242,233,.4); border-radius:var(--radius); outline:none; color:var(--ivory); font-family:var(--sans); font-size:1rem; padding:.85rem 1.3rem; resize:vertical; min-height:120px;}
  .nl-form textarea::placeholder{color:rgba(247,242,233,.55);}
  .nl-form .nl-consent{width:100%; max-width:none; margin:0; text-align:left;}
  .nl-form .nl-consent input{accent-color:var(--ivory); border-color:rgba(247,242,233,.5);}
  .nl-form button{width:100%;}
  .nl-note{margin-top:1.2rem; font-size:.8rem; opacity:.6;}
  .nl-error{display:none; margin-top:1rem; font-size:.82rem; color:#f3b8ab;}
  .nl-form.has-error input{border-color:#f3b8ab;}

  /* ---------- shared marketing-consent checkbox — used in both the
     newsletter section (dark, olive-deep) and the join-promo popup
     (light, ivory), so it relies on currentColor / inherited text color
     rather than a fixed palette to read correctly in both places ---------- */
  .consent-check{
    display:flex; align-items:flex-start; gap:.6rem;
    font-size:.76rem; line-height:1.4; opacity:.85; text-align:left;
    cursor:pointer; width:100%;
  }
  .consent-check input{
    flex-shrink:0; margin-top:.15rem; width:15px; height:15px;
    accent-color:var(--olive-deep); cursor:pointer;
  }
  .consent-check span{
    flex:1; min-width:0; /* the actual fix — without min-width:0, a flex item holding
      long text can collapse to near-zero width in a nested flex layout like this one,
      forcing every word onto its own line instead of wrapping normally */
  }

  /* ============ FOOTER ============ */
  footer{background:var(--charcoal); color:var(--linen); padding:6.5rem 0 2.2rem;}

  .footer-top{
    display:flex; align-items:center; gap:4.5vw;
    padding-bottom:3.8rem; margin-bottom:1.8rem;
    border-bottom:1px solid rgba(247,242,233,.14);
  }

  .footer-brand{flex-shrink:0; padding-right:4vw; border-right:1px solid rgba(247,242,233,.14);}
  .footer-brand img{
    width:100px; height:100px; border-radius:50%; display:block;
    transition:transform .6s var(--ease);
  }
  .footer-brand img:hover{transform:rotate(6deg) scale(1.05);}

  .footer-links{display:grid; grid-template-columns:repeat(4,1fr); gap:3vw; flex:1;}
  .footer-col h4{
    font-size:.72rem; letter-spacing:.12em; text-transform:uppercase;
    color:var(--beige); opacity:.75; margin-bottom:1.3rem; font-weight:500;
  }
  .footer-col ul{list-style:none;}
  .footer-col li{margin-bottom:.75rem;}
  .footer-col a{
    position:relative; display:inline-block;
    font-size:.92rem; color:var(--linen); opacity:.78;
    transition:opacity .3s var(--ease);
  }
  .footer-col a::after{
    content:""; position:absolute; left:0; right:0; bottom:-3px; height:1px;
    background:currentColor; transform:scaleX(0); transform-origin:left;
    transition:transform .4s var(--ease);
  }
  .footer-col a:hover{opacity:1;}
  .footer-col a:hover::after{transform:scaleX(1);}

  .footer-bottom{display:flex; justify-content:space-between; align-items:center; font-size:.76rem; opacity:.5; flex-wrap:wrap; gap:.8rem;}
  .footer-secret{
    font-family:var(--serif); font-style:italic; font-size:.88rem; opacity:.6;
    color:var(--beige); letter-spacing:.01em;
    transition:opacity .5s var(--ease), letter-spacing .5s var(--ease);
  }
  .footer-secret:hover{opacity:1; letter-spacing:.03em;}

  @media (max-width:900px){
    .footer-top{flex-direction:column; align-items:flex-start; gap:2.5rem;}
    .footer-brand{padding-right:0; border-right:none; padding-bottom:0;}
    .footer-links{width:100%; grid-template-columns:1fr 1fr;}
  }
  @media (max-width:480px){
    .footer-brand img{width:80px; height:80px;}
  }
  /* Phone: same content, considerably less air around it — smaller mark,
     tighter gaps top-to-bottom, thinner divider spacing. Nothing removed,
     just compressed so the footer reads as one compact block instead of
     a long scroll of mostly-empty space. */
  @media (max-width:640px){
    footer{padding:3rem 0 1.5rem;}
    .footer-top{
      gap:1.6rem; padding-bottom:1.6rem; margin-bottom:1.1rem;
    }
    .footer-links{gap:1.6rem 6vw;}
    .footer-col h4{margin-bottom:.8rem;}
    .footer-col li{margin-bottom:.5rem;}
    .footer-bottom{font-size:.72rem; gap:.5rem;}
  }

  /* ==========================================================================
     A QUIET PROMISE — a hidden, self-contained one-page experience linked
     only from a small italic aside in the footer (.footer-secret). No
     header, no footer, no nav chrome — the absence of the site's usual
     structure is deliberate, so arriving here feels like stepping into a
     separate, quieter room rather than just another page.
     ========================================================================== */
  body.promise-page{background:var(--charcoal);}

  .promise-return{
    position:fixed; top:2.2rem; left:2.2rem; z-index:50;
    padding:.8rem; margin:-.8rem; /* enlarges the tap target well past the small text itself */
    font-size:.74rem; letter-spacing:.06em; text-transform:uppercase;
    color:var(--linen); opacity:.55;
    transition:opacity .5s var(--ease);
  }
  .promise-return:hover{opacity:1;}

  .promise-hero{
    position:relative; height:100svh; min-height:600px; overflow:hidden;
    display:flex; align-items:center; justify-content:center;
  }
  .promise-hero-image{position:absolute; inset:0;}
  .promise-hero-image img{
    width:100%; height:100%; object-fit:cover;
    filter:brightness(.6) saturate(.85);
    animation:promiseZoom 9s var(--ease) forwards;
  }
  @keyframes promiseZoom{
    0%{transform:scale(1.16);}
    100%{transform:scale(1);}
  }
  .promise-hero-overlay{
    position:absolute; inset:0;
    background:linear-gradient(180deg, rgba(20,17,13,.55) 0%, rgba(20,17,13,.25) 45%, rgba(20,17,13,.75) 100%);
  }
  .promise-hero-content{
    position:relative; z-index:2; text-align:center;
    opacity:0; transform:translateY(26px);
    animation:promiseRise 1.5s var(--ease) .5s forwards;
  }
  @keyframes promiseRise{
    to{opacity:1; transform:translateY(0);}
  }
  .promise-eyebrow{
    display:block; font-family:var(--serif); font-style:italic; color:var(--beige);
    font-size:1.15rem; margin-bottom:1.1rem;
  }
  .promise-title{font-size:clamp(3rem,9vw,6.6rem); color:var(--ivory); line-height:.98;}

  .promise-scroll-cue{
    position:absolute; left:50%; bottom:3rem; z-index:2; transform:translateX(-50%);
    width:1px; height:44px; background:rgba(247,242,233,.3);
    opacity:0; animation:promiseFadeIn 1s ease 2s forwards;
  }
  .promise-scroll-cue span{
    position:absolute; top:0; left:-2px; width:5px; height:5px; border-radius:50%;
    background:var(--ivory);
    animation:promiseScrollCue 2.6s ease-in-out infinite;
  }
  @keyframes promiseFadeIn{to{opacity:1;}}
  @keyframes promiseScrollCue{
    0%{top:0; opacity:1;}
    80%{opacity:0;}
    100%{top:40px; opacity:0;}
  }

  .promise-story{padding:16vh 0 12vh; text-align:center;}
  .promise-story-inner{max-width:640px; margin:0 auto; padding:0 var(--edge);}
  .promise-line{
    font-family:var(--serif); font-style:italic; font-size:clamp(1.3rem,2.6vw,1.9rem);
    line-height:1.5; color:var(--beige);
  }
  .promise-body{
    font-size:1.05rem; line-height:1.85; opacity:.72; color:var(--linen);
    max-width:52ch; margin:3rem auto 0;
  }
  .promise-quiet{
    font-family:var(--serif); font-size:clamp(1.7rem,3.6vw,2.5rem); line-height:1.35;
    color:var(--ivory); margin:4rem 0 3rem;
  }
  .promise-signature{
    display:block; font-size:1.35rem; color:var(--beige); opacity:.85;
  }

  .promise-close{
    display:flex; align-items:center; justify-content:center;
    padding:8vh 0 10vh; color:var(--ivory);
  }
  .promise-close span{
    position:relative; font-family:var(--serif); font-style:italic; font-size:1.3rem;
    padding-bottom:.4rem;
  }
  .promise-close span::after{
    content:""; position:absolute; left:0; right:0; bottom:0; height:1px;
    background:currentColor; transform:scaleX(0); transform-origin:center;
    transition:transform .5s var(--ease);
  }
  .promise-close:hover span::after{transform:scaleX(1);}

  @media (max-width:640px){
    .promise-return{top:1.4rem; left:1.4rem;}
    .promise-story{padding:11vh 0 8vh;}
    .promise-quiet{margin:3rem 0 2.2rem;}
  }
  @media (prefers-reduced-motion: reduce){
    .promise-hero-image img, .promise-hero-content, .promise-scroll-cue, .promise-scroll-cue span{
      animation:none; opacity:1; transform:none;
    }
  }

  /* ==========================================================================
     JOIN THE CLUB — scroll-triggered offer, homepage only. Appears once
     per session after the visitor scrolls partway down the page (see
     join-promo.js), not on load — an immediate popup would work against
     the calm, unhurried feel the rest of the site is built on. Dismissing
     it (or submitting the form, or clicking the backdrop) keeps it hidden
     for the rest of the session via sessionStorage, so it never nags on
     scroll up/down.

     A true centered "stage" moment — a dimmed backdrop focuses attention
     on it, and the entrance is choreographed in three staggered beats
     rather than one flat fade: the card itself settles into place first,
     then the image wipes open like a shutter (clip-path, not just
     opacity), then the heading/form fades up last. Each layer picks up
     roughly where the previous one is finishing, so it reads as one
     continuous unveiling motion rather than three separate animations.

     The image is full-width across the top of the card, not a small
     side column — both because the request was to show it properly, and
     because a full-width block is structurally simpler than a narrow
     nested flex column, which was the actual cause of an earlier layout
     bug (long label text collapsing to near-zero width). Everything
     below the image is a plain vertical block, not a row layout, so
     that failure mode has nowhere to occur here.

     Deliberately non-blocking: no dimming backdrop, no scroll lock. The
     page stays fully scrollable and interactive underneath — the card
     floats in from center as its own moment, but never traps the visitor
     the way a true modal would. */

  .join-promo{
    position:fixed; z-index:80; top:50%; left:50%;
    transform:translate(-50%,-50%) scale(.94);
    width:min(380px, 90vw);
    background:var(--ivory); border-radius:24px;
    overflow:hidden;
    box-shadow:0 40px 90px -20px rgba(20,17,13,.5);
    opacity:0; pointer-events:none;
    transition:opacity .5s var(--ease), transform .6s var(--ease);
  }
  .join-promo.is-visible{
    opacity:1; transform:translate(-50%,-50%) scale(1);
    pointer-events:auto;
  }

  .join-promo-close{
    position:absolute; top:.9rem; right:.9rem; z-index:3;
    width:30px; height:30px; border-radius:50%; border:none;
    background:rgba(20,17,13,.4); color:var(--ivory);
    font-size:1.05rem; line-height:1; display:flex; align-items:center; justify-content:center;
    transition:background .3s ease;
  }
  .join-promo-close::before{
    content:""; position:absolute; inset:-8px; /* extends the tap target to ~46px without changing the visible circle */
  }
  .join-promo-close:hover{background:rgba(20,17,13,.65);}

  /* the image wipes open from the top down (clip-path), starting a beat
     after the card itself has settled into place. The padding here is
     the framing "matte" — an ivory border around the photo, like a
     printed frame — and stays static; the wipe/zoom animation happens on
     the inner element only, so the frame itself never moves or clips.
     Top padding is generous specifically so the close button always sits
     clearly above the image, never overlapping its border. The frame is
     rectangular (4:5) rather than square, matching the source photo's
     own proportions closely, so object-fit:contain has almost no empty
     letterboxing to fill — nothing is cropped, but very little space
     is wasted either. */
  .join-promo-image{
    width:100%; padding:3.4rem 1.6rem 0;
    background:var(--ivory);
  }
  .join-promo-image-inner{
    position:relative; width:100%; aspect-ratio:4/5; overflow:hidden;
    border-radius:18px; background:var(--linen);
    clip-path:inset(0 0 100% 0 round 18px);
    transition:clip-path .8s var(--ease) .25s;
  }
  .join-promo.is-visible .join-promo-image-inner{clip-path:inset(0 0 0% 0 round 18px);}
  .join-promo-image-inner img{
    width:100%; height:100%; object-fit:contain; display:block;
    transform:scale(1.12);
    transition:transform 1s var(--ease) .25s;
  }
  .join-promo.is-visible .join-promo-image-inner img{transform:scale(1);}

  /* content fades up last, picking up as the image finishes wiping open */
  .join-promo-body{
    padding:1.6rem 1.7rem 1.4rem;
    text-align:center;
    opacity:0; transform:translateY(14px);
    transition:opacity .6s var(--ease) .55s, transform .6s var(--ease) .55s;
  }
  .join-promo.is-visible .join-promo-body{opacity:1; transform:translateY(0);}

  .join-promo-body .eyebrow{display:block; margin-bottom:.5rem; font-size:.85rem;}
  .join-promo-body h3{
    font-size:1.15rem; line-height:1.3; color:var(--charcoal);
    margin-bottom:.4rem; font-weight:500;
  }
  .join-promo-sub{font-size:.84rem; opacity:.6; line-height:1.4; margin-bottom:1.2rem;}

  .join-promo-form{display:flex; flex-direction:column; gap:.6rem; max-width:320px; margin:0 auto 1rem;}
  .join-promo-form input{
    width:100%; min-width:0; background:var(--linen); border:1px solid rgba(59,44,31,.18);
    border-radius:999px; padding:.7rem 1.1rem; font-size:1rem; font-family:var(--sans);
    color:var(--espresso); outline:none; text-align:left;
    transition:border-color .3s ease;
  }
  .join-promo-form input:focus{border-color:var(--olive-deep);}
  .join-promo-form .btn{width:100%; padding:.7rem 1.3rem;}
  .join-promo-note{font-size:.72rem; opacity:.5; margin-top:.8rem; line-height:1.4;}

  /* the shared .consent-check is left-aligned by default (used that way in
     the Contact page newsletter), but centered here specifically so it
     matches the rest of this popup's centered composition */
  .join-promo-body .consent-check{justify-content:center; max-width:300px; margin:0 auto;}

  /* success + error states — the form swaps its own content in place
     rather than the whole card jumping or resizing abruptly */
  .join-promo.is-success .join-promo-form,
  .join-promo.is-success .consent-check,
  .join-promo.is-success .eyebrow{display:none;}
  .join-promo-form.has-error input{border-color:#a3453a;}
  .join-promo-error{display:none; font-size:.76rem; color:#a3453a; margin-top:-.3rem; margin-bottom:.7rem;}
  .join-promo-form.has-error + .join-promo-error{display:block;}

  @media (max-width:480px){
    .join-promo{width:min(360px, 90vw);}
    .join-promo-body{padding:1.4rem 1.5rem 1.2rem;}
  }
  @media (prefers-reduced-motion: reduce){
    .join-promo, .join-promo-image-inner, .join-promo-image-inner img, .join-promo-body{
      transition:opacity .3s ease !important;
    }
    .join-promo{transform:translate(-50%,-50%);}
    .join-promo.is-visible{transform:translate(-50%,-50%);}
    .join-promo-image-inner{clip-path:none;}
    .join-promo-image-inner img{transform:none;}
    .join-promo-body{transform:none;}
  }

  /* ============ CART DRAWER ============ */
  .cart-overlay{
    position:fixed; inset:0; background:rgba(20,17,13,.45); z-index:90;
    opacity:0; pointer-events:none; transition:opacity .4s var(--ease);
  }
  .cart-overlay.open{opacity:1; pointer-events:auto;}
  .cart-drawer{
    position:fixed; top:0; right:0; bottom:0; width:min(420px,92vw); z-index:95;
    background:var(--ivory); box-shadow:-20px 0 50px -20px rgba(0,0,0,.35);
    transform:translateX(100%); transition:transform .5s var(--ease);
    display:flex; flex-direction:column;
  }
  .cart-drawer.open{transform:translateX(0);}
  .cart-head{display:flex; justify-content:space-between; align-items:center; padding:1.6rem 1.8rem; border-bottom:1px solid rgba(59,44,31,.12);}
  .cart-head h3{font-size:1.3rem;}
  .cart-close{background:none; border:none; font-size:1.4rem; line-height:1; color:var(--espresso); padding:.6rem; margin:-.6rem;}

  /* flex:0 1 auto (not flex:1) — the items list sizes to its own content
     instead of always stretching to fill the drawer, which was the actual
     cause of the dead space: a short cart used to leave a large gap right
     before the checkout button. Any leftover drawer height now simply
     sits below the footer instead of awkwardly splitting the content. */
  .cart-items{flex:0 1 auto; overflow-y:auto; padding:1.4rem 1.8rem;}

  /* ---------- empty state: a small drawn fish + links back into the site's
     own curated experiences, so an empty cart still feels like part of the
     market rather than a dead end ---------- */
  .cart-empty{padding:2.5rem 0 1.5rem; text-align:center;}
  .cart-empty-mark{
    display:inline-flex; width:52px; height:28px; color:var(--olive-deep); opacity:.5;
    margin-bottom:1.2rem;
  }
  .cart-empty-mark svg{width:100%; height:100%;}
  .cart-empty p{font-size:.92rem; opacity:.65; margin-bottom:1.4rem;}
  .cart-empty-links{display:flex; flex-direction:column; gap:.7rem; align-items:center;}
  .cart-empty-links a{
    font-family:var(--serif); font-style:italic; font-size:1rem; color:var(--olive-deep);
    position:relative; padding-bottom:.15rem;
  }
  .cart-empty-links a::after{
    content:""; position:absolute; left:0; right:0; bottom:0; height:1px;
    background:currentColor; opacity:.4; transform:scaleX(0); transform-origin:left;
    transition:transform .35s var(--ease);
  }
  .cart-empty-links a:hover::after{transform:scaleX(1);}

  /* ---------- line items: a quiet receipt-ticket feel — a dashed rule
     between name and price rather than a plain flex space-between ---------- */
  .cart-line{display:flex; gap:1rem; padding:1.1rem 0; border-bottom:1px dashed rgba(59,44,31,.16);}
  .cart-line .thumb{width:64px; height:64px; border-radius:10px; overflow:hidden; flex-shrink:0; background:var(--linen); border:1px solid rgba(59,44,31,.08);}
  .cart-line .thumb img{width:100%; height:100%; object-fit:cover;}
  .cart-line-info{flex:1;}
  .cart-line-info h4{font-size:1rem; font-weight:400; margin-bottom:.2rem;}
  .cart-line-info .price{font-family:var(--serif); font-style:italic; font-size:.9rem; color:var(--olive-deep); opacity:.85;}
  .qty-controls{display:flex; align-items:center; gap:.6rem; margin-top:.5rem;}
  .qty-controls button{width:24px; height:24px; border-radius:50%; border:1px solid var(--espresso); background:none; font-size:.85rem; display:flex; align-items:center; justify-content:center;}
  .qty-controls span{font-size:.88rem; min-width:14px; text-align:center;}
  .remove-line{
    font-size:.72rem; opacity:.5; text-decoration:underline; margin-left:auto; align-self:flex-start;
    padding:.6rem; margin:-.6rem -.6rem -.6rem auto; /* invisible larger tap target, same visual position */
  }

  /* ---------- footer: a soft market-linen backdrop with a dashed rule
     above the total, reading a little like a handwritten market ticket
     rather than a flat checkout bar ---------- */
  .cart-foot{
    padding:1.6rem 1.8rem; border-top:1px dashed rgba(59,44,31,.22);
    background:var(--linen);
  }
  .cart-subtotal{display:flex; justify-content:space-between; align-items:baseline; margin-bottom:.5rem;}
  .cart-subtotal span:first-child{font-size:.78rem; letter-spacing:.08em; text-transform:uppercase; opacity:.6;}
  .cart-subtotal span:last-child{font-family:var(--serif); font-style:italic; font-size:1.3rem; color:var(--olive-deep);}
  /* Per-order delivery ($5 local) / shipping ($7 nationwide) fee lines, injected
     by renderCart() in script.js so the customer sees them before checkout. */
  .cart-fee{display:flex; justify-content:space-between; align-items:baseline; margin-bottom:.35rem;}
  .cart-fee span:first-child{font-size:.74rem; letter-spacing:.06em; text-transform:uppercase; opacity:.55;}
  .cart-fee span:last-child{font-size:.92rem; color:var(--olive-deep);}
  .cart-total{display:flex; justify-content:space-between; align-items:baseline; margin:.6rem 0 1rem; padding-top:.6rem; border-top:1px solid rgba(59,44,31,.15);}
  .cart-total span:first-child{font-size:.8rem; letter-spacing:.08em; text-transform:uppercase; opacity:.7;}
  .cart-total span:last-child{font-family:var(--serif); font-style:italic; font-size:1.4rem; color:var(--olive-deep);}
  /* Applied discount line (e.g. welcome code) — green, to read as money saved. */
  .cart-discount span{color:var(--olive); opacity:.85;}
  .cart-discount span:first-child{text-transform:none; letter-spacing:.02em; opacity:.7;}
  /* Discount-code entry box in the drawer. */
  .cart-promo{margin-bottom:.9rem;}
  .cart-promo-row{display:flex; gap:.5rem;}
  .cart-promo-row input{
    flex:1; min-width:0; background:var(--linen); border:1px solid rgba(59,44,31,.2);
    border-radius:999px; padding:.6rem 1rem; font-size:.9rem; font-family:var(--sans);
    color:var(--espresso); outline:none; transition:border-color .3s ease;
  }
  .cart-promo-row input:focus{border-color:var(--olive-deep);}
  .cart-promo-row input:disabled{opacity:.6;}
  .cart-promo-btn{
    flex-shrink:0; border:1px solid var(--olive-deep); background:transparent; color:var(--olive-deep);
    border-radius:999px; padding:.6rem 1.1rem; font-size:.74rem; letter-spacing:.06em; text-transform:uppercase;
    cursor:pointer; transition:background .25s ease, color .25s ease;
  }
  .cart-promo-btn:hover{background:var(--olive-deep); color:var(--ivory);}
  .cart-promo-btn:disabled{opacity:.55; cursor:default;}
  .cart-promo-msg{font-size:.76rem; margin:.4rem 0 0; min-height:1em; line-height:1.35;}
  .cart-promo-msg.is-success{color:var(--olive);}
  .cart-promo-msg.is-error{color:#a3453a;}
  .cart-note{font-size:.78rem; opacity:.6; margin-bottom:1.2rem;}

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

  /* ============ MOBILE NAVIGATION DRAWER ============
     Full-screen overlay menu, triggered by the hamburger button. Only
     relevant below the 1000px nav breakpoint (see .nav-toggle above) —
     desktop keeps the horizontal .primary-nav and never sees this. */
  .mobile-nav-overlay{
    position:fixed; inset:0; z-index:110;
    background:rgba(20,17,13,.4);
    opacity:0; pointer-events:none; transition:opacity .4s var(--ease);
  }
  .mobile-nav-overlay.open{opacity:1; pointer-events:auto;}

  .mobile-nav{
    position:fixed; top:0; right:0; bottom:0; z-index:115;
    width:min(360px,86vw);
    background:var(--ivory);
    box-shadow:-24px 0 60px -20px rgba(0,0,0,.35);
    transform:translateX(100%);
    transition:transform .5s var(--ease);
    display:flex; flex-direction:column;
    padding:6.5rem 2.2rem 2.5rem;
  }
  .mobile-nav.open{transform:translateX(0);}

  .mobile-nav-close{
    position:absolute; top:1.4rem; right:1.4rem;
    width:44px; height:44px; display:flex; align-items:center; justify-content:center;
    background:none; border:none; font-size:1.8rem; line-height:1; color:var(--espresso);
  }

  .mobile-nav ul{list-style:none;}
  .mobile-nav li{border-bottom:1px solid rgba(59,44,31,.1);}
  .mobile-nav li:first-child{border-top:1px solid rgba(59,44,31,.1);}
  .mobile-nav a{
    display:flex; align-items:center; min-height:56px;
    font-family:var(--serif); font-size:1.35rem; color:var(--charcoal);
  }
  .mobile-nav a.is-active{color:var(--olive-deep); font-style:italic;}

  .mobile-nav-cta{margin-top:2.2rem; width:100%; justify-content:center;}

  /* prevent background scroll while the drawer is open */
  html.nav-open, html.nav-open body{overflow:hidden; height:100%;}

  /* hamburger -> X transform when open */
  .nav-toggle .bar1, .nav-toggle .bar2, .nav-toggle .bar3{
    display:block; width:22px; height:1.5px; background:var(--ivory); margin:5px 0;
    transition:background .5s var(--ease), transform .35s var(--ease), opacity .25s var(--ease);
  }
  header.scrolled .nav-toggle .bar1,
  header.scrolled .nav-toggle .bar2,
  header.scrolled .nav-toggle .bar3{background:var(--charcoal);}
  .nav-toggle.is-open .bar1, .nav-toggle.is-open .bar2, .nav-toggle.is-open .bar3{background:var(--charcoal);}
  .nav-toggle.is-open .bar1{transform:translateY(6.5px) rotate(45deg);}
  .nav-toggle.is-open .bar2{opacity:0;}
  .nav-toggle.is-open .bar3{transform:translateY(-6.5px) rotate(-45deg);}

  @media (min-width:1000px){
    .mobile-nav, .mobile-nav-overlay{display:none;} /* desktop never needs the drawer */
  }
  @media (prefers-reduced-motion: reduce){
    .mobile-nav, .mobile-nav-overlay, .nav-toggle .bar1, .nav-toggle .bar2, .nav-toggle .bar3{transition:none;}
  }

  /* ============ RESPONSIVE ============ */
  @media (max-width:1000px){
    nav.primary-nav{display:none;}
    .nav-toggle{display:flex; flex-direction:column; background:none; border:none;}
    .hero img{object-position:50% 50%;} /* tablet: keeps the meals centered in the taller crop; the
      container sits in the vertical middle of the photo (roughly 30-60% down), while the
      text card is anchored at the very bottom, so vertical separation should hold even
      though horizontal cropping happens differently than on desktop */
    .weekly-menu{grid-template-columns:1fr; gap:2.5rem; min-width:0;}
    .weekly-menu-panel{min-width:0;} /* grid items default to min-width:auto, which can
      refuse to shrink below a child's intrinsic content width — this plus the missing
      width:100% on .category-tabs together caused the page to overflow horizontally */
    .weekly-menu-frame{margin-left:0; aspect-ratio:4/5;} /* was 16/10 — a landscape ratio that
      doesn't suit these portrait food photos at all, cropping 19-27% off the top AND bottom of
      every tab image on mobile. Matching desktop's 4:5 keeps the same photos properly framed
      instead of aggressively cropped on the exact device most customers will be ordering from. */
    .about-grid{grid-template-columns:1fr; gap:3rem;}
    .about-portrait-wrap{position:static; max-width:320px;}
    .exp-grid{grid-template-columns:1fr;}
    .exp-frame{border-radius:var(--radius); margin-right:0; aspect-ratio:16/10;}
    .exp-copy{border-radius:var(--radius); margin-top:-2rem; padding:3rem 6vw;}
    .exp-typewrite{
      /* Desktop's top:calc(7% + 68px) assumes the taller 4:5 frame above —
         on this shorter 16:10 mobile frame that fixed 68px pushes the
         caption down toward the middle of the (cropped) photo instead of
         sitting near the top. A smaller percentage-only offset keeps it
         high on the frame regardless of how the photo gets cropped. */
      top:6%;
    }
  }
  @media (max-width:640px){
    .hero img{object-position:50% 50%;} /* phone: same reasoning as tablet */
    .hero-card{
      left:var(--edge); right:var(--edge); text-align:left; bottom:6vh; max-width:none;
      /* on phones the full photo height shows with no vertical cropping, and the tray
         sits roughly 32-60% down the frame — this keeps the text block anchored low
         enough to clear it rather than overlapping, and left-aligned as requested
         rather than inheriting the desktop right-alignment */
    }
    .hero-sub{margin-left:0; margin-right:auto;}
    .hero-card .hero-script-img{margin-left:0; margin-right:auto; max-width:420px;} /* left-aligned
      to match .hero-card's mobile text-align:left; capped narrower than the edge-to-edge card so
      the handwriting doesn't stretch full-bleed and lose its natural proportions on phones.
      (Selector needs the .hero-card prefix here too, same specificity reason as above.) */
    .hero-ctas{justify-content:flex-start;}
    .interlude{padding:8rem 0;}
    .about{padding:7rem 0;}
    .experiences, .market, .meals{padding-top:5rem; padding-bottom:5rem;}
  }

  @media (prefers-reduced-motion: reduce){
    *{animation:none !important; transition:none !important;}
    .reveal, .word{opacity:1; transform:none;}
    .hero img{transform:none !important;}
  }
  /* ==========================================================================
     ORDERING SYSTEM — Menu / Drop / Cart extensions
     Added to support menu.html and drop.html. Reuses existing tokens, .btn,
     .reveal, .frame-style patterns, .cart-drawer / .cart-overlay / .cart-line
     / .qty-controls components already defined above. Nothing above this
     point was changed.
     ========================================================================== */

  /* nav.primary-nav a.is-active::after removed on purpose — the active page
     no longer shows a persistent underline. The underline is now a
     hover-only affordance (see nav.primary-nav a:hover::after above), which
     keeps the nav quiet and editorial rather than marking a page as
     "selected" by default. */

  /* ---------- menu.html hero + drop selection ---------- */
  .menu-hero{padding:11rem 0 3rem;}
  .menu-hero h1{font-size:clamp(2.6rem,7vw,5.5rem); line-height:0.95;}
  .menu-hero-sub{margin-top:1.2rem; max-width:46ch; font-size:1.05rem; opacity:.75;}

  .drop-select{padding:2rem 0 8rem;}
  .drop-cards{display:grid; grid-template-columns:repeat(2,1fr); gap:2.4rem;}
  .drop-card{
    display:block; border-radius:var(--radius); overflow:hidden; background:var(--linen);
    transition:transform .5s var(--ease), box-shadow .5s var(--ease);
  }
  .drop-card:hover{transform:translateY(-6px); box-shadow:0 30px 60px -24px rgba(36,31,25,.3);}
  .drop-card-frame{aspect-ratio:16/10; overflow:hidden;}
  .drop-card-frame img{width:100%; height:100%; object-fit:cover; transition:transform .8s var(--ease);}
  .drop-card:hover .drop-card-frame img{transform:scale(1.06);}
  .drop-card-body{padding:2.2rem;}
  .drop-card-body h2{font-size:1.9rem; margin:.5rem 0 .8rem;}
  .drop-card-desc{font-size:.95rem; opacity:.75; margin-bottom:1.3rem; max-width:42ch;}
  .drop-card-meta{display:flex; gap:.6rem; font-size:.82rem; opacity:.6; margin-bottom:1.8rem;}
  .drop-card-footer{display:flex; justify-content:space-between; align-items:center;}
  .drop-card-price{font-family:var(--serif); font-style:italic; color:var(--olive-deep); font-size:1.1rem;}

  /* ---------- drop.html header ---------- */
  .drop-header{background:var(--charcoal); color:var(--ivory); padding-top:5.5rem; padding-bottom:3.5rem;}
  .drop-header-media{height:42vh; min-height:300px; position:relative; overflow:hidden; margin-bottom:2.8rem;}
  .drop-header-media img{width:100%; height:100%; object-fit:cover;}
  .drop-header-media::after{
    content:""; position:absolute; inset:0;
    background:linear-gradient(to top, var(--charcoal) 0%, rgba(36,31,25,.15) 60%);
  }
  .drop-header-inner .eyebrow{color:var(--beige);}
  .drop-header-inner h1{color:var(--ivory); font-size:clamp(2.2rem,5vw,4rem); margin-top:.6rem;}
  .drop-header-desc{margin-top:1rem; max-width:56ch; opacity:.85; font-size:1.05rem;}
  .drop-header-facts{display:flex; flex-wrap:wrap; gap:2.6rem; margin:2.2rem 0;}
  .fact-label{display:block; font-size:.72rem; letter-spacing:.08em; text-transform:uppercase; opacity:.6; margin-bottom:.35rem;}
  .fact-value{font-family:var(--serif); font-size:1.05rem; max-width:34ch;}
  .drop-header-notes{max-width:64ch; font-size:.9rem; opacity:.68; border-top:1px solid rgba(247,242,233,.18); padding-top:1.5rem;}

  /* ---------- drop.html body: grid + sticky summary ---------- */
  .drop-body{padding:4rem 0 8rem;}
  .drop-layout{display:grid; grid-template-columns:1fr 360px; gap:3rem; align-items:start;}
  .drop-grid{display:grid; grid-template-columns:repeat(2,1fr); gap:2rem;}

  .meal-order-card{
    background:var(--ivory); border:1px solid rgba(59,44,31,.1); border-radius:var(--radius);
    overflow:hidden; display:flex; flex-direction:column;
    transition:transform .5s var(--ease), box-shadow .5s var(--ease);
  }
  .meal-order-card:hover{transform:translateY(-4px); box-shadow:0 24px 46px -20px rgba(36,31,25,.22);}
  .meal-order-frame{position:relative; aspect-ratio:4/3; overflow:hidden;}
  .meal-order-frame img{width:100%; height:100%; object-fit:cover; transition:transform .8s var(--ease);}
  .meal-order-card:hover .meal-order-frame img{transform:scale(1.06);}
  .meal-order-card.is-sold-out{opacity:.7;}
  .sold-out-overlay{
    position:absolute; inset:0; background:rgba(36,31,25,.5); color:var(--ivory);
    display:flex; align-items:center; justify-content:center;
    font-family:var(--serif); font-style:italic; font-size:1.15rem; letter-spacing:.02em;
  }
  .meal-order-body{padding:1.7rem; display:flex; flex-direction:column; gap:.65rem; flex:1;}
  .dietary-tags{display:flex; flex-wrap:wrap; gap:.4rem;}
  .dietary-tag{
    font-size:.66rem; letter-spacing:.04em; text-transform:uppercase;
    padding:.32rem .7rem; border-radius:999px; background:var(--linen); color:var(--olive-deep);
  }
  .meal-order-body h3{font-size:1.3rem; margin-top:.15rem;}
  .meal-order-desc{font-size:.9rem; opacity:.72;}
  .macro-row{
    display:flex; gap:1rem; padding:.85rem 0; margin:.3rem 0;
    border-top:1px solid rgba(59,44,31,.1); border-bottom:1px solid rgba(59,44,31,.1);
  }
  .macro-row > div{display:flex; flex-direction:column; align-items:center; flex:1;}
  .macro-value{font-family:var(--serif); font-size:1.05rem; color:var(--charcoal);}
  .macro-label{font-size:.66rem; letter-spacing:.04em; text-transform:uppercase; opacity:.55; margin-top:.15rem;}
  .meal-order-ingredients, .meal-order-allergens{font-size:.8rem; opacity:.65; line-height:1.55;}
  .meal-order-allergens{color:var(--olive-deep);}
  .meal-order-footer{margin-top:auto; padding-top:.9rem; display:flex; justify-content:space-between; align-items:center;}
  .meal-order-footer .price{font-family:var(--serif); font-style:italic; font-size:1.25rem; color:var(--olive-deep);}
  .sold-out-tag{font-size:.75rem; letter-spacing:.05em; text-transform:uppercase; color:var(--stone);}

  /* quantity stepper: extends the existing .qty-controls component */
  .qty-controls button:disabled{opacity:.25; cursor:not-allowed;}
  .qty-controls.has-qty span{color:var(--olive-deep); font-weight:500;}

  /* ---------- order summary rows (Meals / Subtotal / Tax / Total) ---------- */
  .order-row{display:flex; justify-content:space-between; font-size:.95rem; margin-bottom:.6rem; opacity:.85;}
  .order-row-total{
    font-size:1.15rem; opacity:1; margin-top:.8rem; padding-top:.8rem;
    border-top:1px solid rgba(59,44,31,.15); font-family:var(--serif);
  }

  /* ---------- desktop-sticky variant of the shared cart drawer ---------- */
  @media (min-width:1000px){
    .drop-layout .order-drawer{
      position:sticky; top:7rem; right:auto; bottom:auto;
      width:auto; height:auto; max-height:calc(100vh - 9rem); overflow-y:auto;
      transform:none; box-shadow:0 20px 50px -30px rgba(36,31,25,.25);
      border-radius:var(--radius); border:1px solid rgba(59,44,31,.1);
    }
    .drop-layout #order-drawer-close{display:none;}
  }

  /* ---------- mobile sticky checkout bar ---------- */
  .sticky-cart-bar{
    position:fixed; left:0; right:0; bottom:0; z-index:80;
    background:var(--charcoal); color:var(--ivory);
    transform:translateY(100%); transition:transform .45s var(--ease);
    padding-bottom:env(safe-area-inset-bottom, 0);
  }
  .sticky-cart-bar.visible{transform:translateY(0);}
  .sticky-cart-bar button{
    width:100%; display:flex; align-items:center; justify-content:space-between; gap:1rem;
    background:none; border:none; color:inherit; padding:1.1rem var(--edge);
    font-family:var(--sans); font-size:.9rem;
  }
  .sticky-cart-count{opacity:.75;}
  .sticky-cart-subtotal{font-family:var(--serif); font-style:italic; font-size:1.05rem;}
  .sticky-cart-cta{
    font-size:.78rem; letter-spacing:.07em; text-transform:uppercase;
    border-bottom:1px solid rgba(247,242,233,.6); padding-bottom:.25rem;
  }
  @media (min-width:1000px){
    .sticky-cart-bar{display:none;} /* desktop uses the sticky sidebar summary instead */
  }

  /* ---------- responsive: ordering system ---------- */
  @media (max-width:1000px){
    .drop-layout{grid-template-columns:1fr;}
    .drop-grid{grid-template-columns:repeat(2,1fr);}
    .qty-controls button{width:32px; height:32px; font-size:1.05rem;} /* larger touch targets */
    .drop-body{padding-bottom:7rem;} /* clear the sticky mobile bar */
  }
  @media (max-width:700px){
    .drop-cards{grid-template-columns:1fr;}
    .drop-grid{grid-template-columns:1fr;}
    .drop-header-facts{gap:1.6rem;}
    .drop-header-media{height:34vh; min-height:220px;}
    .macro-row{gap:.5rem;}
    .qty-controls button{width:40px; height:40px; font-size:1.1rem;} /* accessible touch target on phones */
    .qty-controls span{min-width:22px;}
  }

  /* ==========================================================================
     WEEKLY MENU — category tabs + accordion meals + single package price
     Reuses existing tokens, .btn, .reveal, and typography. Supersedes the
     old single-dish "featured meal" widget (that markup no longer exists).
     ========================================================================== */

  .category-tabs{
    display:flex; flex-wrap:wrap; gap:.5rem;
    margin-bottom:2.4rem;
  }
  .category-tab{
    font-family:var(--sans); font-size:.76rem; font-weight:500;
    letter-spacing:.06em; text-transform:uppercase;
    padding:.6rem 1.3rem; border-radius:999px;
    border:1px solid transparent; background:transparent;
    color:var(--espresso); opacity:.6;
    transition:background .35s var(--ease), color .35s var(--ease),
               opacity .35s var(--ease), border-color .35s var(--ease);
  }
  .category-tab:hover{
    opacity:1; background:rgba(59,44,31,.06); border-color:rgba(59,44,31,.16);
  }
  .category-tab.is-active{
    background:var(--espresso); color:var(--ivory);
    opacity:1; border-color:var(--espresso);
  }
  .category-tab.is-active:hover{background:var(--olive-deep); border-color:var(--olive-deep);}
  .category-tab:focus-visible{outline:2px solid var(--olive); outline-offset:2px;}

  @media (max-width:640px){
    .category-tabs{
      flex-wrap:nowrap; overflow-x:auto; -webkit-overflow-scrolling:touch;
      width:100%; max-width:100%; /* without this, a nowrap+overflow-x:auto flex container
        can grow to fit its content and push the whole page wider instead of scrolling
        contained within itself — this was the actual cause of the horizontal page
        overflow on mobile, not just the tabs row looking cramped */
      padding-bottom:.4rem; margin-bottom:1.8rem;
    }
    .category-tabs::-webkit-scrollbar{display:none;}
    .category-tab{flex:0 0 auto; padding:.85rem 1.3rem;} /* larger touch target on phones */
  }

  /* ---------- layout: image left, tabs + category panel right ---------- */
  .weekly-menu{
    display:grid; grid-template-columns:1fr 1.2fr; gap:5vw; align-items:start; min-width:0;
    margin-bottom:4rem;
  }
  .weekly-menu-frame{
    position:relative; border-radius:var(--radius); overflow:hidden; aspect-ratio:4/5;
    background:var(--linen); /* shows around the edges when an image uses .fit-contain below */
    margin-left:calc(var(--edge) * -0.75); /* was -1 (full bleed to edge); reduced 25% so
      there's now real breathing room from the border instead of touching it */
  }
  .weekly-menu-frame img{
    width:100%; height:100%; object-fit:cover; object-position:10% 42%;
    /* the crop position only matters for the dessert photo (the one non-4:5
       source among the four tab images) — the other three are native 4:5
       and fill the frame exactly with nothing left to crop, so this has no
       visual effect on them regardless of value. Tuned to keep the cake
       slice comfortably in frame rather than defaulting to dead-center,
       which would crop too far into it on the left side. */
    transition:opacity .36s var(--ease), transform .36s var(--ease);
  }
  /* used for the breakfast/butter photo specifically — that tray needs to
     be shown in full rather than cropped, so it swaps to contain instead
     of cover. Toggled via JS based on each category's optional "fit" field
     (see weekly-menu.js), not a blanket change, so the other three tab
     images are completely unaffected and keep their normal cover fit. */
  .weekly-menu-frame img.fit-contain{object-fit:contain; object-position:50% 50%;}
  /* centered + a slight zoom, specifically for the breakfast/butter photo —
     independent of the dessert-tuned object-position on the base rule above,
     since these two images need different crop treatment and now both share
     the same <img> element across tab switches */
  .weekly-menu-frame img.tab-breakfast{object-position:50% 50%; transform:scale(1.08);}
  .weekly-menu-panel > .eyebrow{display:block; margin:.4rem 0 1.4rem;}

  .weekly-menu.is-switching .weekly-menu-frame img{opacity:0; transform:scale(1.04);}
  .weekly-menu.is-switching .category-panel{opacity:0; transform:translateY(10px);}
  .category-panel{
    transition:opacity .32s var(--ease), transform .32s var(--ease);
  }

  /* ---------- selection groups + option cards ---------- */
  .meal-select-group{margin-bottom:2rem;}
  .meal-select-group:last-child{margin-bottom:0;}
  .meal-select-label{
    display:block; font-size:.72rem; letter-spacing:.09em; text-transform:uppercase;
    color:var(--stone); margin-bottom:.8rem;
  }
  .meal-option-cards{display:grid; grid-template-columns:1fr 1fr; gap:1rem;}
  .meal-option-card{
    position:relative; text-align:left; background:var(--ivory);
    border:1.5px solid rgba(59,44,31,.16); border-radius:calc(var(--radius) - 6px);
    padding:1.2rem 1.3rem 1.3rem; display:flex; flex-direction:column; gap:.4rem;
    transition:border-color .3s var(--ease), background .3s var(--ease), transform .25s var(--ease);
  }
  .meal-option-card:hover{border-color:rgba(59,44,31,.32); transform:translateY(-2px);}
  .meal-option-card.is-selected{
    background:var(--linen); border-color:var(--olive-deep);
  }
  .meal-option-name{font-family:var(--serif); font-size:1.1rem; color:var(--charcoal); padding-right:1.6rem;}
  .meal-option-desc{font-size:.85rem; opacity:.68; line-height:1.5;}
  .meal-option-check{
    position:absolute; top:1.1rem; right:1.1rem; width:18px; height:18px;
    border:1.5px solid rgba(59,44,31,.3); border-radius:50%;
    transition:border-color .3s var(--ease), background .3s var(--ease);
  }
  .meal-option-check::after{
    content:""; position:absolute; inset:3px; border-radius:50%;
    background:var(--olive-deep); transform:scale(0); transition:transform .25s var(--ease);
  }
  .meal-option-card.is-selected .meal-option-check{border-color:var(--olive-deep);}
  .meal-option-card.is-selected .meal-option-check::after{transform:scale(1);}
  .meal-option-card:focus-visible{outline:2px solid var(--olive); outline-offset:2px;}
  /* Included "Sweet Treat" — a single set item, not selectable. */
  .meal-fixed-card{
    text-align:left; background:var(--linen);
    border:1.5px solid var(--olive-deep); border-radius:calc(var(--radius) - 6px);
    padding:1.3rem 1.4rem; display:flex; flex-direction:column; gap:.45rem;
  }
  .meal-fixed-name{font-family:var(--serif); font-size:1.2rem; color:var(--charcoal);}
  .meal-fixed-desc{font-size:.88rem; opacity:.68; line-height:1.5;}
  .meal-fixed-note{margin:1rem 0 0; font-family:var(--serif); font-style:italic; font-size:.92rem; color:var(--olive-deep); opacity:.75;}

  /* ---------- live weekly summary ---------- */
  .weekly-summary{
    background:var(--linen); border-radius:22px; padding:3rem;
    box-shadow:0 1px 2px rgba(59,44,31,.04), 0 12px 32px -16px rgba(59,44,31,.12);
  }
  .weekly-summary-head{margin-bottom:2.5rem; max-width:60ch;}
  .weekly-summary-head .eyebrow{display:block; margin-bottom:.5rem;}
  .weekly-summary-head h3{font-size:clamp(1.7rem,2.8vw,2.3rem); color:var(--charcoal); margin-bottom:.6rem;}
  .weekly-summary-head p{font-size:.92rem; opacity:.65;}

  /* ---------- week blocks: Week 1 / Week 2 read as two matching, clearly
     separated groups rather than one undifferentiated pile of categories ---------- */
  .summary-week-label{
    display:block; font-size:.72rem; letter-spacing:.1em; text-transform:uppercase;
    color:var(--olive-deep); font-weight:600; margin-bottom:1rem;
  }
  .summary-week-divider{
    height:1px; background:rgba(59,44,31,.14); margin:2.5rem 0;
  }

  .summary-rows{display:flex; flex-direction:column;}
  .summary-row{
    display:grid; grid-template-columns:9rem 1fr; align-items:baseline; gap:1rem;
    padding:1rem 0; border-bottom:1px solid rgba(59,44,31,.08);
  }
  .summary-rows .summary-row:last-child{border-bottom:none; padding-bottom:.5rem;}
  .summary-row-label{
    font-size:.7rem; letter-spacing:.08em; text-transform:uppercase; color:var(--stone);
  }
  .summary-row-value{
    display:flex; flex-direction:column; gap:.3rem;
    font-family:var(--serif); font-size:1.05rem; color:var(--charcoal); line-height:1.35;
  }
  .summary-multiplier{font-family:var(--sans); font-size:.85rem; color:var(--olive-deep); opacity:.85;}

  .weekly-summary-footer{
    display:flex; justify-content:space-between; align-items:center; gap:2rem; flex-wrap:wrap;
    margin-top:2.5rem; padding-top:2rem; border-top:1px solid rgba(59,44,31,.14);
  }
  .weekly-price-amount{font-family:var(--serif); font-style:italic; font-size:2.4rem; color:var(--olive-deep);}
  .weekly-summary-footer .add-link.added{background:var(--olive-deep); color:var(--ivory); border-color:var(--olive-deep);}

  /* ---------- utility ---------- */
  .visually-hidden{
    position:absolute; width:1px; height:1px; padding:0; margin:-1px;
    overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;
  }

  /* ---------- second meal set: card, toggle, reveal ---------- */
  .second-week-card{
    background:var(--linen); border-radius:var(--radius); padding:1.8rem 0;
    margin-top:3rem; overflow:hidden;
    /* horizontal padding moved off this card and onto .second-set-toggle-row
       and .second-week-heading specifically (below) — those two stay inset,
       but the actual Week 2 menu (.second-weekly-menu) now has nothing to
       cancel out, so it can span the full card width safely with no
       negative-margin math that can overflow. */
    /* no margin-bottom here — this is inside a grid container (#weekly-menu),
       which doesn't collapse margins with its children, so a bottom margin
       here would stack ON TOP of #weekly-menu's own margin-bottom:4rem
       below instead of merging with it. That double-margin was the large
       empty gap before "Here's what's coming" on mobile. */
  }

  .second-set-toggle-row{
    display:flex; align-items:center; gap:1.2rem; padding:0 2rem;
  }
  .second-set-toggle{
    position:relative; display:inline-flex; cursor:pointer; flex-shrink:0;
    padding:8px; margin:-8px; /* grows the tap target to 44px+ without changing the switch's visual size */
  }
  .second-set-toggle input{position:absolute; opacity:0; width:1px; height:1px;}
  .toggle-track{
    display:block; width:48px; height:28px; border-radius:999px;
    background:rgba(59,44,31,.2);
    transition:background .3s var(--ease);
    position:relative;
  }
  .toggle-thumb{
    position:absolute; top:3px; left:3px; width:22px; height:22px; border-radius:50%;
    background:var(--ivory); box-shadow:0 1px 3px rgba(0,0,0,.22);
    transition:transform .3s var(--ease);
  }
  .second-set-toggle input:checked ~ .toggle-track{background:var(--olive-deep);}
  .second-set-toggle input:checked ~ .toggle-track .toggle-thumb{transform:translateX(20px);}
  .second-set-toggle input:focus-visible ~ .toggle-track{outline:2px solid var(--olive); outline-offset:3px;}

  .second-set-toggle-text{cursor:pointer;}
  .second-set-toggle-text strong{
    display:block; font-family:var(--serif); font-size:1.15rem; color:var(--olive-deep); margin-bottom:.2rem;
  }
  .second-set-toggle-text span{font-size:.85rem; opacity:.7;}
  .second-set-toggle-text em{font-style:italic; color:var(--olive-deep); opacity:1;}

  /* smooth fade + slide-down reveal — grid-rows animates to auto-height
     without any JS height measurement */
  .second-set-reveal{
    display:grid; grid-template-rows:0fr;
    transition:grid-template-rows .5s var(--ease);
  }
  .second-set-reveal.is-open{grid-template-rows:1fr;}
  .second-set-reveal-inner{
    overflow:hidden; min-height:0;
    opacity:0; transform:translateY(-10px);
    transition:opacity .4s var(--ease) .05s, transform .4s var(--ease) .05s;
  }
  .second-set-reveal.is-open .second-set-reveal-inner{opacity:1; transform:translateY(0);}

  .second-week-heading{
    margin-top:2.2rem; padding:2.2rem 2rem 0; border-top:1px solid rgba(59,44,31,.14);
    margin-bottom:1.8rem;
  }
  .second-week-heading .eyebrow{display:block; margin-bottom:.5rem;}
  .second-week-heading p{font-size:.92rem; opacity:.7; max-width:50ch;}

  .second-weekly-menu{
    background:transparent; border-radius:0; padding:0 2rem;
    /* matches the 2rem horizontal inset on .second-set-toggle-row and
       .second-week-heading above it, so the tabs and option cards line up
       flush with everything else in the card instead of touching its edges
       (zero padding matched Week 1's width exactly, but looked like the
       menu was bleeding out of the card since nothing else in the card sits
       edge-to-edge). Still ordinary padding, not a negative-margin bleed —
       nothing here can overflow the card. */
    display:block; /* base .weekly-menu is a 2-column grid for the image+panel;
      Week 2 has no image, so this collapses it to a single block */
  }

  /* price-change pulse — a brief scale+opacity flicker rather than an
     abrupt text swap, triggered by JS toggling .is-updating whenever the
     total changes */
  .weekly-price-amount{display:inline-block; transition:transform .3s var(--ease), opacity .3s var(--ease);}
  .weekly-price-amount.is-updating{transform:scale(1.08); opacity:.55;}

  @media (max-width:640px){
    .weekly-summary{padding:2.2rem;}
    .second-week-card{padding:2rem 0;}
    .second-set-toggle-row{padding:0 1.6rem; align-items:flex-start;}
    .second-week-heading{padding:2.2rem 1.6rem 0;}
    .second-weekly-menu{padding:0 1.6rem;}
    .summary-row{grid-template-columns:1fr; gap:.3rem;}
    .summary-week-divider{margin:2rem 0;}
    .weekly-summary-footer{flex-direction:column; align-items:flex-start; width:100%;}
    .weekly-summary-footer .btn{width:100%;}
    .meal-option-cards{grid-template-columns:1fr;}
  }

  @media (prefers-reduced-motion: reduce){
    .weekly-menu-frame img,
    .category-panel,
    .meal-option-card,
    .meal-option-check::after,
    .second-set-reveal,
    .second-set-reveal-inner,
    .toggle-thumb,
    .toggle-track{
      transition:none !important;
    }
  }

  /* ==========================================================================
     MULTI-PAGE ARCHITECTURE — page fade transitions + standalone page helpers
     --------------------------------------------------------------------------
     Replaces the earlier scroll-snap "paged homepage" approach. The site is
     now genuinely multi-page (see page-transitions.js); each page fades in
     on load and fades out just before an internal navigation, rather than
     relying on any in-page scroll trick.
     ========================================================================== */

  body{
    opacity:0; transform:translateY(10px);
    transition:opacity .45s var(--ease), transform .45s var(--ease);
  }
  body.page-ready{opacity:1; transform:translateY(0);}
  body.page-leaving{
    opacity:0; transform:translateY(-10px);
    transition:opacity .3s var(--ease), transform .3s var(--ease);
  }
  /* if JS never runs (blocked/failed), don't leave the page invisible */
  html:not(.js) body{opacity:1; transform:none;}

  @media (prefers-reduced-motion: reduce){
    body{transition:none; opacity:1; transform:none;}
  }

  /* ==========================================================================
     CUSTOM CURSOR — a small hand-drawn fish outline, inspired by (not a
     literal copy of) the fish illustration on the brand logo. Thin cream
     linework, no fill, no card surface. Restrained motion: the fish glides
     toward the pointer with a light lerp rather than snapping to it, and
     occasionally makes one small unprompted swimming motion so it reads
     as alive rather than mechanical.
     The tail is a separate SVG group with its own transform-origin,
     independent from the body, so it can wiggle on its own (link hover,
     the periodic idle motion) without fighting the body's transform.
     Desktop/mouse only — cursor.js bails out entirely on touch devices and
     prefers-reduced-motion, leaving the normal system cursor untouched.
     ========================================================================== */
  html.custom-cursor-active, html.custom-cursor-active *{cursor:none !important;}

  .cursor-pos, .cursor-pos *{pointer-events:none !important;}
  .cursor-pos{
    position:fixed; top:0; left:0; z-index:9999;
    opacity:0;
    transition:opacity .3s ease;
    will-change:transform;
  }
  html.custom-cursor-active .cursor-pos{opacity:1;}

  /* soft cream halo, only for menu-card hover — sits behind the fish */
  .fish-halo{
    position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
    width:50px; height:50px; border-radius:50%;
    background:radial-gradient(circle, rgba(245,241,232,.32) 0%, rgba(245,241,232,0) 72%);
    opacity:0;
    transition:opacity .35s ease;
  }
  .cursor-pos.is-card .fish-halo{opacity:1;}

  .fish-body-wrap{
    position:relative;
    width:36px; height:19px; /* +20% — was 30x16 */
    opacity:.9;
    transform-origin:50% 50%;
    transition:transform .25s cubic-bezier(.22,.61,.36,1), opacity .25s ease;
    /* a soft dark shadow, not a glow — this is what keeps ivory-on-ivory from
       disappearing against the site's own light/cream sections, which is
       exactly what happened the last time this cursor was ivory-colored */
    filter:drop-shadow(0 0 1.5px rgba(36,31,25,.55)) drop-shadow(0 1px 2px rgba(36,31,25,.35));
  }
  .cursor-pos.is-card .fish-body-wrap{opacity:1;}

  .fish-svg{width:100%; height:100%; display:block; overflow:visible;}
  .fish-outline{fill:none; stroke:#f3ebdd; stroke-width:3.2; stroke-linecap:round; stroke-linejoin:round;}
  .fish-eye{fill:#f3ebdd; stroke:none;}

  /* tail is a separate group so it can move independently of the body */
  .fish-tail{
    transform-box:fill-box; transform-origin:0% 50%;
    transition:transform .2s ease;
  }

  /* ---------- hover: buttons — enlarge, slight rotation ---------- */
  .cursor-pos.is-button .fish-body-wrap{
    transform:scale(1.15) rotate(6deg);
  }

  /* ---------- hover: links — swims slightly forward, tail wiggles once ---------- */
  .cursor-pos.is-link .fish-body-wrap{transform:translateX(3px);}
  @keyframes tailWiggleOnce{
    0%{transform:rotate(0deg);}
    35%{transform:rotate(14deg);}
    65%{transform:rotate(-8deg);}
    100%{transform:rotate(0deg);}
  }
  .cursor-pos.is-link .fish-tail{animation:tailWiggleOnce .45s ease-out;}

  /* ---------- periodic idle motion — a small tilt + tail flick, then settles ----------
     Triggered from JS roughly every 8-10s while the cursor is active and not
     currently hovering anything (so it never fights a hover-state transform). */
  @keyframes idleTilt{
    0%{transform:rotate(0deg);}
    50%{transform:rotate(-4deg);}
    100%{transform:rotate(0deg);}
  }
  @keyframes idleTailFlick{
    0%{transform:rotate(0deg);}
    40%{transform:rotate(16deg);}
    70%{transform:rotate(-10deg);}
    100%{transform:rotate(0deg);}
  }
  .fish-body-wrap.is-alive{animation:idleTilt .9s ease-in-out;}
  .fish-tail.is-alive{animation:idleTailFlick .9s ease-in-out;}

  /* ---------- celebrate: a brief happier burst, triggered by specific
     user actions worth marking (e.g. adding a second week) rather than
     on a timer. Springier than the idle swim — an overshoot easing gives
     it a little joyful "hop" rather than a gentle drift. ---------- */
  @keyframes celebrateBounce{
    0%{transform:scale(1) rotate(0deg);}
    25%{transform:scale(1.22) rotate(-8deg);}
    50%{transform:scale(1.05) rotate(6deg);}
    75%{transform:scale(1.15) rotate(-4deg);}
    100%{transform:scale(1) rotate(0deg);}
  }
  @keyframes celebrateTail{
    0%{transform:rotate(0deg);}
    20%{transform:rotate(22deg);}
    40%{transform:rotate(-16deg);}
    60%{transform:rotate(18deg);}
    80%{transform:rotate(-10deg);}
    100%{transform:rotate(0deg);}
  }
  .fish-body-wrap.is-celebrating{animation:celebrateBounce .75s cubic-bezier(.34,1.56,.64,1);}
  .fish-tail.is-celebrating{animation:celebrateTail .75s ease-in-out;}

  @media (hover:none), (pointer:coarse){
    .cursor-pos{display:none !important;}
  }
  @media (prefers-reduced-motion: reduce){
    .fish-body-wrap, .fish-tail, .fish-halo{transition:none; animation:none;}
  }

  /* ---------- homepage: brand intro + explore paths ---------- */
  .brand-intro{padding:8rem 0 9rem; text-align:center;}
  .brand-intro-inner{max-width:900px; margin:0 auto;}
  .brand-intro h2{font-size:clamp(2rem,5vw,3.6rem); font-style:italic; font-weight:400; line-height:1.18;}
  .brand-intro p{margin-top:2rem; font-size:1.08rem; opacity:.8; max-width:56ch; margin-left:auto; margin-right:auto;}

  /* .explore-paths and related rules removed — the section was removed from
     the homepage; not used on any other page. */

  /* ==========================================================================
     CASCADE FIX — .weekly-menu and .weekly-menu-frame
     --------------------------------------------------------------------------
     The mobile @media(max-width:1000px) overrides for these two selectors
     (defined much earlier in this file) were being silently overridden on
     EVERY screen size, including mobile, by the unqualified desktop
     .weekly-menu / .weekly-menu-frame rules defined later in the file.
     Equal-specificity CSS rules resolve by source order, and the desktop
     rule came second — so it always won, regardless of viewport width.
     This is what caused the two-column desktop grid to silently stay
     active on mobile, squeezing the category panel (including the "Keep
     Your Table Full" card) into roughly half the screen width instead of
     the full width, with a large empty gap on the left.

     Rather than reorder the existing rules (risking other regressions in
     a file this large), this block re-asserts the correct mobile values
     at the very end of the stylesheet, where they're guaranteed to win. */
  @media (max-width:1000px){
    .weekly-menu{grid-template-columns:1fr !important; gap:2.5rem;}
    .weekly-menu-frame{margin-left:0 !important; aspect-ratio:4/5 !important;}
  }


/* ==========================================================================
   CHECKOUT — error note + disabled/redirecting button state
   Added with the Stripe checkout integration (see script.js / cart.js and
   api/create-checkout-session.js).
   ========================================================================== */
.cart-error {
  margin: .6rem 0 0;
  color: #a23a34;
  font-size: .82rem;
  line-height: 1.45;
  text-align: center;
}
.btn[aria-busy="true"],
.btn:disabled {
  opacity: .6;
  cursor: default;
  pointer-events: none;
}

/* ==========================================================================
   DELIVERY MODAL + WEEKLY AVAILABILITY  (delivery launch)
   ========================================================================== */
.delivery-modal{position:fixed; inset:0; z-index:2000; display:none; align-items:flex-start; justify-content:center;}
.delivery-modal.open{display:flex;}
.delivery-overlay{position:absolute; inset:0; background:rgba(36,31,25,.55);}
.delivery-panel{
  position:relative; z-index:1; margin:5vh 1rem 2rem; width:100%; max-width:480px;
  background:var(--ivory); color:var(--espresso); border-radius:var(--radius);
  padding:2.2rem 2rem 2rem; box-shadow:0 30px 70px rgba(36,31,25,.4);
  max-height:90vh; overflow:auto; animation:dmIn .4s var(--ease) both;
}
@keyframes dmIn{from{opacity:0; transform:translateY(16px);} to{opacity:1; transform:translateY(0);}}
.delivery-close{position:absolute; top:.7rem; right:1rem; background:none; border:none; font-size:1.8rem; line-height:1; color:var(--stone); cursor:pointer;}
.delivery-panel h3{font-size:1.55rem; margin:.35rem 0 .5rem;}
.delivery-sub{font-size:.95rem; opacity:.85; margin-bottom:1.3rem;}
.delivery-form label, .waitlist-form label{
  display:block; font-size:.72rem; letter-spacing:.05em; text-transform:uppercase;
  color:var(--olive-deep); margin-bottom:.85rem;
}
.delivery-form .opt{text-transform:none; letter-spacing:0; color:var(--stone); font-size:.7rem;}
.delivery-form input, .delivery-form select, .delivery-form textarea, .waitlist-form input{
  display:block; width:100%; margin-top:.35rem; font-family:var(--sans); font-size:1rem;
  color:var(--espresso); padding:.7rem .85rem; border:1px solid rgba(59,44,31,.25);
  border-radius:10px; background:#fff;
}
.delivery-form textarea{resize:vertical;}
.delivery-form input:focus, .delivery-form select:focus, .delivery-form textarea:focus, .waitlist-form input:focus{
  outline:none; border-color:var(--olive); box-shadow:0 0 0 3px rgba(102,107,73,.12);
}
.delivery-form input[readonly]{background:var(--linen); color:var(--stone); cursor:default;}
.delivery-row{display:grid; grid-template-columns:1fr 130px; gap:.8rem;}
.delivery-submit{width:100%; margin-top:.5rem;}
.delivery-error{color:#a23a34; font-size:.85rem; min-height:1em; margin:.1rem 0 .5rem;}
.delivery-link{display:block; width:100%; margin-top:.85rem; background:none; border:none;
  color:var(--olive-deep); text-decoration:underline; font-size:.85rem; cursor:pointer;}

.avail-banner{
  display:block; max-width:640px; margin:1.5rem auto 0; text-align:center;
  background:var(--olive); color:var(--ivory); font-size:.9rem; letter-spacing:.02em;
  padding:.7rem 1.3rem; border-radius:999px;
}
.avail-banner.soldout{background:var(--espresso); font-size:1rem; font-weight:500;}
.is-soldout{opacity:.45; cursor:not-allowed !important;}

/* Between-menus notice — shown Thursday midnight → Friday 9am ET, while the
   weekly menu is closed. Deliberately quieter and more spacious than the
   sold-out pill: this isn't bad news, it's the rhythm of the week. */
.menu-closed{
  max-width:640px; margin:2.2rem auto 0; text-align:center;
  background:var(--ivory); color:var(--espresso);
  border:1px solid rgba(102,107,73,.28); border-radius:4px;
  padding:2.4rem 1.8rem 2.1rem;
}
.menu-closed-eyebrow{
  display:block; font-size:.7rem; letter-spacing:.22em; text-transform:uppercase;
  color:var(--brass); margin-bottom:1.1rem;
}
.menu-closed-line{
  font-family:var(--serif); font-size:1.35rem; line-height:1.5;
  margin:0 0 .2rem; color:var(--olive-deep);
}
.menu-closed-note{
  margin:1.3rem 0 0; font-size:.85rem; line-height:1.6;
  color:rgba(59,44,31,.62);
}
@media (max-width:520px){
  .menu-closed{padding:1.9rem 1.2rem 1.7rem; margin-top:1.8rem;}
  .menu-closed-line{font-size:1.12rem;}
}

@media (max-width:420px){
  .delivery-panel{padding:1.9rem 1.3rem 1.5rem;}
  .delivery-row{grid-template-columns:1fr;}
}

/* ==========================================================================
   FAQ PAGE — numbered question on the left, answer on the right, hairline
   dividers. Site's Fraunces / olive palette so it reads as one aesthetic.
   ========================================================================== */
.faq-section{padding:9rem 0 7rem;}
.faq-head{text-align:center; max-width:640px; margin:0 auto 4.5rem;}
.faq-head .eyebrow{display:block; margin-bottom:.8rem;}
.faq-head h2{font-family:var(--serif); font-weight:400; font-size:clamp(2.4rem,5.5vw,4rem); color:var(--olive-deep); line-height:1.02;}
.faq-intro{margin-top:1.1rem; font-family:var(--serif); font-style:italic; font-size:1.12rem; color:var(--olive-deep); opacity:.68;}
/* ---------- FAQ — vintage filing cabinet ----------
   The cabinet photograph (faq-cabinet.jpg) is the real hero artwork and is
   never recreated in CSS. Each folder tab (.faq-tab, injected by
   faq-cabinet.js) is a duplicate crop-layer of that exact same photo,
   pixel-aligned over its own band of the base image — at rest the two are
   visually identical, so only a subtle brighten/lift on hover is visible,
   using the real photographed paper and shadow. Band pixels + layout math
   live in faq-cabinet.js since they depend on the artwork itself, not
   something CSS alone can express responsively.

   The answer itself is a single document (.faq-paper) that lives INSIDE
   the stage, not a panel below it. faq-cabinet.js re-anchors its `bottom`
   to whichever folder was clicked (reading that folder's real on-screen
   position, so it's correct at any viewport width without duplicating the
   band math), then a clip-path reveal — not a fade, not a translate-in from
   off-canvas — plays it emerging upward out of that exact folder, as if
   someone were sliding the sheet up out of the slot. The open folder's own
   z-index (30) stays just above the paper's (25) so the folder visibly
   covers the paper's bottom edge; every other folder sits below the paper
   (max 20 while hovered) so the paper passes in front of them as it rises. */
.faq-cabinet-wrap{max-width:960px; margin:0 auto; display:block;}

.faq-cabinet-stage{position:relative; width:100%; aspect-ratio:1536/1024; border-radius:10px; overflow:visible; margin-bottom:2.4rem;}
/* The frame clips the (possibly larger-than-stage, on mobile) base photo to
   the stage's exact rectangle, while the stage itself stays overflow:visible
   so the pulled document can rise above the drawer's own top edge. */
.faq-cabinet-base-frame{
  position:absolute; inset:0; overflow:hidden; border-radius:10px;
  box-shadow:0 30px 60px -30px rgba(36,31,25,.45);
}
.faq-cabinet-base{
  position:absolute; display:block;
  user-select:none; -webkit-user-drag:none; pointer-events:none;
  /* width/height/left/top are set by faq-cabinet.js layout() */
}

/* Each folder is a button spanning the full stage width, sized/positioned
   in JS to its own band of the photo, with a small fixed gap kept between
   neighbors (see GAP in faq-cabinet.js) so hover motion never bleeds into
   the row above or below — every folder stays independently readable and
   clickable, at rest or mid-animation, at any viewport width. The folder
   itself always stays seated in the drawer — only the paper moves. */
.faq-tab{all:unset; box-sizing:border-box; position:absolute; left:0; width:100%; cursor:pointer;}
.faq-tab:nth-child(1){z-index:10;} .faq-tab:nth-child(2){z-index:9;} .faq-tab:nth-child(3){z-index:8;}
.faq-tab:nth-child(4){z-index:7;} .faq-tab:nth-child(5){z-index:6;} .faq-tab:nth-child(6){z-index:5;}
.faq-tab:nth-child(7){z-index:4;}
.faq-tab:hover, .faq-tab:focus-visible{z-index:20;}
.faq-tab[aria-expanded="true"]{z-index:30;}
.faq-tab:focus-visible{outline:2px solid var(--brass); outline-offset:2px; border-radius:2px;}

/* the photo crop — clipped strictly to this folder's own band, never the
   neighbor's, via overflow:hidden on the wrap below */
.faq-tab-crop-wrap{position:absolute; inset:0; overflow:hidden; border-radius:2px;}
.faq-tab-crop{
  position:absolute; left:0; top:0; display:block; background-repeat:no-repeat;
  will-change:transform; transition:transform .3s var(--ease), filter .3s var(--ease);
}
/* Hover: brighten + a 2px lift, nothing more. */
.faq-tab:hover .faq-tab-crop, .faq-tab:focus-visible .faq-tab-crop{
  transform:translateY(-2px);
  filter:brightness(1.06);
}
/* The open folder stays put — just a faint recess, since its document is
   now the thing catching the light, not the tab itself. */
.faq-tab[aria-expanded="true"] .faq-tab-crop{
  filter:brightness(.95);
}

.faq-cabinet-hint{
  margin-top:1.2rem; text-align:center;
  font-family:"Special Elite","Courier New",monospace;
  font-size:.7rem; letter-spacing:.1em; text-transform:uppercase;
  color:var(--stone); opacity:.7;
}

/* ---- the document ----
   Two elements, doing two different jobs:
     .faq-paper       — an invisible clip WINDOW. Bottom-anchored at the
                         clicked folder's own top edge (faq-cabinet.js) and
                         sized in JS to exactly the answer's own height, up
                         to a cap (with scroll as the overflow fallback).
                         It never animates — no clip-path, no size change
                         mid-transition. It just defines the opening the
                         sheet climbs through.
     .faq-paper-sheet  — the physical page itself, including all the paper
                         styling below. It starts translated straight down
                         by the window's own height (fully hidden beneath
                         it) and animates to translateY(0) — one property,
                         `transform`, which the browser can run entirely on
                         the compositor. That's deliberate: a clip-path
                         reveal has to repaint the sheet's own background
                         (including the noise texture below) on every
                         frame, which is exactly what was making the old
                         version stutter partway through. A translateY has
                         nothing to repaint — it's just moved — so the
                         slide stays smooth for its whole ~0.6s, and reads
                         as a real object rising out of the folder rather
                         than a window unmasking. */
.faq-paper{
  position:absolute; left:9%; right:9%; bottom:0; z-index:25;
  overflow-y:auto; overflow-x:hidden;
  pointer-events:none;
  opacity:0;
  transition:opacity .15s ease;
}
.faq-paper.is-visible{ pointer-events:auto; opacity:1; }
.faq-paper-sheet{
  position:relative; min-height:100%;
  border-radius:2px 2px 7px 7px;
  background:
    radial-gradient(120% 90% at 20% -10%, rgba(255,253,246,.55), transparent 55%),
    linear-gradient(180deg,#f7f0dd,#efe5c9 55%,#ece0c0);
  box-shadow:
    0 26px 46px -20px rgba(28,22,13,.4),
    0 6px 14px -6px rgba(28,22,13,.22);
  transition:transform .6s var(--ease);
  will-change:transform;
}
/* Warm paper grain — a tiled fractal-noise texture, tinted sepia and kept
   very faint, so the sheet reads as physical rather than a flat UI card. */
.faq-paper-sheet::before{
  content:""; position:absolute; inset:0; pointer-events:none; z-index:0;
  opacity:.4; mix-blend-mode:multiply; border-radius:inherit;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='matrix' values='0 0 0 0 0.55  0 0 0 0 0.47  0 0 0 0 0.34  0 0 0 0.3 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-size:140px 140px;
}
/* A couple of very faint age-spots — imperfection, not decoration. */
.faq-paper-sheet::after{
  content:""; position:absolute; inset:0; pointer-events:none; z-index:0; border-radius:inherit;
  background:
    radial-gradient(70px 46px at 86% 90%, rgba(112,88,50,.05), transparent 72%),
    radial-gradient(56px 76px at 6% 14%, rgba(112,88,50,.04), transparent 72%);
}
.faq-paper-inner{
  position:relative; z-index:1;
  max-width:620px; margin:0 auto;
  padding:2.6rem clamp(1.5rem,4vw,3rem) 2.8rem;
}
.faq-paper-num{
  display:block; font-family:"Special Elite","Courier New",monospace;
  font-size:.72rem; letter-spacing:.16em; text-transform:uppercase;
  color:var(--brass); opacity:.9; margin-bottom:1.1rem;
}
.faq-paper-a{font-family:var(--serif); font-size:1.05rem; line-height:1.85; color:#4b4128;}
.faq-paper-a p{margin:0 0 1rem;}
.faq-paper-a p:last-child{margin-bottom:0;}
.faq-paper-a a{color:inherit; text-decoration:underline; text-decoration-color:rgba(75,65,40,.4);}
.faq-paper-a strong{font-weight:600;}
.faq-paper-a ul{list-style:none; margin:.1rem 0 1.1rem; padding:0;}
.faq-paper-a li{position:relative; padding-left:1.3rem; margin:.4rem 0; line-height:1.55;}
.faq-paper-a li::before{content:""; position:absolute; left:.15rem; top:.62em; width:5px; height:5px; border-radius:50%; background:var(--brass); opacity:.7;}

@media (max-width:760px){
  .faq-section{padding:7rem 0 4rem;}
}
@media (prefers-reduced-motion:reduce){
  .faq-tab-crop, .faq-paper, .faq-paper-sheet{transition:none;}
}

/* ---------- FAQ mobile — same cabinet, same interaction ----------
   This is the exact same photo-band cabinet and the exact same in-folder
   paper-pull as desktop — nothing is swapped out for an accordion. On
   phones the section's own side padding shrinks so the cabinet runs close
   to full viewport width, and faq-cabinet.js additionally zooms into a
   safe, text-free-margin crop of the photo (verified against the actual
   pixels so no question text is ever cut off) so every folder, its
   typewritten question, and its touch target are meaningfully bigger —
   without changing what the experience *is*. The paper's own margins and
   type scale down to match, but it still emerges from the tapped folder
   exactly the same way. */
@media (max-width:640px){
  .faq-section .wrap{padding-left:2.5vw; padding-right:2.5vw;}

  .faq-head{margin-bottom:2.6rem;}

  .faq-cabinet-hint{font-size:.75rem; margin-top:1.4rem;}

  .faq-paper{left:3%; right:3%;}
  .faq-paper-inner{padding:2.1rem 1.35rem 2.3rem;}
  .faq-paper-num{font-size:.78rem;}
  .faq-paper-a{font-size:1.08rem; line-height:1.85;}

  /* A touch more depth on the smaller screen, so a tapped folder still
     reads as physically distinct even at thumb distance. */
  .faq-tab:hover .faq-tab-crop, .faq-tab:focus-visible .faq-tab-crop{
    filter:brightness(1.08);
  }
  .faq-paper-sheet{
    box-shadow:
      0 20px 38px -16px rgba(28,22,13,.42),
      0 6px 12px -6px rgba(28,22,13,.24);
  }
}

/* ==========================================================================
   MOBILE HOMEPAGE HERO — crop focus
   --------------------------------------------------------------------------
   The hero photo (hero-nosign.jpg) is landscape. On a tall phone hero we frame
   so the branded meal is centred and the BMW badge sits fully visible in the
   lower-left — above the CTA rather than hidden behind it. The "Join the club"
   button is moved to the right side of the card so it never sits over the
   badge, which stays uncovered on the left.
   ========================================================================== */
@media (max-width:900px){
  #hero-img{inset:-8%; width:116%; height:116%; object-position:33% 62%;}
  .hero-card{bottom:7vh;}
  .hero-ctas{justify-content:flex-end;}
  /* Isabel marked up a phone screenshot: raise just the "Slow days, shared."
     script image higher on the photo, closer to the meal container. Using a
     relative offset (not margin) so the subtext and button below it stay
     exactly where they were — nothing else about the layout shifts. */
  .hero-card .hero-script-img{position:relative; top:-11.5vh;}
}
