/* ============================================================================
   seriouslywow.com — one stylesheet. Tokens first; nothing hard-coded below :root.

   THE MODEL IS NOT "THE GUILD WITH A SERIF". It is Seriously Wow's own design,
   rebuilt on the Guild's plumbing. The first pass got that backwards: it took the
   Guild's austerity and swapped the typeface, and lost the purple blocks, the
   175px "Seriously," titles, the orange prices and the editorial mosaic — which
   is to say, everything anyone would recognise.

   INHERITED FROM THE GUILD (invisible, structural):
     token architecture · nothing hard-coded below :root · the #F2F0EA ground,
     shared exactly and by decision · one accent, one value · semantic HTML ·
     no build step · motion near zero, hover is a colour change.

   OWN (visible, and the whole point):
     serif display at page scale · purple as a FILLED SURFACE, not just ink ·
     orange, scoped to that surface · italic serif as a running voice ·
     an editorial mosaic instead of a uniform grid.
   ========================================================================== */

:root{
  /* --- palette ----------------------------------------------------------- *
   * Measured here before use, not taken on trust:
   *   ink on paper 16.17 · purple on paper 8.46 · mono-dim on paper 4.59
   *   paper on purple 8.46 · paper@.72 on purple 5.24 · greige on purple 6.18
   *   orange on purple 3.06 · orange on paper 2.77 · cyan on paper 2.15
   *
   * THE GROUND IS THE GUILD'S, EXACTLY. #F2F0EA is shared by decision. The old
   * Seriously Wow cream #f9efe5 sits at 1.00 against it — indistinguishable —
   * and two near-identical grounds across one group read as a copy error rather
   * than as two brands. If a later session finds the sites too similar, the
   * answer is the display face or the accent. NEVER the ground.
   *
   * ONE ACCENT, ONE VALUE. The Guild needs two — --red is 3.11 on this ground
   * and cannot carry small type, so it ramps down to --red-text. Purple is 8.46:
   * legal on body copy, on 11px mono, as a mark, and as a full ground with paper
   * type on it. DO NOT BUILD A RAMP HERE. The absence of one is a property of
   * the colour, and it is what lets purple be a SURFACE on this site rather than
   * only an accent. That is the single biggest difference between the two sites
   * and it comes free. */
  --purple:#453592;
  --on-purple:#F2F0EA;   /* type on the accent — 8.46, symmetric on both surfaces */

  /* THE LIVE SITE'S OTHER TWO COLOURS, BACK AS SURFACES RATHER THAN AS INK.
     Both fail completely as type on the beige — ochre 2.77, blue 2.15 — which
     is why they were retired, and that has not changed. What was missed is that
     they are the INVERSE OF PURPLE and perfectly legal the other way up:

       ink on ochre  5.84   AA at any size
       ink on blue   7.52   AA at any size
       paper on ochre 2.77 / paper on blue 2.15 — both fail, so light type never
       goes on either, the way ink never goes on purple (1.91).

     So the system is three coloured grounds in two polarities: purple is the
     dark one and takes paper type; ochre and blue are the light ones and take
     ink. Exactly the rule the parent repo's red About page runs on.

     THE ACCENT ON A COLOURED GROUND IS ALWAYS ONE OF THE OTHER TWO, and always
     above 24px: ochre on purple 3.06, purple on ochre 3.06, purple on blue 3.94.
     All three are large-text-and-marks values, never small type. */
  --ochre:#db7637;
  --blue:#00b3e4;
  --on-purple-dim:rgba(242,240,234,.72);   /* 5.24 on purple — small type there */
  --on-light-dim:rgba(20,20,20,.72);       /* small type on ochre and on blue */

  --paper:#F2F0EA;
  --ink:#141414;
  --greige:#D6CEC2;
  --mono-dim:#6E6C69;
  --hairline:rgba(20,20,20,.14);

  /* --- type — THE INVERSE OF THE GUILD'S SETTING -------------------------- *
   * The Guild sets display in grotesk and has no serif. This site sets display
   * in serif and takes the Guild's grotesk for everything else. Same two
   * families, opposite assignment. Jacquard 24 is retired — the blackletter
   * stood in for a Guild reference that now has a real lockup and a real link. */
  --font-display:'Source Serif 4',Georgia,'Times New Roman',serif;
  /* CURRENTLY UNUSED, AND KEPT ON PURPOSE. Nothing on the site resolves to this
     any more — reading copy went serif — so Inter is no longer loaded in the
     page heads either. The token stays as the one line a grotesk would come
     back on, exactly as the brief intends for PP Neue Montreal: set it here and
     add the @font-face or the <link>, and nothing else moves. */
  --font:'Inter','Helvetica Neue',Arial,sans-serif;
  --font-mono:'JetBrains Mono',ui-monospace,'SF Mono',monospace;

  /* THE "SERIOUSLY," TITLES ARE THE PAGE, NOT A SECTION HEAD. On the live site
     they set at 175px / 175px leading / -8.75px tracking — which is -.05em, and
     is the measurement this clamp is built from rather than a guess. They are
     the loudest thing on any page and they are supposed to be. */
  --fs-seriously:clamp(44px,11.5vw,175px);
  --fs-offer:clamp(30px,5.4vw,76px);     /* the centred service lines */
  /* The live site's opening statement on how.html set at 100px on a 1440 canvas
     in a 762px column. This page's measure is 1280, so the right-hand column is
     ~674px — the cap is scaled by that ratio (100 x 674/762) so the sentence
     breaks over the same number of lines it always did. */
  --fs-what:clamp(34px,7vw,92px);
  --fs-large:clamp(32px,6.4vw,84px);
  --fs-lead:clamp(19px,2.2vw,24px);
  --fs-title:clamp(17px,1.6vw,21px);
  /* READING COPY IS SERIF AND 40% LARGER THAN IT WAS. The brief inherited the
     Guild's split — display in serif, everything else in the grotesk — and this
     leaves that behind: the live site was Source Serif almost throughout, and
     15px Inter notes under a 175px serif title read as two unrelated documents.
     Inter now survives only where something is genuinely UI.

     16 -> 22, 15 -> 21, 13 -> 18. --measure stays 34em on purpose: an em-based
     measure holds its CHARACTER count as the size changes, so the line length
     is the same reading task it was before. */
  --fs-body:22px;
  --fs-note:21px;    /* notes, captions, accordion bodies — was 15 */
  --fs-small:18px;   /* the smallest reading copy — was 13 */
  --fs-mono:11px;    /* the mono voice does NOT scale — see below */

  /* --fs-display is gone: every page-scale headline is a "Seriously," title now
     and uses --fs-seriously. --track-display is still used by the wordmark and
     the address, so it stays.

     Tracking is NOT inherited. -.035em is tuned to Inter; on Source Serif 4 at
     140px it closes the serifs into each other. -.05em is the live site's own
     value on the big titles, and it only works because the face is a serif. */
  --track-seriously:-.05em;
  /* The home hero sets the logo artwork instead of the title type. Its width is
     the set title's own measure — "Seriously, wow." inks at 5.47em of
     --fs-seriously at every width — so swapping one for the other changes the
     letterforms, not the scale or the layout around them. */
  --w-hero-mark:calc(var(--fs-seriously) * 5.47);
  --track-display:-.03em;
  --track-mono:.14em;

  /* --- rhythm — the Guild's, unchanged ------------------------------------ */
  --measure:34em;
  --max-w:1280px;
  --pad-x:clamp(20px,5vw,64px);
  --pad-section:clamp(72px,10vw,140px);
  --gap-grid:clamp(28px,4vw,72px);
  --gutter:4px;          /* mosaic gutter — deliberately tight, images touch */

  /* The nav is FIXED on every page, so its height has to be a token: pages that
     do not open on a full-height frame reserve exactly this much at the top.
     Measured, not guessed — 16px padding, 40px lockup, 16px padding, 1px rule. */
  --nav-h:73px;
}

/* --- reset ---------------------------------------------------------------- */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%}
/* THE MONO IS DELIBERATELY LEFT AT 11px. It is not small body copy — it is the
   third voice, carrying tags, counts, labels and the todo markers, and scaling
   it with the prose would turn labels into text and collapse the hierarchy the
   whole site runs on. Same reason the tagstring stays at 13. */
body{
  background:var(--paper);color:var(--ink);
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:var(--fs-body);line-height:1.5;
  font-weight:400;letter-spacing:-.006em;overflow-x:hidden;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
}
a{color:inherit;text-decoration:none}
address{font-style:normal}
img{max-width:100%;display:block}
:focus-visible{outline:2px solid var(--purple);outline-offset:3px}
::selection{background:var(--purple);color:var(--on-purple)}

.wrap{max-width:var(--max-w);margin:0 auto;padding:0 var(--pad-x)}
/* Full-bleed. The mosaic and the purple bands run edge to edge; the type inside
   them keeps the wrap. This is the one structural thing the first pass lacked —
   everything sat inside 1280px and the page never opened up. */
