/* ==========================================================================
   PRODUCTION — Phase 06
   Additions layered on top of the Phase 5 design system: global navigation,
   the About/metadata layout, Selected Work's four data-driven project
   compositions (gallery / single / narrative / comparison), Services'
   supporting/capability copy, the Commercial statement, the expanded
   Contact section, and the two new aspect ratios required by the real
   supplied assets (16:9 CGI stills, 9:16 vertical video).
   Same token set as the rest of the system — no new colours, no new radii.
   ========================================================================== */

.ar-16-9 { aspect-ratio: 16 / 9; }
.ar-9-16 { aspect-ratio: 9 / 16; }

/* ==========================================================================
   SECTION SPACING NORMALIZATION (Phase 6.1 §07)
   Fixed-pixel section padding compounds oddly across viewport sizes,
   reading in places as accidental full-viewport blank gaps rather than
   deliberate pacing. Replacing the flat --space-* values used for section
   padding and project-to-project transitions with the three clamp() bands
   below — general section padding, the larger gap between projects, and
   small media-to-caption gaps — keeps the same negative-space language but
   ties it to viewport size instead of a fixed number. Declared after the
   sections/components rules they adjust so no !important is needed.
   ========================================================================== */

.about,
.work-intro,
.work-end,
.services,
.commercial,
.contact,
.footer {
  padding-top: clamp(72px, 8vw, 150px);
  padding-bottom: clamp(72px, 8vw, 150px);
}

.project {
  padding-top: clamp(100px, 12vw, 210px);
  padding-bottom: clamp(100px, 12vw, 210px);
}
.project-sheet--detail { padding-top: clamp(100px, 12vw, 210px); padding-bottom: clamp(100px, 12vw, 210px); }

.project-beat { margin-top: clamp(72px, 8vw, 150px); }
.project-beat .project-media { margin-top: clamp(18px, 2vw, 36px); }
.project-narrative__stage { margin-bottom: clamp(18px, 2vw, 36px); }
.project__motion-label { margin-bottom: clamp(18px, 2vw, 36px); }

/* ==========================================================================
   GLOBAL NAVIGATION
   ========================================================================== */

.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: max(var(--space-20), env(safe-area-inset-top, 0px));
  padding-bottom: var(--space-20);
}

.site-header__logo {
  display: inline-flex;
}

.site-header__symbol {
  width: var(--symbol-size-header);
  height: var(--symbol-size-header);
}

.site-header__menu-btn {
  min-height: 44px;
  min-width: 44px;
  padding: 0 var(--space-8);
}

body.menu-open {
  overflow: hidden;
}

/* Phase 6.2 QA fix: .site-menu is a position:fixed, inset:0, opaque,
   z-index:900 overlay — it covers the entire viewport, including
   .site-header (a normal in-flow element with no z-index of its own).
   The header's toggle button is the ONLY control that closes the menu
   (its label swaps "Menu" → "Close"; there is no separate close button
   inside the menu panel) and it also becomes invisible and unclickable
   the instant the menu opens, at every scroll position — confirmed via
   elementFromPoint at the toggle's own coordinates returning the menu
   overlay, not the button. Fixing it in place, only while the menu is
   open, so normal (menu-closed) header layout/scrolling is untouched:
   pin the header to the viewport top and raise it above the overlay. */
body.menu-open .site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 901;
  background: var(--color-bg-primary);
}

.site-menu {
  position: fixed;
  inset: 0;
  z-index: 900;
  background: var(--color-bg-primary);
  overflow-y: auto;
  padding-top: max(var(--space-96), calc(env(safe-area-inset-top, 0px) + var(--space-64)));
  padding-bottom: var(--space-64);
}

.site-menu[hidden] { display: none; }

.site-menu__primary {
  display: flex;
  flex-direction: column;
  gap: var(--space-16);
}

.site-menu__link {
  color: var(--color-text-primary);
  transition: color var(--motion-fast) var(--ease-standard);
}
.site-menu__link:hover,
.site-menu__link:active { color: var(--color-red); }

.site-menu__work-label {
  margin-top: var(--space-48);
  margin-bottom: var(--space-16);
}

.site-menu__work {
  display: flex;
  flex-direction: column;
  gap: var(--space-12);
  padding-top: var(--space-16);
  border-top: var(--rule-weight) solid var(--color-rule);
}

.site-menu__work-link {
  color: var(--color-text-secondary);
  transition: color var(--motion-fast) var(--ease-standard);
}
.site-menu__work-link:hover,
.site-menu__work-link:active { color: var(--color-red); }

/* ==========================================================================
   HERO
   ========================================================================== */

.hero {
  min-height: auto;
  padding-top: var(--space-32);
  padding-bottom: var(--space-64);
  display: block;
}

