/*
 * The player surface — Spotlight, cabinet, club awards wall.
 *
 * Posture, from styleguide §9: single column, generous, scrolling. A FLAT
 * hierarchy — 16px screen titles, with 20px reserved for the player's own name
 * and for the one thing on the Spotlight that outranks it, the award. Tone is
 * celebration rather than utility: the troph-e is the hero and the chrome
 * recedes.
 *
 * No club colour appears anywhere in here. Club colours are content — they feed
 * the artwork, and on the wall they would be the single most tempting thing to
 * theme with (D32). Gold stays the only chromatic colour in the chrome.
 *
 * No box-shadow, here or anywhere. Depth is the wash stack, the 1px borders and
 * the ambient glow behind them (§6).
 */

/* ---------------------------------------------------------------------------
 * The Spotlight
 * ------------------------------------------------------------------------ */

/* The card is `flush`, so the artwork meets the card's own edge with nothing
   between them and the picture reads as the card rather than as something
   placed on it. The plate is the copy underneath. */
.spotlight__plate {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-5);
  text-align: center;
}

/* THE ONE PLACE THE FLAT HIERARCHY BREAKS, and deliberately. §9 reserves 20px
   for the player's own name; on this screen the award outranks it, because the
   award is what arrived and the name is already known to the person reading. */
.spotlight__award {
  margin: 0;
  font-size: var(--type-h2-size);
  line-height: var(--type-h2-leading);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
}

/* A perpetual trophy's name (D154), set above the award the way the occasion
   is set above the person: gold, small and lettered wide. */
.spotlight__named {
  margin: 0;
  color: var(--text-gold);
  font-size: var(--type-caption-size);
  line-height: var(--type-caption-leading);
  letter-spacing: 0.08em;   /* the eyebrow tracking already used across the app */
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

.spotlight__recipient {
  margin: 0;
  font-size: var(--type-body-lg-size);
  line-height: var(--type-body-lg-leading);
  color: var(--text-secondary);
}

/* A plaque line may run to 120 characters (D155). Spaced, it wraps on its
   own; an unbroken run — a pasted handle, a hyphen-free double-barrel — must
   break inside the 393 column rather than push it sideways. */
.spotlight__award,
.spotlight__recipient,
.spotlight__meta,
.club-wall__award-title,
.club-wall__award-recipient {
  overflow-wrap: anywhere;
}

/* The club actually wrote this, so it is set as a quotation rather than as UI
   copy: italic, muted, and given room. The default blockquote margin would
   indent it out of the centred column. */
.spotlight__message {
  margin: 0;
  font-size: var(--type-body-size);
  line-height: var(--type-body-leading);
  font-style: italic;
  color: var(--text-secondary);
}

.spotlight__meta,
.spotlight__about {
  margin: 0;
  font-size: var(--type-caption-size);
  line-height: var(--type-caption-leading);
  color: var(--text-muted);
}

.spotlight__share {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
  width: 100%;
  margin-top: var(--space-2);
}

/* Two equal columns, matching the frame's pair, wrapping to a second row when
   the share sheet and Instagram are revealed (D159). `minmax(0, 1fr)` rather
   than `1fr` because a track's default minimum is its content, so a long label
   would push the grid wider than the 393px column instead of wrapping. A
   control still `hidden` takes no cell. */
.spotlight__share > [hidden] {
  display: none;
}

/* An odd control out spans the row rather than sitting alone at half width.
   Set by the share controller, because hidden controls take no cell and
   `:last-child` cannot tell which visible one is last. */
.spotlight__share > .is-wide {
  grid-column: 1 / -1;
}

/* ---------------------------------------------------------------------------
 * The cabinet
 * ------------------------------------------------------------------------ */

.cabinet {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.cabinet__count {
  margin: 0;
  font-size: var(--type-caption-size);
  line-height: var(--type-caption-leading);
  color: var(--text-muted);
}

.cabinet__actions {
  display: flex;
  justify-content: center;
}

/* The club filter (D124). Wraps rather than scrolls, for the Profile's year
   filter's reason — and because a second sideways scroller directly above the
   strip would be two gestures on one screen that look the same. */
.cabinet__clubs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* Separates the display from the index. The same section title as the
   Profile and the club wall, so the player shell keeps one. */
.cabinet__heading {
  margin: var(--space-2) 0 0;
  font-size: var(--type-body-lg-size);
  line-height: var(--type-body-lg-leading);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
}

/* ---------------------------------------------------------------------------
 * The club awards wall
 * ------------------------------------------------------------------------ */

.club-wall {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.club-wall__identity {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  text-align: center;
}

.club-wall__name {
  margin: 0;
  font-size: var(--type-h2-size);
  line-height: var(--type-h2-leading);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
}

.club-wall__meta {
  margin: 0;
  font-size: var(--type-body-size);
  line-height: var(--type-body-leading);
  color: var(--text-secondary);
}

.club-wall__switch {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.club-wall__switch-link {
  padding: var(--space-2) var(--space-4);
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-pill);
  font-size: var(--type-body-size);
  line-height: var(--type-body-leading);
  color: var(--text-secondary);
  text-decoration: none;
}

/* D28: hover and active change the FILL, never the opacity. */
.club-wall__switch-link:hover {
  background: var(--gold-wash-hover);
  color: var(--text-primary);
  text-decoration: none;
}

.club-wall__switch-link:focus-visible {
  outline: var(--focus-ring-outline);
  outline-offset: var(--focus-ring-offset);
}

.club-wall__heading {
  margin: 0;
  font-size: var(--type-body-lg-size);
  line-height: var(--type-body-lg-leading);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
}

.club-wall__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.club-wall__award {
  background: var(--surface-1);
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-md);
}

.club-wall__award-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-4);
  color: var(--text-primary);
  text-decoration: none;
}