.bleed{width:100%}
.skip{position:absolute;left:-9999px}
/* Present for screen readers and search engines, absent on screen. The clip
   pattern rather than display:none, which would hide it from both. */
.visually-hidden{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;
}
.skip:focus{
  left:var(--pad-x);top:12px;z-index:30;background:var(--purple);color:var(--on-purple);
  padding:8px 14px;font-family:var(--font-mono);font-size:var(--fs-mono);
  text-transform:uppercase;letter-spacing:var(--track-mono);
}

/* ==========================================================================
   THE "SERIOUSLY," TITLE — the site's signature device
   Seriously, what? · how · clear · efficient · good to know.
   The wordplay is the voice. It is carried forward from the live site because
   it is the best thing on it, and because a page called "Method" says nothing
   that "Seriously, how" does not say better and in the studio's own mouth.
   ========================================================================== */
.seriously{
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:var(--fs-seriously);font-weight:500;line-height:.98;
  letter-spacing:var(--track-seriously);text-wrap:balance;
}
.seriously em{font-style:italic;color:var(--purple)}
/* Big label left, small explanation right — the shape borrowed from the
   structure of a reference, not its look. It stops a 175px title from being a
   lonely band of type and gives the reader somewhere to land immediately. */
.chapter{
  display:grid;grid-template-columns:1fr minmax(0,300px);
  /* The note centres against the title rather than hanging off its top line.
     A two- or four-line note top-aligned beside a two-line 175px headline reads
     as a stray caption; centred, the pair reads as one unit. The old .9em of
     padding was doing the top-aligned version's optical correction and is gone
     with it — centring makes it wrong, not smaller. */
  gap:clamp(24px,4vw,64px);align-items:center;
  padding-block:clamp(48px,7vw,110px) clamp(32px,4vw,56px);
}
.chapter-note{font-size:var(--fs-note);line-height:1.45;max-width:32em}

/* ONE TITLE IS LONGER THAN THE REST. "Seriously, good to know" measures 8.17em
   set solid, against 5.29em for "Seriously, clear". In the chapter's 794px
   title column it can only hold one line at ~97px — against the 165.6px its
   siblings take at the same viewport, which reads as a mistake rather than as
   a longer title. So it takes the full measure and the note drops beneath it,
   still on the right.

   Two terms, both arithmetic rather than taste, and both to be RE-MEASURED if
   the words or the tracking change:
     140px  the cap, = 1152 / 8.17 — the widest it can set in the full measure,
            which stops growing once --max-w caps the wrap at 1280.
     10.8vw between 1001 and 1280 the measure is 90vw, so the fit is 11.01vw;
            10.8 takes that with enough margin to absorb the scrollbar, which
            vw units do not subtract. Without this term the title overflows
            everywhere in that range — --fs-seriously is 11.5vw there.
   Below 1001 .chapter is already one column, so none of this applies and the
   title wraps like every other one. */
@media (min-width:1001px){
  .chapter--wide{align-items:start}
  .chapter--wide .seriously{
    grid-column:1/-1;white-space:nowrap;
    font-size:min(var(--fs-seriously),10.8vw,140px);
  }
  .chapter--wide .chapter-note{grid-column:2;margin-top:clamp(20px,2.4vw,36px)}
}

/* The italic serif descriptor. The live site runs on this and the first pass
   used it zero times, which is most of why that pass read as a different studio. */
.it{
  font-family:var(--font-display);font-optical-sizing:auto;font-style:italic;
  font-size:var(--fs-lead);line-height:1.3;letter-spacing:-.012em;font-weight:400;
}

.lead{
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:var(--fs-lead);line-height:1.32;letter-spacing:-.012em;
  max-width:24em;font-weight:400;
}
.lead span{display:block}
.prose{max-width:var(--measure)}
.prose p + p{margin-top:1.2em}
.prose--spaced{margin-top:clamp(32px,4vw,56px)}

.mono{
  font-family:var(--font-mono);font-size:var(--fs-mono);font-weight:400;
  letter-spacing:var(--track-mono);color:var(--mono-dim);
}
.mono-up{text-transform:uppercase}
.tagstring{
  font-family:var(--font-mono);font-size:13px;letter-spacing:.1em;
  color:var(--mono-dim);text-transform:lowercase;line-height:1.9;
}

/* Content that is not final. Visible on purpose. */
.todo-inline{
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:var(--track-mono);
  color:var(--mono-dim);background:var(--greige);padding:2px 6px;text-transform:uppercase;
}
.todo-block p{font-size:var(--fs-note);line-height:1.5;max-width:32em}

/* --- nav — identical on every page ---------------------------------------- */
/* FIXED, NOT STICKY, AND ON EVERY PAGE. The home page opens on a full-height
   image with the type and the links over it, which a nav in normal flow cannot
   do without pushing the frame past one screen. Fixing it everywhere — rather
   than only on home — is what keeps the nav identical from page to page: same
   position, same size, same height. Pages that do not open on a frame reserve
   --nav-h at the top of <main> instead. */
.nav{position:fixed;top:0;left:0;right:0;z-index:20;background:var(--paper);border-bottom:1px solid var(--hairline)}
main{padding-top:var(--nav-h)}
.home main{padding-top:0}
.nav-in{display:flex;align-items:center;justify-content:space-between;gap:24px;padding-block:16px}

/* Over the opening frame the nav carries no ground of its own and its tokens
   invert — the same token swap the purple page uses, not a forked nav style, so
   nothing about its geometry moves. site.js takes this class off the moment the
   frame leaves the top of the viewport; the class is in the HTML to begin with
   so the nav never flashes solid over the image on load. */
.nav--over{
  --ink:#F2F0EA;
  --mono-dim:rgba(242,240,234,.80);
  --purple:#F2F0EA;
  background:transparent;border-bottom-color:transparent;color:var(--ink);
}
/* The lockup is pure black on alpha, so an invert makes it pure white and keeps
   the matte. One line, and no second logo file to keep in sync. */
.nav--over .nav-name img{filter:invert(1)}
/* THE REAL WORDMARK. seriously-logo-black.webp is alpha-matted, so it sits on
   the beige with no plate behind it. The first pass dropped it for plain type on
   the assumption that the only lockup was the orange-on-white PNG; that was
   wrong, and the lockup is half the brand's recognition. */
.nav-name{display:inline-flex;align-items:center}
/* The file is 630x234 — a stacked two-line lockup, not a single-line wordmark,
   so it needs real height to read. The live site sets it at 87px tall inside a
   fixed 1440 layout; 40 is the equivalent presence in a sticky bar that has to
   survive 375 as well. */
.nav-name img{height:40px;width:auto}
.nav-links{display:flex;gap:26px}
.nav-links a{
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:16px;letter-spacing:-.01em;color:var(--ink);
  transition:color .15s;white-space:nowrap;
}
.nav-links a:hover,.nav-links a[aria-current="page"]{color:var(--purple)}

/* ==========================================================================
   FULL-HEIGHT FRAMES — the home page opens on two of them
   One screen of image with the type and the links over it, then one screen of
   showreel directly under it. Nothing else is allowed above the fold, which is
   the point: this site proves rather than argues, so the first thing a reader
   meets is a picture and not a paragraph.

   100svh, not 100vh. On mobile, vh resolves against the LARGEST viewport — the
   one with the browser chrome retracted — so a 100vh frame is taller than the
   screen on load and the scroll cue sits below the fold, which is exactly where
   it cannot do its job. svh is the small viewport and always fits.
   ========================================================================== */
.frame{
  position:relative;height:100svh;min-height:520px;overflow:hidden;
  display:flex;flex-direction:column;
}
.frame-media{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;background:var(--greige)}
/* THE SCRIM IS NOT DECORATION, IT IS THE CONTRAST GUARANTEE. Type over an image
   is a gamble unless something underwrites it: swap the file and the measured
   ratio changes with it. This veil is weighted to the left, where the type is,
   and it holds paper type above 4.5 on any frame of any image behind it.
   Measured on the shipped file after it was set, not assumed. */
.frame-scrim{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    linear-gradient(to top,rgba(12,10,20,.72) 0%,rgba(12,10,20,0) 42%),
    linear-gradient(to right,rgba(12,10,20,.82) 0%,rgba(12,10,20,.62) 42%,rgba(12,10,20,.30) 100%),
    linear-gradient(to bottom,rgba(12,10,20,.55) 0%,rgba(12,10,20,0) 28%);
}
.frame-body{
  position:relative;z-index:2;margin-top:auto;
  padding-bottom:clamp(72px,10vh,132px);padding-top:var(--nav-h);
  display:flex;flex-direction:column;gap:clamp(18px,2.4vw,30px);
}
/* Inside a frame the tokens invert, exactly as they do on the purple page.
   No component below here is restyled — they simply resolve to light values. */
