/* ==========================================================================
   PUBLIC SITE - shell, header, footer, buttons, section rhythm.
   Consumes tokens.css. No CSS framework: Bootstrap on an editorial site is
   ~200 KB you then spend the day overriding.
   ========================================================================== */

/* ---- Skip link (keyboard users land here first) ------------------------ */

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: var(--z-toast);
  background: var(--tbs-green);
  color: var(--white);
  padding: var(--sp-3) var(--sp-4);
}

.skip-link:focus { left: var(--sp-4); top: var(--sp-4); }

/* ---- Header ----------------------------------------------------------- */

.site-head {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: var(--cream);
  border-bottom: 1px solid var(--line);
  transition: box-shadow var(--dur-component) var(--ease-brand);
}

.site-head.is-stuck { box-shadow: 0 2px 20px rgba(0, 48, 31, .07); }

.site-head__bar {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  min-height: 64px;
  padding-block: var(--sp-3);
}

@media (min-width: 1024px) {
  .site-head__bar { min-height: 76px; }
}

.brand {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  text-decoration: none;
  flex: 0 0 auto;
}

.brand__mark {
  font-family: var(--font-display);
  font-size: 1.125rem;
  line-height: 1;
  letter-spacing: var(--tracking-display);
  color: var(--tbs-green);
  font-weight: 600;
}

.brand__sub {
  font-size: 0.66rem;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--ink-mute);
}

@media (min-width: 768px) {
  .brand__mark { font-size: 1.375rem; }
}

.site-nav {
    display: none;
    /* 18px, not 24px. Seven links plus a fourth header action do not fit at the
     wider gap inside a 1280px container. */
    gap: 18px;
    margin-left: auto;
}

@media (min-width: 1024px) {
  .site-nav { display: flex; }
}

.site-nav a {
    font-size: 0.9375rem;
    font-weight: 500;
    color: var(--ink);
    text-decoration: none;
    padding-block: var(--sp-2);
    position: relative;
    /* A nav label must never break mid-phrase. Without this the row runs out of
     width silently and you get "Build your / own"; with it, a genuine overflow
     is visible immediately and gets fixed by shortening a label. */
    white-space: nowrap;
}

/* Underline grows from the left rather than appearing - cheaper to read */
.site-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 1px;
  width: 0;
  background: var(--tbs-green);
  transition: width var(--dur-component) var(--ease-brand);
}

    /* .is-active is page state, not hover — it must stay ungated. */
    .site-nav a.is-active::after {
        width: 100%;
    }
.site-nav a.is-active { color: var(--tbs-green); font-weight: 600; }

.head-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-left: auto;
}

@media (min-width: 1024px) {
    .head-actions {
        margin-left: var(--sp-4);
    }
}

.icon-btn {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 0;
  background: none;
  color: var(--tbs-green);
  cursor: pointer;
  border-radius: var(--radius-pill);
  text-decoration: none;
}

  

/* ---- Call button ------------------------------------------------------ */

/* inline-flex, not the grid .icon-btn sets: the icon and the number have to sit
   side by side, and grid would stack them in a single cell. */
.call-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
}

/* Always hidden. Showing it on wide screens was a mistake: .container caps at
   1280px, so a 2560px monitor gives the header exactly as much room as a
   1328px one — the extra 86px the number costs is never available, and the nav
   wrapped into "Build your / own" to pay for it.

   The number still reaches the customer three other ways: the anchor's title
   and aria-label, the mobile drawer, and the help band above the footer. */
.call-btn__num {
    display: none;
}


/* ---- Header search ---------------------------------------------------- */

/* static on purpose: the panel below is absolutely positioned and needs to
   anchor to .site-head — which is sticky, and therefore a positioned ancestor —
   so it spans the whole header instead of the 44px button. */
.site-search {
    position: static;
}

    .site-search > summary {
        cursor: pointer;
        list-style: none;
    }

        .site-search > summary::-webkit-details-marker {
            display: none;
        }

        .site-search > summary::marker {
            content: "";
        }

    .site-search[open] > summary {
        background: var(--tbs-green-soft);
    }

.site-search__panel {
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    z-index: 1;
    background: var(--cream);
    border-bottom: 1px solid var(--line);
    /* A long, soft shadow rather than the card shadow: this is a sheet dropping
     over the page, not a tile sitting on it. */
    box-shadow: 0 18px 40px rgba(0, 48, 31, .10);
    padding-block: var(--sp-5);
    /* <details> has no transition of its own, so the entrance is animated on the
     panel, which runs once each time it is revealed. */
    animation: search-drop var(--dur-component) var(--ease-brand) both;
}

