/* ==========================================================================
   WordPress compatibility layer
   --------------------------------------------------------------------------
   brand.css is the design's own stylesheet, copied out of the static build and
   never edited. Everything WordPress, WooCommerce or Contact Form 7 needs in
   order to sit inside that design lives here instead, so the brand sheet can be
   re-exported from the design at any time without losing this work.

   Most core stylesheets are dequeued in inc/assets.php rather than fought with
   here. What remains is markup we do not control (CF7 wrappers, Woo notices,
   the admin bar), mapped onto the brand's own classes.

   Nothing in this file uses !important except where it undoes an !important
   rule shipped by core.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Admin bar
   The admin bar is position:fixed and core pushes <html> down with an
   !important margin. A sticky header at top:0 then slides underneath it, and
   the full-screen overlays start 32px too high. Only logged-in editors ever
   see this, but they see it on every visit.
   -------------------------------------------------------------------------- */
.admin-bar .hdr        { top: 32px }
.admin-bar .co,
.admin-bar .mnav,
.admin-bar .drawer     { top: 32px; height: calc(100% - 32px) }
.admin-bar .co-top     { top: 0 }
.admin-bar             { scroll-padding-top: 128px }

@media screen and (max-width: 782px) {
  .admin-bar .hdr      { top: 46px }
  .admin-bar .co,
  .admin-bar .mnav,
  .admin-bar .drawer   { top: 46px; height: calc(100% - 46px) }
  .admin-bar           { scroll-padding-top: 142px }
}

/* Core hides the bar under 600px but keeps the margin; match that. */
@media screen and (max-width: 600px) {
  .admin-bar .hdr      { top: 0 }
  .admin-bar .co,
  .admin-bar .mnav,
  .admin-bar .drawer   { top: 0; height: 100% }
}

/* --------------------------------------------------------------------------
   2. Core markup the theme inherits
   -------------------------------------------------------------------------- */
.screen-reader-text {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(1px, 1px, 1px, 1px); clip-path: inset(50%);
  white-space: nowrap; word-wrap: normal;
}
.screen-reader-text:focus {
  z-index: 200; top: 8px; left: 8px; width: auto; height: auto;
  clip: auto; clip-path: none; padding: 14px 22px;
  background: var(--white); color: var(--green-deep);
  border-radius: var(--r-s); box-shadow: var(--shadow-m);
  font-size: .8rem; letter-spacing: .1em; text-transform: uppercase;
}

/* WordPress emits these on any image inserted through the editor. */
.alignleft   { float: left;  margin: 0 28px 22px 0 }
.alignright  { float: right; margin: 0 0 22px 28px }
.aligncenter { display: block; margin-left: auto; margin-right: auto }
.wp-caption  { max-width: 100% }
.wp-caption-text,
.wp-element-caption {
  font-size: .82rem; color: var(--muted); text-align: center; margin-top: 10px;
}
.sticky, .gallery-caption, .bypostauthor { }

/* --------------------------------------------------------------------------
   3. Contact Form 7
   CF7's own stylesheet is dequeued. Its markup is wrapped in .form so it
   inherits the design's card, and its fields are given the .field treatment
   here rather than by pasting classes into the form template — a client
   editing the form in the CF7 admin should not have to remember them.
   -------------------------------------------------------------------------- */
/* --- Structural rules inherited from the dequeued plugin sheet -------------
   Contact Form 7's own stylesheet does two jobs: it makes the form look like
   CF7, and it makes the form *work* — hiding scaffolding markup, positioning
   tips, dimming inert controls. Dequeuing it to protect the brand CSS throws
   away both, so everything load-bearing has to be restated here.

   These are not cosmetic. Without them CF7's internal scaffolding renders as
   visible junk inside the card. Do not delete them as "plugin defaults". */

/* CF7 wraps its six hidden _wpcf7* inputs in a <fieldset>. Left alone, the
   browser's default fieldset styling draws a 2px groove border across the top
   of the card — a pair of stray divider lines above the first field. */
.wpcf7 .hidden-fields-container { display: none }

