/* --------------------------------------------------------------------------
   [hidden] has to mean hidden
   -------------------------------------------------------------------------- */

/* main.css declares [hidden] { display: none } early, then sets display on the
   card classes hundreds of lines later — so a .post-card carrying the hidden
   attribute stayed on screen, and the original author had to patch it one
   class at a time (.card-media[hidden] is that patch). Anything the pager or a
   filter hides has to actually go, whatever display its class asks for, so the
   rule is settled here once rather than chased around the stylesheet. */
[hidden] {
  display: none !important;
}

/* --------------------------------------------------------------------------
   WordPress-only additions.

   main.css is the static bundle's stylesheet and is kept byte-identical to it,
   so anything the template had no need for lives here instead.
   -------------------------------------------------------------------------- */

/* The topic pills are links in WordPress, not the labels the static build had
   — each one opens that category's archive. So they need the states a link
   needs, and the current one needs to say it is current. */
.pill[href] {
  transition: background-color 0.25s ease, border-color 0.25s ease, color 0.25s ease;
}
.pill[href]:hover,
.pill[href]:focus-visible {
  border-color: rgba(61, 48, 37, 0.34);
  background: rgba(61, 48, 37, 0.12);
}

/* Filled, the way the language filters mark their pressed chip. */
.pill[aria-current="page"] {
  background: var(--brown);
  border-color: var(--brown);
  color: var(--ivory);
}
.pill[aria-current="page"]:hover,
.pill[aria-current="page"]:focus-visible {
  background: var(--brown);
  border-color: var(--brown);
}

/* --------------------------------------------------------------------------
   The contents list beside an article
   -------------------------------------------------------------------------- */

/* Railed, the article no longer centres itself in the column — it sits against
   the same left edge as everything else on the page. The measure still holds
   at 62ch; it just stops floating. */
.post-body--railed {
  margin-inline: 0;
}

/* A column that never exceeds the viewport: the contents list takes whatever
   is left after the app card and scrolls inside it, so a piece with twenty
   headings cannot push the card below the fold where nobody can reach it. */
