/* ==========================================================================
   STUDIO BITS. The rules the studio sections need, on top of styles.css.
   Only what the magazine stylesheet does not already carry: the three
   products, the dark argument band, the testimonial, the entrance, and the
   line under the headline. Everything else, cards, fields, reveal and the
   whole palette, is already there, which is why the two halves sit
   together without a seam.
   ========================================================================== */
:root { --pink-ink: #A81F86; }

/* The sentence the whole offer rests on, set apart from the lede rather
   than buried at the end of it. */
.hero-spine {
  font-family: var(--font-display); font-size: clamp(1.6rem, 3.2vw, 2.6rem);
  line-height: 1.02; text-transform: uppercase; letter-spacing: .01em;
  color: var(--yellow);
  margin-top: clamp(18px, 2.4vw, 26px);
  margin-bottom: clamp(34px, 4.4vw, 48px);
}

/* ----------------------------------------------------------------- OFFERS
   Three products, not a menu of deliverables: every one of them is thinking
   sold as thinking, which is the only kind of thing a studio with no
   portfolio yet can honestly put a price on. Side by side, because the whole
   proposition is that you choose how much of us you want beside your team,
   not what you want made. */
.head { display: grid; gap: 14px; margin-bottom: clamp(26px, 4vw, 44px); position: relative; }

.offers { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(14px, 1.8vw, 22px); }
/* Each part is a way in, not a poster: the whole card is the link to the
   brief, carrying which part was clicked so the enquiry arrives knowing
   what caught their eye. Nobody is asked to pick a package; the page just
   remembers where they came from. */
.offer { display: block; height: 100%; text-decoration: none; color: inherit; }
.offer-face {
  display: flex; flex-direction: column; gap: 8px; height: 100%;
  padding: clamp(22px, 2.6vw, 30px);
  background: var(--cream); border: var(--border-w); border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  transition: transform .16s ease, box-shadow .16s ease, background .16s ease;
}
.offer:hover .offer-face,
.offer:focus-visible .offer-face { transform: translate(-3px, -3px); box-shadow: var(--shadow); }
.offer:focus { outline: none; }
.offer:focus-visible .offer-face { outline: 3px solid var(--accent); outline-offset: 3px; }

/* The cue sits on the bottom edge of every card, so the three line up
   however long the copy above them runs. */
.offer-go {
  margin-top: auto; padding-top: clamp(14px, 1.8vw, 20px);
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-mono); font-size: .66rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--accent);
}
.offer-go svg {
  width: 16px; height: 16px; fill: none; stroke: currentColor;
  stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round;
  transition: transform .16s ease;
}
.offer:hover .offer-go svg { transform: translateX(4px); }
@media (prefers-reduced-motion: reduce) {
  .offer:hover .offer-face, .offer:focus-visible .offer-face { transform: none; }
  .offer:hover .offer-go svg { transform: none; }
}

.offer-name {
  font-family: var(--font-display); font-size: clamp(1.4rem, 2.4vw, 1.95rem);
  line-height: 1.02; letter-spacing: .02em; text-transform: uppercase; color: var(--accent);
}
.offer-kind {
  font-family: var(--font-mono); font-size: .66rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; opacity: .55;
}
.offer-copy { font-size: .97rem; line-height: 1.55; margin-top: 6px; }

/* The line under the three, and the way through to the brief. */
.pick-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 16px 22px;
  margin-top: clamp(26px, 3.6vw, 38px);
}
.pick-count { font-size: .98rem; opacity: .7; }

@media (max-width: 900px) { .offers { grid-template-columns: 1fr; } }


/* ----------------------------------------------------------------- WHEN
   Four situations instead of a definition. The heading opens the sentence
   and each line finishes it, so they are set lower case and read as one
   run rather than four headlines competing.

   Deliberately not cards: the page already has cards for the three parts
   and cards for the quotes, and a third set would turn a list of symptoms
   into a third product grid. Hairlines and type, nothing else. */
.when { background: var(--cream); border-block: var(--border-w); }
.when-head { margin-bottom: clamp(18px, 2.6vw, 30px); }
/* Four slips pinned at four angles, which is the one arrangement that ties
   back to the hero film: pages pinned on a wall. It also does something a
   list cannot — four complaints in four boxes read as four different
   voices, rather than one list written about ourselves.

   Each rotation is different and all are under two degrees. Tilted text is
   harder to read than straight text, and four identical angles would just
   be a crooked grid. They flatten on a phone, where a slip fills the width
   and the tilt only costs legibility. */
