/* Läsvärt — the public publications grid.
   Loaded by website/templates/publications/worthyofread.html.

   Written against the brand tokens in core_data/css/design-tokens.css, which
   frontbase.html already loads via core_dependencies/styling_dependencies.html.
   Every colour here used to be a hardcoded hex, which is why the page drifted
   away from the rest of the site — insights.css, its sibling in this same page
   family, was already tokenised and is the model this file now follows.

   The card markup this styles exists twice: server-rendered in the template and
   client-rendered by buildCard() in worthyofread.js for filtered results. Keep
   them identical — the user toggles between the two containers. */

.worthy-shell {
  background: linear-gradient(
    180deg,
    var(--brand-color-surface-muted) 0%,
    var(--brand-color-surface-alt) 42%,
    var(--brand-color-surface) 100%
  );
  min-height: calc(100vh - 80px);
  padding: 7rem 0 3rem;
}

.worthy-header {
  border: 1px solid color-mix(in srgb, var(--brand-color-border) 75%, white);
  border-radius: var(--brand-radius-md);
  background: var(--brand-color-surface);
  box-shadow: 0 16px 36px rgba(16, 24, 40, 0.06);
  padding: 1.4rem;
  margin-bottom: 1.2rem;
}

.worthy-kicker {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.75rem;
  color: var(--brand-color-text-muted);
  font-weight: var(--brand-font-weight-bold, 700);
}

/* ── Filters (inside the header) ───────────────────────────────────────── */

/* Search takes the wider share; the tag picker sits beside it on desktop and
   drops below it on narrow screens. */
.worthy-filters {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: 0.75rem;
}

@media (max-width: 768px) {
  .worthy-filters { grid-template-columns: 1fr; }
}

.worthy-search {
  position: relative;
}

.worthy-search-icon {
  position: absolute;
  top: 50%;
  left: 0.95rem;
  transform: translateY(-50%);
  color: var(--brand-color-text-muted);
  pointer-events: none;
}

#searchInput {
  border-radius: 0.75rem;
  min-height: 2.8rem;
  padding-left: 2.5rem;
  border-color: color-mix(in srgb, var(--brand-color-border) 90%, black);
}

#searchInput:focus {
  border-color: var(--brand-color-accent);
  box-shadow: 0 0 0 3px var(--brand-color-accent-soft);
}

/* Tom Select renders its own control; match the search field's height and
   radius so the two read as one row. */
.worthy-tags .ts-control {
  min-height: 2.8rem;
  border-radius: 0.75rem;
  border-color: color-mix(in srgb, var(--brand-color-border) 90%, black);
  display: flex;
  align-items: center;
}

.worthy-tags .ts-wrapper.focus .ts-control {
  border-color: var(--brand-color-accent);
  box-shadow: 0 0 0 3px var(--brand-color-accent-soft);
}

.worthy-status {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 0.6rem;
  min-height: 1.6rem;
  color: var(--brand-color-text-muted);
  font-size: 0.82rem;
}

.worthy-clear {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.15rem 0.6rem;
  border: 1px solid var(--brand-color-border);
  border-radius: 999px;
  background: var(--brand-color-surface);
  color: var(--brand-color-accent-strong);
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: var(--brand-font-weight-semibold, 600);
  cursor: pointer;
}

.worthy-clear:hover {
  background: var(--brand-color-accent-soft);
  border-color: transparent;
}

.worthy-clear[hidden] {
  display: none;
}

/* ── Grid ──────────────────────────────────────────────────────────────── */

.article-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.1rem;
}

@media (max-width: 992px) {
  .article-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 576px) {
  .article-grid { grid-template-columns: 1fr; }
}

@media (max-width: 991px) {
  .worthy-shell { padding-top: 6.4rem; }
}

@media (max-width: 576px) {
  .worthy-shell { padding-top: 5.6rem; }
  .worthy-header { padding: 1.1rem; }
}

/* ── Card ──────────────────────────────────────────────────────────────── */

.article-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  /* No padding: the cover has to reach the card's edges. The inset lives on
     .article-body instead. */
  padding: 0;
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--brand-color-border) 75%, white);
  border-radius: var(--brand-radius-md);
  background: var(--brand-color-surface);
  transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}

