/* =========================================================
   store.css
   Wildridge STORE - additions only.

   colors.css, main.css, header.css and footer.css are LIFTED VERBATIM
   from the live site and must stay that way: the store has to look like
   the site it replaces, and a fork that drifts is a fork that has to be
   reconciled later. Everything the store needs on top lives here.

   Loaded LAST, so it can override without touching the four.
   ========================================================= */


/* ---------------------------------------------------------
   NAV CART
   The one control the live header does not have, and the whole
   reason /store carries its own header copy (S20).
   --------------------------------------------------------- */
.nav-cart{position:relative;display:inline-flex;align-items:center;gap:7px}

.cart-count{display:inline-grid;place-items:center;min-width:19px;height:19px;padding:0 5px;
  border-radius:var(--radius-pill);background:var(--stone);color:var(--bone);
  font-family:var(--body);font-size:.68rem;font-weight:600;line-height:1;
  transition:background var(--transition-fast),transform var(--transition-fast)}
.cart-count.is-on{background:var(--pine)}

/* Pulse when an item lands. Class is added and removed in js/store.js -
   the CSP forbids inline handlers, so nothing here is triggered from markup. */
.cart-count.is-bumped{transform:scale(1.25)}


/* ---------------------------------------------------------
   PRICE + BUY CONTROLS
   --------------------------------------------------------- */
.price{font-family:var(--display);font-size:1.6rem;color:var(--ink);line-height:1}
.price-unit{font-family:var(--mono);font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--stone);margin-left:8px}
.price-was{font-size:1rem;color:var(--stone);text-decoration:line-through;margin-left:10px}

.buy-row{display:flex;flex-wrap:wrap;align-items:center;gap:14px;margin-top:22px}

.qty{display:inline-flex;align-items:center;border:1px solid var(--border-primary);
  border-radius:var(--radius-pill);overflow:hidden;background:var(--bone)}
.qty button{width:38px;height:42px;border:0;background:none;cursor:pointer;color:var(--bark);
  font-size:1.1rem;line-height:1;transition:background var(--transition-fast)}
.qty button:hover:not(:disabled){background:var(--bg-secondary)}
.qty button:disabled{opacity:.35;cursor:not-allowed}
.qty input{width:46px;height:42px;border:0;background:none;text-align:center;
  font-family:var(--body);font-size:.95rem;color:var(--ink);
  -moz-appearance:textfield;appearance:textfield}
.qty input::-webkit-outer-spin-button,
.qty input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}


/* ---------------------------------------------------------
   STOCK STATE
   Honest, specific copy. "Out of stock" is not an error and is not
   styled like one.
   --------------------------------------------------------- */
.stock{font-family:var(--mono);font-size:.7rem;letter-spacing:.1em;text-transform:uppercase}
.stock--in{color:var(--pine)}
.stock--low{color:var(--wheat)}
.stock--out{color:var(--stone)}
.stock--soon{color:var(--stone)}


/* ---------------------------------------------------------
   SUBSCRIPTION CHOICE
   THE LEGAL SHAPE DRIVES THIS UI, not the other way round.
   ROSCA plus ~25 state auto-renewal statutes; shipping nationwide
   means building to the strictest:
     - conspicuous renewal terms at signup
     - affirmative consent, NEVER a pre-checked box
     - post-enrollment acknowledgment in retainable form
     - online cancellation mirroring online signup

   .sub-terms is the sharp end. First charge and renewal charge are
   different amounts whenever a campaign code is used, which is exactly
   what enforcement targets - so "$X today, then $Y every N weeks" sits
   NEXT TO THE BUTTON, not in a linked policy. Do not move it, do not
   shrink it below body size, and do not let it collapse behind a
   disclosure toggle.
   --------------------------------------------------------- */
.sub-choice{display:grid;gap:10px;margin-top:20px}
.sub-opt{display:flex;align-items:flex-start;gap:11px;padding:14px 16px;cursor:pointer;
  border:1px solid var(--border-primary);border-radius:var(--radius-md);background:var(--bone);
  transition:border-color var(--transition-fast),background var(--transition-fast)}
.sub-opt:hover{border-color:var(--pine)}
.sub-opt input{margin-top:3px;accent-color:var(--pine);flex:none}
.sub-opt.is-on{border-color:var(--pine);background:color-mix(in srgb,var(--pine) 6%,var(--bone))}
.sub-opt-body{display:grid;gap:3px}
.sub-opt-title{font-weight:600;color:var(--ink)}
.sub-opt-note{font-size:.86rem;color:var(--stone)}
.sub-save{font-family:var(--mono);font-size:.64rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--pine)}

.sub-terms{margin-top:14px;padding:13px 15px;border-radius:var(--radius-md);
  background:var(--bg-secondary);border:1px solid var(--border-secondary);
  font-size:.95rem;line-height:1.55;color:var(--ink)}
.sub-terms b{font-weight:600}
.sub-terms a{color:var(--pine);text-decoration:underline}


/* ---------------------------------------------------------
   CART + CHECKOUT
   --------------------------------------------------------- */
.cart-layout{display:grid;grid-template-columns:1.6fr .9fr;gap:clamp(24px,4vw,52px);align-items:start}

.cart-line{display:grid;grid-template-columns:96px 1fr auto;gap:18px;align-items:center;
  padding:20px 0;border-bottom:1px solid var(--border-secondary)}
.cart-line-art{background:var(--bone);border-radius:var(--radius-sm);padding:8px;display:grid;
  place-items:center}
.cart-line-art img{width:100%;height:auto;display:block}
.cart-line h3{font-size:1.08rem;margin:0 0 4px}
.cart-line-meta{font-family:var(--mono);font-size:.66rem;letter-spacing:.09em;text-transform:uppercase;
  color:var(--stone)}
.cart-remove{background:none;border:0;padding:0;cursor:pointer;color:var(--stone);
  font-family:var(--mono);font-size:.64rem;letter-spacing:.1em;text-transform:uppercase;
  transition:color var(--transition-fast)}
.cart-remove:hover{color:var(--beef)}

.summary{position:sticky;top:120px;padding:24px;border-radius:var(--radius-lg);
  background:var(--bg-secondary);border:1px solid var(--border-secondary)}
.summary h3{font-size:1.15rem;margin:0 0 16px}
.summary-row{display:flex;justify-content:space-between;gap:14px;padding:7px 0;font-size:.95rem}
.summary-row span:last-child{font-variant-numeric:tabular-nums}
.summary-row--discount{color:var(--pine)}
.summary-total{display:flex;justify-content:space-between;gap:14px;margin-top:12px;padding-top:14px;
  border-top:1px solid var(--border-primary);font-family:var(--display);font-size:1.3rem;color:var(--ink)}
