@charset "UTF-8";
/* ==========================================================================
   Pakdis — company page
   --------------------------------------------------------------------------
   A standalone sheet for about.html. It introduces no colour, font, radius or
   easing of its own — everything resolves to the tokens in css/style.css, and
   the header, footer, .plate, .section-head, .gallery, .ptitle and .breadcrumb
   components are used exactly as that sheet defines them.

   Two things here are built rather than borrowed, and both are the same idea
   at different scales: THE IDENTITY DRAWS LINES THAT TURN.

     - The certificate rail is an arc, not a row. It is a circle far larger
       than the section, so only its crown crosses the frame.
     - The timeline does not run straight. Each span steps between its
       neighbours and turns with the identity's rounded elbow, and every stop
       carries the pattern's square node.

   Nothing in either is an image: rings and elbows are borders on boxes, so
   they scale with the layout and stay crisp at any zoom.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Opening band
   `page-hero` on the section is a behaviour hook, not a style — js/app.js keys
   the sticky header's transparent→solid switch off `.hero, .page-hero`.
   -------------------------------------------------------------------------- */

.abhead {
  position: relative;
  overflow: hidden;
  /* Over-padded at the foot on purpose: the photograph below is pulled back up
     into that space, so the band hands over to the white page through the
     image rather than at a flat seam. */
  padding-block: var(--hero-top) 172px;
  background: var(--purple-flood);
  background: linear-gradient(158deg,
    color-mix(in srgb, var(--purple-flood) 88%, #fff) 0%,
    var(--purple-flood) 42%,
    #3b256b 78%,
    #34205f 100%);
  isolation: isolate;
}

/* The opening band carries the same ground as the rest of the page. It used to
   stretch the gallery sheet to `cover`, which meant its motifs were sized by
   the viewport rather than by the design — wider screen, bigger pattern, and a
   scale that agreed with nothing else on the page. It now takes the footer
   plate's own numbers — 2477px, `left -419px`, `top -101px` — so every purple
   surface on this page is one grid. The mask is kept: the band still has to
   hand over to the white section below rather than stop at it. */
.abhead::before {
  content: "";
  position: absolute;
  inset: 0;
  background: url(../assets/pattern-gallery.png) left -419px top -101px / 2477px auto repeat;
  opacity: .2;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 22%, #000 76%, transparent 99%);
          mask-image: linear-gradient(to bottom, transparent 0%, #000 22%, #000 76%, transparent 99%);
}

/* Two lights, not one. A single gold pool in the top corner lit that corner
   and left the opposite one visibly flat — the band read as under-exposed on
   the side the title actually sits on. The counter-light is white rather than
   a second gold, so it lifts the ground without introducing a colour: gold on
   both sides would tint the whole band and the identity's accent would stop
   reading as an accent. */
.abhead__glow {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(560px 560px at calc(100% + 220px) -180px,
      rgb(187 167 96 / .26) 0%, rgb(187 167 96 / 0) 70%),
    radial-gradient(760px 520px at -12% 108%,
      rgb(255 255 255 / .07) 0%, rgb(255 255 255 / 0) 72%);
}

/* A gold hairline along the very top of the band, under the sticky header.
   The page opens on a colour with nothing marking where it begins; every
   other edge on this page is drawn, and this one was not. */
.abhead::after {
  content: "";
  position: absolute;
  z-index: 2;
  inset-inline: 0;
  top: 0;
  height: 1px;
  background: linear-gradient(to left,
    rgb(187 167 96 / 0), rgb(187 167 96 / .45) 30%,
    rgb(187 167 96 / .45) 70%, rgb(187 167 96 / 0));
  pointer-events: none;
}

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

.abhead .breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-size: 14.5px;
  font-weight: 400;
  color: rgba(255, 255, 255, .7);
}
.abhead .breadcrumb a { color: rgba(255, 255, 255, .7); transition: color .2s var(--ease); }
.abhead .breadcrumb a:hover { color: var(--gold); }
.abhead .breadcrumb span { color: #fff; }
.abhead .breadcrumb__sep {
  flex: none;
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: .6;
  rotate: 180deg;                      /* RTL: chevron points start-ward */
}

/* --------------------------------------------------------------------------
   2. Photograph and the account
   -------------------------------------------------------------------------- */

.abintro { padding-block: 0 96px; }

.abintro__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 1fr);
  align-items: start;
  gap: 56px;
}

.abintro__media {
  position: relative;
  margin: 0;
  /* Laps the band's foot. The number is the band's over-padding minus the air
     the photograph should keep below the trail. */
  margin-top: -124px;
}

.abintro__frame {
  position: relative;
  display: block;
  overflow: hidden;
  /* The identity's asymmetric radius at feature scale — the same corner
     .card and .gallery__link carry, one step larger. */
  border-radius: 16px 16px 56px 16px;
  box-shadow:
    0 0 0 1px rgb(187 167 96 / .3),
    0 40px 80px -34px rgb(11 5 32 / .55);
}
/* The identity's corner, held off the frame rather than drawn on it: two
   strokes meeting at the outer corner, echoing the bracket the brand rows use
   on the home page. It is what stops a plain rectangle of photograph from
   being the one unbranded object on the page. */
.abintro__media::before {
  content: "";
  position: absolute;
  z-index: 1;
  top: -14px;
  inset-inline-end: -14px;
  width: 78px;
  height: 78px;
  border-top: 2px solid var(--gold);
  border-inline-end: 2px solid var(--gold);
  border-start-end-radius: 18px;
  pointer-events: none;
}

.abintro__frame img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3.15;
  object-fit: cover;
  object-position: 50% 42%;
}

.abintro__media figcaption {
  margin-top: 16px;
  padding-inline-start: 20px;
  border-inline-start: 2px solid rgb(186 166 96 / .55);
  font-size: 13.6px;
  font-weight: 300;
  line-height: 1.75;
  color: var(--grey-600);
}

.abintro__body { padding-top: 26px; }

/* The kicker is a chip, not a floating line — the same object the timeline
   stops carry, so the page has one way of labelling a thing rather than two.
   Its outline is what separates it from the paragraph below; without it a
   14px line above a 32px heading just reads as a stray first line. */
.abintro__kicker {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 20px;
  padding: 7px 15px;
  border: 1px solid rgb(186 166 96 / .45);
  border-radius: 4px 4px 14px 4px;
  background: rgb(186 166 96 / .07);
  font-size: 13.5px;
  font-weight: 500;
  letter-spacing: .04em;
  /* Same hue as --gold, darkened only as far as it takes to clear 4.5:1 on
     white — the value css/article.css already uses for on-white metadata. */
  color: #847132;
}
.abintro__dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 0 5px rgb(187 167 96 / .22);
}

.abintro__title {
  margin: 0 0 22px;
  max-width: min(100%, 620px);
  font-size: clamp(23px, 2.2vw, 32px);
  font-weight: 900;
  line-height: 1.42;
  color: var(--purple);
  text-wrap: balance;
}

