/* --------------------------------------------------------------------------
   Tokens
   -------------------------------------------------------------------------- */
:root {
  --ink: #111111;
  --ink-soft: #6d6d6d;
  --well: #eeedea;
  --page: #ffffff;

  /* Taken from the Em logo artwork so the band and the mark are the same ink. */
  --navy: #0d1f3c;
  --navy-ink: #ffffff;
  --navy-ink-soft: rgba(255, 255, 255, 0.62);

  --page-pad: 1rem;
  --col-gap: 1.25rem;
  --row-gap: 3rem;

  --type-ui: 0.75rem;
  --track: 0.04em;

  --font:
    "Helvetica Neue", Helvetica, "Inter", -apple-system, BlinkMacSystemFont,
    "Segoe UI", Arial, sans-serif;
}

@media (min-width: 900px) {
  :root {
    --page-pad: 1.5rem;
    --col-gap: 3rem;
    --row-gap: 4.5rem;
    --type-ui: 0.8125rem;
  }
}

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  padding: 0 var(--page-pad) 6rem;
  background: var(--page);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--type-ui);
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
p {
  margin: 0;
  font-size: inherit;
  font-weight: 400;
}

img {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
  text-decoration: none;
}

:focus-visible {
  outline: 1px solid var(--ink);
  outline-offset: 3px;
}

/* Read aloud, never drawn. Used for the word behind the ~ on a converted
   price, so a screen reader hears "about" rather than "tilde". */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
}

.skip-link:focus {
  left: var(--page-pad);
  top: 0.5rem;
  z-index: 10;
  background: var(--page);
  padding: 0.5rem 0.75rem;
  letter-spacing: var(--track);
  text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   Masthead
   -------------------------------------------------------------------------- */
/* The band runs the full width of the viewport, so it cancels the page padding
   with a negative margin and puts the same value back as its own padding. */
/* Name on the left, Em's mark on the right. Nothing else sits on the band. */
.masthead {
  /* The mark is sized off the title so the pair stays in proportion. */
  --title-size: clamp(1.75rem, 6vw, 3.75rem);

  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 2rem;
  margin: 0 calc(var(--page-pad) * -1) 2.5rem;
  padding: 3rem var(--page-pad);
  background: var(--navy);
  color: var(--navy-ink);
}

@media (min-width: 900px) {
  .masthead {
    margin-bottom: 3.5rem;
    padding: 4rem var(--page-pad);
  }
}

.masthead__title {
  text-transform: uppercase;
  /* Large type needs far less tracking than the small caps elsewhere. */
  letter-spacing: 0.015em;
  line-height: 0.98;
  font-size: var(--title-size);
  color: var(--navy-ink);
  /* A flex item will not shrink below its own content without this, so on a
     phone the title runs off the band instead of wrapping. */
  min-width: 0;
}

/* Both dimensions are stated. An inline svg carrying only a viewBox has no
   intrinsic width, so leaving width on auto collapses it to nothing.
   1.747 is the mark's own ratio, 290 wide over 166 tall. */
.masthead__mark {
  flex: none;
  height: calc(var(--title-size) * 0.62);
  width: calc(var(--title-size) * 0.62 * 1.747);
}

.masthead__mark[hidden] {
  display: none;
}

/* --------------------------------------------------------------------------
   Toolbar
   -------------------------------------------------------------------------- */
.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 2rem;
  padding-bottom: 2rem;
}

/* Filters, then All and Saved, hard against the left edge. */
.toolbar__start {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.75rem;
}

/* Below 900px the grid picks its own columns, so the control would be a set of
   buttons that change nothing. It appears at the width where it starts to
   matter, which is the same width the grid reads data-cols at. */
.density {
  display: none;
  align-items: center;
  gap: 1rem;
}

@media (min-width: 900px) {
  .density {
    display: flex;
  }
}

/* Says what the numbers do. Set apart from them so the group reads as one
   label followed by three choices, not as four things in a row. */
.density__label {
  margin-right: 0.35rem;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: var(--track);
}

.density__button {
  display: flex;
  margin: 0;
  padding: 0 0 4px;
  border: 0;
  border-bottom: 1px solid transparent;
  background: none;
  color: var(--ink-soft);
  font: inherit;
  cursor: pointer;
  transition:
    color 0.2s ease,
    border-color 0.2s ease;
}

/* Block, so the button is exactly as tall as the drawing and the underline
   sits tight beneath it. An inline svg would carry a text baseline gap. */
