@layer app {
  /* ============================================================
     Location-specific styles
     ============================================================ */

  .location-card {
    transition: all 0.2s ease;

    &:hover {
      transform: translateY(-2px);
      box-shadow: var(--shadow-lg);
    }
  }

  .location-icon-wrapper {
    width: 44px;
    height: 44px;
    border-radius: 12px;
    background: color-mix(in srgb, var(--color-primary) 8%, transparent);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
  }

  .location-members-tag {
    align-items: center;
    display: inline-flex;
    gap: 0.35rem;
  }

  /* Sits tight against the location name. */
  .location-membership {
    align-items: center;
    display: inline-flex;
    flex-shrink: 0;
  }

  /* A member's tag, just the check: pressing it is how they leave. */
  .location-membership__joined {
    align-items: center;
    background: color-mix(in srgb, var(--color-success) 12%, transparent);
    border: 0;
    border-radius: 50%;
    color: var(--color-success);
    display: inline-flex;
    font-size: 1.1rem;
    justify-content: center;
    line-height: 1;
    padding: 0.35rem;

    &:hover {
      background: color-mix(in srgb, var(--color-success) 20%, transparent);
    }
  }

  /* Pressing the tag swaps it for the confirm/cancel pair, sized to match it. */
  .location-membership__confirm {
    display: none;
    gap: 0.35rem;

    .btn {
      font-size: 0.75rem;
      line-height: 1;
      padding: 0.35em 0.65em;
    }
  }

  .location-membership--leaving {
    .location-membership__joined {
      display: none;
    }

    .location-membership__confirm {
      display: inline-flex;
    }
  }

  /* ============================================================
     Location page header: who the place is, with the one thing to
     do about it in the top corner, what it is for, and its views
     as tabs along the card's bottom edge. The feed's topics run
     under the views while the feed is the one on show.
     ============================================================ */

  .location-header {
    --location-header-gutter: 1.5rem;

    column-gap: 1rem;
    display: grid;
    grid-template-areas:
      "identity cta"
      "about about"
      "actions actions"
      "views views";
    grid-template-columns: minmax(0, 1fr) auto;
    padding: 1.25rem var(--location-header-gutter);

    > .alert {
      grid-area: actions;
    }
  }

  .location-header__identity {
    align-items: center;
    column-gap: 0.4rem;
    display: flex;
    flex-wrap: wrap;
    grid-area: identity;
    min-width: 0;
  }

  .location-header__breadcrumb {
    color: color-mix(in srgb, var(--color-dark) 55%, transparent);
    flex-basis: 100%;
    font-size: 0.85rem;
    margin: 0 0 0.15rem;

    a {
      color: var(--color-primary);
      text-decoration: none;

      &:hover {
        text-decoration: underline;
      }
    }
  }

  /* A long name gives way, so the membership tag stays beside it. */
  .location-header__heading {
    align-items: center;
    display: flex;
    flex-basis: 100%;
    gap: 0.6rem;
    min-width: 0;
  }

  .location-header__name {
    font-size: clamp(1.6rem, 5vw, 2.1rem);
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.15;
    margin: 0;
    min-width: 0;
  }

  /* Privacy and member count, under the name. */
  .location-header__badges {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 0.6rem;
  }

  /* Share, Join or Sign in, all the same size, in the top corner. */
  .location-header__cta {
    align-self: start;
    grid-area: cta;

    .invite-badge__share {
      font-size: 0.875rem;
      padding: 0.4rem 1rem;
    }
  }

  .location-header__about {
    color: color-mix(in srgb, var(--color-dark) 70%, transparent);
    font-size: 0.95rem;
    grid-area: about;
    margin: 0.85rem 0 0;
  }

  /* Edge to edge along the bottom of the card. A visitor to a private place
     has a lone Feed view and no topics, so nothing to show here. */
  .location-header__views {
    grid-area: views;
    margin: 1rem calc(-1 * var(--location-header-gutter)) -1.25rem;

    &:not(:has(.location-views > :nth-child(2), .feed-topics)) {
      display: none;
    }
  }

  .location-views {
    border-top: 1px solid color-mix(in srgb, var(--color-dark) 8%, transparent);
    flex-wrap: nowrap;
    gap: clamp(1.25rem, 4vw, 2rem);
    overflow-x: auto;
    padding-inline: var(--location-header-gutter);
    scrollbar-width: none;

    /* A lone Feed view has nothing to switch to. */
    &:not(:has(> :nth-child(2))) {
      display: none;
    }

    .nav-link {
      border-bottom: 3px solid transparent;
      color: color-mix(in srgb, var(--color-dark) 65%, transparent);
      font-size: 1rem;
      font-weight: 600;
      padding: 0.85rem 0 0.7rem;
      white-space: nowrap;

      &:hover {
        color: var(--color-primary);
      }

      &.active {
        border-bottom-color: var(--color-primary);
        color: var(--color-primary);
      }
    }
  }

  /* Topics narrow the feed, so they leave with it when another view is picked. */
  .feed-topics {
    align-items: center;
    border-top: 1px solid color-mix(in srgb, var(--color-dark) 8%, transparent);
    display: flex;
    min-width: 0;
    padding: 0.5rem var(--location-header-gutter);

    .location-header:has(.location-views .nav-link.active:not(#feed-tab)) & {
      display: none;
    }
  }

  /* Every topic on one line that scrolls sideways when they outgrow it,
     fading at its end. All leads, and the chosen topic follows it, so both
     are in sight before anyone scrolls. The padding leaves room for a focus
     ring the scroller would clip, and the scroll padding keeps a chip reached
     with Tab clear of both that edge and the fade. Reaching either end does
     not hand the swipe on to the page, where it would go back a page. */
  .feed-topics__list {
    display: flex;
    flex: 0 1 auto;
    gap: 0.35rem;
    margin-inline-start: -0.25rem;
    mask-image: linear-gradient(to right, #000 calc(100% - 1.5rem), transparent);
    min-width: 0;
    overflow-x: auto;
    overscroll-behavior-inline: contain;
    padding: 0.25rem 1.5rem 0.25rem 0.25rem;
    scroll-padding-inline: 0.25rem 1.5rem;
    scrollbar-width: none;
  }

  /* Outline chips, the chosen one in ink. */
  .feed-topic {
    align-items: center;
    background: var(--color-body-bg);
    border: 1px solid color-mix(in srgb, var(--color-dark) 14%, transparent);
    border-radius: var(--radius-pill);
    color: color-mix(in srgb, var(--color-dark) 72%, transparent);
    display: inline-flex;
    font-size: 0.85rem;
    font-weight: 500;
    line-height: 1.2;
    padding: 0.38rem 0.75rem;
    text-decoration: none;
    transition: border-color var(--transition), color var(--transition);
    white-space: nowrap;

    &:hover {
      border-color: color-mix(in srgb, var(--color-primary) 45%, transparent);
      color: var(--color-primary);
    }

    &:focus-visible {
      outline: 2px solid var(--color-primary);
      outline-offset: 2px;
    }
  }

  .feed-topic--active,
  .feed-topic--active:hover {
    background: var(--color-dark);
    border-color: var(--color-dark);
    color: #fff;
    font-weight: 600;
  }

  /* ============================================================
     Location feed: the composer, and the button that brings it up
     on a phone. Topics written into a post as hashtags show under
     the text as they are typed.
     ============================================================ */

  .location-feed {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
  }

  .location-feed__composer {
    padding: 1rem 1.25rem 0.75rem;
    position: relative;
  }

  .location-feed__dismiss {
    display: none;
  }

  .post-composer {
    align-items: flex-start;
    display: flex;
    gap: 0.9rem;

    > .avatar {
      --avatar-size: 44px;
      --avatar-font-size: 0.9rem;
    }
  }

  .post-composer__body {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    gap: 0.6rem;
    min-width: 0;
  }

  /* A tinted field, so the prompt reads as a place to write. Its text is the
     size of the line about the place above it, not a heading's. */
  .post-composer lexxy-editor.post-composer__input {
    --lexxy-editor-padding: 0.55rem 1rem;
    --lexxy-editor-rows: 1lh;

    background: color-mix(in srgb, var(--color-primary) 4%, var(--color-body-bg));
    border: 1px solid color-mix(in srgb, var(--color-primary) 12%, transparent);
    border-radius: 1.4rem;
    font-size: 0.95rem;

    &:focus-within {
      border-color: color-mix(in srgb, var(--color-primary) 35%, transparent);
      box-shadow: none;
    }
  }

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

  /* Only a wide screen has the narrow closed composer, and room for a hint. */
  .post-composer__sizer,
  .post-composer__hint {
    display: none;
  }

  .post-composer__bar {
    align-items: center;
    border-top: 1px solid color-mix(in srgb, var(--color-dark) 8%, transparent);
    display: flex;
    gap: 0.5rem;
    padding-top: 0.65rem;
  }

  /* Icon only, so a round target sitting flush with the editor's edge. The
     file field it stands for is hidden, so it wears that field's focus. */
  .post-composer__attach {
    align-items: center;
    border-radius: 50%;
    color: var(--color-primary);
    cursor: pointer;
    display: inline-flex;
    justify-content: center;
    padding: 0.55rem;

    .icon {
      font-size: 1.3rem;
    }

    &:hover {
      background: color-mix(in srgb, var(--color-primary) 8%, transparent);
    }

    &.is-invalid {
      color: var(--color-danger);
    }

    :focus-visible + & {
      outline: 2px solid var(--color-primary);
      outline-offset: -2px;
    }
  }

  .post-composer__submit {
    border-radius: var(--radius-pill);
    font-weight: 700;
    margin-inline-start: auto;
    padding: 0.55rem 1.5rem;
  }

  /* On a wide screen the composer is always there, so the button is not. */
  .location-feed__compose {
    display: none;
  }
}

@media (max-width: 767.98px) {
  @layer app {
    .location-header {
      --location-header-gutter: 1rem;

      padding-block: 1rem;
    }

    .location-header__views {
      margin-bottom: -1rem;
    }

    /* The feed comes first on a phone; the composer waits behind a floating
       button, the way the mock-up has it, and rises from the bottom edge when
       that button asks for it, wherever the reader has scrolled to. */
    .location-feed:not(.location-feed--composing) .location-feed__composer {
      display: none;
    }

    /* Doubled to outrank the lift rich-text.css gives a glass card while its
       mention prompt is open, which would drop the sheet back into the page. */
    .location-feed.location-feed--composing .location-feed__composer {
      background: var(--color-body-bg);
      border-radius: var(--radius-lg) var(--radius-lg) 0 0;
      bottom: 0;
      box-shadow: var(--shadow-lg);
      inset-inline: 0;
      padding: 2.5rem 1rem calc(0.85rem + env(safe-area-inset-bottom));
      position: fixed;
      z-index: 1030;
    }

    .location-feed__dismiss {
      align-items: center;
      background: none;
      border: 0;
      border-radius: 50%;
      color: color-mix(in srgb, var(--color-dark) 55%, transparent);
      display: inline-flex;
      height: 2rem;
      justify-content: center;
      position: absolute;
      right: 0.6rem;
      top: 0.4rem;
      width: 2rem;
    }

    .location-feed:not(.location-feed--composing) .location-feed__compose {
      align-items: center;
      border-radius: var(--radius-pill);
      bottom: calc(1rem + env(safe-area-inset-bottom));
      box-shadow: 0 10px 24px color-mix(in srgb, var(--color-primary) 35%, transparent);
      display: inline-flex;
      font-weight: 600;
      gap: 0.4rem;
      padding: 0.7rem 1.2rem;
      position: fixed;
      right: 1rem;
      z-index: 1020;
    }

    .post-composer > .avatar {
      display: none;
    }

    /* Any smaller and iOS Safari zooms the page in when the field is focused. */
    .post-composer lexxy-editor.post-composer__input {
      --lexxy-editor-rows: 3lh;

      font-size: var(--input-font-size);
    }
  }
}

/* On a wide screen the composer rests as a pill only as wide as its
   placeholder. Focus anywhere in it, or a click anywhere on its card, opens
   it to the full width, and the photo button, a hint and Post slide in under
   the field; leaving it empty folds it back. composer_controller.js keeps
   the open class. */
@media (min-width: 768px) {
  @layer app {
    /* The form fills the card, so the blank stretch beside the pill is the
       form's to answer a click on. */
    .location-feed__composer {
      padding: 0;
    }

    .post-composer {
      --post-composer-ease: cubic-bezier(0.2, 0.8, 0.2, 1);

      cursor: text;
      padding: 0.85rem 1.25rem;
    }

    /* The body draws the field, so the bar can sit inside it once it opens.
       Closed it does not grow, which leaves it as wide as the sizer; growing
       from there to the full row is what animates. */
    .post-composer__body {
      background: color-mix(in srgb, var(--color-primary) 4%, var(--color-body-bg));
      border: 1px solid color-mix(in srgb, var(--color-primary) 12%, transparent);
      border-radius: 1.4rem;
      flex-grow: 0;
      gap: 0;
      padding: 0.6rem 1.1rem;
      transition:
        flex-grow 420ms var(--post-composer-ease),
        border-radius 300ms var(--post-composer-ease),
        padding 300ms var(--post-composer-ease),
        background-color 300ms ease,
        border-color 200ms ease,
        box-shadow 300ms ease;

      &:focus-within {
        border-color: color-mix(in srgb, var(--color-primary) 40%, transparent);
        box-shadow: 0 0 0 4px color-mix(in srgb, var(--color-primary) 10%, transparent);
      }
    }

    .post-composer--open .post-composer__body {
      background: var(--color-body-bg);
      border-radius: var(--radius-lg);
      flex-grow: 1;
      padding: 0.8rem 0.6rem 0.5rem 1.1rem;
    }

    .post-composer lexxy-editor.post-composer__input {
      --lexxy-editor-padding: 0;

      background: none;
      border: 0;
      border-radius: 0;
    }

    /* The editor's own width is contained, so it cannot size the closed
       pill; this copy of the placeholder does, at no height. */
    .post-composer__sizer {
      display: block;
      font-size: 0.95rem;
      height: 0;
      overflow: hidden;
      padding-inline-end: 0.1rem;
      visibility: hidden;
      white-space: nowrap;
    }

    /* Grows from no height. Containing its width keeps the bar out of the
       closed pill's measurement, and the tray's negative margin lets focus
       rings and the button's lift show past its clipping edge. */
    .post-composer__drawer {
      contain: inline-size;
      display: grid;
      grid-template-rows: 0fr;
      transition: grid-template-rows 340ms var(--post-composer-ease);
    }

    .post-composer--open .post-composer__drawer {
      grid-template-rows: 1fr;
    }

    .post-composer__tray {
      gap: 0.5rem;
      margin: -0.5rem;
      min-height: 0;
      overflow: hidden;
      padding: 0.5rem;
    }

    .post-composer .media-preview:not(.d-none) {
      padding-top: 0.6rem;
    }

    .post-composer__bar {
      border-top: 0;
      gap: 0.35rem;
      margin-inline-start: -0.55rem;
      padding-top: 0.2rem;
    }

    /* Slides up into place, one after another as it opens, and drops back
       out together as it folds. The button keeps its own hover lift, which
       is why this moves with translate rather than transform. */
    :is(.post-composer__attach, .post-composer__hint, .post-composer__submit) {
      opacity: 0;
      translate: 0 0.5rem;
      transition:
        all 0.2s ease,
        opacity 220ms ease var(--post-composer-delay, 0ms),
        translate 320ms var(--post-composer-ease) var(--post-composer-delay, 0ms);
    }

    .post-composer--open {
      :is(.post-composer__attach, .post-composer__hint, .post-composer__submit) {
        opacity: 1;
        translate: none;
      }

      .post-composer__attach { --post-composer-delay: 90ms; }
      .post-composer__hint { --post-composer-delay: 130ms; }
      .post-composer__submit { --post-composer-delay: 170ms; }
    }

    .post-composer__hint {
      color: color-mix(in srgb, var(--color-dark) 45%, transparent);
      display: block;
      font-size: 0.82rem;
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;

      b {
        color: color-mix(in srgb, var(--color-dark) 60%, transparent);
      }
    }

    .post-composer__submit {
      flex: none;
      font-size: 0.875rem;
      padding: 0.3rem 1rem;
    }

    /* Pale until there is something to post: words, or a picked file. */
    .post-composer:not(:has(lexxy-editor:not(.lexxy-editor--empty), .media-preview:not(.d-none))) .post-composer__submit {
      --btn-bg: color-mix(in srgb, var(--color-primary) 35%, var(--color-body-bg));
      --btn-border: var(--btn-bg);
      --btn-bg-hover: var(--btn-bg);
      --btn-border-hover: var(--btn-bg);
    }
  }

  @media (prefers-reduced-motion: reduce) {
    @layer app {
      .post-composer__body,
      .post-composer__drawer,
      :is(.post-composer__attach, .post-composer__hint, .post-composer__submit) {
        transition: none;
      }
    }
  }
}