@keyframes search-drop {
    from {
        opacity: 0;
        transform: translateY(-10px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .site-search__panel {
        animation: none;
    }
}

/* ---- The field ------------------------------------------------------- */

.site-search__field {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding-left: var(--sp-4);
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: var(--radius-input);
    /* No overflow:hidden. It was rounding the submit button's corners, but the
     moment the input refused to shrink it clipped the button out of existence
     instead. The button carries its own radius below. */
    flex-wrap: nowrap;
    transition: border-color var(--dur-micro) var(--ease-brand), box-shadow var(--dur-micro) var(--ease-brand);
}

    .site-search__field:focus-within {
        border-color: var(--tbs-green);
        box-shadow: 0 0 0 3px rgba(0, 75, 52, .10);
    }

.site-search__icon {
    flex: 0 0 auto;
    color: var(--ink-mute);
    transition: color var(--dur-micro) var(--ease-brand);
}

.site-search__field:focus-within .site-search__icon {
    color: var(--tbs-green);
}

.site-search__input {
    /* flex-basis 0 and min-width 0 together are what let this shrink below the
     input's intrinsic size. See also size="1" in the markup — the element's
     default size="20" is the thing that was pushing the button out. */
    flex: 1 1 0;
    min-width: 0;
    width: 100%;
    font-family: inherit;
    /* 16px minimum — anything smaller and iOS zooms the whole page on focus. */
    font-size: 1rem;
    line-height: 1.4;
    color: var(--ink);
    background: none;
    border: 0;
    padding-block: 15px;
    min-height: 52px;
}

    .site-search__input::placeholder {
        color: var(--ink-mute);
        opacity: .75;
    }

    /* The ring lives on the field, so the input itself must not draw a second one. */
    .site-search__input:focus {
        outline: none;
    }

    /* Safari's own clear button on type=search fights the layout. */
    .site-search__input::-webkit-search-decoration,
    .site-search__input::-webkit-search-cancel-button {
        -webkit-appearance: none;
    }

.site-search__go {
    flex: 0 0 auto;
    /* Belt and braces: this must never be the thing that gives way. */
    flex-shrink: 0;
    align-self: stretch;
    border: 0;
    border-radius: 0 var(--radius-input) var(--radius-input) 0;
    margin: -1px -1px -1px 0; /* sit flush over the field's own border */
    padding-inline: var(--sp-6);
    font-family: inherit;
    font-size: 0.9375rem;
    font-weight: 600;
    letter-spacing: .01em;
    color: var(--white);
    background: var(--tbs-green);
    cursor: pointer;
    transition: background var(--dur-micro) var(--ease-brand);
}

 

/* ---- Popular searches ------------------------------------------------- */

.site-search__quick {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-2);
    margin-top: var(--sp-4);
}

.site-search__quick-label {
    font-size: var(--fs-eyebrow);
    font-weight: 700;
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: var(--ink-mute);
    margin-right: var(--sp-1);
}

.site-search__quick a {
    font-size: 0.85rem;
    color: var(--tbs-green);
    text-decoration: none;
    padding: 6px 13px;
    border: 1px solid var(--line);
    border-radius: var(--radius-pill);
    background: var(--white);
    transition: border-color var(--dur-micro) var(--ease-brand), background var(--dur-micro) var(--ease-brand);
}

 

@media (max-width: 560px) {
    .site-search__go {
        padding-inline: var(--sp-4);
    }

    .site-search__input {
        padding-block: 13px;
        min-height: 48px;
    }

    /* Scrolls sideways rather than wrapping to a second and third row and pushing
     the whole page down. */
    /* Scrolls sideways rather than wrapping to a second and third row. No
     negative margin — that was dragging "POPULAR" 16px left of the field above
     it and out of alignment with everything else in the panel. */
    .site-search__quick {
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: none;
    }

        .site-search__quick::-webkit-scrollbar {
            display: none;
        }

        .site-search__quick a {
            white-space: nowrap;
            flex: 0 0 auto;
        }
}


/* Four actions plus the wordmark is tight on a small phone: at 360px the row
   overflows at the default 44px buttons and 8px gaps. */
@media (max-width: 479px) {
    .head-actions {
        gap: 2px;
    }

    .icon-btn {
        width: 40px;
        height: 40px;
    }
}

.nav-toggle { display: grid; }

@media (min-width: 1024px) {
  .nav-toggle { display: none; }
}

/* ---- Mobile drawer nav ------------------------------------------------- */

.mobile-nav {
  display: none;
  border-top: 1px solid var(--line);

  /* padding-block, NOT the padding shorthand.
     This element also carries .container, and the shorthand was resetting that
     class's padding-inline to 0 — which is why every menu link sat flush
     against the edge of the screen with no gutter at all. */
  padding-block: var(--sp-2) var(--sp-4);
}

.mobile-nav.is-open { display: block; }

@media (min-width: 1024px) {
  .mobile-nav, .mobile-nav.is-open { display: none; }
}

/* 52px rows: comfortably above the 44px minimum touch target, but tight enough
   that eight items and the banner still share the first screen. At the previous
   height the menu filled the phone on its own. */
.mobile-nav a {
  display: flex;
  align-items: center;
  min-height: 52px;
  padding-block: 6px;
  font-size: 1rem;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--line);
}