.summary-note{margin-top:10px;font-size:.8rem;color:var(--stone);line-height:1.5}


/* ---------------------------------------------------------
   COUPON FIELD
   The helper line is REQUIRED, not decorative. Terms sec.9 says
   promotional offers cannot be combined unless otherwise stated -
   and free shipping plus a campaign code IS a deliberate combination,
   so the checkout has to say so (S20).
   --------------------------------------------------------- */
.coupon{margin-top:18px;padding-top:18px;border-top:1px solid var(--border-secondary)}
.coupon-row{display:flex;gap:8px}
.coupon-row input{flex:1;min-width:0;padding:10px 13px;border:1px solid var(--border-primary);
  border-radius:var(--radius-sm);background:var(--bone);font-family:var(--body);font-size:.92rem;
  text-transform:uppercase;letter-spacing:.05em}
.coupon-help{margin-top:8px;font-size:.8rem;color:var(--stone);line-height:1.5}
.coupon-applied{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-top:10px;
  padding:9px 13px;border-radius:var(--radius-sm);
  background:color-mix(in srgb,var(--pine) 9%,transparent);font-size:.88rem;color:var(--pine-deep)}


/* ---------------------------------------------------------
   FORMS
   --------------------------------------------------------- */
.field{display:grid;gap:6px;margin-bottom:16px}
.field label{font-family:var(--mono);font-size:.66rem;letter-spacing:.11em;text-transform:uppercase;
  color:var(--bark)}
.field input,.field select,.field textarea{padding:11px 13px;border:1px solid var(--border-primary);
  border-radius:var(--radius-sm);background:var(--bone);font-family:var(--body);font-size:.96rem;
  color:var(--ink);transition:border-color var(--transition-fast)}
.field input:focus,.field select:focus,.field textarea:focus{outline:none;border-color:var(--pine)}
.field-row{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.field-error{font-size:.82rem;color:var(--beef)}
.field.has-error input,.field.has-error select{border-color:var(--beef)}

/* Marketing opt-in. UNCHECKED BY DEFAULT and it stays that way: a
   pre-checked box is not affirmative consent, and the Privacy Policy
   promises consent-gated promotional mail. */
.optin{display:flex;align-items:flex-start;gap:10px;margin:18px 0;font-size:.92rem;color:var(--bark)}
.optin input{margin-top:3px;accent-color:var(--pine);flex:none}


/* ---------------------------------------------------------
   PAYMENT
   The NMI Payment Component mounts an <nmi-pay-widget> custom element
   with a SHADOW ROOT, backed by three iframes from secure.nmi.com.
   We cannot style inside the shadow root, so this styles the box
   around it and reserves height to stop the page jumping as the
   iframes settle.
   --------------------------------------------------------- */
.pay-mount{min-height:132px;padding:16px;border:1px solid var(--border-primary);
  border-radius:var(--radius-md);background:var(--bone)}
.pay-loading{font-family:var(--mono);font-size:.68rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--stone)}

/* Gateway messages. .pay-dup is its own state on purpose: the duplicate
   filter CANNOT be disabled on this processor and is not evaded by a
   distinct orderid (S20). Most real hits are double-clicks, so
   response_code=300 must read as "this probably already worked",
   never as a decline. */
.pay-msg{margin-top:14px;padding:12px 15px;border-radius:var(--radius-md);font-size:.92rem;
  line-height:1.55}
.pay-msg--error{background:color-mix(in srgb,var(--beef) 9%,transparent);color:var(--beef)}
.pay-msg--dup{background:color-mix(in srgb,var(--wheat) 16%,transparent);color:var(--bark)}


/* ---------------------------------------------------------
   POLICY PAGES
   Long-form legal copy. Measure is capped for readability; these get
   read by underwriters as well as customers.
   --------------------------------------------------------- */
.policy{max-width:72ch;margin:0 auto;padding:clamp(28px,5vw,56px) 0}
.policy h1{font-size:clamp(2.1rem,4.5vw,3rem);margin-bottom:8px}
.policy .updated{font-family:var(--mono);font-size:.68rem;letter-spacing:.11em;text-transform:uppercase;
  color:var(--stone);margin-bottom:34px;display:block}
.policy h2{font-size:1.28rem;margin:36px 0 12px;color:var(--pine-deep)}
.policy p,.policy li{line-height:1.72;color:var(--bark)}
.policy p{margin:0 0 15px}
.policy ul{margin:0 0 15px;padding-left:22px}
.policy li{margin-bottom:7px}
.policy a{color:var(--pine);text-decoration:underline}
.policy address{font-style:normal;line-height:1.72;color:var(--bark)}


/* ---------------------------------------------------------
   THE STORE FOOTER ADDITIONS MOVED OUT (S30)
   ---------------------------------------------------------
   .foot-grid--store, .foot-address, .foot-cards, .card-mark,
   .foot-secure and the two signature-link hovers now live in
   includes/footer.css, which the live site and the store both load and
   which is byte-identical in the two trees. They were store-only while
   the store had its own wider footer; the two footers are one footer
   now. Their responsive columns went with them.

   DO NOT PUT THEM BACK HERE. Two copies of a grid definition is the
   --card-art knob all over again (S27): two numbers somebody has to
   remember to keep equal, and the day they diverge the footer changes
   shape halfway through the site.
   --------------------------------------------------------- */

/* ---------------------------------------------------------
   RESPONSIVE
   --------------------------------------------------------- */
@media(max-width:900px){
  .cart-layout{grid-template-columns:1fr}
  .summary{position:static}
}
@media(max-width:620px){
  .cart-line{grid-template-columns:70px 1fr;row-gap:10px}
  .cart-line-price{grid-column:2}
  .field-row{grid-template-columns:1fr}
}


/* =========================================================
   PRODUCT PAGE - the consolidated, store-shaped layout
   ---------------------------------------------------------
   The live recipe page is seven full-width bands. This is two
   columns above the fold and an accordion below. Same content,
   a third of the scroll.
   ========================================================= */

.product-top{padding-top:clamp(90px,11vw,132px);
  background:
    radial-gradient(120% 92% at 84% 8%, color-mix(in srgb,var(--c) 15%, var(--bone)) 0%, transparent 58%),
    var(--bg-secondary)}

.product-grid{display:grid;grid-template-columns:.85fr 1.15fr;gap:clamp(28px,5vw,64px);
  align-items:center}

.product-art{display:grid;place-items:center}
.product-art img{width:auto;max-width:100%;max-height:440px;
  filter:drop-shadow(0 26px 34px rgba(43,33,24,.26))}

.product-buy h1{font-size:clamp(2.2rem,4.6vw,3.4rem);font-weight:400;letter-spacing:-.01em;
  margin:14px 0 0}
