/* ============================================================
   Lab — /lab and /lab/llm-leaderboard
   ------------------------------------------------------------
   Loaded after globals.css via ck_page(['css' => ['lab']]), so
   these rules win ties against it by source order.

   Everything here uses the globals.css custom properties rather
   than literal colours, so the theme toggle carries it without a
   second [data-theme="dark"] block.
   ============================================================ */

/* ---------- Section index: the entry grid ---------- */
/* auto-fit so this becomes a real multi-column grid the moment a
   second Lab entry lands. The max-width is what stops a single
   card stretching the full 1120px container and looking stranded
   — raise or drop it once there are two or more entries. */
.lab-grid {
  display: grid; gap: 28px;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  max-width: 680px; margin: 0 auto;
}

/* .wf-card is a div elsewhere; here it is the link itself. */
.lab-card { text-decoration: none; color: inherit; }
.lab-card h3 { color: var(--ink); }
.lab-card-source {
  margin-top: 20px; padding-top: 16px;
  border-top: 1px solid var(--border);
  font-size: 0.85rem; color: var(--muted);
}

/* ---------- Leaderboard page ---------- */
.lab-crumb { color: inherit; text-decoration: none; }
.lab-crumb:hover { text-decoration: underline; }

/* Wider than .container's 1120px. The whole reason a rendered table beats the
   embed is horizontal room — every pixel of width is a column that doesn't
   wrap. Same 24px gutters as .container so it lines up with the rest of the
   site at narrow widths. */
.lab-wide {
  width: 100%; max-width: 1280px;
  margin: 0 auto; padding: 0 24px;
}
@media (max-width: 600px) { .lab-wide { padding: 0 18px; } }

/* ---------- The leaderboard table ----------
   globals.css has no table styling at all, and admin.css's .admin-table is not
   reusable here — it is scoped to .admin, whose tokens are defined only inside
   that container, and it hardcodes a white background. So the geometry below is
   ported from it and every colour re-expressed as a globals token, which is what
   makes the table follow the theme toggle with no [data-theme] block. */
/* Expanding breaks the panel out of .lb-wide to near-viewport width, because
   25 columns want every pixel. 94vw not 100vw: the remainder absorbs the
   scrollbar so the document itself never gains a horizontal scrollbar. */
.lb-panel { transition: width 0.2s ease, margin 0.2s ease; }
.lb-panel.is-expanded {
  width: 94vw; max-width: 94vw;
  margin-left: calc(50% - 47vw);
}

.lb-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
  max-width: 100%; margin: 36px 0 14px;
}
.lb-toolbar .result-count { color: var(--muted); font-size: 0.9rem; }
.lb-controls { display: flex; gap: 10px; flex-wrap: wrap; }

.lb-toggle, .lb-expand {
  background: none; border: 1px solid var(--border); color: var(--text-soft);
  font: inherit; font-size: 0.875rem; font-weight: 600;
  padding: 8px 16px; border-radius: 999px; cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.lb-toggle:hover, .lb-expand:hover { border-color: var(--accent); color: var(--accent); }
.lb-expand[aria-expanded="true"] { border-color: var(--accent); color: var(--accent); }

/* Columns beyond the core set, and the group header row that labels them, are
   only meaningful once expanded. Hiding whole columns in CSS keeps the group
   colspans honest: they are only ever shown when every column is visible. */
.lb-extra-col { display: none; }
.is-expanded .lb-extra-col { display: table-cell; }
.lb-groups { display: none; }
.is-expanded .lb-groups { display: table-row; }

.lb-group {
  text-align: left; font-size: 0.72rem !important; letter-spacing: 0.08em;
  color: var(--accent) !important;
  border-bottom: 1px solid var(--border);
  padding-bottom: 6px !important;
}
.lb-group-blank { border-bottom-color: transparent; }

/* The table scrolls inside its own box so the page body never scrolls
   sideways, however many columns are on show. */
.lb-scroll {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface);
}

.lb-table {
  width: 100%; border-collapse: collapse;
  font-size: 0.925rem; text-align: left;
}
.lb-table th, .lb-table td {
  padding: 12px 14px; border-bottom: 1px solid var(--border);
  vertical-align: middle; white-space: nowrap;
}
.lb-table thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--surface-2);
  font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--muted); font-weight: 700;
}
.lb-table tbody tr:last-child td { border-bottom: none; }
.lb-table tbody tr:hover td { background: var(--surface-2); }

/* Numbers line up only with tabular figures — without this the decimal points
   wander and the column stops being scannable. */
.lb-num { text-align: right; font-variant-numeric: tabular-nums; }

/* Rank and model stay pinned while the rest scrolls sideways — without this,
   scrolling to TB-Hard leaves you reading numbers with no idea whose they are.
   The left offset of .lb-model must equal .lb-rank's total width, hence the
   fixed width rather than the usual `width: 1%` shrink-to-fit. */
.lb-rank {
  position: sticky; left: 0; z-index: 2;
  width: 46px; min-width: 46px;
  text-align: right; color: var(--muted);
  font-variant-numeric: tabular-nums;
  background: var(--surface);
}
/* Qualified with .lb-table so the `white-space: normal` actually lands: the
   blanket `.lb-table th, .lb-table td` rule above is a two-class selector and
   was outranking a bare `.lb-model`. Left unwrapped, the longest model name
   sized this column to ~478px — wider than a phone viewport — and since it is
   also sticky it then covered every number you scrolled towards. */
