/* ============================================================================
   FT WEB — stylesheet
   ----------------------------------------------------------------------------
   Contents
     01. Fonts
     02. Tokens
     03. Reset & base
     04. Typography
     05. Layout primitives
     06. Links & buttons
     07. Motion (scroll reveal)
     08. Grain overlay
     09. Header & numbered nav
     10. Hero
     11. Section furniture
     12. The Work
     13. Full-bleed bands
     14. Process
     15. Studio
     16. Contact
     17. Footer
     18. Responsive
   ========================================================================== */


/* 01. FONTS =================================================================
   Self-hosted, latin subset only, ~61KB total. No third-party requests.
   Pulled from Google Fonts' CDN at build time; both faces are SIL OFL.
   ========================================================================== */

@font-face {
  font-family: 'Instrument Serif';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/instrument-serif-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Instrument Serif';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/instrument-serif-latin-italic.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Variable weight axis 400–600 — one file covers body, medium and semibold. */
@font-face {
  font-family: 'Instrument Sans';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('../fonts/instrument-sans-latin-var.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}


/* 02. TOKENS ================================================================
   Palette is near-monochrome. Oxblood is the ONLY accent and appears in
   exactly four places: the active nav numeral, link underlines on
   hover/focus, the hero rule, and the focused form field rule.
   Contrast on --bone: ink 15.8:1 (AAA) · muted 4.77:1 (AA) · oxblood 6.76:1 (AA)
   ========================================================================== */

:root {
  /* Colour */
  --bone: #f4f1ea;
  --bone-deep: #ebe7de;      /* faint tonal shift for placeholder panels */
  --ink: #141414;
  --muted: #6e6a63;
  --oxblood: #8c3a2b;
  --oxblood-light: #b85b45;  /* accent on dark bands — holds contrast on ink */
  --hairline: rgba(20, 20, 20, 0.14);
  --hairline-soft: rgba(20, 20, 20, 0.08);

  /* Type */
  --serif: 'Instrument Serif', 'Iowan Old Style', Georgia, 'Times New Roman', serif;
  --sans: 'Instrument Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI',
    Helvetica, Arial, sans-serif;

  --step-hero: clamp(2.75rem, 7vw, 6rem);
  --step-h2: clamp(2rem, 4.5vw, 3.5rem);
  --step-h3: clamp(1.5rem, 2.6vw, 2.25rem);
  --step-lead: clamp(1.25rem, 2vw, 1.75rem);
  --step-body: clamp(1rem, 0.95rem + 0.3vw, 1.1875rem);
  --step-small: 0.875rem;
  --step-label: 0.6875rem;

  /* Space */
  --gutter: clamp(1.25rem, 5vw, 6rem);
  --gutter-col: clamp(1rem, 2.2vw, 2rem);
  --space-section: clamp(7rem, 14vh, 12rem);
  --header-h: 5rem;

  /* Motion */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --dur: 0.7s;

  --max-width: 1440px;
}


/* 03. RESET & BASE ========================================================== */

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

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Anchor targets clear the fixed header instead of hiding under it. */
  scroll-padding-top: 6rem;
}

body {
  background: var(--bone);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--step-body);
  line-height: 1.7;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Guards against any single element forcing a horizontal scrollbar. */
  overflow-x: hidden;
}

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

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

ul, ol { list-style: none; padding: 0; }

/* Single global focus treatment — the accent's fourth and final job. */
:focus-visible {
  outline: 2px solid var(--oxblood);
  outline-offset: 3px;
}

/* Keyboard-only escape hatch past the nav. */
.skip-link {
  position: absolute;
  top: 0;
  left: var(--gutter);
  z-index: 100;
  transform: translateY(-120%);
  padding: 0.75rem 1.25rem;
  background: var(--ink);
  color: var(--bone);
  font-size: var(--step-small);
  text-decoration: none;
  transition: transform 0.2s var(--ease);
}
.skip-link:focus { transform: translateY(0); }

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


/* 04. TYPOGRAPHY ============================================================ */

h1, h2, h3 {
  font-family: var(--serif);
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 1;
  text-wrap: balance;
}

p { text-wrap: pretty; }

/* Eyebrow / index label — wide tracking is doing the editorial work here. */
.label {
  font-family: var(--sans);
  font-size: var(--step-label);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.lead {
  font-size: var(--step-lead);
  line-height: 1.5;
  letter-spacing: -0.01em;
}


/* 05. LAYOUT PRIMITIVES ===================================================== */

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

.grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter-col);
}

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

