/* Depends on /css/tokens.css for the palette and base rules. */
/* ==========================================================================
   Hometown Services Hub
   Mobile-first. Most of this traffic is a phone held one-handed in a driveway,
   so tap targets stay >= 44px and nothing important sits below a fold that
   needs two scrolls to reach.
   ========================================================================== */





/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */




h1,
h2,
h3,
p,
ul {
  margin: 0;
}

ul {
  padding: 0;
  list-style: none;
}

a {
  color: var(--brand-bright);
}

img {
  max-width: 100%;
}

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: 1.15rem;
}


.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 0.7rem 1rem;
  background: var(--surface);
  border-radius: 0 0 var(--radius-sm) 0;
}

.skip-link:focus {
  left: 0;
}

:where(a, button, input, [tabindex]):focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* --------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  justify-content: center;
  background-color: var(--hero-bg, #000000);
  color: #ffffff;
  padding-block: 3rem 3.25rem;
  padding-top: max(3rem, env(safe-area-inset-top));
  /* A floor, not a fixed height. The padding above still guarantees room to
     breathe, and a headline that wraps on a narrow screen pushes past this
     rather than spilling out of it. */
  min-height: var(--hero-min-h, 14rem);
  /* The brand mark on this page is the red rule under the banner. */
  border-bottom: var(--hero-stroke) solid var(--brand);
}

/* Photo and scrim are separate layers so the opacity control only dims the
   picture -- it must never wash out the text sitting on top. */
.hero__photo,
.hero__scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.hero__photo {
  background-image: var(--hero-image, none);
  background-size: cover;
  background-position: var(--hero-focal, center);
  background-repeat: no-repeat;
}

.hero__scrim {
  background: #000000;
  opacity: var(--hero-overlay, 0);
}

.hero__content {
  position: relative;
  z-index: 1;
}


.hero__title {
  font-size: clamp(1.75rem, 6.5vw, 2.7rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  font-weight: 700;
}

.hero__tagline {
  font-size: clamp(1rem, 3.6vw, 1.2rem);
  color: var(--hero-tagline);
  margin-top: 0.4rem;
}

.hero__intro {
  max-width: 44ch;
  margin-top: 0.9rem;
  color: var(--hero-intro);
  font-size: 0.96rem;
}





/* --------------------------------------------------------------------------
   Layout
   -------------------------------------------------------------------------- */

.layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  padding-block: 1.5rem 0;
}

/* Grid items default to min-width:auto, which refuses to shrink below the
   content's min-content width. The filter rail is a horizontal scroller full
   of chips, so that default made the whole page as wide as the chip row. */
.filters,
.results {
  min-width: 0;
}

@media (min-width: 62rem) {
  .layout {
    grid-template-columns: 14.5rem minmax(0, 1fr);
    gap: 2rem;
    align-items: start;
  }
}

/* --------------------------------------------------------------------------
   Filter rail
   -------------------------------------------------------------------------- */

