/*
Theme Name: Wara El Mazzika
Theme URI: https://waraelmazzika.com
Author: Scoop Empire
Description: Editorial theme for Wara El Mazzika — music, and everything behind it, across the MENA region. Hand-built, no framework, no build step, RTL-ready.
Version: 1.0.0
Requires at least: 6.5
Requires PHP: 8.0
License: GPL-2.0-or-later
Text Domain: waraelmazzika
*/

/* ---------------------------------------------------------------- fonts -- */
/* Public Sans 400, Latin: only the network top bar uses it (network-topbar.css). */
@font-face {
  font-family: 'Public Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('assets/fonts/publicsans-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Figtree';
  src: url('assets/fonts/figtree-var-latin.woff2') format('woff2-variations');
  font-weight: 300 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Mono';
  src: url('assets/fonts/plexmono-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Mono';
  src: url('assets/fonts/plexmono-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}

/* --------------------------------------------------------------- tokens -- */
:root {
  /* Canvas is warmed off pure neutral: vinyl and studio, not tech-dark. */
  --wem-black:   #0C0B0A;
  --wem-surface: #151311;
  --wem-raised:  #1D1A17;
  --wem-line:    rgba(255,255,255,.12);
  --wem-line-strong: rgba(255,255,255,.22);
  --wem-ink:     #FFFFFF;
  --wem-body:    #D8D5D0;
  --wem-muted:   #918C85;
  --wem-amber:   #DFA13A;
  --wem-amber-dim: #A9762480;

  /*
   * Two tokens, one family on this site: English sets both to Figtree, so
   * splitting them changes nothing here. Arabic overrides only --font-display,
   * because its display face and its reading face are not the same design.
   */
  --font-display: 'Figtree', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-body:    var(--font-display);
  --font-mono:    'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --fs-hero:  clamp(2.5rem, 6.4vw, 5.25rem);
  --fs-h1:    clamp(2.1rem, 4.4vw, 3.5rem);
  /* A rung between "this article" and "this page's subject". Without it a
     category name and a 404 both set at --fs-h1, and at 390px all three
     clamped to the same 33.6px. */
  --fs-h1-sub: clamp(1.6rem, 3vw, 2.4rem);
  --fs-h2:    clamp(1.45rem, 2.3vw, 2rem);
  --fs-card:  clamp(1.05rem, 1.45vw, 1.3rem);
  --fs-body:  1.1875rem;
  --fs-small: 0.9375rem;
  --fs-meta:  0.75rem;

  --s1: .5rem;  --s2: 1rem;   --s3: 1.5rem; --s4: 2rem;
  --s5: 3rem;   --s6: 4.5rem; --s7: 7rem;

  --wrap: 78rem;
  --measure: 40rem;
  --ease: cubic-bezier(.2,.6,.2,1);
}

/* ---------------------------------------------------------------- reset -- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--wem-black);
  color: var(--wem-body);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.6;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
}

img, svg, video { max-width: 100%; display: block; }
img { height: auto; }

h1, h2, h3, h4 {
  color: var(--wem-ink);
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1.06;
  letter-spacing: -0.025em;
  margin: 0;
  text-wrap: balance;
}

a { color: inherit; }

/* One focus treatment, everywhere. Never removed. */
:focus-visible {
  outline: 2px solid var(--wem-amber);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  inset-block-start: -100px;
  inset-inline-start: var(--s2);
  z-index: 200;
  background: var(--wem-amber);
  color: #14100A;
  padding: var(--s2) var(--s3);
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  text-transform: uppercase;
  letter-spacing: .12em;
  text-decoration: none;
}
.skip-link:focus { inset-block-start: var(--s2); }

.screen-reader-text {
  position: absolute !important;
  width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%);
  white-space: nowrap;
}

/* -------------------------------------------------------------- helpers -- */
.wrap { width: min(100% - 2.5rem, var(--wrap)); margin-inline: auto; }
@media (max-width: 640px) { .wrap { width: min(100% - 2rem, var(--wrap)); } }

/* The amber rule. The brand's one accent, used as a structural mark and
   nowhere else. Sits under headlines and section labels. */
.rule {
  display: block;
  inline-size: 2.75rem;
  block-size: 3px;
  background: var(--wem-amber);
  border: 0;
  margin-block: var(--s2) 0;
  transition: inline-size .45s var(--ease);
}

/* Liner-note voice: every label, credit, date and tag on the site. */
.mono {
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--wem-muted);
}

/* The signature element: sleeve credits. Role in amber, name in ink. */
.credits {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s1) var(--s3);
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  letter-spacing: .1em;
  text-transform: uppercase;
  margin: 0;
  padding: 0;
}
.credits div { display: flex; gap: .85ch; }
/* Pushed to the far end of the strip. Logical property, so it is the right
   edge in English and the left in Arabic without a second rule. Inert when
   the strip wraps onto two lines, which is what should happen on a phone. */
.credits__date { margin-inline-start: auto; }
.credits dt { color: var(--wem-amber); font-weight: 500; }
.credits dd { color: var(--wem-body); margin: 0; }
.credits dd a { text-underline-offset: .3em; }

/* ------------------------------------------------------------- masthead -- */
.masthead {
  position: sticky;
  inset-block-start: 0;
  z-index: 100;
  background: color-mix(in srgb, var(--wem-black) 88%, transparent);
  backdrop-filter: blur(14px);
  border-block-end: 1px solid var(--wem-line);
}
.masthead__inner {
  display: flex;
  align-items: center;
  /* Inert at every width where the row fits. Below about 340px it does not,
     and a second row is a better answer than a page that scrolls sideways. */
  flex-wrap: wrap;
  gap: var(--s4);
  /* Raised from 4.5rem when the front table replaced the hero: four tiles
     carry far more visual weight than one photograph did, and the masthead
     stopped holding its own against them. */
  min-block-size: 5.75rem;
}

.logo {
  display: flex;
  align-items: center;
  text-decoration: none;
  color: var(--wem-ink);
  /* A flex item with an image in it shrinks before it overflows, so a
     crowded bar quietly took the 156px lockup down to 107px at 940px and
     nothing looked broken. The wordmark is the one thing here that is not
     negotiable; the navigation collapses instead. */
  flex-shrink: 0;
}

/* The lockup is one piece of artwork at 1546x400, so it is sized by width and
   the height follows. Height is what needs to stay consistent across contexts,
   hence the ratio arithmetic in the comments. */
.wem-logo { display: block; block-size: auto; inline-size: auto; }
.wem-logo--masthead { inline-size: 9.75rem; }   /* 156px — scaled with the taller masthead */
.wem-logo--footer   { inline-size: 7.9rem; }    /* 126px — the footer is secondary, so it stays where it was */

.nav { margin-inline-start: auto; }
.nav ul { display: flex; gap: var(--s4); list-style: none; margin: 0; padding: 0; }
.nav a {
  display: block;
  padding-block: 1.6rem;
  font-family: var(--font-mono);
  /* Not --fs-meta: that token is for captions and credits, and the nav needs
     to read as navigation next to a 156px lockup. */
  font-size: .875rem;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--wem-muted);
  text-decoration: none;
  position: relative;
  transition: color .25s var(--ease);
}
.nav a:hover { color: var(--wem-ink); }
.nav a::after {
  content: '';
  position: absolute;
  inset-block-end: 1.05rem;
  inset-inline-start: 0;
  inline-size: 0;
  block-size: 2px;
  background: var(--wem-amber);
  transition: inline-size .35s var(--ease);
}
.nav a:hover::after,
.nav .current-menu-item > a::after,
.nav .current-cat > a::after { inline-size: 100%; }
.nav .current-menu-item > a, .nav .current-cat > a { color: var(--wem-ink); }

.nav-toggle {
  display: none;
  margin-inline-start: auto;
  background: none;
  border: 1px solid var(--wem-line-strong);
  color: var(--wem-ink);
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  letter-spacing: .14em;
  text-transform: uppercase;
  padding: .75rem 1rem;
  min-block-size: 44px;
  cursor: pointer;
}