/* Only the player's own award is a link, because only their own opens (D85).
   The rest carry no hover, no chevron and no pointer, so nothing on the wall
   advertises a destination that would 404. */
.club-wall__award--mine {
  border-color: var(--gold-rest);
}

.club-wall__award-link:hover {
  background: var(--gold-wash-hover);
  text-decoration: none;
}

.club-wall__award-link:focus-visible {
  outline: var(--focus-ring-outline);
  outline-offset: var(--focus-ring-offset);
  border-radius: var(--radius-md);
}

.club-wall__award-title {
  font-size: var(--type-body-lg-size);
  line-height: var(--type-body-lg-leading);
  font-weight: var(--font-weight-semibold);
}

.club-wall__award-recipient {
  font-size: var(--type-body-size);
  line-height: var(--type-body-leading);
  color: var(--text-secondary);
}

.club-wall__award-meta {
  font-size: var(--type-caption-size);
  line-height: var(--type-caption-leading);
  color: var(--text-muted);
}

/* ---------------------------------------------------------------------------
 * Historical claims (D183)
 *
 * The submission and status screens, and the player's own claims on the wall.
 * A claim row shares the people result's rules below (a whole-row link with a
 * chevron), with the status pill before the chevron.
 * ------------------------------------------------------------------------ */

.claim,
.claim__form,
.claim__actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.claim__actions {
  gap: var(--space-2);
}

.claim__prose,
.claim__note {
  margin: 0;
  font-size: var(--type-body-size);
  line-height: var(--type-body-leading);
  color: var(--text-secondary);
}

.claim__note {
  color: var(--text-primary);
  white-space: pre-line;
  overflow-wrap: anywhere;
}

.claim__summary {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.claim__status {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--type-body-size);
  line-height: var(--type-body-leading);
  color: var(--text-secondary);
}

.claim__award {
  margin: 0;
  font-size: var(--type-body-lg-size);
  line-height: var(--type-body-lg-leading);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
  overflow-wrap: anywhere;
}

.claim__meta {
  margin: 0;
  font-size: var(--type-caption-size);
  line-height: var(--type-caption-leading);
  color: var(--text-tertiary);
}

.claim-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* A player's own words, up to 200 characters: two lines and an ellipsis on
   the wall, the whole of it on the status page. */
.claim-list__award {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  overflow-wrap: anywhere;
  font-size: var(--type-body-size);
  line-height: var(--type-body-leading);
  font-weight: var(--font-weight-semibold);
}

/* ---------------------------------------------------------------------------
 * Player search and the public cabinet (D158)
 *
 * A result is a whole-row link with a chevron, as every list that opens
 * something is. The wall's card treatment, so a result reads as the same kind
 * of object as an award row.
 * ------------------------------------------------------------------------ */

.people {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.people__hint,
.people__clubs {
  margin: 0;
  font-size: var(--type-body-size);
  line-height: var(--type-body-leading);
  color: var(--text-secondary);
}

.people__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.people__result,
.claim-list__row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--surface-1);
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  text-decoration: none;
}

