@charset "UTF-8";
/* ===========================================================================
   Gallop Post — pages.css
   Page-level compositions. style.css owns the tokens and the components that
   inc/partials.php renders; this file owns the blocks the page templates
   compose out of them. Loaded last, so it may rely on every token.

   Same rules as style.css: minmax(0,1fr) on every collapse, pinned track
   counts rather than auto-fit, no outline:none, nothing that only works in one
   theme. Dark needs an explicit override only where a token swap cannot reach,
   and each of those says why.
   =========================================================================== */

/* ------------------------------------------------------ reading measure */

.article { max-width: 100%; }
.article__kicker { margin: 0 0 10px; }
.article__h1 {
  font-family: var(--head);
  font-weight: 600;
  font-size: clamp(30px, 5.4vw, 46px);
  line-height: 1.08;
  letter-spacing: -0.01em;
  margin: 0 0 14px;
}
.article__standfirst {
  font-size: clamp(18px, 2.4vw, 21px);
  line-height: 1.5;
  color: var(--text-2);
  margin: 0 0 20px;
  max-width: 62ch;
}
.article__figure { margin: 22px 0 26px; }
.article__figure img { width: 100%; height: auto; display: block; border: 1px solid var(--line); }
.article__figure figcaption {
  font-size: var(--fs-small);
  color: var(--muted);
  padding: 8px 2px 0;
  border-bottom: 1px solid var(--line);
}
.credit { color: var(--void); }
.credit::before { content: " · "; }

/* The body copy. Everything inside .prose comes from a data file, so the
   selectors are element-level: the copy carries no classes. */
.prose { max-width: 68ch; }
.prose > * + * { margin-top: 1.05em; }
.prose p { margin: 0; line-height: var(--lh-body); }
.prose h2, .prose h3 {
  font-family: var(--head);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: .005em;
  margin-top: 1.7em;
}
.prose h2 { font-size: clamp(22px, 3.2vw, 28px); }
.prose h3 { font-size: clamp(18px, 2.6vw, 22px); }
.prose ul, .prose ol { margin: 0; padding-left: 1.3em; }
.prose li + li { margin-top: .45em; }
.prose strong { font-weight: 600; }
.prose a { text-decoration-thickness: 1px; text-underline-offset: 2px; }
.prose blockquote {
  margin: 1.4em 0;
  padding: 2px 0 2px 18px;
  border-left: 3px solid var(--accent);
  font-size: 1.06em;
  color: var(--text-2);
}
.prose table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--mono);
  font-size: var(--fs-table);
  border: 1px solid var(--line-2);
}
.prose th, .prose td { padding: 7px 10px; border-bottom: 1px solid var(--line); text-align: left; }
.prose thead th { background: var(--panel-2); font-family: var(--head); letter-spacing: .04em; text-transform: uppercase; font-size: var(--fs-tiny); }
.prose tbody tr:nth-child(even) { background: var(--zebra); }
/* A table in running copy is the one thing that can outgrow the column; let it
   scroll rather than push the page sideways (scar #3's other half). */
.prose table { display: block; overflow-x: auto; }

.tags { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; padding: 0; margin: 24px 0 0; }
.tags a {
  display: inline-block;
  font-size: var(--fs-tiny);
  font-family: var(--mono);
  padding: 4px 9px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  color: var(--text-2);
  text-decoration: none;
}
.tags a:hover { border-color: var(--line-3); color: var(--link); }

/* ------------------------------------------------------------- the essay */

.cols--essay { grid-template-columns: minmax(0, 1fr) 300px; }
@media (max-width: 1040px) { .cols--essay { grid-template-columns: minmax(0, 1fr); } }
.cols__main { min-width: 0; }

.writer { display: flex; gap: 12px; align-items: center; margin-bottom: 8px; }
.writer__name { margin: 0; font-family: var(--head); font-size: 19px; font-weight: 600; }
.writer p { margin: 0; }
.aside__more { margin: 10px 0 0; font-size: var(--fs-small); }

