/* ==========================================================================
   NewLine Break — sections
   Work, process, studio, contact. The opening lives in hero.css and the two
   scroll scenes in story.css.
   ========================================================================== */

/* Section headings reuse the hero's mask. Same device at a quieter scale, so
   it reads as one system rather than a second idea. */
.head-line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
}

.head-line-in { display: block; }

.js .head.reveal,
.js .contact__title.reveal { opacity: 1; transform: none; }

.js .head-line-in {
  transform: translateY(105%);
  transition: transform 0.95s var(--ease);
}

.js .head.is-in .head-line-in,
.js .contact__title.is-in .head-line-in { transform: none; }

/* --------------------------------------------------------------------------
   Selected work

   Real engagements, each shown with its own documents. The copy holds still
   on the left while the drawings pass on the right, so each sheet is read
   against the description of the system it belongs to.
   -------------------------------------------------------------------------- */

.case {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(2.5rem, 6vw, 6rem);
  align-items: start;
}

/* The next engagement starts under a hairline, far enough down that the one
   before it has let go of its copy. */
.case + .case {
  margin-top: clamp(4rem, 9vw, 8rem);
  padding-top: clamp(3rem, 6vw, 5rem);
  border-top: 1px solid var(--line-lit);
}

.case__text {
  position: sticky;
  top: 7.5rem;
}

.case__meta {
  display: flex;
  gap: 0.6rem;
  font-size: 0.6875rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--signal-lit);
  margin-bottom: 1.5rem;
}

.case__title {
  font-size: clamp(1.625rem, 1.2rem + 1.6vw, 2.5rem);
  font-variation-settings: 'wdth' 100, 'wght' 600;
  margin-bottom: 1rem;
}

.case__body {
  max-width: 46ch;
  color: var(--fog);
  font-size: clamp(1rem, 0.95rem + 0.3vw, 1.125rem);
}

/* A claim the reader can go and check, so it has to look like a link. */
.case__body a {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--signal-lit);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
  transition: color 0.3s var(--ease);
}

@media (hover: hover) {
  .case__body a:hover { color: var(--signal-lit); }
}

/* What was built, layer by layer. Label left, statement right, hairlines
   between: a parts list, not a feature list. */
.facts {
  margin-top: 2rem;
  border-top: 1px solid var(--line-lit);
}

.fact {
  display: grid;
  grid-template-columns: 7.5rem minmax(0, 1fr);
  gap: 1rem;
  padding: 0.95rem 0;
  border-bottom: 1px solid var(--line-lit);
}

.fact__label {
  padding-top: 0.2rem;
  font-size: 0.6875rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fog-dim);
}

.fact__value {
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--text);
}

.stack {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: 0.4rem;
  padding-top: 1.5rem;
}

.stack li {
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--line-lit);
  border-radius: 2px;
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--fog);
}

/* Plates: the project's documents, framed. */
.plates {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.5rem, 2.5vw, 2.25rem) clamp(1rem, 2vw, 1.5rem);
}

.plate { margin: 0; min-width: 0; }
.plate--wide { grid-column: 1 / -1; }

/* Two kinds of document, two treatments, one frame. A model keeps its real
   colour and stands on the panel with room around it. A drawing is line work,
   already set in the page's own line colour, and fills its frame. */
.plate__frame {
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 2px;
  background: var(--raised);
}

.plate img {
  display: block;
  width: 100%;
  height: auto;
}

.plate--model .plate__frame { padding: clamp(1.25rem, 3vw, 2.5rem); }

/* Two sheets side by side share one frame shape, whatever shape the drawings
   are. Contained, never cropped: a cropped drawing is a wrong drawing. */
.plate:not(.plate--wide) .plate__frame { aspect-ratio: 5 / 4; }

.plate:not(.plate--wide) img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* The wide model is not stretched to the frame: it is shown at its own size,
   centred, so a small render is never blown up soft. */
.plate--wide.plate--model img {
  width: auto;
  max-width: min(100%, 34rem);
  margin-inline: auto;
}

/* A drawn figure is a sheet too. It stands on the ground the other figures are
   drawn on, and is composed as one column so its labels are still read on a
   phone: narrow by design, never scaled down to fit. */
.plate--figure .plate__frame {
  padding: clamp(1.5rem, 4vw, 3rem) clamp(0.5rem, 3vw, 2.5rem);
  background: var(--ground);
}

.fig--pool,
.fig--failover {
  max-width: 27rem;
  margin-inline: auto;
}

/* --------------------------------------------------------------------------
   Process — a real sequence, so the numbering carries information
   -------------------------------------------------------------------------- */