/* Was 860px. Five sections plus Events need 586px of bar, and with the lockup,
   the search control and the language switch beside them the row needs 989px
   before anything has to give — measured, not guessed. */
@media (max-width: 1020px) {
  .nav-toggle { display: block; }
  .nav {
    position: absolute;
    inset-block-start: 100%;
    inset-inline: 0;
    background: var(--wem-surface);
    border-block-end: 1px solid var(--wem-line);
    margin: 0;
  }
  .nav[hidden] { display: none; }
  .nav ul { flex-direction: column; gap: 0; padding: var(--s2) 1.25rem var(--s3); }
  .nav a { padding-block: 1rem; font-size: .8125rem; }
  .nav a::after { inset-block-end: .7rem; }
}

/* The masthead grew for the desktop grid; on a phone that space is the page.
   Placed after the base rule rather than inside it because a media query adds
   no specificity — later in the file is the only reason this wins. */
@media (max-width: 620px) {
  .masthead__inner { min-block-size: 4.75rem; }
  .wem-logo--masthead { inline-size: 7rem; }
  /* Measured, not chosen: at 360px the row is lockup + Menu + search + language
     and the 2rem gap does not fit three times over. The row was already exactly
     full before the search control went in. */
  .masthead__inner { gap: var(--s2); }
}

/* Arabic sets the same four controls 51px wider — القائمة against Menu, English
   against عربي — so the width where the row gives way is language-dependent.
   Tightening here is what keeps both of them on one line at 390px. */
@media (max-width: 480px) {
  .masthead__inner { gap: var(--s1); }
}

/* ------------------------------------------------------ masthead search -- */
/*
 * A field in the bar wherever the bar can hold one, and a disclosure where it
 * cannot. One element does both: it is a flex item in the masthead row at full
 * width, and below the breakpoint it takes a line of its own under the row and
 * the button beside the navigation opens it.
 *
 * The breakpoint is not the nav's. Measured at 1240 with the lockup at 156, the
 * six-item nav at 586 and the language switch at 67, the row has 255px of slack
 * — and Arabic spends 51 of it on longer words, so the field flexes rather than
 * claiming a fixed width. Below that it would be a slot too narrow to type a
 * band's name into, which is what a disclosure is for.
 */
.search-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  background: none;
  border: 1px solid var(--wem-line-strong);
  color: var(--wem-muted);
  min-block-size: 44px;
  min-inline-size: 44px;
  padding: 0;
  cursor: pointer;
  transition: color .25s var(--ease), border-color .25s var(--ease);
}
.search-toggle:hover,
.search-toggle[aria-expanded="true"] { color: var(--wem-ink); border-color: var(--wem-amber); }
.search-toggle__icon { inline-size: 18px; block-size: 18px; }

/* Wins over the UA sheet's [hidden] rule: at this width the field is simply
   part of the bar, and the attribute is only there for the narrow layout. */
.masthead__search[hidden] { display: block; }
.masthead__search { flex: 0 1 13.5rem; min-inline-size: 0; }
.masthead__search .searchform { max-inline-size: none; }

/* In the bar the button is a mark, not a word: 'SEARCH' set in mono is 90px,
   which is more than a third of everything the row has left. */
.searchform__icon { display: none; }
.masthead__search .searchform__icon { display: block; inline-size: 18px; block-size: 18px; }
.masthead__search .searchform__label {
  position: absolute;
  inline-size: 1px; block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.masthead__search .searchform button { padding-inline: 0; min-inline-size: 44px; }
/* Same 44px as the language switch beside it. The base padding made the field
   46.19px, so the two controls sat a pixel out at top and bottom. The button
   stretches with the row, so it follows. */
.masthead__search .searchform input[type="search"] { padding-block: 0; block-size: 44px; }

@media (max-width: 1240px) {
  .search-toggle { display: inline-flex; }
  /* Its own line under the row. Inert while the panel is hidden, because
     display: none takes it out of the flex flow entirely. */
  .masthead__search {
    flex: 0 0 100%;
    border-block-start: 1px solid var(--wem-line);
    padding-block: var(--s2);
  }
  .masthead__search[hidden] { display: none; }
  /* Back to a field you can read a query in, at the end of the line, under
     the control that opened it. margin-inline-start rather than a float, so
     it moves to the other side in Arabic on its own. */
  .masthead__search .searchform { max-inline-size: 26rem; margin-inline-start: auto; }
}

/* ------------------------------------------------------ language switch -- */
/*
 * A control, not a fifth section: bordered, mono, muted, and set in the
 * language it leads to, so a reader who cannot read this page still recognises
 * their own word for it.
 *
 * It sits outside .nav deliberately. Under 1020px the navigation collapses
 * behind a toggle, and the one link that must not be hidden behind a control
 * labelled in a language you cannot read is the one that changes the language.
 */
.lang-switch {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: .8125rem;
  color: var(--wem-muted);
  text-decoration: none;
  border: 1px solid var(--wem-line-strong);
  padding-inline: .8rem;
  min-block-size: 44px;
  white-space: nowrap;
  transition: color .25s var(--ease), border-color .25s var(--ease);
}
.lang-switch:hover { color: var(--wem-ink); border-color: var(--wem-amber); }

/* The English site ships no Arabic face — loading 43KB to draw one word would
   be a poor trade — so the Arabic label leans on the faces every OS already
   has. IBM Plex Mono cannot draw these glyphs and would fall through anyway;
   naming the fallbacks is what stops that landing on something ugly. */
.lang-switch[lang="ar"] {
  font-family: 'IBM Plex Sans Arabic', 'Noto Naskh Arabic', 'Geeza Pro',
               'Segoe UI', Tahoma, sans-serif;
  font-size: .9375rem;
  letter-spacing: normal;
}

@media (max-width: 1020px) {
  /* .nav-toggle already carries the auto margin that pushes this group to the
     end; a second one here would split them apart. */
  .lang-switch { margin-inline-start: 0; }
}

/* ----------------------------------------------------------------- hero -- */
/* The thesis: one full-bleed frame that reads exactly like a Wara El Mazzika
   post at page scale — photograph, scrim, headline in the scrim, credits. */
.hero { position: relative; isolation: isolate; }
.hero__media {
  position: relative;
  /* Through a variable, not a value. The feature sets a wider ratio, and it
     has to do it from an ancestor — a `.feature .hero__media` rule would carry
     more specificity than the `.hero__media` rules inside the media queries
     below and would silently win at every width. A variable set on the
     element beats one inherited from an ancestor, so the breakpoints keep
     control of the phone without a specificity contest. */
  aspect-ratio: var(--hero-ratio, 16 / 9);
  /* No minimum height. aspect-ratio plus a min height grows the *width* to
     satisfy the ratio: with a 22rem floor the frame came out 781.33px inside a
     780px wrap at an 820px viewport — 1.3px past the grid it is supposed to
     line up with, and invisible at every width either side of it. The pinned
     inline size is the belt to that braces. */
  inline-size: 100%;
  max-inline-size: 100%;
  overflow: hidden;
  background: var(--wem-surface);
}
.hero__media > img { inline-size: 100%; block-size: 100%; object-fit: cover; }
/* A mild overall darkening only. The scrim that makes text readable belongs
   to the text block below, so it grows with the headline instead of assuming
   one. */
.hero__media::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top,
    rgba(12,11,10,.55) 0%, rgba(12,11,10,.30) 45%, rgba(12,11,10,.14) 100%);
}
.hero__body {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  z-index: 1;
  padding-block: clamp(3rem, 9vw, 7rem) clamp(var(--s4), 5vw, var(--s6));
  background: linear-gradient(to top,
    rgba(12,11,10,.93) 0%, rgba(12,11,10,.88) 45%,
    rgba(12,11,10,.62) 78%, rgba(12,11,10,0) 100%);
}
.hero__title {
  font-size: var(--fs-hero);
  max-inline-size: 18ch;
  margin-block: var(--s2) var(--s3);
}
.hero__title a { text-decoration: none; }
.hero__title a:hover { color: var(--wem-amber); }
.hero__standfirst {
  max-inline-size: 52ch;
  color: var(--wem-body);
  font-size: 1.0625rem;
  margin-block: 0 var(--s3);
}
/* Three steps, because one breakpoint was doing two jobs: a 4:5 crop is right
   on a phone and absurd on a tablet, where it produced an 883px-tall hero.
   Below 720px the text also stops overlaying the photo — the block is taller
   than the image there, and it used to overflow up behind the masthead. */
