/* ═══════════════════════════════════════════════════════════════════════════
   MOZADO — articles
   The public reading half: static pages built by tools/build-articles.mjs.

   Two grounds. The landing's night (#08090b) carries the site header, the
   list headings and every article's title, so a reader who lands here from a
   search result knows at once they are on Mozado. The warm paper of the app
   (#f4f2ee) carries the reading, because a long text is kinder on paper than
   on black. The cover of each article sits across the seam between the two.

   Logical properties throughout; the section is RTL-first like the app.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Estedad and Archivo are cut for this section by tools/subset-fonts.py:
   Persian and punctuation only for the headings, and the six letters of the
   wordmark. The landing keeps the full files. */
@font-face{
  font-family:"Estedad";
  src:url("/assets/fonts/Estedad-fa-var.woff2") format("woff2-variations"),
      url("/assets/fonts/Estedad-fa-var.woff2") format("woff2");
  font-weight:100 900;
  font-display:swap;
}
@font-face{
  font-family:"Vazirmatn";
  src:url("/assets/fonts/Vazirmatn-var.woff2") format("woff2-variations"),
      url("/assets/fonts/Vazirmatn-var.woff2") format("woff2");
  font-weight:100 900;
  font-display:swap;
}
/* The wordmark only: one static instance at its own weight and width, holding
   the letters of «MOZADO» and nothing else (1 KB against the landing's 88). */
@font-face{
  font-family:"Archivo";
  src:url("/assets/fonts/Archivo-brand.woff2") format("woff2");
  font-weight:700;
  font-stretch:125%;
  font-display:swap;
  unicode-range:U+0041, U+0044, U+004D, U+004F, U+005A;
}

:root{
  --paper:      #f4f2ee;
  --paper-2:    #eae7e0;
  --surface:    #ffffff;
  --ink:        #14161a;
  --ink-2:      #4f535a;   /* a step darker than the app's: body-adjacent text is read for minutes here */
  --ink-3:      #7d8189;
  --line:       rgba(20,22,26,.10);

  --night:      #08090b;
  --night-line: rgba(237,234,227,.14);
  --bone:       #edeae3;
  --bone-dim:   #a7a49d;

  --accent:     #ff3b14;
  --accent-ink: #c2300e;
  --accent-wash:#ffece6;

  --sh-1: 0 1px 2px rgba(20,22,26,.04), 0 6px 16px rgba(20,22,26,.05);
  --sh-2: 0 2px 6px rgba(20,22,26,.06), 0 18px 44px rgba(20,22,26,.10);
  --e-out: cubic-bezier(.16,1,.3,1);

  --f-display: "Estedad", system-ui, sans-serif;
  --f-body:    "Vazirmatn", system-ui, sans-serif;
  --f-brand:   "Archivo", "Estedad", sans-serif;
  --f-code:    ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --gutter:  clamp(16px, 4vw, 48px);
  --wide:    1120px;
  /* 68 characters of Vazirmatn at 17px, measured: 623px. Held as rem rather
     than ch because ch resolves against whichever element uses it — in the
     grid and the byline that was a smaller font and a narrower column. */
  --measure: 39rem;
  --overlap: clamp(56px, 9vw, 132px);   /* how far the cover rides up into the night */
}

*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; }
body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font-family:var(--f-body);
  font-size:16px;
  line-height:1.7;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
img{ display:block; max-inline-size:100%; }
::selection{ background:var(--accent-wash); color:var(--ink); }
:focus-visible{ outline:2px solid var(--accent); outline-offset:3px; border-radius:6px; }
:focus:not(:focus-visible){ outline:none; }

/* The page reveal clips this element and shows the next page through it
   (js/page-reveal.js). It must carry its own ground, and must never carry a
   transform — a transform would re-anchor the fixed progress bar to it. */
#stage{ background:var(--paper); min-block-size:100vh; }

/* ── reading progress ─────────────────────────────────────────────────────
   Driven by GSAP ScrollTrigger (js/articles.js). Without script it stays at
   zero, which is the right default for a bar that has nothing to report. In
   RTL a read page fills from the right. */
