/* Public distributor directory. */

.directory-hero {
  text-align: center;
  margin-bottom: clamp(24px, 4vw, 38px);
}

.directory-hero .lede {
  max-width: 40rem;
  margin-inline: auto;
  margin-bottom: 22px;
}

/* Search, role and submit read as one control rather than three. */
/* Local / International.
 *
 * A segmented pair rather than two pills loose on the background: they are two
 * halves of one choice, and the frame around them says only one can be on. Sits
 * above the search bar and borrows its shape, so the hero reads as one stack of
 * controls rather than unrelated widgets. Centred by the hero's text-align. */
.directory-tabs {
  display: inline-flex;
  gap: 4px;
  margin: 0 0 12px;
  padding: 4px;
  background: rgba(255, 255, 255, .82);
  border: 1px solid rgba(255, 255, 255, .9);
  border-radius: 999px;
  box-shadow: var(--shadow-sm);
}

.directory-tab {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 18px;
  border-radius: 999px;
  color: var(--ink-soft);
  font-size: 14px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  transition: background .18s var(--ease), color .18s var(--ease);
}

.directory-tab:hover { background: var(--pink-wash); color: var(--ink); }
.directory-tab.is-on { background: var(--pink); color: #fff; }
.directory-tab.is-on:hover { background: var(--pink-deep); color: #fff; }

/* The second half of the label rather than a badge stuck onto it. */
.directory-tab-count {
  min-width: 20px;
  padding: 1px 6px;
  border-radius: 999px;
  background: rgba(43, 31, 69, .08);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.directory-tab.is-on .directory-tab-count { background: rgba(255, 255, 255, .26); }

.directory-search {
  display: flex;
  gap: 6px;
  align-items: center;
  max-width: 38rem;
  margin: 0 auto 12px;
  padding: 6px;
  background: rgba(255, 255, 255, .82);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(255, 255, 255, .9);
  border-radius: 999px;
  box-shadow: var(--shadow);
}

.directory-search input[type=search],
.directory-search select {
  border: 0;
  /* background-color, not background: the shorthand also clears background-image,
     which is where the select's chevron lives. */
  background-color: transparent;
  box-shadow: none;
  border-radius: 999px;
}

/* Divider between the two fields, since they no longer have borders. */
.directory-search select {
  border-left: 1px solid var(--pink-line);
  padding-left: 15px;
}

/* A flex item beside the field rather than floated over it.
   Overlaying it would mean padding the input out of its way, and the global
   input rule in app.css carries seven :not()s — enough specificity that a
   padding override here loses. This sidesteps that argument entirely, and the
   icon can never end up sitting on top of the text. */
.directory-search-ico {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin-left: 12px;
  color: var(--muted);
  pointer-events: none;
}

.directory-search input[type=search] { flex: 1 1 12rem; min-width: 0; }
.directory-search select { flex: 0 0 auto; width: auto; max-width: 12rem; padding-right: 36px; }
.directory-search input:focus, .directory-search select:focus {
  box-shadow: var(--ring);
  background-color: #fff;
}
.directory-search .btn { flex: 0 0 auto; }
.directory-search .btn.ghost { box-shadow: none; }

.directory-count {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
}

.directory-count .sj-icon {
  width: 16px;
  height: 16px;
  color: var(--pink);
}

/* The number picked out, because it is the one part of this line anybody
   reads. */
.directory-count b {
  color: var(--pink);
  font-weight: 700;
}

.directory-grid {
  display: grid;
  /* min(400px, 100%), not a bare 400px. A bare minimum forces the track to
     400px even when the container is narrower, so on a phone the grid was
     wider than the screen and the whole page scrolled sideways — which reads
     as the page being zoomed in rather than as a layout fault. */
  grid-template-columns: repeat(auto-fill, minmax(min(400px, 100%), 1fr));
  gap: clamp(14px, 2vw, 20px);
  align-items: start;
}

/* Landscape card: the ID on the left, the details that let someone actually
   make contact on the right. A square card put the useful part below the fold
   on a phone. */
.directory-card {
  display: grid;
  grid-template-columns: 190px minmax(0, 1fr);
  grid-template-areas: 'media meta';
  gap: 0 18px;
  padding: 16px;
  background: var(--surface);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(255, 255, 255, .85);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  transition: transform .22s var(--ease), box-shadow .22s var(--ease);
}

.directory-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); }

/* The band the offices sit in, above the sellers.
 *
 * A heading and a rule rather than a boxed panel: wrapping two cards in a
 * container of their own made them look like a callout advertising something
 * rather than like the top of the list.
 */
.directory-team { margin: 0 0 clamp(20px, 3vw, 30px); }

.directory-team-head {
  margin: 0 0 12px;
  padding: 0 0 10px 14px;
  /* The one plum edge on the page, and it is on the heading rather than on the
     cards: it marks where the band starts without putting a stripe down two
     records that are otherwise the same as every other. */
  border-left: 4px solid var(--ink-soft);
  border-bottom: 1px solid rgba(74, 59, 102, .14);
}

.directory-team-head h2 {
  margin: 0;
  font-size: clamp(15px, 2vw, 17px);
  font-weight: 800;
  letter-spacing: .02em;
  color: var(--ink);
}

.directory-team-head p {
  margin: 3px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--muted);
}

