/* ============================================================================
   CHANNELS PAGE — `s/channels`, FE Client file, node 27475:448759
   Body: `Body / Channels / Page` (27475:448764)

   The frame's local styles were NOT copied; every colour, space, radius and
   type step resolves through DESIGN.md. Mapping:

   | Figma                                  | Token                        |
   |----------------------------------------|------------------------------|
   | Body gaps 16                           | `space/md`                   |
   | H1  Roboto Bold 30/38  #262626         | `.txt-heading-xl`            |
   | H2  Roboto Bold 24/32  #262626         | `.txt-heading-lg`            |
   | Tab / Rounded  h32, px16, r16, gap 8   | `space/md`, `space/xs`       |
   |   selected  #f4f1f9 / #4211a0 border   | `soft/brand/default`,
   |             / #4211a0 text             | `border/brand/default`,
   |                                        | `content/brand`              |
   |   default   #f6f6f6 / #595959          | `soft/neutral/default`,
   |                                        | `content/primary`            |
   | Section  #FFFFFF, r8, p16, gap 16      | `surface/raised`,
   |                                        | `shape/radius/card`          |
   | "See all"  #4211a0 14/22               | `.btn--link` (button.css)    |
   | Description  #595959 14/22, max 480    | `content/primary`            |
   | Cards row  gap 16, cards 264 fixed     | `space/md`                   |

   ⚠️ #f4f1f9 is BigHeart's soft tint, one of the two literals root CLAUDE.md
   names in non-negotiable 4 ("They already appear as literals in four DS
   components… Don't add a fifth"). `soft/brand/default` is that value under
   BigHeart and follows the brand switch.

   GEOMETRY, verified against the frame: cards are 264 wide, 16 apart, in a
   984-wide window inside a 1016 body. Four cards need 1104, so the row
   OVERFLOWS by design — the Section is `overflow-clip` and the fourth card is
   cut. That is a horizontal scroller, not a wrap, and it is built as one
   below.

   TODO(tokens): every bare px length in this file is a SIZE or a BREAKPOINT.
   DESIGN.md §12.4 records both as not built. No colour, radius, spacing,
   border-width or font-size literal appears anywhere in this file.
   ========================================================================== */

.channels {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  padding-block-end: var(--space-md);
}

/* --- Body / Header ------------------------------------------------------- */
.channels__title-wrap {
  display: flex;
  align-items: center;
  padding-block: var(--space-md);
}

.channels__title {
  margin: 0;
}

/* --- Channels / Filters — a row of `Tab / Rounded` ------------------------
   These are TABS, not chips: exactly one is current, and choosing one changes
   what the page shows. Marked up as a tablist so that is what a screen reader
   hears too. */
.channels__filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}

.tab-round {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: var(--space-xs);
  /* TODO(tokens): size not built — the frame's 32px control. */
  block-size: 32px;
  padding-inline: var(--space-md);
  /* The frame's radius is 16 on a 32 control, i.e. a pill. `radius/full` says
     that intent rather than restating half the height. */
  border-radius: var(--radius-full);
  border: var(--border-width-thin) solid transparent;
  background: var(--color-soft-neutral-default);
  color: var(--color-content-primary);
  font-family: var(--font-family-text);
  font-size: var(--font-body-md-size);
  line-height: var(--font-body-md-line-height);
  font-weight: var(--font-weight-regular);
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 100ms ease; /* TODO(tokens): motion not built */
}

.tab-round:hover {
  background: var(--color-soft-neutral-hover);
}

/* Pressed — the soft-neutral pressed step is correct and unconsumed by any DS
   component (CLAUDE.md known gaps). Used deliberately. */
.tab-round:active {
  background: var(--color-soft-neutral-pressed);
}

/* Selected. Three channels, like Dropdown / Content / Item (§6.2): brand tint,
   brand ink, and a border the unselected state does not have — so selection
   survives without colour. */
.tab-round[aria-selected="true"] {
  background: var(--color-soft-brand-default);
  border-color: var(--color-border-brand-default);
  color: var(--color-content-brand);
  font-weight: var(--font-weight-medium);
}

.tab-round .icon {
  /* TODO(tokens): size not built. 16px is the frame's tab icon slot. */
  inline-size: 16px;
  block-size: 16px;
}

/* --- Organization Description --------------------------------------------
   480 wide in the frame, clamped to two lines with a Show more beneath. */
.channels__intro {
  max-inline-size: 480px;
}

.channels__intro-text {
  margin: 0;
  color: var(--color-content-primary);
  font-size: var(--font-body-md-size);
  line-height: var(--font-body-md-line-height);
}

.channels__intro[data-expanded="false"] .channels__intro-text {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* --- Section -------------------------------------------------------------- */
.channel-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  padding: var(--space-md);
  background: var(--color-surface-raised);
  border-radius: var(--shape-radius-card);
  /* The frame clips the row; the scroller below owns the overflow, so the
     Section must not also clip or it would cut the focus ring on a card. */
  min-inline-size: 0;
}

/* Channel Header — Title row (H2 + See all) over the description. */
.channel-section__header {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.channel-section__title-row {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}

.channel-section__title {
  margin: 0;
  flex: 1 1 auto;
  min-inline-size: 0;
}

.channel-section__desc {
  margin: 0;
  max-inline-size: 480px;
  color: var(--color-content-primary);
  font-size: var(--font-body-md-size);
  line-height: var(--font-body-md-line-height);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- Channels / Cards / Featured — the horizontal scroller ----------------
   The frame shows 3.5 of 4 cards, clipped. A clipped row with no way to reach
   the rest would be a dead end, so it scrolls. Three things make that usable:

     · scroll-snap, so a drag settles on a card edge rather than mid-card;
     · `overscroll-behavior-inline: contain`, so scrolling to the end of the
       row does not then scroll the page sideways;
     · vertical padding, because `overflow` clips the focus ring on the cards
       and `outline-offset` puts it OUTSIDE the card box. Negative margin puts
       the row back on the Section's own padding edge.

   Keyboard reach needs no extra work: each card is a link, so Tab walks the
   row and the browser scrolls each one into view as it is focused. */
.channel-section__row {
  display: flex;
  gap: var(--space-md);
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scroll-snap-type: inline mandatory;
  padding-block: var(--shape-focus-offset);
  margin-block: calc(var(--shape-focus-offset) * -1);
  /* Room for the ring on the first and last card, same reasoning. */
  padding-inline: var(--shape-focus-offset);
  margin-inline: calc(var(--shape-focus-offset) * -1);
}

.channel-section__row > .ccard {
  /* The frame's fixed 264 — these do not flex the way the collection grid's
     cards do. TODO(tokens): size not built. */
  inline-size: 264px;
  flex: none;
  scroll-snap-align: start;
}

/* A scroller that is only reachable by dragging is not reachable at all for
   many people, so give it a keyboard focus stop when it actually overflows.
   `tabindex` is set by channels.js only in that case. */
.channel-section__row:focus-visible {
  outline: var(--shape-focus-width) solid var(--color-border-focus);
  outline-offset: var(--shape-focus-offset);
}