/* D28: hover and active change the FILL, never the opacity. Hover only for a
   pointer that hovers, or a tapped row stays lit on the next page (see
   data.css's timeline). */
@media (hover: hover) {
  .people__result:hover,
  .claim-list__row:hover {
    background: var(--gold-wash-hover);
    text-decoration: none;
  }
}

.people__result:active,
.claim-list__row:active {
  background: var(--gold-wash-hover);
}

.people__result:focus-visible,
.claim-list__row:focus-visible {
  outline: var(--focus-ring-outline);
  outline-offset: var(--focus-ring-offset);
}

.people__text,
.claim-list__text {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.people__name {
  font-size: var(--type-body-lg-size);
  line-height: var(--type-body-lg-leading);
  font-weight: var(--font-weight-semibold);
}

.people__meta,
.claim-list__meta {
  font-size: var(--type-caption-size);
  line-height: var(--type-caption-leading);
  color: var(--text-tertiary);
}

.people__chevron,
.claim-list__chevron {
  display: flex;
  color: var(--text-tertiary);
}

/* ---------------------------------------------------------------------------
 * The arrival banner (D91)
 *
 * The one place on the player surface where gold is a FILL rather than an
 * accent. It is the product's whole promise arriving, it appears at most a few
 * times a season, and it has to win against a trophy render sitting below it.
 * Everywhere else on this surface gold is a border or a label.
 * ------------------------------------------------------------------------ */

/* NO `.arrival:empty { display: none }` HERE, deliberately. The ERB leaves a
   newline inside the wrapper, so it has a text node and `:empty` never matches
   — a rule that reads as protection and is inert. Nothing is needed instead:
   the wrapper contributes no box model of its own, and the spacing lives on
   `.arrival__banner`, which only exists when there is something to show. */

.arrival__banner {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
  padding: var(--space-4);
  border: var(--border-width) solid var(--gold-rest);
  border-radius: var(--radius-md);
  background: var(--gold-wash-selected);
  color: var(--text-primary);
  text-decoration: none;
}

/* D28: hover and active change the fill, never the opacity. */
.arrival__banner:hover {
  background: var(--gold-wash-active);
  text-decoration: none;
}

.arrival__banner:focus-visible {
  outline: var(--focus-ring-outline);
  outline-offset: var(--focus-ring-offset);
}

.arrival__glyph { display: flex; color: var(--text-gold); }

.arrival__text { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; flex: 1; }

.arrival__title {
  font-size: var(--type-body-lg-size);
  line-height: var(--type-body-lg-leading);
  font-weight: var(--font-weight-semibold);
}

.arrival__detail {
  font-size: var(--type-caption-size);
  line-height: var(--type-caption-leading);
  color: var(--text-secondary);
}

.arrival__chevron { display: flex; color: var(--text-gold); }

/* ---------------------------------------------------------------------------
 * Notifications and the install path (D92, D93)
 * ------------------------------------------------------------------------ */

.spotlight__notify {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-4);
}

.spotlight__notify-hint {
  margin: 0;
  text-align: center;
  font-size: var(--type-caption-size);
  line-height: var(--type-caption-leading);
  color: var(--text-muted);
}

.push { display: flex; flex-direction: column; gap: var(--space-2); }

.push__status {
  margin: 0;
  text-align: center;
  font-size: var(--type-caption-size);
  line-height: var(--type-caption-leading);
  color: var(--text-secondary);
}

.install { display: flex; flex-direction: column; gap: var(--space-4); }

.install__lede {
  font-size: var(--type-body-lg-size);
  line-height: var(--type-body-lg-leading);
  color: var(--text-secondary);
}

.install__prose {
  margin: 0;
  font-size: var(--type-body-size);
  line-height: var(--type-body-leading);
  color: var(--text-secondary);
}

/* The numbers are the instruction, so they are gold and they are not decoration
   — a person following these is looking for "step 3".

   `list-style: decimal` is NOT redundant. Tailwind's preflight sets
   `ol, ul { list-style: none }` on every list in the app, so an <ol> renders as
   unnumbered paragraphs and the sequence silently disappears — which is exactly
   what it did here until a browser showed it. */
.install__steps {
  list-style: decimal;
  margin: 0 0 var(--space-4);
  padding-left: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  font-size: var(--type-body-size);
  line-height: var(--type-body-leading);
  color: var(--text-primary);
}