.when-scatter {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(18px, 2.6vw, 30px);
  /* start, not stretch: a slip hugs its own words. Stretched to the row
     height they come out as four equal rectangles with the text stranded
     in the middle, which is a grid wearing a costume. */
  align-items: start;
  max-width: 920px;
}
.when-slip {
  position: relative; margin: 0;
  padding: clamp(18px, 2.2vw, 26px);
  background: var(--cream); border: var(--border-w); border-radius: 4px;
  box-shadow: var(--shadow);
  font-size: clamp(1rem, 1.6vw, 1.18rem); line-height: 1.45; font-weight: 500;
  max-width: none;   /* styles.css caps every p at 62ch */
}
.when-slip:nth-child(1) { transform: rotate(-1.6deg) translateY(6px); }
.when-slip:nth-child(2) { transform: rotate(1.3deg)  translateY(-14px); }
.when-slip:nth-child(3) { transform: rotate(.9deg)   translateY(-4px); }
.when-slip:nth-child(4) { transform: rotate(-1.1deg) translateY(-22px); }
/* The pin. One colour per slip, so no two notes look like the same hand. */
.when-slip::before {
  content: ''; position: absolute; top: -9px; left: 22px;
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--pin, var(--violet)); border: var(--border-w);
}
.when-slip:nth-child(2)::before { --pin: var(--yellow); }
.when-slip:nth-child(3)::before { --pin: var(--green-ink); }
.when-slip:nth-child(4)::before { --pin: var(--pink-ink); }
@media (max-width: 680px) {
  .when-scatter { grid-template-columns: 1fr; }
  .when-slip:nth-child(n) { transform: rotate(-1deg); }
  .when-slip:nth-child(even) { transform: rotate(1deg); }
}

.when-close {
  margin: clamp(22px, 3vw, 30px) 0 0;
  font-family: var(--font-mono); font-size: .74rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
}
.when-close a { color: var(--violet); text-underline-offset: 4px; }

/* ----------------------------------------------------------------- HOUR
   The one priced thing on the site, so it is the one filled panel: deep
   violet between two pale sections, carrying the only number a visitor
   will see. Copy on the left, the number and the way to buy on the right,
   stacked on a phone with the price first, because on a small screen the
   price is the question being asked.

   Not a card in the offers grid on purpose. The lede above says the brain
   comes in three parts; a fourth tile would contradict it. This is the
   first hour of any of the three. */
/* Its own band, not the tail of the one above. On the same paper as the
   three parts it read as a fourth item in that section, which is exactly
   what it must not be: the brain comes in three, and this is the way in
   rather than a part. Cream between two rules separates it, and keeps the
   page alternating — film, cream, paper, cream, ink. */
.hour { background: var(--cream); border-block: var(--border-w); }
.hour-card {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(20px, 2.6vw, 34px) clamp(22px, 3.4vw, 48px); align-items: start;
  padding: clamp(26px, 3.4vw, 40px) clamp(24px, 3.4vw, 44px);
  background: var(--deep); color: var(--cream);
  border: var(--border-w); border-radius: var(--radius); box-shadow: var(--shadow);
}
.hour-eyebrow { color: var(--yellow); margin-bottom: 10px; }
.hour-name {
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(1.9rem, 4vw, 2.8rem); line-height: 1;
  text-transform: uppercase; letter-spacing: .02em; margin: 0;
}
.hour-kind {
  font-family: var(--font-mono); font-size: .66rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; opacity: .7;
  margin: 8px 0 14px;
}
.hour-text { margin: 0 0 16px; font-size: 1rem; line-height: 1.55; max-width: 52ch; }

/* What lands in the inbox, in four lines. An unfamiliar service is bought
   on the strength of knowing what arrives, and "a direction in writing"
   was not that. The last line is what it is not: the commonest doubt
   about this studio is whether it also makes the thing. */
.hour-gets { list-style: none; margin: 0 0 16px; padding: 0; display: grid; gap: 9px; max-width: 52ch; }
.hour-gets li { position: relative; padding-left: 26px; font-size: .96rem; line-height: 1.45; }
.hour-gets li::before {
  content: ''; position: absolute; left: 0; top: .52em;
  width: 13px; height: 3px; border-radius: 2px; background: var(--yellow);
}
/* The fine print, which is doing the opposite of what fine print usually
   does. It spans the card because both halves are claims about the whole
   thing: what this is not, and the one promise we can keep without asking
   a buyer to judge whether the advice was any good. */
