/* =========================================================================
   Northlight — what every page on seewest.co.uk shares.

   Tokens, the type, the grid, and the components the kit defines: badge,
   text link, button, dot grid, spec list, header bar, segmented control,
   fields, the photograph placeholder, the photograph grid, the footer row
   and the scroll reveals. Anything that belongs to one page stays in that
   page.

   One family (Hanken Grotesk), a grey page, hairlines instead of shadows,
   and one orange: the primary action, the live dot, the full stop that
   ends a heading, and the underline under whatever is pointed at.
   ========================================================================= */
@font-face{font-family:'Hanken Grotesk';font-style:normal;font-weight:100 900;font-display:swap;
  src:url('/fonts/HankenGrotesk-latin-0.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}

/* ---------------------------------------------------------------- tokens */
:root{
  --grey-0:#FFFFFF;--grey-50:#FAFAF9;--grey-100:#F5F5F3;--grey-150:#EBEBE8;--grey-200:#DDDDD9;
  --grey-250:#D4D4D0;--grey-300:#BDBDB8;--grey-400:#9E9E99;--grey-500:#8B8B86;--grey-600:#737370;
  --grey-700:#575754;--grey-800:#3A3A38;--grey-900:#1F1F1E;
  --orange-500:#E4572E;--orange-600:#CC4A24;--orange-700:#B03E1D;--red-600:#A5402F;

  --surface-page:var(--grey-100);--surface-raised:var(--grey-50);--surface-sunken:var(--grey-150);
  --surface-photo:var(--grey-200);--surface-inverse:var(--grey-900);
  --text-primary:var(--grey-900);--text-secondary:var(--grey-700);--text-tertiary:var(--grey-600);
  --text-quiet:var(--grey-400);--text-inverse:var(--grey-100);--text-error:var(--red-600);
  --line-hairline:var(--grey-250);--line-strong:var(--grey-300);--line-ink:var(--grey-900);
  --dot:var(--grey-300);--dot-active:var(--orange-500);
  --action:var(--orange-500);--action-hover:var(--orange-600);--action-press:var(--orange-700);--action-ink:var(--grey-0);
  --focus-ring:var(--grey-900);
  /* The white a control sits on: the segmented control's pill, a switch's
     knob. Its own name so the dark set below can make it something other
     than white. */
  --surface-control:var(--grey-0);
  --surface-inverse-press:var(--grey-800);

  --font-sans:'Hanken Grotesk','Helvetica Neue',Helvetica,Arial,sans-serif;
  --size-display-xl:72px;--size-display-l:52px;--size-display-m:36px;--size-title:22px;
  --size-body-l:17px;--size-body:15px;--size-small:13px;--size-micro:11px;
  --type-title:500 var(--size-title)/1.25 var(--font-sans);
  --type-body:400 var(--size-body)/1.55 var(--font-sans);
  --type-small:400 var(--size-small)/1.4 var(--font-sans);
  --type-label:500 var(--size-micro)/1.3 var(--font-sans);
  --type-wordmark:700 14px/1 var(--font-sans);

  --space-4:16px;--space-6:24px;--space-7:28px;--space-8:36px;--space-9:40px;--space-10:56px;--space-11:80px;--space-12:120px;
  --grid-gutter:12px;--page-max:1280px;--margin:56px;
  --radius-md:8px;--radius-pill:999px;
  --border-hairline:1px solid var(--line-hairline);

  --ease-standard:cubic-bezier(0.2,0,0,1);
  --dur-fast:120ms;--dur-base:180ms;--dur-slow:320ms;
  /* Scroll reveals only. Longer than a hover because they cover distance,
     on the same curve so nothing arrives with a bounce. */
  --dur-reveal:1000ms;
}
/* The dark set. Only the client gallery offers it today — a switch in its
   header, remembered as "cw-theme" in the visitor's browser — so nothing
   else on the site ever has data-theme set. The light set above is still
   the site; this is the same page with the lights down for someone looking
   at their photographs at night.

   Only the meanings change, never the grey ramp, so every rule that says
   --text-primary or --surface-page follows without being touched. The page
   is a warm near-black rather than pure black, the same yellowish neutral
   as the light greys, so the photographs sit on a grey and not a hole. The
   orange stays exactly the orange: it is the one colour the site has. */
:root[data-theme="dark"]{
  --surface-page:#161615;--surface-raised:#1F1F1E;--surface-sunken:#262624;
  --surface-photo:#2C2C2A;--surface-inverse:var(--grey-100);--surface-control:#3A3A38;--surface-inverse-press:var(--grey-300);
  --text-primary:var(--grey-150);--text-secondary:var(--grey-300);--text-tertiary:var(--grey-400);
  --text-quiet:var(--grey-600);--text-inverse:var(--grey-900);--text-error:#E07A64;
  --line-hairline:#333331;--line-strong:#4A4A47;--line-ink:var(--grey-150);
  --dot:#4A4A47;
  --focus-ring:var(--grey-150);
  color-scheme:dark;
}
@media (max-width:1023.98px){:root{--margin:28px;--space-12:88px}}
@media (max-width:479.98px){:root{--margin:20px}}

/* ------------------------------------------------------------------ base */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{margin:0;background:var(--surface-page);color:var(--text-primary);font:var(--type-body);
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;overflow-x:clip}
img{display:block;max-width:100%}
a{color:inherit}
button,input,textarea{font:inherit;color:inherit}
::selection{background:var(--surface-inverse);color:var(--text-inverse)}
:focus-visible{outline:2px solid var(--focus-ring);outline-offset:3px}
.skip{position:absolute;left:-10000px;top:12px;background:var(--surface-inverse);color:var(--text-inverse);padding:10px 14px;border-radius:var(--radius-pill);font:var(--type-small);z-index:10}
.skip:focus{left:12px}
[hidden]{display:none!important}
.vh{position:absolute!important;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

.wrap{max-width:var(--page-max);margin:0 auto;padding:0 var(--margin)}
/* viewport-fit=cover lets the page run under an iPhone's notch and round
   corners, which turned sideways trimmed the edges. The margin is never
   less than the space they take. */
.wrap{padding-left:max(var(--margin),env(safe-area-inset-left));padding-right:max(var(--margin),env(safe-area-inset-right))}
.grid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));column-gap:var(--grid-gutter)}
@media (max-width:1023.98px){.grid{grid-template-columns:repeat(6,minmax(0,1fr))}}