.progress{
  position:fixed;
  inset-inline:0;
  inset-block-start:0;
  z-index:60;
  block-size:3px;
  pointer-events:none;
}
.progress i{
  display:block;
  block-size:100%;
  background:var(--accent);
  transform:scaleX(0);
  transform-origin:100% 50%;
}
[dir="ltr"] .progress i{ transform-origin:0 50%; }

/* ═══ the night band ═════════════════════════════════════════════════════ */

.site-head{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--gutter);
  padding:14px var(--gutter);
  background:var(--night);
  color:var(--bone);
}
.brand{
  display:inline-flex;
  align-items:center;
  gap:10px;
  min-block-size:44px;
  color:var(--bone);
  text-decoration:none;
}
.brand__mark{ inline-size:22px; block-size:22px; color:var(--accent); flex:none; }
/* The landing's wordmark, wide and spaced as it is there. */
.brand__word{
  font-family:var(--f-brand);
  font-weight:700;
  font-stretch:125%;
  font-variation-settings:"wdth" 125;
  font-size:13px;
  letter-spacing:.16em;
  direction:ltr;
}
.site-nav{ display:flex; align-items:center; gap:4px; }
.site-nav a{
  display:inline-flex;
  align-items:center;
  min-block-size:44px;
  padding-inline:12px;
  border-radius:999px;
  color:var(--bone-dim);
  font-size:14px;
  text-decoration:none;
  transition:color .2s var(--e-out);
}
.site-nav a:hover,
.site-nav a[aria-current="page"]{ color:var(--bone); }
/* Near-black on the orange, never white — the site's one rule for a filled
   accent button. */
