@import url("tokens.css");

/* Layout and components. Every value here comes from tokens.css - no colour
   literal appears in this file, which is what keeps a palette change a
   one-file edit. */

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: var(--text-body);
  line-height: 1.5;
  padding-block-end: calc(var(--bottom-nav-h) + 28px + env(safe-area-inset-bottom, 0px));
}

h1,
h2,
h3 {
  font-family: var(--font-ui);
  line-height: 1.3;
  margin: 0;
}

p {
  margin: 0;
}

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

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

button {
  font: inherit;
  color: inherit;
}

/* Anything carrying the hidden attribute stays hidden, whatever display its
   own class would otherwise give it. A count badge with a display value from
   a class is the case this exists for. */
[hidden] {
  display: none !important;
}

/* Accessibility */
.skip-link {
  position: absolute;
  inset-inline-start: -9999px;
  top: 10px;
  z-index: 100;
  background: var(--pink-ink);
  color: var(--surface);
  padding: 10px 16px;
  border-radius: var(--radius-pill);
}

.skip-link:focus {
  inset-inline-start: var(--gutter);
}

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

.visually-hidden {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Shell ------------------------------------------------------------------ */
.shell {
  min-block-size: 100vh;
  display: flex;
  flex-direction: column;
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--surface);
  box-shadow: var(--shadow-header);
}

/* min-inline-size: 0 is what lets the flex children below actually shrink. A
   flex item defaults to min-content, which is why the language toggle was
   overflowing the header rather than fitting into it. */
.site-header__inner {
  display: flex;
  align-items: center;
  gap: 8px;
  min-inline-size: 0;
  block-size: var(--header-h);
  max-inline-size: var(--cap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Brand: the supplied logo, then the name. The logo file has a white ground,
   so it needs no disc behind it - and deliberately none of the pale pink
   circles the older directions described. */
.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-inline-end: auto;
  min-inline-size: 0;
}

.wordmark__logo {
  inline-size: var(--logo);
  block-size: var(--logo);
  object-fit: contain;
  flex: 0 0 auto;
}

.wordmark__name {
  font-weight: 800;
  font-size: 18px;
  letter-spacing: 1.5px;
  color: var(--ink);
  white-space: nowrap;
}

/* Header icon buttons */
.icon-btn {
  display: grid;
  place-items: center;
  inline-size: var(--tap);
  block-size: var(--tap);
  border: 0;
  background: none;
  border-radius: var(--radius-pill);
  color: var(--ink);
  cursor: pointer;
  position: relative;
  flex: 0 0 auto;
  transition: background var(--transition-quick);
}

.icon-btn:hover {
  background: var(--pink-tint);
}

.icon-btn svg {
  inline-size: 22px;
  block-size: 22px;
}

/* A count badge is never colour alone: it is a filled disc carrying a number,
   and the accessible label reads the count as words. */
.icon-btn__badge {
  position: absolute;
  inset-block-start: 4px;
  inset-inline-end: 4px;
  min-inline-size: 18px;
  block-size: 18px;
  padding-inline: 4px;
  display: grid;
  place-items: center;
  background: var(--pink);
  color: var(--on-accent);
  border-radius: var(--radius-pill);
  font-size: 10px;
  font-weight: 800;
}

/* Language toggle */
.lang-toggle {
  display: inline-flex;
  padding: 3px;
  gap: 3px;
  background: var(--pink-tint);
  border-radius: var(--radius-pill);
  flex: 0 0 auto;
  min-inline-size: 0;
}

.lang-toggle__option {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: 38px;
  padding-inline: 10px;
  border-radius: var(--radius-pill);
  color: var(--ink-muted);
  font-size: var(--text-meta);
  font-weight: 700;
  white-space: nowrap;
  transition: background var(--transition-quick), color var(--transition-quick);
}

/* The full word is hidden on narrow screens and the short form shown instead,
   so the control fits without shrinking below a 44px target. */
.lang-toggle__short {
  display: none;
}

/* Active state carries weight and a hairline as well as the fill, so it
   survives greyscale and a colour-blind viewer. */
.lang-toggle__option.is-active {
  background: var(--pink);
  color: var(--on-accent);
  box-shadow: inset 0 0 0 1px var(--pink-ink);
}

/* Main -------------------------------------------------------------------- */
.main {
  flex: 1;
  inline-size: 100%;
  max-inline-size: var(--cap);
  margin-inline: auto;
  padding: 14px var(--gutter) 32px;
}

/* Category chips ---------------------------------------------------------- */
.chips {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding-block: 4px 12px;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

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

/* 44px target including the chip's own padding. */
.chip {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  min-block-size: var(--tap);
  padding-inline: 15px;
  border-radius: var(--radius-chip);
  background: var(--surface);
  border: 1px solid var(--line);
  color: var(--ink-muted);
  font-size: var(--text-meta);
  font-weight: 700;
  white-space: nowrap;
  transition: background var(--transition-quick), color var(--transition-quick);
}

.chip:hover {
  border-color: var(--pink-line);
}

/* Selected chip: pink-soft fill, pink-ink text, and a weight change. */
.chip.is-active {
  background: var(--pink-soft);
  border-color: var(--pink-line);
  color: var(--pink-ink);
  font-weight: 800;
}

/* Section heading --------------------------------------------------------- */
.section-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-block: 4px 12px;
}

.section-head__title {
  font-size: 19px;
  font-weight: 800;
}

.section-head__count {
  color: var(--ink-muted);
  font-size: var(--text-meta);
}

/* Product grid ------------------------------------------------------------ */
.grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap-grid);
}