.abintro__body p {
  margin: 0 0 20px;
  font-size: 16.6px;
  font-weight: 300;
  line-height: 1.95;
  color: var(--grey-600);
}
/* The opening paragraph is set one step up and in the brand purple: an
   account this long needs a way in, and a lead that looks exactly like the
   paragraph after it gives the eye nowhere to start. The rule beside it is the
   identity's own, turned vertical — the same device the photograph's caption
   below uses, which is what ties the two columns together. */
.abintro__body > p:first-of-type {
  margin-bottom: 24px;
  padding-inline-start: 20px;
  border-inline-start: 2px solid rgb(186 166 96 / .55);
  font-size: 17.6px;
  font-weight: 400;
  line-height: 1.9;
  color: var(--purple);
}

/* -- the three figures ----------------------------------------------------
   These were three numbers in a row divided by hairlines — correct, and
   completely inert next to the photograph beside them. They are the only part
   of this account that can be taken in at a glance, so they are given a
   surface of their own: one tinted plate, the figures set into it as three
   panels, each with the identity's broken corner and a gold rule under the
   number. It reads as a specification block rather than as a caption. */
.abstats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  margin: 38px 0 0;
  padding: 0;
  border: 0;
}

.abstats__item {
  position: relative;
  overflow: hidden;
  padding: 20px 18px 18px;
  border: 1px solid rgb(68 47 114 / .09);
  border-radius: 8px 8px 8px 24px;
  background: linear-gradient(168deg, #fbfaFd 0%, #fff 60%);
  transition: transform .35s var(--ease),
              border-color .35s var(--ease),
              box-shadow .35s var(--ease);
}
/* The gold cap on the top edge — the same mark the home page's figures carry,
   so the two sets of numbers read as the same component in two grounds. */
.abstats__item::before {
  content: "";
  position: absolute;
  top: 0;
  inset-inline-start: 0;
  width: 40px;
  height: 2px;
  background: var(--gold);
  transition: width .4s var(--ease);
}
.abstats__item:hover {
  transform: translateY(-3px);
  border-color: rgb(186 166 96 / .5);
  box-shadow: 0 18px 34px -26px rgb(17 7 53 / .34);
}
.abstats__item:hover::before { width: 84px; }

.abstats dt {
  margin-bottom: 12px;
  font-size: 13px;
  font-weight: 400;
  letter-spacing: .01em;
  color: var(--grey-600);
}
.abstats dd {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin: 0;
}
.abstats dd b {
  font-size: clamp(28px, 2.6vw, 38px);
  font-weight: 900;
  line-height: 1;
  color: var(--purple);
  font-variant-numeric: tabular-nums;
}
.abstats dd span {
  font-size: 13px;
  font-weight: 400;
  color: var(--grey-600);
}

/* --------------------------------------------------------------------------
   3. Certificates, on an arc
   --------------------------------------------------------------------------
   The whole section is driven by two numbers set here and read by both the
   rail and the cards, so they can never disagree:

     --arc-r     the radius of the circle the cards ride
     --arc-step  the angle between two neighbouring cards

   The hub — the circle's centre — sits far below the section. That is the
   trick: at this radius only the crown of the circle crosses the frame, so
   the line reads as an arc drawn across the page rather than as a ring that
   happens to be cropped.
   -------------------------------------------------------------------------- */

.arc {
  /* A much larger circle than before. The chord the six cards cover is
     2r·sin(2.5·step) — at 780px that was ~950px, which left the arc floating in
     the middle of a wide screen. At 1460px it measures ~1660px, so the crown
     runs the full width of the viewport and only its flattest part shows. */
  /* --arc-r and --arc-hub are inherited from .abfield — see there for why. */
  --arc-step: 15deg;
  position: relative;
  /* The plate above provides the ground; this section only spaces itself.
     `overflow: hidden` stays — it is what crops the rings to their crown. */
  /* The foot is over-padded so the white section below can reach up into it
     and dissolve the purple there. It has to stay larger than that overlap
     MINUS the crown offset — that difference is where the first pixel of white
     actually appears, and on a 1920 screen it lands 155px above this edge. At
     280px the gold readout keeps ~125px of untouched purple beneath it, which
     is what stopped it being washed out from below. */
  padding-block: 92px 194px;
  overflow: hidden;
}

/* The head is a heading and nothing else now — the sentence that used to sit
   under it is gone. Its own bottom margin replaces what that paragraph was
   spacing, so the stage does not ride up against the title. */
.arc__head {
  position: relative;
  z-index: 2;
  margin-bottom: 8px;
}


.arc__stage {
  position: relative;
  z-index: 1;
  height: clamp(360px, 34vw, 430px);
  margin-top: 44px;
  /* The rail and the cards are both positioned from this box's bottom centre,
     which is where the hub is measured from. */
}

/* -- the rail ------------------------------------------------------------- */
/* ONE arc, not three. There used to be a gold ring, a white one 14px inside it
   and a dotted one further in again — the pattern's own habit of drawing two
   lines a hair apart, borrowed at the wrong scale. Across a 1460px radius those
   three strokes never read as a considered triple; they read as a curve that
   had been drawn three times slightly wrong, which is exactly the "خط‌های زیر
   سکشن" complaint. One clean stroke, brighter than any of the three were, is
   the whole rail now.

   A border on a circle rather than an SVG: no viewBox to distort when the
   section changes proportion, and the stroke stays exactly 1px at any zoom.
   Only `border-top` is drawn, so nothing is painted where nothing shows. */
.arc__rail {
  position: absolute;
  inset-inline-start: 50%;
  bottom: calc(var(--arc-hub) * -1);
  width: 0;
  height: 0;
  pointer-events: none;
}

.arc__ring {
  position: absolute;
  inset-inline-start: 50%;
  bottom: 0;
  width: calc(var(--arc-r) * 2);
  height: calc(var(--arc-r) * 2);
  border-radius: 50%;
  border: 1px solid transparent;
  border-top-color: rgb(187 167 96 / .7);
  translate: 50% 50%;
}

/* -- the cards ------------------------------------------------------------ */
.arc__track {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Each card is placed by rotating around the hub, riding out to the radius,
   then rotating back so the card itself stays upright-ish. `--i` is its
   distance from the one being read, set by js/about.js. */
.cert {
  --i: 0;
  --a: calc(var(--i) * var(--arc-step));
  position: absolute;
  inset-inline-start: 50%;
  bottom: calc(var(--arc-hub) * -1);
  /* Neighbouring cards are 2r·sin(step/2) apart — 381px here. At the old
     264px they floated with 117px of nothing between them; at 340px the set
     reads as one continuous rank with a 41px gutter. */
  width: clamp(250px, 24vw, 340px);
  margin-inline-start: calc(clamp(250px, 24vw, 340px) / -2);
  transform-origin: 50% 100%;
  /* rotate out along the arc, ride to the rim, then take back most of the
     rotation — a little tilt is left in, which is what makes the row read as
     following the curve instead of standing on it. */
  transform:
    rotate(var(--a))
    translateY(calc((var(--arc-r) - 6px) * -1))
    rotate(calc(var(--a) * -.72));
  transition: transform .55s var(--ease), opacity .45s var(--ease), filter .45s var(--ease);
}

/* Depth from the geometry, not from a shadow: the further round the arc, the
   smaller, paler and greyer. Anything past the third stop is out of the frame
   anyway and stops taking pointer events. */
.cert[data-far="1"] { opacity: .72; }
.cert[data-far="2"] { opacity: .4; }
.cert[data-far="3"] { opacity: .14; pointer-events: none; }
.cert[data-far="4"] { opacity: 0; pointer-events: none; }

.cert__card {
  position: relative;
  overflow: hidden;
  border: 1px solid rgb(255 255 255 / .16);
  /* The identity's broken corner. */
  border-radius: 14px 14px 44px 14px;
  background: linear-gradient(180deg, rgb(255 255 255 / .1) 0%, rgb(255 255 255 / .05) 100%);
  -webkit-backdrop-filter: blur(14px) saturate(1.3);
          backdrop-filter: blur(14px) saturate(1.3);
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / .22),
    0 30px 60px -30px rgb(11 5 32 / .8);
  transition: border-color .4s var(--ease), transform .4s var(--ease);
}

/* The card at the apex is the one being read, so it is the only one the gold
   edge belongs to. */
.cert[data-far="0"] .cert__card {
  border-color: rgb(187 167 96 / .8);
  /* Four layers, and the third is the new one: a wide, very soft gold bloom
     under the card. The apex was marked only by an outline, which reads as a
     selected item in a list; lit from underneath it reads as the one being
     held up. Kept under 20% so it never becomes a halo. */
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / .3),
    0 0 0 1px rgb(187 167 96 / .25),
    0 18px 60px -12px rgb(187 167 96 / .18),
    0 36px 70px -28px rgb(11 5 32 / .85);
}