/* Thin rule. Never a boxed card, never a shadow — there is not one
   box-shadow declaration in this file, by design. */
.rule {
  border: 0;
  border-top: 1px solid var(--hairline);
  margin: 0;
}


/* 06. LINKS & BUTTONS =======================================================
   Two link treatments only.
   .link-arrow — CTA. Underline wipes in from the left, arrow nudges right.
                 The arrow glyph carries the affordance when the underline
                 is at rest, so no persistent underline is needed.
   .link-text  — inline/contact. Keeps a permanent hairline underline so it
                 is identifiable as a link without relying on colour.
   ========================================================================== */

a { color: inherit; }

.link-arrow {
  display: inline-flex;
  align-items: baseline;
  gap: 0.55em;
  text-decoration: none;
  color: var(--ink);
  padding-bottom: 0.14em;
  background-image: linear-gradient(var(--oxblood), var(--oxblood));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size var(--dur) var(--ease), color 0.35s var(--ease);
}

.link-arrow .arrow {
  display: inline-block;
  transition: transform var(--dur) var(--ease);
}

.link-arrow:hover,
.link-arrow:focus-visible {
  color: var(--oxblood);
  background-size: 100% 1px;
}

.link-arrow:hover .arrow,
.link-arrow:focus-visible .arrow { transform: translateX(4px); }

.link-text {
  text-decoration: none;
  color: var(--ink);
  padding-bottom: 0.1em;
  background-image: linear-gradient(var(--hairline), var(--hairline));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 1px;
  transition: background-image 0.35s var(--ease), color 0.35s var(--ease);
}

.link-text:hover,
.link-text:focus-visible {
  color: var(--oxblood);
  background-image: linear-gradient(var(--oxblood), var(--oxblood));
}

/* The only button on the site. Thin border, no fill, no radius to speak of,
   no shadow. Inverts to ink on hover. */
.btn {
  display: inline-block;
  padding: 1rem 2.5rem;
  border: 1px solid var(--ink);
  border-radius: 2px;
  background: transparent;
  color: var(--ink);
  font-size: var(--step-label);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color 0.35s var(--ease), color 0.35s var(--ease);
}

.btn:hover:not(:disabled) { background: var(--ink); color: var(--bone); }
.btn:disabled { opacity: 0.45; cursor: default; }


/* 07. MOTION ================================================================
   One IntersectionObserver adds .is-visible. Children stagger via --i.
   Restrained: 14px of travel, no bounce, no parallax, no scroll-jacking.
   ========================================================================== */

.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity var(--dur) var(--ease),
    transform var(--dur) var(--ease);
  transition-delay: calc(var(--i, 0) * 80ms);
}

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

/* Hero rule draws itself once on load. */
.hero-rule {
  height: 1px;
  width: 0;
  background: var(--oxblood);
  transition: width 1.4s var(--ease) 0.35s;
}
.hero.is-visible .hero-rule { width: min(22rem, 60%); }

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

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
  }

  /* Nothing may stay hidden when motion is off. */
  .reveal { opacity: 1; transform: none; }
  .hero-rule { width: min(22rem, 60%); }
}


/* 08. GRAIN OVERLAY =========================================================
   Keeps flat bone from reading as an unstyled page. Inline feTurbulence,
   ~0.5KB, no network request, never intercepts pointer events.
   ========================================================================== */

.grain {
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 180px 180px;
}


/* 09. HEADER & NUMBERED NAV =================================================
   Index-style navigation, not a nav bar. Real anchors — works without JS.
   Desktop: fixed top row. Mobile: wordmark stays top, index moves to a
   bottom-anchored row. No hamburger, no overlay menu.
   ========================================================================== */