/* The accessibility live region. It is empty on load, but CF7 fills it with the
   status message and a list of links to the invalid fields on every failed
   submission — so without this it stays invisible until the first error and
   then dumps a duplicate error list at the top of the card. */
.wpcf7 .screen-reader-response {
  position: absolute;
  overflow: hidden;
  clip: rect(1px, 1px, 1px, 1px);
  clip-path: inset(50%);
  height: 1px;
  width: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  word-wrap: normal !important;
}

/* The positioning context for validation tips. */
.wpcf7-form-control-wrap { position: relative }

/* Checkbox and radio lists — not in the seeded form, but the shop owner can add
   one in the CF7 admin at any time, and it would stack vertically without this. */
.wpcf7-list-item { display: inline-block; margin: 0 0 0 1em }

/* Feedback for controls CF7 disables (an unticked acceptance box disables the
   submit) and for panes it marks inert. */
.wpcf7 [inert] { opacity: .5 }
.wpcf7 .wpcf7-submit:disabled { cursor: not-allowed }
.wpcf7 input[type="file"] { cursor: pointer }

/* Reflection outputs, used by CF7's [reflection] tag. */
.wpcf7-reflection > output { display: list-item; list-style: none }
.wpcf7-reflection > output[hidden] { display: none }

/* --- Brand styling ------------------------------------------------------- */

.form .wpcf7-form-control-wrap { display: block }

.form input[type="text"],
.form input[type="email"],
.form input[type="tel"],
.form input[type="url"],
.form input[type="date"],
.form input[type="number"],
.form select,
.form textarea {
  width: 100%;
  padding: 15px 18px;
  border: 1px solid var(--line);
  border-radius: var(--r-s);
  background: var(--cream);
  font-size: .95rem;
  transition: border-color .3s var(--ease), background .3s var(--ease), box-shadow .3s var(--ease);
}
.form input:focus,
.form select:focus,
.form textarea:focus {
  outline: none;
  border-color: var(--green);
  background: #fff;
  box-shadow: 0 0 0 4px rgba(40, 98, 11, .07);
}
.form textarea { resize: vertical; min-height: 130px }

/* CF7 marks an invalid field with this class; reuse the brand's .field.bad look.
   The element selectors are load-bearing: `.form input[type="text"]` above
   scores (0,2,1), so a bare `.form .wpcf7-not-valid` at (0,2,0) loses the
   border colour to it and the field never turns red. */
.form input.wpcf7-not-valid,
.form select.wpcf7-not-valid,
.form textarea.wpcf7-not-valid {
  border-color: #c96a4a;
  background: #fdf7f5;
}
.form .wpcf7-not-valid-tip {
  display: block;
  color: #b3421f;
  font-size: .76rem;
  margin-top: 7px;
  letter-spacing: .04em;
}

/* CF7 renders the response banner on every page load and only fills it after a
   submission, so on first paint it is an empty box. Its own stylesheet hides it
   until there is something to say — and since that sheet is dequeued, the
   hiding has to be replicated here, or the empty banner reads as a stray input
   sitting under the Send button.

   Keyed off the three states that never carry a message, exactly as CF7 does,
   with :empty as a backstop for any state added in a later version. */
.form form[data-status="init"] .wpcf7-response-output,
.form form[data-status="resetting"] .wpcf7-response-output,
.form form[data-status="submitting"] .wpcf7-response-output,
.form .wpcf7-response-output:empty {
  display: none;
}

/* The response banner under the submit button. */
.form .wpcf7-response-output {
  margin: 20px 0 0;
  padding: 14px 18px;
  border: 1px solid var(--line);
  border-radius: var(--r-s);
  font-size: .88rem;
  line-height: 1.6;
  background: var(--cream);
  color: var(--ink-soft);
}
.form form.sent .wpcf7-response-output {
  border-color: rgba(40, 98, 11, .35);
  background: rgba(40, 98, 11, .06);
  color: var(--green-deep);
}
.form form.invalid .wpcf7-response-output,
.form form.unaccepted .wpcf7-response-output,
.form form.payment-required .wpcf7-response-output {
  border-color: #d9b6a6;
  background: #fdf7f5;
  color: #b3421f;
}
.form form.failed .wpcf7-response-output,
.form form.aborted .wpcf7-response-output {
  border-color: #d9b6a6;
  background: #fdf7f5;
  color: #b3421f;
}