.article-card:hover,
.article-card:focus-within {
  transform: translateY(-4px);
  border-color: color-mix(in srgb, var(--brand-color-accent) 45%, white);
  box-shadow: var(--brand-shadow-soft);
}

/* A card with no hero gets a thin accent rule where the cover would have been.
   Only 2 of 10 articles currently carry an image, so without this the grid
   reads as a page of cards whose pictures failed to load rather than as a
   deliberate text variant. Kept to 3px and the soft accent so it frames the
   card without competing with the ones that do have a cover. */
.article-card--text {
  border-top: 3px solid var(--brand-color-accent-soft);
}

/* ── Cover ─────────────────────────────────────────────────────────────── */

.article-cover {
  display: block;
  /* Reserves the space before the image arrives, so the grid does not jump as
     covers load in. */
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--brand-color-surface-muted);
}

.article-cover img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.35s ease;
}

.article-card:hover .article-cover img {
  transform: scale(1.03);
}

/* ── Lead card ─────────────────────────────────────────────────────────── */

/* The newest article spans the full row in the default grid. Only the
   server-rendered grid ever carries this class — search results stay an even
   grid. Below 992px it is simply an ordinary full-width card. */
.article-card--lead {
  grid-column: 1 / -1;
}

@media (min-width: 992px) {
  .article-card--lead:not(.article-card--text) {
    display: grid;
    grid-template-columns: minmax(0, 11fr) minmax(0, 9fr);
  }

  .article-card--lead .article-cover {
    aspect-ratio: auto;
    min-height: 100%;
  }

  .article-card--lead .article-body {
    padding: 1.6rem 1.8rem;
    justify-content: center;
  }

  .article-card--lead .article-title {
    font-size: 1.5rem;
    line-height: 1.25;
  }

  .article-card--lead .article-excerpt {
    font-size: 1rem;
    -webkit-line-clamp: 5;
    line-clamp: 5;
    flex-grow: 0;
  }
}

.article-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  padding: 1.1rem;
}

/* ── Text ──────────────────────────────────────────────────────────────── */

.article-title {
  font-size: 1.05rem;
  font-weight: var(--brand-font-weight-bold, 700);
  line-height: 1.3;
  margin-bottom: 0.35rem;
}

.article-title a {
  color: var(--brand-color-heading);
  text-decoration: none;
}

.article-title a:hover {
  color: var(--brand-color-accent-strong);
}

.article-meta {
  color: var(--brand-color-text-muted);
  font-size: 0.82rem;
  margin-bottom: 0.6rem;
}

.article-excerpt {
  color: var(--brand-color-text-muted);
  font-size: 0.92rem;
  line-height: 1.6;
  margin-bottom: 1rem;
  /* Together with margin-top:auto on .article-actions, this is what pins the
     button row to the bottom of every card — so a row mixing cards with and
     without covers still lines its buttons up. */
  flex-grow: 1;
  /* Clamped so one long excerpt does not stretch every card in its row. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}

/* ── Tags ──────────────────────────────────────────────────────────────── */

.article-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-bottom: 0.6rem;
}

/* Neutral, not blue. Follows .fc-chip in core_data/css/feed-card.css — the
   house chip, already loaded on this page — but a size up: .fc-chip is tuned
   for a dense feed row and looks cramped on a card this roomy. The tags are
   metadata, so they should sit quietly under the cover rather than compete
   with the title for attention, which the old blue outline did. */
.article-tag {
  padding: 0.16rem 0.55rem;
  border: 1px solid var(--brand-color-border);
  border-radius: 999px;
  background: var(--brand-color-surface-muted);
  color: var(--brand-color-text-muted);
  font-size: 0.72rem;
  font-weight: var(--brand-font-weight-medium, 500);
  line-height: 1.5;
}

/* ── Actions ───────────────────────────────────────────────────────────── */

/* Same idiom as .fc-actions: a rule separating the controls from the prose, so
   the buttons read as a footer rather than as another paragraph. */
.article-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-top: auto;
  padding-top: 0.7rem;
  border-top: 1px solid color-mix(in srgb, var(--brand-color-border) 70%, white);
}

.article-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.38rem 0.75rem;
  border: 1px solid var(--brand-color-border);
  border-radius: var(--brand-radius-sm);
  background: var(--brand-color-surface);
  color: var(--brand-color-text);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: var(--brand-font-weight-semibold, 600);
  line-height: 1.5;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}