.hero__main {
  margin-top: var(--space-24);
  display: flex;
  flex-direction: column;
  gap: var(--space-16);
}

/* Phase 8.5A: no longer independently capped at 30rem — that was narrower
   than .hero__main's own 46rem cap (below), which is what actually governs
   the name block's right edge, so the discipline line was wrapping well
   before it needed to. Bounding it by the same container the name uses
   (no max-width of its own) satisfies "must not extend farther right than
   the name block" exactly, at every breakpoint, without a separate value
   to keep in sync. */
.hero__discipline {
  color: var(--color-text-secondary);
}

/* Phase 8.5B §A2 — optical left-edge alignment.
   Investigated before writing this rule: .hero__name and .hero__discipline
   are both direct children of .hero__main (a column flexbox, no padding)
   and share the exact same CSS box left edge at every breakpoint —
   confirmed by direct measurement (getBoundingClientRect), identical to
   the pixel, from 320px through 1920px. There is no existing margin,
   padding, text-indent, or transform difference between them, so this is
   not a layout bug to "fix" by moving the container, the discipline line,
   or anything else.
   The visible mismatch is real but optical: Inter's "K" glyph carries a
   left side-bearing that is imperceptible at the discipline line's small
   size but becomes visually significant at the hero name's much larger
   size, so the rendered ink of "KOSTAS" starts a few pixels right of the
   rendered ink of "ARCHITECTURAL…" even though both boxes start at the
   same x. Measured directly against rendered pixels (not assumed) at all
   seven QA widths: the ink offset is 2-6px, scaling with the hero name's
   own responsive font-size at a fairly constant ~0.05em of it. A small
   negative margin on .hero__name alone — sized in em so it tracks the
   clamp()'d font-size instead of a fixed px value that would drift at
   other widths — is the standard optical-margin-alignment technique for
   exactly this glyph-metric mismatch, and it moves only the hero name:
   .hero__main, .hero__discipline, the buttons and the icon row are
   untouched.

   Phase 8.9: this correction was calibrated specifically for Inter's "K"
   side-bearing and was NOT assumed to carry over to Plus Jakarta Sans
   (see the Hero-name font-family change in typography.css). Re-derived
   from scratch: first tested with this rule at `margin-left: 0` — i.e.
   no correction — then measured Plus Jakarta Sans's own rendered-ink
   offset against .hero__discipline the same way, via Playwright
   pixel-level screenshot analysis, at this phase's specified widths
   (320/375/768/1024/1440/1920). Result: a comparable but independently
   real optical mismatch, 2-6px (~0.048-0.061em, ~0.055em average, no
   fixed relationship to Inter's value beyond coincidental proximity).
   Re-applying this same -0.055em value and re-measuring confirms it:
   the residual ink offset drops to well under 1px (≤0.5px) at every
   tested width, so no further/different adjustment is needed. No other
   Hero-name property (letter-spacing, line-height, width, transform,
   font-size) was changed to accommodate the new font. */
.hero__name {
  margin-left: -0.055em;
}

@media (min-width: 960px) {
  .hero { padding-top: var(--space-64); padding-bottom: var(--space-96); }
  .hero__main { max-width: 46rem; }
  /* Phase 6.3F: this rule's 7.5rem (120px) ceiling was calibrated against
     the Georgia fallback (Ogg Text was 404ing when it was set). With the
     real self-hosted Ogg Text now loading, "GALIMITAKIS" at 120px/400
     measures ~785px wide against the fixed 736px column (.hero__main's
     max-width: 46rem, active at this same breakpoint) — a ~49px overflow,
     clipped invisibly by the global overflow-x:hidden safety net. Re-
     measured via canvas at the real font/weight (~6.818px of width per 1px
     of font-size for that word): a 6.4rem/102.4px ceiling measures ~698px,
     leaving real margin inside the 736px column at every width from
     1440px up (where this term is already pinned to its ceiling) through
     1920px+. The 4.5rem floor and 6vw scaling term are unchanged — this
     only lowers how large the headline is allowed to grow at wide
     viewports, which was already effectively capped near this size in
     practice once the fixed-width column is accounted for. */
  .hero__name { font-size: clamp(4.5rem, 6vw, 6.4rem); }
}

/* ==========================================================================
   ABOUT
   ========================================================================== */

.about__media {
  max-height: 70vh;
}

.about__copy {
  margin-top: var(--space-32);
}

.about__paragraphs {
  display: flex;
  flex-direction: column;
  gap: var(--space-16);
}

.about__paragraph {
  color: var(--color-text-primary);
  max-width: 34rem;
}

.about__metadata {
  margin: var(--space-32) 0 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-24) var(--space-16);
  max-width: 34rem;
}

.about__metadata dt { grid-row: 1; }
.about__metadata-value {
  margin: var(--space-4) 0 0;
  color: var(--color-text-primary);
}