.process__head {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(2rem, 6vw, 6rem);
  align-items: end;
  margin-bottom: clamp(3rem, 6vw, 5rem);
}

.process__head .head { margin-bottom: 0; }

/* The way in for a team that is not ready to commit to a build. Set as an
   aside to the heading: it is an alternative to the sequence, not part of it. */
.review {
  padding-left: 1.5rem;
  border-left: 1px solid var(--line-lit);
}

.review__title {
  font-size: 1.125rem;
  font-variation-settings: 'wdth' 98, 'wght' 600;
  letter-spacing: -0.01em;
  margin-bottom: 0.6rem;
}

.review__body {
  max-width: 40ch;
  color: var(--fog);
  font-size: 0.9375rem;
  line-height: 1.7;
}

.steps {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(2rem, 4vw, 3.5rem);
}

.step { padding-top: 1.75rem; border-top: 1px solid var(--line-lit); }

.step__num {
  font-size: 0.8125rem;
  letter-spacing: 0.2em;
  color: var(--signal-lit);
  margin-bottom: 2rem;
}

.step__title {
  font-size: 1.5rem;
  font-variation-settings: 'wdth' 100, 'wght' 600;
  margin-bottom: 0.85rem;
}

.step__body {
  color: var(--fog);
  font-size: 0.9375rem;
  line-height: 1.75;
}

/* --------------------------------------------------------------------------
   Studio
   -------------------------------------------------------------------------- */

.studio {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(2.5rem, 6vw, 6rem);
  align-items: end;
}

.studio__text .lede { margin-bottom: 1.75rem; }

.studio__text p:not(.lede):not(.eyebrow) {
  color: var(--fog);
  margin-bottom: 1.5rem;
  max-width: 58ch;
}

.studio__text p:last-child { margin-bottom: 0; }

/* Terms, set as a readout: what a client can hold the studio to. */
.terms {
  display: grid;
  gap: 1px;
  background: var(--line);
  border-block: 1px solid var(--line);
}

.term {
  background: var(--strata);
  padding: 1.6rem 0 1.7rem;
}

.term__label {
  font-size: 0.6875rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fog-dim);
  margin-bottom: 0.7rem;
}

.term__value {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.2em 0.9rem;
  font-size: clamp(2.25rem, 1.8rem + 1.8vw, 3.25rem);
  font-variation-settings: 'wdth' 100, 'wght' 600;
  line-height: 1;
  letter-spacing: -0.04em;
}

/* Units sit on the baseline. A superscript unit reads as a footnote marker. */
.term__unit {
  font-family: var(--mono);
  font-size: 0.8125rem;
  font-variation-settings: normal;
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0.04em;
  color: var(--fog);
}

/* --------------------------------------------------------------------------
   Contact
   -------------------------------------------------------------------------- */

.band--contact {
  padding-bottom: clamp(6rem, 12vh, 10rem);
}

.contact__title {
  font-size: clamp(2.25rem, 1.1rem + 2.8vw, 4rem);
  font-variation-settings: 'wdth' 100, 'wght' 620;
  letter-spacing: -0.036em;
  max-width: 16ch;
  margin-bottom: 1.5rem;
}

.contact__lede {
  color: var(--fog);
  max-width: 52ch;
  font-size: clamp(1.0625rem, 1rem + 0.35vw, 1.1875rem);
  margin-bottom: clamp(2rem, 4vw, 3rem);
}

/* The form is a sheet to fill in: the raised panel a drawing stands on, with
   fields ruled like a paper form. Two fields, one of them optional. */
.sheet {
  max-width: 34rem;
  padding: clamp(1.5rem, 3vw, 2.25rem);
  border: 1px solid var(--line);
  border-radius: 2px;
  background: var(--raised);
}

.sheet__trap { display: none; }

.field + .field { margin-top: 1.75rem; }

.field__label {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.6875rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fog-dim);
}

/* 18px: iOS zooms the page into any field set smaller than 16. */
.field__input {
  display: block;
  width: 100%;
  margin-top: 0.4rem;
  padding: 0.55rem 0;
  border: 0;
  border-bottom: 1px solid var(--line-lit);
  border-radius: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 1.125rem;
  line-height: 1.5;
  transition: border-color 0.2s var(--ease);
}

textarea.field__input {
  min-height: 5.5rem;
  resize: vertical;
}

.field__input:focus { border-bottom-color: var(--signal); }

.sheet__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
  margin-top: 2rem;
}

.sheet__note {
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fog-dim);
}

.btn[aria-disabled="true"] {
  opacity: 0.6;
  cursor: progress;
}