.filters__title {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.filters__hint {
  margin-top: 0.15rem;
  font-size: 0.8rem;
  color: var(--ink-faint);
}

.filters__list {
  display: flex;
  min-width: 0;
  gap: 0.45rem;
  margin-top: 0.7rem;
  /* Mobile: one scrolling row. Desktop: a left column. Same markup either way. */
  overflow-x: auto;
  padding-bottom: 0.3rem;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.filters__list::-webkit-scrollbar {
  display: none;
}

@media (min-width: 62rem) {
  .filters {
    position: sticky;
    top: 1rem;
  }

  .filters__list {
    flex-direction: column;
    align-items: stretch;
    overflow-x: visible;
    gap: 0.3rem;
  }

  .chip {
    /* In the rail the labels read as a list, so they align left. */
    justify-content: flex-start;
    width: 100%;
    white-space: normal;
    text-align: left;
  }
}

/* --------------------------------------------------------------------------
   Controls
   -------------------------------------------------------------------------- */


.need {
  max-width: 40rem;
  padding: 0.9rem 1rem 0.8rem;
  background: var(--surface);
  border: var(--line-w) solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.need__label {
  display: block;
  font-size: 1.02rem;
  font-weight: 650;
  color: var(--ink);
}

.need__hint {
  margin: 0.15rem 0 0.6rem;
  font-size: 0.85rem;
  color: var(--ink-faint);
}

.need__input {
  display: block;
  width: 100%;
  min-height: 5.5rem;
  padding: 0.65rem 0.8rem;
  font-family: inherit;
  font-size: 1rem; /* 16px stops iOS zooming the page on focus */
  line-height: 1.45;
  color: var(--ink);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  resize: vertical;
}

.need__input::placeholder {
  color: var(--ink-faint);
}

.need__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 0.45rem;
  min-height: 1.6rem;
}

.need__clear {
  min-height: 2rem;
  padding: 0.2rem 0.7rem;
  font: inherit;
  font-size: 0.85rem;
  color: var(--ink-soft);
  background: none;
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
}

.need__clear[hidden] {
  display: none;
}

.need__count {
  margin-left: auto;
  font-size: 0.78rem;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

/* The line that names what we think they need, filled in from the matcher. */
.need__suggestion {
  margin: 0.6rem 0 0;
  padding: 0.55rem 0.7rem;
  font-size: 0.88rem;
  color: var(--ink-soft);
  background: var(--bg);
  border-left: 3px solid var(--brand);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.need__suggestion[hidden] {
  display: none;
}

.need__suggestion strong {
  color: var(--ink);
}

.need__suggestion.is-thinking {
  color: var(--ink-faint);
  border-left-color: var(--line);
}

/* --------------------------------------------------------------------------
   Controls
   -------------------------------------------------------------------------- */


.search {
  position: relative;
  max-width: 34rem;
}

.search__input {
  width: 100%;
  min-height: var(--tap);
  padding: 0.65rem 2.5rem 0.65rem 0.95rem;
  font-size: 1rem; /* 16px stops iOS zooming the page on focus */
  font-family: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  box-shadow: var(--shadow);
}

.search__input::placeholder {
  color: var(--ink-faint);
}

.search__clear[hidden] {
  display: none;
}

.search__clear {
  position: absolute;
  right: 0.35rem;
  top: 50%;
  transform: translateY(-50%);
  translate: 0 -50%;
  width: var(--tap);
  height: var(--tap);
  display: grid;
  place-items: center;
  font-size: 1.35rem;
  line-height: 1;
  color: var(--ink-soft);
  background: none;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
}



.chip {
  flex: 0 0 auto;
  min-height: var(--tap);
  padding: 0.35rem 0.95rem;
  font-size: 0.88rem;
  font-family: inherit;
  font-weight: 500;
  white-space: nowrap;
  color: var(--ink-soft);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
  box-shadow: var(--shadow);
  transition:
    box-shadow 0.18s ease,
    transform 0.18s ease;
}

/* The trade icon on a chip. currentColor, so it follows the label between the
   resting and the selected state without a second rule. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}

.chip__icon {
  flex: 0 0 auto;
  width: 1.15em;
  height: 1.15em;
  color: currentColor;
}

/* The sprite is a definition, not a picture. Out of the flow entirely, and
   never a gap at the top of the page. */
.sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.chip.is-active {
  color: var(--brand-ink);
  background: var(--brand);
  border-color: var(--brand);
  box-shadow: var(--shadow-brand);
}


/* --------------------------------------------------------------------------
   Card grid

   The card itself lives in card.css, which the partner portal loads too.
   Only the public page's arrangement of them is here.
   -------------------------------------------------------------------------- */

.grid {
  /*
   * Flex rather than grid, and the reason is the last row.
   *
   * With `grid-template-columns: repeat(auto-fit, ...)`, justify-content aligns
   * the whole track set -- so centring put a tidy block on the page but left an
   * incomplete final row hard against its left edge. Flex wrapping aligns each
   * row independently, which is what "centre the incomplete row" actually asks
   * for. Everything else about the behaviour is unchanged: cells are a fixed
   * phone width, a row simply holds fewer of them, and a listing drops to the
   * next row the moment it would be squeezed into the page padding.
   */
  display: flex;
  flex-wrap: wrap;
  gap: var(--grid-gap);
  padding-block: 1.1rem 2.5rem;
  justify-content: var(--grid-align, flex-start);

  /*
   * The column ceiling, as a width. --grid-cols is a maximum rather than a
   * count: capping the grid here lets a narrow screen still drop to fewer,
   * which is the whole point of letting it wrap.
   */
  max-width: calc(
    var(--grid-cols, 5) * var(--card-w) + (var(--grid-cols, 5) - 1) * var(--grid-gap)
  );

  /* Where the capped block itself sits. Centring the rows without this would
     leave a tidy centred row inside a block still pinned to the left. */
  margin-inline: var(--grid-inline, 0 auto);
}

/*
 * A fixed cell, never a stretched one: with `flex: 1` a lone card on a tablet
 * grew to 700px, which is not "phone width" by any reading. The 100% ceiling is
 * the important half -- without it the 24rem floor would overflow a 320px
 * phone.
 */
.grid > .card {
  flex: 0 0 var(--card-w);
  max-width: 100%;
  min-width: 0;
}

/* --------------------------------------------------------------------------
   Grid or list

   Same cards, same content, same three ways out. List turns each one on its
   side into a full-width row -- worth having once the directory is long enough
   that scanning matters more than presentation.
   -------------------------------------------------------------------------- */

.results__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.viewswitch {
  display: flex;
  gap: 0.25rem;
  padding: 0.2rem;
  background: var(--surface-sunken);
  border: 1px solid var(--line);
  border-radius: 999px;
}

.viewswitch[hidden] {
  display: none;
}

.viewswitch__btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.35rem 0.7rem;
  font: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  line-height: 1;
  color: var(--ink-soft);
  background: none;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  transition: color 0.15s ease, background-color 0.15s ease;
}

.viewswitch__btn:hover {
  color: var(--ink);
}

.viewswitch__btn[aria-pressed='true'] {
  color: #fff;
  background: var(--brand);
}

.viewswitch__btn:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* Drawn in CSS rather than shipped as files -- two shapes at 12px each. */
.viewswitch__icon {
  width: 0.8rem;
  height: 0.8rem;
  background:
    linear-gradient(currentColor, currentColor) 0 0 / 45% 45% no-repeat,
    linear-gradient(currentColor, currentColor) 100% 0 / 45% 45% no-repeat,
    linear-gradient(currentColor, currentColor) 0 100% / 45% 45% no-repeat,
    linear-gradient(currentColor, currentColor) 100% 100% / 45% 45% no-repeat;
}

.viewswitch__icon--list {
  background:
    linear-gradient(currentColor, currentColor) 0 0 / 100% 22% no-repeat,
    linear-gradient(currentColor, currentColor) 0 50% / 100% 22% no-repeat,
    linear-gradient(currentColor, currentColor) 0 100% / 100% 22% no-repeat;
}

/* In list view a row spans the page, so the column ceiling does not apply. */
.grid[data-view='list'] {
  max-width: var(--wrap);
  justify-content: flex-start;
  margin-inline: 0 auto;
}

.grid[data-view='list'] > .card {
  flex: 1 1 100%;
  max-width: 100%;
}


@media (hover: hover) {
  .chip:hover {
    border-color: var(--brand);
    box-shadow: var(--shadow-lift);
    transform: translateY(-2px);
  }

  .chip.is-active:hover {
    box-shadow: var(--shadow-brand);
  }

  .share__toggle:hover {
    transform: translateY(-2px);
  }
}
.empty {
  padding: 2.5rem 0 3.5rem;
  text-align: center;
  color: var(--ink-soft);
}

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

.footer {
  padding-block: 2rem;
  padding-bottom: max(2rem, env(safe-area-inset-bottom));
  background: var(--surface);
  border-top: 1px solid var(--line);
  font-size: 0.88rem;
  color: var(--ink-soft);
}

.footer__name {
  font-weight: 600;
  color: var(--ink);
}

.footer__meta {
  margin-top: 0.15rem;
}

.footer__partner {
  margin-top: 1.1rem;
}

.footer__login {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0.5rem 1rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink-soft);
  text-decoration: none;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}

.footer__login:hover,
.footer__login:focus-visible {
  color: var(--brand);
  border-color: var(--brand);
}

.footer__copy {
  margin-top: 1.25rem;
  font-size: 0.8rem;
  color: var(--ink-faint);
}


/* --------------------------------------------------------------------------
   Results column
   -------------------------------------------------------------------------- */

.results__count {
  margin-top: 0.6rem;
  font-size: 0.8rem;
  color: var(--ink-faint);
}

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

.footer__note {
  margin-top: 0.6rem;
  font-size: 0.82rem;
  color: var(--ink-faint);
}

/* --------------------------------------------------------------------------
   Share
   -------------------------------------------------------------------------- */

.share {
  margin-bottom: 1.1rem;
}

.share__toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  width: 100%;
  min-height: var(--tap);
  padding: 0.5rem 0.9rem;
  font: inherit;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--brand-ink);
  background: var(--brand);
  border: 1px solid var(--brand);
  border-radius: var(--radius-sm);
  cursor: pointer;
  justify-content: center;
  box-shadow: var(--shadow-brand);
  transition:
    box-shadow 0.18s ease,
    transform 0.18s ease;
}