@media (max-width: 720px) {
  .hero__media { --hero-ratio: 3 / 2; }
  .hero__body {
    position: static;
    background: none;
    padding-block: var(--s4) 0;
  }
  .hero__media::after { background: none; }
  .hero__title { margin-block-start: var(--s2); }
}
@media (max-width: 520px) {
  .hero__media { --hero-ratio: 4 / 5; }
}

/* -------------------------------------------------------------- section -- */
.section { padding-block: clamp(var(--s5), 6vw, var(--s7)); }
.section + .section,
.front + .section { padding-block-start: 0; }

.section__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  margin-block-end: var(--s4);
  padding-block-end: var(--s3);
  border-block-end: 1px solid var(--wem-line);
}
.section__head > div { display: flex; flex-direction: column; }
.section__head .rule { margin-block-start: .6rem; }
.section__title { font-family: var(--font-mono); font-size: .8125rem; font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase; color: var(--wem-ink); }
.section__more {
  font-family: var(--font-mono); font-size: var(--fs-meta); font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--wem-amber); text-decoration: none; white-space: nowrap;
  /* 19px in a section head, 14px in an article foot. */
  display: inline-block; padding-block: .4rem;
}
.section__more:hover { text-decoration: underline; text-underline-offset: 4px; }

/* ----------------------------------------------------------------- card -- */
/* Card shape carries meaning: portraits for people, sleeves for records,
   wide stills for sessions. */
.grid { display: grid; gap: var(--s4); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 900px) { .grid--3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) {
  .grid--3, .grid--2 { grid-template-columns: 1fr; }
}

/* Carousel rail: the same grid and cards, laid in one row that scrolls. Three
   in view like .grid--3, two under 900px, and under 620px one plus a sliver of
   the next, so a phone can see there is more. [data-carousel] .grid is (0,2,0),
   which is what lets it beat .grid--3's own media-query rules. */
[data-carousel] .grid {
  --per-view: 3;
  grid-template-columns: none;
  grid-auto-flow: column;
  grid-auto-columns: calc((100% - (var(--per-view) - 1) * var(--s4)) / var(--per-view));
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
[data-carousel] .grid::-webkit-scrollbar { display: none; }
[data-carousel] .grid > * { scroll-snap-align: start; }
@media (max-width: 900px) { [data-carousel] .grid { --per-view: 2; } }
@media (max-width: 620px) { [data-carousel] .grid { --per-view: 1.25; } }

/* The buttons ride the row's two edges, centred on the photographs. They sit
   over pictures, so they carry their own dark ground rather than borrowing the
   page's, and z-index 5 clears the card's link overlay (2) and eyebrow (3). */
.carousel { position: relative; }
.carousel__btn {
  position: absolute;
  inset-block-start: 50%;
  transform: translateY(-50%);
  z-index: 5;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(12, 11, 10, .78);
  border: 1px solid var(--wem-line-strong);
  color: var(--wem-ink);
  min-block-size: 44px;
  min-inline-size: 44px;
  padding: 0;
  cursor: pointer;
  transition: color .25s var(--ease), border-color .25s var(--ease), opacity .25s var(--ease);
}
/* display above outranks the UA's [hidden] rule, which the no-JS state needs. */
.carousel__btn[hidden] { display: none; }
.carousel__btn[data-carousel-step="-1"] { inset-inline-start: var(--s2); }
.carousel__btn[data-carousel-step="1"]  { inset-inline-end: var(--s2); }
.carousel__btn:hover { color: var(--wem-amber); border-color: var(--wem-amber); }
/* At either end the arrow fades out of the photograph — but stays on screen,
   dimmed, while it holds keyboard focus, so focus is never on something unseen. */
.carousel__btn[aria-disabled="true"] { opacity: .35; cursor: default; color: var(--wem-ink); border-color: var(--wem-line-strong); }
.carousel__btn[aria-disabled="true"]:not(:focus-visible) { opacity: 0; pointer-events: none; }
.carousel__btn svg { inline-size: 18px; block-size: 18px; fill: none; stroke: currentColor; stroke-width: 1.7; }
/* The arrows point the way the row travels, which RTL reverses. */
[dir="rtl"] .carousel__btn svg { transform: scaleX(-1); }

/* Media and body share one grid cell. This is load-bearing: when the body was
   absolutely positioned it became the containing block for the headline's
   inset:0 overlay, so only the text strip was clickable and the photograph
   was dead. A grid item takes z-index without being positioned. */
/* container-type so the headline can be sized against the card instead of the
   window — see .card__title. .card is already position: relative, so the
   containment does not change what the tile-wide ::before overlay resolves
   against. */
.card { position: relative; display: grid; container-type: inline-size; }
.card__media {
  grid-area: 1 / 1;
  position: relative;
  overflow: hidden;
  background: var(--wem-surface);
  aspect-ratio: 4 / 5;
  /* The ratio sets the height, which means it also stops the media stretching
     to the card — and the headline sits in the same grid cell. Whenever the
     text is taller than the ratio allows (a short tile in a narrow column, a
     three-line headline) the body spilled out below the photograph onto bare
     background and the scrim stopped being a scrim. The picture now grows to
     whichever is taller; the ratio is the floor, not the ceiling.

     inline-size is not decoration. A box with aspect-ratio and a min height
     satisfies the ratio by growing SIDEWAYS: at 1000px the front table's
     middle tile came out 283px wide in a 248px column and pushed 35px of the
     page off the right edge, with nothing on screen to say why. An explicit
     width is what makes the ratio yield instead. */
  inline-size: 100%;
  min-block-size: 100%;
}
.card--wide .card__media { aspect-ratio: 16 / 9; }
/* The front table's shape. Landscape, but a long way short of the 16:9 sleeve:
   4:3 asks the source photography for the least height of any crop that still
   reads as a picture rather than a banner. */
.card--tile .card__media { aspect-ratio: 4 / 3; }
/* Direct child only, so anything else placed in this box (an overlay, a
   badge) is not stretched to fill the card by a descendant selector. */
.card__media > img {
  inline-size: 100%; block-size: 100%; object-fit: cover;
  transition: transform .7s var(--ease);
}
.card:hover .card__media > img { transform: scale(1.045); }
.card__media::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(to top,
    rgba(12,11,10,.62) 0%, rgba(12,11,10,.28) 55%, rgba(12,11,10,.10) 100%);
}
.card__body {
  grid-area: 1 / 1;
  align-self: end;
  position: static;
  z-index: 1;
  padding: 3.25rem var(--s3) var(--s3);
  background: linear-gradient(to top,
    rgba(12,11,10,.93) 0%, rgba(12,11,10,.86) 55%, rgba(12,11,10,0) 100%);
}
/* The eyebrow sits above the tile-wide overlay so it keeps its own link, and
   holds white because muted grey lost to every bright photograph. */
.card__body .mono,
.article__head .mono,
.hero__body .mono {
  position: relative;
  z-index: 3;
  color: var(--wem-ink);
  text-decoration: none;
  display: inline-block;
  /* 19px tall measured, and it sits at z-index 3 above the headline's
     full-tile overlay — so a tap 2px off it opened the article instead of the
     section. The negative margin buys the height back without moving anything. */
  padding-block: .4rem;
  margin-block-start: -.4rem;
  transition: color .25s var(--ease);
}
.card__body .mono:hover,
.article__head .mono:hover,
.hero__body .mono:hover { color: var(--wem-amber); }
/*
 * Sized in cqi — a proportion of the card — not vw.
 *
 * --fs-card was clamp(1.05rem, 1.45vw, 1.3rem), and 1.45vw does not overtake
 * the 1.05rem floor until a 1159px viewport. So from 360px to 1279px every
 * card headline sat at its 16.8px floor while the card image grew 79%, and at
 * 390px the headline was 0.88x the body text it linked to: the most important
 * text on a feed page was the smallest text on it.
 *
 * Worse, the two axes disagreed. Size tracked the viewport; card width tracks
 * the column count. At 619px one card filled 587px and got 16.8px; at 621px
 * the same card was 279px wide and still got 16.8px. On desktop the 624px wide
 * tile got exactly the 20.8px the 300px tile got.
 *
 * cqi makes the headline monotonic in card width, which is the only thing it
 * was ever supposed to track.
 */