.article-btn-primary {
  border-color: transparent;
  background: var(--brand-color-accent-soft);
  color: var(--brand-color-accent-strong);
}

.article-btn-primary:hover {
  background: color-mix(in srgb, var(--brand-color-accent-soft) 60%, var(--brand-color-accent));
  color: var(--brand-color-surface);
}

/* The arrow nudges on hover — the same small signal .insights-cta uses, so the
   two public card types behave alike. */
.article-btn-primary i {
  transition: transform 0.2s ease;
}

.article-btn-primary:hover i {
  transform: translateX(3px);
}

/* Pushed right, so Dela sits in the same place on every card regardless of how
   wide the primary label renders. */
.article-btn-share {
  margin-left: auto;
  color: var(--brand-color-text-muted);
}

.article-btn-share:hover {
  background: var(--brand-color-surface-muted);
  border-color: color-mix(in srgb, var(--brand-color-border) 100%, black 12%);
  color: var(--brand-color-text);
}

/* Confirmation state, set by worthyofread.js for ~2s after a successful copy. */
.article-btn-share.is-copied {
  border-color: transparent;
  background: color-mix(in srgb, var(--brand-color-success) 12%, white);
  color: var(--brand-color-success);
}

/* ── Pills ─────────────────────────────────────────────────────────────── */

.cat-pill-row,
.subcat-pill-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 1rem;
}

.subcat-pill-row {
  margin-top: -0.4rem;
}

/* On phones the pills scroll sideways instead of wrapping into a tall stack
   that pushes the articles off the first screen. */
@media (max-width: 576px) {
  .cat-pill-row,
  .subcat-pill-row {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 0.15rem;
  }

  .cat-pill-row::-webkit-scrollbar,
  .subcat-pill-row::-webkit-scrollbar {
    display: none;
  }

  .cat-pill,
  .subcat-pill {
    flex: 0 0 auto;
  }
}

.cat-pill,
.subcat-pill {
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--brand-color-border);
  border-radius: 999px;
  background: var(--brand-color-surface-muted);
  color: var(--brand-color-text-muted);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: var(--brand-font-weight-semibold, 600);
  cursor: pointer;
  transition: color 0.16s ease, background 0.16s ease, border-color 0.16s ease;
}

.cat-pill:hover,
.subcat-pill:hover {
  background: var(--brand-color-surface-alt);
  color: var(--brand-color-accent-strong);
}

.cat-pill.active,
.subcat-pill.active {
  background: var(--brand-color-accent-strong);
  border-color: var(--brand-color-accent-strong);
  color: var(--brand-color-surface);
}

.subcat-pill {
  font-size: 0.76rem;
  padding: 0.28rem 0.7rem;
}

/* ── States ────────────────────────────────────────────────────────────── */

.results-state,
.article-empty-state {
  border: 1px dashed color-mix(in srgb, var(--brand-color-border) 100%, black 8%);
  border-radius: var(--brand-radius-md);
  background: var(--brand-color-surface-muted);
  color: var(--brand-color-text-muted);
  text-align: center;
}

/* Rendered inside .article-grid, so without this it filled one column of
   three and the message sat squeezed in the top-left corner. */
.results-state {
  grid-column: 1 / -1;
  padding: 1.5rem;
}

.article-empty-state {
  padding: 3.5rem 1.5rem;
}

.article-empty-icon {
  font-size: 2.6rem;
  color: color-mix(in srgb, var(--brand-color-accent) 40%, white);
  display: block;
  margin-bottom: 0.75rem;
}

/* ── Focus & motion ────────────────────────────────────────────────────── */

/* The page had no focus styling at all. :focus-visible rather than :focus so a
   mouse click does not leave a ring behind on the card it just opened. */
.article-btn:focus-visible,
.cat-pill:focus-visible,
.subcat-pill:focus-visible,
.worthy-clear:focus-visible,
.article-title a:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--brand-color-accent-soft);
  border-radius: var(--brand-radius-sm);
}

@media (prefers-reduced-motion: reduce) {
  .article-card,
  .article-cover img,
  .article-btn,
  .article-btn-primary i,
  .cat-pill,
  .subcat-pill {
    transition: none;
  }

  .article-card:hover,
  .article-card:focus-within {
    transform: none;
  }

  .article-card:hover .article-cover img {
    transform: none;
  }
}