.product-lead{font-size:1.05rem;line-height:1.62;color:var(--bark);max-width:52ch;margin:14px 0 0}

/* Badges: the live page renders these as five 120px circles across a
   full band. Same five claims, one compact row. They are label facts,
   so the words do not change - only the room they take. */
.badge-row{display:flex;flex-wrap:wrap;gap:7px;margin:20px 0 0;padding:0;list-style:none}
.badge-row li{padding:5px 11px;border:1px solid var(--border-primary);border-radius:var(--radius-pill);
  background:var(--bone);font-family:var(--mono);font-size:.63rem;letter-spacing:.09em;
  text-transform:uppercase;color:var(--bark)}

.price-block{display:flex;align-items:baseline;flex-wrap:wrap;gap:14px;
  margin-top:26px;padding-top:22px;border-top:1px solid var(--border-primary)}

.buy-form{margin-top:6px}
.buy-fine{margin-top:14px;font-family:var(--mono);font-size:.64rem;letter-spacing:.09em;
  text-transform:uppercase;color:var(--stone)}
.buy-fine--out{margin-top:20px;font-family:var(--body);font-size:.95rem;letter-spacing:0;
  text-transform:none;line-height:1.6;color:var(--bark);max-width:46ch}

/* card price on the grid tiles */
.buy-row--card{margin-top:14px;gap:8px}
.buy-row--card .price{font-size:1.3rem}
.can-sub-note{margin:4px 0 10px;font-size:.84rem;color:var(--stone)}
.can .stock{display:block;margin-bottom:12px}


/* The full declaration, label order. Slightly smaller and looser than
   body copy because it is a wall of ingredient names, and it is here to
   be checked rather than read straight through. */
.ingredient-declaration{font-size:.9rem;line-height:1.78;color:var(--bark)}

.ga-table,.feeding-table{width:100%;border-collapse:collapse;margin-bottom:14px}
.ga-table td,.feeding-table td,.feeding-table th{padding:10px 2px;text-align:left;
  border-bottom:1px solid var(--border-secondary);font-size:.94rem;color:var(--bark)}
.ga-table td:last-child,.feeding-table td:last-child{text-align:right;
  font-variant-numeric:tabular-nums;color:var(--ink)}
.feeding-table th{font-family:var(--mono);font-size:.64rem;letter-spacing:.11em;
  text-transform:uppercase;color:var(--stone)}
.feeding-table td:last-child{text-align:left}
.feeding-fine,.feeding-aafco{font-size:.84rem;line-height:1.66;color:var(--stone)}


@media(max-width:860px){
  .product-grid{grid-template-columns:1fr;gap:26px}
  .product-art{order:-1}
  .product-art img{max-height:300px}
}


/* =========================================================
   TABS
   ---------------------------------------------------------
   Recipe / What's inside / Nutrition / Feeding chart.

   Every panel is server-rendered and stays in the DOM. `hidden`
   is applied by js/store.js only, so with JS off all four show
   and the section reads as one document - the static fallback
   these pages need, because they are the 301 targets for
   indexed live URLs.
   ========================================================= */
.tabs{max-width:78ch;margin:0 auto}

.tablist{display:flex;flex-wrap:wrap;gap:2px;border-bottom:1px solid var(--border-primary);
  margin-bottom:28px}
.tab{position:relative;padding:13px 18px;background:none;border:0;cursor:pointer;
  font-family:var(--mono);font-size:.72rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--stone);white-space:nowrap;
  transition:color var(--transition-fast)}
.tab:hover{color:var(--bark)}
.tab::after{content:"";position:absolute;left:12px;right:12px;bottom:-1px;height:2px;
  background:var(--c,var(--pine));opacity:0;transition:opacity var(--transition-fast)}
.tab[aria-selected="true"]{color:var(--ink)}
.tab[aria-selected="true"]::after{opacity:1}

.panel-h{font-family:var(--mono);font-size:.68rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--stone);margin:0 0 14px;font-weight:400}
.tab-panel p{line-height:1.72;color:var(--bark);margin:0 0 14px;max-width:68ch}
.tab-panel p:last-child{margin-bottom:0}
.tab-panel a{color:var(--pine);text-decoration:underline}

/* JS-off: consecutive visible panels need separating, since nothing
   is hidden and they stack. A hidden panel is display:none, so this
   never applies once the tabs are live. */
.tab-panel + .tab-panel{margin-top:30px;padding-top:26px;
  border-top:1px solid var(--border-secondary)}


/* =========================================================
   PURCHASE OPTIONS - two choices and a dropdown
   ---------------------------------------------------------
   Was five stacked radio cards, one per interval. Same
   information, a third of the height: the cadence is a
   detail of subscribing, not a separate product.
   ========================================================= */
.sub-opt{align-items:center}
.sub-opt-price{margin-left:auto;flex:none;font-family:var(--display);font-size:1.12rem;
  color:var(--ink)}

.sub-freq{margin-top:12px;max-width:280px}
.sub-freq select{appearance:none;
  background-image:linear-gradient(45deg,transparent 50%,var(--stone) 50%),
                   linear-gradient(135deg,var(--stone) 50%,transparent 50%);
  background-position:calc(100% - 17px) 52%, calc(100% - 12px) 52%;
  background-size:5px 5px,5px 5px;background-repeat:no-repeat;padding-right:38px}


/* =========================================================
   ALSO LIKE
   ========================================================= */
.also-like{background:var(--bg-secondary)}
/* Five across, picture and name. Same treatment as the shop shelf, and
   two per row at every width down to the smallest phone - one column
   turns a cross-sell into five screens of scrolling. */
.recipe-grid--also{grid-template-columns:repeat(5,1fr);gap:14px}
.recipe-grid--also .can-body{padding:11px 12px 14px;text-align:center;
  display:flex;flex-direction:column;align-items:center}
.recipe-grid--also .can-body h3{font-size:1.02rem;margin:0;line-height:1.28}
@media(max-width:1100px){.recipe-grid--also{grid-template-columns:repeat(3,1fr)}}
@media(max-width:720px){.recipe-grid--also{grid-template-columns:repeat(2,1fr);gap:10px}}


/* A class that sets `display` beats the UA sheet's [hidden]{display:none},
   so a hidden .field renders anyway. Scoped to this tree; it is the one
   line that keeps `hidden` meaning hidden. */
[hidden]{display:none !important}


/* ---------------------------------------------------------
   VERTICAL RHYTHM - tighter than the brochure site
   The live pages breathe because they are read top to bottom.
   A store page is scanned, and air between the buy panel and
   the detail reads as "the page ended". These override the
   shared .section padding for this tree only.
   --------------------------------------------------------- */