.frame--hero{
  --ink:#F2F0EA;
  --purple:#F2F0EA;
  --mono-dim:rgba(242,240,234,.80);
  --hairline:rgba(242,240,234,.30);
  color:var(--ink);
}
/* The accent word takes orange rather than the collapsed paper value, so the
   hero keeps a second colour. Orange on the scrimmed ground is measured well
   clear of 4.5 and the word is display-size regardless. */
.frame--hero .seriously em{color:var(--ochre)}
.hero-mark{margin:0;line-height:0}
.hero-mark img{display:block;width:var(--w-hero-mark);max-width:100%;height:auto}
.frame--hero .it{max-width:26em}
.scroll-cue{
  position:relative;z-index:2;align-self:flex-start;
  margin:0 auto clamp(20px,3vh,34px) 0;padding-left:var(--pad-x);
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:var(--track-mono);
  color:var(--mono-dim);transition:color .15s;
}
.frame--hero .scroll-cue:hover{color:var(--ochre)}
/* The reel frame carries no type at all — the frames are unknown and the line
   it needs is on the purple band that follows.
   THE FILM IS SHOWN WHOLE, NEVER COVER-CROPPED. V3 sets words right across the
   frame ("We don't generate, we direct." spans the full width), so a cover crop
   cut type off at both edges. Filling a full-height frame also enlarged the
   1080p film about 1.7x on a laptop, which is what made the type edges jagged.
   Measured at native size, the file itself is clean. So the reel sits at its
   own 16:9, capped at the site's measure (--max-w, where it is shown at or
   below its own pixels on a standard screen), on the paper ground. The margin
   is EQUAL ALL ROUND: percentage padding resolves against width on both axes,
   so max(pad, (100% - cap) / 2) grows the top and bottom exactly as fast as the
   sides once the cap is reached. */
.frame.frame--reel{
  height:auto;min-height:0;display:block;
  padding:max(var(--pad-x), calc((100% - var(--max-w)) / 2));
  background:var(--paper);
}
.frame--reel .frame-media{
  position:static;display:block;width:100%;height:auto;aspect-ratio:16/9;
  object-fit:contain;background:var(--ink);
}

/* --- page header ---------------------------------------------------------- */
/* A "Seriously," title sets at line-height .98, so its descenders — the y of
   "Seriously,", the g of "good to know" — hang below the box. Anything under it
   collides. The margin here is what stops that, and it went missing when page
   heads moved from .display to .seriously and this rule kept naming the old
   class. Measured against the italic g at 175px, which is the deepest one. */
.page-head{padding-block:clamp(40px,6vw,88px) clamp(28px,3.5vw,48px)}
.page-head .seriously{margin-bottom:clamp(26px,3.2vw,44px)}
/* CONTACT'S NOTE IS A PARAGRAPH, NOT A CAPTION. The 300px note column suits the
   one-line qualifiers the other chapters carry; Contact's is 30 words and broke
   to eight lines in it. At this measure it reads as body copy, which is what it
   is. Page heads only — the chapter notes further down keep the narrow column. */
.page-head .chapter{grid-template-columns:1fr minmax(0,34em)}

.section{padding-block:0 var(--pad-section)}
/* Sections carry their space underneath, so a section that follows a full-bleed
   frame has nothing above it and its first line sits against the picture. The
   pillars end flush by design, so the section after them supplies the gap. */
.pillars + .section{padding-top:var(--pad-section)}
/* THE PRICE HEADING IS A LABEL FOR THE CARDS, NOT A SECTION OF ITS OWN. #much
   holds one heading and a note, and the four price frames begin immediately
   under it — at the standard --pad-section that took 621px to say two things
   and the cards read as unrelated to the words above them. */
#much{padding-bottom:clamp(20px,2.8vw,40px);margin-top:clamp(-48px,-3.4vw,0px)}
/* And the same exception the pillars already had. A section following a
   full-bleed block starts flush against it, which was right while nothing
   followed the price cards and wrong now that a heading does. */
.plans + .section{padding-top:var(--pad-section)}

/* ==========================================================================
   THE PURPLE SURFACE, USED AS A SURFACE
   This is the device the first pass lost. On the live site purple is not an
   accent colour — it is a BLOCK: the pricing cards, the rules, the bands. It
   carries paper type at 8.46 and orange display type at 3.06.
   ========================================================================== */

/* A full-bleed band. Type inside keeps the wrap. */
.band{background:var(--purple);color:var(--on-purple);padding-block:clamp(56px,8vw,120px)}
.band .mono,.band .chapter-note{color:var(--on-purple-dim)}
/* HOVER MOVES THE UNDERLINE, NOT THE WORDS. Links inside a band are 15–24px on
   purple, where ochre is 3.06 — legal for a mark, illegal for type that size.
   The rule beneath is a non-text mark, so it can take the colour while the
   words stay at 8.46. Same fix as .band-link. */
.band a:hover{
  text-decoration:underline;text-decoration-color:var(--ochre);
  text-decoration-thickness:2px;text-underline-offset:.22em;
}
/* The three-line refusal from the live site's "Seriously, cheap" — concrete,
   and pointedly NOT the Guild's argument about abundance and meaning. */
.nos{
  display:flex;flex-direction:column;gap:.06em;
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:var(--fs-offer);font-weight:500;line-height:1.02;
  letter-spacing:var(--track-display);
}
.nos span:last-child{color:var(--ochre)}   /* 3.06 — large display only */
/* Sits under a statement inside a band — on catalogue.html it still does, and
   there the margin is what separates the two. Inside .band-split the grid gap
   does that job instead, so the margin is zeroed there rather than dropped here. */
.band-note{margin-top:clamp(24px,3vw,40px);max-width:26em}

/* The home band, given room. Title left at display scale, the note across from
   it on the right — the same big-label / small-note split the chapter heads
   use, so the page has one way of pairing a statement with its qualifier. */
.band--tall{padding-block:clamp(88px,13vw,190px)}
/* THE TRIO IS SIZED TO ITS COLUMN, NOT TO THE PAGE. It sits beside a 26em note
   in .band-split, which leaves it about 500-516px between 1001 and 1920 — the
   note column stops the first column growing once --max-w caps the wrap. At the
   old 7.2vw all three lines broke mid-phrase ("No / logistics."), and the
   longest, "No limitations.", needs 6.22em of width. So the size is capped to
   what that column can hold rather than to the viewport.
   MEASURED, not guessed — re-measure if the words change. Below 1000 the band
   stacks to one column and the trio has the full measure. */
.band--tall .nos{font-size:clamp(40px,5.2vw,78px);line-height:.98}
/* THE NOTE CENTRES ON THE STATEMENT, WHICH IS WHY THE ROWS ARE EXPLICIT.
   Row one holds the statement and the note, so align-items:center lines their
   middles up. The link sits in row two under the statement. Wrapping the
   statement and the link together and centring the note against that pair is
   the obvious construction and it is wrong — the note lands 42px low, because
   it is centring on a column that is taller than the words it belongs to. */
.band-split{
  display:grid;grid-template-columns:1fr minmax(0,26em);
  column-gap:clamp(32px,5vw,80px);row-gap:clamp(28px,3.4vw,52px);
  align-items:center;
}
.band-split .nos{grid-column:1;grid-row:1}
.band-split .band-note{grid-column:2;grid-row:1;margin-top:0}
.band-split .band-link{grid-column:1;grid-row:2;justify-self:start}

/* THE LINK STAYS PAPER-COLOURED AND THE UNDERLINE CARRIES THE HOVER. Orange is
   3.06 on this ground: legal for large text and for non-text marks, and not for
   anything under 24px. This clamps down to 19px on a phone, so orange can never
   be its text colour — but the rule beneath it is a non-text mark, where 3.06
   passes at any size. So the colour change on hover happens there, and the
   words stay at 8.46 throughout. */
.band-link{
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:clamp(19px,2.2vw,24px);line-height:1.2;letter-spacing:-.015em;
  color:var(--on-purple);display:inline-flex;align-items:baseline;gap:.5em;
  padding-bottom:.22em;border-bottom:1px solid rgba(242,240,234,.45);
  transition:border-color .15s;
}
.band-link:hover{border-bottom-color:var(--ochre)}
.band-link-arrow{font-size:.9em}


/* ==========================================================================
   PLANS — solid purple cards. The thing you actually recognise.
   Contrast inside a card: name/list/italic in --paper (8.46), the meta label in
   --on-purple-dim (5.24), and ONLY the price in orange, because it is the only
   type on the card above 24px. The live site set the meta label in orange too,
   at ~11px, where orange is 3.06 and needs 4.5 — that one is a fix, not a
   flattening, and it is the single change to the card.
   ========================================================================== */