/* The wordmark and the index are two independently positioned fixed
   elements (see the note in index.html for why they can't be nested).
   Rather than try to make their line boxes agree — inline text against an
   inline-flex link, which does not work — both get the SAME height and
   centre their own contents. That makes them share a centre line by
   construction, whatever the type metrics do. */
.site-header,
.index-nav {
  position: fixed;
  top: 0;
  height: var(--header-h);
  display: flex;
  align-items: center;
  padding: 0 var(--gutter);
  /* The header's hairline is transparent until it sticks; the nav carries a
     matching one purely so both boxes are the same total height and centre
     on exactly the same line. */
  border-bottom: 1px solid transparent;
}

.site-header {
  left: 0;
  right: 0;
  z-index: 50;
  gap: var(--gutter-col);
  transition: background-color 0.4s var(--ease), border-color 0.4s var(--ease);
  border-bottom: 1px solid transparent;
}

.index-nav {
  right: 0;
  z-index: 51; /* above the header's backdrop */
}

/* Applied by JS once the hero has scrolled past. */
.site-header.is-stuck {
  background: rgba(244, 241, 234, 0.92);
  backdrop-filter: blur(8px);
  border-bottom-color: var(--hairline-soft);
}

.wordmark {
  font-family: var(--sans);
  font-size: var(--step-label);
  font-weight: 600;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  white-space: nowrap;
  /* Matches .index-nav a. The wordmark and the index sit in two separate
     fixed elements, so their line boxes have to be pinned to the same
     height or they don't share a baseline — inheriting the body's 1.7
     left them 9px apart on desktop. */
  line-height: 1;
}

.index-nav ul {
  display: flex;
  align-items: center;
  gap: clamp(1.25rem, 2.5vw, 2.75rem);
}

/* Each item is a flex container so its height is the link's height and
   nothing more. As plain list items they inherited the body's 19px font
   size and 1.7 line-height, producing a 32px strut that the 11px link then
   sat low inside — which is what knocked the index out of line with the
   wordmark even after both bars were given a matching height. */
.index-nav li { display: flex; }

.index-nav a {
  display: inline-flex;
  align-items: baseline;
  gap: 0.5em;
  font-size: var(--step-label);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  line-height: 1; /* see .wordmark */
  transition: color 0.35s var(--ease);
}

.index-nav .num {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  transition: color 0.35s var(--ease);
}

.index-nav a:hover .num,
.index-nav a:focus-visible .num { color: var(--ink); }

/* Active section — the accent's first job. */
.index-nav a[aria-current='true'] .num { color: var(--oxblood); }

.index-nav .nav-word { transition: opacity 0.35s var(--ease); }


/* 10. HERO ==================================================================
   Full-bleed bone. Headline sits in the lower-left third — the asymmetry
   is deliberate, a centred hero is the thing we are avoiding.

   TO ADD A REAL BACKGROUND IMAGE LATER: set --section-bg-image on .hero,
   e.g.  .hero { --section-bg-image: url('../assets/hero.avif'); }
   The scrim below is already in place to protect text contrast.
   ========================================================================== */

.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding-block: 8rem clamp(3rem, 8vh, 6rem);
  overflow: hidden;
}

.hero::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--section-bg-image, none);
  background-size: cover;
  background-position: center;
}

/* Only paints when an image is actually set — keeps the bone hero clean. */
.hero[style*='--section-bg-image']::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    to top,
    rgba(244, 241, 234, 0.96) 0%,
    rgba(244, 241, 234, 0.72) 45%,
    rgba(244, 241, 234, 0.4) 100%
  );
}

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

.hero h1 {
  font-size: var(--step-hero);
  line-height: 0.98;
  /* Overrides the balance inherited from the h1/h2/h3 rule. Balancing a
     four-line display headline evens the line lengths out, which here
     splits "independent businesses" across two lines. The measure below
     does the line-breaking instead, and scales with the font size because
     it is set in ch. */
  text-wrap: pretty;
  max-width: 24ch;
}

/* "Built properly." drops to its own line and carries the accent rule. */
.hero h1 .emphasis {
  display: block;
  font-style: italic;
}

.hero-rule-wrap { margin-top: clamp(1.75rem, 4vh, 2.75rem); }