/* The two company offices.
 *
 * Their card is the same card. It carried a plum edge down its left side and a
 * wash behind the top of it, on the reasoning that an office is not the same
 * kind of thing as a seller and the card should say so - but the band above it
 * is already headed The S&J Beauty team and names them, so the edge was the
 * third thing on screen making the same point, and two cards carrying a stripe
 * nobody else has read as flagged rather than as senior.
 *
 * What is left is the role line in plum where a seller's is pink. It is the
 * quietest version of the distinction: it marks the one field that actually
 * differs instead of drawing a box around the whole record.
 */
.directory-card.is-office .directory-role { color: var(--ink-soft); }

.directory-card-media { grid-area: media; position: relative; }

.directory-thumb {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: none;
  cursor: zoom-in;
}

.directory-card img {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background: var(--pink-wash);
  transition: transform .4s var(--ease);

  /* Discourages drag-to-desktop and long-press-to-save. Not a control — the
     protection is that the file behind this URL is already watermarked and
     downscaled — but it removes the easiest route. */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  pointer-events: none;
}

.directory-card:hover img { transform: scale(1.05); }

.directory-thumb-hint {
  position: absolute;
  inset: auto 0 0 0;
  padding: 20px 10px 8px;
  background: linear-gradient(180deg, rgba(43, 31, 69, 0), rgba(43, 31, 69, .66));
  color: #fff;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .03em;
  opacity: 0;
  transition: opacity .22s var(--ease);
}

.directory-card:hover .directory-thumb-hint,
.directory-thumb:focus-visible .directory-thumb-hint { opacity: 1; }

/* Reads as a stamp on the ID rather than a label beside it. */
.directory-stamp {
  position: absolute;
  top: 8px;
  left: 8px;
  padding: 4px 10px;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--pink-soft), var(--pink));
  color: #fff;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
  box-shadow: 0 3px 10px rgba(254, 81, 130, .4);
}

.directory-meta { grid-area: meta; min-width: 0; }

.directory-name {
  margin: 2px 0 0;
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -.01em;
  line-height: 1.25;
  /* Capitals, per the annotation — applied here rather than in the database so
     rows saved before the fields were upper-cased still read consistently. */
  text-transform: uppercase;
}

/* The line the directory exists for: not who they are but what they are
   authorized as, which is the thing a buyer is checking. It was the smallest
   type on the card, under a name set half again as large. */
.directory-role {
  margin: 6px 0 0;
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--pink);
}

.directory-location {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 7px 0 0;
  font-size: 12.5px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .02em;
}

/* The lightbox subtitle is the same two values joined. */
#directory-preview-role { text-transform: uppercase; }

.directory-ico {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--pink-wash);
  color: var(--pink);
  font-size: 10px;
  font-weight: 800;
  line-height: 1;
}

/* Number and seller-since share a row, divided by a thin bar.
 *
 * The two are unrelated — one is how to reach them, the other how long they
 * have sold — so the bar is doing real work separating them, and it wraps
 * rather than squeezing when the card is narrow. */