.share__icon {
  font-size: 1.05em;
  line-height: 1;
}

.share__panel {
  margin-top: 0.6rem;
  padding: 0.8rem;
  background: var(--bg);
  border: var(--line-w) solid var(--line);
  border-radius: var(--radius-sm);
}

.share__panel[hidden] {
  display: none;
}

.share__hint,
.share__qrhint {
  font-size: 0.78rem;
  color: var(--ink-faint);
}

.share__row {
  display: flex;
  gap: 0.35rem;
  margin-top: 0.55rem;
}

.share__url {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 2.4rem;
  padding: 0.35rem 0.55rem;
  font: inherit;
  font-size: 0.78rem;
  color: var(--ink-soft);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 6px;
}

.share__copy,
.share__native {
  flex: 0 0 auto;
  min-height: 2.4rem;
  padding: 0.35rem 0.75rem;
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--action-ink);
  background: var(--action-site);
  border: 0;
  border-radius: 6px;
  cursor: pointer;
}

.share__native {
  width: 100%;
  margin-top: 0.45rem;
}

/* White quiet zone regardless of scheme -- a QR on a dark card will not scan. */
.share__qr {
  display: block;
  width: 100%;
  max-width: 11rem;
  height: auto;
  margin: 0.7rem auto 0.35rem;
  padding: 0.35rem;
  background: #ffffff;
  border: 1px solid var(--line);
  border-radius: 6px;
}