/* CF7 wraps the submit in a <p>; keep the button full width like the design. */
.form .wpcf7-submit { width: 100% }

/* The submit button is the spinner's positioning context. */
.form .yamna-submit { position: relative }

/* CF7's spinner takes its size, its shape, its animation and — crucially — its
   hidden-by-default state from the plugin stylesheet. With that sheet dequeued
   the element is an inert 0x0 span that is permanently "visible", so the
   customer gets no feedback at all while a message is sending. All of it is
   restated here, sized and coloured for the brand's own submit button rather
   than CF7's grey dot.

   The design is a full-width pill, so the spinner is pinned inside its right
   edge instead of sitting after it, where it would push the layout. */
.form .wpcf7-spinner {
  visibility: hidden;
  position: absolute;
  top: 50%;
  right: 26px;
  margin: 0;
  width: 20px;
  height: 20px;
  transform: translateY(-50%);
  border-radius: 50%;
  background: rgba(255, 255, 255, .25);
}
.form form.submitting .wpcf7-spinner { visibility: visible }

.form .wpcf7-spinner::before {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: #fff;
  transform-origin: 7px 7px;
  animation: yamnaSpin 1s linear infinite;
}

/* brand.css already disables every animation under prefers-reduced-motion with
   an !important rule, which leaves the dot sitting still — visible, but not
   spinning. That is the design's own policy, so it is left to win. */
@keyframes yamnaSpin {
  to { transform: rotate(360deg) }
}

/* CF7 wraps every field in <p>, which the brand card does not expect. */
.form p { margin: 0 }

/* --------------------------------------------------------------------------
   4. WooCommerce
   The storefront is the one-page design: its own cards, drawer and checkout.
   Woo's stylesheets are dequeued on the front page. The pages that remain
   (my account, order received, any product permalink someone shares) still
   load them, and only need the shell below to sit inside the brand.
   -------------------------------------------------------------------------- */
.page-shell { padding: 72px 0 110px; min-height: 52vh }
.page-shell .page-title { margin-bottom: 12px }
.page-shell .lead { margin-bottom: 40px }

.entry-content > * + * { margin-top: 1.15em }
.entry-content h2,
.entry-content h3,
.entry-content h4 { margin-top: 1.6em }
.entry-content ul,
.entry-content ol { padding-left: 1.3em }
.entry-content li + li { margin-top: .4em }
.entry-content a { color: var(--green); text-decoration: underline; text-underline-offset: 3px }
.entry-content a:hover { color: var(--green-deep) }
.entry-content blockquote {
  border-left: 2px solid var(--gold-deep);
  padding-left: 24px;
  font-family: var(--serif);
  font-size: 1.3rem;
  font-style: italic;
  color: var(--muted);
}
.entry-content img { border-radius: var(--r-m) }
.entry-content table { width: 100%; border-collapse: collapse }
.entry-content th,
.entry-content td { padding: 10px 12px; border-bottom: 1px solid var(--line); text-align: left }

/* Woo notices, shown on account and order pages. */
.woocommerce-message,
.woocommerce-info,
.woocommerce-error {
  border-radius: var(--r-m);
  border: 1px solid var(--line);
  background: var(--white);
  padding: 18px 22px;
  list-style: none;
  font-size: .92rem;
  color: var(--ink-soft);
}
.woocommerce-message { border-left: 3px solid var(--green) }
.woocommerce-info    { border-left: 3px solid var(--gold-deep) }
.woocommerce-error   { border-left: 3px solid #c96a4a; color: #b3421f }

/* Woo's own buttons, restyled as the brand's pill. */
.woocommerce .button,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  padding: 15px 26px; border-radius: 100px; border: 0;
  background: var(--green); color: #fff;
  font-family: var(--sans); font-size: .82rem; font-weight: 500;
  letter-spacing: .11em; text-transform: uppercase; line-height: 1;
  transition: all .45s var(--ease);
}
.woocommerce .button:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover {
  background: var(--green-deep); color: #fff;
}