.product-top{padding-bottom:clamp(30px,4vw,48px)}
.product-detail{padding-top:clamp(34px,4vw,52px);padding-bottom:clamp(34px,4vw,52px)}
.also-like{padding-top:clamp(40px,5vw,60px);padding-bottom:clamp(44px,5vw,68px)}
.product-buy .buy-fine{margin-bottom:0}

/* Merch sits on the same grid as the cans but there are three of it, not
   four. (.cross-grid sets columns without setting display:grid, so it
   only works where something else already made the parent a grid - the
   store uses .recipe-grid and overrides the count here instead.) */
.recipe-grid.merch-shelf{grid-template-columns:repeat(3,1fr)}
@media(max-width:900px){.recipe-grid.merch-shelf{grid-template-columns:1fr 1fr}}
@media(max-width:620px){.recipe-grid.merch-shelf{grid-template-columns:1fr}}


/* ---------------------------------------------------------
   ALSO-LIKE IMAGE SIZE  <-- THE ONE KNOB
   ---------------------------------------------------------
   Change --also-art and nothing else. It is the max height of
   the can in a "you might also like" tile.

   These cards otherwise inherit .can-art--photo from main.css,
   which sets width:100% and lets the grid column decide the
   size - which is why they came out LARGER than the main
   product image. The main image is capped at 440px
   (.product-art img), so anything below that reads as
   secondary. 200px is roughly 45% of it.

   Raise it toward 280 for more presence, drop toward 150 to
   push them further back.
   --------------------------------------------------------- */
.recipe-grid--also{--also-art:120px}

.recipe-grid--also .can-art--photo{min-height:0;padding:14px 12px 0}
.recipe-grid--also .can-art--photo img{
  width:auto;
  max-width:60%;
  max-height:var(--also-art);
  height:auto}


/* NAV LOGO: sized and positioned ONLY in header.css. Nothing here.
   A second rule for the same element in a later file is why editing
   header.css appeared to do nothing. */

/* =========================================================
   PRODUCT PAGE - SIZE + SPACING CORRECTIONS
   ========================================================= */

/* Was clamp(90px,11vw,132px): sized for a full-bleed brochure
   hero, far too much above a buy panel. */
.product-top{padding-top:clamp(44px,5vw,68px)}

/* Was clamp(2.2rem,4.6vw,3.4rem). A product name is a label,
   not a headline - the price and the buy controls are what the
   eye should land on. */
.product-buy h1{font-size:clamp(1.9rem,3.2vw,2.5rem);margin-top:10px}

/* THE LINE UNDER THE BUTTON WAS BARELY VISIBLE.
   It was --stone at .64rem in uppercase with wide tracking -
   three things working against legibility at once, on a line
   that carries real information (case count, packed weight,
   shipping). Now --bark, larger, and sentence case. */
.buy-fine{margin-top:16px;font-family:var(--body);font-size:.86rem;
  letter-spacing:0;text-transform:none;line-height:1.55;color:var(--bark)}


/* =========================================================
   PRODUCT GALLERY
   ---------------------------------------------------------
   A fixed box, one image in it at a time, centered.
   --gallery-h is the height.

   Not built on .product-art: that sets place-items:center,
   which collapses the box. The gallery owns its own layout.
   ========================================================= */
.gallery{display:grid;gap:16px;align-content:start;--gallery-h:400px}

.gallery-stage{display:grid;height:var(--gallery-h)}
.gallery-frame{margin:0;min-height:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:10px}
.gallery-frame img{min-height:0;max-width:100%;max-height:100%;object-fit:contain;
  filter:drop-shadow(0 26px 34px rgba(43,33,24,.26))}
.gallery-frame figcaption{font-family:var(--mono);font-size:.7rem;letter-spacing:.05em;
  color:var(--stone);text-align:center;max-width:38ch;line-height:1.5}

.gallery-thumbs{display:flex;flex-wrap:wrap;justify-content:center;gap:10px;
  margin:0;padding:0;list-style:none}
.gallery-thumb{width:64px;height:64px;padding:6px;cursor:pointer;display:grid;
  place-items:center;background:var(--bone);border:1px solid var(--border-primary);
  border-radius:var(--radius-sm);transition:border-color var(--transition-fast)}
.gallery-thumb img{max-width:100%;max-height:100%;object-fit:contain}
.gallery-thumb[aria-selected="true"]{border-color:var(--c,var(--pine));
  box-shadow:0 0 0 1px var(--c,var(--pine))}

@media(max-width:860px){
  .gallery{--gallery-h:290px}
  .gallery-thumb{width:54px;height:54px}
}


/* =========================================================
   SHOP RHYTHM  (added after seeing it live)
   =========================================================
   A store page is SCANNED, not read. The live pages open like a
   magazine because someone is being told a story; here they have
   already decided to shop, so the product comes first and the copy
   gets out of the way.

   Measured before and after at 1440x900:

                              before    after
     hero block                 428px    198px
     first can starts at        547px    307px
     gap: cans -> Merch         115px     49px
     Merch heading -> tiles      46px     26px
     whole page               2196px   1439px

   The 116px top AND bottom on .section stacked to 232px of nothing
   between two blocks, which is most of what read as "lost space".
   ========================================================= */

/* Sections: the live 116px top AND bottom stack to 232px of nothing
   between two blocks. Halved for the store tree only. */
.section{padding:clamp(34px,3.4vw,52px) 0}
.section-heading{margin-bottom:26px}

/* THE FIRST BLOCK ON ANY STORE PAGE MUST CLEAR THE FLOATING BRAND.
   The logo is out of the document flow now, so without this the page's
   top-left copy runs underneath it. Measured: at rest the mark ends at
   y=134, so the first section starts below that. This is the cost of
   floating the brand, and it is why the at-rest size matters. */
main > .section:first-child{padding-top:76px}

/* The shop opener becomes a BAND, not a hero. Headline and the
   shipping promise sit side by side on one line instead of stacking
   into 428px of runway before the first can. */
.page-hero{padding-bottom:0}
.page-hero .container{display:flex;flex-wrap:wrap;align-items:baseline;
  justify-content:space-between;gap:10px 40px}
.page-hero .label{flex:0 0 100%;margin-bottom:2px}
.page-hero h1{font-size:clamp(1.7rem,2.6vw,2.3rem);max-width:none;margin:0}
.page-hero .page-lead{margin:0;max-width:46ch;font-size:.95rem;
  text-align:right;flex:1 1 300px}

/* The grid sits straight under the band. */
.menu-grid-section{padding-top:clamp(20px,2.2vw,30px)}

@media(max-width:820px){
  .page-hero .container{display:block}
  .page-hero .page-lead{text-align:left;margin-top:10px;max-width:52ch}
}