.share__qrhint {
  text-align: center;
}

.share__status {
  margin-top: 0.4rem;
  min-height: 1.1rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--action-map);
}

/* --------------------------------------------------------------------------
   Mobile filter drawer

   Below the rail breakpoint the filter column becomes a tray that slides in
   from the left. Above it, every rule here is switched back off and the aside
   is a plain static column again -- one piece of markup, two behaviours.
   -------------------------------------------------------------------------- */

.drawer-trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  align-self: start;
  min-height: var(--tap);
  padding: 0.5rem 1rem;
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  cursor: pointer;
}

.drawer-trigger__icon {
  font-size: 1.05em;
  line-height: 1;
}

.drawer-trigger__count {
  min-width: 1.4rem;
  padding: 0.05rem 0.4rem;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--brand-ink);
  background: var(--brand);
  border-radius: 999px;
}

.drawer-trigger__count[hidden] {
  display: none;
}

.drawer-backdrop {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgb(0 0 0 / 45%);
}

.drawer-backdrop[hidden] {
  display: none;
}

.drawer-close {
  width: var(--tap);
  height: var(--tap);
  display: grid;
  place-items: center;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--ink-soft);
  background: none;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
}

.filters__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

@media (max-width: 61.99rem) {
  .filters {
    position: fixed;
    inset-block: 0;
    left: 0;
    z-index: 50;
    width: min(20rem, 86vw);
    padding: 1.1rem 1.15rem;
    padding-top: max(1.1rem, env(safe-area-inset-top));
    overflow-y: auto;
    background: var(--surface);
    border-right: 1px solid var(--line);
    box-shadow: var(--shadow-lift);
    transform: translateX(-100%);
    visibility: hidden;
    transition:
      transform 0.22s ease,
      visibility 0.22s;
  }

  .filters.is-open {
    transform: translateX(0);
    visibility: visible;
  }

  /* In the tray there is room for a real list, so drop the horizontal scroll. */
  .filters__list {
    flex-direction: column;
    align-items: stretch;
    overflow-x: visible;
    gap: 0.3rem;
  }

  .filters__list .chip {
    justify-content: flex-start;
    width: 100%;
    white-space: normal;
    text-align: left;
  }
}