.sheet__terms {
  margin-top: 1rem;
  font-size: 0.8125rem;
  color: var(--fog-dim);
}

/* What happened, said in place. It stays in the page while empty: a live
   region that is taken out and put back is often not read out. */
.sheet__status { margin-top: 1.25rem; }
.sheet__status:empty { margin-top: 0; }

.sheet__status a {
  border-bottom: 1px solid var(--signal);
  color: var(--signal-lit);
}

/* Sent: the fields have done their job and leave the sheet to the answer. */
.sheet[data-state="sent"] .field,
.sheet[data-state="sent"] .sheet__foot,
.sheet[data-state="sent"] .sheet__terms { display: none; }

.sheet[data-state="sent"] .sheet__status,
.sheet--sent {
  margin-top: 0;
  font-size: clamp(1.0625rem, 1rem + 0.35vw, 1.1875rem);
}

/* The same answer without scripting: the service sends the browser back to
   #sent, and this line takes the form's place. With scripting the form
   answers for itself, so a link to #sent changes nothing. */
.sheet--sent { display: none; }
html:not(.js) .sheet--sent:target { display: block; }
html:not(.js) .contact:has(.sheet--sent:target) form.sheet { display: none; }

.contact__alt {
  margin-top: clamp(1.75rem, 3vw, 2.5rem);
  color: var(--fog);
}

/* The address, for anyone who would rather write. The form is the first
   thing asked, so this is body-sized; the break still underlines it. */
.contact__mail {
  font-variation-settings: 'wdth' 100, 'wght' 600;
  color: var(--text);
  word-break: break-word;
  background-image: linear-gradient(var(--break), var(--break));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 2px;
  transition: background-size 0.5s var(--ease), color 0.3s var(--ease);
}

@media (hover: hover) {
  .contact__mail:hover { background-size: 100% 2px; }
}

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 1080px) {
  .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .studio { grid-template-columns: minmax(0, 1fr); align-items: start; }
  .process__head { grid-template-columns: minmax(0, 1fr); align-items: start; }

  .case { grid-template-columns: minmax(0, 1fr); }
  .case__text { position: static; }
}

@media (max-width: 720px) {
  .steps { grid-template-columns: minmax(0, 1fr); }

  .plates { grid-template-columns: minmax(0, 1fr); }
  .fact { grid-template-columns: minmax(0, 1fr); gap: 0.35rem; }
}

/* ==========================================================================
   Motion layer
   Every animation below has one job. If you cannot state the job in a
   sentence, delete it rather than keep it.
   All of it is gated on .js so the page stays complete without scripting,
   and the reduced-motion block in tokens.css collapses it to static.
   ========================================================================== */

/* 1. Process steps. Job: hierarchy. Reading order is left to right, so the
   row resolves in that order instead of snapping in whole. */
.js .step.reveal:nth-child(2) { transition-delay: 0.09s; }
.js .step.reveal:nth-child(3) { transition-delay: 0.18s; }

/* 2. Plates. Job: arrival. Each sheet is uncovered from its top edge as it
   scrolls in, the way a drawing is slid out of a folder. */
.js .plate.reveal .plate__frame { clip-path: inset(0 0 100% 0); }

.js .plate.reveal.is-in .plate__frame {
  clip-path: inset(0 0 0 0);
  transition: clip-path 1.1s var(--ease) 0.1s;
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* 3. The gutter rail draws as the section passes. Job: storytelling. The
       rail is the mark at page scale, so it should be drawn rather than simply
       present. Drawn with background-size, not scaleY: the break node lives on
       this element's pseudo-elements, and a transform would squash it along
       with the line. Backgrounds do not affect pseudo-element children. */
    .js .band__rail {
      background-repeat: no-repeat;
      animation: rail-draw linear both;
      animation-timeline: view();
      animation-range: entry 10% cover 45%;
    }

    @keyframes rail-draw {
      from { background-size: 100% 0%; }
      to   { background-size: 100% 100%; }
    }
  }

  /* 4. The process line. Job: storytelling. Three stages in a fixed order, so
     the rule above them is drawn in that order as the section arrives. Only
     where the three sit in one row; stacked, a single rule means nothing. */
  @media (prefers-reduced-motion: no-preference) and (min-width: 1081px) {
    .steps::after {
      content: '';
      position: absolute;
      inset: 0 0 auto 0;
      height: 1px;
      background: var(--signal-lit);
      transform-origin: left center;
      animation: steps-run linear both;
      animation-timeline: view();
      animation-range: entry 35% cover 55%;
    }

    @keyframes steps-run {
      from { transform: scaleX(0); }
      to   { transform: scaleX(1); }
    }
  }
}
