/* ==========================================================================
   base.css - reset, typography, and the elements that repeat everywhere:
   rules, nav, buttons, reveals, the cinematic band, form controls, footer.
   Section specific layout lives in sections.css.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Reset
   -------------------------------------------------------------------------- */

*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  background: var(--bone);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

body.is-menu-open { overflow: hidden; }

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;          /* Instrument Serif ships one weight */
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
}

p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
dl, dd { margin: 0; }

/* figure carries a 40px horizontal margin by default in every browser, which
   silently widens any grid column it sits in. The cinematic band is a figure,
   so this reset is load bearing rather than cosmetic. */
figure, figcaption, blockquote { margin: 0; }

img, svg, picture { display: block; max-width: 100%; height: auto; }

a { color: inherit; text-decoration: none; }

button, input, textarea, select { font: inherit; color: inherit; }

/* --------------------------------------------------------------------------
   2. Focus and skip link
   -------------------------------------------------------------------------- */

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

.skip-link {
  position: absolute;
  top: var(--space-s);
  left: var(--space-s);
  z-index: 200;
  padding: var(--space-xs) var(--space-m);
  background: var(--ink);
  color: var(--bone);
  font-size: var(--text-small);
  font-weight: 600;
  transform: translateY(-180%);
  transition: transform var(--ui-duration) var(--ease);
}

.skip-link:focus { transform: translateY(0); }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   3. Layout and the rule system
   Sections are separated by full width ink rules. Columns inside a section
   are separated by hairlines. The difference in weight is what makes the
   page read as a broadsheet rather than a set of cards.
   -------------------------------------------------------------------------- */

.shell {
  width: 100%;
  max-width: var(--width);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section {
  padding-block: var(--space-2xl);
  border-top: var(--rule-ink);
}

.section--tight { padding-block: var(--space-xl); }

/* Divided columns.
   Single column on mobile with horizontal hairlines between items. At the
   breakpoint the flow turns and the hairlines become vertical, which is the
   mobile rule in the brief handled in one place.
   .cols--ink upgrades the divider to a full ink rule for major splits. */
.cols {
  display: grid;
  gap: var(--space-l);
}

/* Grid items default to min-width:auto, so one long word or a wide child can
   push a column past its share and overflow the page. */
.cols > * { min-width: 0; }

.cols > * + * {
  border-top: var(--rule-hair);
  padding-top: var(--space-l);
}

.cols--ink > * + * { border-top: var(--rule-ink); }

@media (min-width: 860px) {
  .cols {
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: 0;
  }

  .cols > * {
    padding-inline: var(--space-l);
    padding-top: 0;
  }

  .cols > *:first-child { padding-left: 0; }
  .cols > *:last-child { padding-right: 0; }

  .cols > * + * {
    border-top: 0;
    border-left: var(--rule-hair);
  }

  .cols--ink > * + * { border-left: var(--rule-ink); }
}

/* --------------------------------------------------------------------------
   4. Type patterns
   -------------------------------------------------------------------------- */

.eyebrow {
  display: block;
  margin-bottom: var(--space-m);
  font-family: var(--font-body);
  font-size: var(--text-label);
  font-weight: 700;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--rust);
}

.headline {
  font-size: var(--text-display);
  line-height: var(--leading-tight);
}

.headline--hero {
  font-size: var(--text-hero);
  line-height: var(--leading-hero);
  letter-spacing: var(--tracking-hero);
}

/* The one emphasised phrase per headline. Serif italic, rust, used once. */
.em {
  font-style: italic;
  color: var(--rust);
}

.lede {
  max-width: var(--measure);
  font-size: var(--text-lead);
  line-height: 1.5;
  color: var(--mid);
}

.headline + .lede { margin-top: var(--space-m); }

/* Serif italic numerals used as list markers and ornament. */
.num {
  display: block;
  font-family: var(--font-display);
  font-style: italic;
  color: var(--rust);
  line-height: 1;
  letter-spacing: 0;
}

.num--sm { font-size: 1.05rem; margin-bottom: var(--space-s); }
.num--lg { font-size: clamp(2.2rem, 1.6rem + 2vw, 3.25rem); }

/* Small uppercase label used under statistics and beside list items. */
.label {
  font-family: var(--font-body);
  font-size: var(--text-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--faint);
}

/* --------------------------------------------------------------------------
   5. Buttons and links
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6em;
  padding: 1em 1.9em;
  border: 1px solid var(--ink);
  border-radius: 0;                /* editorial: no rounded corners */
  background: var(--ink);
  color: var(--bone);
  font-family: var(--font-body);
  font-size: var(--text-small);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--ui-duration) var(--ease),
              color var(--ui-duration) var(--ease),
              border-color var(--ui-duration) var(--ease);
}

.btn:hover { background: var(--rust); border-color: var(--rust); }

.btn--ghost {
  background: transparent;
  color: var(--ink);
}

.btn--ghost:hover { background: var(--ink); color: var(--bone); border-color: var(--ink); }