.post-toc-rail {
  position: sticky;
  /* Clear of the pinned header, with room to breathe under it. */
  top: calc(var(--nav-h-pinned, 68px) + 1.75rem);
  max-height: calc(100vh - var(--nav-h-pinned, 68px) - 3.5rem);
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.post-toc {
  border-left: 1px solid rgba(61, 48, 37, 0.14);
  padding-left: clamp(1rem, 1.6vw, 1.5rem);
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.post-toc__list {
  list-style: none;
  margin: 1.1rem 0 0;
  padding: 0;
  /* Long lists scroll inside the rail rather than running off the bottom of a
     sticky box that cannot be reached. */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.post-toc__item + .post-toc__item {
  margin-top: 0.15rem;
}

/* Sub-headings step in, so the shape of the piece is legible at a glance. */
.post-toc__item--h3 {
  padding-left: 0.9rem;
}

.post-toc__link {
  display: block;
  position: relative;
  padding: 0.42rem 0;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--bronze);
  transition: color 0.22s ease;
}

.post-toc__link:hover,
.post-toc__link:focus-visible {
  color: var(--brownd);
}

/* The marker sits on the rule the list hangs from, so the eye tracks one line
   down the page rather than a second column of dots. */
.post-toc__link::before {
  content: "";
  position: absolute;
  left: calc(clamp(1rem, 1.6vw, 1.5rem) * -1 - 1px);
  top: 0.42rem;
  bottom: 0.42rem;
  width: 2px;
  background: var(--gold);
  opacity: 0;
  transform: scaleY(0.4);
  transform-origin: top;
  transition: opacity 0.28s ease, transform 0.28s ease;
}

.post-toc__item--h3 .post-toc__link::before {
  left: calc(clamp(1rem, 1.6vw, 1.5rem) * -1 - 0.9rem - 1px);
}

.post-toc__link[aria-current="location"] {
  color: var(--brownd);
  font-weight: 600;
}

.post-toc__link[aria-current="location"]::before {
  opacity: 1;
  transform: scaleY(1);
}

/* Stacked, the rail is a plain block above the article: sticky would pin a
   contents list over the words it is meant to be introducing. */
@media (max-width: 1023px) {
  .post-toc-rail {
    position: static;
    display: block;
    max-height: none;
    margin-bottom: clamp(2rem, 4vw, 3rem);
  }
  .post-toc {
    display: block;
  }
  .post-toc__list {
    overflow-y: visible;
  }
}

@media (prefers-reduced-motion: reduce) {
  .post-toc__link,
  .post-toc__link::before {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   The Santo app card, under the contents list
   -------------------------------------------------------------------------- */
.app-card {
  flex: none;
  margin-top: clamp(1.75rem, 3vw, 2.5rem);
  padding: clamp(1.15rem, 1.9vw, 1.5rem);
  border-radius: var(--r-md, 18px);
  background: var(--brownd, #241b13);
  color: var(--ivory, #fbf7ef);
}

.app-card__name {
  margin-top: 0.55rem;
  font-size: clamp(1.05rem, 1.5vw, 1.2rem);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.02em;
  color: var(--ivory, #fbf7ef);
}

.app-card__body {
  margin-top: 0.6rem;
  font-size: 0.83rem;
  line-height: 1.6;
  color: rgba(251, 247, 239, 0.76);
}

.app-card__stores {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 1.1rem;
}

/* Stacked in the rail, side by side wherever the card has room — on a phone
   the rail is full width, and two badges on one line read better there. */
@media (min-width: 480px) and (max-width: 1023px) {
  .app-card__stores {
    flex-direction: row;
  }
  .app-card__stores > * {
    flex: 1 1 0;
  }
}

.app-store {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.85rem;
  border: 1px solid rgba(251, 247, 239, 0.28);
  border-radius: 999px;
  color: var(--ivory, #fbf7ef);
  transition: background-color 0.25s ease, border-color 0.25s ease;
}

.app-store:hover,
.app-store:focus-visible {
  background: rgba(251, 247, 239, 0.1);
  border-color: rgba(251, 247, 239, 0.5);
}

.app-store__mark {
  flex: none;
}

.app-store__pre {
  display: block;
  font-size: 0.56rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(251, 247, 239, 0.6);
}

.app-store__name {
  display: block;
  font-size: 0.87rem;
  font-weight: 600;
  line-height: 1.25;
}

@media (prefers-reduced-motion: reduce) {
  .app-store {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   A full-width header bar
   -------------------------------------------------------------------------- */

/* The bar itself was always edge to edge; its contents sat in the 1180px
   column, which put the wordmark 130px in from the left on a wide screen and
   read as a boxed strip floating on a full-bleed band. Widened, the wordmark
   and the menu sit against the viewport with a gutter of their own.

   Scoped to the bar by the child combinator, so the footer's .shell and the
   mobile menu overlay are untouched — and shell.js stays as exported. */
.site-nav > .shell {
  width: 100%;
  max-width: none;
  /* Wider than the page gutter, because the bar has no ground of its own to
     sit on and needs the air; capped so it stops spreading on a large monitor. */
  padding-inline: clamp(1.25rem, 3.2vw, 3rem);
}

/* --------------------------------------------------------------------------
   The videos filter — chips for the collection, a select for the language
   -------------------------------------------------------------------------- */

/* One group on one line. Two stacked rows of identical pills read as a single
   wrapped row, and put two black "All" chips directly above each other where
   nothing said which belonged to which axis. */
.media-filter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1.5rem;
}

.media-filter__select {
  position: relative;
  flex: none;
}

/* Sized to the chips beside it, so the row has one baseline and one height
   rather than a form control dropped into a filter bar. */
.media-filter__select .field__input {
  appearance: none;
  -webkit-appearance: none;
  width: auto;
  min-height: 44px;
  padding: 0.5rem 2.6rem 0.5rem 1.1rem;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--bronze);
  background: transparent;
  border-color: rgba(61, 48, 37, 0.2);
  border-radius: 999px;
  cursor: pointer;
}

.media-filter__select .field__input:hover {
  border-color: rgba(61, 48, 37, 0.34);
  color: var(--brownd);
}

.media-filter__select .field__chev {
  right: 1.1rem;
}

/* Narrow: the select takes the full width under the chips rather than being
   squeezed against them. */
@media (max-width: 639px) {
  .media-filter {
    justify-content: flex-start;
  }
  .media-filter__select,
  .media-filter__select .field__input {
    width: 100%;
  }
}

/* --------------------------------------------------------------------------
   Skeletons — what stands in until a renderer arrives
   -------------------------------------------------------------------------- */

/* The reveal system holds every child of a [data-stagger] host at opacity 0
   until app.js adds .is-in — which is precisely the window a placeholder
   exists to cover. Left in the system, the skeletons were laid out correctly
   and painted nothing. They opt out: they are the waiting state, not content
   arriving. */
[data-stagger] > .skel,
[data-stagger] > .skel-row,
[data-reveal].skel,
.skel,
.skel-row {
  opacity: 1;
  transform: none;
  filter: none;
}

/* The tones have to clear the ground they sit on. At 7% on a cream page the
   placeholder was in the DOM, correctly laid out, and invisible — the card was
   four values lighter than the section behind it. */
.skel {
  border-radius: var(--r-md, 18px);
  overflow: hidden;
  background: var(--warmwhite, #fffdf9);
  border: 1px solid rgba(61, 48, 37, 0.11);
}

.skel__media {
  aspect-ratio: 16 / 9;
  background: rgba(61, 48, 37, 0.13);
}

.skel--card .skel__media { aspect-ratio: 16 / 9; }
.skel--tall .skel__media { aspect-ratio: 4 / 5; }
.skel--panel .skel__media { aspect-ratio: 3 / 2; }
.skel--wide .skel__media { aspect-ratio: 21 / 9; }

.skel__body {
  padding: 1.25rem 1.35rem 1.6rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.skel__line {
  display: block;
  height: 0.7rem;
  border-radius: 999px;
  background: rgba(61, 48, 37, 0.11);
}

.skel__line--eyebrow { height: 0.5rem; width: 38%; }
.skel__line--title { height: 1.1rem; width: 82%; margin-top: 0.2rem; }
.skel__line--short { width: 58%; }

/* The shimmer rides across the whole card rather than each bar separately, so
   a card reads as one object catching the light and not as four loading bars.
   Bars and plate share one moving highlight because they share one background
   position on the card itself. */
@media (prefers-reduced-motion: no-preference) {
  .skel {
    position: relative;
    overflow: hidden;
  }
  .skel::after {
    content: "";
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(
      90deg,
      rgba(255, 253, 249, 0) 0%,
      rgba(255, 253, 249, 0.85) 50%,
      rgba(255, 253, 249, 0) 100%
    );
    animation: skel-sweep 1.5s ease-in-out infinite;
  }
}

@keyframes skel-sweep {
  100% { transform: translateX(100%); }
}

/* On a dark band the placeholder has to lighten, not darken, or it disappears
   into the ground it is sitting on. */
.on-dark .skel,
.bg-navy .skel,
.bg-midnight .skel {
  background: rgba(251, 247, 239, 0.05);
  border-color: rgba(251, 247, 239, 0.1);
}
.on-dark .skel__media,
.on-dark .skel__line,
.bg-navy .skel__media,
.bg-navy .skel__line,
.bg-midnight .skel__media,
.bg-midnight .skel__line {
  background: rgba(251, 247, 239, 0.14);
}
.on-dark .skel::after,
.bg-navy .skel::after,
.bg-midnight .skel::after {
  background: linear-gradient(
    90deg,
    rgba(251, 247, 239, 0) 0%,
    rgba(251, 247, 239, 0.09) 50%,
    rgba(251, 247, 239, 0) 100%
  );
}

/* The blog grid is a wide banner over a row of three, so its placeholder has
   to be the same shape or the page jumps when the real cards land. */
.skel-row {
  display: grid;
  gap: clamp(1rem, 2vw, 1.75rem);
  margin-top: clamp(1rem, 2vw, 1.75rem);
}
@media (min-width: 640px) { .skel-row { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .skel-row { grid-template-columns: repeat(3, 1fr); } }

/* --------------------------------------------------------------------------
   Pager
   -------------------------------------------------------------------------- */
.pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  margin-top: clamp(2.5rem, 4vw, 3.5rem);
}

.pager__num,
.pager__step {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0 0.6rem;
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--bronze);
  border: 1px solid transparent;
  border-radius: 999px;
  transition: color 0.25s ease, background-color 0.25s ease, border-color 0.25s ease;
}

.pager__num:hover,
.pager__step:hover:not([disabled]),
.pager__num:focus-visible,
.pager__step:focus-visible {
  color: var(--brownd);
  border-color: rgba(61, 48, 37, 0.2);
}

/* Filled, the way the filter chips mark their pressed state, so "where I am"
   reads the same everywhere on the site. */
.pager__num[aria-current="page"] {
  background: var(--brown);
  border-color: var(--brown);
  color: var(--ivory);
}

.pager__step[disabled] {
  opacity: 0.3;
  cursor: default;
}

.pager__gap {
  padding: 0 0.2rem;
  color: var(--antique, #8a7663);
}

@media (prefers-reduced-motion: reduce) {
  .pager__num,
  .pager__step {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   Paired call-to-action buttons
   -------------------------------------------------------------------------- */

/* Side by side they keep their natural width. Once the pair no longer fits on
   one line they each take a line, and a 228px button in a 354px column leaves
   a ragged edge that reads as a mistake — so on their own line they fill it.

   The query is on the row, not the viewport, because the row is what decides
   whether they wrap. The labels are editable, so a longer one wraps at a wider
   screen; a viewport breakpoint would fire at the wrong moment for anything
   but the labels in place today. */
.hero-actions {
  container-type: inline-size;
  container-name: actions;
}

@container actions (max-width: 30rem) {
  .hero-actions > .btn {
    width: 100%;
    justify-content: center;
  }
}

/* Older browsers without container queries fall back to the viewport, at the
   width the current labels happen to wrap. Without this they keep their
   natural width — the behaviour before this rule, not a broken one. */
@supports not (container-type: inline-size) {
  @media (max-width: 34rem) {
    .hero-actions > .btn {
      width: 100%;
      justify-content: center;
    }
  }
}