/* --------------------------------------------------------------------------
   5. Blog / archive shell
   Not part of the original design, but WordPress will route here for search
   results, category archives and anything the client publishes later.
   -------------------------------------------------------------------------- */
.post-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 32px }
.post-card {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r-l); overflow: hidden; box-shadow: var(--shadow-s);
  transition: transform .5s var(--ease), box-shadow .5s var(--ease);
}
.post-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-m) }
.post-card img { aspect-ratio: 16/10; object-fit: cover; width: 100% }
.post-card-body { padding: 26px 28px 30px }
.post-card-body time { font-size: .74rem; letter-spacing: .2em; text-transform: uppercase; color: var(--muted) }
.post-card-body h3 { margin: 10px 0 12px; font-size: 1.5rem }
.post-card-body p { font-size: .93rem; color: var(--ink-soft) }

.pagination { display: flex; gap: 10px; justify-content: center; margin-top: 60px; flex-wrap: wrap }
.pagination .page-numbers {
  min-width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center;
  padding: 0 14px; border-radius: 100px; border: 1px solid var(--line);
  font-size: .86rem; background: var(--white); transition: all .3s var(--ease);
}
.pagination .page-numbers:hover { border-color: var(--green) }
.pagination .page-numbers.current { background: var(--green); color: #fff; border-color: var(--green) }

/* --------------------------------------------------------------------------
   6. Navigation wrappers
   The design's header and mobile drawer are flex containers whose direct
   children are the links themselves. wp_nav_menu() always wraps them in a
   <ul>, which becomes a single flex item and collapses the row. These rules
   make the list transparent to the layout so an assigned menu renders exactly
   as the hand-written anchors do.
   -------------------------------------------------------------------------- */
.nav .nav-list {
  display: flex; align-items: center; gap: 26px;
  list-style: none; margin: 0; padding: 0;
}
.nav .nav-list li { margin: 0 }

.mnav-links { display: flex; flex-direction: column }
.mnav-links .nav-list {
  display: flex; flex-direction: column;
  list-style: none; margin: 0; padding: 0;
}

/* The mobile drawer relies on its links being block-level flex items; inside a
   list they are ordinary inline anchors and lose their row height. */
.mnav-links a:not(.btn) { display: block }

.ftr .nav-list { list-style: none; margin: 0; padding: 0 }
.ftr .nav-list li + li { margin-top: 12px }

/* The design tightens the row at 1000px and hides it at 820px; with a menu
   assigned those gaps live on the list, so mirror the first of them. The
   second needs nothing — .nav{display:none} takes the list with it. */
@media (max-width: 1000px) {
  .nav .nav-list { gap: 10px }
}

/* --------------------------------------------------------------------------
   8. Floating WhatsApp button
   Fixed to the viewport, so it never moves with the scroll and no section's
   overflow can clip it. It sits above every layer the design defines — the
   header is 50, the mobile nav 70, the cart drawer 90, the product modal 96,
   the toast 100 and the checkout 120.
   -------------------------------------------------------------------------- */
.wa-float {
  position: fixed;
  right: 24px;
  /* The safe-area inset keeps it clear of the iOS home indicator, and resolves
     to 0 everywhere else, so the same rule serves both. */
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  z-index: 2147483000;

  display: grid;
  place-items: center;
  width: 60px;
  height: 60px;
  border-radius: 50%;

  background: #25d366;           /* WhatsApp brand green, not a theme token */
  color: #fff;
  box-shadow: 0 6px 20px -4px rgba(22, 33, 13, .35), 0 2px 6px rgba(22, 33, 13, .16);

  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.wa-float svg { width: 34px; height: 34px; display: block }

.wa-float:hover,
.wa-float:focus-visible {
  transform: translateY(-3px) scale(1.04);
  box-shadow: 0 12px 28px -6px rgba(22, 33, 13, .42), 0 3px 8px rgba(22, 33, 13, .2);
  color: #fff;
}
.wa-float:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 3px;
}
.wa-float:active { transform: translateY(-1px) scale(.98) }

/* Step aside for the full-screen overlays. Left on top it would sit directly
   over the cart drawer's "Proceed to Checkout" button and the checkout's own
   actions — both bottom-right — so the highest z-index on the page would be
   covering the two controls that matter most. :has() is supported by every
   current browser; anywhere it is not, the button simply stays put. */
body:has(.drawer.on)  .wa-float,
body:has(.co.on)      .wa-float,
body:has(.modal.on)   .wa-float,
body:has(.mnav.open)  .wa-float {
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px) scale(.9);
  pointer-events: none;
}

