@charset "UTF-8";
/* ==========================================================================
   Pakdis — home page
   --------------------------------------------------------------------------
   Built 1:1 from the supplied artwork (1920 × 6480 artboard).
   Every measurement below is taken from the design file, so the numbers are
   deliberately literal: the layout matches the artboard at a 1920px viewport
   and reflows through the breakpoints at the end of the sheet.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Fonts
   The artwork is set in Modam (Light / Regular / Medium / Bold / Black).
   Drop the licensed web fonts into /fonts and they will be picked up here;
   Vazirmatn and the system Persian faces cover the gap until then.
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   1. The brand face
   The @font-face declarations live in css/fonts.css and every page links it
   before its own sheet.

   They were here, which meant brands.html — the one page that does not load
   this file — never loaded Modam at all and rendered in a fallback. A font is
   the whole site's, not one stylesheet's.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   2. Design tokens
   -------------------------------------------------------------------------- */
:root {
  /* Brand palette, sampled from the artwork */
  --purple:        #442f72;   /* type, rules, UI                       */
  --purple-flood:  #422a74;   /* large flooded areas (hero, gallery)   */
  --purple-deep:   #110735;   /* foot of the footer gradient           */
  --gold:          #baa660;   /* brand gold, per the identity spec        */
  --ink:           #000000;   /* card headlines                        */
  --grey-600:      #666666;   /* card body copy                        */
  --grey-400:      #999999;   /* card dates                            */

  /* Type */
  --font: "Modam", "Vazirmatn", "IRANSans", "Segoe UI", Tahoma, sans-serif;

  /* Geometry — content column is 1365px on the 1920px artboard */
  --container: 1365px;
  --header-h: 133px;          /* height of the navigation bar          */
  --header-drop: 44px;        /* how far it sits down the hero         */

  /* Where a page's own content starts.

     The header is fixed at --header-drop and is --header-h tall, so its bottom
     edge is the sum of the two — not --header-h alone. Every inner page used to
     write its own version of this sum and they had drifted apart badly: two
     pages put their breadcrumb *inside* the bar (contact at -44px, news at
     -24px), one was 10px clear, three were 34px clear. One token, one answer.

     The third term is the clearance itself. 56px is enough that the trail reads
     as the start of the page rather than as part of the navigation. */
  --hero-top: calc(var(--header-h) + var(--header-drop) + 56px);
  --edge: 88px;               /* header side padding                   */

  /* Motion */
  --ease: cubic-bezier(.22, .61, .36, 1);
}

/* --------------------------------------------------------------------------
   3. Reset & base
   -------------------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

/* THE BOTTOM OF THE PAGE WAS UNREACHABLE, AND `clip` WAS WHY.

   `overflow-x` has to be set on the ROOT as well as on body: with it on body
   alone the viewport's scrolling is still handed to the root, so the layout
   kept panning sideways on a phone. That part was right.

   The value was not. `overflow-x: clip` looks like the careful choice — it does
   not create a scroll container, so it cannot break `position: sticky` inside.
   But the two axes are not independent: `overflow-y` is `visible` here, and
   `visible` is not a legal pairing with `clip`, so the computed value of
   `overflow-y` becomes `clip` as well. The root was therefore clipped
   VERTICALLY: the document could not scroll to its own full height, the last
   band of the footer sat outside the clip, and dragging past it rubber-banded
   and snapped straight back — exactly the reported fault.

   `hidden` has the opposite pairing rule: `visible` alongside `hidden` computes
   to `auto`, so the root scrolls normally on the y axis and only the x axis is
   contained. Nothing on this site relies on `position: sticky` inside the root,
   so `hidden` costs nothing here. */
html {
  -webkit-text-size-adjust: 100%;
  overflow-x: hidden;
  /* The colour the browser paints OUTSIDE the document — the rubber-band area
     past either end. With no background on the root, body's white propagates
     to the canvas and a white band shows under a purple footer. --purple-deep
     is the colour the footer ends on. */
  background: var(--purple-deep);
}

body {
  margin: 0;
  background: #fff;
  color: var(--purple);
  font-family: var(--font);
  font-weight: 300;
  font-size: 16px;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* `hidden`, not `clip`, for the reason given on the root above. */
  overflow-x: hidden;
}

h1, h2, h3, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img, svg { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }

:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  inset-inline-start: 24px;
  top: -100px;
  z-index: 100;
  padding: 12px 22px;
  background: var(--purple);
  color: #fff;
  font-weight: 500;
  border-radius: 0 0 10px 10px;
  transition: top .2s var(--ease);
}
.skip-link:focus { top: 0; }

.container {
  width: min(var(--container), calc(100% - 80px));
  margin-inline: auto;
}

/* --------------------------------------------------------------------------
   4. Arrow link — "اطلاعات بیشتر" / "مشاهده همه"
   The artwork places the glyph after the label in most links and before it
   in the section "view all" links, hence the --reverse modifier.
   -------------------------------------------------------------------------- */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-size: 23.6px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--gold);
  transition: color .25s var(--ease), gap .25s var(--ease);
}
.link-arrow--reverse { flex-direction: row-reverse; gap: 16px; }

.link-arrow__icon {
  flex: none;
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform .25s var(--ease);
}
.link-arrow:hover { gap: 18px; }
.link-arrow:hover .link-arrow__icon { transform: translate(2px, -2px); }

/* ==========================================================================
   5. Site header
   Transparent while the hero is in view, solid once the page scrolls.
   ========================================================================== */
.site-header {
  position: fixed;
  inset-inline: 0;
  top: var(--header-drop);
  z-index: 50;
  height: var(--header-h);
  transition: top .35s var(--ease), background-color .35s var(--ease), box-shadow .35s var(--ease);
}

/* Solid plate, faded in when stuck. The stops are sampled straight off the
   artwork, so they already carry the faint ornamental strip printed behind. */
.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, #ece9f1 0%, #efe8ef 34%, #f8e7ec 52%, #f0e2e9 76%, #e6d9e3 100%);
  opacity: 0;
  transition: opacity .35s var(--ease);
}

.site-header.is-stuck { top: 0; box-shadow: 0 6px 30px rgba(68, 47, 114, .10); }
.site-header.is-stuck::before { opacity: 1; }

/* A touch of glass once stuck: hold the plate back from fully opaque so the
   page reads faintly through it, and blur what's behind so the nav labels stay
   legible over whatever scrolls past — without the blur, thinning the plate
   would just make text collide with photos and cards.
   .74 is about as far as this can go before the ornamental strip printed into
   the gradient starts to wash out, so the blur is raised alongside it — the
   thinner the plate, the more the blur has to do to keep the nav readable.
   Gated behind @supports because the fallback has to be the solid plate: a
   see-through header with no blur is worse than no glass at all. Saturation is
   nudged up because blurring alone tends to leave the backdrop looking grey. */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header.is-stuck {
    -webkit-backdrop-filter: blur(18px) saturate(1.5);
    backdrop-filter: blur(18px) saturate(1.5);
  }
  .site-header.is-stuck::before { opacity: .74; }
}

.site-header__inner {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 107px;
  height: 100%;
  padding-inline: var(--edge);
}

/* Logo — the two lock-ups are cross-faded with the header state */
.site-header__logo {
  position: relative;
  flex: none;
  width: 232px;
  height: 89px;
}
.site-header__logo-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  transition: opacity .35s var(--ease);
}
.site-header__logo-img--dark { opacity: 0; }
.site-header.is-stuck .site-header__logo-img--light { opacity: 0; }
.site-header.is-stuck .site-header__logo-img--dark  { opacity: 1; }

.site-nav__list {
  display: flex;
  align-items: center;
  gap: 60px;
}

.site-nav__link {
  position: relative;
  display: block;
  padding-bottom: 6px;
  font-size: 23.8px;
  font-weight: 300;
  line-height: 1.5;
  color: #fff;
  white-space: nowrap;
  transition: color .3s var(--ease);
}
.site-header.is-stuck .site-nav__link { color: var(--purple); }

.site-nav__link::after {               /* the underline on the current page */
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: inline-start;
  transition: transform .3s var(--ease);
}
.site-nav__link:hover::after,
.site-nav__link.is-active::after { transform: scaleX(1); }

/* Burger — only surfaces on small screens */
.site-header__burger {
  display: none;
  flex: none;
  width: 46px;
  height: 46px;
  margin-inline-start: auto;
  padding: 12px 9px;
  flex-direction: column;
  justify-content: space-between;
}
.site-header__burger span {
  display: block;
  height: 2px;
  background: #fff;
  border-radius: 2px;
  transition: background-color .3s var(--ease), transform .3s var(--ease), opacity .2s var(--ease);
}
.site-header.is-stuck .site-header__burger span { background: var(--purple); }

/* ==========================================================================
   6. Hero
   ========================================================================== */
/* 929px, not 796 — the corner pattern's own vector geometry runs the full
   0–929.5 (traced straight off the PDF), matching the artboard's hero +
   "docked nav" strip combined. Treating the hero as just the 796px photo
   band clipped the pattern's bottom ~130px, which only shows once you
   stop assuming the sticky header eats that space: with the header taken
   out of flow (position:fixed), nothing else was reserving it, so the
   section came up short and the pattern never reached its real end. */
.hero {
  position: relative;
  height: 929px;
  overflow: hidden;
  background: var(--purple-flood);
  isolation: isolate;
}

.hero__media { position: absolute; inset: 0; }

/* The slides are stacked, not laid side by side, and only their opacity
   changes — so nothing reflows and there is no track to keep in sync. The one
   below stays in the layout rather than being display:none, because a video
   that has been removed from the box tree stops buffering and has to start
   again every time it comes back. `visibility` is what takes the hidden slide
   out of the tab order and off the accessibility tree. */
.hero__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity .7s var(--ease), visibility 0s linear .7s;
}
.hero__slide.is-active {
  opacity: 1;
  visibility: visible;
  transition: opacity .7s var(--ease), visibility 0s;
}

.hero__photo,
.hero__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 55%;
}
/* The video is 1080×608 — wider than the hero's own 929px-tall box at most
   widths, so `cover` crops its sides rather than its middle. Centred
   vertically instead of the photograph's 55%, because the framing was shot
   for the frame it is in and has no headroom to give away. */
.hero__video { object-position: 50% 50%; }

/* Purple wash: floods the right-to-left start edge, plus a top scrim so the
   navigation stays legible over any slide. The vertical stops were sampled
   against the photo at its true 796px band, then rescaled to this
   element's actual 929px height (×796/929) so they still land on the same
   physical pixels rather than stretching over the taller box. */
.hero__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to left,
      rgba(66, 42, 116, 0)   42%,
      rgba(66, 42, 116, .92) 68%,
      rgba(66, 42, 116, 1)   82%),
    linear-gradient(to bottom,
      rgba(66, 42, 116, 1)    0%,
      rgba(66, 42, 116, .93) 17.1%,
      rgba(66, 42, 116, .34) 36.0%,
      rgba(66, 42, 116, .30) 66.8%,
      rgba(66, 42, 116, .46) 85.7%);
}

/* Traced straight off the artwork's own vector paths (box -2,-1.6 to
   350,931.5) — its true extent runs the full height of this section, not
   just the photo band above the "docked nav" strip. */
.hero__pattern {
  position: absolute;
  top: -2px;
  left: -2px;
  width: 352px;
  height: auto;
  max-width: none;
  opacity: .72;
  pointer-events: none;
}

.hero__content {
  position: relative;
  z-index: 1;
  height: 100%;
  padding-inline-end: 261px;           /* left edge on the artboard */
  padding-top: 479px;
}

/* The artwork sets the headline flush to the left edge of the block */
.hero__title {
  font-size: 43px;
  font-weight: 900;
  line-height: 1.198;
  color: #fff;
  text-align: left;
}

/* The hero block is set flush to the left edge, so the rule is pushed there
   with an auto margin on the inline-start (right) side. */
.hero__rule {
  width: 461px;
  height: 1px;
  margin: 63px 0 0;
  margin-inline-start: auto;
  border: 0;
  background: rgba(255, 255, 255, .8);
}

.hero__actions {
  display: flex;
  flex-direction: row-reverse;         /* CTA on the left, dots to its right */
  align-items: center;
  gap: 180px;
  margin-top: 17px;
}