.hero-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem 2rem;
  margin-top: clamp(2.5rem, 6vh, 4.5rem);
}

.hero-foot p {
  color: var(--muted);
  font-size: var(--step-small);
  max-width: 34ch;
  line-height: 1.6;
}

.scroll-cue {
  font-size: var(--step-label);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}


/* 11. SECTION FURNITURE ===================================================== */

.section-head {
  display: flex;
  align-items: baseline;
  gap: 1.25rem;
  padding-bottom: 1.5rem;
  margin-bottom: clamp(3rem, 8vh, 6rem);
  border-bottom: 1px solid var(--hairline);
}

.section-head h2 {
  font-size: var(--step-h2);
  flex: 1 1 auto;
}

.section-head .label { flex: 0 0 auto; }


/* 12. THE WORK ==============================================================
   Asymmetric grid. Five entries, no two rows sharing a rhythm — varied
   spans, varied aspect ratios, two entries offset downward. Explicitly not
   a uniform 3-column card grid.
   ========================================================================== */

.work-grid { row-gap: clamp(4rem, 10vh, 9rem); align-items: start; }

.work-item { position: relative; }

/* Whole entry is clickable via the stretched pseudo-element on the title
   link, so there is one link per entry rather than three overlapping ones. */
.work-item:focus-within { outline: 2px solid var(--oxblood); outline-offset: 1.25rem; }
.work-item:focus-within .work-title-link { outline: none; }

.work-title-link { text-decoration: none; color: inherit; }
.work-title-link::after { content: ''; position: absolute; inset: 0; z-index: 2; }

/* Placeholder panel. Holds exact layout, so dropping in a real screenshot
   causes zero layout shift. The oversized numeral keeps it looking
   designed rather than broken. */
.work-media {
  position: relative;
  display: grid;
  place-items: center;
  overflow: hidden;
  background-color: var(--bone-deep);
  border: 1px solid var(--hairline);
  /* Wide and faint — a drafting-paper texture, not graph paper. At 56px and
     full hairline strength this read as a wireframe rather than a considered
     placeholder. */
  background-image:
    repeating-linear-gradient(to right, rgba(20, 20, 20, 0.045) 0 1px, transparent 1px 88px),
    repeating-linear-gradient(to bottom, rgba(20, 20, 20, 0.045) 0 1px, transparent 1px 88px);
  transition: opacity 0.5s var(--ease);
}

.work-item:hover .work-media { opacity: 0.82; }

.work-media-num {
  font-family: var(--serif);
  font-size: clamp(3rem, 9vw, 7rem);
  line-height: 1;
  color: var(--ink);
  opacity: 0.11;
  font-variant-numeric: tabular-nums;
}

/* Real images inherit the aspect box exactly — see the swap comments
   in index.html. */
.work-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.work-body {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1.25rem;
  margin-top: 1.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--hairline);
}

.work-title {
  font-size: var(--step-h3);
  flex: 1 1 auto;
  min-width: 0;
}

.work-meta {
  color: var(--muted);
  font-size: var(--step-small);
  letter-spacing: 0.02em;
}

/* The CTA is a <span>, not a second link — the entry already has exactly one
   link. So its animation is driven by the parent's hover/focus state rather
   than its own, which keeps one link per entry for screen readers while
   still giving the whole card a hover response. */
.work-cta { margin-top: 0.75rem; flex-basis: 100%; font-size: var(--step-small); }

.work-item:hover .work-cta,
.work-item:focus-within .work-cta {
  color: var(--oxblood);
  background-size: 100% 1px;
}

.work-item:hover .work-cta .arrow,
.work-item:focus-within .work-cta .arrow { transform: translateX(4px); }

.work-title-link {
  background-image: linear-gradient(var(--oxblood), var(--oxblood));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size var(--dur) var(--ease);
  padding-bottom: 0.06em;
}

.work-item:hover .work-title-link,
.work-item:focus-within .work-title-link { background-size: 100% 1px; }