@media (max-width: 640px) {
  .wa-float {
    right: 16px;
    bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    width: 54px;
    height: 54px;
  }
  .wa-float svg { width: 30px; height: 30px }
}

/* The toast is centred at the bottom and the button is at the right, so they
   do not collide on a wide screen. On a narrow one the toast is full width,
   so lift the button clear while a toast is showing. */
@media (max-width: 640px) {
  body:has(.toast.on) .wa-float { transform: translateY(-56px) }
}

/* The admin bar does not affect a bottom-anchored element, but a logged-in
   editor on a phone gets a 46px bar that WordPress pins to the bottom. */
@media screen and (max-width: 782px) {
  .admin-bar .wa-float { bottom: calc(62px + env(safe-area-inset-bottom, 0px)) }
}

/* --------------------------------------------------------------------------
   9. Product grid — the orphaned last card

   .prod-grid is repeat(auto-fit, minmax(300px, 1fr)). That is the right
   primitive for an unknown number of products, but it strands the last card
   whenever the count does not divide by the column count. With three products
   that happens across the whole tablet range: two cards on the first row and
   the third alone on the left, with a card-sized hole beside it.

   The band where auto-fit resolves to two columns is derived from brand.css's
   own numbers — minmax(300px) with a 34px gap inside 40px page padding above
   820px, and minmax(280px) with a 26px gap inside 28px padding below it:

     three columns need  3*300 + 2*34 = 968px of track  ->  1048px of viewport
     two columns need    2*280 + 1*26 = 586px of track  ->   642px of viewport

   Between those two figures the grid is exactly two columns, and that is the
   only place a third card can be orphaned. Above 1048px three products sit in
   one row; below 642px every card is full width and there is no orphan.

   If brand.css is ever re-exported with different minmax or gap values, these
   two boundaries have to be recalculated from the same arithmetic.
   -------------------------------------------------------------------------- */
@media (min-width: 642px) and (max-width: 1047px) {
  /* A card that is both the last one and an odd-numbered child is alone on its
     row in a two-column grid. Matches 3, 5 and 7 products; correctly leaves 2,
     4 and 6 alone.

     It is left in its natural single column — so it keeps exactly the width of
     the two cards above it, with no cap to compute — and simply nudged right by
     half a column plus half a gap, which lands it centred across the pair.
     `left: 50%` on a grid item resolves against its grid area, and the area
     here is one column, so the arithmetic is (column + gap) / 2.

     Three more obvious approaches all fail, because .card carries
     container-type: inline-size and so may not size itself from its contents:

       justify-self: center      -> shrink-to-fit, collapses to 2px
       margin-inline: auto       -> shrink-to-fit, collapses to 2px
       transform: translateX()   -> sizes fine, but .rv and .card:hover both
                                    animate transform and would overwrite it

     position/left touches neither sizing nor the transform property, so it
     composes with the reveal animation and the hover lift untouched. */
  .prod-grid > .card:last-child:nth-child(odd) {
    position: relative;
    left: calc(50% + 17px);   /* half a column + half of the 34px gap */
  }
}

/* Below 820px brand.css narrows the gap to 26px. */
@media (min-width: 642px) and (max-width: 820px) {
  .prod-grid > .card:last-child:nth-child(odd) {
    left: calc(50% + 13px);
  }
}