.hero__cta { color: #fff; }
.hero__cta:hover { color: var(--gold); }

.hero__dots { display: flex; align-items: center; gap: 12.7px; }

.hero__dot {
  width: 15.2px;
  height: 15.2px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .45);
  transition: background-color .3s var(--ease), transform .3s var(--ease);
}
.hero__dot:hover { background: rgba(255, 255, 255, .7); }
.hero__dot.is-active { background: #fff; transform: scale(1.06); }

/* ==========================================================================
   7. About

   Same title, same mark image, same two-column layout and every geometric
   offset below it — only the ground they sit on and the depth around them
   changed. Flat gold measures 2.41:1 against the white copy, well under the
   system's own 4.5 floor; a flat fill is also the single least "لوکس" surface
   available given how much of the page it covers. Both are fixed together by
   the same move: the gold now runs as a gradient that stays true gold where
   the mark sits and settles towards --purple-deep behind the copy, which
   brings the text to 5.6:1 while the identity's colour is still what a reader
   sees first.
   ========================================================================== */
.about {
  position: relative;
  isolation: isolate;
  /* `to left`, not an angled gradient: the earlier 152deg carried its darkest
     stop toward the bottom-*right* corner — the mark's side, not the copy's —
     which is exactly the excess darkness that was reported. A flat horizontal
     gradient keeps the mark's side (right, the RTL start) at true gold and
     only deepens as it crosses to the copy (left); the mix ratio itself is
     unchanged (65% gold / 35% --purple-deep at the far stop → 4.94:1 for the
     white copy, just over the system's 4.5 floor). */
  background: linear-gradient(to left,
    color-mix(in srgb, var(--gold) 96%, #fff) 0%,
    var(--gold) 40%,
    color-mix(in srgb, var(--gold) 65%, var(--purple-deep)) 100%);
  padding-block: 64px 203px;           /* 64 + 479 (mark) + 203 = 746, as drawn */
}

/* Mark on the right, copy on the left. The columns and side padding are the
   artboard's exact values at 1920 and give way proportionally below it. */
.about__inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 465px) minmax(0, 975px);
  gap: 17px;
  padding-inline: clamp(24px, 10.73vw, 206px) clamp(24px, 13.39vw, 257px);
}

/* A soft halo so the mark reads as lifted off the ground rather than printed
   flat onto it — white at low opacity, which on gold is a highlight, not a
   second colour. Sized past the image on every side so it falls off gently
   rather than showing an edge. */
.about__mark {
  position: relative;
}
.about__mark::before {
  content: "";
  position: absolute;
  inset: -12% -18%;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(circle, rgb(255 255 255 / .22) 0%, rgb(255 255 255 / 0) 68%);
  pointer-events: none;
}

.about__mark img {
  width: 100%;
  max-width: 461px;
  height: auto;
  /* A drop shadow, not a box-shadow: it follows the artwork's own silhouette
     (the image is mostly transparent), so the depth sits under the drawn
     shapes instead of behind a rectangle no one can see. */
  filter: drop-shadow(0 18px 30px rgb(17 7 53 / .22));
}

.about__body {
  position: relative;
  padding-top: 89px;                 /* headline lands 153px into the section */
}

.about__title {
  font-size: 37.4px;
  font-weight: 900;
  line-height: 1.35;
  color: #fff;
  text-shadow: 0 2px 20px rgb(17 7 53 / .18);
}

/* The rule runs past the copy column and lands on the horizontal line drawn
   inside the ornament — 258px down the section, which is 193.8px into the
   mark image. 54.5 = 258 − 153 (headline top) − 50.49 (headline box). Both
   ends are geometry, not type, so keep this in step with the mark's offset.

   Two-tone now, purple handing off to the identity's gold-on-dark pairing
   rather than a flat line — the same purple-to-gold relationship the brand
   rows draw as a bracket, here drawn as a single stroke. */
.about__rule {
  width: 407px;
  height: 1px;
  margin: 54.5px 0 0 auto;
  margin-inline-start: -41px;
  border: 0;
  background: linear-gradient(to left, var(--purple) 60%, rgb(68 47 114 / 0));
}

.about__text {
  margin-top: 16px;
  font-size: 24.5px;
  font-weight: 300;
  line-height: 1.204;
  color: #fff;
  text-align: justify;
  text-justify: inter-word;
  text-shadow: 0 1px 12px rgb(17 7 53 / .14);
}

/* ==========================================================================
   8. Brands
   ========================================================================== */
.brands {
  background: #fff;
  padding-block: 13px 119px;
}

/* -- centred section headline with its ornament -------------------------- */
/* The artwork is exported at exactly 2× its display size (1308×488 → 654×244),
   so letting the image size the box keeps it undistorted at every width — the
   old fixed `height` stretched it once the width was capped at narrower
   breakpoints, and forced a hand-tuned `top` for the headline at each one. */
.brands__head {
  position: relative;
  width: 654px;
  max-width: 100%;
  margin-inline: auto;
}
.brands__head-orn {
  display: block;
  width: 100%;
  height: auto;
}
/* Both offsets are read straight off the artwork, as percentages of it, so
   they hold at any size the head is drawn:
     - the square motif's bottom edge is 62.9% down the image; the headline is
       written *on* that edge, so its baseline goes there. A text baseline sits
       0.975em below its box's top, hence the subtraction — and because `em`
       resolves against each breakpoint's own font-size, one rule covers them
       all instead of a separate `top` per breakpoint.
     - the motif's left edge is 15.44% in from the right; the headline stops
       just short of it, plus 12px of optical breathing room. */
.brands__title {
  position: absolute;
  top: calc(62.9% - 0.975em);
  inset-inline-start: calc(15.44% + 12px);
  font-size: 51.6px;
  font-weight: 900;
  line-height: 1.35;
  color: var(--gold);
  white-space: nowrap;
}

/* -- rows -----------------------------------------------------------------
   Fixes one real bug and adds four purely decorative touches; the DOM, the
   grid columns, the per-brand logo widths and the bracket are all unchanged.

   THE BUG: `.brand-row__media` used to be a zero-height box, with the image
   centred inside it via `top: 50%; translate(0, -50%)`. A percentage `top`
   resolves against its containing block's height — and on a handful of rows
   (the ones whose native aspect ratio put more of the image below its own
   optical centre, cogent and vebs among them) that zero-height reference was
   fragile enough to drift, so the mark visibly sat off the paragraph beside
   it instead of centred on it. `align-self: stretch` gives the media column
   the row's own real, non-zero height, so the same `top: 50%` now resolves
   against a definite number and centres correctly regardless of the image's
   own proportions. */
.brands__list { margin-top: 138px; }

.brand-row {
  position: relative;
  isolation: isolate;              /* keeps ::before's negative z-index local */
  display: grid;
  grid-template-columns: 449px minmax(0, 1fr);  /* RTL: media column on the right */
  align-items: center;
  min-height: 253px;
  transition: transform .4s var(--ease);
}
.brand-row:hover { transform: translateY(-3px); }

/* 144px, not a round number — reverse-engineered from the design's own
   heading-to-heading spacing (~385px average, measured directly off the
   PDF) minus this row's own content height (~241px), so the "read more"
   link lands where the source actually put it instead of drifting further
   off with every row. */
.brand-row + .brand-row { margin-top: 144px; }

/* A soft, boundless wash rather than a boxed card: the marks are drawn to
   bleed past the column on purpose ("exactly as drawn", below), so anything
   with a hard edge would either clip that bleed or visibly fight it. A wide,
   faint radial glow has no edge to fight — it just reads as the pair sharing
   a pool of light, biased toward whichever side the mark sits on, alternating
   gold/purple down the list so five near-identical rows gain a rhythm instead
   of repeating. */
.brand-row::before {
  content: "";
  position: absolute;
  inset: -14% -8%;
  z-index: -1;
  background: radial-gradient(60% 78% at 74% 50%,
    rgb(var(--row-tint) / .09) 0%, rgb(var(--row-tint) / 0) 70%);
  opacity: .75;
  transition: opacity .4s var(--ease);
  pointer-events: none;
}
.brand-row--flip::before {
  background: radial-gradient(60% 78% at 26% 50%,
    rgb(var(--row-tint) / .09) 0%, rgb(var(--row-tint) / 0) 70%);
}
.brand-row:hover::before { opacity: 1; }
.brand-row:nth-child(odd)  { --row-tint: 187 167 96; }   /* --gold */
.brand-row:nth-child(even) { --row-tint: 66 42 116; }    /* --purple-flood */

/* A quiet running number, ۰۱ through ۰۵ — reads as an index into a catalogue
   rather than a plain repeated list, and costs no markup beyond the
   :nth-child selectors below. A native `counter()` was the first instinct,
   but the built-in counter styles render Western or Arabic-Indic digits —
   neither matches the Persian digits the rest of the site uses (the card
   dates, the certificate readout) — and there are only ever five rows, so
   five explicit values are simpler and exactly right rather than close.
   Small and low-contrast on purpose, so it sits ahead of the bracket as a
   lead-in rather than competing with the brand name for attention. */
.brand-row__body::before {
  content: "";
  position: absolute;
  top: -32px;
  inset-inline-start: 7px;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .06em;
  color: rgb(68 47 114 / .4);
}
.brand-row:nth-child(1) .brand-row__body::before { content: "۰۱"; }
.brand-row:nth-child(2) .brand-row__body::before { content: "۰۲"; }
.brand-row:nth-child(3) .brand-row__body::before { content: "۰۳"; }
.brand-row:nth-child(4) .brand-row__body::before { content: "۰۴"; }
.brand-row:nth-child(5) .brand-row__body::before { content: "۰۵"; }

/* A hairline marking the middle of the gap between rows — the quiet version
   of the divider the identity draws elsewhere (the section heads' long rule,
   the about column's own hairline), here just marking a beat between one
   brand and the next rather than separating two things that need keeping
   apart. */
.brand-row:not(:last-child)::after {
  content: "";
  position: absolute;
  bottom: -72px;                     /* half of the 144px gap above */
  inset-inline-start: 50%;
  translate: -50% 0;
  width: min(220px, 46%);
  height: 1px;
  background: linear-gradient(to left,
    rgb(68 47 114 / 0), rgb(68 47 114 / .16) 50%, rgb(68 47 114 / 0));
  pointer-events: none;
}

.brand-row--flip { grid-template-columns: minmax(0, 1fr) 449px; }
.brand-row--flip .brand-row__media { grid-column: 2; }
.brand-row--flip .brand-row__body  { grid-column: 1; }

/* The marks bleed a little past the content column, exactly as drawn */
.brand-row__media { position: relative; align-self: stretch; }
.brand-row__logo {
  position: absolute;
  top: 50%;
  max-width: none;
  transition: transform .45s var(--ease);
}
.brand-row:hover .brand-row__logo { transform: scale(1.035); }

/* `translate: 0 -50%` centres each PNG's bounding BOX on the row — which is
   not the same thing as centering the mark's own ink on it, and the gap
   between the two is exactly what was still reading as "not lined up with
   the text" after the row itself was fixed to centre correctly. Each of
   these five files carries a different amount of transparent margin around
   a differently-shaped mark (a solid triangle's fill sits low in its own
   frame; a wordmark drawn inside a blob can sit high in its own), so one
   shared −50% cannot be right for all five at once.

   Measured directly — the alpha-weighted centroid of each PNG against its
   own canvas centre — rather than adjusted by eye:
     sundis   +0.6%   barleta  +5.3%   sunda  +0.2%
     cogent  +13.1%   vebs     −4.97%
   (positive = the ink sits below the frame's centre). Each value below is
   −50% plus that offset, so after this the mark's actual ink — not its
   transparent frame — is what lines up with the row's centre and the text
   beside it. cogent and vebs were the two visibly off; barleta's 5% and the
   other two's ~0.5% are corrected for the same reason but were never visibly
   wrong. */
.brand-row__logo--sundis  { width: 421px; inset-inline-start: -34px; translate: 0 -50.6%; }
.brand-row__logo--cogent  { width: 448px; inset-inline-end:   -29px; translate: 0 -18.0%; }
.brand-row__logo--barleta { width: 428px; inset-inline-start: -34px; translate: 0 -55.3%; }
.brand-row__logo--vebs    { width: 408px; inset-inline-end:   -27px; translate: 0 -7.0%; }
.brand-row__logo--sunda   { width: 418px; inset-inline-start: -24px; translate: 0 -50.2%; }

.brand-row__body {
  position: relative;
  padding-inline-start: 24px;
}

/* Two-tone bracket, traced from the source design (صفحه اول پاکدیس.pdf): the
   stroke comes down purple beside the brand name, hooks left, hands off to
   gold for the horizontal rule, then gold hooks back down and runs beside the
   copy. Read as one continuous S, drawn as two elbows meeting on the same line.

   The subtlety that caused a doubled line: in the design the purple's bottom
   border is *entirely* its corner curve — measured, its box is only as wide as
   its own radius, so the stroke turns and immediately stops. Give the purple
   box any extra width and that surplus renders as a straight horizontal run
   sitting a hair above the gold rule, and the two read as two parallel lines
   rather than one. So the width here is not a free number: it must equal the
   radius. (It was 46px against an 18px radius, i.e. 28px of stray rule.) */