/* --- Collapsed state ---------------------------------------------------
   Stands in for the grid while there are no confirmed projects to publish.
   Everything above is left intact and unused, so restoring the grid is a
   paste with no CSS changes — see .parked/work-entries.html.

   Kept to a narrow measure and given real vertical room: a short line
   floating in a section-sized gap reads as a page that failed to load,
   whereas a deliberate measure with a CTA under it reads as a choice. */
.work-pending {
  max-width: 42ch;
  padding-bottom: clamp(2rem, 6vh, 4rem);
}

.work-pending-line {
  font-family: var(--serif);
  font-size: var(--step-h3);
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin-bottom: 1.25rem;
}

.work-pending-note {
  color: var(--muted);
  margin-bottom: 1.75rem;
}


/* 13. FULL-BLEED BANDS ======================================================
   These replace the brief's full-bleed photography. Same structural job —
   a full-width tonal break punctuating the page — at zero image weight.

   TO USE A REAL PHOTOGRAPH: set --section-bg-image on the band, e.g.
   <section class="band" style="--section-bg-image:url('../assets/break-01.avif')">
   The ink background then acts as the scrim behind it.
   ========================================================================== */

.band {
  position: relative;
  background-color: var(--ink);
  background-image: var(--section-bg-image, none);
  background-size: cover;
  background-position: center;
  color: var(--bone);
  padding-block: clamp(6rem, 16vh, 11rem);
  overflow: hidden;
}

/* Darkening scrim, only painted when an image is present. */
.band[style*='--section-bg-image']::before {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(20, 20, 20, 0.62);
}

.band > * { position: relative; }

/* Targets the statement by class, not by element. A bare `.band p` rule
   outranks `.label` on specificity and blows the eyebrow up to headline
   size — which is exactly what it did before this was scoped. */
.band-statement {
  font-family: var(--serif);
  font-size: var(--step-h2);
  line-height: 1.12;
  letter-spacing: -0.02em;
  max-width: 22ch;
}

.band .label { color: rgba(244, 241, 234, 0.62); margin-bottom: 2rem; }
.band em { font-style: italic; color: var(--oxblood-light); }


/* 14. PROCESS ===============================================================
   An editorial numbered list. Deliberately not icon cards, not a
   three-across feature grid.
   ========================================================================== */

/* No border-top here — the section head above already ends in a hairline,
   and two parallel rules 70px apart read as a mistake. Each row's
   border-bottom carries the ruling from here down. */
.process-list { margin-top: -1rem; }

.process-list li {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 7fr);
  gap: var(--gutter-col);
  align-items: start;
  padding-block: clamp(2.5rem, 6vh, 3.5rem);
  border-bottom: 1px solid var(--hairline);
}

.process-num {
  font-family: var(--serif);
  font-size: clamp(2.5rem, 5vw, 4.5rem);
  line-height: 0.85;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.process-step h3 {
  font-size: var(--step-h3);
  margin-bottom: 0.85rem;
}

.process-step p {
  color: var(--muted);
  max-width: 54ch;
}


/* 15. STUDIO ================================================================ */

.studio-inner {
  grid-column: 3 / span 8;
  max-width: 58ch;
}

.studio-quote {
  font-family: var(--serif);
  font-size: var(--step-h2);
  line-height: 1.14;
  letter-spacing: -0.02em;
  margin-bottom: 2.25rem;
  text-wrap: balance;
}

.studio-inner p + p { margin-top: 1.5rem; }
.studio-inner .body-copy { color: var(--muted); }

.studio-sign {
  margin-top: 2.75rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--hairline);
}


/* 16. CONTACT =============================================================== */

.contact-form-col { grid-column: 1 / span 6; }
.contact-detail-col { grid-column: 8 / span 5; }

.field { margin-bottom: 2.75rem; }

/* Persistent labels — never placeholder-as-label. */
.field label {
  display: block;
  margin-bottom: 0.75rem;
}

/* Underline-only inputs. No box, no fill, no radius. */
.field input,
.field textarea {
  width: 100%;
  padding: 0.5rem 0 0.75rem;
  border: 0;
  border-bottom: 1px solid var(--hairline);
  background: transparent;
  font-size: var(--step-body);
  border-radius: 0;
  transition: border-color 0.35s var(--ease);
}

.field textarea { resize: vertical; min-height: 7rem; }