.card__title {
  font-size: clamp(1.25rem, 6cqi, 1.7rem);
  font-weight: 700;
  letter-spacing: -.02em;
}
.card__title a { text-decoration: none; }
/* Whole card is clickable, but the link text is still the headline. */
.card__title a::before { content: ''; position: absolute; inset: 0; z-index: 2; }
.card:hover .rule { inline-size: 4.5rem; }
.card:hover .card__title { color: var(--wem-amber); }

/* ------------------------------------------------------------ tracklist -- */
/* Releases are records. A record has square art and sits in a listing. */
.tracklist { list-style: none; margin: 0; padding: 0; }
.tracklist li { border-block-end: 1px solid var(--wem-line); }
.tracklist a {
  position: relative;
  display: grid;
  grid-template-columns: 4.5rem 1fr auto;
  align-items: center;
  gap: var(--s3);
  padding-block: var(--s3);
  text-decoration: none;
  transition: background .3s var(--ease);
}
.tracklist a:hover { background: linear-gradient(to right, var(--wem-surface), transparent 70%); }
.track__art { aspect-ratio: 1; overflow: hidden; background: var(--wem-surface); }
.track__art img { inline-size: 100%; block-size: 100%; object-fit: cover; }
.track__title { display: block; font-size: 1.125rem; font-weight: 700; color: var(--wem-ink); letter-spacing: -.015em; }
.tracklist a:hover .track__title { color: var(--wem-amber); }
.track__meta { display: block; margin-block-start: .4rem; }
.track__date { color: var(--wem-muted); font-family: var(--font-mono); font-size: var(--fs-meta);
  letter-spacing: .1em; text-transform: uppercase; white-space: nowrap; }
@media (max-width: 620px) {
  .tracklist a { grid-template-columns: 3.5rem 1fr; }
  .track__date { grid-column: 2; }
}

/* ------------------------------------------------------------- newslist -- */
/* News is text. No image, because there usually isn't one worth showing. */
.newslist { list-style: none; margin: 0; padding: 0; }
.newslist li { border-block-end: 1px solid var(--wem-line); }
.newslist a {
  display: grid;
  grid-template-columns: 7.5rem 1fr;
  gap: var(--s3);
  align-items: baseline;
  padding-block: var(--s3);
  text-decoration: none;
  color: var(--wem-ink);
  transition: color .25s var(--ease);
}
.newslist a:hover { color: var(--wem-amber); }
.newslist strong { font-size: 1.0625rem; font-weight: 700; letter-spacing: -.015em; }
@media (max-width: 620px) {
  .newslist a { grid-template-columns: 1fr; gap: .5rem; }
}

/* -------------------------------------------------------------- article -- */
/* --------------------------------------------------------- article head -- */
/*
 * The article opens with type, and the photograph follows at its own size.
 *
 * It used to open with a full-bleed 21:9 hero, which this archive cannot pay
 * for. 77 of the lead images are 720px wide and the hero drew them across
 * 1440 — a 2x upscale — after a 16:9 hard crop had been forced onto pictures
 * whose real ratios run from 1.0 to 2.5. Every lead was cropped twice and then
 * stretched, and no art direction survives that.
 *
 * So the frame is gone rather than resized. The image is never drawn wider
 * than the file itself and never re-cropped, which is the largest sharp
 * showing these photographs can have: a small picture now reads as a small
 * sharp picture instead of a big soft one.
 */
.article__head { padding-block-start: clamp(var(--s5), 6vw, var(--s6)); }

.article__figure {
  margin: clamp(var(--s4), 4vw, var(--s5)) 0 0;
  padding-inline: 1.25rem;
  display: flex;
  justify-content: center;
}
/* inline-size: auto is the point of this rule — it lets the file's intrinsic
   width win, so max-inline-size can only ever shrink the picture, never
   stretch it. */
.article__figure img {
  inline-size: auto;
  block-size: auto;
  max-inline-size: min(100%, 64rem);
}

/*
 * The measure is 75% of the page, not a character count.
 *
 * 20ch was drawn for headlines around 52 characters. The Arabic archive's
 * median title is 48 and its upper quartile 56, but almost all of them fall
 * under the 62-character threshold for .is-long, so nearly every article was
 * setting a 48-character headline into a 20-character box and taking three
 * lines to do it. A proportion of the page holds at any type size, where a
 * character count silently depends on one.
 */
.article__title {
  font-size: var(--fs-h1);
  max-inline-size: 75%;
  margin-block: var(--s2) var(--s3);
}
/* Below the tablet break there is no width to give away, so the headline takes
   the full measure and the size steps do the work on their own. */
@media (max-width: 720px) {
  .article__title { max-inline-size: 100%; }
}

.article__body {
  max-inline-size: var(--measure);
  margin-inline: auto;
  padding-block: clamp(var(--s5), 5vw, var(--s6));
  font-size: var(--fs-body);
  line-height: 1.75;
}
.article__body > * + * { margin-block-start: 1.6em; }
.article__body h2 { font-size: var(--fs-h2); margin-block-start: 2.2em; }
.article__body h3 { font-size: 1.35rem; margin-block-start: 2em; }
.article__body a { color: var(--wem-amber); text-underline-offset: 3px; }
.article__body strong { color: var(--wem-ink); }
.article__body blockquote {
  margin-inline: 0;
  padding-inline-start: var(--s3);
  border-inline-start: 3px solid var(--wem-amber);
  font-size: 1.375rem;
  line-height: 1.4;
  font-weight: 500;
  color: var(--wem-ink);
  letter-spacing: -.015em;
}
.article__body img { margin-block: var(--s4); }
.article__body figcaption { margin-block-start: var(--s2); }
.article__body ul, .article__body ol { padding-inline-start: 1.25em; }
.article__body li + li { margin-block-start: .5em; }

.article__foot {
  max-inline-size: var(--measure);
  margin-inline: auto;
  padding-block-end: var(--s5);
  border-block-start: 1px solid var(--wem-line);
  padding-block-start: var(--s3);
}

/* ------------------------------------------------------------ page head -- */
.pagehead { padding-block: clamp(var(--s5), 6vw, var(--s7)) var(--s4); }
.pagehead h1 { font-size: var(--fs-h1-sub); }
.pagehead p { color: var(--wem-muted); max-inline-size: 46ch; margin-block: var(--s3) 0; }