/* NOTE: the brand mark's size lives in header.css and ONLY in header.css.
   A .brand-fab rule here loads later and silently beats the responsive
   heights there - which is what sliced the top off the logo at narrow
   widths on first load. Do not put one back. */

/* ---------------------------------------------------------
   PRODUCT CARD ART SIZE  <-- ONE KNOB
   ---------------------------------------------------------
   main.css sizes the can at width:80% of whatever the grid column
   happens to be, so on a wide screen the picture grows and the price
   gets pushed down. Capping the HEIGHT instead makes the card a fixed
   shape: the can is recognizable well below full size, and what a
   shopper is actually looking for - price, auto-ship, stock - comes
   up the page.

   Change --card-art and nothing else. Matches the --also-art pattern
   already in this file.
   --------------------------------------------------------- */
.recipe-grid{--card-art:210px}
.recipe-grid .can-art--photo{padding:14px 12px 0}
.recipe-grid .can-art--photo img{
  width:auto;
  max-width:74%;
  max-height:var(--card-art);
  height:auto}

/* The merch shelf keeps its own 5:6 box from main.css; just cap it too
   so a lid and a can read at the same scale on the same page. */
.recipe-grid.merch-shelf{--card-art:190px}
.recipe-grid.merch-shelf .can-art--photo{aspect-ratio:auto}
.recipe-grid.merch-shelf .can-art--photo img{max-height:var(--card-art);height:auto}

/* ---------------------------------------------------------
   THE SHELVES - cans 2x2 on the left, merch 1x2 on the right
   One screen, and no section heading standing between a customer and
   half the catalogue. The proportions say what the business is: food
   takes two thirds, merch is the sideline beside it.
   --------------------------------------------------------- */
.shop-shelves{display:grid;grid-template-columns:2.3fr 1fr;gap:20px;align-items:stretch}

.shelf{display:grid;gap:14px}
.shelf .can{height:100%}

/* The height cap has to be repeated here: tighten.css hangs it off
   .recipe-grid, and these shelves are not that grid. Without it the
   image sizes to the column and a card runs to 570px. */
.shelf .can-art--photo{padding:14px 12px 0}
.shelf .can-art--photo img{width:auto;max-width:74%;height:auto;
  max-height:var(--card-art)}

/* ONE KNOB FOR BOTH SHELVES, AND IT LIVES ON THE CONTAINER.

   The two shelves stand side by side in the same rows, and since the
   art box holds the knob's height (see CARD ART IS A FIXED BOX, below)
   a shorter knob no longer just draws a smaller picture - it draws a
   shorter box, and every name under it rides up by the difference.

   Measured at 1440px with food on 132 and merch on 112: the can names
   sat at 198 and the merch names at 178, in both rows. Twenty pixels,
   which is 132 minus 112 exactly.

   So the number belongs to .shop-shelves, not to either shelf. Two
   knobs beside each other is two numbers that have to be kept equal by
   somebody remembering to, and this is the second time that has been
   lost. Change this one value and both shelves move together. */
.shop-shelves{--card-art:132px}
.shelf-food{grid-template-columns:repeat(2,1fr);grid-template-rows:1fr 1fr}
.shelf-merch{grid-template-columns:1fr;grid-template-rows:1fr 1fr}

.shelf .can-body{padding:12px 15px 15px;display:flex;flex-direction:column;
  align-items:center;text-align:center}
.shelf .can-body h3{font-size:1.2rem;margin:0;line-height:1.25}
.shelf .can-body p{font-size:.8rem}
.shelf .buy-row{margin-top:auto;padding-top:10px}
.shelf .price{font-size:1.3rem}
.shelf .can-sub-note{margin:2px 0 0;font-size:.78rem}
.shelf-merch .can-body h3{font-size:1.1rem}

@media(max-width:1000px){
  .shop-shelves{grid-template-columns:1fr;gap:16px}
  .shelf-food,.shelf-merch{grid-template-rows:auto}
  .shelf-merch{grid-template-columns:repeat(2,1fr)}
}
/* TWO PER ROW AT EVERY WIDTH. A single column turns six products into
   six screens of scrolling, and a shop that needs scrolling to show what
   it sells is back to the problem this layout was fixing. The art shrinks
   instead. */
@media(max-width:640px){
  .shelf-food,.shelf-merch{grid-template-columns:repeat(2,1fr);gap:10px}
  /* Same one knob on the phone. The shelves stack here so nothing is
     beside anything, but a second number is a second thing to drift. */
  .shop-shelves{--card-art:104px}
  .shelf .can-body{padding:9px 8px 11px}
  .shelf .can-body h3{font-size:.92rem;line-height:1.3}
  .shelf .can-art--photo{padding:10px 8px 0}
  .shop-shelves{gap:10px}
}


/* =========================================================
   MUTED TEXT - a contrast fix, measured not eyeballed
   =========================================================
   --stone (#8A8270) is a fine border and icon color and a poor TEXT
   color. Measured against the two page backgrounds:

       #8A8270 on cream #F4ECD6   3.23:1
       #8A8270 on bone  #FBF7EC   3.56:1

   WCAG AA wants 4.5:1 at these sizes, and the store used it for text in
   roughly forty places: the inactive tabs, every small-caps panel label,
   the feeding notes, the sold-out state, cart meta, coupon help. Set in
   Cormorant at .68rem with .13em tracking, thin letterforms and wide
   spacing make 3.2:1 read worse than the number suggests.

   PATCHING FORTY RULES WOULD BE THE WRONG SHAPE. The token is what is
   wrong, so the token is what changes - same hue, taken down until it
   clears AA on BOTH backgrounds and no further:

       #6F695A on cream           4.63:1
       #6F695A on bone            5.10:1

   Still clearly lighter than --bark (9.68:1) and --ink (13.36:1), so the
   hierarchy is intact; secondary text just stops being decoration.

   SCOPED TO THE STORE. This overrides the token for /store only, because
   store.css loads after colors.css. The live site keeps its own value
   until the two are consolidated at go-live, at which point this belongs
   in colors.css and this block goes away.
   ========================================================= */
:root{
  --stone:#6F695A;
  --text-muted:#6F695A;
}

/* =========================================================
   THE CART  (/store/cart.php)
   ---------------------------------------------------------
   No JavaScript anywhere in here. The quantity control is two
   submit buttons carrying the target number the server already
   knows, so it works with scripting off and there is no
   fallback to maintain. A cart is four numbers and a list; it
   does not need a framework.

   Deliberately NOT reusing .qty - that class is the product
   page's JS stepper, and store.js binds to it.
   ========================================================= */
.cart-section{padding-top:0}