.brand-row__bracket {
  position: absolute;
  top: 13px;
  inset-inline-start: 6px;
  width: 70px;
  height: 228px;
}
.brand-row__bracket::before,
.brand-row__bracket::after {
  content: "";
  position: absolute;
  inset-inline-start: 0;
}
.brand-row__bracket::before {          /* purple ╯ — descends, then hooks left */
  top: 0;
  height: 53px;                        /* meets ::after's top edge */
  inset-inline-end: 52px;              /* width 70−52 = 18px = the radius */
  border-bottom: 1.6px solid var(--purple);
  border-inline-start: 1.6px solid var(--purple);
  border-end-start-radius: 18px;
}
.brand-row__bracket::after {           /* gold ╮ — the rule, then down the side */
  top: 51.4px;
  bottom: 0;
  inset-inline-end: 0;
  border-top: 1.6px solid var(--gold);
  border-inline-start: 1.6px solid var(--gold);
  border-start-start-radius: 18px;
}

.brand-row__name {
  font-size: 27.8px;
  font-weight: 900;
  line-height: 1.4;
  color: var(--gold);
  transition: color .3s var(--ease);
}
.brand-row:hover .brand-row__name { color: var(--purple); }

.brand-row__text {
  margin-top: 42px;
  font-size: 24.5px;
  font-weight: 300;
  line-height: 1.204;
  color: var(--purple);
  text-align: justify;
  text-justify: inter-word;
}

/* In the source design this link sits at the *end* of the text column — the
   left edge, in RTL — not tucked under the paragraph's start. Left to itself
   it would inherit the paragraph's start edge, because `.link-arrow` is
   inline-flex and so just begins where the text does.

   Switching it to a block-level box sized to its own content lets an
   inline-start auto margin push it to the opposite edge. That's sturdier than
   setting an explicit inset would be: it stays correct no matter how long the
   label gets or how wide the column is, with nothing to recompute. */
.brand-row__link {
  display: flex;
  width: fit-content;
  margin-top: 7px;
  margin-inline-start: auto;
}
.brand-row__link:hover { color: var(--purple); }

/* ==========================================================================
   9. Editorial band — news & articles
   ========================================================================== */
.editorial {
  padding-block: 94px 97px;
  background: linear-gradient(180deg, #f7f7f9 0%, #fbfbfb 16%, #fdfdfd 32%, #fefefe 48%, #fefefe 100%);
}
.editorial__second { margin-top: 76px; }

/* -- shared section head (news, articles, gallery) -------------------------
   The ornament stays in flow so it sets the head's height and scales with the
   column; the headline and "view all" link are anchored to its baseline rule. */
.section-head {
  position: relative;
  margin-bottom: 31px;
}

.section-head__orn {
  display: block;
  width: calc(100% + 29px);            /* bleeds 22px / 7px past the column */
  height: auto;
  max-width: none;
  margin-inline-start: -22px;
}

/* Headline and "مشاهده همه" both sit on the same writing line, and that line
   is the bottom edge of the ornament's square motif — not the long rule below
   it. In the source artwork that edge is 71.5 of 178 natural px up from the
   image's bottom, i.e. 40.2% of the ornament's height, whatever that height
   scales to.

   Expressing it as a percentage rather than a px value per breakpoint is what
   keeps it honest: the ornament is `height: auto`, so `.section-head`'s height
   *is* the scaled ornament, and 40.2% therefore lands on the motif's edge at
   every width automatically. Subtracting 0.375em drops the box's bottom edge
   far enough that the text's own baseline — not the box — is what rests on
   the line; because each element resolves `em` against its own font-size, the
   two land on a shared baseline without needing separate numbers. */
.section-head__title {
  position: absolute;
  bottom: calc(40.2% - 0.375em);
  inset-inline-start: 68px;            /* clears the ornament */
  margin: 0;
  font-size: 34.9px;
  font-weight: 900;
  line-height: 1.35;
  color: var(--gold);
}

.section-head__more {
  position: absolute;
  bottom: calc(40.2% - 0.375em);
  inset-inline-end: -3px;
}
.section-head__more:hover { color: var(--purple); }

/* The gallery's ornament is the same template redrawn ~5.5 natural px higher
   (its motif edge measures 76.5 up from the bottom instead of 71.5), so its
   own percentage differs — this is the reason the old code carried a separate
   set of `bottom` values for --light rather than a shared one. */
.section-head--light { margin-bottom: 14px; }
.section-head--light .section-head__title { bottom: calc(43% - 0.375em); }
.section-head--light .section-head__more  { bottom: calc(43% - 0.375em); }
.section-head--light .section-head__more:hover { color: #fff; }

/* -- card grid ------------------------------------------------------------ */
/* CSS Grid auto-placement reads `direction`, so on an RTL page a plain grid
   fills its tracks right-to-left — that put the first card (پاکدیس) on the
   right, the reverse of the design, where it's the leftmost. Forcing the
   grid itself to ltr fixes placement order; direction:rtl on each card
   below undoes that for the Persian text and icons inside it. */
.card-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 27px;
  direction: ltr;
}
.card-grid > .card { direction: rtl; }

/* Each card carries its brand colour as raw channels so the photo wash can be
   built from the same value at three different alphas. */
.card {
  --tint: 66 42 116;                   /* --purple-flood */
  --card-tint: rgb(var(--tint));
  --card-accent: var(--purple);
}
.card--gold {
  --tint: 187 167 96;                  /* --gold */
  --card-accent: var(--gold);
}

/* Outer corner radii were never a vector path in the source — the rounding
   is baked into the raster photo itself — so these four numbers came from
   fitting a circular arc to the actual pixel edge: ~12px on three corners,
   ~35px on the bottom-right accent corner. */
.card__link {
  position: relative;
  display: block;
  height: 393px;
  border-radius: 12px 12px 35px 12px;
  background: var(--card-tint);
  overflow: hidden;
  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}
.card__link:hover {
  transform: translateY(-6px);
  box-shadow: 0 22px 44px -18px rgba(68, 47, 114, .45);
}

.card__media { position: absolute; inset: 0; }
.card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 30%;
  transition: transform .6s var(--ease);
}
.card__link:hover .card__media img { transform: scale(1.04); }

/* Photograph washes into the brand colour towards the panel. Measured by
   differencing the purple and gold cards pixel-for-pixel — they share one
   photo, so subtracting cancels the photo content and leaves only the wash's
   own alpha curve: near 0 until ~8% down the card, then a near-linear ramp
   that lands at full opacity right where the panel begins (~55%). Stopping
   at 100% (the card's full height) instead of 55% — the panel's own top
   edge — was the earlier version's mistake; it left the visible strip of
   photo above the panel only about half-tinted. */
.card__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgb(var(--tint) / 0) 8%, rgb(var(--tint) / 1) 55%);
}

/* Fixed height (165px, matching the source's own panel rect) is the load-
   bearing fix here: with an auto height, a card whose title happened to
   wrap to one line instead of two ended up with a shorter panel, so its top
   edge sat lower than its neighbours' and the whole row went uneven. A
   fixed height keeps every panel's top edge — and therefore the notch and
   the photo/tint seam above it — identical across the row regardless of
   how much text a given card has; line-clamp guards the two text blocks so
   longer real content clips with an ellipsis instead of overflowing it. */
.card__panel {
  position: absolute;
  inset-inline: 12px;
  bottom: 11.3px;
  height: 165px;
  padding: 5px 19px 24px;
  background: #fff;
  border-radius: 0 0 29.6px 12px;
  overflow: hidden;
}

/* The drip cut in the top edge of the panel — traced from the artwork's own
   compound path (panel outline 285,4481.7–582.8,4646.7 in the source PDF).
   There the notch spans x 192.6–229.0 of a 297.77-wide panel: 64.68% from
   the panel's physical left edge, 12.22% of its width. That's a physical
   offset, not a logical one — it came out of the PDF's fixed left-to-right
   coordinate space, so `left` here (not `inset-inline-start`) is what keeps
   it glued to the same spot regardless of the page's own text direction. */
.card__notch {
  position: absolute;
  display: block;
  top: 0;
  left: 64.68%;
  width: clamp(28px, 12.22%, 40px);
  aspect-ratio: 36.4 / 18.6;
  height: auto;
  fill: var(--card-tint);
}

.card__meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-inline: -7px;
  font-size: 14.9px;
  font-weight: 400;
  line-height: 1.9;
}
.card__brand { color: var(--card-accent); }
.card__date  { color: var(--grey-400); }