.install__steps::marker { color: var(--text-gold); }
.install__steps li::marker { color: var(--text-gold); font-weight: var(--font-weight-semibold); }

.install__steps strong { font-weight: var(--font-weight-semibold); color: var(--text-primary); }

.install__actions { margin-top: var(--space-4); }

/* ---------------------------------------------------------------------------
 * THE SPOTLIGHT REVEAL (D97)
 *
 * The reveal is the LIGHT arriving, not the trophy arriving. A gold band crosses
 * the plate at an even pace; the plate lights up behind it as it passes; then
 * the engraving is read out line by line. It is the only motion in the product
 * that is content rather than chrome.
 *
 * IT WORKS ON AN OPAQUE JPEG. Nothing cuts the trophy out of its background, so
 * it animates every troph-e already in the database and D48's seven-times-dearer
 * Pro tier stays unspent and undecided.
 *
 * TWO GATES, AND BOTH MUST BE TRUE TO HIDE ANYTHING.
 *
 *   `.reveal-armable` is set on <html> by a synchronous inline script in the
 *   head — so it is present only when scripting is ACTUALLY RUNNING, and that
 *   same script removes it after a ceiling so a module that never loads cannot
 *   leave the page dark. This replaced a <noscript> block that did not work: it
 *   rendered before the stylesheets at equal specificity, so these rules won and
 *   the escape was inert. A no-JS Spotlight really was a black rectangle.
 *
 *   `.reveal--armed` is on the article, from the server, on a first view only.
 *
 * So: scripting off, or scripting broken, and the Spotlight is simply a
 * Spotlight. That is the failure mode that matters, on the one screen in the
 * product it would be worst to lose.
 *
 * No box-shadow, here or anywhere (§6). The depth is the wash stack, the borders
 * and this light.
 * ------------------------------------------------------------------------ */

/* The flush card clips to its own radius. The stage scales from 1.04, and
   without this it visibly overhangs the card's 1px border and its corners for
   the first quarter-second — the artwork appearing to escape the card it is
   supposed to be arriving inside. Scoped to the Spotlight rather than added to
   the shared component. */
.spotlight .ui-card { overflow: hidden; }

/* The stage is a wrapper the reveal owns, sitting OUTSIDE the turbo-frame. The
   frame is replaced by broadcast (D69) and anything animated inside it would be
   torn out mid-sequence; the sweep and the light therefore apply here, to an
   element nothing else touches. */
.reveal__stage {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-md);
}

/* The band. Translucent gold on the same anti-diagonal the ambient glow already
   uses, so the light in the reveal and the light in the room come from the same
   place. */
.reveal__stage::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(
    var(--reveal-sweep-angle),
    transparent 35%,
    var(--reveal-sweep) 50%,
    transparent 65%
  );
}

.reveal-armable .reveal--armed .reveal__stage {
  opacity: 0;
  filter: brightness(var(--reveal-dim));
  transform: scale(var(--reveal-scale-from));
}

/* Every line of the engraving starts below its place and invisible. `> *`
   rather than a class per line: the plate's children ARE the sequence, so a line
   added to the view joins the reveal instead of being silently skipped.

   The Replay control and the notification prompt are in here too. They sit
   outside the card, and leaving them out meant the two pieces of chrome that ask
   the player to DO something were fully lit while the trophy behind them was
   still dark.

   `pointer-events: none` because opacity alone leaves them clickable and
   focusable: a keyboard user tabbing straight in would land on an invisible
   focus ring, and a stray tap on the invisible Replay would cancel the reveal
   it cannot see. */
.reveal-armable .reveal--armed .spotlight__plate > *,
.reveal-armable .reveal--armed .spotlight__replay,
.reveal-armable .reveal--armed .spotlight__notify {
  opacity: 0;
  transform: translateY(var(--reveal-lift));
  pointer-events: none;
}

.reveal-armable .reveal--playing .reveal__stage {
  animation: reveal-light var(--reveal-duration-light) var(--reveal-easing-light) both;
}

/* LINEAR, and that is the whole difference between a sweep and a flicker. Under
   the decelerating curve the light uses, 71% of the band's travel happened in
   the first 25% of the time: it crossed the plate in about 160ms of a 900ms
   animation, while the plate was still too dim to show it, and then sat
   off-screen for 600ms. An even traverse is what reads as light moving. */