/* FOUR FRAMES ACROSS THE SCREEN, like the pillars on the home page. Cards
   inside a 1280 wrap read as a price table; frames edge to edge read as four
   things you can buy. Same gutter-less treatment the pillars use.

   THREE GROUNDS, TWO POLARITIES. Purple is the dark surface and takes paper
   type; ochre and blue are the light ones and take ink. Nothing below is
   restyled per card — each variant only redefines what the card's tokens mean,
   the same mechanism as .page-purple. Four frames in one flat purple is a slab;
   this is what the live site actually looked like.

   THE PRICE IS ALWAYS THE ACCENT THAT IS NOT THE GROUND, and always large:
   ochre on purple 3.06, purple on ochre 3.06, purple on blue 3.94 — all three
   are large-text values and the figure is 30px and up. */
.plans{display:grid;grid-template-columns:repeat(4,1fr);gap:0}
.plan{
  background:var(--card-bg);color:var(--card-ink);
  padding:clamp(26px,2.9vw,48px);display:flex;flex-direction:column;gap:16px;
  /* HEIGHT ONLY, NEVER aspect-ratio. A ratio here fights the 1fr track: at 1440
     the min-height resolves to 634px, the ratio then demands 422px of width
     against a 360px column, and the grid overflows the page horizontally.
     Height is the thing being designed; the width is the column's business. */
  min-height:clamp(420px,44vw,640px);
}
.plan--purple{
  --card-bg:var(--purple); --card-ink:var(--on-purple);
  --card-dim:var(--on-purple-dim); --card-accent:var(--ochre);
}
.plan--ochre{
  --card-bg:var(--ochre); --card-ink:var(--ink);
  --card-dim:var(--on-light-dim); --card-accent:var(--purple);
}
.plan--blue{
  --card-bg:var(--blue); --card-ink:var(--ink);
  --card-dim:var(--on-light-dim); --card-accent:var(--purple);
}
/* THE FLAGSHIP TIER STANDS OUT BY STANDING BACK. White, not paper — paper is
   1.00 against the page and the frame would simply vanish. Even white is only
   1.14 against the beige, so its outer edge is effectively invisible and the
   row reads as three colours with an opening cut in it. That is the point of
   putting it last and it is why nothing draws a border: a rule around it would
   turn the opening back into a fourth card.

   Ink 18.42, purple 9.64, dim label 7.34 — the highest-contrast frame in the
   row. Its accent is purple; ochre is 3.15 here and would be legal only as
   large text, which the price is, but purple is the stronger and safer read. */
.plan--white{
  --card-bg:#FFFFFF; --card-ink:var(--ink);
  --card-dim:rgba(20,20,20,.72); --card-accent:var(--purple);
}
.plan-name{
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:clamp(32px,3.7vw,62px);font-weight:400;line-height:.96;
  letter-spacing:-.032em;
}
.plan-for{
  font-family:var(--font-display);font-optical-sizing:auto;font-style:italic;
  font-size:clamp(16px,1.4vw,22px);line-height:1.35;
}
.plan-list{
  list-style:none;display:flex;flex-direction:column;gap:7px;
  font-size:clamp(19px,1.6vw,25px);line-height:1.35;
}
.plan-price{margin-top:auto;display:flex;flex-direction:column;gap:4px}
.plan-meta{
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:var(--track-mono);
  text-transform:uppercase;color:var(--card-dim);
}
.plan-figure{
  font-family:var(--font-display);font-optical-sizing:auto;
  /* Sized against the widest string, "€8–15k", measured at 1024/1200/1440/1920:
     the glyphs clear their column by 46px at the tightest of those. Weight 600
     rather than 400 — on a coloured ground the figure is competing with a whole
     field of colour, and at 400 it read as a caption that happened to be big. */
  font-size:clamp(44px,5.8vw,92px);font-weight:600;line-height:1;
  letter-spacing:-.035em;color:var(--card-accent);font-variant-numeric:tabular-nums;
}

/* ==========================================================================
   PILLARS — the three offerings as three full-height vertical frames
   Home page only. Photography, moving image, illustration, side by side across
   the whole screen width, each one a picture with its own name over it.

   This is the same argument as the opening frame, made three times: the studio
   proves rather than describes, so each discipline is shown in the medium it
   sells rather than named in a list. The typographic treatment is deliberately
   NOT the centred purple setting on how.html — over an image the type has to
   sit in a corner and hold its own ground, so it is left-aligned, bottom-left,
   and much smaller than a page-scale heading.

   Swapping any of the three is one attribute. how.html keeps the centred
   version, where there is no image to sit on.
   ========================================================================== */
/* No gutter. The three frames butt against each other so the band reads as one
   continuous picture divided three ways rather than as three cards on a page.
   The dark ground behind them is insurance: at fractional viewport widths the
   1fr columns can round apart by a subpixel, and a paper-coloured seam between
   two dark frames is visible where a dark one is not. */
.pillars{
  display:grid;grid-template-columns:repeat(3,1fr);gap:0;
  background:#0c0a14;
}
.pillar{
  /* Tokens invert inside the frame, exactly as they do in .frame--hero and on
     the purple page. Nothing below is restyled — it resolves to light values. */
  --ink:#F2F0EA;
  --mono-dim:rgba(242,240,234,.84);
  color:var(--ink);
  position:relative;aspect-ratio:2/3;max-height:92svh;overflow:hidden;
  display:flex;flex-direction:column;justify-content:flex-end;
}
.pillar-media{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;
  background:var(--greige);
}
/* THE CAROUSEL IS A CROSSFADE, NOT A SLIDE. Frames stack and only opacity
   changes — nothing travels across the screen, which keeps to the site's rule
   that motion stays near zero. Each frame is sized exactly like a single
   .pillar-media image, so the swap from still to carousel moved nothing. */
.pillar-carousel img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transition:opacity 1.2s ease;
}
.pillar-carousel img.is-active{opacity:1}
@media (prefers-reduced-motion:reduce){ .pillar-carousel img{transition:none} }
/* Same contract as the hero scrim: this is the contrast guarantee, not a mood.
   Weighted hard to the bottom because that is the only place type sits, so the
   top two thirds of each picture stay untouched. Measured on the shipped files. */
.pillar-scrim{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(to top,
    rgba(12,10,20,.88) 0%,rgba(12,10,20,.62) 22%,rgba(12,10,20,.20) 48%,rgba(12,10,20,0) 68%);
}
.pillar-body{position:relative;z-index:2;padding:clamp(18px,2.1vw,32px)}
.pillar-title{
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:clamp(20px,2.35vw,36px);font-weight:500;line-height:1.02;
  letter-spacing:-.03em;text-wrap:balance;
}
.pillar-desc{
  font-family:var(--font-display);font-optical-sizing:auto;font-style:italic;
  font-size:clamp(17px,1.5vw,24px);line-height:1.3;letter-spacing:-.012em;
  margin-top:.42em;color:var(--mono-dim);max-width:20em;
  /* Two lines' worth, reserved. The bodies bottom-align, so a descriptor that
     wraps in one column and not in the next pushes that column's title up and
     the three names stop sitting on a line together. "For editorial, product
     imagery and campaigns." is the long one and wraps first. */
  min-height:2.7em;
}

.ph{
  background:var(--greige);display:grid;place-items:center;overflow:hidden;
  position:relative;
}
.ph-label{
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:var(--track-mono);
  color:var(--mono-dim);text-transform:lowercase;padding:0 16px;text-align:center;
}
.ph img,.ph video{width:100%;height:100%;object-fit:cover;display:block}



/* The work mosaic, its tiles, the .case details and the source/result .pair all
   lived here until work.html was retired. They are in legacy/projects-tiles.js
   with the data they rendered. .ph and .ph-label stayed: the derivation's source
   slot on how.html still uses them for its marked placeholder.
   The reel is shown whole in its own frame — see .frame--reel above. */

/* ==========================================================================
   CREATIVE — the output wall
   A different page from work.html and deliberately so. Work is eight cases with
   clients, categories and blurbs. This is the same studio with the labels taken
   off: one screen of name, then everything we have made, uncaptioned.

   The hero centres its title, which nothing else on this site does. That is not
   drift — a page whose whole subject is volume opens on a frame with the work
   pressing in from every edge, and a left-aligned title leaves one side of that
   composition empty. It is the only centred title on the site and it earns it.
   ========================================================================== */
.creative-hero{
  position:relative;min-height:100svh;overflow:hidden;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:calc(var(--nav-h) + clamp(40px,7vh,90px)) var(--pad-x) clamp(48px,8vh,96px);
  text-align:center;
}
/* THE TITLE IS CAPPED AGAINST THE VIEWPORT'S HEIGHT HERE, and only here.
   --fs-seriously scales with WIDTH (11.5vw), which is right on every other page
   because those titles have a whole page to grow into. This one shares a fixed
   100svh frame with six images, so on a short wide window — 1366x768, the most
   common laptop there is — the title grew to 157px while the frames, sized off
   height, shrank. That is where the collision came from, and capping the type
   is the honest fix: the frames were not too big, the headline was. */