.card__title {
  margin-top: 7px;
  font-size: 15.1px;
  font-weight: 700;
  line-height: 1.36;
  color: var(--ink);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

.card__excerpt {
  margin-top: 13px;
  font-size: 11px;
  font-weight: 400;
  line-height: 1.36;
  color: var(--grey-600);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
}

/* ==========================================================================
   9b. Figures band — "پاکدیس در یک نگاه"
   Sits between the two card grids inside the editorial band. Its job is
   structural before it is decorative: news and articles are two nearly
   identical grids of white cards on a near-white field, so read back to back
   they blur into one long list. A single full-bleed purple beat between them
   restores the page's rhythm — the eye gets a wall to land on, and the second
   grid reads as a second thing rather than a continuation of the first.

   The band breaks the editorial container on purpose (100vw, negative inline
   margins) so the colour runs edge to edge like .plate does at the foot of
   the page; boxed inside the column it would read as an oversized card and
   compete with the very grids it is separating.
   ========================================================================== */
.figures {
  position: relative;
  overflow: hidden;
  margin-block: 96px;
  /* Full-bleed out of the editorial column without needing a wrapper. The
     scrollbar-safe form: 100vw can exceed the visible width when a classic
     scrollbar is present, so the offset is halved against the element's own
     width rather than the viewport's. */
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  padding-block: 78px 72px;
  /* No pattern here — colour alone. The identity's own gradient logic is the
     footer plate's: it opens at --purple-flood and sinks toward --purple-deep,
     so the page gets darker as it goes down. This band borrows that same
     descent but runs it on the diagonal, which is what keeps a 300px-tall
     strip from reading as the footer arriving early: the plate's transition is
     purely vertical, this one is angled, so they are recognisably the same
     palette doing two different jobs.

     Every stop is a mix of two existing tokens rather than a new colour, so
     the band cannot drift away from the identity as the palette evolves. */
  background: linear-gradient(148deg,
    /* 96/4, not a more generous lift: measured, gold on a 12%-whitened flood
       falls to 3.36:1, and the gold figures sit on exactly this end of the
       band. At 96% the lightest stop still clears 4.5:1 with the panel's own
       white overlay on top of it. */
    color-mix(in srgb, var(--purple-flood) 96%, #fff) 0%,
    var(--purple-flood) 26%,
    color-mix(in srgb, var(--purple-flood) 62%, var(--purple-deep)) 58%,
    color-mix(in srgb, var(--purple-flood) 28%, var(--purple-deep)) 84%,
    var(--purple-deep) 100%);
}

/* With the pattern gone, the light has to do all of the work the texture was
   doing — otherwise the band is one flat rectangle, and flat purple at this
   height reads as a gap in the page rather than a section of it.

   Three edge-less pools, no hard shape anywhere:
   · a gold dome at the head, where the title and rule sit, so the section has
     an obvious point of focus and the brand colour is present in the surface
     itself rather than only in the type;
   · a wide cool lift low on the start side, which stops the diagonal from
     going uniformly dark toward the bottom corner;
   · a faint gold echo on the far side, low — the counterweight that keeps the
     whole band from leaning to one edge.
   All three are gold or white against purple, i.e. entirely within the
   identity's own two-colour logic; no fourth hue is introduced. */
.figures::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(58% 66% at 50% -8%,  rgb(186 166 96 / .2)  0%, rgb(186 166 96 / 0) 70%),
    radial-gradient(52% 78% at 6% 104%,  rgb(255 255 255 / .09) 0%, rgb(255 255 255 / 0) 68%),
    radial-gradient(40% 62% at 96% 88%,  rgb(186 166 96 / .1)  0%, rgb(186 166 96 / 0) 72%);
  pointer-events: none;
}

/* Gold hairlines along the two long edges, fading out before the corners.
   This is the identity's own device — the section heads' rule, the about
   band's rule, the brand rows' bracket are all a gold line marking an edge —
   and it is what makes the band read as a deliberately placed plate rather
   than a colour that merely starts and stops. */
.figures::after {
  content: "";
  position: absolute;
  inset: 0;
  /* Two 1px-tall background layers rather than borders: a border would run the
     full width including the corners, and these are meant to fade out before
     they reach them. Same gradient twice, pinned to opposite edges. */
  background:
    linear-gradient(to left,
      rgb(186 166 96 / 0), rgb(186 166 96 / .42) 28%,
      rgb(186 166 96 / .42) 72%, rgb(186 166 96 / 0)) top    / 100% 1px no-repeat,
    linear-gradient(to left,
      rgb(186 166 96 / 0), rgb(186 166 96 / .28) 28%,
      rgb(186 166 96 / .28) 72%, rgb(186 166 96 / 0)) bottom / 100% 1px no-repeat;
  pointer-events: none;
}

.figures__inner { position: relative; z-index: 1; }

.figures__head {
  position: relative;
  text-align: center;
}

/* The brand's own line, set as an eyebrow between two hairlines — the same
   "short gold rule flanking a mark" arrangement the section heads use, turned
   horizontal. It gives the head three tiers to read down (line → title → lead)
   instead of two, which is what makes the band read as a composed plate
   rather than a heading with a sentence under it. Flexbox draws the rules, so
   they always meet the text no matter how long it is. */
.figures__eyebrow {
  display: flex;
  align-items: center;
  gap: 16px;
  justify-content: center;
  margin-bottom: 20px;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: .12em;
  color: var(--gold);
}
.figures__eyebrow::before,
.figures__eyebrow::after {
  content: "";
  width: 54px;
  height: 1px;
  background: linear-gradient(to left, rgb(186 166 96 / 0), rgb(186 166 96 / .7));
}
/* Mirrored, so both rules fade away from the words rather than both fading
   the same direction — the pair has to read as symmetrical about the text. */
.figures__eyebrow::after { scale: -1 1; }

/* The headline is filled with a gradient rather than a flat white: a very
   slight warm cast toward the end of the line, picked up from --gold, so the
   type belongs to the same light the band is lit by. The `color` above the
   clip is not decoration — it is what any engine without background-clip:text
   falls back to, and it has to be the readable value. */
.figures__title {
  font-size: 34px;
  font-weight: 900;
  line-height: 1.4;
  color: #fff;
  background: linear-gradient(to left,
    #fff 0%,
    #fff 42%,
    color-mix(in srgb, var(--gold) 34%, #fff) 100%);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* The gold hairline under the headline, drawn as a border on the lead's top
   edge would tie the two together; as a separate ::after it keeps its own
   width independent of however long the sentence runs. */
.figures__title::after {
  content: "";
  display: block;
  width: 96px;
  height: 2px;
  margin: 18px auto 0;
  background: linear-gradient(to left,
    rgb(186 166 96 / 0), var(--gold) 30%, var(--gold) 70%, rgb(186 166 96 / 0));
}

.figures__lead {
  width: min(620px, 100%);
  margin: 20px auto 0;
  font-size: 17px;
  font-weight: 300;
  line-height: 1.8;
  /* Not plain white: at 300 weight a full-strength white paragraph vibrates
     against a saturated purple. 82% still clears 4.5:1 against every stop of
     the gradient above. */
  color: rgb(255 255 255 / .82);
}

.figures__list {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 26px;
  margin-top: 62px;
  list-style: none;
}

/* Each figure is a panel, not a floating number. Four numerals of very
   different widths (۵ against ۱۲۰) with nothing around them read as loosely
   scattered; given a shared box they read as four entries of one set.

   The corner radius is the card's own — 12px 12px 35px 12px — so these are
   recognisably the same family of object as the news and article cards on
   either side of the band, rather than a shape invented for this section.
   RTL note: that value is written start-side-first by the card's own rule and
   is inherited here unchanged for exactly the same reason. */
/* The panels arrive one after another as the band scrolls in, rather than all
   four appearing at once. The delay is per-position rather than per-element
   so the sequence follows the reading direction; in RTL that is right to left,
   which is the order the browser lays them out in anyway, so nth-child is
   already correct with nothing to reverse.

   The reveal is opt-*in*: without `.is-in` the panel is simply visible. That
   ordering matters — if the hidden state were the default, a failure to
   observe (no IntersectionObserver, JS blocked) would leave the whole band
   permanently invisible. */
.figures__list.is-in .figure {
  animation: figure-rise .7s var(--ease) backwards;
}
.figures__list.is-in .figure:nth-child(1) { animation-delay: 0s; }
.figures__list.is-in .figure:nth-child(2) { animation-delay: .09s; }
.figures__list.is-in .figure:nth-child(3) { animation-delay: .18s; }
.figures__list.is-in .figure:nth-child(4) { animation-delay: .27s; }

@keyframes figure-rise {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: translateY(0); }
}

.figure {
  position: relative;
  overflow: hidden;
  padding: 34px 22px 28px;
  text-align: center;
  border: 1px solid rgb(255 255 255 / .1);
  border-radius: 12px 12px 35px 12px;
  /* A pane of light rather than a solid fill: the pattern behind stays
     readable through it, so the panels sit *in* the band instead of covering
     it up. Slightly stronger at the top edge so each has its own light source
     matching the band's. */
  background: linear-gradient(165deg,
    rgb(255 255 255 / .07) 0%,
    rgb(255 255 255 / .035) 45%,
    rgb(255 255 255 / .015) 100%);
  /* An inset highlight along the top inside edge — the one detail that makes a
     translucent panel read as a pane of glass catching light rather than a
     flat grey rectangle. Inset, so it is drawn inside the rounded corner and
     needs nothing to clip it. */
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .12);
  transition: transform .35s var(--ease),
              border-color .35s var(--ease),
              background .35s var(--ease),
              box-shadow .35s var(--ease);
}

/* The gold stroke that draws itself around the panel on hover.

   A conic-gradient whose sweep angle is animated, masked down to a 1px ring
   just inside the panel's own edge: `padding: 1px` makes the padding box 1px
   smaller than the border box, and excluding the content box from the mask
   leaves exactly that 1px frame. Because the mask follows `border-radius:
   inherit`, the stroke rounds the panel's 12/12/35/12 corner correctly rather
   than cutting it square.

   The angle is a registered custom property (@property, below) — without the
   registration the browser has no way to know `--figure-sweep` holds an angle
   and would jump straight from 0 to 360deg instead of interpolating, which is
   the whole effect. Where @property is unsupported the stroke simply appears
   whole on hover: no trace, nothing broken.

   `linear`, not the site's --ease: this is a line being drawn at a constant
   speed, and easing it would make the stroke visibly hesitate at the corners.
   .9s is also what the counter is synced to (js/app.js), so the number lands
   on its final value in the same frame the ring closes. */
@property --figure-sweep {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

.figure__trace {
  position: absolute;
  inset: 0;
  padding: 1px;
  border-radius: inherit;
  background: conic-gradient(from -90deg,
    var(--gold) 0deg,
    var(--gold) var(--figure-sweep),
    transparent var(--figure-sweep));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  opacity: 0;
  transition: --figure-sweep .9s linear, opacity .18s var(--ease);
  pointer-events: none;
}
.figure:hover .figure__trace,
.figure:focus-visible .figure__trace {
  --figure-sweep: 360deg;
  opacity: 1;
}

/* The gold cap along the top edge: the one piece of brand colour each panel
   carries at rest, and what makes the row scan as a set of four rather than a
   grid of four. It retracts as the traced ring takes over, so the two never
   read as two separate gold marks competing on the same edge. */
.figure::before {
  content: "";
  position: absolute;
  top: 0;
  inset-inline-start: 50%;
  translate: -50% 0;
  width: 46px;
  height: 2px;
  background: var(--gold);
  transition: width .4s var(--ease);
}

/* A pool of gold light that follows the pointer across the panel. The two
   coordinates come from js/app.js as percentages of the panel's own box, so
   the gradient needs no knowledge of the panel's size and stays correct
   through every breakpoint and any resize.

   The fallbacks in var() are what a keyboard user gets: with no pointer
   there are no coordinates, and 50%/108% puts the light low and centred —
   the fixed position this had before pointer tracking was added.

   Kept inside `overflow: hidden` so it fades against the panel's own rounded
   corners instead of squaring them off. */
.figure::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(72% 64% at var(--figure-mx, 50%) var(--figure-my, 108%),
    rgb(186 166 96 / .32) 0%, rgb(186 166 96 / 0) 70%);
  opacity: 0;
  transition: opacity .4s var(--ease);
  pointer-events: none;
}

.figure:hover,
.figure:focus-visible {
  transform: translateY(-6px);
  /* The resting border goes fully transparent rather than gold: the traced
     ring is now drawing that same edge, and leaving both on would show a
     finished gold outline underneath the line still being drawn — which
     defeats the point of tracing it. */
  border-color: transparent;
  /* The pane brightens very slightly as it lifts, so the panel reads as
     rising into the light rather than merely translating upward. */
  background: linear-gradient(165deg,
    rgb(255 255 255 / .1) 0%,
    rgb(255 255 255 / .05) 45%,
    rgb(255 255 255 / .02) 100%);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .18),
              0 22px 44px rgb(17 7 53 / .32);
}
.figure:hover::before,
.figure:focus-visible::before { width: 0; }
.figure:hover::after,
.figure:focus-visible::after  { opacity: 1; }

/* The panel is keyboard-reachable (tabindex on the li) so the same reveal is
   available without a pointer; the ring itself is the focus indicator, so the
   default outline would only double it. */
.figure:focus         { outline: none; }
.figure:focus-visible { outline: none; }

/* Drawn in the site's only existing icon language — 24-unit box, 1.6 stroke,
   round caps and joins, no fill — the same as .link-arrow__icon, so these
   read as part of the system rather than a stock icon set dropped in. Their
   job is to make four numbers scannable at a glance: without them every panel
   opens with an identical gold numeral and the eye has to read the label to
   tell them apart.

   Deliberately quiet at rest (60%) and full gold on hover, so at a glance the
   numbers lead and the icons support, not the other way round. */
.figure__icon {
  position: relative;
  z-index: 1;
  /* Inline with the number, not stacked above it: at this size the glyph and
     the numeral read as one unit — the mark and the measurement it belongs to
     — where a centred icon on its own line just added a third row to a panel
     that only has two things to say.
     `margin-inline-end` is the gap toward the number: the icon is first in
     source order, so in RTL it sits at the right and the number follows to
     its left. */
  display: inline-block;
  width: 38px;
  height: 38px;
  margin-inline-end: 14px;
  /* Optically centred against the numeral rather than baseline-aligned: these
     glyphs are drawn to fill their 24-box, so their true centre sits a little
     above a digit's own middle. */
  vertical-align: -6px;
  fill: none;
  stroke: var(--gold);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: .6;
  transition: opacity .35s var(--ease), transform .45s var(--ease);
}
.figure:hover .figure__icon,
.figure:focus-visible .figure__icon {
  opacity: 1;
  transform: translateY(-3px);
}

/* The number and its unit are one reading — "۳۵ سال" — so they sit on one
   baseline rather than stacked, with the unit deliberately at a fraction of
   the numeral's size so the figure itself still carries the emphasis. */
.figure__value {
  position: relative;
  z-index: 1;
  display: inline-block;
  font-size: 58px;
  font-weight: 900;
  line-height: 1;
  color: var(--gold);
  /* Tabular figures: without them the count-up visibly jitters, because most
     Persian numerals are narrower than ۴ and the number's width changes on
     almost every frame — the digits shuffle sideways all the way up. */
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  text-shadow: 0 4px 26px rgb(186 166 96 / .3);
  /* The glow strengthens as the ring closes, so the number reads as being
     lit by the stroke rather than merely sitting inside it. Matched to the
     trace's own .9s so both settle together. */
  transition: text-shadow .9s var(--ease);
}
.figure:hover .figure__value,
.figure:focus-visible .figure__value {
  text-shadow: 0 6px 34px rgb(186 166 96 / .55);
}

/* Nothing here is load-bearing: the panel's final number is in the markup and
   its border is a real border, so with motion suppressed the section reads as
   a finished, static set of four figures. Only the drawing of it is dropped.
   The count-up is skipped in js/app.js under the same query. */
@media (prefers-reduced-motion: reduce) {
  .figure,
  .figure__trace,
  .figure::before,
  .figure::after,
  .figure__icon,
  .figure__value,
  .figure__unit,
  .figure__label,
  .figures__more,
  .figures__more::before { transition: none; }

  /* The button is filled outright instead of being swept: the end state is
     the informative one, and only the sweep is motion. */
  .figures__more:hover::before,
  .figures__more:focus-visible::before { transform: scaleX(1); }

  /* `animation: none` rather than a zero duration: the panels' resting state
     is already the finished one, so removing the animation entirely leaves
     them correct with nothing to play out. */
  .figures__list.is-in .figure { animation: none; }

  .figure:hover,
  .figure:focus-visible { transform: none; border-color: rgb(186 166 96 / .38); }
  .figure__trace { display: none; }
  .figure:hover::before,
  .figure:focus-visible::before { width: 46px; }
}

.figure__unit {
  position: relative;
  z-index: 1;
  display: inline-block;
  margin-inline-start: 8px;
  font-size: 16px;
  font-weight: 500;
  color: rgb(255 255 255 / .82);
  transition: color .35s var(--ease);
}
/* Warms toward the numeral it belongs to as the panel lights up, so "۳۵ سال"
   reads as one phrase in one colour rather than a gold number with a white
   word stuck after it. */
.figure:hover .figure__unit,
.figure:focus-visible .figure__unit {
  color: color-mix(in srgb, var(--gold) 55%, #fff);
}

/* The hairline above the label separates the measurement from what is being
   measured — the same job the card panel's rule does, at this scale. */
.figure__label {
  position: relative;
  z-index: 1;
  display: block;
  margin-top: 20px;
  padding-top: 16px;
  font-size: 14px;
  font-weight: 300;
  letter-spacing: .02em;
  color: rgb(255 255 255 / .66);
  border-top: 1px solid rgb(255 255 255 / .1);
  transition: color .3s var(--ease), border-color .3s var(--ease);
}
.figure:hover .figure__label {
  color: rgb(255 255 255 / .9);
  border-top-color: rgb(186 166 96 / .3);
}

/* The band's one call to action, given a pill outline rather than left as a
   bare text link. Everything above it is read-only — a heading, a sentence,
   four numbers — so the single clickable thing has to look clickable; on a
   dark field a gold text link alone is easy to take for another label.

   The fill comes in from the start edge instead of fading the whole box, so
   the button reads as being *filled* on approach. `transform` on a ::before
   rather than an animated width, because width would relayout the label. */
.figures__more {
  position: relative;
  z-index: 1;
  display: flex;
  width: fit-content;
  margin: 54px auto 0;
  padding: 13px 30px;
  overflow: hidden;
  border: 1px solid rgb(186 166 96 / .5);
  border-radius: 8px 8px 22px 8px;   /* the card corner, at button scale */
  transition: color .3s var(--ease), border-color .3s var(--ease);
}
.figures__more::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: right center;    /* RTL: the start edge */
  transition: transform .42s var(--ease);
}
.figures__more:hover,
.figures__more:focus-visible {
  /* Deep purple on gold, not white: measured 7.9:1, where white on gold is
     only 2.4:1 and would fail outright. */
  color: var(--purple-deep);
  border-color: var(--gold);
}
.figures__more:hover::before,
.figures__more:focus-visible::before { transform: scaleX(1); }

/* ==========================================================================
   10. Purple plate — gallery + footer
   ========================================================================== */
.plate {
  position: relative;
  overflow: hidden;
  background: linear-gradient(180deg,
    var(--purple-flood)  0%,
    var(--purple-flood) 40%,
    #3b256b 52%,
    #321e60 63%,
    #271751 74%,
    #1a0d40 86%,
    var(--purple-deep)  95%,
    var(--purple-deep) 100%);
}

/* This asset carries the pattern's full bleed (source box -419,5326 to
   2058,5953) — a narrower crop silently drops the two widest compound
   paths, which run from x -417 to 2040 in source coordinates, losing the
   entire right half of the pattern. Opacity is measured off the artwork
   itself: comparing a pattern-line pixel against its immediate neighbour
   (so the plate's own background gradient is controlled for) gives ~0.20
   consistently. The fade is diagonal, not a horizontal curtain — fitting
   the contour of equal pattern-strength across the width gives a
   consistent ~13deg tilt (the boundary sits ~343px lower at the right edge
   than at the left), so the right-hand side keeps its pattern well after
   the left has gone. 193deg is that tilt expressed as a CSS gradient axis;
   the stops come from the same measurement projected onto it. */
.plate__pattern {
  position: absolute;
  top: -101px;
  left: -419px;
  width: 2477px;
  max-width: none;
  opacity: .2;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(193deg, #000 0%, #000 51%, transparent 73%);
          mask-image: linear-gradient(193deg, #000 0%, #000 51%, transparent 73%);
}

.gallery {
  position: relative;
  z-index: 1;
  padding-top: 59px;                   /* ornament top on the artboard */
}

.section-head--light .section-head__title { color: var(--gold); }

.gallery__viewport { position: relative; }

/* A real slider: native scroll-snap rather than a JS-animated transform, so
   it gets touch/trackpad swipe, momentum and keyboard scrolling for free.
   The RTL grid-placement fix from .card-grid still applies (direction:ltr
   on the track, direction:rtl restored per item) — for a scroll container
   that also sidesteps RTL's inverted scrollLeft/scroll-anchor quirks, so
   "forward" reliably means increasing scrollLeft everywhere this runs. */
.gallery__track {
  display: flex;
  gap: 24px;
  direction: ltr;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding-bottom: 4px;                 /* keeps the focus ring from clipping */
}
.gallery__track::-webkit-scrollbar { display: none; }

.gallery__track > .gallery__item {
  direction: rtl;
  flex: 0 0 calc((100% - 3 * 24px) / 4);
  min-width: 0;
  scroll-snap-align: start;
}

/* One tile at a time is "lit": full colour, purple wash, white caption. The
   rest are printed as a gold duotone. --lit drives every one of those, so the
   highlight can move without restating the treatment. */
@property --lit {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

.gallery__item {
  --lit: 0;
  --caption-ink: var(--ink);
  --caption-rule: rgba(0, 0, 0, .4);
  transition: --lit .45s var(--ease), --caption-ink .45s var(--ease), --caption-rule .45s var(--ease);
}

.gallery__item.is-active,
.gallery__item:hover,
.gallery__item:focus-within {
  --lit: 1;
  --caption-ink: #fff;
  --caption-rule: #fff;
}

/* Pointing at any tile hands the highlight over to it. */
.gallery__track:hover .gallery__item.is-active:not(:hover):not(:focus-within),
.gallery__track:focus-within .gallery__item.is-active:not(:hover):not(:focus-within) {
  --lit: 0;
  --caption-ink: var(--ink);
  --caption-rule: rgba(0, 0, 0, .4);
}

.gallery__link {
  position: relative;
  display: block;
  height: 218px;
  border-radius: 14px 48px 16px 16px;
  overflow: hidden;
  transition: transform .35s var(--ease);
}
.gallery__item:hover .gallery__link { transform: translateY(-4px); }

.gallery__media {
  position: absolute;
  inset: 0;
  display: block;
  background: var(--gold);
}
/* The gold duotone: this chain was fitted against pixels sampled from the
   artwork — a plain colour blend leaves the highlights far too grey. */
.gallery__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 34%;
  filter:
    grayscale(calc(1 - var(--lit)))
    sepia(calc(1 - var(--lit)))
    saturate(calc(1 + .1 * (1 - var(--lit))))
    brightness(calc(1 - .17 * (1 - var(--lit))));
}

.gallery__media::after {                 /* gold foot, fades out when lit */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(187, 167, 96, 0) 38%, rgba(187, 167, 96, 1) 97%);
  opacity: calc(1 - var(--lit));
}
.gallery__link::after {                  /* purple foot, fades in when lit */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(66, 42, 116, 0) 42%, rgba(66, 42, 116, 1) 97%);
  opacity: var(--lit);
}

.gallery__caption {
  position: absolute;
  inset-inline: 24px;
  bottom: 31px;
  z-index: 1;
  display: block;
  padding-bottom: 14px;
  font-size: 15.1px;
  font-weight: 700;
  line-height: 1.32;
  text-align: center;
  color: var(--caption-ink);
}
.gallery__caption::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 50%;
  translate: -50% 0;
  width: 128px;
  height: 1px;
  background: var(--caption-rule);
}