.site-nav .site-nav__cta{
  margin-inline-start:6px;
  padding-inline:18px;
  background:var(--accent);
  color:#14161a;
  font-family:var(--f-display);
  font-weight:800;
}
.site-nav .site-nav__cta:hover{ color:#14161a; background:#ff4a26; }
.site-nav a{ white-space:nowrap; }
/* On a phone the band keeps the mark and the one call to action: the mark
   already goes home, and every article's breadcrumb leads back to the list. */
@media (max-width:560px){
  .site-nav a:not(.site-nav__cta){ display:none; }
}

/* ── list heading ─────────────────────────────────────────────────────────
   The night continues under the heading, and the type does the work: one
   very large word, a quiet line, the category chips. */
.list-head{
  padding:clamp(40px, 8vw, 104px) var(--gutter) clamp(32px, 5vw, 56px);
  background:var(--night);
  color:var(--bone);
}
.list-head__inner{ max-inline-size:var(--wide); margin-inline:auto; }
.eyebrow{ margin:0; font-size:13px; color:var(--bone-dim); }
.eyebrow a{ color:inherit; }
.list-head h1{
  margin:10px 0 0;
  font-family:var(--f-display);
  font-weight:900;
  font-size:clamp(44px, 9vw, 96px);
  line-height:1.05;
  letter-spacing:-.01em;
}
.list-head .lede{
  max-inline-size:36em;
  margin:20px 0 0;
  font-size:clamp(16px, 1.6vw, 18px);
  line-height:1.9;
  color:var(--bone-dim);
}

.chips{ display:flex; flex-wrap:wrap; gap:8px; margin-block-start:32px; }
.chip{
  display:inline-flex;
  align-items:center;
  min-block-size:40px;
  padding-inline:16px;
  border:1px solid var(--night-line);
  border-radius:999px;
  color:var(--bone-dim);
  font-size:14px;
  text-decoration:none;
  transition:color .2s var(--e-out), border-color .2s var(--e-out);
}
.chip:hover{ color:var(--bone); border-color:rgba(237,234,227,.32); }
.chip[aria-current="page"]{
  border-color:var(--accent);
  background:var(--accent);
  color:#14161a;
  font-weight:700;
}

/* Search: a plain GET form to /articles/search/, so it works before any
   script runs. On the results page the same field narrows the list live. */
.search{ max-inline-size:32em; margin-block-start:28px; }
.list-head--search .search{ margin-block-start:24px; }
.search label{ display:block; margin-block-end:8px; font-size:13px; color:var(--bone-dim); }
.search__row{ display:flex; gap:8px; }
.search input{
  flex:1;
  min-inline-size:0;
  min-block-size:48px;
  padding-inline:16px;
  border:1px solid var(--night-line);
  border-radius:14px;
  background:transparent;
  color:var(--bone);
  font:inherit;
  font-size:16px;              /* 16px or iOS zooms the page on focus */
  -webkit-appearance:none;
  appearance:none;
}
.search input:hover{ border-color:rgba(237,234,227,.32); }
.search input:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
.search button{
  min-block-size:48px;
  padding-inline:20px;
  border:0;
  border-radius:14px;
  background:var(--bone);
  color:var(--night);
  font:inherit;
  font-weight:700;
  cursor:pointer;
}
.search button:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
.search__status{ margin:14px 0 0; font-size:14px; color:var(--bone-dim); }

/* ── article heading ──────────────────────────────────────────────────────
   Aligned to the reading column, not centred: the title starts where the
   text will start, and the page reads as one column from the top. The bottom
   padding is where the cover will sit. */
.article-head{
  padding:clamp(28px, 6vw, 72px) var(--gutter) calc(var(--overlap) + clamp(32px, 5vw, 56px));
  background:var(--night);
  color:var(--bone);
}
.article-head__inner{ max-inline-size:var(--wide); margin-inline:auto; }
.crumbs{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; font-size:13px; color:var(--bone-dim); }
.crumbs a{ color:inherit; text-decoration:none; }
.crumbs a:hover{ color:var(--bone); }
.article-head h1{
  max-inline-size:17em;
  margin:18px 0 0;
  font-family:var(--f-display);
  font-weight:800;
  font-size:clamp(30px, 5.2vw, 54px);
  line-height:1.3;
  text-wrap:balance;
}
.article-head .lede{
  max-inline-size:38em;
  margin:18px 0 0;
  font-size:clamp(16px, 1.7vw, 19px);
  line-height:1.9;
  color:var(--bone-dim);
}
.article-meta{
  display:flex;
  flex-wrap:wrap;
  gap:8px;
  margin:24px 0 0;
  font-size:14px;
  color:var(--bone-dim);
}

.cover{
  max-inline-size:var(--wide);
  margin:calc(-1 * var(--overlap)) auto 0;
  padding-inline:var(--gutter);
  box-sizing:content-box;
}
.cover img{
  inline-size:100%;
  block-size:auto;
  aspect-ratio:5/3;
  object-fit:cover;
  border-radius:clamp(16px, 2.4vw, 28px);
  background:var(--paper-2);
  box-shadow:var(--sh-2);
}

/* ═══ reading ════════════════════════════════════════════════════════════ */

/* Text in a 68ch column at the reading side; the table of contents keeps the
   other side on wide screens, where there is room to have both in view. */
.article-layout{
  display:grid;
  gap:28px;
  max-inline-size:var(--wide);
  margin:clamp(36px, 6vw, 72px) auto 0;
  padding-inline:var(--gutter);
  box-sizing:content-box;
}
@media (min-width:1024px){
  .article-layout{
    grid-template-columns:minmax(0, var(--measure)) minmax(200px, 280px);
    justify-content:space-between;
    column-gap:clamp(40px, 6vw, 96px);
  }
  .toc{ grid-column:2; grid-row:1; }
  .prose{ grid-column:1; grid-row:1; }
}

.prose{
  max-inline-size:var(--measure);
  font-size:17px;
  line-height:1.9;
}
.prose > *{ margin-block:0; }
.prose > * + *{ margin-block-start:1.15em; }
.prose h2{
  margin-block-start:2.3em;
  font-family:var(--f-display);
  font-weight:800;
  font-size:clamp(22px, 2.5vw, 28px);
  line-height:1.45;
  text-wrap:balance;
  scroll-margin-block-start:24px;
}
.prose h3{
  margin-block-start:1.8em;
  font-family:var(--f-display);
  font-weight:700;
  font-size:20px;
  line-height:1.5;
  scroll-margin-block-start:24px;
}
.prose h2 + *,
.prose h3 + *{ margin-block-start:.6em; }
.prose a{
  color:var(--accent-ink);
  text-decoration-thickness:1px;
  text-underline-offset:.35em;
}
.prose a:hover{ text-decoration-thickness:2px; }
.prose strong{ font-weight:700; }
.prose ul,
.prose ol{ padding-inline-start:1.4em; }
.prose ol{ list-style-type:persian; }
.prose li + li{ margin-block-start:.45em; }
.prose li::marker{ color:var(--accent-ink); font-weight:700; }
.prose hr{
  block-size:1px;
  margin-block:2.6em;
  border:0;
  background:var(--line);
}
.prose figure{ margin-inline:0; }
.prose figure img{ border-radius:16px; }
.prose figcaption{ margin-block-start:8px; font-size:14px; color:var(--ink-3); }

/* Pull-quote: part of the argument, set as display type. A short accent rule
   above it instead of a quotation mark — it is the article's own sentence,
   not somebody else's. */
.prose .pull{
  margin-block:2em;
  margin-inline:0;
  padding:0;
  font-family:var(--f-display);
  font-weight:800;
  font-size:clamp(21px, 2.6vw, 27px);
  line-height:1.6;
  color:var(--ink);
  text-wrap:balance;
}
.prose .pull::before{
  content:"";
  display:block;
  inline-size:48px;
  block-size:3px;
  margin-block-end:.7em;
  background:var(--accent);
}
.prose .pull p{ margin:0; }

/* Tables sit on a white card, headed in the recessed paper; figures are
   tabular so a column of sums lines up digit under digit. */
.prose .table{
  overflow-x:auto;
  border-radius:16px;
  background:var(--surface);
  box-shadow:var(--sh-1);
}
.prose table{
  inline-size:100%;
  border-collapse:collapse;
  font-size:15px;
  line-height:1.7;
  font-variant-numeric:tabular-nums;
}
.prose th{
  padding:12px 16px;
  background:var(--paper-2);
  font-family:var(--f-display);
  font-size:14px;
  font-weight:800;
  text-align:start;
  white-space:nowrap;
}
.prose td{
  padding:12px 16px;
  border-block-start:1px solid var(--line);
  vertical-align:top;
}
/* The label column keeps its words together; on a phone that was breaking
   «لنت ترمز جلو» one word per line while the figures took the width. The
   table scrolls sideways before a label is broken. */
.prose td:first-child{ min-inline-size:6.5em; }
@media (max-width:560px){
  .prose table{ font-size:14px; }
  .prose th,
  .prose td{ padding:10px 12px; }
}

/* Code runs left to right whatever surrounds it, and keeps to itself in the
   bidi run so a Latin string cannot pull the Persian around it out of order. */
.prose code{
  padding:.1em .4em;
  border-radius:6px;
  background:var(--paper-2);
  font-family:var(--f-code);
  font-size:.86em;
  direction:ltr;
  unicode-bidi:isolate;
}
.prose pre{
  overflow-x:auto;
  padding:20px;
  border-radius:16px;
  background:var(--ink);
  color:var(--bone);
  font-size:14px;
  line-height:1.7;
  text-align:start;
}
.prose pre code{ padding:0; background:none; color:inherit; font-size:inherit; }

/* ── table of contents ────────────────────────────────────────────────────
   A <details>, so it works without script and folds away on a phone. Sticky
   beside the text on wide screens; the section being read is marked by
   js/articles.js. */
.toc{ align-self:start; font-size:14px; }
@media (min-width:1024px){ .toc{ position:sticky; inset-block-start:28px; } }
@media (max-width:1023px){
  .toc details{ padding:14px 18px; border-radius:16px; background:var(--surface); box-shadow:var(--sh-1); }
}
.toc summary{
  cursor:pointer;
  font-family:var(--f-display);
  font-weight:800;
  font-size:14px;
  list-style:none;
}
.toc summary::-webkit-details-marker{ display:none; }
.toc summary::after{ content:" ▾"; color:var(--ink-3); }
.toc details[open] summary::after{ content:" ▴"; }
.toc ol{
  margin:14px 0 0;
  padding:0;
  list-style:none;
  border-inline-start:1px solid var(--line);
}
.toc a{
  display:block;
  margin-inline-start:-1px;
  padding:7px 14px;
  border-inline-start:2px solid transparent;
  color:var(--ink-2);
  line-height:1.6;
  text-decoration:none;
  transition:color .2s var(--e-out), border-color .2s var(--e-out);
}
.toc a:hover{ color:var(--ink); }
.toc a[aria-current="location"]{ color:var(--ink); border-color:var(--accent); font-weight:600; }

/* ── byline ───────────────────────────────────────────────────────────────── */
.byline{
  max-inline-size:var(--measure);
  margin:56px auto 0;
  padding:24px var(--gutter) 0;
  box-sizing:content-box;
  border-block-start:1px solid var(--line);
  font-size:14px;
  color:var(--ink-2);
}
@media (min-width:1024px){
  .byline{ max-inline-size:var(--wide); }
  .byline > *{ max-inline-size:var(--measure); }
}
.byline p{ margin:0; }
.byline strong{ color:var(--ink); }
.byline__tags{ display:flex; flex-wrap:wrap; gap:6px; margin-block-start:14px !important; }
.byline__tags span{
  padding:4px 12px;
  border-radius:999px;
  background:var(--paper-2);
  font-size:13px;
}

/* ═══ cards ══════════════════════════════════════════════════════════════ */

.list-body{
  max-inline-size:var(--wide);
  margin:clamp(32px, 5vw, 56px) auto 0;
  padding-inline:var(--gutter);
  box-sizing:content-box;
}
.list-empty{ color:var(--ink-2); }
.card[hidden]{ display:none; }   /* a search miss; .card's own display would win over the attribute */

.grid{
  display:grid;
  gap:clamp(16px, 2vw, 24px);
  grid-template-columns:repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  margin-block-start:clamp(16px, 2vw, 24px);
}

.card{
  position:relative;
  display:flex;
  flex-direction:column;
  overflow:hidden;
  border-radius:24px;
  background:var(--surface);
  box-shadow:var(--sh-1);
  transition:box-shadow .35s var(--e-out), transform .35s var(--e-out);
}
.card:hover{ box-shadow:var(--sh-2); transform:translateY(-2px); }
.card__media{ display:block; aspect-ratio:5/3; overflow:hidden; background:var(--paper-2); }
.card__media img{
  inline-size:100%;
  block-size:100%;
  object-fit:cover;
  transition:transform .8s var(--e-out);
}
.card:hover .card__media img{ transform:scale(1.035); }
.card__body{
  display:flex;
  flex:1;
  flex-direction:column;
  gap:8px;
  padding:20px 22px 24px;
}
.card__cat{
  align-self:flex-start;
  font-size:13px;
  font-weight:600;
  color:var(--accent-ink);
  text-decoration:none;
}
.card__cat:hover{ text-decoration:underline; text-underline-offset:.3em; }
.card__title{
  margin:0;
  font-family:var(--f-display);
  font-weight:800;
  font-size:19px;
  line-height:1.5;
  text-wrap:balance;
}
.card__title a{ color:inherit; text-decoration:none; }
.card__title a:hover{ text-decoration:underline; text-decoration-thickness:1px; text-underline-offset:.35em; }
.card__desc{
  display:-webkit-box;
  margin:0;
  overflow:hidden;
  -webkit-box-orient:vertical;
  -webkit-line-clamp:3;
  font-size:15px;
  line-height:1.85;
  color:var(--ink-2);
}
.card__meta{ margin:auto 0 0; padding-block-start:6px; font-size:13px; color:var(--ink-3); }

/* The newest article leads the list: wider than the grid, photograph and
   words side by side, the one card on the page that gets to be large. */
@media (min-width:860px){
  .card--featured{ flex-direction:row; }
  .card--featured .card__media{ flex:0 0 58%; aspect-ratio:auto; min-block-size:360px; }
  .card--featured .card__body{ justify-content:center; padding:40px; gap:12px; }
  .card--featured .card__title{ font-size:clamp(24px, 2.4vw, 32px); line-height:1.4; }
  .card--featured .card__desc{ -webkit-line-clamp:4; font-size:16px; }
}

/* The third related card goes home, in the landing's own colours. */
.card--landing{ background:var(--night); color:var(--bone); box-shadow:none; }
.card--landing .card__cat{ color:var(--bone-dim); }
.card--landing .card__desc{ color:var(--bone-dim); -webkit-line-clamp:4; }
.card--landing .brand__mark{
  inline-size:56px;
  block-size:56px;
  margin:0 22px 24px;
  align-self:flex-end;
}

.pager{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:16px;
  margin-block-start:40px;
  font-size:14px;
  color:var(--ink-2);
}
.pager__link{
  display:inline-flex;
  align-items:center;
  gap:8px;
  min-block-size:44px;
  padding-inline:18px;
  border-radius:999px;
  background:var(--surface);
  box-shadow:inset 0 0 0 1px var(--line);
  color:var(--ink);
  font-weight:600;
  text-decoration:none;
}
.pager__link:hover{ box-shadow:inset 0 0 0 1px var(--ink-3); }

/* ── related ──────────────────────────────────────────────────────────────── */
.related{
  max-inline-size:var(--wide);
  margin:clamp(72px, 9vw, 120px) auto 0;
  padding-inline:var(--gutter);
  box-sizing:content-box;
}
.related h2{
  margin:0;
  font-family:var(--f-display);
  font-weight:900;
  font-size:clamp(26px, 3.4vw, 40px);
  line-height:1.3;
}
@media (min-width:900px){ .grid--three{ grid-template-columns:repeat(3, 1fr); } }

/* ═══ footer ═════════════════════════════════════════════════════════════ */
.site-foot{
  margin-block-start:clamp(72px, 9vw, 120px);
  padding:48px var(--gutter) calc(48px + env(safe-area-inset-bottom, 0px));
  background:var(--night);
  color:var(--bone-dim);
  font-size:14px;
}
.site-foot__inner{
  display:grid;
  gap:20px;
  max-inline-size:var(--wide);
  margin-inline:auto;
}
@media (min-width:860px){
  .site-foot__inner{ grid-template-columns:auto 1fr auto; align-items:center; column-gap:48px; }
}
.site-foot p{ margin:0; max-inline-size:36em; line-height:1.8; }
.site-foot nav{ display:flex; flex-wrap:wrap; gap:4px 18px; }
.site-foot nav a{ color:var(--bone-dim); text-decoration:none; }
.site-foot nav a:hover{ color:var(--bone); }
.brand--quiet .brand__word{ color:var(--bone-dim); }

/* ── reduced motion ───────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{ transition-duration:.01ms !important; }
  .card:hover{ transform:none; }
  .card:hover .card__media img{ transform:none; }
}

/* Jumps from the table of contents glide, unless motion is unwelcome. */
@media (prefers-reduced-motion: no-preference){
  html{ scroll-behavior:smooth; }
}

/* Separator for meta lines. Not «·»: in Vazirmatn the middle dot is the
   Persian zero's twin, so «۱۴۰۵ · ۳» read as «۱۴۰۵ ۰ ۳». A hairline cannot
   be mistaken for a digit. */
.sep{
  display:inline-block;
  inline-size:1px;
  block-size:.9em;
  margin-inline:8px;
  background:currentColor;
  opacity:.4;
  vertical-align:-.1em;
}
.article-meta .sep{ margin-inline:0; }