.hour-fine {
  /* styles.css caps every p at 62ch, which at this size is 500px and was
     stopping the rule halfway across the card. A line that spans the card
     has to say so. */
  grid-column: 1 / -1; max-width: none; margin: 0;
  border-top: 2px solid rgba(255, 255, 255, .2); padding-top: 16px;
  font-size: .88rem; line-height: 1.55; opacity: .74;
}
.hour-fine strong { font-weight: 700; opacity: 1; color: var(--yellow); }

.hour-buy { display: grid; justify-items: start; gap: 12px; }
.hour-price {
  display: flex; align-items: baseline; gap: 8px; margin: 0;
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(2.4rem, 5vw, 3.4rem); line-height: 1; color: var(--yellow);
}
.hour-from {
  font-family: var(--font-mono); font-size: .64rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--cream); opacity: .66;
}
.hour-note {
  margin: 0; font-family: var(--font-mono); font-size: .62rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; opacity: .6;
}
@media (max-width: 760px) {
  .hour-card { grid-template-columns: 1fr; }
}

/* -------------------------------------------------------------- PROCESS
   One torn ticket, five stubs, dashed perforations. It is one object
   rather than five, because it describes one engagement rather than five
   stages, and that is the whole reason this shape was chosen over a row
   of numbered circles.

   The last stub is yellow and says you build it. Every agency process
   diagram ends with the agency delivering; the colour makes it impossible
   to miss that this one does not.

   On paper, so the band sits between the cream of The Hour and the ink of
   the argument without two of either touching. */
.process { background: var(--paper); }
.ticket {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
  background: var(--cream); color: var(--ink);
  border: var(--border-w); border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;   /* keeps the yellow stub inside the rounded corner */
}
.stub {
  /* Column flex rather than grid, so the timing can be pushed to the foot
     of every stub with an auto margin. Left to flow, each one sat wherever
     its own description happened to end and the five times staggered down
     the ticket like a broken hem. */
  display: flex; flex-direction: column; gap: 9px;
  padding: clamp(20px, 2.4vw, 30px) clamp(15px, 1.8vw, 24px);
}
/* The perforation. A dashed rule, not a solid one: a ticket tears. */
.stub + .stub { border-left: 2.5px dashed rgba(28, 28, 28, .32); }
.stub:last-child { background: var(--yellow); }
.stub-n {
  font-family: var(--font-mono); font-size: .62rem; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase; color: var(--hue, var(--violet));
}
.stub:nth-child(2) .stub-n { --hue: var(--deep); }
.stub:nth-child(3) .stub-n { --hue: var(--green-ink); }
.stub:nth-child(4) .stub-n { --hue: var(--pink-ink); }
.stub:nth-child(5) .stub-n { --hue: var(--ink); }
.stub-t {
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(1.1rem, 2vw, 1.55rem); line-height: 1.02;
  text-transform: uppercase; letter-spacing: .02em;
}
.stub-d { margin: 0; max-width: none; font-size: .92rem; line-height: 1.45; }
.stub-w {
  margin: auto 0 0; max-width: none;
  font-family: var(--font-mono); font-size: .58rem; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; opacity: .52;
}
@media (max-width: 900px) {
  .ticket { grid-template-columns: 1fr; }
  .stub + .stub { border-left: none; border-top: 2.5px dashed rgba(28, 28, 28, .32); }
}

/* ------------------------------------------------------------- THE ARGUMENT
   One dark band, one claim. This is where the boldness is spent, so nothing
   else on the page needs to raise its voice. */
/* Deep violet, not ink. The paper band that used to separate this from the
   founder's letter went with the film, and two ink sections in a row read as
   one very long dark stretch. The letter keeps the ink; the argument takes
   the brand colour, so the seam is a change of colour rather than a 2.5px
   border nobody can see. Yellow and paper both carry on deep. */
.argument { background: var(--deep); color: var(--paper); border-block: var(--border-w); }
.argument .eyebrow { color: var(--yellow); }
.argument h2 { color: var(--paper); max-width: 22ch; margin-block: 14px 28px; }
/* Beats .argument p, which is the more specific selector of the two. */
.argument .pull {
  font-family: var(--font-display); font-size: clamp(1.6rem, 3.2vw, 2.5rem);
  line-height: 1.15; text-transform: uppercase; color: var(--yellow); max-width: 34ch;
}



/* ------------------------------------------------------------------ MARK
   A breath between the argument and the letter, and the one place the mark
   resolves on its own. Paper, because the film is nearly white: as a band
   it reads as a held beat, and behind words it would read as a fault.

   The band is empty while the animation is being replaced. These rules stay
   so putting the new one back is a matter of restoring the section and
   dropping the file inside .hero-reel. */