.reveal-armable .reveal--playing .reveal__stage::after {
  animation: reveal-sweep var(--reveal-duration-light) var(--reveal-easing-sweep) both;
}

.reveal-armable .reveal--playing .spotlight__plate > *,
.reveal-armable .reveal--playing .spotlight__replay,
.reveal-armable .reveal--playing .spotlight__notify {
  animation: reveal-copy var(--reveal-duration-copy) var(--reveal-easing-copy) both;
}

/* The stagger. The plate has up to six children — award, recipient, message,
   club and date, description, share — and the message and description are both
   conditional, so the count varies. `nth-child(n+5)` collapses the tail rather
   than trailing another 90ms per line. */
.reveal-armable .reveal--playing .spotlight__plate > *:nth-child(1) { animation-delay: var(--reveal-delay-copy); }
.reveal-armable .reveal--playing .spotlight__plate > *:nth-child(2) { animation-delay: calc(var(--reveal-delay-copy) + var(--reveal-stagger)); }
.reveal-armable .reveal--playing .spotlight__plate > *:nth-child(3) { animation-delay: calc(var(--reveal-delay-copy) + var(--reveal-stagger) * 2); }
.reveal-armable .reveal--playing .spotlight__plate > *:nth-child(4) { animation-delay: calc(var(--reveal-delay-copy) + var(--reveal-stagger) * 3); }
.reveal-armable .reveal--playing .spotlight__plate > *:nth-child(n+5) { animation-delay: calc(var(--reveal-delay-copy) + var(--reveal-stagger) * 4); }

/* Last of all, and after a real beat rather than one more stagger. These were
   90ms behind the final line, which the eye reads as part of the same run
   instead of as the sequence finishing and the controls then appearing. */
.reveal-armable .reveal--playing .spotlight__replay,
.reveal-armable .reveal--playing .spotlight__notify {
  animation-delay: calc(var(--reveal-delay-copy) + var(--reveal-stagger) * 4 + var(--reveal-duration-copy));
}

@keyframes reveal-light {
  0% {
    opacity: 0;
    filter: brightness(var(--reveal-dim));
    transform: scale(var(--reveal-scale-from));
  }
  /* Opacity resolves early so there is a dim plate for the band to cross.
     Brightness then rises across the WHOLE duration, tracking the band. */
  25% { opacity: 1; }
  100% {
    opacity: 1;
    filter: brightness(1);
    transform: scale(1);
  }
}

/* Travels right across and off. It must END fully clear: a band left resting on
   the artwork would tint a picture the club paid for, which is the one thing the
   plate rule in trophy.css exists to prevent. */
@keyframes reveal-sweep {
  0%   { opacity: 0; transform: translateX(-120%); }
  15%  { opacity: 1; }
  85%  { opacity: 1; }
  100% { opacity: 0; transform: translateX(120%); }
}

@keyframes reveal-copy {
  0%   { opacity: 0; transform: translateY(var(--reveal-lift)); }
  100% { opacity: 1; transform: none; }
}

/* The Replay control. Quiet, and below the card rather than on it — the trophy
   is the hero and a prominent button competing with it would be the tail wagging
   the dog (§9). */
.spotlight__replay {
  display: flex;
  justify-content: center;
  margin-top: var(--space-3);
}

/* REDUCED MOTION: THE CONTENT IS NOT OPTIONAL.
 *
 * The durations already collapse to zero in tokens.css, but a zero-duration
 * animation still runs and would flash its first keyframe — a black plate and an
 * empty engraving — before landing. So the armed state is neutralised outright:
 * the Spotlight renders finished, and nothing moves. The Stimulus controller
 * makes the same check; this is the half that holds when it is slow to arrive.
 *
 * Every selector here carries the same `.reveal-armable .reveal--playing`
 * ancestry as the rule it overrides. The sweep's neutralisation previously did
 * not, and lost on specificity while reading as protection. */
@media (prefers-reduced-motion: reduce) {
  .reveal-armable .reveal--armed .reveal__stage,
  .reveal-armable .reveal--playing .reveal__stage,
  .reveal-armable .reveal--armed .spotlight__plate > *,
  .reveal-armable .reveal--playing .spotlight__plate > *,
  .reveal-armable .reveal--armed .spotlight__replay,
  .reveal-armable .reveal--playing .spotlight__replay,
  .reveal-armable .reveal--armed .spotlight__notify,
  .reveal-armable .reveal--playing .spotlight__notify {
    opacity: 1;
    filter: none;
    transform: none;
    animation: none;
    pointer-events: auto;
  }

  .reveal-armable .reveal--playing .reveal__stage::after,
  .reveal__stage::after { opacity: 0; animation: none; }

  /* There is nothing to replay when nothing moved. A control that silently does
     nothing is worse for these users than no control. */
  .spotlight__replay { display: none; }
}