.density__icon {
  display: block;
  width: 16px;
  height: 12px;
  fill: currentColor;
  /* The click belongs to the button. Without this the target of a click is a
     rect inside the svg, and the handler has to walk back up to find it. */
  pointer-events: none;
}

.density__button[aria-pressed="true"] {
  color: var(--ink);
  border-bottom-color: var(--ink);
  cursor: default;
}

.views {
  display: flex;
  gap: 1.75rem;
}

.nav-link {
  text-transform: uppercase;
  letter-spacing: var(--track);
  color: var(--ink-soft);
  padding-bottom: 2px;
  border-bottom: 1px solid transparent;
  transition:
    color 0.2s ease,
    border-color 0.2s ease;
}

.nav-link[aria-current="page"] {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

.nav-link__count,
.filters-toggle__count {
  margin-left: 0.4em;
  font-variant-numeric: tabular-nums;
}

.nav-link__count[hidden],
.filters-toggle__count[hidden] {
  display: none;
}

.filters-toggle {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin: 0;
  padding: 0 0 2px;
  border: 0;
  border-bottom: 1px solid transparent;
  background: none;
  color: var(--ink-soft);
  font: inherit;
  text-transform: uppercase;
  letter-spacing: var(--track);
  cursor: pointer;
  transition:
    color 0.2s ease,
    border-color 0.2s ease;
}

/* Open, or narrowing something, reads as the current state. */
.filters-toggle[aria-expanded="true"],
.filters-toggle:has(.filters-toggle__count:not([hidden])) {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

.filters-toggle__icon {
  flex: none;
  width: 16px;
  height: 12px;
  fill: currentColor;
}

/* --------------------------------------------------------------------------
   Filter drawer
   -------------------------------------------------------------------------- */
.drawer-scrim {
  position: fixed;
  inset: 0;
  z-index: 20;
  background: rgba(17, 17, 17, 0.3);
}

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

.drawer {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 21;
  display: flex;
  flex-direction: column;
  width: min(22rem, 88vw);
  height: 100%;
  background: var(--page);
  /* The one hard edge on the page, and only because the panel sits over the
     grid and needs to be told apart from it. */
  border-right: 1px solid var(--ink);
}

.drawer[hidden] {
  display: none;
}

/* Holds the page still while the panel is over it. */
body.has-drawer {
  overflow: hidden;
}

.drawer__head {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.5rem var(--page-pad);
  border-bottom: 1px solid var(--well);
}

/* Clear all and Close, kept together on the right so the title still owns the
   left edge and the two controls read as a pair. */
.drawer__actions {
  display: flex;
  align-items: center;
  gap: 1.5rem;
}

.drawer__title {
  text-transform: uppercase;
  letter-spacing: var(--track);
}

.drawer__close,
.drawer__clear {
  margin: 0;
  padding: 0 0 2px;
  border: 0;
  border-bottom: 1px solid var(--ink);
  background: none;
  color: var(--ink);
  font: inherit;
  text-transform: uppercase;
  letter-spacing: var(--track);
  cursor: pointer;
}

.drawer__clear:disabled {
  border-bottom-color: transparent;
  color: var(--ink-soft);
  cursor: default;
}

.drawer__body {
  flex: 1;
  overflow-y: auto;
  padding: 0 var(--page-pad);
}

.facet {
  margin: 0;
  padding: 1.5rem 0;
  border: 0;
  border-bottom: 1px solid var(--well);
}

.facet:last-child {
  border-bottom: 0;
}

.facet__title {
  display: block;
  margin-bottom: 0.85rem;
  padding: 0;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: var(--track);
}

.facet__options {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.facet__option {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  cursor: pointer;
}

.facet__checkbox {
  flex: none;
  width: 13px;
  height: 13px;
  margin: 0;
  accent-color: var(--navy);
  cursor: pointer;
}

.facet__name {
  flex: 1;
  min-width: 0;
}

.facet__count {
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}

/* Native select, styled down to one rule so it stays keyboard and screen
   reader friendly without importing anything. */
.drawer__select {
  appearance: none;
  width: 100%;
  margin: 0;
  padding: 0.3rem 1.5rem 0.3rem 0;
  border: 0;
  border-bottom: 1px solid var(--ink);
  border-radius: 0;
  background: transparent;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--ink) 50%),
    linear-gradient(135deg, var(--ink) 50%, transparent 50%);
  background-position:
    right 0.5rem center,
    right 0.25rem center;
  background-size:
    5px 5px,
    5px 5px;
  background-repeat: no-repeat;
  color: var(--ink);
  font: inherit;
  text-transform: uppercase;
  letter-spacing: var(--track);
  cursor: pointer;
}

/* Show more on a long facet. Reads as a control rather than a filter row, so it
   is left aligned with the options and underlined instead of boxed. */
.facet__more {
  display: block;
  margin: 0.6rem 0 0;
  padding: 0.2rem 0;
  border: 0;
  border-bottom: 1px solid var(--ink);
  background: none;
  color: var(--ink);
  font: inherit;
  text-transform: uppercase;
  letter-spacing: var(--track);
  cursor: pointer;
}

/* The last line under the list, and the only thing below the grid now that the
   whole list renders at once. It carries the gap the pager used to hold. */
.result-count {
  padding-top: 4rem;
  color: var(--ink-soft);
  text-align: center;
  text-transform: uppercase;
  letter-spacing: var(--track);
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   Grid
   -------------------------------------------------------------------------- */
.grid {
  display: grid;
  grid-template-columns: 1fr;
  column-gap: var(--col-gap);
  row-gap: var(--row-gap);
}

@media (min-width: 560px) {
  .grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* How many fit across is the visitor's choice once there is room for it. Each
   count is written out rather than driven off a variable, so what the markup
   asks for and what the layout does are the same thing. */
@media (min-width: 900px) {
  .grid[data-cols="2"] {
    grid-template-columns: repeat(2, 1fr);
  }

  .grid[data-cols="3"] {
    grid-template-columns: repeat(3, 1fr);
  }

  .grid[data-cols="4"] {
    grid-template-columns: repeat(4, 1fr);
    /* Four across leaves less room, so the gutters come in with it. */
    column-gap: 2rem;
  }
}

/* --------------------------------------------------------------------------
   Product
   -------------------------------------------------------------------------- */
.product {
  position: relative;
}

.product__media {
  background: var(--well);
  aspect-ratio: 2 / 3;
  overflow: hidden;
}

.product__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: opacity 0.35s ease;
}

.product__image[hidden] {
  display: none;
}

.product__info {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding-top: 0.9rem;
}

.product__text {
  min-width: 0;
}

.product__brand {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.35rem;
  color: var(--ink-soft);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.product__brand:empty,
.product__brand.is-empty {
  display: none;
}

.product__logo {
  width: auto;
  height: 14px;
  max-width: 72px;
  object-fit: contain;
  object-position: left center;
}

.product__logo[hidden] {
  display: none;
}

.product__name {
  text-transform: uppercase;
  letter-spacing: var(--track);
}

/* The link is stretched across the whole product so the image, the name and
   the information block all open the retailer. The heart sits above it. */
.product__link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.product__price {
  color: var(--ink);
}

/* The retailer's own wording, kept under the translated name and the converted
   price so the source is never lost. */
.product__original,
.product__price-original,
.product__meta,
.product__note {
  color: var(--ink-soft);
}

.product__original:empty,
.product__price-original:empty,
.product__meta:empty,
.product__note:empty {
  display: none;
}

.product__original {
  margin-bottom: 0.25rem;
}

.product__note {
  margin-top: 0.35rem;
}

/* Available colourways, shown as small squares under the price. */
.product__colors {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-top: 0.55rem;
}

.product__colors[hidden] {
  display: none;
}

.product__swatch {
  width: 11px;
  height: 11px;
  flex: none;
  box-shadow: inset 0 0 0 1px rgba(17, 17, 17, 0.16);
}

@media (hover: hover) {
  .product__link {
    cursor: pointer;
  }

  .product:hover .product__image {
    opacity: 0.82;
  }
}

.product__link:focus-visible {
  outline: none;
}

.product__link:focus-visible::after {
  outline: 1px solid var(--ink);
  outline-offset: 6px;
}

/* --------------------------------------------------------------------------
   Heart
   -------------------------------------------------------------------------- */
.product__save {
  position: relative;
  z-index: 2;
  flex: none;
  margin: -0.5rem -0.5rem 0 0;
  padding: 0.5rem;
  border: 0;
  background: none;
  color: var(--ink);
  cursor: pointer;
  line-height: 0;
  -webkit-tap-highlight-color: transparent;
}

.product__heart {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linejoin: round;
  transition:
    fill 0.18s ease,
    transform 0.18s ease;
}

.product__save[aria-pressed="true"] .product__heart {
  fill: currentColor;
}

.product__save.is-pulsing .product__heart {
  transform: scale(1.18);
}

/* --------------------------------------------------------------------------
   Messages
   -------------------------------------------------------------------------- */
.feedback {
  color: var(--ink-soft);
  padding: 1rem 0 4rem;
}

.status {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}