.directory-contact-line {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 10px;
}

.directory-since {
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
}

/* The divider is drawn on the seller-since rather than sitting between the two
   as its own element.
 *
 * The meta column of a card is about 190px, which the number and this together
 * overrun, so the pair wraps. As a separate element the bar was left stranded
 * at the end of the number's line, pointing at nothing. Attached here it goes
 * wherever the text it divides goes, and it is generated content, so a screen
 * reader is not read a punctuation mark between two unrelated facts. */
.directory-since::before {
  content: '|';
  margin-inline-end: 9px;
  color: var(--pink-line);
  font-weight: 400;
}

.directory-contact {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--pink-line);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.directory-contact-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink-soft);
  text-decoration: none;
  border-radius: 8px;
}

.directory-contact-row:hover { color: var(--pink); }
.directory-contact-row.is-facebook:hover { color: #1877f2; }
.directory-contact-row.is-facebook:hover .directory-ico { background: #e7f0ff; color: #1877f2; }

/*
 * Real icons rather than whichever character came closest.
 *
 * The location was a filled circle standing in for a pin, the phone a Unicode
 * telephone and Facebook a lowercase f — three different kinds of thing in one
 * column. These are Font Awesome glyphs from the two faces the app already
 * loads for the ID artwork, so the set costs nothing new and matches the marks
 * on the chips below.
 */
.directory-ico.is-pin,
.directory-ico.is-phone {
  font-family: 'SJ Icons';
  font-weight: 900;
  font-size: 10px;
}

.directory-ico.is-facebook {
  font-family: 'SJ Icons Brand';
  font-weight: 400;
  font-size: 11px;
}

.directory-ico.is-pin::before { content: '\f3c5'; }
.directory-ico.is-phone::before { content: '\f095'; }
.directory-ico.is-facebook::before { content: '\f39e'; }

/* In the card's own column now, under the contact details, rather than across
   the foot of the card. Unlabelled: a row of platform marks says "these are the
   shops" without a heading saying so. */
.directory-links {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--pink-line);
}

/* The contact block already draws the rule above itself, so a second one
   directly beneath it would be two lines with one row between them. */
.directory-contact + .directory-links {
  margin-top: 10px;
  padding-top: 0;
  border-top: 0;
}

.directory-link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 12px 5px 8px;
  border-radius: 999px;
  border: 1px solid var(--pink-line);
  background: rgba(255, 255, 255, .9);
  color: var(--ink-soft);
  font-size: 12px;
  font-weight: 700;
  text-decoration: none;
  transition: background .16s var(--ease), border-color .16s var(--ease), color .16s var(--ease);
}

/*
 * The platform's own mark, cut from the ID artwork rather than drawn again.
 * Font Awesome's free set has no Shopee or Lazada, and an approximation of
 * somebody's logo is worse than none — these are the exact marks already
 * printed along the bottom of every S&J ID.
 */
.directory-link::before {
  content: '';
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}

.directory-link.is-shopee::before { background-image: url('../assets/social/shopee.webp'); }
.directory-link.is-lazada::before { background-image: url('../assets/social/lazada.webp'); }
.directory-link.is-tiktok::before { background-image: url('../assets/social/tiktok.webp'); }

/* Facebook is not on that bar — it is drawn into the ID's pills instead — so it
   keeps the icon font the rest of the card already uses for it. */
.directory-link.is-facebook::before {
  content: '\f39e';
  font-family: 'SJ Icons Brand';
  font-weight: 400;
  font-size: 13px;
  line-height: 18px;
  text-align: center;
  color: #1877f2;
}