.cart-layout{display:grid;grid-template-columns:minmax(0,1fr) 320px;
  gap:var(--space-lg);align-items:start;margin-top:18px}

/* ---- lines ---- */
.cart-lines{display:grid;gap:0;border-top:1px solid var(--border-primary)}

.cart-line{display:grid;grid-template-columns:96px minmax(0,1fr) auto;
  gap:var(--space-md);align-items:center;padding:18px 0;
  border-bottom:1px solid var(--border-secondary)}

.cart-line-art{display:flex;align-items:center;justify-content:center;
  aspect-ratio:5/7;border-radius:var(--radius-md);overflow:hidden;
  background:color-mix(in srgb,var(--c,var(--pine)) 7%,var(--bone))}
.cart-line-art img{max-width:82%;max-height:88%;object-fit:contain}

.cart-line-body h2{margin:0;font-family:var(--display);font-size:1.06rem;
  font-weight:500;line-height:1.3}
.cart-line-body h2 a{color:var(--ink);text-decoration:none}
.cart-line-body h2 a:hover{color:var(--pine)}

.cart-line-mode{margin:5px 0 0;font-family:var(--mono);font-size:.72rem;
  letter-spacing:.08em;text-transform:uppercase;color:var(--text-muted)}

.cart-line-terms{margin:7px 0 0;font-size:.82rem;line-height:1.5;
  color:var(--bark);max-width:44ch}

.cart-line-side{display:grid;justify-items:end;gap:8px}

.cart-qty{display:inline-flex;align-items:center;gap:2px;
  border:1px solid var(--border-primary);border-radius:var(--radius-pill);
  background:var(--bone);padding:2px}
.cart-qty button{width:28px;height:28px;border:0;border-radius:var(--radius-pill);
  background:transparent;color:var(--bark);font-size:1rem;line-height:1;cursor:pointer;
  transition:background var(--transition-fast)}
.cart-qty button:hover:not(:disabled){background:color-mix(in srgb,var(--pine) 12%,transparent)}
.cart-qty button:disabled{opacity:.3;cursor:default}
.cart-qty-n{min-width:26px;text-align:center;font-size:.94rem;color:var(--ink)}

.cart-line-total{margin:0;font-family:var(--display);font-size:1.02rem;color:var(--ink)}

.cart-remove{border:0;background:none;padding:0;cursor:pointer;
  font-family:var(--mono);font-size:.68rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--text-muted);transition:color var(--transition-fast)}
.cart-remove:hover{color:var(--beef)}

/* ---- the money ---- */
.cart-sum{border:1px solid var(--border-primary);border-radius:var(--radius-lg);
  background:var(--bone);padding:22px}
.cart-sum-row{display:flex;justify-content:space-between;gap:14px;
  padding:7px 0;font-size:.94rem;color:var(--bark)}
.cart-sum-row--save span:last-child{color:var(--pine)}
.cart-sum-row--total{margin-top:8px;padding-top:14px;
  border-top:1px solid var(--border-primary);
  font-family:var(--display);font-size:1.2rem;color:var(--ink)}

.cart-sum-note{margin:12px 0 0;font-size:.8rem;line-height:1.5;color:var(--text-muted)}

.cart-sum-warn{margin:14px 0 0;padding:11px 13px;border-radius:var(--radius-sm);
  background:color-mix(in srgb,var(--wheat) 16%,var(--bone));
  font-size:.84rem;line-height:1.5;color:var(--bark)}

/* ---- mixed cadences: the flag, and the way out of it ----
   Same wheat ground as the other cart notice, so it reads as
   information rather than an error - two schedules are allowed, and
   this is a suggestion, not a refusal. */
.cart-sync{margin:14px 0 0;padding:13px 14px;border-radius:var(--radius-sm);
  background:color-mix(in srgb,var(--wheat) 16%,var(--bone));
  border:1px solid color-mix(in srgb,var(--wheat) 32%,transparent)}
.cart-sync-lead{margin:0;font-size:.84rem;line-height:1.55;color:var(--bark)}
.cart-sync-ask{margin:11px 0 7px;font-family:var(--mono);font-size:.7rem;
  letter-spacing:.09em;text-transform:uppercase;color:var(--text-muted)}
.cart-sync form + form{margin-top:6px}
.cart-sync-btn{display:block;width:100%;padding:8px 12px;cursor:pointer;
  border:1px solid var(--border-primary);border-radius:var(--radius-pill);
  background:var(--bone);color:var(--bark);
  font-family:var(--mono);font-size:.74rem;letter-spacing:.04em;
  transition:background var(--transition-fast),color var(--transition-fast)}
.cart-sync-btn:hover{background:var(--pine);color:var(--bone);border-color:var(--pine)}

/* The cadence on a line, when the lines disagree about it. */
.cart-line-mode--differs{color:var(--bark);
  border-bottom:1px solid color-mix(in srgb,var(--wheat) 60%,transparent);
  display:inline-block;padding-bottom:2px}

.cart-go{display:block;width:100%;margin-top:18px;text-align:center}
.cart-back{display:block;margin-top:12px;text-align:center;
  font-family:var(--mono);font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--text-muted);text-decoration:none}
.cart-back:hover{color:var(--pine)}

/* ---- notices and the empty state ---- */
.cart-alert{margin-bottom:22px;padding:13px 16px;border-radius:var(--radius-md);
  background:color-mix(in srgb,var(--wheat) 16%,var(--bone));
  border:1px solid color-mix(in srgb,var(--wheat) 34%,transparent)}
.cart-alert p{margin:0;font-size:.9rem;line-height:1.55;color:var(--bark)}
.cart-alert p + p{margin-top:5px}

.cart-empty{padding:8px 0 40px;max-width:46ch}
.cart-empty p{margin:0 0 20px;color:var(--bark)}

.cart-clear{margin-top:22px}
.cart-clear button{border:0;background:none;padding:0;cursor:pointer;
  font-family:var(--mono);font-size:.68rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--text-muted)}
.cart-clear button:hover{color:var(--beef)}

/* ---- narrow ---- */
@media (max-width:860px){
  .cart-layout{grid-template-columns:1fr;gap:var(--space-md)}
  .cart-sum{order:2}
}
@media (max-width:520px){
  .cart-line{grid-template-columns:72px minmax(0,1fr);row-gap:12px}
  .cart-line-side{grid-column:1/-1;grid-template-columns:auto 1fr auto;
    align-items:center;justify-items:start}
  .cart-line-total{justify-self:end;text-align:right}
  .cart-remove{justify-self:end}
}

/* The add-to-cart confirmation on the product page. Sits between the
   price and the buy form, where the eye already is after pressing the
   button. */
