/* ==========================================================================
   Sections
   Hero and portrait plate, about, and the motion layer.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  /* Capped rather than a flat 100vh: on tall viewports the centred text
     column is much shorter than the box, and the slack below it was
     stacking with the About section's own top padding into one large gap. */
  min-block-size: min(100vh, 46rem);
  min-block-size: min(100svh, 46rem);
  padding-block: calc(var(--header-h) + var(--space-lg)) var(--space-md);
  overflow: clip;
}

.hero__text {
  position: relative;
  z-index: 2;
  max-inline-size: min(34rem, 92%);
}

.hero__eyebrow {
  margin-block-end: var(--space-md);
}

.hero__name {
  font-size: var(--text-display);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  margin-block-end: var(--space-md);
}

.hero__name .line {
  display: block;
  overflow: hidden;
  padding-block-end: 0.06em;
}

.hero__name .line:last-child {
  color: var(--copper);
}

.hero__lede {
  font-size: var(--text-lede);
  line-height: 1.6;
  color: var(--ink-soft);
  max-inline-size: 26rem;
  margin-block-end: var(--space-lg);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

/* Portrait ---------------------------------------------------------------- */

/* The cut-out portrait stands directly on the sand — no plate, no crop, no
   blending tricks. It's the treatment the warm-sand direction wanted from the
   start, and it only became possible once the background was removed. */
.portrait {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: flex-end;
}

/* <picture> is the flex item, not the <img>. Without a definite height here
   the image's block-size:100% resolves against an auto-height parent and it
   falls back to its natural size, overflowing the hero and cropping his head. */
.portrait picture {
  display: block;
  block-size: 100%;
  position: relative;
  z-index: 1;
}

.portrait__img {
  display: block;
  margin-inline: auto;
  inline-size: auto;
  max-inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
  object-position: bottom center;
  /* The lower robe falls into shadow (luminance ~154 against the sand's
     ~243), so it is dissolved rather than cut off at a hard edge. */
  -webkit-mask-image: linear-gradient(to bottom, #000 82%, transparent 99%);
  mask-image: linear-gradient(to bottom, #000 82%, transparent 99%);
}

/* A soft disc behind the figure. Only one step darker than the page, so it
   reads as depth rather than as a shape.
   Centring must stay purely logical: inset-inline-start:50% paired with a
   physical translateX(-50%) only centred it by coincidence under LTR — in
   RTL, inline-start flips to the physical right, but translateX still
   pushes left, so the disc landed a full width outside the portrait. Setting
   both inline insets to 0 and letting margin-inline:auto share the slack is
   the standard centring trick that stays correct under both directions. */
.portrait__halo {
  position: absolute;
  z-index: 0;
  inset-block-start: 4%;
  inset-inline: 0;
  margin-inline: auto;
  inline-size: min(30rem, 82%);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(
    circle at 50% 45%,
    var(--sand-200) 0%,
    var(--sand-200) 58%,
    transparent 72%
  );
  pointer-events: none;
}

/* Copper rule, echoing the section labels. */
.portrait__frame {
  display: none;
  position: absolute;
  z-index: 0;
  inset-block: 12% 16%;
  inset-inline-start: 0;
  inline-size: 1px;
  background: var(--copper);
  opacity: 0.5;
  pointer-events: none;
}

/* Mobile / tablet: the figure sits under the text, centred. */
@media (max-width: 63.99em) {
  .hero {
    min-block-size: 0;
    display: block;
  }

  .portrait {
    margin-block-start: var(--space-md);
    block-size: min(70vh, 32rem);
  }

  .portrait__halo {
    inline-size: min(22rem, 74%);
  }
}

/* Desktop: the figure is pinned to the inline-end of the viewport and stands
   on the floor of the hero. */
@media (min-width: 64em) {
  .hero__text {
    max-inline-size: min(38rem, 46vw);
  }

  .portrait {
    position: absolute;
    /* Height comes from the two insets (header clearance to hero's own
       bottom) rather than a fixed value, so it always fits inside the hero
       box and can never push above the header, whatever the hero's height
       resolves to. */
    inset-block: var(--header-h) 0;
    inset-inline-end: clamp(0rem, 4vw, 5rem);
    inline-size: min(40vw, 32rem);
    z-index: 1;
  }

  .portrait__frame {
    display: block;
  }
}

/* --------------------------------------------------------------------------
   About
   -------------------------------------------------------------------------- */

.about {
  /* Only the section directly after the hero gets a tighter top offset —
     Connect keeps the standard --space-section rhythm below it. */
  padding-block-start: clamp(2rem, 1rem + 3vw, 4rem);
}

.about__body {
  max-inline-size: var(--measure);
  display: grid;
  gap: var(--space-md);
}

.about__body p:first-child {
  font-size: var(--text-lede);
  line-height: 1.65;
}

.about__body strong {
  font-weight: var(--weight-medium);
  color: var(--copper-deep);
  white-space: nowrap;
}

/* An excerpted line from aboutP2, set apart rather than left to blend into
   the paragraph flow — the one moment in About that isn't run-on prose. */
.pull-quote {
  padding-inline-start: 1.25rem;
  border-inline-start: 2px solid var(--copper);
  font-family: var(--font-display);
  font-style: italic;
  font-weight: var(--weight-bold);
  font-size: var(--text-lede);
  line-height: var(--leading-snug);
  color: var(--ink);
}

/* Arabic has no real italic tradition and Alexandria doesn't carry an
   italic cut worth faking, so the rule + weight alone carry the emphasis. */
html[lang="ar"] .pull-quote {
  font-style: normal;
}

/* A quiet list of specialties, standing in for the removed credentials
   table. Plain labels rather than pills — a pill/chip shape reads as
   clickable in most people's mental model (filters, removable tags), and
   these aren't; a divided list reads as attributes instead. */
.focus-list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.85rem;
  margin-block-start: var(--space-lg);
  padding: 0;
  list-style: none;
  max-inline-size: var(--measure);
}

.focus-list li {
  position: relative;
  padding-inline-end: 0.85rem;
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--ink-soft);
}

.focus-list li:not(:last-child)::after {
  content: "";
  position: absolute;
  inset-inline-end: 0;
  inset-block: 0.2em;
  inline-size: 1px;
  background: var(--sand-400);
}

html[lang="ar"] .focus-list li {
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--text-sm);
}