/* Each platform's own colour, so the row is scannable at a glance. */
.directory-link.is-shopee:hover { border-color: #ee4d2d; color: #ee4d2d; background: #fff3f0; }
.directory-link.is-lazada:hover { border-color: #0f146d; color: #0f146d; background: #f1f2ff; }
.directory-link.is-tiktok:hover { border-color: #111; color: #111; background: #f5f5f5; }
.directory-link.is-facebook:hover { border-color: #1877f2; color: #1877f2; background: #f0f5ff; }

/* ---------- closing panels ---------- */

.directory-note { margin-top: clamp(24px, 4vw, 36px); }

.directory-note-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: clamp(18px, 3vw, 34px);
}

/* Separates the pair once they sit side by side. Dropped when they stack,
   where a line between them would read as a rule under the first. */
@media (min-width: 700px) {
  .directory-note-grid > .directory-note-item + .directory-note-item {
    padding-left: clamp(18px, 3vw, 34px);
    border-left: 1px solid var(--pink-line);
  }
}

/* Centred against the text, not pinned to its top. The two notes are different
   heights, so top-aligning left one icon level with a heading and the other
   floating above a short paragraph. */
.directory-note-item { display: flex; gap: 14px; align-items: center; }
.directory-note-item h2 { margin: 0 0 6px; font-size: 16px; }
.directory-note-item p { margin: 0; font-size: 14px; color: var(--muted); line-height: 1.6; }
.directory-note-item strong { color: var(--ink); }

/* No tile behind these two. They are drawn marks rather than glyphs now, and
   at this size a rounded square around them reads as a button. */
.directory-note-ico {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  color: var(--pink);
}

.directory-note-ico .sj-icon { width: 100%; height: 100%; }

/* The seal is the page's whole claim, so it is the strongest thing on it. */
.directory-note-ico.is-seal { filter: drop-shadow(0 6px 14px rgba(254, 81, 130, .28)); }

.directory-trust {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: clamp(14px, 2vw, 22px);
  margin-top: 18px;
  padding: clamp(18px, 3vw, 26px);
  background: rgba(255, 255, 255, .6);
  border: 1px solid rgba(255, 255, 255, .8);
  border-radius: var(--radius);
}

/* Centred as a column: icon, then label, then the line under it. The icon was
   centred over left-aligned text for a moment, which reads as a mistake rather
   than as a choice — the whole stack has to agree. */
.directory-trust-item { text-align: center; }
.directory-trust-item strong { display: block; margin-top: 8px; font-size: 13.5px; }
.directory-trust-item p {
  margin: 4px auto 0;
  /* Held short so a two-line caption breaks near the middle instead of leaving
     one word stranded under a full-width line. */
  max-width: 24ch;
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.55;
}

.directory-trust-ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 12px;
  background: linear-gradient(135deg, #fff0f5, #ffe3ee);
  color: var(--pink);
}

.directory-trust-ico .sj-icon { width: 20px; height: 20px; }

.directory-preview-note { margin: 0; text-align: center; }

@media (max-width: 620px) {
  .directory-search {
    flex-wrap: wrap;
    border-radius: var(--radius);
    padding: 10px;
  }
  /* The bar stacks here, and a magnifier alone on its own row marks nothing.
     The placeholder already says what the field is for. */
  .directory-search-ico { display: none; }
  .directory-search input[type=search] { flex: 1 1 100%; }
  .directory-search select { flex: 1 1 auto; max-width: none; border-left: 0; padding-left: 14px; }
  .directory-search .btn { flex: 1 1 auto; }
}

@media (max-width: 520px) {
  /* Stacks rather than squeezing the ID into a thumbnail too small to read. */
  .directory-card {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: 'media' 'meta';
    gap: 14px 0;
  }
  .directory-card-media { max-width: 240px; margin-inline: auto; }

  /*
   * Centred once the card stacks, because the ID above it is.
   *
   * Side by side these details are a column beside a picture, and a column
   * reads down its left edge. Stacked, that edge is gone: the ID sits centred
   * in the card and everything beneath it hangs off to the left of it, which
   * looks less like an alignment than like a mistake. Every other block on this
   * page — the hero, the search bar, the trust strip — is centred on a phone,
   * and this was the one that was not.
   *
   * Only here. Above this width the two-column card keeps its left edge, where
   * a centred column would be genuinely harder to read.
   */
  .directory-meta { text-align: center; }

  /* The rows inside are flex, so text-align does not reach them; each has to be
     told where to sit on its own main axis. */
  .directory-location,
  .directory-contact-line,
  .directory-contact-row { justify-content: center; }

  /*
   * Who this is, sized as three ranks instead of three lines.
   *
   * Stacked under a full-width ID, the name, the role and the place ran at
   * 17px, 11.5px and 12.5px — near enough the same size to read as a heap, and
   * the role, which is the whole point of the directory, was the smallest thing
   * in it. Somebody checking a seller is checking exactly that word: whether
   * this is a Depot Distributor or a Reseller. The name grows, the role grows
   * more, and the gaps open up so the three are read in order rather than at
   * once.
   */
  .directory-name {
    font-size: 20px;
    line-height: 1.2;
  }

  .directory-role {
    margin-top: 8px;
    font-size: 16px;
    /*
     * Tracking tightens as the size grows, which is the opposite of the usual
     * rule but is what keeps the longest role in the vocabulary —
     * INTERNATIONAL DISTRIBUTOR, 25 characters — on one line on a 320px phone,
     * the narrowest still in use. At .1em it needed two.
     */
    letter-spacing: .02em;
    /*
     * And if it ever does wrap — a longer role added later, a device narrower
     * than 320, Inter failing to load and a wider fallback standing in — it
     * wraps into two balanced lines rather than dropping one orphaned word
     * under a full one.
     */
    text-wrap: balance;
  }

  .directory-location {
    margin-top: 10px;
    font-size: 13px;
  }

  /*
   * The mark sits against the word it marks.
   *
   * The gap that looked too wide was mostly not the gap: the glyph is centred
   * inside a round tile with nearly twice its diameter, so half the distance to
   * the text was empty tile. Shrinking the tile towards the glyph closes it
   * without the icon and the text starting to touch.
   */
  .directory-location { gap: 4px; }

  .directory-location .directory-ico {
    width: 18px;
    height: 18px;
    font-size: 12px;
  }

  /*
   * On the call button the tile is invisible anyway — it is the same wash as
   * the pill behind it — so it was contributing nothing but that dead space.
   */
  .directory-contact-row { gap: 6px; }

  .directory-contact-row .directory-ico {
    width: 16px;
    height: 16px;
    font-size: 12.5px;
    background: none;
  }

  /* A clear step between who they are and how to reach them, now that the block
     above it carries more weight. */
  .directory-contact {
    margin-top: 15px;
    padding-top: 15px;
  }

  /*
   * The number stays text on a phone, as it is everywhere else.
   *
   * It used to be drawn as a pill here, on the reasoning that tapping to dial
   * is the one thing somebody does from this card and a line of centred text
   * gives a thumb nothing to aim at. That held while it had the row to itself.
   * Now that seller-since sits beside it, a pill next to plain text reads as
   * two different kinds of thing rather than as one line of contact detail —
   * and the eye goes to the shape, not to the number.
   *
   * The padding stays, so what is tappable is still comfortably bigger than
   * the text; it is the border and the fill that are gone.
   */
  .directory-contact-row {
    padding: 8px 2px;
  }

  /*
   * The shops in two even columns rather than a centred wrap.
   *
   * Four platforms at their natural widths wrapped three-and-one, leaving a
   * single chip stranded under a full row — the arrangement changed with the
   * number of links and the widths of their names, so no two cards agreed. A
   * grid makes every chip the same size and every card the same shape, and four
   * of them land as a tidy square block.
   */
  .directory-links {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
  }

  /* An odd one at the end takes the whole row instead of sitting half-width
     with a hole beside it. */
  .directory-links > :last-child:nth-child(odd) { grid-column: 1 / -1; }

  .directory-link {
    justify-content: center;
    padding: 9px 12px;
  }
}

/* "Authorized" picked out in the heading, as in the mockup. */
.directory-hero h1 em { font-style: normal; color: var(--pink); }

/* The name links to the same verification page the ID's QR points at. */
.directory-name a {
  color: inherit;
  text-decoration: none;
}
.directory-name a:hover { color: var(--pink); text-decoration: underline; text-underline-offset: 3px; }

/* The directory's lede runs one sentence per line.
   At the shared 38rem the second sentence broke across two, which read as
   three lines of small print rather than two plain statements. */
.directory-hero .lede { max-width: 54rem; }