.quiet{color:var(--text-quiet)}
/* A heading's full stop, in the one orange. */
.stop{color:var(--action)}
.display-xl{margin:0;font-weight:300;font-size:clamp(44px,6vw,var(--size-display-xl));line-height:1;letter-spacing:-0.03em;text-wrap:balance}
.display-l{margin:0;font-weight:300;font-size:clamp(36px,4.2vw,var(--size-display-l));line-height:1.04;letter-spacing:-0.025em;text-wrap:balance}

/* ------------------------------------------------------------ components */
.badge{display:inline-flex;align-items:center;gap:8px;font:var(--type-small);color:var(--text-primary)}
.badge::before{content:"";width:8px;height:8px;border-radius:50%;background:var(--dot-active);flex:none}

.textlink{align-self:flex-start;font:500 var(--size-small)/1.4 var(--font-sans);color:var(--text-primary);text-decoration:none;
  border-bottom:1px solid var(--line-strong);padding-bottom:2px;transition:border-color var(--dur-fast) var(--ease-standard)}
.textlink:hover{border-bottom-color:var(--action)}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;border-radius:var(--radius-pill);border:1px solid transparent;
  font:500 14px/1 var(--font-sans);padding:13px 20px;cursor:pointer;text-decoration:none;white-space:nowrap;
  transition:background var(--dur-base) var(--ease-standard),color var(--dur-base) var(--ease-standard),border-color var(--dur-base) var(--ease-standard)}