/* --------------------------------------------------------------------------
   10. Header navigation on tablets

   brand.css swaps the inline nav for the burger below 820px. Every current
   iPad is wider than that in portrait — 820 on an Air, 834 on an 11" Air or
   Pro — so they get the desktop nav in a header too narrow to hold it, and the
   links wrap onto a second row under the logo.

   Measured against the real header: brand (164px) + nav + actions (106px) +
   two 24px gaps + 80px page padding. The nav itself is about 420px of link
   text for the five sections that currently render, and roughly 500px once
   Reviews appears — that section is hidden while the testimonials are drafts,
   so the header is carrying less than it eventually will. At the design's
   26px nav gap that needs a viewport of about 1030px, which would wrap on an
   iPad in landscape too.

   So: tighten the gap earlier, and hand over to the burger below 1000px.
   Landscape iPads (1024 and up) keep the full nav with room to spare.

   A menu with more than six top-level items will outgrow this again — it is
   the link text that sets the floor, not the breakpoint.
   -------------------------------------------------------------------------- */
@media (max-width: 1100px) {
  .hdr .nav { gap: 12px }
}

@media (max-width: 1000px) {
  .hdr .nav { display: none }
  .hdr .burger { display: grid }
}

/* Nothing should be able to push the header onto a second line regardless. */
.hdr-in { flex-wrap: nowrap }
.hdr .nav { flex-wrap: nowrap; white-space: nowrap }

/* --------------------------------------------------------------------------
   11. The card footer at narrow card widths

   .card-foot lays the price and the two buttons out in a row with
   justify-content:space-between, and .card-btns is flex:none so it refuses to
   shrink. Together they need about 430px of card:

     price 96 + gap 16 + buttons 257 = 369px of content
     + 60px of .card-body padding + 2px of border = 431px of card

   Below that the row overflows, and .card sets overflow:hidden, so the excess
   is not merely untidy — it is cut off. At a 360px card the Add to Cart button
   is clipped 15px short; at 377px it is the price's strikethrough that goes.

   brand.css already has the right treatment for this — stacked, full-width
   buttons — but keys it to a 560px *viewport*, which is the wrong axis. Card
   width does not follow viewport width here: three products at a 1280px
   desktop give 377px cards and clip, while two products at 1024px give 455px
   cards and are fine. The number of products moves the card width as much as
   the screen does.

   So the same treatment is triggered by the card's own width instead.
   .card already declares container-type:inline-size for its product image, so
   the container exists; this just asks it a question.
   -------------------------------------------------------------------------- */
@container (max-width: 450px) {
  .card-foot {
    flex-direction: column;
    align-items: stretch;
    gap: 18px;
  }

  /* Two equal buttons, laid out with grid rather than `flex: 1`.
     brand.css's own mobile rule uses flex:1 on these, and it does not survive
     being moved here: with flex-basis 0 the buttons collapse to their padding
     and the row never distributes its free space — setting flex-grow inline,
     even !important, changes nothing, while flex-basis:auto or an explicit
     width does. Two 1fr grid columns split the row deterministically and are
     not subject to whatever that flex container is doing. */
  .card-btns {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    width: 100%;
  }
  .card-btns .btn {
    flex: initial;
    width: auto;
    min-width: 0;
  }
}

/* Belt and braces, for a browser without container query support: let the row
   wrap onto a second line rather than be clipped by the card's overflow.
   Pinning the price at its natural width means the overflow lands on the wrap
   rather than silently squeezing the strikethrough out of view. */
.card-foot { flex-wrap: wrap }
.card-foot .price { flex: 0 0 auto }

/* Two more tiers, because a half-width button is not automatically wide enough
   for its own label. "Add to Cart" sets the floor: about 104px of letter-spaced
   uppercase text plus brand.css's 40px of horizontal padding, so 144px. A card
   of 343px only leaves (343 - 62 - 10) / 2 = 135px per button, and .btn has
   overflow:hidden, so the label loses its last characters rather than wrapping.

   This was already true of the design's own mobile rule at a 390px phone — the
   label was clipped by a few pixels there before any of this — so the tiers
   below fix that too. */
@container (max-width: 400px) {
  .card-btns .btn {
    padding-left: 12px;
    padding-right: 12px;
    letter-spacing: .06em;
  }
}

/* Below roughly 320px of card the two buttons cannot sit side by side at any
   sane padding, so they stack instead. */
@container (max-width: 340px) {
  .card-btns { grid-template-columns: 1fr }
}