.creative-hero .seriously{max-width:14em;font-size:min(var(--fs-seriously),13.5vh)}
.creative-lead{
  margin-top:clamp(18px,2.4vw,30px);max-width:22em;
  font-family:var(--font-display);font-optical-sizing:auto;font-style:italic;
  font-size:var(--fs-lead);line-height:1.35;letter-spacing:-.012em;
}
.creative-cue{
  margin-top:clamp(26px,3.4vw,44px);
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:var(--track-mono);
  text-transform:uppercase;color:var(--mono-dim);
  padding-bottom:.5em;border-bottom:1px solid var(--hairline);transition:color .15s,border-color .15s;
}
.creative-cue:hover{color:var(--purple);border-bottom-color:var(--purple)}
/* The type sits above the scatter and needs its own stacking context, or the
   frames that bleed inward would cross it. */
.creative-hero .wrap-mid{position:relative;z-index:2;display:flex;flex-direction:column;align-items:center}

/* THE SCATTER. Six frames pinned to the edges of the opening screen, each one
   partly outside it, so the page reads as a wall that continues past the fold
   rather than as six pictures arranged on a page. Positions are percentages of
   the frame, so the composition holds as the viewport changes rather than
   drifting apart at one width and colliding at another.

   No background grid behind them: the frames are the composition. */
.scatter{position:absolute;inset:0;z-index:1;pointer-events:none}
.scatter img{
  position:absolute;display:block;object-fit:cover;
  width:100%;height:100%;
}
.scatter figure{position:absolute;overflow:hidden;background:var(--greige)}
/* ALL SIX SIT INSIDE THE FRAME, OUT OF THE TYPE'S WAY, AND AT SIX DIFFERENT
   SIZES. Three things are load-bearing here:

   SIZED OFF THE VIEWPORT'S HEIGHT, NOT ITS WIDTH. A width in % makes a frame's
   HEIGHT depend on how wide the window is, which is why the bottom row once
   grew tall enough to sit behind the title at 1440. Height is the thing that
   has to be controlled, so height is what is set and the ratio derives the
   width. The min() with a vw term stops them going absurd on a short, wide one.

   SIX DIFFERENT SCALES, AND THE BOTTOM ROW IS NOW THE BIGGER ONE — measured,
   not chosen. The type is three elements of very different widths: at 1440x900
   the TITLE is 878px wide, the lead 506, the cue only 130. The top row sits
   under the title and is boxed in by the widest of the three, so it can only
   grow until it meets the title's top edge. The bottom row sits under the lead
   and the cue, and there is 467px of clear space either side of those — so it
   can rise well past where the title's band would have stopped it, as long as
   it stays outside their much narrower boxes.

   That is why the bottom row grew by half and the top row by a fifth. A single
   uniform increase would either waste the bottom or collide at the top.

   EACH BOX MATCHES ITS SOURCE'S RATIO, so cover crops nothing: 3/2 for the two
   landscapes, 3/4 for the four portraits.

   The insets and the parallax travel below are a pair — see site.js. */
.scatter figure{width:auto;will-change:transform}
/* Still the largest of the six, but 23vh not 25: at 25 it reached 288px down a
   900px hero and the title's first line starts at 287. Nine pixels, measured at
   1180/1440/1600 — the sort of overlap that only shows up on one window size
   and looks like a mistake on that one. */
/* 26vh at a 2% inset, not 27 at 3%: on short screens — 1280x720, 1366x768 —
   27vh put its bottom edge 3-6px into the title's first line. It is the widest
   frame of the six (3:2), so it is also the one with no horizontal escape from
   a title that runs 878px at 1440. */
.scatter figure:nth-child(1){top:2%;    left:2%;   aspect-ratio:3/2;height:min(31vh,33vw)}
.scatter figure:nth-child(2){top:3%;    left:45%;  aspect-ratio:3/4;height:min(27vh,29vw)}
.scatter figure:nth-child(3){top:2%;    right:3%;  aspect-ratio:3/4;height:min(31vh,33vw)}
/* 34vh and hard to the left edge, not 37 at 3%: at 37 its right edge reached
   279px against a lead beginning at 262 on a 981-wide window. The bottom-left
   frame is the one that runs closest to the lead's left margin. */
.scatter figure:nth-child(4){bottom:5%; left:2%;   aspect-ratio:3/4;height:min(34vh,36vw)}
.scatter figure:nth-child(5){bottom:6%; left:41%;  aspect-ratio:3/2;height:min(23vh,26vw)}
.scatter figure:nth-child(6){bottom:5%; right:3%;  aspect-ratio:3/4;height:min(35vh,37vw)}

/* THE WALL — JUSTIFIED ROWS. NOTHING CROPPED, ANY RATIO ACCEPTED.
   It was uniform squares first (27% of every frame discarded), then a two-ratio
   modular grid (portrait one column, landscape two — exact, because 1.5 is
   precisely twice 0.75). The library then grew a third ratio: 16:9. There is no
   column unit that fits 0.75, 1.5 and 1.778 together, so the modular grid could
   not hold it — 21 frames were being silently dropped.

   THE ARITHMETIC THAT MAKES THIS WORK. Each item gets flex-grow AND flex-basis
   proportional to its own aspect ratio. In a flex line the final width is
   basis + free x grow/sum(grow); with both terms proportional to `ar` that
   comes out as width = ar x (B + free/sum(ar)) — so every width is proportional
   to its aspect, which means every HEIGHT in that line is identical. Rows sit
   flush at both ends, each frame keeps its true proportion, and no ratio is
   privileged. Add a 4:5 or a panorama tomorrow and it just works.

   THE LAST ROW is the classic failure of this layout: with nothing to fill it,
   grow stretches the survivors to enormous size. .wall-fill soaks up that free
   space instead — zero height so it adds no row, huge grow so it wins nearly
   all of the remainder, leaving the final row at its natural size rather than
   blown up. */
.wall{
  /* The basis that decides roughly how many frames land in a row, and so how
     big they are. It is the one number that sizes this whole wall.

     Raised hard: at 14vw a desktop row held four or five frames at ~227px and
     the page read as a contact sheet. At 23vw it holds two or three at ~470px
     and the frames are big enough to actually look at, which is the only reason
     this page exists. The floor keeps a phone at roughly one frame per row. */
  --wall-base:clamp(230px,23vw,380px);
  display:flex;flex-wrap:wrap;align-items:flex-start;
  gap:var(--gutter);padding-inline:var(--gutter);
}
.wall-item{
  margin:0;position:relative;background:var(--greige);overflow:hidden;
  /* GROW IS SCALED BY 100, AND THAT x100 IS LOAD-BEARING. Using the aspect
     ratio raw looks equivalent — the proportions between items are identical
     either way — but flexbox has a rule for lines whose grow factors sum to
     LESS THAN ONE: it hands out only that fraction of the free space. A lone
     portrait has an aspect of 0.67, so a row holding just that one frame was
     filling 67% of the width and stopping. Six rows did it at 375px. Scaling
     every factor by the same constant fixes it without changing any ratio. */
  flex:calc(var(--ar) * 100) 1 calc(var(--ar) * var(--wall-base));
}
.wall-item img{width:100%;height:auto;display:block}
.wall-fill{flex:999 1 0;height:0;margin:0;padding:0}
/* The scatter above is clipped at the hero's bottom edge, so without this the
   half-frames sit directly on the first row of the grid and the two read as one
   broken thing. The gap is what separates the composition from the catalogue. */
.wall-band{padding-top:clamp(56px,8vw,120px)}
/* The grid ends flush; the closing line needs room of its own, and more of it
   than a normal section break — after eighty-four frames the eye needs the page
   to stop before it is asked to read a sentence. */
.wall-band + .section{padding-top:clamp(96px,13vw,190px)}
.wall-item::after{
  content:'';position:absolute;inset:0;background:var(--purple);
  opacity:0;transition:opacity .15s;pointer-events:none;
}
.wall-item:hover::after{opacity:.16}

/* ==========================================================================
   THE CONTENT SYSTEM — one source, a season of assets (how.html)
   The catalogue page folded in here. Its argument was volume; gallery.html now
   carries that. What lives here instead is DERIVATION — the object is directed
   once and the assets come out of it — which is the part a production lead is
   actually buying and the part no gallery can show.
   ========================================================================== */

/* SERIOUSLY, WHAT — THE LIVE SITE'S OWN OPENING, REBUILT ON THIS PALETTE.
   Title across the full width, then the product study on the left against one
   very large sentence on the right, with the small print under it. What stood
   here was a .chapter — title left, note right — which is the shape every other
   section of this page uses, so the page opened the same way it continued.

   Two things do NOT carry over from the old page. The accent phrase was ochre;
   ochre is a ground in this palette and not an ink (2.77 on paper, fails at
   every size) so the accent is purple, which measures 8.47. And reading copy
   keeps this site's tracking rather than the old export's -.05em on everything
   — that value is a display setting and stays on the display line only. */