.mark { background: var(--paper); border-block: var(--border-w); }
.mark-inner { display: flex; justify-content: center; }
.hero-reel {
  width: 100%; max-width: 840px;
  border: var(--border-w); border-radius: var(--radius);
  box-shadow: var(--shadow); overflow: hidden; background: var(--cream);
}
.hero-reel video { width: 100%; height: auto; display: block; }

/* A phone number is useful and asking for it is not. Marked optional in the
   label, so nobody abandons the form over a field they did not want to
   fill, and nobody wonders whether they have to. */
/* Phone is not marked optional and is not enforced either: the label
   says nothing, a line under it says we will ring, and the step asks once
   before letting anyone past. The "optional" tag that used to sit here was
   an instruction to skip it. */
.field-note {
  margin: 6px 0 0; font-size: .82rem; line-height: 1.45; opacity: .62;
}
/* A nudge is not a failure, so it does not wear the error's colours. */
.form-error.soft {
  background: var(--cream); color: var(--ink);
  border-color: var(--ink); box-shadow: inset 4px 0 0 var(--violet);
}

/* ------------------------------------------------------------ THE STEPS
   One question at a time. The pane is given a floor so the card does not
   change height between steps, which is what makes a stepped form feel
   like it is lurching rather than turning a page. */
.step-count {
  font-family: var(--font-mono); font-size: .64rem; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase; opacity: .5;
  margin-bottom: 14px;
}
/* The three steps share one grid cell, so the card is always as tall as
   the tallest of them and never jumps when you move between them. That
   used to be a reserved min-height, a number guessed at one font size:
   it was 63px taller than the tallest step actually needs on a phone,
   and all of that slack sat under the fields pushing Next down into the
   corner where the sound pill floats, on top of the only control that
   screen has. Stacking measures instead of guessing, at any font.

   A hidden step keeps its box and loses its visibility, which also takes
   it out of the tab order and out of the way of clicks, so every field
   stays in the form for FormData and for the form's own validity check. */
.form-steps { display: grid; }
.step { grid-area: 1 / 1; display: block; }
.step[hidden] { visibility: hidden; }
.step-ask {
  font-family: var(--font-display); font-size: clamp(1.35rem, 2.4vw, 1.8rem);
  line-height: 1.05; text-transform: uppercase; letter-spacing: .01em;
  margin-bottom: 18px;
}
.step-nav { display: flex; align-items: center; gap: 12px; }
/* .btn sets display, and an author rule beats the hidden attribute, so the
   buttons for the other steps sat there in plain sight. */
.step-nav [hidden] { display: none; }
.step-back { flex: none; }

/* ------------------------------------------------------------ HERO, SMALL
   The hero hangs its copy off the bottom edge, which is right on a wide
   screen where the film has room beside the words. On a phone the film is
   behind them and the block is shorter than the plate, so all the slack
   piles up above the text: 156px of empty dark over the first line on a
   tall phone against 49 under the buttons.

   Centred instead, with the plate a little shorter, so the slack is split
   and the first line starts where the eye already is. */
@media (max-width: 760px) {
  .hero {
    align-items: center;
    min-height: clamp(460px, 70vh, 640px);
    padding-block: clamp(34px, 5vh, 54px);
  }
}

/* ------------------------------------------------------------------ SAID
   One quote, not a wall of them. A new studio with five testimonials reads
   as padding; one with a name on it reads as true.

   Cream and quiet on purpose. It sits straight after the argument, so the
   page claims a human understands what a human wants and then a human says
   so, and a quote that shouts would undo that.

   The whole thing is centred on a short measure, because the point of a
   testimonial is that somebody reads all of it. */
.said { background: var(--cream); border-block: var(--border-w); }
.said-head { text-align: center; justify-items: center;
  margin-bottom: clamp(20px, 3vw, 34px); }
.said-head h2 { max-width: 18ch; }

/* THE RAIL. The cards sit in one row you swipe, which is what a phone
   expects of a row of cards and what a laptop gets through the arrows,
   the dots, a trackpad or the arrow keys. Snap points mean it always
   comes to rest on a card rather than between two.

   Each card is still the tile a wall would be built from: nothing here
   changes when there are six, there is just more to swipe through.

   One card fills most of a phone with the next one showing at the edge,
   because a card that stops exactly at the screen edge looks like the
   end of the list. Two fill a laptop. */