/* ----------------------------------------------------------- pagination -- */
.pagination { display: flex; flex-wrap: wrap; gap: var(--s1); padding-block: var(--s5); }
.pagination .page-numbers {
  display: grid; place-items: center;
  min-inline-size: 44px; min-block-size: 44px;
  padding-inline: .5rem;
  border: 1px solid var(--wem-line);
  font-family: var(--font-mono); font-size: var(--fs-meta); letter-spacing: .1em;
  color: var(--wem-body); text-decoration: none;
  transition: border-color .25s var(--ease), color .25s var(--ease);
}
.pagination .page-numbers:hover { border-color: var(--wem-amber); color: var(--wem-amber); }
.pagination .page-numbers.current { border-color: var(--wem-amber); color: #14100A; background: var(--wem-amber); }

/* --------------------------------------------------------------- search -- */
.searchform { display: flex; gap: 0; max-inline-size: 26rem; }
.searchform input[type="search"] {
  flex: 1;
  background: var(--wem-surface);
  border: 1px solid var(--wem-line);
  color: var(--wem-ink);
  font-family: var(--font-mono);
  font-size: .8125rem;
  letter-spacing: .08em;
  padding: .85rem 1rem;
  min-block-size: 44px;
}
.searchform input[type="search"]::placeholder { color: var(--wem-muted); text-transform: uppercase; letter-spacing: .14em; font-size: var(--fs-meta); }
.searchform button {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--wem-amber);
  border: 1px solid var(--wem-amber);
  color: #14100A;
  font-family: var(--font-mono); font-size: var(--fs-meta); font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase;
  padding-inline: 1.1rem;
  min-block-size: 44px;
  cursor: pointer;
}
.searchform button:hover { background: #EBB055; }

/* -------------------------------------------------------------- contact -- */
/* Fields take the reading measure, not the wrap: a 78rem-wide text input is a
   worse target than a narrow one, and the labels above them line up with the
   standfirst that introduces the page. */
.contact { max-inline-size: var(--measure); padding-block-end: var(--s6); }
.contact__field { margin-block: 0 var(--s4); }
.contact__field label {
  display: block;
  font-family: var(--font-mono); font-size: var(--fs-meta); font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--wem-muted);
  margin-block-end: var(--s1);
}
.contact input[type="text"],
.contact input[type="email"],
.contact select,
.contact textarea {
  inline-size: 100%;
  background: var(--wem-surface);
  border: 1px solid var(--wem-line);
  color: var(--wem-ink);
  font-family: var(--font-body);
  /* 16px, not --fs-small's 15: iOS Safari zooms the whole page in on a focused
     field set below 16px, and the way back out is a pinch. */
  font-size: 1rem;
  padding: .85rem 1rem;
  min-block-size: 44px;
  border-radius: 0;
  transition: border-color .25s var(--ease);
}
.contact textarea { resize: vertical; line-height: 1.6; }
/* The select keeps the platform arrow; appearance:none would mean drawing and
   positioning one, and it would be the only control on the site that needed a
   background image. */
.contact select { appearance: auto; }
.contact :is(input, select, textarea):focus-visible {
  outline: 2px solid var(--wem-amber);
  outline-offset: 2px;
  border-color: var(--wem-amber);
}
.contact :is(input, textarea)[aria-invalid="true"] { border-color: #C2554B; }

.contact__error {
  display: block;
  color: #E08A80;
  font-size: var(--fs-small);
  margin-block-start: var(--s1);
}
.contact__error--form {
  border-inline-start: 3px solid #C2554B;
  padding-inline-start: var(--s2);
  margin-block-end: var(--s4);
  max-inline-size: var(--measure);
}

/* Off-screen rather than display:none — a bot that skips hidden fields still
   fills this one, which is the whole point of it. */
.contact__pot {
  position: absolute;
  inline-size: 1px; block-size: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%);
  overflow: hidden;
}

.contact__actions { margin-block: 0; }
.contact button[type="submit"] {
  background: var(--wem-amber);
  border: 1px solid var(--wem-amber);
  color: #14100A;
  font-family: var(--font-mono); font-size: var(--fs-meta); font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase;
  padding: 0 1.8rem;
  min-block-size: 44px;
  cursor: pointer;
}
.contact button[type="submit"]:hover { background: #EBB055; }

.contact__done {
  border-inline-start: 3px solid var(--wem-amber);
  padding-inline-start: var(--s2);
  max-inline-size: var(--measure);
  margin-block-end: var(--s6);
}

/* --------------------------------------------------------------- footer -- */
/* Sections already carry their own bottom padding; a top margin here added a
   second gap on top of it. */
.footer {
  border-block-start: 1px solid var(--wem-line);
  padding-block: var(--s5);
}
.footer__inner { display: flex; flex-wrap: wrap; gap: var(--s5); justify-content: space-between; }
.footer__blurb { max-inline-size: 32ch; color: var(--wem-muted); font-size: var(--fs-small); margin-block: var(--s3) 0; }
.footer__links { display: flex; flex-wrap: wrap; gap: var(--s4); list-style: none; margin: 0; padding: 0; }
.footer__links a {
  font-family: var(--font-mono); font-size: var(--fs-meta); font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--wem-muted);
  text-decoration: none; display: inline-block; padding-block: .6rem;
}
.footer__links a:hover { color: var(--wem-amber); }
.footer__legal { color: var(--wem-muted); font-family: var(--font-mono); font-size: var(--fs-meta);
  letter-spacing: .04em; margin-block-start: var(--s5); }
/* The separator is a literal in the template, not a ::before here: the dot
   would sit inside this anchor's box and the underline would run under it.
   44px of height so the tap target clears the minimum even at --fs-meta. */
.footer__legal a {
  display: inline-flex; align-items: center;
  min-block-size: 44px;
  color: var(--wem-body); text-decoration: none;
  border-block-end: 1px solid var(--wem-line-strong);
}
.footer__legal a:hover { color: var(--wem-amber); border-block-end-color: var(--wem-amber); }

/* ---------------------------------------------------------- empty / 404 -- */
.empty { padding-block: var(--s7); max-inline-size: 46ch; }
.empty h1 { font-size: var(--fs-h1-sub); }
/* Was unstyled, so it fell through to the UA default 1.5em = 28.5px, a size
   that exists nowhere else in the scale. */
.empty h2 { font-size: var(--fs-h1-sub); }
.empty p { color: var(--wem-muted); margin-block: var(--s3) var(--s4); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

/* ------------------------------------------------------- network chrome -- */
/* Network top bar: styled by network-topbar.css, the file shared by every Scoop
   theme. What stays here is the palette and the .se-social base the footer uses. */
:root {
  --se-red:   #FD0000;
  --se-red-ink: #E00000;
  --se-blue:  #0000FF;
  --se-black: #000000;
  --se-white: #FFFFFF;
}

.se-social { display: flex; gap: 14px; }
.se-social a {
  color: var(--se-black);
  display: flex;
  align-items: center;
  /* 17px icons are well under the 44px touch target, so the hit area is
     padded out without changing how big the icon looks. The inline padding
     matters as much: measured 17px WIDE, under the 24px AA minimum. */
  padding-block: 11px;
  padding-inline: 6px;
}
.se-social a:hover { color: var(--se-red-ink); }
.se-social svg { inline-size: 17px; block-size: 17px; }

/* The same component on the opposite ground. Two classes rather than one, so
   it outranks the network strip's colour without depending on source order —
   a media query would not have raised the specificity at all, and neither
   does a second single-class rule. The inline padding is pulled back to the
   edge so the icons line up with the blurb above them, and the block padding
   stays: it is what makes a 17px icon a 39px target. */
.se-social.footer__social { margin-block-start: var(--s1); }
.se-social.footer__social a { color: var(--wem-ink); padding-inline: 0; margin-inline-end: 12px; }
.se-social.footer__social a:hover { color: var(--wem-amber); }


/* ------------------------------------------------------------- playlist -- */
/* The one section that is not an article. It gets its own surface so it reads
   as a different kind of object — something to play, not something to read. */
.playlist__inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(var(--s4), 5vw, var(--s6));
  align-items: center;
  background: var(--wem-raised);
  border: 1px solid var(--wem-line);
  padding: clamp(var(--s4), 4vw, var(--s6));
}

.playlist__kicker {
  display: flex;
  align-items: center;
  gap: .65rem;
  margin: 0 0 var(--s3);
}
.playlist__month { color: var(--wem-amber); }
.playlist__month::before { content: '— '; color: var(--wem-muted); }

.playlist__title {
  font-size: clamp(1.9rem, 3.2vw, 2.9rem);
  max-inline-size: 16ch;
}
.playlist__note {
  color: var(--wem-body);
  max-inline-size: 46ch;
  margin-block: var(--s3) var(--s4);
  font-size: 1.0625rem;
}