.btn--lg{padding:16px 26px;font-size:16px}
.btn--sm{padding:9px 14px;font-size:13px}
.btn--primary{background:var(--action);color:var(--action-ink)}
.btn--primary:hover{background:var(--action-hover)}
.btn--primary:active{background:var(--action-press)}
.btn--outline{background:transparent;color:var(--text-primary);border-color:var(--line-strong)}
.btn--outline:hover{background:var(--surface-inverse);color:var(--text-inverse);border-color:var(--surface-inverse)}
.btn--outline:active{background:var(--surface-inverse-press)}
.btn[disabled]{background:var(--surface-photo);color:var(--text-quiet);cursor:default}


.dots{display:grid;grid-template-columns:repeat(9,6px);gap:7px}
.dots i{width:6px;height:6px;border-radius:50%;background:var(--dot);transition:background var(--dur-base) var(--ease-standard)}
.dots i.is-on{background:var(--dot-active)}

.spec{margin:0;display:flex;flex-direction:column;gap:18px}
.spec dt{font:var(--type-label);letter-spacing:0.02em;color:var(--text-tertiary);margin:0 0 6px}
.spec dd{margin:0;font:var(--type-body)}
.spec a{text-decoration:none;border-bottom:1px solid var(--line-strong);transition:border-color var(--dur-fast) var(--ease-standard)}
.spec a:hover{border-bottom-color:var(--action)}

/* ---------------------------------------------------------------- header */
.bar{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));column-gap:var(--grid-gutter);align-items:center;padding:22px 0;border-bottom:var(--border-hairline)}
.wordmark{grid-column:1/4;font:var(--type-wordmark);text-decoration:none;justify-self:start}
.nav{grid-column:4/7;display:flex;justify-content:space-between;gap:12px}
.nav a{font:var(--type-small);color:var(--text-tertiary);text-decoration:none;padding-bottom:3px;border-bottom:1px solid transparent;
  transition:color var(--dur-fast) var(--ease-standard),border-color var(--dur-fast) var(--ease-standard)}
.nav a:hover,.nav a[aria-current="page"]{color:var(--text-primary);border-bottom-color:var(--action)}
@media (max-width:599.98px){.wordmark{grid-column:1/3}.nav{grid-column:3/7}}

/* The headline arrives a word at a time, each rising out of its own line box. */
.words .w{display:inline-block;overflow:hidden;vertical-align:top;padding-bottom:0.1em;margin-bottom:-0.1em}
.words .w>span{display:inline-block}
.js .words .w>span{transform:translate3d(0,108%,0);transition:transform var(--dur-reveal) var(--ease-standard);transition-delay:calc(var(--i,0) * 55ms)}
.js .words.is-in .w>span{transform:none}

/* Where a photograph goes. Flat grey, labelled with the shape it wants —
   swap the element for an <img> with the same class and the motion carries on. */
.ph{position:relative;background:var(--surface-photo)}
.ph::after{content:attr(data-label);position:absolute;left:12px;bottom:10px;font:var(--type-label);letter-spacing:0.02em;color:var(--text-tertiary)}

/* ------------------------------------------------------- photograph grid
   Recent work on the home page and every album on /portfolio (js/work.js
   lays them out). The photographs at their own shapes, in columns that
   finish level; each rises into place as it's reached. Without script
   they sit in a plain grid. */
.work__head{padding-top:var(--space-12);padding-bottom:var(--space-8);align-items:end;row-gap:24px}
.work__head>h1,.work__head>h2{grid-column:1/10}
.work__all{grid-column:10/13;justify-self:end;margin-bottom:6px}
@media (max-width:1023.98px){.work__head>h1,.work__head>h2{grid-column:1/-1}.work__all{grid-column:1/-1;justify-self:start}}