/* The pattern's square node, sitting on the rail where the card meets it. */
.cert__mark {
  position: absolute;
  inset-block-start: -1px;
  inset-inline-end: 18px;
  z-index: 2;
  width: 15px;
  height: 15px;
  border: 1px solid rgb(187 167 96 / .7);
  border-radius: 3px 3px 8px 3px;
  background: var(--purple-flood);
  translate: 0 -50%;
  rotate: 45deg;
}
.cert[data-far="0"] .cert__mark { background: var(--gold); border-color: var(--gold); }

.cert__media {
  position: relative;
  display: block;
  overflow: hidden;
  aspect-ratio: 4 / 3.1;
  background: var(--purple);
}

/* A scrim at the foot of every photograph. Nothing is written on it — it is
   there because a photograph that stops at a hard edge floats, and one that
   darkens into its own corner sits. It also gives the gold rim of the apex
   card something to read against whatever the picture happens to be. */
.cert__media::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 46%;
  background: linear-gradient(to top, rgb(17 7 53 / .62), rgb(17 7 53 / 0));
  pointer-events: none;
}

/* A hairline of the identity's gold, set in from the edge — the frame a
   certificate is mounted in, at one pixel. It is drawn only on the card being
   read; on the others it fades with them. */
.cert__card::after {
  content: "";
  position: absolute;
  inset: 7px;
  z-index: 2;
  border: 1px solid rgb(187 167 96 / 0);
  border-radius: 8px 8px 36px 8px;
  pointer-events: none;
  transition: border-color .45s var(--ease), inset .45s var(--ease);
}
.cert[data-far="0"] .cert__card::after { border-color: rgb(187 167 96 / .55); }
.cert__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 40%;
  /* Resting in the identity's gold duotone, the same treatment .gallery__media
     uses — so a wall of certificate photographs reads as one field. The card
     at the apex comes back to colour. */
  filter: grayscale(1) sepia(1) saturate(1.15) brightness(.66);
  transition: filter .5s var(--ease), transform .6s var(--ease);
}
.cert[data-far="0"] .cert__media img { filter: none; }
.cert__card:hover .cert__media img { transform: scale(1.05); }
/* Only the card being read lifts. The others are not targets. */
.cert[data-far="0"] .cert__card:hover { transform: translateY(-6px); }

/* The card is the photograph. Its wording is not deleted — it stays in the
   document for assistive technology and it is what the readout below the arc
   is filled from — it simply is not drawn on the card. */
.u-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.cert__code {
  margin: 0 0 6px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .06em;
  color: rgb(17 7 53 / .72);
}
.cert__name {
  margin: 0 0 8px;
  font-size: 15.5px;
  font-weight: 700;
  line-height: 1.6;
  color: #fff;
}
.cert__note {
  margin: 0;
  font-size: 12px;
  font-weight: 300;
  color: rgba(255, 255, 255, .62);
}

/* -- controls ------------------------------------------------------------- */
/* Below the stage, not inside it. The cards two stops out land 8 to 35px above
   the stage floor depending on the breakpoint — right where a controls row at
   `bottom: 0` would sit. They keep their own band inside the section's foot
   padding instead, so nothing ever overlaps them.

   They stay a child of `.arc__stage` in the markup because the arrow-key
   handler is bound to the stage; moving them out would put the buttons outside
   the element that listens for the keys operating them. */
.arc__controls {
  position: absolute;
  inset-inline: 0;
  bottom: -100px;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 18px;
}

/* The two controls are the readout's own ends. They carry the gold as an
   outline where the card carries it as a fill, so the three together read as
   one control and not as a card with two buttons parked beside it. On hover
   the outline becomes the fill and the chevron inverts — the same swap the
   card already makes, run the other way. */