/* --------------------------------------------------------------------------
   Instagram
   -------------------------------------------------------------------------- */

.instagram {
  border-block-start: var(--hairline);
}

/* Plain link shown until (if) the live feed loads — see assets/js/
   instagram-feed.js. Never removed, just visually replaced in place. */
.instagram-fallback {
  color: var(--ink-soft);
}

.instagram-fallback a {
  color: var(--copper-deep);
}

.instagram-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-sm);
}

@media (min-width: 35em) {
  .instagram-grid {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-md);
  }
}

.instagram-card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: var(--hairline);
  border-radius: var(--radius-sm);
  color: inherit;
  text-decoration: none;
  background: var(--sand-100);
  transition: transform var(--dur) var(--ease-out-expo),
    box-shadow var(--dur) var(--ease-out-expo), border-color var(--dur-fast) var(--ease-out-soft);
}

.instagram-card:hover,
.instagram-card:focus-visible {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lift);
  border-color: var(--sand-400);
}

@media (prefers-reduced-motion: reduce) {
  .instagram-card:hover,
  .instagram-card:focus-visible {
    transform: none;
  }
}

.instagram-card__img {
  aspect-ratio: 1;
  inline-size: 100%;
  object-fit: cover;
}

.instagram-card__caption {
  padding: 0.75rem;
  font-size: var(--text-xs);
  line-height: var(--leading-snug);
  color: var(--ink-soft);
  white-space: pre-line;
}

.instagram-card__caption:empty {
  display: none;
}

.instagram-cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  text-align: center;
  margin-block-start: var(--space-xl);
  padding: var(--space-lg);
  background: var(--sand-200);
  border: var(--hairline);
  border-radius: var(--radius-sm);
}