.work__grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-8) var(--grid-gutter);align-items:start}
.work__grid.is-columns{display:flex;gap:var(--grid-gutter);align-items:flex-start}
.work__col{flex:1;min-width:0;display:flex;flex-direction:column;gap:var(--space-8)}
.frame{margin:0;display:flex;flex-direction:column;gap:10px;color:inherit;text-decoration:none}
.frame__img{position:relative;background:var(--surface-photo);overflow:hidden;aspect-ratio:var(--ar,2/3)}
.frame__img img,.frame__img .ph{display:block;width:100%;height:100%;object-fit:cover}
.js .frame__img img{opacity:0;transition:opacity var(--dur-slow) var(--ease-standard)}
.js .frame__img img.is-loaded{opacity:1}
.frame__zoom{display:block;width:100%;padding:0;border:0;cursor:zoom-in}
.frame__cap{display:flex;gap:12px;font:var(--type-small);color:var(--text-tertiary)}
.frame__cap>span:first-child{color:var(--text-quiet);font-variant-numeric:tabular-nums;flex:none}
/* The number's wheels: a window one figure tall on a strip of 0–9 twice
   over. As the photograph rises into view each strip turns through a full
   revolution to its own figure, each wheel a little longer than the one
   before, so they click into place left to right. */
.roll{display:inline-flex;vertical-align:top}
.roll__wheel{display:block;height:1.4em;overflow:hidden}
.roll__strip{display:block;transform:translate3d(0,calc(var(--to) * -1.4em),0)}
.roll__strip i{display:block;height:1.4em;font-style:normal;line-height:1.4em}
.js .frame .roll__strip{transform:none}
.js .frame.is-in .roll__strip{transform:translate3d(0,calc(var(--to) * -1.4em),0);
  transition:transform calc(900ms + var(--k,0) * 260ms) cubic-bezier(0.25,0.6,0.1,1) calc(280ms + var(--i,0) * 80ms)}
html.calm .frame .roll__strip{transform:translate3d(0,calc(var(--to) * -1.4em),0);transition:none}
@media (max-width:1023.98px){.work__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:599.98px){.work__grid{grid-template-columns:1fr}}

/* A photograph that leads to its gallery. Pointed at, it says where it
   goes, in the photograph's bottom left corner; on a touchscreen the album's name under
   it says the same. */
.frame__cat{margin-left:auto;padding-left:12px;color:var(--text-quiet);white-space:nowrap;transition:color var(--dur-fast) var(--ease-standard)}
.frame__more{position:absolute;left:14px;bottom:14px;z-index:2;display:inline-flex;align-items:center;gap:8px;padding:10px 14px;
  border-radius:var(--radius-pill);background:var(--grey-0);color:var(--text-primary);font:500 var(--size-small)/1 var(--font-sans);white-space:nowrap;
  opacity:0;transform:translate3d(0,8px,0);transition:opacity var(--dur-slow) var(--ease-standard),transform var(--dur-slow) var(--ease-standard)}
.frame__more svg{width:12px;height:12px;flex:none;color:var(--action)}
/* The chevron runs out of the right of its box and back in from the left,
   once, as the button comes up. */
@keyframes through{0%{transform:translateX(0)}45%{transform:translateX(13px)}45.1%{transform:translateX(-13px)}100%{transform:translateX(0)}}
.frame--link:hover .frame__more path,.frame--link:focus-visible .frame__more path{animation:through .7s var(--ease-standard) .12s}
.frame--link:hover .frame__more,.frame--link:focus-visible .frame__more{opacity:1;transform:none}
.frame--link:hover .frame__cat,.frame--link:focus-visible .frame__cat{color:var(--text-primary)}
@media (hover:none){.frame__more{display:none}}

/* ----------------------------------------------------------------- forms */
.form{display:flex;flex-direction:column;gap:var(--space-7)}
.seg{position:relative;display:inline-flex;flex-wrap:wrap;gap:2px;padding:3px;margin:0;border:0;border-radius:22px;background:var(--surface-sunken);align-self:flex-start;max-width:100%}
.seg label{position:relative;z-index:1;display:block}
.seg input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:pointer}
.seg span{display:block;padding:9px 16px;border-radius:var(--radius-pill);font:500 var(--size-small)/1 var(--font-sans);color:var(--text-tertiary);
  transition:background var(--dur-fast) var(--ease-standard),color var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard)}