.arc__nav {
  display: grid;
  place-items: center;
  width: 50px;
  height: 50px;
  padding: 0;
  color: var(--gold);
  background: rgb(28 15 68 / .5);
  border: 1.5px solid rgb(187 167 96 / .55);
  border-radius: 50%;
  cursor: pointer;
  -webkit-backdrop-filter: blur(10px) saturate(1.18);
          backdrop-filter: blur(10px) saturate(1.18);
  transition: background .25s var(--ease), color .25s var(--ease),
              transform .25s var(--ease), border-color .25s var(--ease),
              box-shadow .25s var(--ease);
}
.arc__nav:hover {
  color: var(--purple-deep);
  background: var(--gold);
  border-color: var(--gold);
  box-shadow: 0 12px 26px -14px rgb(187 167 96 / .6);
}
.arc__nav:active { transform: scale(.94); }
.arc__nav:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.arc__nav svg {
  width: 10px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Physical insets: these mean "towards the start of the set" and "towards the
   end", and the chevrons are drawn pointing at fixed screen edges. */
.arc__nav--prev:hover { transform: translateX(3px); }
.arc__nav--next:hover { transform: translateX(-3px); }

/* The readout is the card's caption, moved out from under the photograph so
   the photograph can fill it. One line per level: standard, then what it
   certifies, then its dates. */
/* The readout is the certificate's caption and it sits directly on the
   patterned field, so it takes the same surface the timeline's stops do —
   brand purple brought forward, closed by a gold light along the top edge, the
   identity's corner broken on one side. */
.arc__readout {
  min-width: min(100%, 300px);
  max-width: min(100%, 470px);
  margin: 0;
  padding: 13px 28px 15px;
  text-align: center;
  border: 1px solid color-mix(in srgb, var(--gold) 70%, #fff);
  border-radius: 6px 6px 30px 6px;
  /* Gold, the way the gallery's caption bar is gold: the brand colour carrying
     dark type, not a tint behind light type. It is the only solid gold surface
     on the page, which is exactly why it works here — it marks the one
     certificate being read out of six. Lit from the top corner so it reads as
     metal rather than as a flat swatch. */
  background: linear-gradient(163deg,
    color-mix(in srgb, var(--gold) 82%, #fff) 0%,
    var(--gold) 44%,
    color-mix(in srgb, var(--gold) 90%, var(--purple-deep)) 100%);
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / .5),
    0 20px 44px -26px rgb(11 5 32 / .85);
}

/* Where the reader is in the set — it answers "how much more is there" without
   competing with the certificate itself. */
.arc__readout__count {
  display: block;
  margin-bottom: 7px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .12em;
  color: rgb(17 7 53 / .55);
}
.arc__readout__code {
  display: block;
  margin-bottom: 5px;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .06em;
  color: rgb(17 7 53 / .74);
}
.arc__readout__name {
  display: block;
  margin-bottom: 5px;
  font-size: 17.5px;
  font-weight: 900;
  line-height: 1.5;
  color: var(--purple-deep);
}
.arc__readout__note {
  display: block;
  font-size: 12.8px;
  font-weight: 500;
  color: rgb(17 7 53 / .68);
}

/* --------------------------------------------------------------------------
   4. Timeline
   --------------------------------------------------------------------------
   Vertical, directly under the arc, on the same purple.

   It was horizontal — five spans across the column — and that was wrong twice
   over. It read as a chart rather than as a path, and at any width narrower
   than the artboard each stop got about 130px, which is less than the words in
   it. Vertical it can be read the way a history is read: top to bottom, one
   entry at a time, with room for a sentence.

   The rail keeps the identity's habit of turning. It does not simply drop: it
   opens with a rounded elbow under the section head, each stop reaches it with
   a short spur, and it closes with an elbow at the foot. Every part is a
   border on a box, so it scales with the layout and stays a hairline at any
   zoom.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   THE ROUTE
   One purple field, read across. See about.html for why it is horizontal and
   why it no longer hands the page over to a white ground.
   -------------------------------------------------------------------------- */

.tline {
  position: relative;
  z-index: 1;
  /* --rail is the one measurement everything else is taken from: the height at
     which the gold line crosses a stop. Card, node and year are all placed
     against it, so the whole route moves by editing one number. */
  --rail: 300px;

  /* NO GROUND OF ITS OWN. The crossing from purple to white is a property of
     the PAGE, not of this section, and it is drawn once on .abfield — see
     "the crossing" there. Every earlier attempt painted it here instead, which
     is why it kept covering the certificates above with a slab that did not
     match the field's own pattern. A section that owns its background cannot
     dissolve into the one above it; it can only sit on top of it. */
  padding-block: 60px 104px;
}

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

/* -- the head ------------------------------------------------------------- */
.tline__head {
  width: min(var(--container), calc(100% - 80px));
  margin: 0 auto 58px;
  text-align: center;
}

/* The brand's line between two rules — the same "short stroke flanking a mark"
   the section heads carry, turned horizontal. Darkened from the token: gold
   measures 2.41:1 on white, and #6f5d22 is the same hue at 6.43:1. */
.tline__eyebrow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin: 0 0 20px;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .14em;
  color: #6f5d22;
}
.tline__eyebrow::before,
.tline__eyebrow::after {
  content: "";
  width: 40px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(to left, rgb(186 166 96 / 0), var(--gold));
}
.tline__eyebrow::after { scale: -1 1; }

.tline__title {
  margin: 0;
  font-size: clamp(27px, 2.7vw, 40px);
  font-weight: 900;
  line-height: 1.35;
  color: var(--purple);
  text-wrap: balance;
}
.tline__lead {
  width: min(560px, 100%);
  margin: 16px auto 0;
  font-size: 16px;
  font-weight: 300;
  line-height: 1.85;
  color: var(--grey-600);
}

/* -- the route ------------------------------------------------------------
   A hairline down the reading edge, fading in above the first node and out
   below the last, so it reads as a stretch of road rather than a rule with two
   hard ends. --rail is the only measurement; everything else derives from it. */
.tline__track {
  --rail: 21px;
  --node: 15px;
  --gutter: 62px;
  position: relative;
  z-index: 1;
  width: min(var(--container), calc(100% - 80px));
  margin: 0 auto;
  padding: 0;
  list-style: none;
}
.tline__track::before {
  content: "";
  position: absolute;
  inset-block: 10px 0;
  inset-inline-start: calc(var(--rail) - 1px);
  width: 2px;
  background: linear-gradient(to bottom,
    rgb(186 166 96 / 0)   0%,
    rgb(186 166 96 / .8)  6%,
    rgb(186 166 96 / .8) 86%,
    rgb(186 166 96 / 0)  100%);
}

.tstop {
  position: relative;
  padding-inline-start: var(--gutter);
  padding-block-end: 30px;
}
.tstop--last { padding-block-end: 0; }

/* A ring at rest, a filled disc on hover — the same outline-becomes-fill swap
   the certificate controls use. Its centre is opaque white, not transparent:
   the rail runs behind it and a hollow ring would show a line straight through
   the middle. The halo doubles as the spur's end stop. */
.tstop__node {
  position: absolute;
  top: 34px;
  inset-inline-start: calc(var(--rail) - var(--node) / 2);
  width: var(--node);
  height: var(--node);
  border: 2px solid var(--gold);
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 6px #fff;
  transition: background .35s var(--ease), box-shadow .35s var(--ease), transform .35s var(--ease);
}
/* The spur from the node to the card — the join that makes the card belong to
   the stop rather than merely sit near it. */
.tstop::before {
  content: "";
  position: absolute;
  top: calc(34px + var(--node) / 2);
  inset-inline-start: calc(var(--rail) + var(--node) / 2 + 6px);
  width: calc(var(--gutter) - var(--rail) - var(--node) / 2 - 6px);
  height: 1px;
  background: linear-gradient(to left, rgb(186 166 96 / .8), rgb(186 166 96 / .15));
}

/* -- the card -------------------------------------------------------------
   One surface, not a panel plus a picture: a single border, one radius, one
   ground, and the photograph bled to its inside edge. On white the card is
   white too — a grey card on a white page reads as disabled — so what lifts it
   off the field is a border and a shadow rather than a change of fill. */
.tstop__body {
  position: relative;
  display: flex;
  align-items: stretch;
  overflow: hidden;
  width: 100%;
  height: var(--card-h, 236px);
  border: 1px solid rgb(68 47 114 / .09);
  border-radius: 10px 10px 10px 40px;
  background: #fff;
  /* Two shadows rather than one: a tight contact shadow that keeps the card's
     own edge crisp against the white field, and a wide, very soft one that
     gives it height. A single shadow has to choose between the two and ends up
     looking like grey fog under a white box. */
  box-shadow:
    0 1px 2px rgb(68 47 114 / .06),
    0 22px 48px -30px rgb(17 7 53 / .38);
  transition: border-color .4s var(--ease),
              transform .4s var(--ease),
              box-shadow .4s var(--ease);
}

/* The tick: a short gold stroke at the top of the edge facing the rail — the
   card's end of the join, not a border, hence 34px and not full height. */
.tstop__body::before {
  content: "";
  position: absolute;
  z-index: 3;
  top: -1px;
  inset-inline-start: -1px;
  width: 2px;
  height: 34px;
  border-radius: 0 0 2px 2px;
  background: linear-gradient(to bottom, var(--gold), rgb(186 166 96 / 0));
}

.tstop__thumb {
  position: relative;
  flex: none;
  display: block;
  width: clamp(210px, 23vw, 320px);
  overflow: hidden;
  background: var(--purple);
}
/* The hairline where the picture meets the words — the only division the card
   needs, and gold because every other join on this page is. */
.tstop__thumb::after {
  content: "";
  position: absolute;
  z-index: 2;
  inset-block: 0;
  inset-inline-end: 0;
  width: 1px;
  background: linear-gradient(to bottom,
    rgb(186 166 96 / .2), rgb(186 166 96 / .65), rgb(186 166 96 / .2));
}
/* A scrim over the top of the photograph. The chip is placed there and these
   are documentary pictures — whatever falls under it changes from stop to
   stop, so the label needs a ground it can rely on. */
.tstop__thumb::before {
  content: "";
  position: absolute;
  z-index: 1;
  inset: 0 0 auto;
  height: 96px;
  background: linear-gradient(to bottom, rgb(17 7 53 / .45), rgb(17 7 53 / 0));
  pointer-events: none;
}

.tstop__thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 45%;
  /* The gold duotone .gallery__media and .cert__media already use, so a column
     of photographs down the route reads as one field rather than five
     unrelated pictures. Colour returns on hover. */
  filter: grayscale(1) sepia(1) saturate(1.2) brightness(.82);
  transition: filter .5s var(--ease), transform .6s var(--ease);
}