@media (min-width: 600px) {
  .grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

@media (min-width: 1440px) {
  .grid {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

/* Product card ------------------------------------------------------------ */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: var(--gap-grid);
  transition: box-shadow var(--transition-std);
}

.card:hover {
  box-shadow: var(--shadow-card-hover);
}

.card__link {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  color: inherit;
  text-decoration: none;
}

/* 4:5 portrait. The ratio lives on the box, so the card does not reflow as
   the image arrives - and width/height attributes on the img give the browser
   the same information before the bytes land. */
.card__media {
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: var(--radius-img);
  overflow: hidden;
  background: var(--pink-tint);
}

.card__img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

.card__placeholder {
  inline-size: 100%;
  block-size: 100%;
  display: grid;
  place-items: center;
  color: var(--pink-line);
}

.card__placeholder svg {
  inline-size: 40%;
  block-size: auto;
}

/* Save control: a full 44x44 target even though the visible heart is smaller.
   The amendment names this as the element most likely to be built undersized. */
.card__save {
  position: absolute;
  inset-block-start: 4px;
  inset-inline-end: 4px;
  z-index: 2;
  inline-size: var(--tap);
  block-size: var(--tap);
  display: grid;
  place-items: center;
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--pink-ink);
  cursor: pointer;
  border-radius: var(--radius-pill);
}

.card__save-glyph {
  display: grid;
  place-items: center;
  inline-size: 32px;
  block-size: 32px;
  border-radius: var(--radius-pill);
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-card);
  overflow: visible;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}

.card__save-glyph svg {
  inline-size: 17px;
  block-size: 17px;
  overflow: visible;
}

/* Saved state carries a Rose Pink fill (#f79cb0 / var(--pink)) and soft pink
   border (#fed0d2 / var(--pink-line)) without clipping or border distortion. */
.card__save.is-saved .card__save-glyph {
  background: var(--pink-tint);
  border-color: var(--pink-line);
  color: var(--pink);
}

.card__save .heart-filled {
  display: none;
}

.card__save.is-saved .heart-outline {
  display: none;
}

.card__save.is-saved .heart-filled {
  display: block;
  fill: var(--pink);
  stroke: var(--pink);
}

/* Badge: white pill, pink-ink text. Not a pink fill - the mockup reserves the
   pink fill for the save heart and the discount case only. */