@media (min-width: 1280px) {
  .about__body {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--margin-full);
    align-items: start;
  }
  .about__media { max-height: none; }
  .about__copy { margin-top: 0; }
}

/* ==========================================================================
   WORK INTRO / WORK END
   ========================================================================== */

.work-intro__chapter {
  margin-top: var(--space-4);
}

.work-intro__index {
  margin-top: var(--space-20);
}

.work-intro__line {
  margin-top: var(--space-16);
  max-width: 30rem;
  color: var(--color-text-primary);
}

.work-end {
  text-align: left;
}

.work-end__statement {
  margin-top: var(--space-20);
  max-width: 30rem;
}

/* ==========================================================================
   PROJECTS — shared scaffolding
   ========================================================================== */

.project {
  border-top: var(--rule-weight) solid var(--color-rule);
}

.project__intro {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
}

.project__title {
  margin-top: var(--space-8);
}

.project__type {
  color: var(--color-text-secondary);
  margin-top: var(--space-4);
}

.project__show-title {
  color: var(--color-text-primary);
  margin-top: var(--space-8);
}

.project__supporting {
  color: var(--color-text-primary);
  max-width: 34rem;
  margin-top: var(--space-8);
}

.project__location,
.project__classification {
  color: var(--color-text-secondary);
  margin-top: var(--space-4);
}

.project-media {
  margin-top: var(--space-40);
}

.project-media.bleed {
  margin-top: var(--space-40);
}

/* ---- Gallery (Project 01 — Eros Residence) -------------------------------- */

.project-gallery {
  margin-top: var(--space-24);
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--gutter-compact);
}

@media (min-width: 768px) {
  .project-gallery { grid-template-columns: repeat(3, 1fr); gap: var(--gutter-wide); }
}

.project__motion {
  margin-top: var(--space-48);
}

.project-video {
  width: 100%;
  background: var(--color-ink);
  border: var(--rule-weight) solid var(--color-rule);
  max-width: 420px;
}
.project-video__el {
  width: 100%;
  height: 100%;
  display: block;
}

/* ---- Narrative (Project 03 — Material / 01) ------------------------------- */

/* Block layout, not flex-column: a flex item that also carries `.wrap`'s
   `margin: 0 auto` (for centering at Full grid width) has its auto margins
   absorb the flex container's free cross-axis space instead of just
   centering a capped box — the item shrinks to its content's min width
   instead of stretching, which is exactly the "Material / 01 renders as
   tiny thumbnails" bug. Plain block stacking with margin-top between
   beats gets the identical vertical rhythm without that interaction. */
.project-narrative {
  margin-top: var(--space-24);
}

.project-narrative__beat + .project-narrative__beat {
  margin-top: var(--space-48);
}

/* Desktop editorial rhythm (brief §05): each image gets meaningful but
   deliberately DIFFERENT visual weight and alternating alignment — not
   identical full-width or identically-sized frames. Intrinsic aspect
   ratio is untouched throughout (still governed by each image's own
   `ar-4-5` class); only the column width and left/right position change
   per beat. Mobile/tablet stay full-width — this is a small-desktop-and-
   up refinement, matching how the rest of the system only introduces
   multi-column composition from 960px.
   Phase 8.5C: the sequence's original first image (65%, no offset) is no
   longer part of this loop — it now renders separately, full-bleed,
   directly on the article (see buildNarrativeProject in scripts/main.js)
   for the same large-editorial prominence Project 02's hero image has.
   The three remaining beats below are renumbered from their original
   nth-of-type(2/3/4) to (1/2/3) to match their new position in the
   (now-shorter) loop, but each keeps its EXACT original max-width/
   alignment value — the detail sequence's own visual rhythm (55% right-
   offset / 55% / 48% right-offset) is unchanged, just shifted up one
   position in source order. */
@media (min-width: 960px) {
  .project-narrative__beat:nth-of-type(1) .project-media { max-width: 55%; margin-left: auto; }
  .project-narrative__beat:nth-of-type(2) .project-media { max-width: 55%; }
  .project-narrative__beat:nth-of-type(3) .project-media { max-width: 48%; margin-left: auto; }
}

/* The lead stage label (Phase 8.5C) sits above the now-full-bleed first
   image, same content and same position in the sequence as before — only
   its container changed from the `.wrap`-padded beat to a standalone
   `.wrap` paragraph, so it keeps the page's standard inset margin while
   the image beneath it is free to bleed full width. Uses the exact same
   top margin `.project-narrative` itself used to open the sequence
   (`--space-24`, immediately below buildIntro in the article) — the gap
   from the project's intro copy down to this label is unchanged from
   before this element existed outside `.project-narrative`. The image
   below it still gets its own `--space-40` from the shared `.project-media`
   rule, exactly as every other project image does. */