/* The one-word gloss set on the photograph rather than out in the margin:
   five bare years give the eye nothing to hold between them, and on the image
   the label costs the card no vertical room at all. */
.tstop__tag {
  position: absolute;
  z-index: 2;
  inset-block-start: 14px;
  inset-inline-start: 14px;
  padding: 6px 13px;
  border-radius: 4px 4px 12px 4px;
  background: rgb(17 7 53 / .88);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .08em;
  color: #fff;
  transition: background .35s var(--ease), color .35s var(--ease);
}

.tstop__panel {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 26px 40px 28px;
  text-align: start;
}

/* Purple, not gold: gold measures 2.41:1 on white, so on this ground the
   identity's colour is carried by the rail, the node, the tick and the rule —
   and the type takes the purple. */
.tstop__year {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0 0 12px;
  font-size: clamp(26px, 2.2vw, 34px);
  font-weight: 900;
  line-height: 1;
  color: var(--purple);
  font-variant-numeric: tabular-nums;
}
/* The rule runs out from the year to the card's far edge, which is what gives
   the panel a horizontal structure instead of three stacked blocks of text. */
.tstop__year::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: linear-gradient(to left, rgb(186 166 96 / .75), rgb(186 166 96 / 0));
  opacity: .75;
  transition: opacity .4s var(--ease);
}

.tstop__title {
  margin: 0 0 10px;
  font-size: 21px;
  font-weight: 700;
  line-height: 1.55;
  color: var(--purple);
  transition: color .3s var(--ease);
}
/* Deepens rather than changes hue: the card is already lifting and its rule is
   already growing, so the title only has to join in, not compete. 14.9:1. */
.tstop:hover .tstop__title,
.tstop:focus-within .tstop__title { color: var(--purple-deep); }