.what{padding-block:clamp(48px,7vw,110px) var(--pad-section)}
.what .seriously{margin-bottom:clamp(32px,4vw,60px)}

/* 539 : 762 in a 1326px content width on the live site — kept as a ratio so it
   holds at this page's narrower measure. The gutter there was 25px, which is
   deliberately tighter than this site's --gap-grid: the picture and the
   sentence are one composition, not two columns of a layout. */
.what-grid{
  display:grid;grid-template-columns:minmax(0,41.5fr) minmax(0,58.5fr);
  gap:clamp(20px,2.4vw,32px);
}
.what-fig{margin:0}
.what-fig img{width:100%;height:auto;display:block;background:var(--greige)}

/* Lead and provenance share the right-hand cell, so the paragraph sits under
   the headline beside the picture instead of dropping to a second grid row
   below the image — .what-grid has two cells and a third child would wrap. */
.what-col{display:flex;flex-direction:column}
.what-body{
  margin-top:clamp(20px,2.4vw,32px);font-size:var(--fs-note);
  line-height:1.5;max-width:34em;
}
.what-lead{
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:var(--fs-what);font-weight:400;line-height:1;
  letter-spacing:var(--track-seriously);margin:0;
}

/* TWO WAYS TO BUY. The page opens on the choice rather than on a list of media,
   because "a set of images" and "a system that keeps making them" are different
   purchases with different budgets, and a reader who does not know which one
   they want cannot read the prices further down. */
/* The section's heading, borrowed from the open-step setting: purple serif at
   the same clamp. It names a choice inside the page rather than opening a
   chapter, so it deliberately does NOT use --fs-seriously — a fifth 175px title
   here would flatten the four that give the page its structure.
   Purple on paper measures 8.47, so it is legal at any size, not just this one. */
.buys-title{
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:clamp(22px,3vw,40px);font-weight:400;
  letter-spacing:-.028em;line-height:1.05;color:var(--purple);
  max-width:20em;margin-bottom:clamp(26px,3.2vw,46px);
}

.buys{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(16px,2vw,28px)}
.buy{
  border-top:2px solid var(--purple);padding-top:clamp(18px,2vw,26px);
  display:flex;flex-direction:column;gap:12px;
}
.buy-kicker{
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:var(--track-mono);
  text-transform:uppercase;color:var(--purple);
}
.buy-name{
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:clamp(26px,3.2vw,46px);font-weight:400;line-height:1;letter-spacing:-.03em;
}
.buy-body{font-size:var(--fs-note);line-height:1.5;max-width:30em}

/* The source frame and its outputs. The source sits alone and large because the
   whole claim is that it is the only expensive thing on the page. */
.derive{
  display:grid;grid-template-columns:minmax(0,300px) 1fr;
  gap:clamp(24px,3.4vw,56px);align-items:start;
  margin-top:clamp(36px,4.5vw,64px);
}
.derive-source{
  aspect-ratio:3/4;background:var(--greige);overflow:hidden;position:relative;
  display:grid;place-items:center;
}
.derive-source img{width:100%;height:100%;object-fit:cover}
/* Two cases stacked: enough air that each reads as its own proof, not so much
   that the second looks like a new section. */
.derive + .derive{margin-top:clamp(56px,7vw,112px)}
.derive-label{
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:var(--track-mono);
  text-transform:uppercase;color:var(--mono-dim);margin-bottom:12px;display:block;
}
/* Stacked, the fan follows the source as a sequence rather than sitting beside
   it, so it needs space of its own above the label. */
/* THE BAND STACKS BEFORE THE REST OF THE PAGE DOES. Everything else collapses
   at 1000, but the trio is sized to the first column of .band-split and that
   column runs out sooner: at 1001 it is 279px and "No limitations." needs 323px
   at the size the clamp gives there. Measured — below this the trio takes the
   full measure and the note drops beneath it, which is what happens on a phone
   anyway. Specificity matches .band-split .nos (0,2,0); a `.band-split > *`
   shorthand is one class lighter and quietly loses. */
@media (max-width:1150px){
  .band-split .nos,
  .band-split .band-note,
  .band-split .band-link{grid-column:1;grid-row:auto}
  .band-split .band-note{margin-top:0;padding-top:0}
}

@media (max-width:1000px){ .derive > * + *{margin-top:clamp(28px,3.5vw,44px)} }
/* THE FAN-OUT: EQUAL ROW HEIGHTS, NOTHING CROPPED.
   A uniform square grid would crop all ten — the set is four 3:2 landscapes and
   six 3:4 portraits, and "equal cell" and "uncropped" cannot both hold with
   mixed ratios. So the constant is the ROW instead of the cell: each item grows
   by its own aspect against a zero basis, which makes every image in a row the
   same height and the row flush at both ends. The image keeps its proportion
   and the box is whatever that proportion makes it — no object-fit, nothing to
   crop. The two rows are ordered to carry near-identical aspect sums, so they
   also come out the same height as each other. */
.fanout{display:flex;flex-direction:column;gap:var(--gutter)}
.fan-row{display:flex;gap:var(--gutter);flex-wrap:wrap}
.fan-item{margin:0;position:relative;background:var(--greige);min-width:112px}
.fan-item img{width:100%;height:auto;display:block}
.fan-item::after{
  content:'';position:absolute;inset:0;background:var(--purple);
  opacity:0;transition:opacity .15s;pointer-events:none;
}
.fan-item:hover::after{opacity:.16}

/* WHAT HOLDS / WHAT MOVES. The mechanism, stated as two lists. This is the most
   load-bearing copy on the page: anyone can write "scalable image libraries",
   and only somebody who has built one of these can say precisely which
   properties are locked and which are free. Specificity is the credential. */
.holds{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(24px,3.4vw,56px);align-items:start}
.holds h3{
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:var(--track-mono);
  text-transform:uppercase;color:var(--purple);
  padding-bottom:12px;border-bottom:1px solid var(--hairline);
}
.holds ul{list-style:none;display:flex;flex-direction:column;gap:0;margin-top:4px}
.holds li{
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:clamp(17px,1.7vw,22px);line-height:1.3;letter-spacing:-.015em;
  padding:11px 0;border-bottom:1px solid var(--hairline);
}
.holds--moves li{font-style:italic;color:var(--mono-dim)}

/* The cost line. No invented figures anywhere — a season's costs are named as
   categories, because the reader already knows their own numbers and an
   invented one would be the first thing they caught. */
.costs{
  list-style:none;display:flex;flex-wrap:wrap;gap:8px;margin-top:clamp(20px,2.4vw,32px);
}
.cost-chip{
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:var(--track-mono);
  text-transform:uppercase;color:var(--mono-dim);
  border:1px solid var(--hairline);padding:7px 12px;
}
.cost-chip--gone{text-decoration:line-through;color:var(--mono-dim)}
/* WHAT YOU STILL PAY FOR IS FILLED, NOT OUTLINED — the three that survive are
   the product, and an outline reads as another absence. Ink on ochre is 5.84,
   which passes AA at 11px, so this is one of the few places either of the two
   light grounds can carry small type. */
.cost-chip--kept{
  background:var(--ochre);border-color:var(--ochre);color:var(--ink);
}

/* --- numbered accordion (method + questions) ------------------------------ */
/* Full-width rows, big serif, tabular number, hairline between. A better home
   for method and FAQ than a card grid: it reads as a list of answers rather
   than a list of features, and <details> gives it keyboard support for free. */
.steps{border-top:1px solid var(--hairline)}
.steps details,.steps .step{border-bottom:1px solid var(--hairline)}
.steps summary{
  list-style:none;cursor:pointer;padding:clamp(16px,2vw,26px) 0;
  display:grid;grid-template-columns:auto 1fr auto;gap:clamp(14px,2vw,28px);
  align-items:baseline;transition:color .15s;
}
.steps summary::-webkit-details-marker{display:none}
.steps summary::after{content:'+';font-family:var(--font-mono);font-size:16px;color:var(--purple)}
.steps details[open] summary::after{content:'\2013'}
.steps summary:hover,.steps details[open] summary{color:var(--purple)}
.step-num{
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:var(--track-mono);
  color:var(--purple);font-variant-numeric:tabular-nums;
}
.step-title{
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:clamp(22px,3vw,40px);font-weight:400;letter-spacing:-.028em;line-height:1.05;
}
.step-body{
  padding:0 0 clamp(20px,2.4vw,32px);
  display:grid;grid-template-columns:auto 1fr;gap:clamp(14px,2vw,28px);
}
.step-body > div{max-width:var(--measure);font-size:var(--fs-note);line-height:1.5}
.step-body p + p{margin-top:.9em}
.step-body ul{margin:.9em 0 0 1.1em;display:flex;flex-direction:column;gap:4px}
/* The short answer, in the studio's own register: the question gets one line
   before the explanation starts. */