.btn--small { padding: 0.8em 1.4em; font-size: var(--text-label); }

/* On a dark band the button inverts. */
.cine .btn {
  background: var(--band-text);
  border-color: var(--band-text);
  color: var(--ink);
}

.cine .btn:hover { background: var(--amber); border-color: var(--amber); }

/* Text link. A rust underline on hover is the whole interaction. */
.link {
  display: inline-block;
  font-size: var(--text-small);
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ink);
  border-bottom: 1px solid var(--rule);
  padding-bottom: 2px;
  transition: color var(--ui-duration) var(--ease),
              border-color var(--ui-duration) var(--ease);
}

.link:hover { color: var(--rust); border-bottom-color: var(--rust); }

/* --------------------------------------------------------------------------
   6. Nav
   Sticky, bone, quiet. Condenses on scroll: the bar shortens and the ink
   rule appears underneath it. nav.js adds .is-condensed past 24px.
   -------------------------------------------------------------------------- */

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  background: var(--bone);
  border-bottom: 1.5px solid transparent;
  transition: border-color var(--ui-duration) var(--ease);
}

.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-m);
  height: 82px;
  transition: height var(--ui-duration) var(--ease);
}

.nav.is-condensed { border-bottom-color: var(--ink); }
.nav.is-condensed .nav__inner { height: 62px; }

.nav__brand {
  display: inline-flex;
  align-items: baseline;
  gap: 0.5rem;
  white-space: nowrap;
}

/* The needle. Centred against a baseline aligned lockup, so it sits with the
   wordmark rather than hanging off its baseline. */
/* The box is wider than the art needs so that the needle scales to the
   height rather than being squeezed by the width. */
.nav__mark {
  width: 16px;
  height: 28px;
  flex: none;
  align-self: center;
  margin-right: 0.15rem;
}

.nav__brand-name {
  font-family: var(--font-display);
  font-size: 1.45rem;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.nav__brand-sub {
  font-family: var(--font-body);
  font-size: var(--text-label);
  font-weight: 600;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--faint);
}

.nav__links {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.4vw, 2.25rem);
}

.nav__link {
  position: relative;
  padding: 0.35rem 0;
  font-size: var(--text-label);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mid);
  transition: color var(--ui-duration) var(--ease);
}

.nav__link::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--rust);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--ui-duration) var(--ease);
}

.nav__link:hover { color: var(--ink); }
.nav__link:hover::after { transform: scaleX(1); }

.nav__link.is-active { color: var(--rust); }
.nav__link.is-active::after { transform: scaleX(1); }

.nav__toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--ink);
  cursor: pointer;
}

.nav__toggle-bars,
.nav__toggle-bars::before,
.nav__toggle-bars::after {
  display: block;
  width: 17px;
  height: 1.5px;
  background: var(--ink);
  transition: transform var(--ui-duration) var(--ease),
              opacity var(--ui-duration) var(--ease);
}

.nav__toggle-bars::before,
.nav__toggle-bars::after { content: ""; position: absolute; }
.nav__toggle-bars::before { transform: translateY(-6px); }
.nav__toggle-bars::after  { transform: translateY(6px); }

.nav__toggle[aria-expanded="true"] .nav__toggle-bars { background: transparent; }
.nav__toggle[aria-expanded="true"] .nav__toggle-bars::before { transform: rotate(45deg); }
.nav__toggle[aria-expanded="true"] .nav__toggle-bars::after  { transform: rotate(-45deg); }

/* Mobile drawer.
   The drawer is a JavaScript feature, so the whole mechanism is scoped to
   .js. A no-script visitor gets a header with just the wordmark and a fully
   scrollable page, rather than an overlay with no way to dismiss it.
   nav.js uses the same 1080px value; keep the two in step. */
@media (max-width: 1080px) {
  .js .nav__toggle { display: inline-flex; }
  .js .nav__links,
  .js .nav__cta { display: none; }

  html:not(.js) .nav__menu { display: none; }

  .js .nav__menu {
    position: fixed;
    inset: 62px 0 0 0;
    padding: var(--space-xl) var(--gutter) var(--space-2xl);
    background: var(--bone);
    border-top: var(--rule-ink);
    overflow-y: auto;
  }

  .nav__menu[hidden] { display: none; }

  .nav__menu .nav__links {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }

  .nav__menu .nav__link {
    padding: var(--space-m) 0;
    font-family: var(--font-display);
    font-size: 1.65rem;
    font-weight: 400;
    letter-spacing: var(--tracking-tight);
    text-transform: none;
    color: var(--ink);
    border-bottom: var(--rule-hair);
  }

  .nav__menu .nav__link::after { display: none; }
  .nav__menu .nav__link.is-active { color: var(--rust); font-style: italic; }

  .nav__menu .nav__cta {
    display: inline-flex;
    width: 100%;
    margin-top: var(--space-l);
  }
}

@media (min-width: 1081px) {
  .nav__menu { display: contents; }
}