/* ------------------------------------------------------------ the front */

.kicker {
  font-family: var(--head);
  font-size: var(--fs-tiny);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--accent-text);
  margin: 0 0 6px;
}

.featured { display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); gap: 26px; }
@media (max-width: 860px) { .featured { grid-template-columns: minmax(0, 1fr); } }
.featured__rest { display: grid; gap: 16px; align-content: start; }

.deskstrip {
  border: 1px solid var(--line-2);
  border-top: 3px solid var(--accent);
  background: var(--accent-wash);
  padding: 20px var(--gut) 16px;
}
.deskstrip__head h2 { margin: 2px 0 4px; font-size: clamp(21px, 3.2vw, 27px); }
.deskstrip__head p { margin: 0; }

.picks { list-style: none; display: grid; gap: 1px; padding: 0; margin: 16px 0 12px;
         background: var(--line); border: 1px solid var(--line);
         grid-template-columns: minmax(0, 1fr); }
@media (min-width: 620px) { .picks { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.pick { background: var(--page); padding: 14px 14px 16px; border-top: 3px solid var(--void); }
.pick--top    { border-top-color: var(--accent); }
.pick--value  { border-top-color: var(--link); }
.pick--out    { border-top-color: var(--ochre); }
.pick__label { margin: 0 0 6px; font-family: var(--head); font-size: var(--fs-tiny);
               letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.pick__who { margin: 0 0 6px; display: flex; align-items: center; gap: 8px;
             font-family: var(--head); font-size: 19px; font-weight: 600; }
.pick__num { margin: 0; font-family: var(--mono); font-size: var(--fs-small); }
.pick__num .muted { display: block; font-size: var(--fs-tiny); }
.pick__why { margin: 8px 0 0; font-size: var(--fs-small); color: var(--text-2); }
.picks--strip .pick { background: transparent; }

.promo { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0;
         border: 1px solid var(--line-2); align-items: stretch; }
@media (max-width: 860px) { .promo { grid-template-columns: minmax(0, 1fr); } }
.promo > div { padding: 24px var(--gut); align-self: center; }
.promo img { width: 100%; height: 100%; object-fit: cover; display: block; min-height: 220px; }
.promo h2 { margin: 0 0 10px; }
.promo--play { background: var(--panel); }

.btn {
  display: inline-block;
  font-family: var(--head);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  font-size: 15px;
  padding: 11px 20px;
  background: var(--accent);
  color: var(--on-accent);
  border: 1px solid var(--accent);
  border-radius: var(--r-sm);
  text-decoration: none;
}
.btn:hover { background: var(--accent-text); border-color: var(--accent-text); color: #FFF; }

.tabs { display: flex; gap: 0; border-bottom: 1px solid var(--line-2); margin-bottom: 10px; }
.tabs button {
  font-family: var(--head);
  font-size: 15px;
  letter-spacing: .05em;
  text-transform: uppercase;
  background: none;
  border: 0;
  border-bottom: 3px solid transparent;
  padding: 9px 13px;
  color: var(--muted);
  cursor: pointer;
}
.tabs button[aria-selected="true"] { color: var(--text); border-bottom-color: var(--accent); }

/* ---------------------------------------------------------- the card page */

.desk { margin: 30px 0; }
.desk__by { display: flex; align-items: center; gap: 9px; margin: 12px 0 0;
            font-size: var(--fs-small); color: var(--muted); }

.vmini img { width: 100%; height: auto; display: block; border: 1px solid var(--line); background: var(--panel); }
.vmini h3 { margin: 10px 0 8px; font-size: 20px; }

/* Pinned track counts, never auto-fit: an empty grid area shows the container's
   gap colour as a phantom panel (scar #13). */
.statgrid--card { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 560px) { .statgrid--card { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 900px) { .statgrid--card { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.statgrid--mini { grid-template-columns: repeat(2, minmax(0, 1fr)); }

.listc--races em { display: block; font-style: normal; font-family: var(--mono);
                   font-size: var(--fs-tiny); color: var(--accent-text); }
.listc--terms a { display: block; padding: 7px 0; border-bottom: 1px solid var(--line); text-decoration: none; }
.listc--terms a:hover { color: var(--link-hover); }
.listc--terms li:last-child a { border-bottom: 0; }

/* ------------------------------------------------------ listings, filters */

.filters, .facets {
  border: 1px solid var(--line-2);
  background: var(--panel);
  padding: 14px var(--gut);
  margin: 0 0 20px;
}
.filters__grid, .facets__field {
  display: grid;
  gap: 12px;
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 620px) {
  .filters__grid, .facets__field { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 960px) {
  .filters__grid, .facets__field { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.filters__act, .facets__actions { display: flex; gap: 10px; align-items: center; margin-top: 12px; flex-wrap: wrap; }
.filters__meta, .facets__note { margin: 10px 0 0; font-size: var(--fs-small); color: var(--muted); }
.filters label, .facets label {
  display: block;
  font-family: var(--head);
  font-size: var(--fs-tiny);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 4px;
}

.emptystate, .emptynote {
  border: 1px dashed var(--line-2);
  padding: 20px var(--gut);
  color: var(--text-2);
  margin: 16px 0;
}

.feed { list-style: none; padding: 0; margin: 0; display: grid; gap: 18px; }
.feed__item { min-width: 0; }
.feed__lead { margin-bottom: 22px; }

.cgroup, .daygroup { margin: 0 0 30px; }
.daygroup__h, .cgroup > h3 {
  font-family: var(--head);
  font-size: clamp(17px, 2.4vw, 21px);
  letter-spacing: .04em;
  text-transform: uppercase;
  border-bottom: 2px solid var(--line-2);
  padding-bottom: 6px;
  margin: 0 0 14px;
}
.daygroup__h .mono { color: var(--muted); font-size: var(--fs-small); letter-spacing: 0; }

.table--winners td:last-child, .table--winners th:last-child { text-align: right; }

/* ------------------------------------------------------------------ dark */

:root[data-theme="dark"] .pick { background: var(--panel); }
/* The wash tokens are light-theme tints; dark needs its own or the strip glows. */
:root[data-theme="dark"] .deskstrip { background: #1A1710; }
:root[data-theme="dark"] .btn:hover { background: var(--scrim-amber); border-color: var(--scrim-amber); color: var(--on-accent); }
/* object-fit images sit against the panel in both themes, but a dark panel
   behind a bright frame needs the same 1px line the light theme gets. */
:root[data-theme="dark"] .promo img,
:root[data-theme="dark"] .article__figure img,
:root[data-theme="dark"] .vmini img { border-color: var(--line); }

/* The diary table: a day of the programme, where only some rows have a card. */
.table--diary td:first-child, .table--diary th:first-child { white-space: nowrap; }
.table--diary tr td:last-child { color: var(--muted); font-size: var(--fs-small); }

/* ------------------------------------------------- the autocomplete popup

   style.css styles the suggest list against generic descendants — `.suggest p`,
   `.suggest a b`, `.suggest a span:last-child` — but search.js builds explicit
   classes instead: a.suggest__opt holding span.suggest__label and an optional
   span.suggest__meta, grouped in div.suggest__group under p.suggest__head, with
   p.suggest__none for an empty result. Those selectors never matched, so the
   "nothing matches" sentence rendered as a 10.5px uppercase group head and the
   option labels lost their weight. These rules address the real markup; being in
   the later sheet, they win where the two overlap. */

.suggest__group + .suggest__group { border-top: 1px solid var(--line); }

.suggest__head {
  margin: 0;
  padding: 7px 12px 5px;
  background: var(--panel-2);
  border-bottom: 1px solid var(--line);
  font-family: var(--head);
  font-size: var(--fs-tiny);
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--muted);
}

.suggest__opt {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 9px 12px;
  text-decoration: none;
  color: var(--text);
  border-bottom: 1px solid var(--line);
}
.suggest__group:last-child .suggest__opt:last-child { border-bottom: 0; }

.suggest__label { font-weight: 600; min-width: 0; }

.suggest__meta {
  margin-left: auto;
  flex: 0 1 auto;
  font-family: var(--mono);
  font-size: var(--fs-tiny);
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Hover and the keyboard cursor must not be the same indicator: a keyboard user
   cannot see a tint that only differs by 1.1:1 (scar #15). Hover tints; the
   cursor tints AND carries a 3px rule. */
.suggest__opt:hover { background: var(--hover-row); }
.suggest__opt.is-sel {
  background: var(--sel-row);
  box-shadow: inset 3px 0 0 var(--accent);
}
.suggest__opt:hover .suggest__meta,
.suggest__opt.is-sel .suggest__meta { color: var(--text-2); }
.suggest__opt:focus-visible { outline: 2px solid var(--ring); outline-offset: -2px; }

/* The empty state is a sentence, not a heading. */
.suggest__none {
  margin: 0;
  padding: 12px;
  font-family: var(--body);
  font-size: var(--fs-small);
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-2);
  background: transparent;
  border: 0;
}

/* Modifiers deliberately left without rules, because they inherit a styled base
   and only exist as filter or JS hooks. Listed so the next audit does not
   re-flag them: .cols__side, .card--grid, .listc--races (base .listc),
   .statgrid--track. */

/* ------------------------------------------------------------ glossary */

.azindex { border: 1px solid var(--line-2); background: var(--panel); padding: 12px var(--gut); margin: 0 0 26px; }
.azindex__group { display: flex; flex-wrap: wrap; gap: 8px; align-items: baseline; }
.azindex__group + .azindex__group { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
.azindex__letter {
  font-family: var(--head); font-weight: 600; font-size: 19px;
  min-width: 1.4em; color: var(--accent-text);
}
.azindex__list { list-style: none; display: flex; flex-wrap: wrap; gap: 6px 14px; padding: 0; margin: 0; }
.azindex__list a { font-size: var(--fs-small); text-decoration: none; }
.azindex__list a:hover { text-decoration: underline; }

.gloss { margin: 0; }
.gloss__item { padding: 18px 0; border-bottom: 1px solid var(--line); }
.gloss__item:target { background: var(--accent-wash); box-shadow: inset 3px 0 0 var(--accent); padding-left: 14px; }
.gloss__term {
  font-family: var(--head); font-weight: 600; font-size: clamp(19px, 2.6vw, 23px);
  margin: 0 0 4px; scroll-margin-top: calc(var(--head-h) + 14px);
}
.gloss__short { margin: 0 0 8px; color: var(--text-2); }
.gloss__def { margin: 0; max-width: 68ch; }
.gloss__def > * + * { margin-top: .9em; }
.gloss__see { margin: 10px 0 0; font-size: var(--fs-small); color: var(--muted); }
.gloss__see a { margin-right: 10px; }

:root[data-theme="dark"] .gloss__item:target { background: #1A1710; }

/* --------------------------------------------------------- the demo page */

/* A 16:9 box that fits a phone in landscape and a desktop alike. The game draws
   at a fixed 1920x1080 and asks for landscape itself, so the frame only has to
   give it the right shape and let it scale. */
.playframe { margin: 0 0 22px; }
.playframe__box {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--scrim);
  border: 1px solid var(--line-2);
  overflow: hidden;
}
.playframe__box iframe {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  border: 0; display: block;
}

/* ------------------------------------------------------------ venue card */

.vcard__map { display: block; padding: 10px 0 0; }
.vcard__map img { width: 100%; height: auto; display: block; background: var(--panel-2); border: 1px solid var(--line); }

/* ------------------------------------------------------------ feed hooks */

/* The feed wrappers exist only to carry data-row and data-tag for the client
   filter; display:contents keeps the card itself as the real grid item. The
   global [hidden]{display:none!important} still beats this when a row is
   filtered out, which is the whole reason that rule is marked !important. */
.feed__item, .feed__lead { display: contents; }