.cart-added{margin:16px 0 0;padding:10px 13px;border-radius:var(--radius-sm);
  background:color-mix(in srgb,var(--pine) 10%,var(--bone));
  border:1px solid color-mix(in srgb,var(--pine) 26%,transparent);
  font-size:.9rem;line-height:1.5;color:var(--bark)}
.cart-added a{color:var(--pine);font-weight:600}
.cart-added--no{background:color-mix(in srgb,var(--wheat) 16%,var(--bone));
  border-color:color-mix(in srgb,var(--wheat) 34%,transparent)}

/* =========================================================
   CHECKOUT  (/store/checkout.php, /store/thanks.php)
   ---------------------------------------------------------
   Same two-column frame as the cart, and the same summary
   card, because it IS the same summary - it just knows more
   once there is an address. Reusing .cart-sum rather than
   cloning it means one place to change when a row is added.
   ========================================================= */
.checkout-section{padding-top:0}

.checkout-layout{display:grid;grid-template-columns:minmax(0,1fr) 320px;
  gap:var(--space-lg);align-items:start;margin-top:18px}

.checkout-main{max-width:34rem}
.checkout-main h2{margin:26px 0 14px;font-family:var(--display);font-size:1.12rem;
  font-weight:500;color:var(--ink)}
.checkout-main h2:first-child{margin-top:0}

.field-help{margin:-8px 0 18px;font-size:.82rem;line-height:1.5;color:var(--text-muted)}

.checkout-optin{display:flex;gap:10px;align-items:flex-start;margin-top:22px;
  font-size:.88rem;line-height:1.5;color:var(--bark);cursor:pointer}
.checkout-optin input{margin-top:3px;accent-color:var(--pine)}

.checkout-actions{display:flex;align-items:center;gap:18px;flex-wrap:wrap;margin-top:28px}
.checkout-back{border:0;background:none;padding:0;cursor:pointer;text-decoration:none;
  font-family:var(--mono);font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--text-muted);transition:color var(--transition-fast)}
.checkout-back:hover{color:var(--pine)}

/* ---- review ---- */
.review-block{padding:18px 0;border-bottom:1px solid var(--border-secondary)}
.review-block:first-child{padding-top:0}
.review-block:last-of-type{border-bottom:0}
.review-block h2{margin:0 0 10px;font-size:1.02rem}

.review-address,.review-contact{margin:0;line-height:1.65;color:var(--bark)}
.review-contact{margin-top:8px;font-size:.9rem;color:var(--text-muted)}

.review-items{list-style:none;margin:0;padding:0}
.review-items li{display:grid;grid-template-columns:minmax(0,1fr) auto;
  column-gap:14px;padding:8px 0;border-bottom:1px solid var(--border-secondary)}
.review-items li:last-child{border-bottom:0}
.review-item-name{color:var(--ink)}
.review-item-mode{grid-column:1;font-family:var(--mono);font-size:.68rem;letter-spacing:.09em;
  text-transform:uppercase;color:var(--text-muted)}
.review-item-cash{grid-row:1;grid-column:2;text-align:right;color:var(--ink)}

.review-note{margin:12px 0 0;font-size:.84rem;line-height:1.55;color:var(--text-muted)}

/* The consent block is deliberately the loudest thing on the page after
   the button. Auto-renewal terms hidden in a quiet grey line is the
   exact pattern the statutes were written about. */
.review-consent{padding:16px 18px;margin-top:18px;border-radius:var(--radius-md);
  border:1px solid color-mix(in srgb,var(--pine) 26%,transparent);
  background:color-mix(in srgb,var(--pine) 8%,var(--bone))}
.review-consent p{margin:0 0 8px;line-height:1.6;color:var(--bark)}
.review-consent p:last-child{margin-bottom:0}

/* Today, then each schedule. Kept visually distinct because the whole
   point of separating them is that a reader should not run the two
   figures together. */
.consent-today{font-size:1.02rem;color:var(--ink)}
.consent-cycle{padding-left:13px;border-left:2px solid color-mix(in srgb,var(--pine) 34%,transparent)}
.consent-cycle + .consent-cycle{margin-top:10px}
.consent-detail{display:block;margin-top:2px;font-size:.82rem;color:var(--text-muted)}

.checkout-sum{position:sticky;top:120px}
.btn:disabled{opacity:.45;cursor:not-allowed}

@media (max-width:860px){
  .checkout-layout{grid-template-columns:1fr;gap:var(--space-md)}
  .checkout-main{max-width:none}
  .checkout-sum{position:static;order:2}
}

/* =========================================================
   POLICY PAGES
   (privacy-policy, returns-policy, shipping-policy,
    subscription-policy, terms)
   ---------------------------------------------------------
   One column, generous measure, nothing decorative. These
   are read by two audiences: a customer looking for one
   answer, and an underwriter checking that the answer
   exists. Both are served by plain hierarchy and a line
   length that does not fight the eye.
   ========================================================= */
.policy{max-width:44rem;padding-top:6px;
  /* Something upstream centres a max-width block inside .container.
     Measured: the body sat 208px right of its own h1, which reads as
     a mistake rather than a choice. Pin it to the left edge the
     heading uses. */
  margin-inline:0 auto}
.policy .policy-updated{margin:0 0 30px;font-family:var(--mono);font-size:.72rem;
  letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted)}

.policy h2{margin:34px 0 12px;font-family:var(--display);font-size:1.24rem;
  font-weight:500;color:var(--ink)}
.policy h2:first-of-type{margin-top:0}
.policy h3{margin:22px 0 8px;font-family:var(--body);font-size:1rem;
  font-weight:600;color:var(--ink)}

.policy p{margin:0 0 14px;line-height:1.7;color:var(--bark)}
.policy ul{margin:0 0 16px;padding-left:20px}
.policy li{margin-bottom:7px;line-height:1.65;color:var(--bark)}

.policy a{color:var(--pine)}
.policy strong{color:var(--ink)}

/* The contact block that closes every policy. */
.policy-contact{margin-top:34px;padding:20px 22px;border-radius:var(--radius-md);
  border:1px solid var(--border-primary);background:var(--bone)}
.policy-contact h2{margin-top:0}
.policy-contact p{margin-bottom:6px}
.policy-contact p:last-child{margin-bottom:0}

/* Cross-reference to another policy, so the satisfaction
   guarantee is described once and pointed at four times. */
.policy-see{margin:0 0 14px;padding:12px 15px;border-radius:var(--radius-sm);
  background:color-mix(in srgb,var(--pine) 7%,var(--bone));
  border-left:3px solid var(--pine);line-height:1.65}

/* Category shelves (food.php, merch.php). The index pairs two shelves
   of different shapes; a single-category page just flows. Fixed-width
   tracks left-aligned rather than stretched columns, so two merch tiles
   are the same size as four food tiles instead of twice as wide. */