.said-rail { --rail-gap: clamp(14px, 2vw, 20px); }
.said-track {
  display: grid; grid-auto-flow: column; grid-auto-columns: 86%;
  gap: var(--rail-gap);
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  /* Room for the hard shadow, which falls outside the card's own box and
     would otherwise be sliced off by the scroller's edges. */
  padding: 8px 8px 18px; margin-inline: -8px;
  scrollbar-width: none;
}
.said-track::-webkit-scrollbar { display: none; }
.said-track:focus-visible { outline: 3px solid var(--violet); outline-offset: 2px; border-radius: var(--radius-sm); }
@media (min-width: 760px) {
  .said-track { grid-auto-columns: calc((100% - var(--rail-gap)) / 2); }
}

.said-card {
  scroll-snap-align: center;
  display: grid; gap: 20px; align-content: start;
  padding: clamp(24px, 3vw, 32px) clamp(22px, 3vw, 34px);
  background: var(--cream); color: var(--ink);
  border: var(--border-w); border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
}
@media (min-width: 760px) { .said-card { scroll-snap-align: start; } }
/* The disc colour cycles, so a new card needs no styling of its own and
   a row never reads as one person repeated. */
.said-card:nth-child(3n+1) .said-disc { background: var(--violet); }
.said-card:nth-child(3n+2) .said-disc { background: var(--green-ink); }
.said-card:nth-child(3n+3) .said-disc { background: var(--pink-ink); }

.said-top { display: flex; align-items: center; gap: 13px; }
.said-disc {
  flex: 0 0 auto; width: 56px; height: 56px; border-radius: 50%;
  border: var(--border-w); display: grid; place-items: center;
  background: var(--violet); color: var(--cream);
  font-family: var(--font-display); font-size: 1.4rem; letter-spacing: .02em;
}
.said-who { min-width: 0; display: grid; gap: 4px; }
.said-name { font-weight: 700; font-size: 1.2rem; line-height: 1.1; }
.said-role {
  font-family: var(--font-mono); font-size: .68rem; font-weight: 700;
  letter-spacing: .13em; text-transform: uppercase; color: var(--pink-ink);
}
.said-text {
  margin: 0; font-weight: 500;
  font-size: clamp(1rem, 1.4vw, 1.1rem); line-height: 1.55;
}

/* The controls. JS unhides them only when there is something off screen,
   so with two cards on a laptop they are not there at all. */
.said-nav { display: flex; align-items: center; justify-content: center; gap: 16px; margin-top: 6px; }
.said-nav[hidden] { display: none; }
.rail-btn {
  display: grid; place-items: center; width: 46px; height: 46px; padding: 0;
  background: var(--cream); color: var(--ink);
  border: var(--border-w); border-radius: 50%; box-shadow: var(--shadow-sm);
  cursor: pointer; transition: transform .16s ease, box-shadow .16s ease, opacity .16s ease;
}
.rail-btn svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
.rail-btn:hover:not(:disabled) { transform: translate(-2px, -2px); box-shadow: var(--shadow); }
.rail-btn:disabled { opacity: .3; cursor: default; }
.rail-dots { display: flex; align-items: center; gap: 9px; }
.rail-dot {
  width: 11px; height: 11px; padding: 0; border-radius: 50%;
  border: 2px solid var(--ink); background: transparent; cursor: pointer;
  transition: background .18s ease, transform .18s ease;
}
.rail-dot[aria-current="true"] { background: var(--violet); transform: scale(1.18); }

/* ----------------------------------------------------------- THE ENTRANCE
   The loader hands over to a page that was simply there. Now the hero
   arrives: the line, the headline, the promise and the buttons, a beat
   apart, once the loader is out of the way.

   Held off until the script adds .in, so a page whose script never runs
   shows the hero rather than an empty plate. */
[data-enter].in .hero-copy > *,
[data-enter].in .hero-inner > * { animation: enter .62s cubic-bezier(.2,.8,.3,1) both; }
[data-enter].in .hero-inner > *:nth-child(1) { animation-delay: .04s; }
[data-enter].in .hero-inner > *:nth-child(2) { animation-delay: .13s; }
[data-enter].in .hero-inner > *:nth-child(3) { animation-delay: .22s; }
[data-enter].in .hero-inner > *:nth-child(4) { animation-delay: .31s; }
[data-enter].in .hero-inner > *:nth-child(5) { animation-delay: .40s; }
@keyframes enter {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: none; }
}
/* The film itself comes up out of the dark rather than snapping on. */
[data-enter] .hero-video { opacity: 0; transition: opacity 1.1s ease; }
[data-enter].in .hero-video { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  [data-enter].in .hero-inner > * { animation: none; }
  [data-enter] .hero-video, [data-enter].in .hero-video { opacity: 1; transition: none; }
}