.card__badge {
  position: absolute;
  inset-block-start: 8px;
  inset-inline-start: 8px;
  padding: 4px 9px;
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--pink-ink);
  font-size: var(--text-badge);
  font-weight: 800;
  letter-spacing: 0.5px;
  text-transform: uppercase;
}

.card__body {
  padding: 10px 2px 2px;
}

/* Two lines, then truncate. A card that grows to three lines breaks the row
   rhythm of the whole feed. */
.card__name {
  font-size: var(--text-name);
  font-weight: 600;
  line-height: 1.35;
  color: var(--ink);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Price sits directly under the name, larger than body text, with no rule
   between them. A divider here was V2's treatment and is deliberately absent. */
.card__price {
  font-family: var(--font-price);
  font-size: var(--text-price);
  font-weight: 700;
  color: var(--pink-ink);
  margin-block-start: 3px;
}

/* Out of stock is shown, never hidden: a labelled product teaches the
   catalogue's depth, a hidden one teaches nothing. */
.card.is-out .card__media {
  opacity: 0.55;
}

.card__stock {
  margin-block-start: 3px;
  font-size: var(--text-meta);
  font-weight: 700;
  color: var(--warn);
}

.card.is-out .card__stock {
  color: var(--danger);
}

.card__cart-btn {
  margin-block-start: 8px;
  inline-size: 100%;
  min-block-size: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--radius-pill);
  background: var(--pink-tint);
  color: var(--pink-ink);
  border: 1px solid var(--pink-line);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  transition: all var(--transition-quick);
  text-decoration: none;
}

.card__cart-btn:hover {
  background: var(--pink-soft);
  color: var(--pink-ink);
  border-color: var(--pink-line);
  box-shadow: 0 2px 10px rgba(138, 74, 88, 0.15);
}

.card__cart-btn:active {
  transform: scale(0.97);
}

.card__cart-btn svg {
  flex-shrink: 0;
  inline-size: 15px;
  block-size: 15px;
}

/* Load more --------------------------------------------------------------- */
.load-more {
  display: flex;
  justify-content: center;
  margin-block-start: 24px;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: var(--tap);
  padding-inline: 22px;
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
  font-weight: 800;
  cursor: pointer;
  transition: background var(--transition-quick);
}

/* Dark ink on the pink fill. White here measures 2.9:1 and fails WCAG AA -
   the specification's C01 amendment corrects it and the mockup agrees. */
.btn--primary {
  background: var(--pink);
  color: var(--on-accent);
}

.btn--primary:hover {
  background: var(--pink-soft);
}

.btn:disabled {
  background: var(--pink-line);
  color: var(--ink-muted);
  cursor: default;
}

.btn--ghost {
  background: var(--surface);
  border-color: var(--line);
  color: var(--ink);
}

/* Empty state ------------------------------------------------------------- */
.empty {
  background: var(--surface);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 40px 20px;
  text-align: center;
}

.empty__title {
  font-size: 17px;
  font-weight: 800;
}

.empty__body {
  margin-block-start: 6px;
  color: var(--ink-muted);
  font-size: var(--text-meta);
}

.empty__action {
  margin-block-start: 18px;
}

/* Footer ------------------------------------------------------------------ */
.site-footer {
  border-block-start: 1px solid var(--line);
  margin-block-start: 32px;
}

.site-footer__inner {
  max-inline-size: var(--cap);
  margin-inline: auto;
  padding: 20px var(--gutter);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.site-footer__note,
.site-footer__link {
  color: var(--ink-muted);
  font-size: var(--text-meta);
}

.site-footer__link:hover {
  color: var(--pink-ink);
}

/* Bottom navigation (mobile) ---------------------------------------------- */
.bottom-nav {
  position: fixed;
  inset-inline: 14px;
  inset-block-end: calc(14px + env(safe-area-inset-bottom, 0px));
  z-index: 30;
  block-size: var(--bottom-nav-h);
  max-inline-size: 460px;
  margin-inline: auto;
  background: rgba(255, 255, 255, 0.96);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--line);
  border-radius: 26px;
  box-shadow: 0 4px 20px rgba(138, 74, 88, 0.12), 0 2px 6px rgba(0, 0, 0, 0.05);
}