@media (min-width: 62rem) {
  /* Desktop: the rail is permanent, so the tray chrome disappears. */
  .drawer-trigger,
  .drawer-backdrop,
  .drawer-close {
    display: none;
  }
}

/* A drawer that slid in while the visitor asked for less motion should just
   appear instead. */









/* A card someone arrived on via that partner's own QR code. Marked, not
   isolated -- the rest of the directory stays visible, which is the point of
   being listed in it. */
.card.is-spotlit {
  border-color: var(--brand);
  box-shadow: var(--shadow-brand);
}

/* --------------------------------------------------------------------------
   The Offers button

   Sits between the listing's own content and the three ways out. Red, so it
   reads as the group's own thing rather than as a fourth route to the
   business -- and only present on cards that actually have an offer.
   -------------------------------------------------------------------------- */

.card__offers-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
  min-height: var(--tap);
  margin: 0.15rem 0 0.1rem;
  padding: 0.55rem 0.9rem;
  font: inherit;
  font-size: 0.95rem;
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: 1.2;
  color: #fff;
  /* --brand-bright is the deeper red, so this lights the top and settles the
     foot -- the way a raised button catches light. */
  background: linear-gradient(180deg, var(--brand) 0%, var(--brand-bright) 100%);
  border: 0;
  border-radius: var(--radius-xs);
  box-shadow: var(--shadow-brand);
  cursor: pointer;
  /* Single line, sized down rather than wrapped -- the same rule the three
     action buttons follow. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: transform 0.12s ease, box-shadow 0.15s ease, filter 0.15s ease;
}

.card__offers-btn:hover {
  filter: brightness(1.08);
  transform: translateY(-1px);
  box-shadow: var(--shadow-lift);
}

.card__offers-btn:active {
  transform: translateY(0);
}

.card__offers-btn:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/*
 * The portal preview renders this disabled, because the preview is a picture of
 * the card rather than a working one. It still has to look like the button the
 * public page will show -- greying it out would misrepresent the very thing the
 * partner is checking.
 */
.card__offers-btn:disabled {
  cursor: default;
  opacity: 1;
}

.card__offers-btn:disabled:hover {
  filter: none;
  transform: none;
  box-shadow: var(--shadow-brand);
}

/* How many are waiting behind it. */
.card__offers-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.5em;
  height: 1.5em;
  padding: 0 0.4em;
  font-size: 0.82em;
  font-weight: 800;
  color: var(--brand);
  background: #fff;
  border-radius: 999px;
}

/* --------------------------------------------------------------------------
   The offers modal
   -------------------------------------------------------------------------- */

.offers-modal {
  width: min(30rem, calc(100vw - 2rem));
  max-height: min(85vh, 44rem);
  padding: 0;
  color: var(--ink);
  background: var(--surface);
  border: 0;
  border-top: 5px solid var(--brand);
  border-radius: var(--radius);
  box-shadow: 0 24px 60px rgb(0 0 0 / 35%);
  overflow: hidden;
}

.offers-modal::backdrop {
  background: rgb(0 0 0 / 55%);
}