.qa-short{
  font-family:var(--font-display);font-optical-sizing:auto;font-style:italic;
  font-size:var(--fs-lead);line-height:1.3;color:var(--purple);margin-bottom:.6em;
}
/* Spacer so a non-collapsing step aligns with the accordion rows above it. */
.step-gutter{width:2.4em}

/* --- statement / mail ----------------------------------------------------- */
.statement{
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:clamp(34px,5vw,64px);font-weight:400;line-height:1.06;
  letter-spacing:-.028em;max-width:15em;text-wrap:balance;
}
.statement em{font-style:italic;color:var(--purple)}
.band .statement em{color:var(--ochre)}   /* large display only — 3.06 */
.statement-cta{margin-top:clamp(28px,3.4vw,44px)}

.mail{
  display:inline-flex;align-items:center;gap:.4em;flex-wrap:wrap;
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:clamp(24px,5.6vw,72px);font-weight:500;letter-spacing:var(--track-display);
  line-height:1.05;transition:color .15s;white-space:nowrap;
}
/* word-break:break-word USED TO LIVE HERE and it broke the address mid-domain
   — "hello@seriouslywow.c / om" — which is worse than any overflow it avoided.
   The address is 9.76em wide, the gap .4em and the chip .775em (it is .5em set
   at 1.55em square), so the whole thing needs 10.94em. Against the full measure
   that clears at every width the clamp produces, down to 320: 24px x 10.94 =
   262px inside a 280px measure. It only failed because it was set in a 620px
   column, which is what .contact-mail below fixes. flex-wrap stays on, so at
   some impossible width the chip drops rather than the domain splitting. */
.mail:hover{color:var(--purple)}
.mail--sm{font-size:clamp(22px,3.3vw,44px)}
/* Arrow chip. Two separate centring problems, both measured rather than eyed.

   THE CHIP AGAINST THE ADDRESS. align-items:center centres it on the LINE BOX,
   which is not where the words look centred. Measured on Source Serif 4 at the
   address size: font ascent 1.0375em, descent 0.3276em, line-height 1.05 — so
   the baseline sits 48.34 of 57.68px down the line box, and the ink centre of
   "hello@seriouslywow.com" lands at 34.91 against a line-box centre of 28.84.
   The chip therefore moves DOWN 0.221em of its own size, not up. It carried
   -.34em inherited from the parent repo, where the face is Inter and the
   ascent is far shorter; that value was simply wrong here, by 0.56em.
   Everything in the sum is em-based, so it holds at .mail--sm too.

   THE ARROW INSIDE THE CHIP. place-items:center centres the arrow's line box,
   and its ink sits high of that, so .2em of bottom padding drops the content
   box by half that and lands the glyph on the disc's centre. The stroke, not
   the weight, is what thickens it — font-weight does nothing to this glyph. */
.chip{
  display:inline-grid;place-items:center;width:1.55em;height:1.55em;line-height:1;
  background:var(--purple);color:var(--on-purple);font-size:.50em;border-radius:50%;
  flex:none;transform:translateY(.221em);padding-bottom:.2em;
  -webkit-text-stroke:.035em currentColor;
}
.band .chip{background:var(--on-purple);color:var(--purple)}
.contact-block{display:flex;flex-direction:column;gap:10px;align-items:flex-start}
.contact-block a:hover{color:var(--purple)}
.contact-layout{
  display:grid;grid-template-columns:1fr minmax(300px,460px);
  gap:clamp(32px,5vw,80px);align-items:start;padding-block:0 var(--pad-section);
}
.contact-main{display:flex;flex-direction:column;gap:clamp(24px,3.2vw,44px)}

/* THE ADDRESS TAKES THE WHOLE MEASURE, not the left column. In a 620px column
   it can only hold one line at 55px, against the 72px the clamp asks for; over
   the full 1152px it needs 787px and keeps its size. It is the page's one call
   to act, so it reads as a banner across the top rather than as the first item
   of a list. */
.contact-mail{grid-column:1/-1}

/* The film is square — 1996 x 1996, an 8.7s loop — so it is sized by the column
   rather than cropped into a band. It closes the left column, which is short
   next to the form; without it the form leaves that side empty below the copy.
   site.js pauses any video[autoplay] under prefers-reduced-motion and hands
   back the controls, so this needs nothing of its own. */
.contact-film{margin:0;background:var(--greige)}
.contact-film video{width:100%;height:auto;display:block;aspect-ratio:1/1;object-fit:cover}
.contact-film figcaption{margin-top:12px}

/* --- form ----------------------------------------------------------------- */
/* Netlify handles the POST — data-netlify plus the hidden form-name field,
   which is what the live build already used. No script, no dependency.
   The form sits on a purple card, so it reads as the page's one call to act. */
.form{
  background:var(--purple);color:var(--on-purple);
  padding:clamp(24px,3vw,40px);display:flex;flex-direction:column;gap:16px;
}
.form-h{
  font-family:var(--font-display);font-optical-sizing:auto;font-style:italic;
  font-size:var(--fs-lead);line-height:1.3;margin-bottom:4px;
}
.field{display:flex;flex-direction:column;gap:5px}
.field label{
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:var(--track-mono);
  text-transform:uppercase;color:var(--on-purple-dim);
}
.field input,.field textarea,.field select{
  font:inherit;font-size:var(--fs-note);color:var(--on-purple);
  background:transparent;border:0;border-bottom:1px solid var(--on-purple-dim);
  padding:8px 0;width:100%;transition:border-color .15s;
}
.field textarea{resize:vertical;min-height:88px;line-height:1.6}
/* Placeholders are examples, not labels — but they still have to be readable.
   --on-purple-dim measures 5.24 on the card; a browser default placeholder is
   the text colour at roughly half alpha, which would not clear 4.5. */
.field ::placeholder{color:var(--on-purple-dim);opacity:1}

/* SELECTS. appearance:none is what lets a select carry the same borderless
   underline as the inputs beside it — a native control keeps its own box and
   ground and would read as a different kind of field on this card. The arrow
   is then ours to draw, below. padding-right keeps a long option clear of it. */
.field select{appearance:none;-webkit-appearance:none;padding-right:1.6em;cursor:pointer}
/* The OPEN list is painted by the OS, not by this stylesheet, and it does not
   inherit the card. Left alone, several platforms render --on-purple text on a
   white system menu. Stating both ends puts it back at 15.2. */
.field select option{color:var(--ink);background:var(--paper)}
/* The indicator, drawn from two borders so it stays on a token rather than
   being baked into an SVG data URI. .field is the label+control column, so the
   chevron is measured from the BOTTOM of it — the control is the last child —
   and sits on the select's own centre line. */
.field--select{position:relative}
.field--select::after{
  content:'';position:absolute;right:3px;bottom:1.05em;
  width:.42em;height:.42em;font-size:var(--fs-note);
  border-right:2px solid var(--on-purple);border-bottom:2px solid var(--on-purple);
  transform:rotate(45deg);pointer-events:none;
}
.field input:focus,.field textarea:focus,.field select:focus{outline:0;border-bottom-color:var(--ochre)}
/* A 1px underline changing colour is a weak thing to hunt for with a keyboard,
   and ochre on purple is 3.06 — legal for a non-text mark, but only just. This
   adds a real ring for keyboard users only: :focus-visible does not fire on a
   mouse click, so the quiet treatment above still holds for pointer users.
   --on-purple on the card is 8.46. */
.field input:focus-visible,.field textarea:focus-visible,.field select:focus-visible{
  outline:2px solid var(--on-purple);outline-offset:3px;
}
.send{
  align-self:flex-start;margin-top:8px;cursor:pointer;
  background:var(--on-purple);color:var(--purple);border:0;
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:var(--track-mono);
  text-transform:uppercase;padding:12px 22px;transition:opacity .15s;
}
.send:hover{opacity:.86}
/* Anti-spam with no script and no service: a field a person never sees. */
.hp{position:absolute;left:-9999px}

/* --- footer --------------------------------------------------------------- */
.footer{background:var(--purple);color:var(--on-purple);padding:clamp(48px,6vw,88px) 0 32px}
/* TWO COLUMNS, NOT THREE. The middle one was Group, and the group is now
   stated in .network below — once, in the row all three sites share, rather
   than twice in two different shapes. */
.foot-cols{display:grid;grid-template-columns:repeat(2,1fr);gap:32px}
.foot-col{display:flex;flex-direction:column;align-items:flex-start;gap:9px}
.foot-h{
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:var(--track-mono);
  text-transform:uppercase;color:var(--on-purple-dim);margin-bottom:6px;
}
.foot-col a,.foot-col address,.foot-col span:not(.foot-h){font-size:20px;letter-spacing:-.012em}
/* 15px on the purple footer: ochre would be 3.06 and needs 4.5. The underline
   carries the colour instead and the link text holds at 8.46. */