/* Plain icon, no button chrome — the source draws these as a bare white
   chevron directly on the photo, nothing else. */
.gallery__nav {
  position: absolute;
  top: 50%;
  translate: 0 -50%;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  color: #fff;
  opacity: .85;
  transition: opacity .25s var(--ease), transform .25s var(--ease);
}
.gallery__nav svg {
  width: 12px;
  height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.gallery__nav:hover { opacity: 1; }
.gallery__nav--prev { left: 3px; }
.gallery__nav--next { right: 3px; }

/* -- footer --------------------------------------------------------------- */
.site-footer {
  position: relative;
  z-index: 1;
  /* The bottom pad takes the phone's home-indicator inset on top of its own
     56px, so the last row is never sitting under the system bar. `env()`
     resolves to 0 everywhere it does not apply. */
  padding-block: 72px calc(56px + env(safe-area-inset-bottom, 0px));
}

/* Screen-reader-only. The newsletter's label is real text that simply is not
   drawn — a placeholder alone is not a label: it disappears the moment the
   field is typed into, and several screen readers do not announce it at all. */
.u-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* -- row one: the company, and the one thing the footer asks for -----------
   The account sits on the reading edge and the form opposite it. The columns
   are unequal on purpose: prose needs a measure, a single field does not. */
/* Two columns, each stacking its own things — not two full-width rows one
   above the other. That earlier arrangement is what made the footer so tall:
   the account, then a divider, then a badge row, then an icon row, four bands
   of nearly empty space where two columns hold the same content side by side.

   The aside is a fixed 340px so the newsletter and the icon row beneath it
   come to exactly the same width; at `1fr` the form would stretch to whatever
   was left over and the two would never line up. */
.site-footer__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  /* `stretch`, not `start`. With the aside pinned to the top it ended where
     the form's second row did, and the brand column carried on for another
     200px underneath — so one side of the footer was a short block at the top
     and the other a tall one, and the bottom-left quarter was empty. Stretched,
     the aside spans the same height and can place its two pieces against both
     ends of it. */
  /* `stretch`, so the aside spans the brand column's full height and can put
     its two pieces against both ends of it. With `start` the aside stopped
     wherever its own content ran out — the icons landed level with the middle
     of the paragraph and the bottom-left quarter was empty while the form sat
     alone at the bottom-right. */
  align-items: stretch;
  gap: 56px;
}

/* Two pieces, one at each end: the address takes the top edge, level with the
   logo opposite it; the icons take the bottom, level with the form. Both
   columns then start together and finish together, which is what makes the
   pair read as balanced rather than as one heavy side and one light one. */
.site-footer__aside {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: space-between;
  gap: 26px;
}

/* A flex column, so the form's `margin-top: auto` has a floor to be pushed
   against. As a plain block it would have nothing to measure from and the
   `auto` would collapse to zero. */
.site-footer__brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  height: 100%;
}

.site-footer__logo {
  display: block;
  width: 204px;
  /* The logo art carries transparent margin at its head that the form's border
     does not, so the two would not start on the same line by their boxes
     alone. */
  margin-block-start: -6px;
  /* Each asset carries a little transparent margin from the artboard, so the
     negative offset aligns the artwork itself — not its canvas — with the
     content column. */
  margin-inline-start: -12px;
  transition: opacity .25s var(--ease);
}
.site-footer__logo:hover { opacity: .8; }

.site-footer__about {
  max-width: 54ch;
  margin: 18px 0 0;
  font-size: 15px;
  font-weight: 300;
  line-height: 1.9;
  /* 78% white clears 4.5:1 against every stop of the plate's gradient; at
     weight 300 full-strength white vibrates against a saturated purple. */
  color: rgb(255 255 255 / .78);
}

/* The marks sit UNDER the address, not beside it. Side by side they were
   always going to float: the address's three rows are short, so whatever gap
   was set between them read as arbitrary — too near at 12px, adrift at 34px.
   Stacked, they have an edge to hold instead of a gap to justify, and they take
   the column's own start edge, in line with the logo, the paragraph and the
   first word of every address row above them. */
/* The marks and the icons, as one block at the foot of the column. Both rows
   run on the same four-column grid and the same width, so each mark sits
   directly over the icon beneath it — which is what "هم‌تراز" asks for and what
   a gap between two separately-placed rows could never guarantee. */
.site-footer__marks {
  width: 100%;
}

.site-footer__address {
  font-style: normal;                  /* <address> italicises by default */
}
/* The two rows the marks are meant to face — the phone and the email — are the
   short ones, so nothing here needs to reach across the column. */
.site-footer__address p {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 0 0 7px;
  font-size: 14.2px;
  font-weight: 400;
  line-height: 1.85;
  color: rgb(255 255 255 / .72);
}
.site-footer__address p:last-child { margin-bottom: 0; }
/* The marks read as one more row of the same block, so the gap above them is
   the block's own row rhythm, not a section break. */
.site-footer__address a {
  color: rgb(255 255 255 / .72);
  transition: color .25s var(--ease);
  /* The phone number and the address are Persian text but the address block
     runs LTR-ish digits; kept as the document's own direction so nothing
     re-orders. */
}
.site-footer__address a:hover { color: var(--gold); }