.tstop__text {
  margin: 0;
  /* The guarantee the fixed height holds: three lines, then an ellipsis. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
  font-size: 16px;
  font-weight: 300;
  line-height: 1.9;
  color: var(--grey-600);
}

/* -- hover ---------------------------------------------------------------- */
.tstop:hover .tstop__node,
.tstop:focus-within .tstop__node {
  background: var(--gold);
  transform: scale(1.15);
  box-shadow: 0 0 0 6px #fff, 0 0 18px rgb(186 166 96 / .45);
}
.tstop:hover .tstop__body,
.tstop:focus-within .tstop__body {
  transform: translateY(-5px);
  border-color: rgb(186 166 96 / .5);
  box-shadow:
    0 1px 2px rgb(68 47 114 / .06),
    0 34px 62px -30px rgb(17 7 53 / .42);
}
.tstop:hover .tstop__year::after,
.tstop:focus-within .tstop__year::after { opacity: 1; }
.tstop:hover .tstop__tag,
.tstop:focus-within .tstop__tag { background: var(--gold); color: var(--purple-deep); }
.tstop:hover .tstop__thumb img,
.tstop:focus-within .tstop__thumb img { filter: none; transform: scale(1.05); }

/* The reveal's resting state. `.is-observed` is set by js/about.js, so the
   stops are only ever hidden when something is going to show them again. */
.tline__track.is-observed > .tstop {
  opacity: 0;
  transform: translateY(18px);
}
.tline__track.is-observed > .tstop.is-in {
  opacity: 1;
  transform: none;
  transition:
    opacity .5s var(--ease) var(--stop-delay, 0ms),
    transform .6s var(--ease) var(--stop-delay, 0ms);
}

/* --------------------------------------------------------------------------
   4b. The shared plate
   The certificates and the timeline are one field. The plate's own gradient
   runs to --purple-deep at its foot, which is what hands the page over to the
   footer below without a seam.
   -------------------------------------------------------------------------- */

.abplate { position: relative; }
/* The arc's geometry lives here, one level up, because two different sections
   are drawn from it: .arc rides its cards on this circle, and .tline dissolves
   the purple along the very same one. Declared once, so they cannot drift. */
.abfield {
  position: relative;
  --arc-r: 1460px;
  --arc-hub: 1300px;
  /* Where the ground starts turning, measured from the top of the field. 250px
     puts it high behind the certificate photographs — which is the point: at
     that height the wash is well under 1% and nothing up there is touched, and
     there is no horizon anywhere because the change begins long before the eye
     is looking for it. --crown lifts with it, so the curve rides at the same
     height in the run rather than being left near its foot. */
  --cross-top: 250px;
  --cross: 1250px;                     /* the length of the whole dissolve */
  /* How far the purple weave carries past the crossing, and it is a separate
     number from --cross on purpose: the ground has to finish, the texture only
     has to accompany it and then leave.

     1.5 × --cross is measured, not chosen. From the top of the field the
     certificates run about 990px, the route's own head about 230px more, and
     the first card is 236px tall with a 30px gap under it — so "تولد ساندیس",
     the second stop, begins roughly 1230px below where the crossing starts.
     Against a 1875px run that is 66%, which is where the mask below holds full
     strength until, before thinning away over the rest. */
  --weave: calc(var(--cross) * 1.5);
  --crown: 190px;                      /* the arc's crown inside that run */
}
.abfield > .arc,
.abfield > .tline,
.abplate > .abfield,
.abplate > .abfoot { position: relative; z-index: 1; }

/* The field itself is flat corporate purple. All of the darkening — and the
   corner drawing, and therefore the footer's whole appearance — is left to the
   nested `.plate` below, unchanged from every other page. */
.abplate { background: var(--purple-flood); }

/* The footer keeps the plate's darkening — that gradient IS the footer's
   appearance, and it is untouched — but not the plate's pattern image. That
   image is one 2477px-wide drawing pinned to the top corner: it cannot repeat,
   so on a wide screen it runs out and leaves the ground bare, and where it met
   the tiled field above, two different drawings collided at the seam. Both
   faults were the same fault. The gradient now opens fully transparent, so the
   single tiled ground above simply continues down through the gallery and only
   disappears where the page is meant to go dark. One pattern, complete at any
   width, with no join to get wrong. */
/* -- THE CROSSING ---------------------------------------------------------
   The page turns from purple to white HERE, on the field itself, under
   everything. That is the whole correction: for several passes this was
   painted on .tline, a section that begins below the certificates — so it
   could only ever lie on top of them as a slab, with its own pattern and its
   own edge, instead of the field's ground changing underneath them.

   Two layers make the shape, and they are two because a curve alone cannot do
   it. At a 1460px radius a curved colour boundary is a 300px bulge in the
   middle of the screen with flat colour either side, which the eye reads as a
   lamp shining on the page.
     · THE RAMP crosses the whole width evenly, so no column is ever flat
       purple beside a lit one. Twelve stops, easing in very slowly so the top
       of the run is imperceptible behind the cards.
     · THE CURVE, capped at 55%, runs ahead of the ramp in the middle only. It
       bends the crossing by the arc's own amount — measured, the half-way line
       sits ~200px higher at the centre than at the screen edge — without ever
       becoming a lobe.
   Both are white over the same purple, so the alphas compose: 1−(1−a₁)(1−a₂).

   Below the run it is solid white all the way to the footer, which is what
   makes this the page's ground rather than a band. z-index 0 keeps it under
   .arc and .tline, both of which are z-index 1, so the certificate cards and
   the gold readout sit on top of it untouched. */
.abfield::after {
  content: "";
  position: absolute;
  z-index: 0;
  inset: var(--cross-top) 0 0;
  background:
    radial-gradient(circle var(--arc-r) at 50% calc(var(--arc-r) + var(--crown)),
      rgb(255 255 255 / .42)  88%,
      rgb(255 255 255 / .36)  91%,
      rgb(255 255 255 / .26)  94%,
      rgb(255 255 255 / .15)  97%,
      rgb(255 255 255 / .06)  99%,
      rgb(255 255 255 / 0)   100%)
      top / 100% var(--cross) no-repeat,
    /* Sixteen stops on a slow S: almost nothing for the first fifth, the
       steepest part kept to the middle, and a long tail that closes on white
       rather than arriving at it. The alpha never climbs more than about six
       points between neighbouring stops, which is what stops any one level
       from becoming a locatable band. */
    linear-gradient(180deg,
      rgb(255 255 255 / 0)     0,
      rgb(255 255 255 / .008)  7%,
      rgb(255 255 255 / .02)  13%,
      rgb(255 255 255 / .04)  19%,
      rgb(255 255 255 / .07)  25%,
      rgb(255 255 255 / .11)  31%,
      rgb(255 255 255 / .16)  37%,
      rgb(255 255 255 / .23)  43%,
      rgb(255 255 255 / .31)  49%,
      rgb(255 255 255 / .40)  55%,
      rgb(255 255 255 / .50)  61%,
      rgb(255 255 255 / .60)  67%,
      rgb(255 255 255 / .70)  74%,
      rgb(255 255 255 / .81)  81%,
      rgb(255 255 255 / .91)  89%,
      #fff                   100%)
      top / 100% var(--cross) no-repeat,
    linear-gradient(180deg, #fff 0%, #fff 100%)
      bottom / 100% calc(100% - var(--cross) + 1px) no-repeat;
  pointer-events: none;
}

/* -- the weave, on the white half ----------------------------------------
   The field's own sheet again, recoloured to purple — the file is drawn in
   white, which is invisible on white — and given a DIFFERENT curve from the
   ground's on purpose. The ground has to cross completely; the pattern only
   has to accompany it and then leave, or five cards of body copy end up
   competing with a texture. It is nothing at the top (where .abfield::before
   is still drawing the white weave, and two copies would double), comes in as
   the white arrives, peaks just past the crossing, and is gone by 62% of the
   run — which is roughly where the first card lands. */
.abfield__weave {
  position: absolute;
  z-index: 0;
  inset: var(--cross-top) 0 0;
  background: url(../assets/pattern-gallery.png) left -419px top -101px / 2477px auto repeat;
  /* Fainter than the purple half's own weave (.2): on white the same ink reads
     considerably stronger than it does on a saturated ground, so matching the
     numbers would not match the effect. */
  opacity: .1;
  filter: invert(1) sepia(1) saturate(2.4) hue-rotate(228deg) brightness(.55);
  /* Percentages of --weave, not of --cross: it comes in with the white, holds
     at full strength all the way down to the second stop (66% — see --weave
     for the arithmetic), and only then thins away, over the remaining third of
     the run, so it leaves gradually rather than stopping. */
  -webkit-mask-image: linear-gradient(180deg,
    rgb(0 0 0 / 0)   0%,
    rgb(0 0 0 / .18) 6%,
    rgb(0 0 0 / .6)  14%,
    #000             22%,
    #000             66%,
    rgb(0 0 0 / .72) 76%,
    rgb(0 0 0 / .42) 85%,
    rgb(0 0 0 / .16) 93%,
    rgb(0 0 0 / 0)  100%);
          mask-image: linear-gradient(180deg,
    rgb(0 0 0 / 0)   0%,
    rgb(0 0 0 / .18) 6%,
    rgb(0 0 0 / .6)  14%,
    #000             22%,
    #000             66%,
    rgb(0 0 0 / .72) 76%,
    rgb(0 0 0 / .42) 85%,
    rgb(0 0 0 / .16) 93%,
    rgb(0 0 0 / 0)  100%);
  -webkit-mask-size: 100% var(--weave);
          mask-size: 100% var(--weave);
  -webkit-mask-position: top;
          mask-position: top;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  pointer-events: none;
}

/* Nothing of the footer is overridden — it is `.plate` with its own gradient
   and its own corner drawing, exactly as index, news, articles and contact use
   it. The only thing this page adds is the hand-over above it. */
.abfoot {
  z-index: 1;
}

/* The pattern. `.plate__pattern` is a single large drawing pinned to the top
   corner — it dresses a section-height plate, but over a field this tall it
   covers the first third and leaves the rest bare, which is what made the
   ground look assembled rather than continuous. This field uses the seamless
   tile instead, at one scale, from the first pixel to the last: no seam, no
   second pass at a different size, nothing to fall out of register. */
.abfield::before {
  content: "";
  position: absolute;
  inset: 0;
  /* The footer plate's pattern, continued upward — literally. Same file family,
     same 2477px, same `left -419px`, and anchored to this field's FOOT rather
     than its head: `bottom 101px` puts the last copy's lower edge exactly where
     the plate's own image begins (it sits at `top: -101px` inside the plate).
     The drawing therefore carries on across the join instead of restarting, so
     the two grounds share one grid rather than merely one scale.

     And it is the footer's own file, not a stand-in. pattern-tile.png is drawn
     in white only; the plate's sheet carries the identity's gold in its four
     dots, which is the difference that was still showing. The sheet was assumed
     not to tile — it does: measured, its first and last columns are identical
     to the pixel, and so are its first and last rows, against an 8.75 average
     difference between neighbouring columns inside it. So it can simply repeat,
     and the two grounds are now the same drawing, the same colours, the same
     grid, from one file. */
  background: url(../assets/pattern-gallery.png) left -419px bottom 101px / 2477px auto repeat;
  opacity: .2;
  /* White ink disappears of its own accord as the ground whitens, but not fast
     enough — it lingers as a grey haze through the middle of the crossing. It
     is faded out deliberately instead, on its own curve: full strength until
     the crossing begins, gone a little before the ground finishes. */
  -webkit-mask-image: linear-gradient(180deg,
    #000 0, #000 calc(var(--cross-top) + var(--cross) * .12),
    transparent calc(var(--cross-top) + var(--cross) * .58));
          mask-image: linear-gradient(180deg,
    #000 0, #000 calc(var(--cross-top) + var(--cross) * .12),
    transparent calc(var(--cross-top) + var(--cross) * .58));
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   5. Responsive — the project's existing breakpoints only.
   -------------------------------------------------------------------------- */

@media (max-width: 1500px) {
    /* On .abfield, not .arc: the timeline's fade is drawn from the same circle
     and has to shrink with it. */
  .abfield { --arc-r: 1180px; --arc-hub: 1045px; }
  .abintro__grid { gap: 46px; }
}

@media (max-width: 1200px) {
  .abhead { padding-block: var(--hero-top) 148px; }
  .abintro { padding-block: 0 76px; }
  .abintro__media { margin-top: -104px; }
  .abintro__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 36px; }
  .abintro__body { padding-top: 12px; }
  .abintro__body p { font-size: 15.6px; }

  .abfield { --arc-r: 900px; --arc-hub: 790px; }
  .arc { --arc-step: 16deg; }
  .arc { padding-block: 74px 162px; }
  /* The overlap follows the arc's own bottom padding at each width, and the
     top padding is that overlap plus the section's own opening space. */
  /* The crossing shrinks with the arc it is bent by; the section's own top
     padding shrinks with it so the head still lands on settled white. */
  .abfield { --cross-top: 220px; --cross: 1100px; --crown: 160px; }
  .tline { padding-block: 50px 96px; }
  .tline__head { margin-bottom: 54px; }
  .tstop__body { --card-h: 216px; }
  .tstop__panel { padding: 22px 32px 24px; }
  .tstop__title { font-size: 20px; }
  .tstop__text { font-size: 15.4px; }
}

@media (max-width: 1024px) {
  /* Both layers are the same fixed 2477px sheet, tiled at one scale from the
     header band down through the certificates/timeline field. That scale was
     tuned for a full desktop width; unshrunk on a tablet it reads as a much
     coarser, larger-looking weave than the footer plate below it (which does
     scale, via .plate__pattern). Both position and size move together, by the
     same .62 factor, since they are the same coordinate system — moving one
     without the other would throw off the registration the header/field seam
     depends on. */
  .abhead::before { background-position: left -260px top -63px; background-size: 1536px auto; }
  .abfield::before { background-position: left -260px bottom 63px; background-size: 1536px auto; }

  /* One column: the photograph keeps its lap over the band and the account
     follows it, which is the order it would be read in anyway. */
  .abintro__grid { grid-template-columns: 1fr; gap: 30px; }
  .abintro__body { padding-top: 0; }

  .abfield { --arc-r: 660px; --arc-hub: 565px; }
  .arc { --arc-step: 19deg; }
  .arc__stage { height: clamp(340px, 44vw, 400px); }

  /* The route is the same shape at every width — that is the point of a single
     rail — so only the measurements move: the gutter closes up and the card
     loses its width cap now that it has the full column to itself. */
  /* The route keeps its shape — that is the point of a single rail — so only
     the measurements move: the gutter closes up and the photograph narrows. */
  .abfield { --cross-top: 180px; --cross: 880px; --crown: 120px; }
  .tline { padding-block: 40px 78px; }
  .tline__head { margin-bottom: 44px; }
  .tline__head,
  .tline__track { width: calc(100% - 60px); }
  .tline__track { --rail: 18px; --gutter: 52px; }
  .tstop { padding-block-end: 24px; }
  .tstop__body { --card-h: 190px; }
  .tstop__thumb { width: clamp(168px, 24vw, 230px); }
  .tstop__panel { padding: 20px 26px 22px; }
  .tstop__title { font-size: 18.5px; }
  .tstop__text { font-size: 14.8px; }
}

@media (max-width: 620px) {
  /* Same sheet again at .4, matching the footer plate's own phone-width
     scale so the header band, the certificates/timeline field, and the
     footer all read as one texture rather than three different densities. */
  .abhead::before { background-position: left -168px top -40px; background-size: 991px auto; }
  .abfield::before { background-position: left -168px bottom 40px; background-size: 991px auto; }

  .abhead { padding-block: var(--hero-top) 108px; }
  .abintro { padding-block: 0 54px; }
  .abintro__media { margin-top: -76px; }
  .abintro__frame { border-radius: 12px 12px 40px 12px; }
  .abintro__frame img { aspect-ratio: 16 / 11; }

  /* Three panels side by side under 620px give each about 100px, which is
     narrower than "تن در شبانه‌روز" alone. They stack; the panel keeps every
     other part of its treatment, only the column count changes. */
  .abstats { grid-template-columns: 1fr; gap: 10px; }
  .abstats__item { padding: 16px 16px 15px; border-radius: 8px 8px 8px 20px; }
  .abintro__kicker { font-size: 12.5px; padding: 6px 13px; }
  .abintro__media::before { top: -10px; inset-inline-end: -10px; width: 54px; height: 54px; }
  .abintro__body > p:first-of-type { font-size: 16px; padding-inline-start: 15px; }

  /* Neighbouring cards sit 2r·sin(step/2) apart, so the card can only be as
     wide as that spacing allows. Rather than shrink the card to fit a small
     circle, the circle is opened up: at 660px and 20° the spacing is 229px,
     which carries a 212px card with a 17px gutter — the certificate reads at
     a real size instead of a thumbnail. --arc-hub keeps its 105px offset from
     the radius, so the apex card sits exactly where it did in the stage. */
  .abfield { --arc-r: 660px; --arc-hub: 555px; }
  .arc { --arc-step: 20deg; }
  .arc { padding-block: 52px 122px; }
  .arc__controls { bottom: -96px; gap: 10px; }
  /* The cards are placed from the stage's BOTTOM edge (bottom: −hub, then
     ridden out to the radius), so the stage's height is dead space above them
     — nothing is drawn in it, the arc's crown is far below. On a desktop that
     space is what the arc needs to curve through; at a 660px radius across a
     phone the curve is only 77px deep and the rest of it was 100px of empty
     purple between the heading and the first card. Trimmed to what the crown
     actually uses. The cards do not move relative to each other, because they
     are all measured from the same edge. */
  .arc__stage { height: 276px; margin-top: 30px; }
  .arc__head { margin-bottom: 6px; }
  .cert { width: 212px; margin-inline-start: -106px; }
  .cert__card { border-radius: 10px 10px 30px 10px; }

  /* The readout sits between two buttons, so its width has to leave room for
     them or the row overflows the column: 2 x 46 + 2 x 10 of gap = 112px. It
     was capped at 100%, which on a 360px screen put the whole row 112px wider
     than the page. */
  .arc__readout {
    min-width: 0;
    max-width: calc(100% - 112px);
    padding: 11px 16px 12px;
  }
  .arc__readout__count { margin-bottom: 5px; font-size: 10.5px; }
  .arc__readout__code { font-size: 11.5px; }
  .arc__readout__name { font-size: 15px; }
  .arc__readout__note { font-size: 11.8px; }
  /* 44px minimum tap target. */
  .arc__nav { width: 46px; height: 46px; }

  /* Mobile only — desktop is untouched. --cross-top is measured from the top
     of the field, and on a phone the field's head is much shorter than on a
     desktop while the stage is not: 52px of padding, ~110px of heading, a 44px
     gap and then a 360px stage, so the certificate cards do not begin until
     about 210px down and run to roughly 570px. At 130px the crossing was
     starting ABOVE them — the one place it must not, because there is nothing
     up there for it to hide behind and it reads as a line across the section.
     340px puts its first, invisible percent behind the cards themselves, the
     same way the desktop value does. */
  .abfield { --cross-top: 276px; --cross: 620px; --crown: 90px; }
  .tline { padding-block: 30px 64px; }
  /* At 660px of radius across a 390px screen the crown is 13px of sagitta —
     a curve that flat is indistinguishable from a straight rule, and a stray
     hairline across the dissolve is worse than none. */
  /* The tile is not shrunk here the way .plate__pattern is: that one is a
     single placed crop that would overrun, whereas a repeating ground should
     simply show less of the same drawing on a smaller screen. */
  .tline__head { margin-bottom: 34px; }
  .tline__eyebrow { font-size: 13px; gap: 11px; margin-bottom: 15px; }
  .tline__eyebrow::before,
  .tline__eyebrow::after { width: 26px; }
  .tline__lead { font-size: 15px; }
  .tline__head,
  .tline__track { width: calc(100% - 40px); }
  /* The rail moves in tight against the column edge — at this width a gutter
     of any size leaves the card too narrow for these titles. */
  .tline__track { --rail: 9px; --gutter: 28px; --node: 13px; }
  .tstop { padding-block-end: 22px; }
  .tstop__node { top: 26px; }
  /* The spur has almost no distance left to cross; the node sitting against
     the card's own edge is the join. */
  .tstop::before { display: none; }

  /* A picture beside the words leaves them too narrow here; it goes above them
     instead — still inside the same card. Stacked, a fixed height would either
     crop the words or leave a gap, so the picture keeps its ratio and the card
     takes whatever that adds up to. */
  .tstop__body { flex-direction: column; height: auto; border-radius: 8px 8px 8px 24px; }
  /* 16:7.6 was a letterbox — at this width the photographs are the only thing
     carrying the section visually, and they were the thinnest they are
     anywhere on the site. */
  .tstop__thumb { width: 100%; aspect-ratio: 16 / 9.2; }
  .tstop__thumb::after {
    inset-block: auto 0;
    inset-inline: 0;
    width: auto;
    height: 1px;
    background: linear-gradient(to left,
      rgb(186 166 96 / .2), rgb(186 166 96 / .65), rgb(186 166 96 / .2));
  }
  .tstop__panel { padding: 18px 20px 20px; }
  .tstop__year { font-size: 26px; gap: 12px; margin-bottom: 10px; }
  .tstop__title { font-size: 17px; }
  /* The clamp exists to protect a fixed card height. There is no fixed height
     here — the card grows — so clamping would only truncate for nothing. */
  .tstop__text { font-size: 14.4px; -webkit-line-clamp: none; }
}

/* --------------------------------------------------------------------------
   6. Motion preferences
   Extends the block at the end of css/style.css to what this sheet adds. Every
   state is also carried by colour or position, so nothing is lost by holding
   it still.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .cert,
  .cert__card,
  .cert__media img,
  .arc__nav { transition: none; }

  .cert__card:hover .cert__media img { transform: none; }
  .abstats__item { transition: none; }
  .abstats__item:hover { transform: none; }
  .abstats__item::before { transition: none; }
  .tstop__body,
  .tstop__node,
  .tstop__year,
  .tstop__tag,
  .tstop__thumb img { transition: none; }
  /* Colour still carries every hover state — the node fills, the picture
     regains its colour — so only the movement is dropped. */
  .tstop:hover .tstop__body,
  .tstop:focus-within .tstop__body { transform: none; }
  .tstop:hover .tstop__node,
  .tstop:focus-within .tstop__node { transform: none; }
  .tstop:hover .tstop__thumb img,
  .tstop:focus-within .tstop__thumb img { transform: none; }
  .arc__nav--prev:hover,
  .arc__nav--next:hover { transform: none; }

  /* The reveal is a transition out of a hidden resting state, so switching the
     transition off alone would leave every stop invisible. The resting state
     has to be neutralised too. */
  .tline__track.is-observed > .tstop { opacity: 1; transform: none; }
  .abintro__frame,
  .tstop__title { transition: none; }
}

/* --------------------------------------------------------------------------
   7. Page-wide finish
   Two details that belong to the page rather than to any one section, and that
   were the last places its identity stopped short.
   -------------------------------------------------------------------------- */

/* Selected text in the brand's own colours. It costs one rule and it is the
   one piece of chrome a reader can produce themselves — left at the browser's
   default blue it is the only non-brand colour that ever appears on the page.
   Purple ground, white type: 11.1:1. */
.abhead ::selection,
.abintro ::selection,
.abplate ::selection { background: var(--purple); color: #fff; }

/* One focus ring for the whole page. The certificate arrows had their own and
   nothing else did, which meant a keyboard reader crossing this page got a
   gold ring on two buttons and the browser's default outline everywhere else.
   `:focus-visible`, so it never appears for a pointer. */
.abhead a:focus-visible,
.abintro a:focus-visible,
.abplate a:focus-visible,
.abplate button:focus-visible,
.abstats__item:focus-visible,
.tstop__body:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
  border-radius: 4px;
}