.bottom-nav__inner {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  block-size: 100%;
  max-inline-size: var(--cap);
  margin-inline: auto;
  align-items: center;
}

/* DOM order is Home, Store, Wishlist, Cart. Grid mirrors it under RTL
   automatically - never reverse the list in JavaScript. */
.bottom-nav__link {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-block-size: var(--tap);
  color: var(--ink-muted);
  font-size: 11px;
  font-weight: 600;
  position: relative;
  transition: color var(--transition-quick);
}

.bottom-nav__link svg {
  inline-size: 22px;
  block-size: 22px;
}

/* Active tab: pink-soft pill, 800 weight label, and a 2px indicator bar.
   Three signals, so state is never carried by colour alone. */
.bottom-nav__link.is-active {
  color: var(--pink-ink);
  font-weight: 800;
}

.bottom-nav__link.is-active .bottom-nav__glyph {
  background: var(--pink-soft);
}

.bottom-nav__glyph {
  display: grid;
  place-items: center;
  inline-size: 38px;
  block-size: 26px;
  border-radius: var(--radius-pill);
  transition: background var(--transition-quick);
}

/* Header navigation: icons only ------------------------------------------------- */
.header-nav {
  display: none;
  gap: 2px;
  align-items: center;
}

/* Home icon is excluded on desktop because the brand wordmark links home */
.header-nav a[href="/"] {
  display: none !important;
}

/* The active destination carries a soft pill and a weight change; the icon
   itself thickens because stroke-width is set per state, so this is not
   colour alone. */
.header-nav__icon.is-active {
  background: var(--pink-soft);
  color: var(--pink-ink);
}

.header-nav__icon.is-active::before {
  content: "";
  position: absolute;
  inset-block-end: 6px;
  inset-inline: 30%;
  block-size: 2px;
  border-radius: var(--radius-pill);
  background: var(--pink-ink);
}

/* Mobile header ----------------------------------------------------------- */
/* Below 700px the header keeps the logo and the actions a phone actually
   needs. The brand text and the secondary icons are dropped, and the language
   toggle switches to short labels, because two full words plus two icon
   buttons do not fit in a 414px row and the toggle was rendering past the
   container edge. */
@media (max-width: 699px) {
  .site-header .wordmark__name,
  .site-header .header-nav,
  .site-header .header-desktop-only {
    display: none;
  }

  .site-header__inner {
    display: grid;
    grid-template-columns: var(--tap) var(--tap) minmax(0, 1fr);
    gap: 6px;
    padding-inline: 12px;
  }

  .site-header .wordmark {
    margin-inline-end: 0;
  }

  .site-header .lang-toggle {
    justify-self: end;
  }

  /* Full words are hidden and the two-letter forms shown, with the full word
     kept as the element's own text for anyone reading it aloud. */
  .lang-toggle__long {
    display: none;
  }

  .lang-toggle__short {
    display: inline;
  }

  .site-header .lang-toggle__option {
    min-block-size: var(--tap);
    min-inline-size: var(--tap);
    padding-inline: 8px;
    font-size: 12px;
  }
}

/* One breakpoint moves the navigation from the bottom bar to the header. */
@media (min-width: 700px) {
  .header-nav {
    display: flex;
  }

  .bottom-nav {
    display: none;
  }

  body {
    padding-block-end: 0;
  }
}

/* Error and placeholder pages --------------------------------------------- */
.panel {
  background: var(--surface);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 32px 24px;
  max-inline-size: 34rem;
  margin-inline: auto;
  text-align: center;
}

.panel__title {
  font-size: 22px;
  font-weight: 800;
}

.panel__body {
  margin-block: 8px 20px;
  color: var(--ink-muted);
}