.seg label:hover span{color:var(--text-primary)}
.seg input:checked+span{background:var(--surface-control);color:var(--text-primary);box-shadow:0 0 0 1px var(--line-hairline)}
.seg input:focus-visible+span{outline:2px solid var(--focus-ring);outline-offset:1px}
/* With script the white pill is one piece under the options: choosing
   another slides it across, gathering speed and stopping firmly, like a
   switch clicking over. The script sets where it sits. */
.seg__thumb{position:absolute;left:0;top:0;border-radius:var(--radius-pill);background:var(--surface-control);box-shadow:0 0 0 1px var(--line-hairline);pointer-events:none}
.seg.has-thumb .seg__thumb{transition:transform 380ms cubic-bezier(0.6,0,0.15,1),width 380ms cubic-bezier(0.6,0,0.15,1)}
.seg.has-thumb input:checked+span{background:none;box-shadow:none}
html.calm .seg .seg__thumb{transition:none}

.fields{display:grid;grid-template-columns:1fr 1fr;gap:20px}
.field{display:flex;flex-direction:column;gap:8px;min-width:0}
.field--wide{grid-column:1/-1}
.field>span{font:var(--type-label);letter-spacing:0.02em;color:var(--text-tertiary)}
.field input,.field textarea{width:100%;min-width:0;font:var(--type-body);color:var(--text-primary);background:var(--surface-raised);
  border:1px solid var(--line-hairline);border-radius:var(--radius-md);padding:12px 14px;outline:none;-webkit-appearance:none;appearance:none;
  transition:border-color var(--dur-fast) var(--ease-standard)}
.field input{min-height:47px}
/* iPhone Safari zooms the page in on any text box set smaller than 16px
   when it's tapped, and leaves it zoomed after: a gallery opened with its
   code then sat enlarged, its right edge off the screen and its header
   under the clock. At 16px on a touch screen it doesn't. Pinch-zoom is
   untouched. */
@media (pointer:coarse){.field input,.field textarea,.field select{font-size:16px}}
.field input::-webkit-date-and-time-value{text-align:left}
.field input::placeholder,.field textarea::placeholder{color:var(--text-quiet)}
.field input:focus,.field textarea:focus{border-color:var(--line-ink)}
.field textarea{resize:vertical;min-height:128px}
.field.has-error input{border-color:var(--red-600)}
.field input.is-empty{color:var(--text-quiet)}
.field em{font:var(--type-small);font-style:normal;color:var(--text-error)}
.hp{position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden}
@media (max-width:599.98px){.fields{grid-template-columns:1fr}}

/* ------------------------------------------------------------- the way out
   Get in touch, and a button to the enquiry form — the foot of every page
   but the home page, which has the form itself. */
.next{padding-top:var(--space-12);padding-bottom:var(--space-12);align-items:end;row-gap:var(--space-7)}
.next h2{grid-column:1/9}
.next .btn{grid-column:10/13;justify-self:end}
@media (max-width:1023.98px){.next h2{grid-column:1/-1}.next .btn{grid-column:1/-1;justify-self:start}}

/* ---------------------------------------------------------------- footer */
.foot{border-top:var(--border-hairline);padding-top:var(--space-10);padding-bottom:28px;overflow:hidden}
.foot__row{display:flex;flex-wrap:wrap;gap:12px 28px;font:var(--type-small);color:var(--text-tertiary)}
.foot__row a{text-decoration:none;transition:color var(--dur-fast) var(--ease-standard)}
.foot__row a:hover{color:var(--text-primary)}
.foot__row>span:first-child{margin-right:auto}
@media (max-width:599.98px){.foot__row>span:first-child{flex-basis:100%}}

/* --------------------------------------------------------------- reveals */
.js [data-reveal]{opacity:0;transform:translate3d(0,28px,0);
  transition:opacity .9s var(--ease-standard),transform var(--dur-reveal) var(--ease-standard);transition-delay:calc(var(--i,0) * 80ms)}
.js [data-reveal].is-in{opacity:1;transform:none}

/* ------------------------------------------------------------- calm mode */
html.calm{scroll-behavior:auto}
html.calm [data-reveal],html.calm .words .w>span{opacity:1;transform:none;transition:none}
html.calm .frame__more path{animation:none!important}