/* ---------------------------------------------------------------------------
 * The player profile (§7's fourth tab)
 *
 * The one screen the 20px size was reserved for. styleguide.md §9 keeps the
 * player surface flat at 16px and holds 20px for the player's own NAME; the
 * Spotlight borrows it for the award instead, because there the award is what
 * arrived. Here it is used as written.
 * ------------------------------------------------------------------------ */

.profile {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.profile__identity {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  text-align: center;
}

.profile__name {
  margin: 0;
  font-size: var(--type-h2-size);
  line-height: var(--type-h2-leading);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
}

/* Tailwind's preflight already clears the list marker and the padding; both are
   restated because this is a <ul> whose bullets would be wrong and the reset
   should not be something a reader has to know about to trust the rule. */
.profile__clubs {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.profile__club {
  margin: 0;
  font-size: var(--type-body-size);
  line-height: var(--type-body-leading);
  color: var(--text-secondary);
}

/* A section title outside a card, matching the club wall's own heading. */
.profile__heading {
  margin: 0;
  font-size: var(--type-body-lg-size);
  line-height: var(--type-body-lg-leading);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
}

/* The year filter. Wraps rather than scrolls: a player with six seasons on a
   393px column gets two rows of chips, and a horizontal scroller hides the
   oldest year behind a gesture nothing advertises. */
.profile__years {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.profile__actions {
  display: flex;
  justify-content: center;
}

/* The row into Account Settings. The whole card is the target (`href:` on
   CardComponent), so the chevron is the visible half of an affordance that is
   already full-width — global policy's rule for a row that opens something. */
.profile__account {
  display: block;
  text-decoration: none;
  color: inherit;
}

.profile__account:hover {
  text-decoration: none;
}

.profile__chevron {
  display: inline-flex;
  color: var(--text-muted);
}

.profile__account-note {
  margin: 0;
  font-size: var(--type-body-size);
  line-height: var(--type-body-leading);
  color: var(--text-secondary);
}

/* ---------------------------------------------------------------------------
 * Comments under a troph-e (D187), on its Spotlight and on its public page.
 *
 * Below the troph-e and quieter than it: a 16px title (the flat hierarchy), the
 * comments on one card wash split by hairlines, and the form under them. The
 * troph-e stays the hero; nothing here is gold but its links and its button.
 * ------------------------------------------------------------------------ */

/* A custom element lays out inline by default (D69's note on the artwork
   frame), so the frame states its own display. */
.comments {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin-top: var(--space-8);
  scroll-margin-top: var(--space-5);
}

.comments__title {
  margin: 0;
  font-size: var(--type-body-lg-size);
  line-height: var(--type-body-lg-leading);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
}

.comments__count {
  color: var(--text-tertiary);
  font-weight: var(--font-weight-regular);
}

.comments__list {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0 var(--space-4);
  list-style: none;
  background: var(--surface-1);
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-md);
}

.comments__item {
  padding: var(--space-4) 0;
  border-bottom: var(--border-width) solid var(--divider);
}

.comments__item:last-child { border-bottom: 0; }

.comments__form {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.comments__barred,
.report-modal__note {
  margin: 0;
  font-size: var(--type-body-size);
  line-height: var(--type-body-leading);
  color: var(--text-secondary);
}

/* The report in the app: a page in a native modal sheet, not a <dialog>. */
.report-page,
.report-page__form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.report-page__form { gap: var(--space-2); }

/* The words being deleted or reported, quoted in the confirm modal so the
   person knows which comment the button means. */
.comments__quote {
  margin: 0 0 var(--space-3);
  padding-left: var(--space-3);
  border-left: var(--rule-width) solid var(--divider-strong);
  font-size: var(--type-body-size);
  line-height: var(--type-body-leading);
  color: var(--text-secondary);
  overflow-wrap: anywhere;
}

/* "Report this Troph-e" on the public page, under the card and centred with it. */
.spotlight__report {
  display: flex;
  justify-content: center;
  margin-top: var(--space-3);
}