.field input:focus,
.field textarea:focus {
  outline: none;
  border-bottom-color: var(--oxblood);
}

/* Focus ring for keyboard users specifically — the border alone is colour-only. */
.field input:focus-visible,
.field textarea:focus-visible {
  outline: 2px solid var(--oxblood);
  outline-offset: 4px;
}

/* Errors are always text, never colour alone. */
.field-error {
  display: block;
  margin-top: 0.6rem;
  font-size: var(--step-small);
  color: var(--oxblood);
  min-height: 0;
}

.field input[aria-invalid='true'],
.field textarea[aria-invalid='true'] { border-bottom-color: var(--oxblood); }

.form-status {
  margin-top: 1.5rem;
  font-size: var(--step-small);
  color: var(--muted);
}
.form-status:empty { margin-top: 0; }

.contact-detail-col dt { margin-bottom: 0.75rem; }
.contact-detail-col dd {
  margin: 0 0 2.25rem;
  font-size: var(--step-lead);
  letter-spacing: -0.01em;
}
.contact-detail-col dd:last-of-type { margin-bottom: 0; }

/* Supporting notes sit at body size — the lead size above is reserved for
   the things a visitor might actually want to copy down. */
.contact-detail-col .detail-note {
  font-size: var(--step-body);
  line-height: 1.6;
  letter-spacing: 0;
  color: var(--muted);
  max-width: 34ch;
}


/* 17. FOOTER ================================================================ */

.site-footer {
  border-top: 1px solid var(--hairline);
  padding-block: 3rem;
}

.site-footer .wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 2rem;
}

.site-footer .label { color: var(--muted); }


/* 18. RESPONSIVE ============================================================
   Mobile-first would mean writing the small layout unprefixed; this file
   instead keeps the desktop grid definitions above and unwinds them here,
   which for a single page is far fewer rules and easier to read. Every
   layout below 900px is single-column.
   ========================================================================== */

/* --- Tablet ---------------------------------------------------------- */
@media (max-width: 900px) {
  .studio-inner { grid-column: 1 / -1; }

  .contact-form-col,
  .contact-detail-col { grid-column: 1 / -1; }

  .contact-detail-col { margin-top: 4rem; }

  .process-list li {
    grid-template-columns: 1fr;
    gap: 1rem;
  }

  .process-num { line-height: 1; }
}

/* --- Mobile ---------------------------------------------------------- */
@media (max-width: 720px) {
  /* Every work entry goes full width in source order; the desktop
     offsets are removed entirely. */
  .work-item {
    grid-column: 1 / -1 !important;
    margin-top: 0 !important;
  }

  .work-item:focus-within { outline-offset: 0.75rem; }

  /* Index nav moves to a bottom-anchored row. No hamburger. */
  :root { --header-h: 3.75rem; }

  .index-nav {
    top: auto;
    bottom: 0;
    height: auto;
    left: 0;
    right: 0;
    background: rgba(244, 241, 234, 0.94);
    backdrop-filter: blur(8px);
    border-top: 1px solid var(--hairline);
    padding: 0.9rem var(--gutter);
  }

  .index-nav ul {
    justify-content: space-between;
    gap: 0.4rem;
  }

  /* Words stay visible here. Four bare numerals tell a first-time visitor
     nothing about where they lead — tightening the size and tracking buys
     enough room for the labels at 390px, which is worth more than keeping
     the wide tracking. */
  .index-nav a {
    gap: 0.35em;
    font-size: 0.625rem;
    letter-spacing: 0.1em;
  }

  .index-nav .num { color: var(--muted); }

  /* Clears the fixed bottom index so the footer is never trapped under it. */
  body { padding-bottom: 4rem; }

  .hero { padding-block: 6rem 4rem; }
  .hero-foot { flex-direction: column; align-items: flex-start; }

  .section-head {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
  }

  .btn { width: 100%; }
}

/* --- Print ------------------------------------------------------------ */
@media print {
  .site-header, .index-nav, .grain, .scroll-cue, .btn { display: none; }
  .reveal { opacity: 1; transform: none; }
  body { background: #fff; color: #000; }
}
