/* tattooartists.fyi */
@layer vendor, tokens, reset, base, layout, components, utilities;

@font-face {
  font-family: 'Satoshi';
  src: url('Satoshi-Variable.woff2') format('woff2');
  font-weight: 300 900;
  font-style: normal;
  font-display: swap;
}
@layer tokens {
  :root {
    --font-sans: 'Satoshi', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    /* type */
    --f-15: 0.9375rem;
    --f-16: 1rem;
    --f-18: 1.125rem;
    --f-20: 1.25rem;
    --f-22: 1.375rem;

    --lh-1-5: 1.5;
    --lh-1-25: 1.25;
    --fw-500: 500;
    --fw-700: 700;
    /* space */
    --s-2: 0.125rem;
    --s-4: 0.25rem;
    --s-8: 0.5rem;
    --s-12: 0.75rem;
    --s-16: 1rem;
    --s-32: 2rem;
    /* radius */
    --r-12: 0.75rem;
    /* colour */
    --black: #141414;
    --grey: #eaeaea;
    --white: #ffffff;
    --accent: #e8553b;
    --bubble-dark: #b93a24;
    --green: #3F9658;       /* the shortlist button with 1+ saved: green fill, white heart + count */
    --bubble-light: #f3b39c;
    --black-60: color-mix(in srgb, var(--black) 60%, transparent);
    --black-20: color-mix(in srgb, var(--black) 20%, transparent);
    --z-map: 0;
    --z-bar: 5;
    --z-panel: 6;
    --z-modal: 10;
    --tap-h: 48px;
    --vendor-chrome: 29px;    /* the Mapbox wordmark we must not cover */
  }
}
@layer reset {
  :root { color-scheme: light; }
  *,
  *::before,
  *::after { box-sizing: border-box; }
  html,
  body { height: 100%; margin: 0; overflow: hidden; }
  html {
    touch-action: pan-x pan-y;
    overscroll-behavior: none;
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
  }
  body {
    min-height: 100dvh;
    overscroll-behavior: none;
    -webkit-tap-highlight-color: transparent;
    user-select: none;
    -webkit-user-select: none;
  }
  input,
  .card,
  dialog { margin: 0; padding: 0; border: 0; color: inherit; }
  .shortlist { user-select: text; -webkit-user-select: text; }
  /* the sheet reads env(safe-area-inset-top) through this probe: env() is not readable from JS */
  #safeTop { position: fixed; left: 0; top: 0; width: 1px; height: env(safe-area-inset-top); pointer-events: none; }
  button,
  input { font: inherit; color: inherit; }
  input::placeholder { color: var(--black-60); }
  button { appearance: none; cursor: pointer; }
  [x-cloak] { display: none !important; }
  @media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
      transition-duration: 0.01ms !important;
    }
  }
}
@layer base {
  body {
    -webkit-font-smoothing: antialiased;
    letter-spacing: 0.01em;
    font-family: var(--font-sans);
    font-size: var(--f-16);
    line-height: var(--lh-1-5);
    font-weight: var(--fw-500);
    color: var(--black);
    background: var(--white);
  }
  a { color: inherit; }
  /* no bottom margins: rhythm comes from one top margin or a flex gap, so nothing can collapse */
  p { margin: 0; }
  h2 { margin: 0; }
  /* no focus ring on tap, by request */
  :focus { outline: none; }
}
@layer layout {
  #map {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100dvh;
    z-index: var(--z-map);
  }
  body > header {
    position: fixed;
    inset: calc(env(safe-area-inset-top) + var(--s-12)) 0 auto;
    z-index: var(--z-bar);
    display: flex;
    flex-direction: column;
    pointer-events: none;

    > * { pointer-events: auto; }
    > search { margin-inline: var(--s-12); }
  }
  .filters {
    flex: 1 1 auto;
    display: flex;
    gap: var(--s-8);
    padding: var(--s-8) var(--s-12);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;

    &::-webkit-scrollbar { display: none; }
  }
  /* the artist detail: a content-fit bottom sheet. No detents, so the transform alone slides it in
     and out, exactly as the shortlist sheet's does. */
  .card-sheet {
    position: fixed;
    inset: auto 0 0 0;
    width: 100%;
    max-width: none;
    max-height: none;
    margin: 0;
    border: 0;
    padding: var(--s-16) var(--s-16) var(--s-32);
    background: var(--white);
    border-radius: var(--r-12) var(--r-12) 0 0;
    overflow: clip;
    z-index: var(--z-modal);
    transform: translate3d(0, 100%, 0);
    transition: transform .5s cubic-bezier(.32, .72, 0, 1);
  }
  .card-sheet.is-open { transform: translate3d(0, 0, 0); }
  .card-sheet > .grabber { margin-bottom: var(--s-12); }
  .grabber {
    display: block;
    flex: none;
    width: 36px;
    height: var(--s-4);
    margin: 0 auto;
    border-radius: var(--r-12);
    background: var(--grey);
  }
  .shortlist {
    position: fixed;
    inset: auto 0 0 0;
    width: 100%;
    max-width: none;
    max-height: none;
    height: calc(100dvh - env(safe-area-inset-top) - var(--s-12));    /* matches the 12px in app.js */
    display: flex;
    flex-direction: column;
    overflow: hidden;
    z-index: var(--z-modal);
    transform: translate3d(0, 100vh, 0);
    transition: transform .5s cubic-bezier(.32, .72, 0, 1);
  }
  .shortlist.dragging { transition: none; will-change: transform; }
  /* touch-action goes on the drag surface and the list, never the whole sheet */
  .shortlist > .grabber, .shortlist > header { touch-action: none; }
  .shortlist .body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: none;
  }
  .shortlist .body::-webkit-scrollbar { display: none; }
  .shortlist:not(.at-full) .body { overflow-y: hidden; touch-action: none; }
  .shortlist.at-full .body { touch-action: pan-y; }
  .shortlist-button {
    position: fixed;
    inset-inline-start: var(--s-12);
    bottom: calc(var(--vendor-chrome) + var(--s-4));    /* clear of the wordmark */
    /* the design's pill: 48 tall, as wide as its heart and count */
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-8);
    height: var(--tap-h);
    padding: 0 var(--s-12);
    border: 0;
    border-radius: var(--r-12);
    background: var(--white);
    /* the same small lift as the search field and the chips */
    box-shadow: 0 2px 8px var(--black-20);
    color: var(--black);
    font-size: var(--f-18);
    font-weight: var(--fw-700);
    line-height: 1;

    svg { width: 24px; height: 20px; flex: none; }

    /* 1+ saved: the design's green with a white heart and count */
    &.is-on { background: var(--green); color: var(--white); }
  }
  .notice {
    align-self: flex-start;
    margin-inline-start: var(--s-12);
  }
}
@layer components {
  search {
    display: flex;
    height: var(--tap-h);
    background: var(--white);
    border-radius: var(--r-12);
    /* a small lift: the panel's own 12/32 shadow reads as a grey box under a 42px chip */
    box-shadow: 0 2px 8px var(--black-20);

    input {
      flex: 1;
      min-width: 0;
      padding-inline: var(--s-12);
      border: 0;
      background: none;
      /* iOS zooms an input below 16px on focus; the page is locked, so it must stay 16px */
      font-size: var(--f-18);
    }
  }
  search button,
  .card header button,
  .shortlist header button {
    display: grid;
    place-items: center;
    width: var(--tap-h);
    height: var(--tap-h);
    padding: 0;
    border: 0;
    border-radius: var(--r-12);
    background: none;
    font-size: var(--f-16);
    line-height: 1;

    &:hover { background: var(--grey); }
  }
  .card header button { width: 40px; height: 40px; }
  .filter {
    flex: 0 0 auto;
    padding: var(--s-8) var(--s-12);
    border: 0;
    border-radius: var(--r-12);
    background: var(--white);
    /* the same lift as the search field, well under the panel's own elevation */
    box-shadow: 0 2px 8px var(--black-20);
    font-size: var(--f-18);
    height: 42px;
    white-space: nowrap;

    &.is-on { background: var(--black); color: var(--white); }
  }
  .filters > div { position: relative; flex: 0 0 auto; }
  .filter-break { flex: 0 0 auto; width: 0; }
  /* fixed, not absolute: the filter row scrolls, so overflow-x would clip it */
  .options {
    position: fixed;
    z-index: var(--z-panel);
    min-width: 232px;
    overflow: hidden;      /* clips a square row band to the panel's rounded corner */
    border-radius: var(--r-12);
    background: var(--white);
    box-shadow: 0 var(--s-12) 32px var(--black-20);

    button {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--s-16);
      width: 100%;
      height: 42px;
      padding: var(--s-8) var(--s-12);
      border: 0;
      /* square: the panel's own radius and its overflow clip the first and last row */
      background: none;
      font: inherit;
      font-size: var(--f-18);
      color: var(--black);
      text-align: start;
      cursor: pointer;

      &.is-on { font-weight: var(--fw-700); background: var(--grey); }
      > span:last-child { font-size: var(--f-16); color: var(--black-60); font-variant-numeric: tabular-nums; }
    }
  }
  /* the artist detail's content: the sheet carries the surface, the padding and the radius */
  .card {
    display: flex;
    flex-direction: column;
    gap: var(--s-16);

    header {
      display: flex;
      align-items: start;
      justify-content: space-between;
      gap: var(--s-8);

      > div {
        flex: 1;
        min-width: 0;
        display: flex;
        flex-direction: column;
        gap: var(--s-4);

        span,
        a { font-size: var(--f-16); }
        a {
          text-decoration: underline dashed;
          text-decoration-thickness: 1px;
          text-underline-position: from-font;
        }
      }
      /* nudged 4px up and out, per the design */
      > button { position: relative; top: -4px; inset-inline-end: -4px; }
    }
    h2 {
      font-size: var(--f-20);
      font-weight: var(--fw-700);
      line-height: var(--lh-1-25);
      /* names run to 64 characters and carry emoji: clamp, do not sanitise */
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
      overflow: hidden;
    }
    ul {
      display: flex;
      flex-wrap: wrap;
      gap: var(--s-8) var(--s-4);
      margin: 0;
      padding: 0;
      list-style: none;

      li { padding: var(--s-2) var(--s-8); background: var(--grey); border-radius: var(--r-12); font-size: var(--f-16); }
    }
    footer {
      display: flex;
      align-items: center;
      gap: var(--s-8);
      /* the design gaps the head+tags group at 16 and the footer 24 from it */
      margin-block-start: var(--s-8);

      a {
        flex-grow: 1;
        display: flex;
        align-items: center;
        justify-content: center;
        height: 42px;
        padding: var(--s-8) var(--s-12);
        border-radius: var(--r-12);
        background: var(--black);
        color: var(--white);
        font-size: var(--f-18);
        font-weight: var(--fw-700);
        line-height: var(--lh-1-25);
        text-decoration: none;
      }
      /* the map's shortlist pill again, with the word: grey "Save", green "Saved" */
      button {
        flex-grow: 1;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: var(--s-12);
        height: 42px;
        padding: var(--s-8) var(--s-12);
        border: 0;
        border-radius: var(--r-12);
        background: var(--grey);
        color: var(--black);
        font-size: var(--f-18);
        font-weight: var(--fw-700);
        line-height: var(--lh-1-25);

        svg { width: 21px; height: 18px; flex: none; }

        &.is-on { background: var(--green); color: var(--white); }
      }
    }
  }
  .shortlist {
    padding: var(--s-16) calc(var(--s-16) + env(safe-area-inset-right)) 0 calc(var(--s-16) + env(safe-area-inset-left));
    background: var(--white);
    border-radius: var(--r-12) var(--r-12) 0 0;

    > p { margin: var(--s-12) 0 0; }
    header { position: relative; display: flex; align-items: start; justify-content: space-between; flex: none; margin-block-start: var(--s-12); }
    /* the close control sits 4px up and out, as on the card */
    header button { position: absolute; top: -4px; inset-inline-end: -4px; width: 40px; height: 40px; }
    h2 { font-size: var(--f-20); font-weight: var(--fw-700); line-height: var(--lh-1-25); }
    ul {
      display: flex;
      flex-direction: column;
      gap: 20px;
      margin: var(--s-16) 0 0;
      padding: 0 0 calc(var(--s-16) + env(safe-area-inset-bottom));
      list-style: none;
    }
    li {
      display: flex;
      flex-direction: column;
      align-items: start;
      gap: var(--s-8);

      /* the row head: the identity on the left, remove on the right */
      > div:first-child {
        display: flex;
        align-items: start;
        justify-content: space-between;
        gap: var(--s-8);
        align-self: stretch;
      }
      /* the identity: the name over the town */
      > div:first-child > div {
        display: flex;
        flex-direction: column;
        gap: var(--s-4);

        a {
          font-size: var(--f-18);
          font-weight: var(--fw-700);
          line-height: var(--lh-1-25);
          text-decoration: underline 1px;
          text-underline-position: from-font;
        }
        span { font-size: var(--f-16); line-height: var(--lh-1-5); }
      }
      button {
        padding: 0;
        border: 0;
        background: none;
        color: var(--black-60);
        font-size: var(--f-16);
        line-height: var(--lh-1-5);
        text-decoration: underline 1px;
        text-underline-position: from-font;
      }
      /* the tags: the first three, then an overflow chip */
      > .tags {
        display: flex;
        flex-wrap: wrap;
        column-gap: var(--s-4);
        row-gap: var(--s-8);

        span {
          padding: var(--s-2) var(--s-8);
          background: var(--grey);
          border-radius: var(--r-12);
          font-size: var(--f-16);
          line-height: var(--lh-1-5);
        }
      }
    }
  }
  .meta { color: var(--black-60); font-size: var(--f-15); }
  .notice {
    padding: var(--s-8) var(--s-12);
    background: var(--white);
    border-radius: var(--r-12);
    color: var(--black-60);
    font-size: var(--f-15);
  }
}
@layer utilities {
  /* ---- the area sheet: one counted marker's artists ----
     Its two states share one header: the back control sits leading on the lane the rows use, and the
     meta line drops away once the list has scrolled, so the title is all that is left and nothing
     moves sideways. These live in utilities because they override the card's own rules in components. */
  .studio header .lane {
    display: flex;
    align-items: center;
    gap: var(--s-8);
    min-width: 0;
  }
  .studio header .back {
    position: static;                    /* the card floats its close; this one sits in the lane */
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    margin-inline-start: calc(-1 * var(--s-8));   /* the glyph sits on the lane, not its box */
    border: 0;
    background: none;
  }
  .studio.at-scrolled .lane .meta { display: none; }
  /* Inside the area sheet the detail is the artist card, so the shortlist's row rules must not reach
     its tag list: a tag is a chip, not a row. */
  .shortlist.studio .detail .card ul {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--s-8) var(--s-4);
    padding: 0;
  }
  .shortlist.studio .detail .card ul li {
    flex: 0 0 auto;
    display: block;
    width: fit-content;
    padding: var(--s-2) var(--s-8);
    border-radius: var(--r-12);
    background: var(--grey);
    font-size: var(--f-16);
    line-height: var(--lh-1-5);
    list-style: none;
  }
  /* the actions sit at the sheet's bottom edge, as they do on the standalone card */
  .studio .detail .card footer {
    display: flex;
    gap: var(--s-8);
    padding-block: var(--s-16) var(--s-32);
  }
  /* labels are lowercase (they are the filter keys): only the first letter is cased */
  .card ul li::first-letter,
  .shortlist li .meta::first-letter,
  .options button > span:first-child::first-letter { text-transform: uppercase; }
  /* seen by screen readers only */
  .visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}