.shelf-cat{grid-template-columns:repeat(auto-fill,minmax(200px,260px));
  justify-content:start;--card-art:132px}
@media(max-width:720px){
  .shelf-cat{grid-template-columns:repeat(2,1fr)}
}

/* =========================================================
   CARD ART IS A FIXED BOX, NOT THE SHAPE OF THE PHOTO
   ---------------------------------------------------------
   Every grid above caps the image height with its own knob
   and lets the art box hug whatever comes back. That works
   only while every product is the same shape as a can.

   Measured on the cross-sell row: a 335x384 hat photo, sized
   to the same width as a 335x500 can, came out 133px tall
   against the can's 206px. The box shrank with it, so the
   hat's name sat 71px above every other name in the row.

   The box now holds the knob's height and the picture is
   contained inside it, centred. Names line up along the
   bottom whatever shape the next product photo turns out to
   be - which is the same problem .merch-shelf solved in S17
   with a 5:7 box, generalised to every grid.

   The knobs still work exactly as before. Nothing to relearn.
   ========================================================= */
.recipe-grid--also .can-art--photo img{
  width:60%;
  height:var(--also-art);
  object-fit:contain;
  max-width:none;
  max-height:none}

.recipe-grid .can-art--photo img,
.shelf .can-art--photo img{
  width:74%;
  height:var(--card-art);
  object-fit:contain;
  max-width:none;
  max-height:none}

/* ---- the payment block (checkout review) ----
   The three card fields are iframes from secure.nmi.com and their
   internals are not ours to style; this frames them and nothing more. */
.pay-block{margin-top:18px}
.pay-fields{min-height:96px;padding:14px;border-radius:var(--radius-sm);
  border:1px solid var(--border-primary);background:var(--bone)}
.pay-status{margin:9px 0 0;font-size:.86rem;line-height:1.5;color:var(--text-muted)}
.pay-status--bad{color:var(--beef)}
.pay-note{margin:9px 0 0;font-size:.8rem;line-height:1.5;color:var(--text-muted)}

/* ---- the magic link (manage.php) ----
   No account, so this page is the whole relationship: what comes, where
   it goes, how often, and how to stop it. Cancelling is given the same
   visual weight as changing - a stop control that is hard to find is a
   stop control that fails the thing the policies promise. */
.manage-layout{display:grid;grid-template-columns:1.7fr .8fr;gap:clamp(24px,4vw,52px);align-items:start}
.manage-block{padding:20px 22px;margin-bottom:18px;border-radius:var(--radius-md);
  border:1px solid var(--border-primary);background:var(--bone)}
.manage-block h2{margin:0 0 12px;font-family:var(--display);font-size:1.1rem;font-weight:500}

.manage-items{list-style:none;margin:0;padding:0}
.manage-items li{display:flex;justify-content:space-between;gap:14px;padding:6px 0;
  font-size:.95rem;color:var(--bark)}
.manage-item-cash{font-variant-numeric:tabular-nums}

.manage-state{margin:14px 0 0;padding-top:13px;border-top:1px solid var(--border-secondary);
  font-size:1rem;line-height:1.6;color:var(--ink)}
.manage-state--off{color:var(--text-muted)}

.manage-address{margin:0;line-height:1.7;color:var(--bark)}
.manage-note{margin:10px 0 0;font-size:.83rem;line-height:1.55;color:var(--text-muted)}
.manage-note a{color:var(--pine)}

.manage-freq{display:flex;flex-wrap:wrap;gap:9px;align-items:center}
.manage-freq select{padding:10px 13px;border:1px solid var(--border-primary);
  border-radius:var(--radius-sm);background:var(--bone);
  font-family:var(--body);font-size:.95rem;color:var(--ink)}

.manage-stop label{display:block;margin:14px 0 5px;font-family:var(--mono);
  font-size:.68rem;letter-spacing:.09em;text-transform:uppercase;color:var(--text-muted)}
.manage-stop input{width:100%;max-width:340px;padding:10px 13px;
  border:1px solid var(--border-primary);border-radius:var(--radius-sm);
  background:var(--bone);font-family:var(--body);font-size:.95rem}
.btn-stop{margin-top:16px;background:transparent;color:var(--beef);
  border:1px solid color-mix(in srgb,var(--beef) 45%,transparent)}
.btn-stop:hover{background:var(--beef);color:var(--bone);border-color:var(--beef)}

.manage-notice,.manage-error{margin-bottom:20px;padding:13px 16px;border-radius:var(--radius-md)}
.manage-notice{background:color-mix(in srgb,var(--pine) 10%,var(--bone));
  border:1px solid color-mix(in srgb,var(--pine) 30%,transparent)}
.manage-error{background:color-mix(in srgb,var(--beef) 9%,var(--bone));
  border:1px solid color-mix(in srgb,var(--beef) 30%,transparent)}
.manage-notice p,.manage-error p{margin:0;font-size:.93rem;line-height:1.55;color:var(--bark)}

.manage-dead{max-width:52ch}
.manage-dead p{margin:0 0 14px;line-height:1.65;color:var(--bark)}
.manage-dead a{color:var(--pine)}

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

@media (max-width:860px){ .manage-layout{grid-template-columns:1fr} }

/* ---- unsubscribe (unsubscribe.php) ----
   A CAN-SPAM page: one field, one button, no account. Deliberately plain. */
.unsub-form,.unsub-done{max-width:48ch}
.unsub-form p,.unsub-done p{margin:0 0 16px;line-height:1.65;color:var(--bark)}
.unsub-form label{display:block;margin:6px 0 6px;font-family:var(--mono);
  font-size:.68rem;letter-spacing:.09em;text-transform:uppercase;color:var(--text-muted)}
.unsub-form input[type=email]{width:100%;max-width:360px;padding:11px 14px;
  border:1px solid var(--border-primary);border-radius:var(--radius-sm);
  background:var(--bone);font-family:var(--body);font-size:1rem;color:var(--ink)}
.unsub-form input[readonly]{color:var(--text-muted);background:var(--bg-secondary)}
.unsub-form button{margin-top:16px}
.unsub-note{margin-top:22px;font-size:.83rem;line-height:1.55;color:var(--text-muted)}
.unsub-done a,.unsub-form a{color:var(--pine)}
.unsub-error{margin-bottom:20px;padding:13px 16px;border-radius:var(--radius-md);
  background:color-mix(in srgb,var(--beef) 9%,var(--bone));
  border:1px solid color-mix(in srgb,var(--beef) 30%,transparent)}
.unsub-error p{margin:0;font-size:.93rem;color:var(--bark)}