/* --------------------------------------------------------------------------
   7. Cinematic band
   A full bleed dark interruption in the light page. Used in the hero, and
   reserved for the case study openers once real photography arrives.
   Amber lives here and nowhere else.
   -------------------------------------------------------------------------- */

.cine {
  position: relative;
  background: var(--band-bg);
  color: var(--band-text);
  overflow: hidden;
}

.cine__media {
  position: relative;
  width: 100%;
  height: 100%;
}

.cine__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Warm stage light behind the subject. */
.cine__glow {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(62% 58% at 50% 64%,
    var(--amber-glow) 0%,
    rgba(200, 135, 58, 0.08) 45%,
    transparent 72%);
}


.cine__caption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  display: flex;
  justify-content: space-between;
  gap: var(--space-m);
  padding: var(--space-s) var(--space-m);
  font-family: var(--font-body);
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: var(--tracking-caption);
  text-transform: uppercase;
  color: var(--band-faint);
}


/* --------------------------------------------------------------------------
   8. Scroll reveals
   Fade and rise, 24px, 0.7s. Nothing else moves.
   Progressive enhancement: the hidden state only applies when JS confirms
   it is running, so a script failure leaves the page fully readable.
   -------------------------------------------------------------------------- */

.js .reveal {
  opacity: 0;
  transform: translate3d(0, var(--reveal-shift), 0);
  transition:
    opacity var(--reveal-duration) var(--ease),
    transform var(--reveal-duration) var(--ease);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}

.js .reveal.is-visible {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  will-change: auto;
}

/* Rules draw in horizontally on first view. */
.js .rule-draw {
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 900ms var(--ease);
  transition-delay: var(--reveal-delay, 0ms);
}

.js .rule-draw.is-visible { transform: scaleX(1); }

@media (prefers-reduced-motion: reduce) {
  .js .reveal,
  .js .rule-draw {
    opacity: 1;
    transform: none;
    transition: none;
    transition-delay: 0ms;
  }
}

/* --------------------------------------------------------------------------
   9. Image placeholders
   Every .media wraps an <img> at the final aspect ratio so dropping in the
   real asset does not move anything on the page.
   -------------------------------------------------------------------------- */

.media {
  position: relative;
  overflow: hidden;
  background: var(--bone-warm);
}

.media img { width: 100%; height: 100%; object-fit: cover; }


/* --------------------------------------------------------------------------
   10. Footer
   -------------------------------------------------------------------------- */

.footer {
  padding-block: var(--space-xl);
  border-top: var(--rule-ink);
}

.footer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-m);
  font-size: var(--text-small);
  color: var(--faint);
}

.footer__links { display: flex; flex-wrap: wrap; gap: var(--space-m); }

.footer__links a {
  font-size: var(--text-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  transition: color var(--ui-duration) var(--ease);
}

.footer__links a:hover { color: var(--rust); }


/* ==========================================================================
   COOKIE CONSENT
   A fixed bar on ink, so it reads as chrome rather than as part of the page.
   It carries the hidden attribute in the markup and js/consent.js removes it,
   which means with JavaScript off the bar never appears and analytics stays
   denied. Failing closed is deliberate.
   ========================================================================== */

.consent {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 200;
  background: var(--dark-bg);
  color: var(--dark-text);
  border-top: 1px solid var(--dark-rule);
}

/* Insurance. Nothing here sets display, so the hidden attribute already works,
   but a later layout rule must not be allowed to override it silently. */
.consent[hidden] { display: none; }

.consent__inner {
  display: grid;
  gap: var(--space-m);
  padding-block: var(--space-m);
}

.consent__title {
  font-family: var(--font-body);
  font-size: var(--text-label);
  font-weight: 700;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--rust-light);          /* 5.8:1 on ink */
  margin-bottom: var(--space-2xs);
}

.consent__text p {
  max-width: 70ch;
  font-size: var(--text-small);
  color: var(--dark-mid);            /* 11:1 on ink */
}

.consent__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-s);
}

/* Page buttons are ink on bone and would disappear inside this bar, so they
   invert: solid bone to accept, outlined to decline. Decline stays visually
   quieter than accept but is the same size and equally reachable, which is
   what makes the choice a real one. */
.consent .btn {
  background: var(--bone);
  border-color: var(--bone);
  color: var(--ink);
}

.consent .btn:hover {
  background: var(--rust-light);
  border-color: var(--rust-light);
  color: var(--ink);
}

.consent .btn--ghost {
  background: transparent;
  color: var(--dark-text);
  border-color: var(--dark-rule);
}

.consent .btn--ghost:hover {
  background: var(--dark-text);
  border-color: var(--dark-text);
  color: var(--ink);
}

@media (min-width: 800px) {
  .consent__inner {
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: var(--space-xl);
  }
}

/* The page .link is ink with a rust hover, which disappears on the ink bar.
   Inside the consent bar it inverts to match the surrounding text. */
.consent .link { color: var(--dark-text); }
.consent .link:hover { color: var(--rust-light); }