.mobile-nav a:last-child { border-bottom: 0; }

/* ---- Buttons ---------------------------------------------------------- */

.b {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 48px;
  padding: 13px 26px;
  font-family: inherit;
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: .01em;
  border: 1px solid transparent;
  border-radius: var(--radius-input);
  cursor: pointer;
  text-decoration: none;
  text-align: center;
  position: relative;
  overflow: hidden;
  transition: color var(--dur-component) var(--ease-brand),
              border-color var(--dur-component) var(--ease-brand);
}

/* Fill sweeps in from the left on hover instead of a flat colour swap */
.b::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--tbs-green-deep);
  transform: translateX(-101%);
  transition: transform var(--dur-component) var(--ease-brand);
  z-index: 0;
}

.b > * { position: relative; z-index: 1; }


.b--primary { background: var(--tbs-green); color: var(--white); }


.b--outline {
  background: transparent;
  color: var(--tbs-green);
  border-color: var(--tbs-green);
}


.b--ghost {
  background: transparent;
  color: var(--tbs-green);
  border-color: var(--line);
  min-height: 40px;
  padding: 9px 18px;
  font-size: 0.875rem;
}

.b--ghost::before { background: var(--tbs-green-soft); }


.b--gold { background: var(--gold); color: #2A2115; }
.b--gold::before { background: #B3945A; }

.b--block { width: 100%; }

.b:disabled, .b[aria-disabled="true"] {
  opacity: .5;
  pointer-events: none;
}

/* ---- Section rhythm --------------------------------------------------- */

.band { padding-block: var(--sp-7); }

@media (min-width: 768px) {
  .band { padding-block: var(--sp-8); }
}

/* For strips of shortcuts rather than sections of content — they do not need
   the same breathing room as a band of product cards. */
.band--compact { padding-block: var(--sp-5); }

@media (min-width: 768px) {
  .band--compact { padding-block: var(--sp-6); }
}

.band--compact .band-head { margin-bottom: var(--sp-3); }

.band--tint { background: var(--tbs-green-soft); }
.band--dark { background: var(--tbs-green); color: rgba(255, 255, 255, .88); }
.band--dark h1, .band--dark h2, .band--dark h3 { color: var(--white); }

.band-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
  margin-bottom: var(--sp-5);
}

.band-head h2 {
  font-family: var(--font-display);
  margin: 0;
}

.band-head p {
  margin: var(--sp-1) 0 0;
  color: var(--ink-mute);
  max-width: 56ch;
}

/* On a phone the head wraps and the "See all gifts" button drops onto its own
   row, where a bordered box reads as the section's primary action rather than
   the aside it is. Below the rail it would be missed, so it stays here but
   becomes a text link — the gifts themselves are what should draw the tap. */
@media (max-width: 640px) {
  /* Stacked, not side by side. As a row the link aligned itself with the
     eyebrow — so "See all gifts" ended up level with "CURATED FOR EVERY
     RELATIONSHIP" and above the heading it belongs to. */
  .band-head {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--sp-2);
    margin-bottom: var(--sp-4);
  }

  .band-head .b--ghost {
    min-height: 0;
    padding: 0;
    border: 0;
    background: none;
    font-size: 0.875rem;
    color: var(--tbs-green);
    text-decoration: underline;
    text-underline-offset: 3px;
  }
}

/* ---- Breadcrumbs ----------------------------------------------------- */

.crumbs {
  padding-block: var(--sp-4);
  font-size: 0.82rem;
  color: var(--ink-mute);
}

.crumbs a { color: var(--ink-mute); text-decoration: none; }

.crumbs span[aria-hidden] { padding-inline: var(--sp-2); opacity: .5; }

/* ---- Footer ---------------------------------------------------------- */