.site-footer__ico {
  flex: none;
  width: 17px;
  height: 17px;
  margin-top: 6px;                     /* onto the first line's optical centre */
  fill: none;
  stroke: var(--gold);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* -- the newsletter -------------------------------------------------------
   One field and one button. A footer form that also asks for a name is a
   footer form nobody finishes. The pair sits inside one bordered box rather
   than as an input beside a button, so it reads as a single control — and the
   box, not the input, is what carries the focus ring. */
/* The form is now a field and nothing else — no frame, no heading, no note.
   A bordered panel wrapped around a bordered field was two boxes doing one job,
   and the heading repeated what the button already says. What is left is the
   control itself and the line that answers it. */
.nletter {
  /* Sized to the paragraph it now sits under, not to the column: the brand
     column is the wide one and a field stretched across all of it would be the
     largest object in the footer. 420px is the measure the address opposite it
     comes to, so the two sides read as a pair. */
  width: min(100%, 420px);
  margin-top: auto;                    /* pushed to the column's own floor */
  padding-top: 26px;
}


.nletter__field {
  display: flex;
  align-items: stretch;
  gap: 6px;
  padding: 5px;
  border: 1px solid rgb(255 255 255 / .22);
  border-radius: 8px 8px 8px 22px;
  background: rgb(17 7 53 / .34);
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.nletter__field:focus-within {
  border-color: rgb(186 166 96 / .7);
  background: rgb(17 7 53 / .5);
}

.nletter__input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 9px 12px;
  border: 0;
  background: transparent;
  font-family: inherit;
  font-size: 14px;
  font-weight: 400;
  color: #fff;
  /* The ring is drawn on the wrapper by :focus-within, so a second one here
     would double it. */
  outline: none;
}
.nletter__input::placeholder { color: rgb(255 255 255 / .4); }

.nletter__submit {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  /* The label carries the whole instruction now — "عضویت" alone said what the
     button did to the form, not what it does for the reader — so it is given
     the room to sit on one line and never wrap. */
  padding: 0 15px;
  white-space: nowrap;
  border: 0;
  border-radius: 6px 6px 6px 18px;
  background: var(--gold);
  font-family: inherit;
  font-size: 13px;
  font-weight: 700;
  /* Deep purple on gold measures 7.9:1. White on gold is 2.4:1 and fails. */
  color: var(--purple-deep);
  cursor: pointer;
  transition: background .25s var(--ease), transform .25s var(--ease);
}
.nletter__submit svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform .25s var(--ease);
}
.nletter__submit:hover {
  background: color-mix(in srgb, var(--gold) 84%, #fff);
  transform: translateY(-1px);
}
.nletter__submit:hover svg { transform: translate(2px, -2px); }

/* Empty until there is something to say, so it takes no room at rest. */
.nletter__msg {
  margin: 12px 0 0;
  font-size: 13.4px;
  font-weight: 500;
  line-height: 1.7;
  min-height: 0;
}
.nletter__msg:empty { display: none; }
.nletter__msg.is-ok  { color: color-mix(in srgb, var(--gold) 55%, #fff); }
.nletter__msg.is-bad { color: #ffb4b4; }

/* The marks, cut out of their own backgrounds. They are the one place in the
   footer where the company's word is not the evidence, so they are shown
   rather than described — and they sit directly under the account they vouch
   for rather than in a band of their own.

   Sized by HEIGHT, not width: a round seal and a tall trophy are wildly
   different shapes, and matching their widths would make one of them enormous.
   A common height is what makes a row of unlike objects read as a set. */
/* Four marks in one even row, and `1fr` columns rather than a flex gap: equal
   shares mean the row is exactly as wide as the block above it whatever the
   artwork measures, so its two ends land on the address's own edges. That is
   what stops a row of unlike objects from drifting.

   `align-items: end` sits them all on one floor, and a common HEIGHT — not a
   common width — is what makes them read as a set: a round seal and a tall
   trophy matched by width would leave one of them enormous.

   The eye is given a path rather than a queue: each mark is nudged a little
   lower than the one before it, so the row descends gently from the reading
   edge instead of sitting as four identical blocks. The offsets are tiny, 0 to
   9px, which is enough to be felt and not enough to look misaligned. */
.site-footer__certs {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  align-items: end;
  justify-items: center;
  margin: 0 0 18px;
}
.site-footer__certs li { display: flex; }
.site-footer__certs li:nth-child(2) { transform: translateY(3px); }
.site-footer__certs li:nth-child(3) { transform: translateY(6px); }
.site-footer__certs li:nth-child(4) { transform: translateY(9px); }

.site-footer__certs img {
  width: auto;
  height: 62px;
  /* The artwork carries its own colour and its own gold; nothing is tinted, so
     each reads as the object it is against the purple. */
  filter: drop-shadow(0 8px 16px rgb(11 5 32 / .45));
  transition: transform .3s var(--ease), filter .3s var(--ease);
}
.site-footer__certs img:hover {
  transform: translateY(-4px);
  filter: drop-shadow(0 14px 24px rgb(11 5 32 / .6));
}

.site-footer__social {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  direction: ltr;                      /* Instagram first, on the far left */
  place-items: center;
  width: 100%;
  /* The marks above set the distance; a margin here would add to it. */
  margin: 0;
}
.site-footer__social li { display: flex; }
.site-footer__social img {
  width: 54px;
  height: 58px;
  transition: transform .25s var(--ease);
}
.site-footer__social a:hover img { transform: translateY(-3px); }

/* One focus ring for everything the footer offers a keyboard. */
.site-footer a:focus-visible,
.nletter__submit:focus-visible,
.nletter__field:focus-within {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}

/* ==========================================================================
   11. Responsive
   The artboard is 1920 wide; below that the columns give way in stages.
   ========================================================================== */
@media (max-width: 1700px) {
  :root { --edge: 48px; }
  .site-header__inner { gap: 56px; }
  .site-nav__list { gap: 40px; }
}

@media (max-width: 1500px) {
  :root { --container: 1160px; }

  .site-nav__link { font-size: 20px; }
  .site-header__logo { width: 190px; height: 73px; }

  .hero { height: 700px; }
  .hero__content { padding-top: 400px; padding-inline-end: 90px; }
  .hero__title { font-size: 38px; }
  .hero__rule { width: 400px; }
  .hero__actions { gap: 120px; }

  .about { padding-block: 64px 74px; }
  .about__body { padding-top: 40px; }
  .about__title { font-size: 32px; }
  .about__text { font-size: 21px; }

  .brand-row { grid-template-columns: 380px minmax(0, 1fr); }
  .brand-row--flip { grid-template-columns: minmax(0, 1fr) 380px; }
  .brand-row__logo { width: 100% !important; inset-inline: 0 !important; }
  .brand-row__text { font-size: 21px; }

  /* No `bottom` overrides needed here any more — the base rule anchors both
     to a percentage of the ornament's height, which rescales on its own. */
}

@media (max-width: 1200px) {
  .container { width: calc(100% - 64px); }

  .brands__title { font-size: 42px; }

  .card-grid { grid-template-columns: repeat(3, 1fr); }
  .card-grid > :last-child { display: none; }

  .gallery__track > .gallery__item { flex-basis: calc((100% - 2 * 24px) / 3); }

  /* The full nav (7 Persian labels + logo) stops fitting well before the
     1024px structural breakpoint below — by ~1150px it was already
     overflowing the header. Switching to the drawer here, rather than at
     1024, means desktop nav never has to run in a width it doesn't fit. */
  :root {
    --header-h: 96px;
    --header-drop: 16px;
    --hero-top: calc(var(--header-h) + var(--header-drop) + 44px);
  }

  .site-nav { display: none; }
  .site-header__burger { display: flex; }

  /* With the nav gone the bar holds two items, and where each one lands was
     being decided by leftovers: the 107px/56px `gap` written for the desktop
     nav, plus an auto inline-start margin on the burger. That only reads as
     "logo at one edge, burger at the other" while there happens to be spare
     room — and the logo is still carrying its 190×73 desktop size inside a
     bar that just shrank to 96px, so on a narrow phone the two fought for
     width and drifted inward instead of sitting on their edges.

     space-between states the intent directly, so placement no longer depends
     on gap arithmetic at any width, and the logo is resized to the shorter
     bar (73px of art in a 96px bar left almost no breathing room). */
  .site-header__inner { gap: 16px; justify-content: space-between; }
  .site-header__logo { width: 168px; height: 64px; }
  .site-header__burger { margin-inline-start: 0; }

  /* 46×46 was the drawn size; the padding-box is what a finger has to hit, so
     it goes to the 44px floor with the three bars unchanged inside it. */
  .site-header__burger { width: 44px; height: 44px; padding: 11px 8px; }

  /* Mobile drawer */
  .site-nav.is-open {
    position: absolute;
    inset-inline: 0;
    top: 100%;
    display: block;
    padding: 24px var(--edge) 32px;
    background: #fff;
    box-shadow: 0 18px 40px rgba(68, 47, 114, .18);
  }
  .site-nav.is-open .site-nav__list { flex-direction: column; align-items: flex-start; gap: 18px; }
  .site-nav.is-open .site-nav__link { color: var(--purple); font-size: 19px; }
}

@media (max-width: 1024px) {
  .hero { height: 620px; }
  .hero__content { padding-top: 330px; padding-inline-end: 56px; }
  .hero__title { font-size: 32px; }
  .hero__pattern { width: 170px; opacity: .55; }
  .hero__rule { width: min(360px, 60vw); }
  .hero__actions { gap: 60px; }

  .about__inner { grid-template-columns: 1fr; gap: 32px; padding-inline: 0; }
  .about__mark { order: 2; justify-self: center; width: min(400px, 80%); }
  .about__mark img { max-width: none; }
  .about__body { padding-top: 0; }
  .about__title { font-size: 30px; }
  .about__rule { margin-inline-start: 0; width: min(340px, 70%); }
  .about__text { font-size: 18px; line-height: 1.5; }
  .about__inner { width: min(var(--container), calc(100% - 64px)); margin-inline: auto; }

  /* Only the width cap and the type scale change; the headline's placement
     follows from the base rule's percentages + em. */
  .brands__head { width: min(560px, 100%); }
  .brands__title { font-size: 34px; }
  .brands__list { margin-top: 90px; }

  .brand-row { grid-template-columns: 1fr; gap: 28px; min-height: 0; }
  .brand-row--flip .brand-row__media,
  .brand-row--flip .brand-row__body { grid-column: 1; }
  .brand-row__media { order: 2; align-self: auto; height: auto; }
  .brand-row__logo,
  .brand-row__logo--sundis,
  .brand-row__logo--cogent,
  .brand-row__logo--barleta,
  .brand-row__logo--vebs,
  .brand-row__logo--sunda { position: static; translate: none; width: min(320px, 70%) !important; margin-inline: auto; }
  /* The wash was biased toward whichever side the mark sat on; stacked, media
     and body share one column and there is no "side" left to bias toward. */
  .brand-row::before,
  .brand-row--flip::before {
    background: radial-gradient(70% 60% at 50% 38%,
      rgb(var(--row-tint) / .08) 0%, rgb(var(--row-tint) / 0) 72%);
  }
  .brand-row + .brand-row { margin-top: 72px; }
  .brand-row:not(:last-child)::after { bottom: -36px; }   /* half of 72px, not 144px */
  .brand-row__text { font-size: 18px; line-height: 1.5; margin-top: 22px; }

  /* The gold half used to be dropped here, leaving a bare purple stub: its
     length was written as `calc(100% + 120px)`, sized for the tall side-by-side
     media column, which overshot badly once the layout stacked. That was a
     sizing problem, not a reason to lose half the motif — the purple-to-gold
     handoff is the identity, so it should survive at every width. With the tail
     now bounded by the bracket itself (`bottom: 0`) it scales sanely, so the
     full two-tone stroke comes back, just shorter and with a tighter corner in
     proportion to the smaller type.

     Everything is scaled by the same factor so the S keeps its shape, and the
     base rule's constraint still governs: the purple box's width must equal its
     radius (46 − 34 = 12), and its height must land on the gold's top edge. */
  .brand-row__bracket { width: 46px; height: 72px; }
  .brand-row__bracket::before {
    height: 30px;
    inset-inline-end: 34px;            /* width 46−34 = 12px = the radius */
    border-end-start-radius: 12px;
  }
  .brand-row__bracket::after {
    display: block;
    top: 28.4px;
    border-start-start-radius: 12px;
  }
  .brand-row__name { font-size: 23px; }

  .editorial { padding-block: 70px 72px; }
  .editorial__second { margin-top: 60px; }

  /* Four across becomes two-by-two: below this width each panel is narrower
     than its own number is wide, and the labels start wrapping mid-word. */
  .figures { margin-block: 76px; padding-block: 62px 58px; }
  .figures__eyebrow { font-size: 13px; margin-bottom: 16px; }
  .figures__eyebrow::before,
  .figures__eyebrow::after { width: 40px; }
  .figures__title { font-size: 28px; }
  .figure__icon { width: 32px; height: 32px; margin-inline-end: 11px; vertical-align: -5px; }
  .figures__lead { font-size: 16px; }
  .figures__list { grid-template-columns: repeat(2, 1fr); gap: 20px; margin-top: 46px; }
  .figure { padding: 28px 18px 24px; }
  .figure__value { font-size: 48px; }

  .section-head { margin-bottom: 26px; }
  /* Only the type scale changes here; the shared baseline follows the smaller
     font automatically, since the base rule's offset is in `em`. */
  .section-head__title { font-size: 26px; inset-inline-start: 54px; }
  .section-head--light { margin-bottom: 14px; }
  .link-arrow { font-size: 18px; }

  .card-grid { grid-template-columns: repeat(2, 1fr); }
  .card-grid > :last-child { display: block; }

  .gallery { padding-top: 50px; }
  .gallery__track { gap: 18px; }
  .gallery__track > .gallery__item { flex-basis: calc((100% - 18px) / 2); }

  /* The artwork is one fixed-pixel drawing (2477px), so it never shrank with
     the viewport — on a tablet it was still the same physical size it is on a
     1920px desktop, which reads as oversized against a much narrower footer.
     Scaling it down from its own pinned corner (left/top stay put) keeps the
     registration intact while bringing its footprint back in line with how
     much of the plate it actually covers on desktop. */
  .plate__pattern { top: -60px; opacity: .2; transform: scale(.62); transform-origin: top left; }
  /* Below a tablet the two columns leave the account about 300px wide, which
     breaks its sentences into four-word lines. They stack, and the aside — the
     form and the icon row it is paired with — follows the address. */
  .site-footer { padding-block: 62px calc(52px + env(safe-area-inset-bottom, 0px)); }
  .site-footer__grid { grid-template-columns: 1fr; gap: 34px; }
  /* Stacked, there is no shared height for either column to distribute
     against, so both fall back to plain flow. */
  .site-footer__brand { display: block; height: auto; }
  .site-footer__aside { width: min(100%, 420px); display: block; }
  .nletter { margin-top: 22px; padding-top: 0; }
  /* The block was pinned to the foot of a column that no longer has one. */
  .site-footer__marks { margin-top: 26px; }
  .site-footer__about { max-width: none; font-size: 14.6px; }
  .site-footer__certs img { height: 52px; }
  .site-footer__social img { width: 50px; height: 54px; }
}

@media (max-width: 620px) {
  .container,
  .about__inner { width: calc(100% - 40px); }
  :root { --edge: 20px; --hero-top: calc(var(--header-h) + var(--header-drop) + 32px); }

  /* Same corner drawing, scaled further for a phone-width footer — .4 of the
     2477px original instead of the tablet's .62, so the motif stays a fine
     texture rather than a handful of oversized lines across a 375px column. */
  .plate__pattern { transform: scale(.4); transform-origin: top left; }

  .site-footer { padding-block: 48px calc(40px + env(safe-area-inset-bottom, 0px)); }
  .site-footer__logo { width: 158px; margin-block-start: 0; }
  .site-footer__about { font-size: 14.2px; line-height: 1.95; margin-top: 14px; }
  .site-footer__address p { font-size: 13.6px; gap: 8px; margin-bottom: 8px; }
  .site-footer__ico { width: 15px; height: 15px; margin-top: 5px; }

  /* Stacked, because a 90px field beside a 130px button is not a field. The
     button takes the full width so it reads as the action rather than as a tab
     stuck to the end of an input. */
  .nletter__field { flex-direction: column; gap: 6px; }
  /* Stacked, the button is no longer beside the field, so it takes the full
     width rather than sitting as a short tab under a long input. */
  .nletter__submit { justify-content: center; padding: 12px 20px; }
  /* Four across a phone column gives each about 70px, which is smaller than
     the trophy reads at. Two by two, and the descent is dropped with the row
     it belonged to. */
  /* All four stay on one line, as on the desktop — so the row still reads as a
     set and each mark still sits over the icon beneath it. Four `1fr` columns
     across a 350px content width give about 87px each, so the marks are sized
     to that share rather than to a fixed height: `max-width: 100%` lets the
     trophy shrink to fit its column instead of overflowing it, and the height
     is the cap for the seal, which is the wider of the two shapes. The descent
     is dropped — at this size a 4px step reads as a mistake, not as motion. */
  .site-footer__certs {
    grid-template-columns: repeat(4, 1fr);
    justify-items: center;
    margin-bottom: 18px;
  }
  .site-footer__certs li:nth-child(n) { transform: none; }
  .site-footer__certs img { height: 46px; max-width: 100%; object-fit: contain; }

  /* The icons keep their four columns — they are the same shape and they fit —
     but they no longer have the marks above them to line up with, so they are
     spread across the column on their own. */
  .site-footer__social img { width: 46px; height: 50px; }

  /* Two-by-two is kept rather than dropping to one per row: these are short
     numbers, and a single column of four would stretch the band to nearly a
     full phone screen — long enough to stop reading as a beat between the two
     grids and start reading as a section of its own. */
  /* The pattern keeps its full drawing scale here on purpose. Scaling it down
     for a narrow screen — the way .plate__pattern has to, because it is one
     placed crop that would otherwise overrun — would turn a motif into noise;
     tiled, a phone simply shows less of the same drawing, which is what a
     surface treatment should do. */
  .figures { margin-block: 60px; padding-block: 48px 44px; }
  /* The flanking rules shrink to almost nothing at this width; dropped
     entirely rather than left as two 12px stubs beside the words. */
  .figures__eyebrow { font-size: 12px; gap: 12px; margin-bottom: 12px; }
  .figures__eyebrow::before,
  .figures__eyebrow::after { display: none; }
  .figures__title { font-size: 23px; }
  .figure__icon { width: 25px; height: 25px; margin-inline-end: 8px; vertical-align: -4px; }
  .figures__more { padding: 11px 22px; border-radius: 8px 8px 18px 8px; }
  .figures__title::after { width: 72px; margin-top: 14px; }
  .figures__lead { font-size: 15px; margin-top: 16px; }
  .figures__list { margin-top: 38px; gap: 14px; }
  .figure { padding: 24px 12px 20px; border-radius: 10px 10px 26px 10px; }
  .figure__value { font-size: 38px; }
  .figure__unit { font-size: 13.5px; margin-inline-start: 6px; }
  .figure__label { font-size: 12.5px; margin-top: 16px; padding-top: 12px; }
  .figures__more { margin-top: 38px; }

  /* On desktop the headline and its rule are deliberately off-axis: the rule
     is a fixed 407px starting 41px outside the copy column, because it has to
     meet a line drawn inside the mark image sitting beside it, and the 54.5px
     gap above it is the vertical half of that same alignment. Stacked on
     mobile the mark is no longer alongside, so none of that geometry has
     anything to point at — the rule just reads as a stray off-centre dash
     floating well below the headline. Centre both on the column's own axis
     instead and close the gap, so they read as one titled unit.
     margin-inline:auto (not the -41px start offset) is what re-centres it. */
  .about__title { text-align: center; }
  .about__rule {
    width: min(280px, 62%);
    margin-block-start: 18px;
    margin-inline: auto;
    /* The desktop rule fades toward one end because it is reaching *towards*
       the mark beside it. Centred under the headline there is no "towards"
       any more, so a one-sided fade would just look like the line ran out on
       one side — symmetric here fades both ends into the same centred stroke. */
    background: linear-gradient(to left,
      rgb(68 47 114 / 0), var(--purple) 30%, var(--purple) 70%, rgb(68 47 114 / 0));
  }

  /* Placement itself is settled at the 1200px breakpoint (space-between);
     all that's left here is the phone size for the lock-up. 132×51 keeps the
     wordmark legible while leaving the burger its full 44px on the opposite
     edge — together with the two 20px edge paddings that's 216px, so the two
     still sit on their own edges on a 320px screen instead of meeting in the
     middle. */
  .site-header__logo { width: 132px; height: 51px; }

  .hero { height: 540px; }
  .hero__content { padding-top: 270px; padding-inline-end: 20px; }
  .hero__title { font-size: 25px; line-height: 1.35; }
  /* Scaled down rather than removed — the corner motif is part of the
     identity at every size, not just desktop/tablet. At 100px it fits
     entirely above where the headline starts (padding-top:270px), so nothing
     competes with the text underneath. */
  .hero__pattern { width: 100px; opacity: .4; }
  /* RTL column flex: cross-end is the left edge, matching the headline */
  .hero__actions { flex-direction: column; align-items: flex-end; gap: 22px; }
  .hero__rule { margin-top: 26px; }

  /* The fixed height + object-fit:contain that used to be here letterboxed the
     artwork inside a box that no longer matched its aspect, which shifted the
     motif by an amount that changed with viewport width — so no single `top`
     could keep the headline on its edge. With the head sized by the image
     itself (base rule), the percentages stay exact here too and only the type
     scale needs stating.

     The headline is `white-space: nowrap` (wrapping it would pull the second
     line off the motif's edge, which is the whole point of the alignment), so
     on the narrowest phones it has to shrink rather than overflow: below about
     a 380px viewport, 25px no longer fits in the width left beside the motif.
     The `em`-based `top` means the baseline follows the smaller size on its
     own. The vw term assumes this breakpoint's `.container` width of
     100% − 40px; revisit it if that changes. */
  .brands__title { font-size: min(25px, calc(8.1vw - 4.6px)); }

  /* "اطلاعات بیشتر برند" needs no override here — it's pushed to the column's
     end edge by the base rule, at every width, as the source design has it. */

  .card-grid { grid-template-columns: 1fr; }
  /* One card per view, with a sliver of the next peeking in — a standard
     "there's more, keep going" affordance on a single-column slider. */
  .gallery__track { gap: 14px; }
  .gallery__track > .gallery__item { flex-basis: 88%; }
  .gallery__nav { width: 40px; height: 40px; }

  /* Below ~620px the ornament's own width/auto-height scaling shrinks the
     swirl-and-rule artwork down to a thin, barely-visible sliver. Same fix
     used for the brand-band head ("برندهای شرکت پاکدیس"): give the
     ornament a fixed height and let it fill that with object-fit:cover
     instead of shrinking to the column's width — it reads at full size
     again, cropped to its meaningful right-hand portion (icon + rule)
     rather than letterboxed down.

     Title and link are no longer both overlaid on the ornament, sharing
     its stacking context — the ornament now sits in normal flow (a plain
     block, not absolutely positioned) and only the title overlays it,
     baseline resting on the rule next to the icon, matching how the
     desktop version pairs them. The "مشاهده همه" link comes *after* the
     ornament in normal flow instead — a separate row below the line, not
     another absolutely-positioned layer competing with the title for the
     same box. That guarantees it always renders under the rule regardless
     of exactly how tall the ornament ends up or whether the title wraps —
     nothing to miscalculate, the browser's normal flow does the work. */
  .section-head { margin-bottom: 22px; }
  /* Height governs the `cover` scale at every mobile width, so this number
     also sets how big the icon glyph renders — they share one scale factor.
     The glyph is only 51×96 px in the source artwork's own 1394×178 natural
     box, i.e. tiny relative to the sheet, which is exactly why the original
     width-driven scaling made it vanish: at a 340px column it came out ~12px
     across. 150px height scales it to ~43×81px — present and legible, the
     way it reads on desktop — while still leaving ~250px of headline room.

     margin-bottom trims the ~18px of blank canvas the artwork carries below
     its rule (21.5 of 178 natural px, scaled by 150/178), so the element's
     layout box ends on the rule rather than below it. That's what lets the
     "مشاهده همه" link sit right under the line with a plain, readable gap
     instead of a negative margin cancelling out invisible whitespace. */
  .section-head__orn {
    position: static;
    display: block;
    width: 100%;
    height: 150px;
    margin-block-end: -18px;
    margin-inline-start: 0;
    object-fit: cover;
    object-position: right bottom;
  }
  /* The headline's underline should read as a continuation of the icon's own
     square — not the long rule below it. Those are two different lines in the
     artwork: measuring the source PNG, the square's bottom edge sits at
     natural y≈106 and the long rule at y≈155.5 (of 178). At `cover` scale
     150/178 ≈ 0.843 the square's edge lands at y≈89px in the rendered box.
     Text baselines sit ~0.375em above their box's bottom edge (half-leading
     plus descender), which is ~8px at this size, so the box bottom goes at
     ≈98px to put the baseline itself on the motif's edge.

     The base rule expresses this same alignment as a percentage of the
     ornament's height, which works there because the ornament is height:auto
     and so `.section-head` is exactly as tall as the scaled artwork. Here the
     ornament is a fixed-height `cover` crop with a negative bottom margin, so
     the container's height no longer tracks the artwork — hence the explicit
     px value. If the 150px height above changes, recompute this as
     150 - 71.5 × (150/178) + 0.375 × font-size.

     Anchoring with `top` alone would break the moment a long headline (e.g.
     "اخبار و رویدادهای شرکت" at a narrow width) wraps to two lines: the box
     would grow *downward*, straight through the artwork. `top` plus
     translateY(-100%) anchors the box's bottom edge there instead, so extra
     lines stack upward into the empty space above and the last line always
     rests on the square's edge — regardless of line count or font metrics,
     which is exactly the sort of thing that can't be verified without a
     browser.

     72px of inline-start (= the right edge, RTL) clears the square, whose
     left edge measures ~61px in from the container's right at this scale;
     the remainder is optical breathing room so the text doesn't crowd it. */
  .section-head__title {
    position: absolute;
    top: 98px;
    bottom: auto;
    transform: translateY(-100%);
    inset-inline-start: 72px;
    max-width: calc(100% - 95px);
    margin: 0;
    font-size: 21px;
  }
  /* `.section-head--light .section-head__title` (gallery, on the purple
     plate) is a two-class selector, so its `bottom` value from the
     1024px/1500px breakpoints above — never re-declared at this
     breakpoint until now — otherwise beats this block's plain
     `.section-head__title` on specificity alone and reintroduces the
     bottom-anchored desktop position underneath the top-anchored one set
     above. Neutralize it explicitly rather than relying on source order,
     which doesn't help across a specificity gap. */
  /* The gallery ornament's motif edge is drawn ~5.5 natural px higher than the
     news/articles one (76.5 up from the bottom vs 71.5), so at this crop scale
     its writing line lands ~5px above theirs — same reason the base rules use
     a different percentage for --light. */
  .section-head--light .section-head__title { bottom: auto; top: 93px; }

  /* "مشاهده همه" drops below the rule instead of sharing the headline's line.
     This block never re-declared it, so the link kept the desktop rule —
     `bottom: calc(40.2% - .375em)` — and that percentage resolves against the
     container, whose height here is the fixed 150px crop rather than the
     artwork's own scaled height. It landed at ~52px, straight through
     "اخبار و رویدادهای شرکت".

     `position: static` is the whole fix: the link returns to flow, and since
     the ornament is the only other in-flow child, flow puts it immediately
     under the ornament's layout box — which ends on the rule itself, because
     of the -18px that trims the artwork's blank foot. Measured: the long rule
     sits at natural y=156 of 178, so at the 150/178 crop scale it renders at
     131.5px against a 132px box. 7px of margin puts the link just below the
     line, which is where it was asked to be.

     The gallery ornament draws its rule 5.5 natural px higher (150.5 vs 156),
     so on the purple plate it lands ~5px above the box's foot — the link needs
     that much less margin to keep the same visible gap. */
  .section-head__more {
    position: static;
    /* Block-level so an auto start-margin can push it, `fit-content` so it
       stays only as wide as its own words: in RTL an auto margin-inline-start
       is a margin on the right, which drives the box to the far (left) edge —
       the same corner it holds on desktop. */
    display: flex;
    width: fit-content;
    margin-inline-start: auto;
    inset-inline-end: auto;
    bottom: auto;
    margin-top: 7px;
    font-size: 15px;
  }
  .section-head--light .section-head__more { bottom: auto; margin-top: 2px; }
}

/* --------------------------------------------------------------------------
   Breadcrumb rhythm
   --------------------------------------------------------------------------
   The trail's own look is set per page, because it sits on purple on some and
   over a photograph on others. What is shared is its place in the vertical
   rhythm: the same gap under it everywhere, so the first line of a page always
   lands in the same spot no matter which page it is.

   Pages whose trail is the only thing in its band opt out with a rule of their
   own — there is nothing below it for the gap to separate it from.
   -------------------------------------------------------------------------- */
.breadcrumb { margin-bottom: 26px; }

@media (max-width: 1200px) { .breadcrumb { margin-bottom: 22px; } }
@media (max-width: 620px)  { .breadcrumb { margin-bottom: 18px; } }

/* --------------------------------------------------------------------------
   Page title
   --------------------------------------------------------------------------
   The h1 treatment shared by every inner page: the identity's ornament running
   under the headline, its square motif standing at the reading-start edge, and
   the long rule closing the block.

   It lives here rather than in each page's sheet because it is the one thing
   every page has in common — separate copies would drift apart the first time
   one of them was adjusted. A page sets only which motif it uses, whether it
   sits on purple, and whether the rule runs short or full.

   WHY THE ORNAMENT IS ONE IMAGE
   The motif and the rule are a single continuous stroke joined by a rounded
   elbow. Drawing them as two elements — a mark and a border — loses that join,
   which is the detail that makes the device the brand's rather than a generic
   heading rule. So the sheet is used whole.

   WHY THE ARTWORK IS PULLED UP WITH A PERCENTAGE
   `.section-head` positions its headline absolutely, hung off a percentage of
   the ornament's height. That works for a one-line section title and breaks the
   moment the text wraps — which a page title does. Here the headline stays in
   normal flow and the artwork is pulled up under it instead.

   The pull has to scale with the block, and a percentage margin resolves
   against the containing block's *width* — which is exactly what is needed,
   because the artwork's own height is also a fixed fraction of its width.

   WHY THERE ARE TWO SHEET LENGTHS
   A rule that crosses the entire column is a heavier horizontal than a page
   title needs; it reads as a section divider rather than as the close of a
   heading. So the default sheet is cropped to its last 52% and the element is
   narrowed by the same 52%.

   Cropping and narrowing by the same factor cancel out, which is the whole
   trick: the motif and the artwork's height come out identical either way, and
   only the rule gets shorter.

       default   0.52 x W / 6.97  = 7.46% of W tall, motif 5.25% of W
       --wide    1.00 x W / 13.41 = 7.46% of W tall, motif 5.25% of W

   `--wide` exists for the two single-item pages, where the headline is the
   article's own and long enough that a full-width rule sits under it properly.
   -------------------------------------------------------------------------- */

.ptitle {
  position: relative;
  /* Room for the motif's overhang.

     The artwork is pulled up under the text, and the motif is taller than a
     line of type — so it rises above the headline by (pull - text height),
     which measures 20 to 28px depending on the width. Nothing was reserving
     that, so the breadcrumb's own gap was landing on the mark's top edge.

     The number to hold steady is not this padding, it is what the eye actually
     sees: the gap between the trail and the top of the mark. That comes out as

         visible gap = breadcrumb margin-bottom + this padding - overhang

     and all three terms move with the breakpoint. Solved for a 15-20px gap it
     gives 19 / 18 / 26 — the padding going *up* on phones precisely because
     the overhang is largest there and the trail's own margin smallest.

     Padding rather than margin: adjacent margins collapse to the larger of the
     two, which would have swallowed most of this. */
  padding-top: 19px;
}

.ptitle__text {
  margin: 0;
  /* Clears the motif, which lands on the last 5.25% of the column either way.
     7.6% leaves a little over two motif-widths of air between mark and type. */
  padding-inline-start: 7.6%;
  /* Down from clamp(26px, 3.3vw, 47.5px): at the old ceiling a two-word page
     title filled half the artboard and outweighed the content under it. This
     tops out just above the 34.9px `.section-head` uses, which is the size the
     rest of the site's headings are set at. */
  font-size: clamp(24px, 2.6vw, 38px);
  font-weight: 900;
  line-height: 1.34;
  color: var(--gold);
  text-wrap: balance;
}

.ptitle__art {
  display: block;
  width: 52%;
  height: auto;
  max-width: none;
  margin-top: -5.66%;
  pointer-events: none;
}

/* Full-length rule, for the single-item pages. */
.ptitle--wide .ptitle__art { width: 100%; }

/* The four motifs. They are genuinely different drawings, not one mark
   recoloured — measured pairwise, 11 to 25 mean alpha difference. */
.ptitle--section  .ptitle__art { content: url("../assets/ptitle-section-short.png"); }
.ptitle--articles .ptitle__art { content: url("../assets/ptitle-articles-short.png"); }
.ptitle--gallery  .ptitle__art { content: url("../assets/ptitle-gallery-short.png"); }
.ptitle--brands   .ptitle__art { content: url("../assets/ptitle-brands-short.png"); }

.ptitle--wide.ptitle--section  .ptitle__art { content: url("../assets/ptitle-section.png"); }
.ptitle--wide.ptitle--articles .ptitle__art { content: url("../assets/ptitle-articles.png"); }
.ptitle--wide.ptitle--gallery  .ptitle__art { content: url("../assets/ptitle-gallery.png"); }
.ptitle--wide.ptitle--brands   .ptitle__art { content: url("../assets/ptitle-brands.png"); }

/* On the purple pages the ornament switches to the light ink — the sheets are
   drawn in --purple, which on --purple-flood is invisible. Same artwork, one
   recoloured copy, so the join and the proportions are identical. */
.ptitle--onpurple.ptitle--section  .ptitle__art { content: url("../assets/ptitle-section-short-light.png"); }
.ptitle--onpurple.ptitle--articles .ptitle__art { content: url("../assets/ptitle-articles-short-light.png"); }
.ptitle--onpurple.ptitle--gallery  .ptitle__art { content: url("../assets/ptitle-gallery-short-light.png"); }
.ptitle--onpurple.ptitle--brands   .ptitle__art { content: url("../assets/ptitle-brands-short-light.png"); }

.ptitle--wide.ptitle--onpurple.ptitle--section  .ptitle__art { content: url("../assets/ptitle-section-light.png"); }
.ptitle--wide.ptitle--onpurple.ptitle--articles .ptitle__art { content: url("../assets/ptitle-articles-light.png"); }
.ptitle--wide.ptitle--onpurple.ptitle--gallery  .ptitle__art { content: url("../assets/ptitle-gallery-light.png"); }
.ptitle--wide.ptitle--onpurple.ptitle--brands   .ptitle__art { content: url("../assets/ptitle-brands-light.png"); }

/* The article hero sets its headline on a photograph, where gold measures 3.4:1
   against the scrim. That page keeps white type and its own shadow; only the
   ornament changes, to the light ink so the line work survives the picture. */
.ptitle--onphoto .ptitle__text { color: #fff; }
/* The short crop, matching every other page. This pointed at the full-length
   artwork while `.ptitle__art` was still sized (52%) and pulled (-5.66%) for
   the short one — so the article hero drew a whole rule inside half a rule's
   width, which put the motif at half scale and landed the line across the
   headline's second row. The two have to name the same crop. */
.ptitle--onphoto.ptitle--gallery .ptitle__art { content: url("../assets/ptitle-gallery-short-light.png"); }

/* --------------------------------------------------------------------------
   No tablet width override.

   There was one — the artwork went to 68% so the rule would not look stubby in
   a narrower column. It was wrong twice over: widening the artwork also widens
   the *motif*, so the mark grew against a title that was shrinking, and the
   pull was left at the 52% value, which dropped 42px of rule below the text
   where every other width shows about 20. Holding 52% everywhere means the
   whole device scales with the column, which is what it was built to do.
   -------------------------------------------------------------------------- */

@media (max-width: 1200px) {
  .ptitle { padding-top: 18px; }
}

/* --------------------------------------------------------------------------
   Below 620px the shared ratio stops working, and it is worth recording why
   rather than just changing numbers. At a 390px column the artwork is 29px
   tall and its motif 20px wide — smaller than the type it is meant to lead, so
   it reads as a smudge.

   The fix is to draw the artwork wider than the column and let it overflow. In
   RTL the image box starts at the inline-start edge, which is the right, so the
   sheet's own right end — where the motif is — lands exactly on the visible
   edge, and the rule is what runs off past the left. The motif comes back to a
   real size, in the place the desktop layout puts it.

   The type comes down harder than the fluid ramp alone would take it. At the
   desktop scale a page title was reaching three lines on a 390px phone, which
   for two or three words is a wrapping failure rather than a long title.
   -------------------------------------------------------------------------- */
@media (max-width: 620px) {
  .ptitle { overflow: hidden; padding-top: 26px; }
  .ptitle__text {
    /* Re-derived, not guessed. The motif is a fraction of the *artwork*, and
       the artwork is wider than the column here, so the motif's share of the
       column grows with it:

           short   0.101 x 118% = 11.9% of the column
           --wide  0.0525 x 230% = 12.1% of the column

       15% clears the larger of the two with about 12px to spare at 390px. The
       previous 12% was below both, which is why the headline was running into
       the mark. */
    padding-inline-start: 15%;
    font-size: clamp(20px, 5.6vw, 26px);
    line-height: 1.4;
  }
  .ptitle__art {
    width: 118%;
    /* 118% over a 6.97 ratio is 16.9% of the column tall, less the 1.8% that
       should stay visible below the type. */
    margin-top: -15.1%;
  }
  /* The wide sheet is 13.41:1, so it needs its own pair. */
  .ptitle--wide .ptitle__art { width: 230%; margin-top: -15.4%; }
}

@media print {
  .site-header,
  .gallery__nav,
  .hero__dots { display: none !important; }
  .plate { background: #fff; color: #000; }
}