.playlist__cta {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  min-block-size: 44px;
  padding-inline: 1.25rem;
  background: var(--wem-amber);
  color: #14100A;
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background .25s var(--ease);
}
.playlist__cta:hover { background: #EBB055; }
.playlist__cta span { transition: transform .3s var(--ease); }
.playlist__cta:hover span { transform: translateX(3px); }

.playlist__embed iframe {
  inline-size: 100%;
  block-size: 420px;
  border: 0;
  display: block;
}

@media (max-width: 860px) {
  .playlist__inner { grid-template-columns: 1fr; }
  .playlist__embed iframe { block-size: 380px; }
}

/* ------------------------------------------------- hero under real content -- */
/* The hero body was absolutely positioned, so a headline taller than the
   photograph grew upward and ran through the masthead. Stacking media and body
   in one grid cell means a long headline makes the hero taller instead — the
   same fix the cards needed, for the same reason. */
.hero { display: grid; }
.hero__media { grid-area: 1 / 1; align-self: stretch; }
.hero__body {
  grid-area: 1 / 1;
  align-self: end;
  position: static;
  z-index: 1;
}

/* Headlines step down with length. The archive's median is 82 characters
   against the 52 this scale was drawn for. */
.hero__title { max-inline-size: 20ch; }
.hero__title.is-long  { font-size: clamp(2.1rem, 4.6vw, 3.7rem); max-inline-size: 24ch; }
.hero__title.is-xlong { font-size: clamp(1.9rem, 3.8vw, 3rem);   max-inline-size: 28ch; }

.article__title.is-long  { font-size: clamp(1.9rem, 3.6vw, 2.9rem); }
.article__title.is-xlong { font-size: clamp(1.7rem, 3vw, 2.5rem); }

/* Card headlines run long too; keep them from swamping the tile. */
.card__title.is-xlong { font-size: clamp(1.1rem, 5cqi, 1.45rem); }

/* ------------------------------------------------------- hero treatments -- */
/* The photograph across the whole frame with the headline in the scrim over
   it — the brand's own post format. The wrap is the containing block, not the
   section: the body is absolutely positioned, and against the section it
   resolved against the window, which put the headline 54px to the left of the
   photograph it sits on at 1440. */
.hero--bleed { position: relative; }
.hero--bleed .hero__inner { position: relative; }
.hero--bleed .hero__body {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  padding-block: clamp(3rem, 9vw, 7rem) clamp(var(--s4), 5vw, var(--s6));
  padding-inline: clamp(var(--s3), 2.5vw, var(--s4));
  background: linear-gradient(to top,
    rgba(12,11,10,.93) 0%, rgba(12,11,10,.88) 45%,
    rgba(12,11,10,.62) 78%, rgba(12,11,10,0) 100%);
}

/* ---------------------------------------------------------- the feature -- */
/* The hero, contained. It runs the width of the table below it rather than
   the width of the window, so the two read as one block — a lead and the four
   stories behind it — instead of a band that happens to sit above a grid.

   21:9 rather than the hero's 16:9: at 1248px the 16:9 came out 702px tall and
   the table underneath started below the fold, which turns a lead into a
   splash screen. */
.feature { --hero-ratio: 21 / 9; margin-block-start: var(--s5); }
/* The cap is what keeps it a lead rather than a splash screen. At 1360px a
   21:9 frame is 583px tall and the table underneath starts below the fold on
   a laptop; clamped to 30rem the same frame reads as a banner and the first
   row of tiles is on screen with it. A max in the block axis is safe here in
   a way a min is not — only a minimum makes an aspect-ratio grow the width. */
.feature .hero__media { max-block-size: 30rem; }

/* The credits here are one byline, so they need no measure of their own. */

/* --fs-hero is drawn for a page-scale headline on an article, and it tops out
   at 5.25rem — 84px, measured, in a banner 480px tall. That is a poster, not a
   lead. Roughly half of it: large enough to be the first thing read, small
   enough that the photograph is still the thing you see. */
.feature .hero__title { font-size: clamp(1.75rem, 3.2vw, 3rem); }
.feature .hero__title.is-long  { font-size: clamp(1.6rem, 2.8vw, 2.6rem); }
.feature .hero__title.is-xlong { font-size: clamp(1.45rem, 2.4vw, 2.2rem); }

/* The table already carries a bottom margin; the feature's own top margin on
   top of it is a gap twice the size of every other one on the page. */
.front + .feature { margin-block-start: 0; }

@media (max-width: 720px) {
  /* Below here the body stops overlaying the picture (see the .hero__body
     rule in the base hero block) and becomes a paragraph under it, so the
     scrim's inset padding would just indent the text away from everything
     else on the page. */
  .feature .hero__body { padding-inline: 0; }
}

/* ----------------------------------------------------------- event list -- */
/* These events have no photography of their own — the calendar builds its
   tiles from colour — so this is a listing. When and where are the two facts
   worth reading, so they get the fixed columns and the title takes the slack. */
.eventlist { list-style: none; margin: 0; padding: 0; }
.eventlist li { border-block-end: 1px solid var(--wem-line); }
.eventlist a {
  display: grid;
  /* 11.5rem, not 9.5rem: the date is nowrap and measured 160px in English and
     up to 173px in Arabic against a 152px track, so it spilled into the
     gutter on nearly every row. */
  grid-template-columns: 11.5rem minmax(0, 1fr) auto;
  gap: var(--s3);
  align-items: baseline;
  padding-block: var(--s3);
  text-decoration: none;
  color: var(--wem-ink);
  transition: color .25s var(--ease);
}
.eventlist a:hover { color: var(--wem-amber); }
.event__when { color: var(--wem-amber); white-space: nowrap; }
.event__title { font-size: 1.0625rem; font-weight: 700; letter-spacing: -.015em; }
.event__where { color: var(--wem-muted); text-align: end; white-space: nowrap; }

@media (max-width: 760px) {
  .eventlist a { grid-template-columns: 1fr; gap: .45rem; }
  .event__where { text-align: start; white-space: normal; }
}

.events__handoff { padding-block: var(--s5) var(--s6); }

/* ------------------------------------------------------ cards without art -- */
/* A real feed always has gaps — here, Instagram signs its CDN URLs with a
   ten-day expiry, so anything cached longer ago than that has no usable image.
   Rather than a grey rectangle, those tiles become typographic: the headline
   gets the whole card and the amber rule does the work the photograph would. */
.card--textonly .card__media {
  background:
    radial-gradient(120% 90% at 85% 0%, rgba(223,161,58,.10), transparent 60%),
    linear-gradient(160deg, var(--wem-raised) 0%, var(--wem-surface) 55%, var(--wem-black) 100%);
}
.card--textonly .card__media::after { background: none; }
.card--textonly .card__body {
  align-self: stretch;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  background: none;
  padding-block-start: var(--s3);
}
.card--textonly .card__title { font-size: clamp(1.3rem, 6.5cqi, 1.8rem); }
.card--textonly .card__title.is-xlong { font-size: clamp(1.15rem, 5.5cqi, 1.55rem); }
.card--textonly:hover .card__media { border-color: var(--wem-line-strong); }

/* --------------------------------------------------------------- ticker -- */
/* A thin strip under the masthead carrying short scene items. It moves, so it
   has to be stoppable: it pauses on hover and on keyboard focus, and under
   prefers-reduced-motion it stops being an animation at all and becomes a
   plain horizontally scrollable row. */
.ticker {
  border-block-end: 1px solid var(--wem-line);
  background: var(--wem-surface);
  overflow: hidden;
}
.ticker__inner {
  display: flex;
  align-items: stretch;
  max-inline-size: 100%;
}

.ticker__label {
  flex: none;
  display: flex;
  align-items: center;
  gap: .5rem;
  padding-inline: 1.25rem;
  background: var(--wem-amber);
  color: #14100A;
  font-weight: 500;
  letter-spacing: .16em;
  text-decoration: none;
  min-block-size: 42px;
}
.ticker__label:hover { background: #EBB055; }

.ticker__viewport { overflow: hidden; flex: 1 1 auto; min-inline-size: 0; }

.ticker__track {
  display: flex;
  inline-size: max-content;
  animation: wem-ticker 70s linear infinite;
}
.ticker:hover .ticker__track,
.ticker:focus-within .ticker__track { animation-play-state: paused; }

@keyframes wem-ticker {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.ticker__list {
  display: flex;
  align-items: center;
  list-style: none;
  margin: 0;
  padding: 0;
}
.ticker__list a {
  display: flex;
  align-items: baseline;
  gap: .6rem;
  padding: .7rem 1.5rem;
  white-space: nowrap;
  text-decoration: none;
  color: var(--wem-body);
  font-size: .9375rem;
  transition: color .2s var(--ease);
}
.ticker__list a:hover { color: var(--wem-amber); }
.ticker__list li + li { border-inline-start: 1px solid var(--wem-line); }

@media (prefers-reduced-motion: reduce) {
  .ticker__viewport { overflow-x: auto; }
  .ticker__track { animation: none; inline-size: auto; }
  .ticker__track .ticker__list[aria-hidden="true"] { display: none; }
}

@media (max-width: 640px) {
  .ticker__label { padding-inline: .9rem; font-size: .6875rem; }
  .ticker__list a { padding-inline: 1rem; font-size: .875rem; }
}

/* A lead with no photograph at all: the headline carries it, rather than a
   split layout leaving an empty column. */
.hero--text { display: block; padding-block: clamp(var(--s5), 6vw, var(--s7)); }
.hero--text .hero__media { display: none; }
.hero--text .hero__body { position: static; background: none; padding: 0; }
.hero--text .hero__title { max-inline-size: 24ch; }

/* ---------------------------------------------------------------------------
   The front table

   Four stories at once instead of one. The lead fills the height of the two
   tiles beside it and the wide one closes the block off along the bottom, so
   the eye gets a shape to read before it gets a headline — the same thing the
   cards do inside a rail. The tiles are 4:3 rather than the rails' 4:5: this
   is where the largest pictures on the site are rendered, and a tall crop was
   asking the archive for height most of it does not have.

   The lead has no aspect-ratio of its own on purpose: it stretches to whatever
   height the right-hand column lands on, and the photograph fills it. Giving
   it a ratio instead makes the tile drive its own width and it grows out of
   the grid.
   --------------------------------------------------------------------------- */
.front { margin-block: var(--s5) var(--s6); }

.front__grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: var(--s3);
}

.front__slot--lead { grid-column: 1; grid-row: 1 / 3; }
.front__slot--b    { grid-column: 2; grid-row: 1; }
.front__slot--c    { grid-column: 3; grid-row: 1; }
.front__slot--d    { grid-column: 2 / 4; grid-row: 2; }

/* The lead fills its two rows rather than setting its own height. */
.front__slot--lead .card,
.front__slot--lead .card__media { block-size: 100%; }
.front__slot--lead .card__media { aspect-ratio: auto; min-block-size: 26rem; }

/* It carries the page, so it gets the larger setting — the supporting tiles
   stay at card scale so the hierarchy is legible at a glance. */
/* Bigger than a card, smaller than a page headline: the lead has to read
   as the lead without the title outgrowing the tile it sits in. */
.front__slot--lead .card__title { font-size: clamp(1.6rem, 2.6vw, 2.4rem); }
.front__slot--lead .card__body { padding: 4.5rem var(--s4) var(--s4); }

@media (max-width: 900px) {
  /* Two up: the lead keeps the full width above, the rest pair off below. */
  .front__grid { grid-template-columns: 1fr 1fr; }
  .front__slot--lead { grid-column: 1 / 3; grid-row: 1; }
  .front__slot--b    { grid-column: 1; grid-row: 2; }
  .front__slot--c    { grid-column: 2; grid-row: 2; }
  .front__slot--d    { grid-column: 1 / 3; grid-row: 3; }
  /* One row wide, so it reads as a banner. Without a ratio here it has
     nothing to size against and grows to the height of the photograph. */
  .front__slot--lead .card__media { aspect-ratio: 3 / 2; min-block-size: 0; block-size: auto; }
}

@media (max-width: 620px) {
  .front__grid { grid-template-columns: 1fr; gap: var(--s2); }
  .front__slot--lead,
  .front__slot--b,
  .front__slot--c,
  .front__slot--d { grid-column: 1; grid-row: auto; }
  .front__slot--lead .card__media { min-block-size: 0; aspect-ratio: 4 / 3; }
  /* Sized against the tile, like every other card headline. At one column
     wide the four slots are the same 358x448 shape, so type is the only thing
     left carrying the hierarchy — and --fs-h2 gave the lead a 1.08x step over
     its neighbours, which reads as an accident rather than a lead. */
  .front__slot--lead .card__title { font-size: clamp(1.6rem, 8cqi, 2.2rem); }
  .front__slot--lead .card__body { padding: 3.25rem var(--s3) var(--s3); }
}

/* ==================================================================== */
/* Video — Shorts rack + Long-form grid, and the shared play-frame that   */
/* gives both a broadcast-viewfinder chrome: corner brackets and a play   */
/* glyph on real Instagram/YouTube thumbnails, no stock icon set.         */
/* ==================================================================== */

/* One signature rule for this page only: a perforated film-strip in place
   of the plain amber bar every other pagehead uses. Repeating-radial-
   gradient rather than a background image — no asset, no request. */
.rule--film {
  inline-size: 6.5rem;
  block-size: .5rem;
  background:
    repeating-radial-gradient(circle at 4px 50%, var(--wem-ink) 0 1.4px, transparent 1.6px 8px),
    var(--wem-amber);
  background-size: 8px 100%, auto;
}

/* Experience mode wants the content fast, not a mastheaded utility-page
   gap: the section right below IS the first viewport. */
.video-page .pagehead { padding-block: var(--s2) var(--s1); }

.video-section { padding-block: var(--s3) var(--s5); }
.video-section + .video-section { border-block-start: 1px solid var(--wem-line); }

/* --------------------------------------------------------- video-frame -- */
/* Shared by both card sizes: the image, the corner-bracket viewfinder, and
   the play glyph. A button wraps only this, never the caption text below
   it — the target is exactly what looks pressable. */
.video-trigger {
  display: block;
  inline-size: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  text-align: start;
}
.video-trigger:focus-visible .video-frame { outline: 2px solid var(--wem-amber); outline-offset: 3px; }

.video-frame {
  position: relative;
  display: block;
  overflow: hidden;
  aspect-ratio: 9 / 16;
  background: var(--wem-surface);
  border: 1px solid var(--wem-line);
}
.video-frame--wide { aspect-ratio: 16 / 9; }
.video-frame img {
  position: absolute; inset: 0;
  inline-size: 100%; block-size: 100%;
  object-fit: cover;
  transition: transform .4s var(--ease);
}
.video-trigger:hover .video-frame img { transform: scale(1.045); }

/* Four L-shaped corners rather than a full frame border — a viewfinder,
   not a picture frame. Each corner is one gradient pair on a single
   pseudo-element, positioned by background-position, so it is one paint
   layer instead of four extra elements. */
.video-frame__corners {
  position: absolute; inset: .6rem;
  pointer-events: none;
  --corner: 16px;
  --stroke: 2px;
  background-image:
    linear-gradient(var(--wem-amber), var(--wem-amber)), linear-gradient(var(--wem-amber), var(--wem-amber)),
    linear-gradient(var(--wem-amber), var(--wem-amber)), linear-gradient(var(--wem-amber), var(--wem-amber)),
    linear-gradient(var(--wem-amber), var(--wem-amber)), linear-gradient(var(--wem-amber), var(--wem-amber)),
    linear-gradient(var(--wem-amber), var(--wem-amber)), linear-gradient(var(--wem-amber), var(--wem-amber));
  background-repeat: no-repeat;
  background-size:
    var(--stroke) var(--corner), var(--corner) var(--stroke),
    var(--stroke) var(--corner), var(--corner) var(--stroke),
    var(--stroke) var(--corner), var(--corner) var(--stroke),
    var(--stroke) var(--corner), var(--corner) var(--stroke);
  background-position:
    top left, top left,
    top right, top right,
    bottom left, bottom left,
    bottom right, bottom right;
  opacity: .85;
  transition: opacity .25s var(--ease);
}
.video-trigger:hover .video-frame__corners,
.video-trigger:focus-visible .video-frame__corners { opacity: 1; }

/* Triangle drawn with a border, not an SVG or icon font — the one glyph on
   this page earns being a shape, not an asset. */
.video-frame__play {
  position: absolute; top: 50%; left: 50%;
  inline-size: 3rem; block-size: 3rem;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: rgba(20, 16, 10, .55);
  border: 1px solid var(--wem-amber-dim);
  backdrop-filter: blur(2px);
  transition: transform .25s var(--ease), background-color .25s var(--ease);
}
.video-frame__play::before {
  content: '';
  position: absolute; top: 50%; left: 54%;
  transform: translate(-50%, -50%);
  border-style: solid;
  border-width: .55rem 0 .55rem .95rem;
  border-color: transparent transparent transparent var(--wem-amber);
}
.video-trigger:hover .video-frame__play,
.video-trigger:focus-visible .video-frame__play {
  transform: translate(-50%, -50%) scale(1.08);
  background: rgba(20, 16, 10, .8);
}
.video-frame--wide .video-frame__play { inline-size: 3.75rem; block-size: 3.75rem; }
.video-frame--wide .video-frame__play::before { border-width: .7rem 0 .7rem 1.2rem; }

/* -------------------------------------------------------------- shorts -- */
.short-rack {
  display: flex;
  list-style: none;
  margin-block: 0;
  gap: var(--s3);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding-block: 0 var(--s2);
  margin-inline: calc(var(--s3) * -1);
  padding-inline: var(--s3);
}
.short-card {
  flex: 0 0 auto;
  inline-size: 12.5rem;
  scroll-snap-align: start;
}
.short-card__caption {
  margin-block-start: var(--s2);
  font-size: var(--fs-small);
  color: var(--wem-body);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* -------------------------------------------------------------- long-form -- */
.longform-grid { align-items: start; list-style: none; margin: 0; padding: 0; }
.longform-card__body { padding-block-start: var(--s2); }
.longform-card__title { font-size: var(--fs-card); margin-block-end: .4rem; }
.longform-card__excerpt {
  color: var(--wem-muted);
  font-size: var(--fs-small);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ------------------------------------------------------------- lightbox -- */
.video-lightbox {
  border: 1px solid var(--wem-line-strong);
  background: var(--wem-surface);
  padding: 0;
  /* Width and the frame's height are set inline, in px, by sizeLightbox() in
     wem.js — computed from the real viewport and the clicked video's ratio.
     No CSS fallback size: the trigger always sets one before showModal(). */
}
.video-lightbox::backdrop {
  background: rgba(8, 7, 5, .82);
  backdrop-filter: blur(6px);
}
.video-lightbox__frame {
  inline-size: 100%;
  background: #000;
}
.video-lightbox__frame iframe {
  display: block;
  inline-size: 100%; block-size: 100%;
  border: 0;
}
/* Overlapping the top-right corner, not floating above the box: a negative
   offset there rendered outside the dialog's own hit-testable area in
   testing — Chromium routed the click to the dialog underneath it instead of
   the button. z-index above the frame's iframe, which paints its own layer. */
.video-lightbox__close {
  position: absolute;
  z-index: 1;
  inset-block-start: .6rem; inset-inline-end: .6rem;
  inline-size: 2.25rem; block-size: 2.25rem;
  display: grid; place-items: center;
  background: rgba(8, 7, 5, .7);
  border: 1px solid var(--wem-line-strong);
  color: var(--wem-ink);
  font-size: 1.5rem; line-height: 1;
  cursor: pointer;
}
.video-lightbox__close:hover,
.video-lightbox__close:focus-visible { border-color: var(--wem-amber); color: var(--wem-amber); }
.video-lightbox__source {
  display: block;
  text-align: center;
  padding: .75rem;
  font-size: var(--fs-meta);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--wem-muted);
  text-decoration: none;
  border-block-start: 1px solid var(--wem-line);
}
.video-lightbox__source:hover { color: var(--wem-amber); }
.video-lightbox__source[hidden] { display: none; }

@media (max-width: 620px) {
  .short-card { inline-size: 9.75rem; }
  .video-frame__corners { --corner: 12px; inset: .45rem; }
  .video-frame__play { inline-size: 2.5rem; block-size: 2.5rem; }
}

/* ------------------------------------------------------------ reel rail -- */
/* The Videos page's reels, in the Features rail's old carousel: five in view,
   three under 900px, two and a sliver on a phone so it reads as more. */
.reel-rail { list-style: none; margin: 0; padding: 0; }
[data-carousel] .reel-rail { --per-view: 5; }
.reel-rail .short-card { inline-size: auto; }
.reel-rail .short-card__caption { -webkit-line-clamp: 2; }
@media (max-width: 900px) { [data-carousel] .reel-rail { --per-view: 3; } }
@media (max-width: 620px) { [data-carousel] .reel-rail { --per-view: 2.2; gap: var(--s2); } }

/* ------------------------------------------------------ features spread -- */
/* A print spread, not a fourth block of scrim tiles: the headlines sit on the
   page. One story leads with its standfirst and byline under the photograph;
   four more run down the other column as a contents list, each with a
   portrait thumb — Features' card shape, at the size of a mark. */
.spread {
  display: grid;
  grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
  gap: var(--s5) clamp(var(--s4), 4vw, var(--s6));
}
.spread__lead,
.spread__item { position: relative; }
.spread__media { aspect-ratio: 4 / 3; overflow: hidden; background: var(--wem-surface); }
.spread__media img,
.spread__thumb img {
  inline-size: 100%; block-size: 100%; object-fit: cover;
  transition: transform .7s var(--ease);
}
.spread__lead:hover .spread__media img,
.spread__item:hover .spread__thumb img { transform: scale(1.045); }
.spread__title {
  font-size: clamp(1.6rem, 2.7vw, 2.4rem);
  font-weight: 700;
  letter-spacing: -.025em;
  line-height: 1.12;
  text-wrap: balance;
  max-inline-size: 26ch;
  margin-block: var(--s3) 0;
}
.spread__title.is-long  { font-size: clamp(1.45rem, 2.3vw, 2.1rem); }
.spread__title.is-xlong { font-size: clamp(1.3rem, 2vw, 1.85rem); }
.spread__standfirst {
  color: var(--wem-muted);
  max-inline-size: 58ch;
  margin-block: var(--s2) var(--s3);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.spread__lead { align-self: start; }
/* The list runs the full height of the lead beside it, rows shared out
   evenly, so the column ends where the lead's byline does. */
.spread__list { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-rows: 1fr; }
.spread__item {
  display: grid;
  grid-template-columns: 6.5rem minmax(0, 1fr);
  gap: var(--s3);
  align-items: start;
  padding-block: var(--s3);
  border-block-end: 1px solid var(--wem-line);
}
.spread__item:first-child { padding-block-start: 0; }
.spread__thumb { aspect-ratio: 4 / 5; overflow: hidden; background: var(--wem-surface); }
.spread__item-title {
  font-size: 1.125rem;
  font-weight: 700;
  letter-spacing: -.015em;
  line-height: 1.25;
  text-wrap: pretty;
  margin-block-end: .5rem;
}
.spread__title a,
.spread__item-title a { text-decoration: none; transition: color .25s var(--ease); }
/* The whole story is the link; the byline rises above it to reach its author. */
.spread__title a::before,
.spread__item-title a::before { content: ''; position: absolute; inset: 0; z-index: 2; }
.spread .credits a { position: relative; z-index: 3; }
.spread__lead:hover .spread__title a,
.spread__item:hover .spread__item-title a { color: var(--wem-amber); }

@media (max-width: 900px) {
  .spread { grid-template-columns: minmax(0, 1fr); }
  .spread__list { grid-auto-rows: auto; }
}
@media (max-width: 620px) {
  .spread__item { grid-template-columns: 4.5rem minmax(0, 1fr); }
  .spread__item-title { font-size: 1.0625rem; }
}