.lb-table .lb-model {
  position: sticky; left: 46px; z-index: 2;
  white-space: normal; min-width: 220px;
  background: var(--surface);
}
/* Sticky cells sit above their neighbours, so they need the hover and header
   backgrounds painted explicitly or the scrolled content shows through. */
.lb-table tbody tr:hover .lb-rank,
.lb-table tbody tr:hover .lb-model { background: var(--surface-2); }
.lb-table thead .lb-rank,
.lb-table thead .lb-model { z-index: 4; background: var(--surface-2); }
.lb-table thead th { z-index: 3; }
.lb-name { display: block; font-weight: 600; color: var(--ink); }
.lb-creator { display: block; font-size: 0.8rem; color: var(--muted); margin-top: 2px; }

/* A quiet bar behind the intelligence figure, width set per row by an inline
   --lb-bar custom property. Sits under the text via a pseudo-element so it
   never affects layout or alignment. */
.lb-intel { position: relative; font-weight: 600; color: var(--ink); }
.lb-intel::before {
  content: ""; position: absolute; right: 0;
  /* A fixed height centred on the row, not top/bottom insets: once model names
     wrap the row can be three lines tall, and an inset bar grew with it into a
     filled block. */
  top: 50%; transform: translateY(-50%); height: 1.9em;
  width: var(--lb-bar, 0%);
  background: var(--accent); opacity: 0.14; border-radius: 4px;
}

.lb-sort {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: inherit; text-transform: inherit; letter-spacing: inherit;
}
.lb-sort:hover { color: var(--accent); }
.lb-sort.is-active { color: var(--accent); }
.lb-sort.is-active::after { content: " \2193"; }
.lb-sort.is-active[aria-sort="ascending"]::after { content: " \2191"; }

/* One line under the table: claim, source, freshness. Flex rather than a
   sentence so the three parts keep their own separators and can drop to a
   second line on narrow screens without stranding a lone word. */
.lb-credit {
  margin: 16px 0 0;
  display: flex; flex-wrap: wrap; align-items: baseline;
  column-gap: 10px; row-gap: 4px;
  font-size: 0.9rem; line-height: 1.6; color: var(--muted);
}
.lb-credit > span + span::before {
  content: "\2022"; margin-right: 10px; color: var(--line, currentColor); opacity: 0.5;
}
.lb-credit a { color: var(--accent); }
.lb-updated { white-space: nowrap; }

@media (max-width: 768px) {
  .lb-table th, .lb-table td { padding: 10px 11px; }
  .lb-table { font-size: 0.875rem; }
  /* Same specificity as the base rule above, or its 220px would win. */
  .lb-table .lb-model { min-width: 150px; }
}

/* The embed. Two things globals.css does not solve for us:

     1. its media guard (img, svg, video { max-width: 100% }) does
        not cover iframe, so an unstyled frame overflows on mobile.
     2. the source ships no postMessage/iframeResizer auto-height
        protocol, so aspect-ratio would clip a tall data table.
        Hence an explicit min-height per breakpoint — the frame
        scrolls internally past it. These numbers are eyeballed
        against the live embed and will need revisiting if
        Artificial Analysis change their layout. */
/* Overrides .media-frame's 940px cap. The embed is a wide data table, so it
   gets the same room the rendered table does. */
.lab-embed { margin: 40px auto 0; max-width: 100%; }

/* The stage is what the fallback is measured against — it must wrap the frame
   only, not the figcaption, or the message centres itself against the caption
   too. */
.lab-embed-stage { position: relative; }

.lab-embed iframe {
  display: block; width: 100%; border: 0;
  min-height: 820px;
  position: relative; z-index: 1;   /* paints over the fallback once it loads */
  /* Deliberately transparent, NOT var(--surface-2): an iframe element's own
     background paints whether or not the document inside ever loads, so any
     colour here would cover the fallback in exactly the case it exists for. */
  background: transparent;
}

/* Revealed only if the iframe never paints — a cross-origin frame's
   load state is not readable, so this is the honest limit of what a
   fallback can do here. */
.lab-embed-fallback {
  position: absolute; inset: 0; z-index: 0;
  display: flex; align-items: center; justify-content: center;
  margin: 0; padding: 24px; text-align: center;
  color: var(--muted); font-size: 0.95rem;
}
.lab-embed-fallback a { color: var(--accent); }

.lab-embed figcaption {
  position: relative; z-index: 1;
  padding: 14px 18px; font-size: 0.85rem; line-height: 1.5;
  color: var(--muted); text-align: center;
  background: var(--surface-2);
  border-top: 1px solid var(--border);
}
.lab-embed figcaption a { color: var(--accent); }

@media (max-width: 768px) {
  .lab-embed iframe { min-height: 640px; }
  .lab-embed { margin-top: 32px; }
}
@media (max-width: 600px) {
  .lab-embed iframe { min-height: 560px; }
}

/* ---------- Sourcing / "how to read it" cards ---------- */
/* Both Lab pages run three cards through the two-column
   .feature-grid, which leaves the last one stranded in the left
   column. Span it across both tracks and hold it to one column's
   width so it centres under the pair instead. Keyed off
   :nth-child(odd) so an even count is left alone. */
@media (min-width: 769px) {
  .features .feature-grid > .feature-card:last-child:nth-child(odd) {
    grid-column: 1 / -1;
    width: calc((100% - 24px) / 2); /* 24px = .feature-grid gap */
    justify-self: center;
  }
}