.site-foot {
  background: var(--tbs-green);
  color: rgba(255, 255, 255, .78);
  padding-block: var(--sp-6) var(--sp-4);
  /* No top margin. The trust strip now sits immediately above and provides the
     separation; 64px of gap between them read as a gap in the page. */
  margin-top: 0;
}

.site-foot h3 {
  color: var(--white);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  margin-bottom: var(--sp-4);
}

.foot-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--sp-6);
}

/* On a phone the link columns stacked into one long ladder — around 900px of
   scrolling past text nobody reads. Two columns halves it, and 15 links in two
   short lists reads as a site map rather than a wall.

   The brand blurb spans both, because it is prose and does not belong in a
   narrow column. */
@media (max-width: 719px) {
  .foot-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-5) var(--sp-4);
  }

  .foot-brand { grid-column: 1 / -1; }

  .foot-grid a { font-size: 0.8125rem; padding-block: 3px; }
  .site-foot h3 { margin-bottom: var(--sp-2); }
}

.foot-grid a {
  display: block;
  color: rgba(255, 255, 255, .78);
  text-decoration: none;
  padding-block: 5px;
  font-size: 0.9rem;
}


.foot-brand__mark {
  font-family: var(--font-display);
  font-size: 1.25rem;
  color: var(--white);
  margin-bottom: var(--sp-3);
}

/* Fraunces renders <sup> at close to full size, so the registered mark was
   sitting almost as large as the wordmark beside it. Sized down explicitly
   rather than left to the font's defaults. */
.foot-brand__mark sup {
  font-size: 0.5em;
  vertical-align: super;
  line-height: 0;
  margin-left: 1px;
}

.foot-brand p { font-size: 0.9rem; max-width: 34ch; }

.foot-legal {
  margin-top: var(--sp-6);
  padding-top: var(--sp-4);
  border-top: 1px solid rgba(255, 255, 255, .16);
  display: flex;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
  font-size: 0.8rem;
  color: rgba(255, 255, 255, .58);
}

/* ---- Floating WhatsApp ----------------------------------------------- */

.wa-float {
  position: fixed;
  right: var(--sp-4);
  bottom: var(--sp-4);
  z-index: var(--z-sticky);
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  background: #25D366;
  color: #06331A;
  font-weight: 700;
  font-size: 0.875rem;
  padding: 12px 18px;
  border-radius: var(--radius-pill);
  text-decoration: none;
  box-shadow: var(--shadow-lift);
}

.wa-float span { display: none; }

@media (min-width: 768px) {
  .wa-float span { display: inline; }
}

/* Keep clear of the shortlist pill on mobile */
@media (max-width: 767px) {
  .wa-float { bottom: 84px; padding: 12px; }
}

/* ---- Reveal on scroll (progressive enhancement) --------------------- */

.reveal {
  opacity: 0;
  transform: translateY(28px);
}

.reveal.is-in {
  opacity: 1;
  transform: none;
  transition: opacity var(--dur-section) var(--ease-brand),
              transform var(--dur-section) var(--ease-brand);
}

/* Never hide content if JS fails or is disabled */
.no-js .reveal, html:not(.js) .reveal { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal.is-in { opacity: 1; transform: none; transition: none; }
}

/* ==========================================================================
   HOVER — POINTER DEVICES ONLY

   On a touch screen :hover latches onto the last element tapped and never
   clears, because there is no "pointer left" event. A tapped "Add to
   shortlist" kept its swept-in fill while its untouched neighbour stayed
   outlined, so two identical buttons looked like two different components.

   Anything that changes appearance on hover belongs in here. State classes
   (.is-active, .is-on, :focus-visible) stay outside — they are meant to persist.
   ========================================================================== */

@media (hover: hover) {
    .site-nav a:hover::after {
        width: 100%;
    }

    .icon-btn:hover {
        background: var(--tbs-green-soft);
    }

    /* The fill parked off-screen at translateX(-101%) by .b::before (line 465). */
    .b:hover::before {
        transform: translateX(0);
    }

    .b--primary:hover {
        color: var(--white);
    }

    .b--outline:hover {
        color: var(--white);
    }

    .b--ghost:hover {
        color: var(--tbs-green);
        border-color: var(--tbs-green);
    }

    .b--gold:hover {
        color: #2A2115;
    }

    .crumbs a:hover {
        color: var(--tbs-green);
        text-decoration: underline;
    }

    .foot-grid a:hover {
        color: var(--white);
        text-decoration: underline;
    }

    .site-search__go:hover {
        background: var(--tbs-green-deep);
    }

    .site-search__quick a:hover {
        border-color: var(--tbs-green);
        background: var(--tbs-green-soft);
    }
}