.project-narrative__stage--lead {
  margin-top: var(--space-24);
}

/* ---- Comparison (Project 04 — Vision to Reality) -------------------------- */

.project-beat__heading {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
}

.project-beat__title {
  color: var(--color-text-primary);
}

.project-beat__meta {
  color: var(--color-text-secondary);
}

.project-beat__duration {
  margin-top: var(--space-8);
}

.project-comparison {
  margin-top: var(--space-64);
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-32);
}

.project-comparison__col p { margin-bottom: var(--space-12); }

@media (min-width: 768px) {
  .project-comparison { grid-template-columns: 1fr 1fr; gap: var(--gutter-wide); }
}

.project-pairs {
  margin-top: var(--space-64);
}

.project-pairs__labels {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gutter-wide);
  margin-bottom: var(--space-16);
}

.project-pairs__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gutter-wide);
  margin-bottom: var(--space-24);
}

.project__end {
  margin-top: var(--space-64);
  text-align: left;
}

.project__end-statement {
  color: var(--color-text-primary);
  max-width: 28rem;
}

.project__end-label {
  margin-top: var(--space-12);
}

/* ---- Credits (shared by every project kind) ------------------------------- */

.project-credits {
  margin-top: var(--space-48);
  display: flex;
  flex-direction: column;
  gap: var(--space-24);
  border-top: var(--rule-weight) solid var(--color-rule);
  padding-top: var(--space-24);
}

@media (min-width: 601px) {
  .project-credits { flex-direction: row; flex-wrap: wrap; gap: var(--space-48); }
}

.project-credits__role {
  margin-bottom: var(--space-8);
}

.project-credits__name {
  color: var(--color-text-primary);
}

/* ==========================================================================
   SERVICES
   ========================================================================== */

.services__title { color: var(--color-text-primary); }

.services__supporting {
  margin-top: var(--space-32);
  max-width: 34rem;
  color: var(--color-text-primary);
}

.services__capabilities {
  margin-top: var(--space-24);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-8) var(--space-20);
}

.services__capability::after {
  content: "";
}

.services__capability {
  color: var(--color-text-secondary);
}

.services__capability:not(:last-child)::after {
  content: "·";
  margin-left: var(--space-20);
  color: var(--color-text-tertiary);
}

/* ==========================================================================
   COMMERCIAL STATEMENT
   ========================================================================== */

/* Generic red-field rule, applied via the `data-bg="red"` attribute rather
   than a section-specific class so any red-field section gets it
   automatically. `.statement` (sections.css) hardcodes the same two
   declarations for itself only — this rule is what makes `.commercial`
   (which also carries `data-bg="red"`) match it without duplicating the
   declarations under a second class. */
[data-bg="red"] {
  background: var(--color-bg-inverse);
  color: var(--color-text-inverse);
}

.commercial__label {
  color: rgba(21, 25, 28, 0.6);
}

.commercial__statement {
  color: var(--color-text-inverse);
  margin-top: var(--space-16);
  max-width: 32rem;
}

.btn--secondary--on-red {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding: 0 var(--space-24);
  border-radius: var(--radius-max);
  border: 1px solid var(--color-ink);
  color: var(--color-ink);
  margin-top: var(--space-32);
  transition: background-color var(--motion-fast) var(--ease-standard),
              color var(--motion-fast) var(--ease-standard);
}
.btn--secondary--on-red:hover,
.btn--secondary--on-red:active {
  background: var(--color-ink);
  color: var(--color-warm-white);
}

/* ==========================================================================
   CONTACT
   ========================================================================== */

.contact__large {
  margin-top: var(--space-8);
  max-width: 24rem;
}

.contact__statement {
  margin-top: var(--space-16);
  max-width: 32rem;
  color: var(--color-text-primary);
}

.contact__actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-12);
  margin-top: var(--space-40);
  max-width: 24rem;
}
@media (min-width: 601px) {
  .contact__actions { flex-direction: row; max-width: none; }
}

.contact__secondary {
  margin-top: var(--space-24);
}

.contact__location {
  margin-top: var(--space-32);
  color: var(--color-text-secondary);
}

/* The generic `.is-disabled` treatment (components.css) dims via opacity —
   correct for the quiet inline action-row links (Email/LinkedIn greyed out
   when unconfigured), but on a `.btn--primary` it washes the brand red
   down to a muted brown, reading as a broken/wrong button color rather
   than an inert one. The button stays genuinely inert either way (the
   disabled-link click-guard in main.js already blocks navigation); this
   only restores its correct #FF3131 / #15191C appearance. */
.btn--primary.is-disabled {
  opacity: 1;
}

/* ==========================================================================
   FOOTER
   ========================================================================== */

.footer__lines {
  margin-top: var(--space-4);
}