/* The dialog is its own scroll container, so a long list of offers scrolls
   inside the panel instead of the page moving behind it. */
.offers-modal {
  display: flex;
  flex-direction: column;
}

.offers-modal:not([open]) {
  display: none;
}

.offers-modal__head {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 1rem 1.1rem 0.85rem;
  border-bottom: 1px solid var(--line);
}

.offers-modal__heading {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  font-size: 1.05rem;
  font-weight: 800;
  line-height: 1.3;
}

.offers-modal__close {
  flex: 0 0 auto;
  width: 2rem;
  height: 2rem;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--ink-soft);
  background: none;
  border: 0;
  border-radius: var(--radius-xs);
  cursor: pointer;
}

.offers-modal__close:hover {
  color: var(--ink);
  background: var(--surface-sunken);
}

.offers-modal__close:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}

.offers {
  flex: 1 1 auto;
  margin: 0;
  padding: 0.85rem;
  list-style: none;
  overflow-y: auto;
}

.offer {
  background: var(--surface-sunken);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.offer + .offer {
  margin-top: 0.6rem;
}

/* --------------------------------------------------------------------------
   One offer: the title opens it

   Three deliberate sizes -- the headline is what the offer is, the details
   elaborate, and the fine print is the part that matters only when somebody
   is disappointed, so it stays legible rather than merely present.
   -------------------------------------------------------------------------- */

.offer__title {
  margin: 0;
  font-size: inherit;
  font-weight: inherit;
}

.offer__toggle {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  min-height: var(--tap);
  padding: 0.7rem 0.8rem;
  font: inherit;
  text-align: left;
  color: var(--ink);
  background: none;
  border: 0;
  border-left: 4px solid var(--brand);
  cursor: pointer;
}

.offer__toggle:hover {
  background: rgb(200 16 46 / 4%);
}

.offer__toggle:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}

.offer__headline {
  flex: 1 1 auto;
  font-size: 1rem;
  font-weight: 800;
  line-height: 1.3;
}

.offer__chevron {
  flex: 0 0 auto;
  width: 0.55rem;
  height: 0.55rem;
  margin-right: 0.15rem;
  border-right: 2px solid var(--brand);
  border-bottom: 2px solid var(--brand);
  transform: rotate(45deg) translate(-0.1rem, -0.1rem);
  transition: transform 0.18s ease;
}

.offer__toggle[aria-expanded='true'] .offer__chevron {
  transform: rotate(-135deg) translate(-0.15rem, -0.15rem);
}

.offer__body {
  padding: 0 0.8rem 0.8rem 1.05rem;
}

.offer__body[hidden] {
  display: none;
}

.offer__details {
  margin: 0;
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.45;
  color: var(--ink-soft);
}

.offer__terms {
  margin: 0.4rem 0 0;
  font-size: 0.75rem;
  font-style: italic;
  font-weight: 400;
  line-height: 1.4;
  color: var(--ink-faint);
}

.offer__claim {
  display: block;
  width: 100%;
  margin-top: 0.7rem;
  min-height: var(--tap);
  padding: 0.5rem 0.75rem;
  font: inherit;
  font-size: 0.92rem;
  font-weight: 800;
  line-height: 1.2;
  color: #fff;
  background: var(--brand);
  border: 0;
  border-radius: var(--radius-xs);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background-color 0.15s ease;
}

.offer__claim:hover {
  background: var(--brand-bright);
}

.offer__claim:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.offer__claim:disabled {
  opacity: 0.7;
  cursor: default;
}

/* What the customer reads down the phone. Loud on purpose. */
.offer__code {
  margin-top: 0.7rem;
  padding: 0.7rem 0.5rem;
  text-align: center;
  background: var(--surface);
  border: 2px dashed var(--brand);
  border-radius: var(--radius-xs);
}

.offer__code-value {
  display: block;
  font-family: var(--font-mono);
  font-size: 1.6rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  line-height: 1.15;
  color: var(--brand);
}

.offer__code-label {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.75rem;
  font-style: italic;
  line-height: 1.35;
  color: var(--ink-soft);
}