.foot-col a:hover{
  text-decoration:underline;text-decoration-color:var(--ochre);
  text-decoration-thickness:2px;text-underline-offset:.22em;
}
.footer .todo-inline{background:rgba(242,240,234,.16);color:var(--on-purple-dim)}
/* THE GUILD IS THE MASTER SITE. Two studios sit below it, not four. Strange
   Worlds and Sir Woof retire from public view — that easter egg was the only
   place this site asserted a group structure, and it contradicted the real one. */
.foot-guild{
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:19px;font-weight:600;letter-spacing:-.02em;
}
/* ============================================================================
   THE NETWORK LINE. One component, shared verbatim across sillywizardsguild.com,
   seriouslywow.com and standardwork.design — same class names, same markup
   shape, same place: the last row above the closing lock. Two things differ per
   site, both on purpose: the LABEL, because each site sits differently in the
   group, and the FACE of .network-link, because each site sets it in its own
   display face. Here that is the serif, matching what .foot-guild already did
   for the Guild link this row replaces.

   THIS ROW IS ON THE PURPLE, so it takes the purple's values and not the
   page's: --on-purple-dim is 5.24 and carries the 14px label, --on-purple is
   8.46 and carries the link. THE HOVER IS AN UNDERLINE, NOT A COLOUR, for the
   reason written above .foot-col a:hover — ochre on purple is 3.06 and the link
   text has to hold at 8.46. Same rule, same fix.
   ========================================================================== */
.network{
  display:flex;justify-content:flex-end;align-items:baseline;gap:14px 32px;flex-wrap:wrap;
  margin-top:clamp(40px,5vw,72px);padding-top:20px;border-top:1px solid var(--on-purple-dim);
}
.network-item{display:inline-flex;align-items:baseline;gap:14px;flex-wrap:wrap}
.network-label{font-size:14px;color:var(--on-purple-dim)}
.network-link{
  font-family:var(--font-display);font-optical-sizing:auto;
  font-size:19px;font-weight:600;letter-spacing:-.02em;color:var(--on-purple);
  white-space:nowrap;
}
.network-link:hover{
  text-decoration:underline;text-decoration-color:var(--ochre);
  text-decoration-thickness:2px;text-underline-offset:.22em;
}

.foot-lock{
  display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap;
  margin-top:clamp(40px,5vw,72px);padding-top:20px;border-top:1px solid var(--on-purple-dim);
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:var(--track-mono);
  text-transform:uppercase;color:var(--on-purple-dim);
}
.foot-mark{width:10px;height:10px;background:var(--ochre);flex:none}

/* --- responsive ----------------------------------------------------------- */
@media (max-width:1000px){
  /* One column. The picture leads, because the sentence is the thing it is
     evidence for and evidence reads better before the claim at this width. */
  .what-grid{grid-template-columns:1fr;gap:clamp(26px,4vw,40px)}
}

@media (max-width:1000px){
  .plans{grid-template-columns:repeat(2,1fr)}
  .plan{min-height:clamp(380px,52vw,520px)}
  .chapter{grid-template-columns:1fr}
  /* The note goes back under the statement rather than beside it; at this width
     a 26em column next to a 108px headline leaves neither enough room. */
  .band-split{grid-template-columns:1fr;gap:clamp(28px,4vw,44px)}
  /* Stacked, placement is source order: statement, qualifier, link. Written at
     the same specificity as the placements above — `.band-split > *` is one
     class lighter than `.band-split .nos` and quietly loses, which left the
     note pinned to a second column that no longer existed. */
  .hero-body{grid-template-columns:1fr;align-items:start}
  .contact-layout{grid-template-columns:1fr}
  .derive{grid-template-columns:1fr}
  /* Stays 3:4 when stacked. The 16:9 this used to be was sized for the empty
     placeholder box; with the real frame in it, a landscape crop would cut the
     top and bottom off a standing bottle — the one frame that must be shown
     whole, since everything beside it comes out of it. */
  .derive-source{max-width:420px}
  .buys,.holds{grid-template-columns:1fr}
}
/* Three 2:3 columns need roughly 260px each to stay a frame rather than a
   sliver; below that they stack and each one takes the full width at a shorter
   ratio, because a full-width 2:3 frame on a phone is two screens tall. */
@media (max-width:820px){
  .pillars{grid-template-columns:1fr}
  /* 4:5 rather than 2:3: a full-width 2:3 frame on a phone is most of a screen
     each, three times over. Against the 3:4 sources this crops 33px off the
     height and nothing off the width, so no object-position correction is
     needed — the figures stay whole. */
  .pillar{aspect-ratio:4/5;max-height:none}
}

@media (max-width:700px){
  /* --nav-h TRACKS THE NAV'S ACTUAL GEOMETRY. The nav is fixed, so every page
     that does not open on a frame reserves this much at the top of <main>; if
     the token and the measured height disagree, content slides under the bar.
     Here the lockup drops to 28px: 28 + 16 + 16 + 1 = 61. */
  :root{--nav-h:61px}
  /* The mosaic collapses to a 2-column grid, and anything wider than a half
     becomes full width. A third-width tile at 375 is a thumbnail. */
  .mosaic{grid-template-columns:repeat(2,1fr)}
  .tile{grid-column:span 2}
  .tile[data-span="2"],.tile[data-span="3"]{grid-column:span 1}
  .plans{grid-template-columns:1fr}
  .plan{min-height:0}
  .foot-cols{grid-template-columns:1fr;gap:32px}
  .network{justify-content:flex-start}
  .nav-links{gap:15px}
  .nav-links a{font-size:14px}
  /* 17px made the stacked lockup 46px wide — unreadable. Below 420 the links
     drop to their own row anyway, so the mark has the height to spare. */
  .nav-name img{height:28px}
  .steps summary{grid-template-columns:auto 1fr auto;gap:12px}
  .step-body{grid-template-columns:1fr}
  .step-gutter{display:none}
  /* Rows wrap inside themselves on a phone rather than restructuring —
     each wrapped line still justifies, so the treatment survives. */
  .fan-item{min-width:132px}
  /* Four of the six scatter frames come out on a phone. Six frames pinned to
     the edges of a 375px screen leave no middle for the title to sit in; the
     two that stay are the ones that frame it rather than crowd it. */
  .scatter figure:nth-child(2),
  .scatter figure:nth-child(3),
  .scatter figure:nth-child(5),
  .scatter figure:nth-child(6){display:none}
  .scatter figure:nth-child(1){height:min(30vh,52vw)}
  .scatter figure:nth-child(4){height:min(28vh,46vw)}
}
@media (max-width:420px){
  /* Two rows now: 28px lockup + 8px gap + a 22px links row + 16 + 16 + 1 = 91. */
  :root{--nav-h:91px}
  /* Four serif nav items no longer fit beside the lockup. The links wrap to
     their own row rather than the wordmark shrinking to nothing. */
  .nav-in{flex-wrap:wrap;gap:8px}
  .nav-links{width:100%;justify-content:space-between;gap:8px}
}

/* --- motion — near zero, and honoured ------------------------------------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{transition:none!important;animation:none!important;scroll-behavior:auto!important}
}

/* ==========================================================================
   THE PURPLE PAGE
   One inversion on a wrapper class, exactly as the Guild does it with
   body.page-red. Ground and ink trade places; the accent collapses onto the ink.
   Nothing here restyles a component — it only redefines what tokens mean.

   NOT APPLIED TO ANY PAGE. Which surface inverts is unassigned and blocked
   (§9). Assigning it is `<body class="page-purple">` and nothing else moves.

   Note this site now uses purple as a surface in several places already — the
   band, the plans, the form, the footer — so a fully purple PAGE is a bigger
   gesture here than the red About is on the Guild. That is a reason to place it
   deliberately, not a reason to avoid it.
   ========================================================================== */
.page-purple{
  --paper:#453592;
  --ink:#F2F0EA;
  --purple:#F2F0EA;              /* the accent was purple; on purple it is ink */
  --on-purple:#453592;           /* so type on the accent is the ground */
  --mono-dim:rgba(242,240,234,.72);
  --greige:rgba(242,240,234,.16);
  --hairline:rgba(242,240,234,.30);
  background:var(--paper);color:var(--ink);
}
/* Orange is 3.06 on this ground too, so it keeps its one job and its one rule:
   large display type only. The bands and cards inside an inverted page invert
   with it, which is why they are not given a second value here. */
.page-purple ::selection{background:var(--ink);color:var(--paper)}
/* The lockup is a black alpha file, so it does not invert with the tokens the
   way type does — it would sit black on purple. Same one-line fix the nav uses
   over the opening frame, and the reason .page-purple is genuinely one class:
   without this, choosing the inversion would also mean fixing a bug. */
.page-purple .nav-name img{filter:invert(1)}