.instagram-cta__icon {
  inline-size: 34px;
  block-size: 34px;
  fill: var(--copper-deep);
}

.instagram-cta__title {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-lede);
}

.instagram-cta__desc {
  color: var(--ink-soft);
  max-width: 32rem;
}

.instagram-cta__btn {
  margin-block-start: 0.5rem;
}

/* --------------------------------------------------------------------------
   Work
   -------------------------------------------------------------------------- */

.work {
  background: var(--sand-50);
  border-block-start: var(--hairline);
}

.work-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr));
  gap: var(--space-md);
}

.work-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.75rem;
  padding: var(--space-lg);
  background: var(--sand-100);
  border: var(--hairline);
  border-radius: var(--radius-sm);
  transition: transform var(--dur) var(--ease-out-expo),
    box-shadow var(--dur) var(--ease-out-expo),
    border-color var(--dur-fast) var(--ease-out-soft);
}

.work-card:hover,
.work-card:focus-within {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lift);
  border-color: var(--sand-400);
}

@media (prefers-reduced-motion: reduce) {
  .work-card:hover,
  .work-card:focus-within {
    transform: none;
  }
}

.work-card__title {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-lede);
  line-height: var(--leading-snug);
}

/* Full text, no truncation — the card's block-size is auto, so it grows
   or shrinks to whatever the description needs at any viewport width
   instead of clipping it. flex:1 only matters when a row holds more than
   one card of differing lengths: it lets the shorter ones stretch so
   every "Visit project" link still lines up along the same baseline. */
.work-card__desc {
  color: var(--ink-soft);
  flex: 1;
}

.work-card__link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--copper-deep);
  text-decoration: none;
}

.work-card__arrow {
  display: inline-block;
  transition: transform var(--dur-fast) var(--ease-out-soft);
}

.work-card__link:hover .work-card__arrow,
.work-card__link:focus-visible .work-card__arrow {
  transform: translate(2px, -2px);
}

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

/* --------------------------------------------------------------------------
   404
   -------------------------------------------------------------------------- */

.notfound {
  display: flex;
  align-items: center;
  min-block-size: min(100vh, 46rem);
  text-align: center;
}

.notfound__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-inline: auto;
}

.notfound__label {
  justify-content: center;
}

.notfound__label::after {
  content: "";
  inline-size: 2.25rem;
  block-size: 1px;
  background: var(--copper);
  flex: none;
}

.notfound__code {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-display);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  color: var(--copper);
  margin-block: var(--space-md);
}

.notfound__desc {
  font-size: var(--text-lede);
  line-height: 1.6;
  color: var(--ink-soft);
  max-inline-size: 26rem;
  margin-block-end: var(--space-lg);
}

.notfound__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-sm);
}

@media (max-width: 35em) {
  .notfound {
    min-block-size: 0;
    padding-block: var(--space-lg) 0;
  }
}

/* --------------------------------------------------------------------------
   Motion
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  /* Hero name rises line by line. Pure CSS with `both` fill, so it never
     depends on JS to become visible. */
  .hero__name .line > span {
    display: block;
    animation: rise 1.1s var(--ease-out-expo) both;
    animation-delay: var(--delay, 0ms);
  }

  .hero__name .line:nth-child(1) > span {
    animation-delay: 80ms;
  }

  .hero__name .line:nth-child(2) > span {
    animation-delay: 200ms;
  }

  @keyframes rise {
    from {
      transform: translateY(115%);
    }
    to {
      transform: translateY(0);
    }
  }

  /* Scroll reveal. The hidden start state is scoped to `.js` so that with
     JavaScript disabled every section renders normally. */
  .js .reveal {
    opacity: 0;
    transform: translateY(1.5rem);
    transition: opacity var(--dur-slow) var(--ease-out-soft),
      transform var(--dur-slow) var(--ease-out-expo);
    transition-delay: var(--delay, 0ms);
  }

  .js .reveal.is-revealed {
    opacity: 1;
    transform: none;
  }
}
