/* ============================================================================
   Sundials by Robert Foster
   The plate book. An instrument maker's catalogue.

   Palette sampled from Robert's own photographs: the stone plinths, the brass,
   the bronze patina, the anodised rings. Type is EB Garamond, because his
   mottos are Latin and his numerals are Roman, with Archivo for chrome and data.

   Single deliberate world, light only. Every colour is painted explicitly so
   the page never borrows a host ground.
   ============================================================================ */

:root{
  --ground:#EAE5DA;
  --ground-2:#E1DACB;
  --ground-3:#D6CDBA;
  --ink:#211E19;
  --ink-2:#4A453C;
  --ink-3:#665F52;
  --brass:#8A6D28;
  --brass-lit:#C9A227;
  --patina:#4C5F52;
  --azure:#2E5C9A;
  --night:#14171C;
  --night-2:#1D2128;

  --serif:"EB Garamond",Georgia,"Times New Roman",serif;
  --sans:"Archivo","Helvetica Neue",Helvetica,Arial,sans-serif;

  /* type scale */
  --t-xs:13px; --t-sm:15px; --t-base:18px; --t-md:21px;
  --t-lg:24px; --t-xl:31px; --t-2xl:42px; --t-3xl:58px; --t-4xl:76px;

  /* measure and rhythm */
  --measure:66ch;
  --gut:clamp(20px,5vw,40px);
  --page:1180px;
  --s1:8px; --s2:14px; --s3:22px; --s4:34px; --s5:52px; --s6:78px; --s7:116px;
}

*,*::before,*::after{box-sizing:border-box}

html{-webkit-text-size-adjust:100%}

body{
  margin:0;
  background:var(--ground);
  color:var(--ink);
  font-family:var(--serif);
  font-size:var(--t-base);
  line-height:1.62;
  font-synthesis-weight:none;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}

img{max-width:100%;height:auto;display:block}

::selection{background:var(--brass);color:var(--ground)}

/* focus: visible, brass, never removed */
:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:2px solid var(--brass);
  outline-offset:3px;
  border-radius:1px;
}

/* Hidden by clipping, not by a negative offset: a -9999px element still
   widens the scrollable area on a 390px phone. */
.skip{
  position:absolute;top:0;left:0;z-index:99;
  width:1px;height:1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;
  background:var(--ink);color:var(--ground);
  font-family:var(--sans);font-size:var(--t-sm);
  padding:12px 18px;text-decoration:none;
}
.skip:focus{
  width:auto;height:auto;overflow:visible;
  clip:auto;clip-path:none;top:8px;left:8px;
}

/* ---------------------------------------------------------------- layout -- */

.wrap{max-width:var(--page);margin:0 auto;padding-inline:var(--gut)}
.wrap--narrow{max-width:760px}
.wrap--wide{max-width:1360px}

.stack>*+*{margin-top:var(--s3)}
.prose{max-width:var(--measure)}
.prose p{margin:0 0 1.15em}
.prose p:last-child{margin-bottom:0}

section{padding-block:var(--s6)}
section.tight{padding-block:var(--s5)}
section.loose{padding-block:var(--s7)}

.rule{height:1px;background:var(--ground-3);border:0;margin:0}

/* ------------------------------------------------------------- typography -- */

h1,h2,h3,h4{
  font-weight:400;margin:0;
  line-height:1.1;letter-spacing:-.005em;
  text-wrap:balance;
}
h1{font-size:clamp(var(--t-2xl),6.2vw,var(--t-4xl));line-height:1.02;letter-spacing:-.015em}
h2{font-size:clamp(var(--t-xl),4vw,var(--t-3xl));line-height:1.06;letter-spacing:-.01em}
h3{font-size:var(--t-lg)}
h4{font-size:var(--t-md)}

.lede{font-size:clamp(var(--t-md),2.2vw,var(--t-lg));line-height:1.5;color:var(--ink-2)}

/* The motto. Robert's own words, always italic, always his. */
.motto{
  font-family:var(--serif);font-style:italic;
  font-size:var(--t-md);line-height:1.45;color:var(--ink-2);
  text-wrap:balance;margin:0;
}
.motto cite{display:block;font-style:normal;font-family:var(--sans);
  font-size:var(--t-xs);color:var(--ink-3);margin-top:var(--s1);letter-spacing:.01em}

/* Section labels. Plain sentence case, NEVER tracked uppercase, and never
   preceded by a decorative dash. Both read as an AI tell. */
.label{
  font-family:var(--serif);font-size:var(--t-sm);font-weight:500;
  color:var(--ink-3);margin:0 0 var(--s2);
}

/* Roman plate numbers, as Robert numbers his own catalogue */
.plate-no{
  font-family:var(--serif);font-size:var(--t-sm);color:var(--ink-3);
  font-variant-numeric:tabular-nums;font-feature-settings:"smcp";
  display:inline-block;min-width:1.9em;   /* two digits and a full stop */
}

/* One serif, everywhere the reader reads. A blind critic put it plainly: with a
   Garamond name and a grotesque price stacked under it, "the most important
   number on the page is set in the least considered face", and the mismatch
   repeated across every tile in the grid. The sans is now reserved for things
   that are genuinely apparatus: form controls, and the workshop book. Sizes go
   up a step because an old-style serif sets visually smaller than a grotesque
   at the same nominal size. */
.meta{font-family:var(--serif);font-size:var(--t-sm);color:var(--ink-3);line-height:1.45}
.price{font-family:var(--serif);font-size:var(--t-md);font-weight:500;
  font-variant-numeric:tabular-nums;color:var(--ink);letter-spacing:.005em}
.price--lg{font-size:var(--t-md)}
.motto cite{font-family:var(--serif);font-size:var(--t-sm)}

a{color:var(--ink);text-decoration-thickness:1px;text-underline-offset:3px;
  text-decoration-color:var(--ground-3);transition:text-decoration-color .18s}
a:hover{text-decoration-color:var(--brass)}
a.plain{text-decoration:none}

/* ---------------------------------------------------------------- buttons -- */
/* Thin, outlined, understated. Never a saturated filled CTA. */

.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  font-family:var(--serif);font-size:var(--t-base);font-weight:500;
  color:var(--ink);background:transparent;
  border:1px solid var(--ink-3);border-radius:1px;
  padding:12px 22px;min-height:46px;
  text-decoration:none;cursor:pointer;
  transition:border-color .18s,background-color .18s,color .18s;
}
.btn:hover{border-color:var(--ink);background:rgba(33,30,25,.035)}
.btn--brass{border-color:var(--brass);color:var(--brass)}
.btn--brass:hover{background:rgba(138,109,40,.07);border-color:var(--brass);color:var(--brass)}
.btn--solid{background:var(--ink);color:var(--ground);border-color:var(--ink)}
.btn--solid:hover{background:#100E0B;color:var(--ground)}
.btn--sm{font-size:var(--t-sm);padding:8px 15px;min-height:38px}
.btn[disabled],.btn[aria-disabled="true"]{opacity:.42;cursor:not-allowed}

/* ----------------------------------------------------------------- plates -- */
/* The mat. Every photograph, portrait or landscape, occupies an identical
   rectangle on the same ground, so the collection reads as one collection.
   contain, never cover: nothing is cropped and nothing is upscaled. */

/* The photograph sits directly on the page ground, with no card behind it.
   Every plate crop is a true 4:5, so they line up without needing a mat to
   square them off, and a mat would turn each piece into a card. */
.plate{display:block;text-decoration:none;color:inherit}
.plate__frame{
  display:block;aspect-ratio:1/1;overflow:hidden;
  background:var(--ground-2);   /* only ever seen for a moment before load */
}
.plate__frame img{
  width:100%;height:100%;object-fit:cover;
  transition:transform .6s cubic-bezier(.22,.61,.36,1);
}
.plate:hover .plate__frame img{transform:scale(1.03)}

/* A photograph that was NOT cropped to a plate keeps its own shape and is
   contained, never stretched. */
.plate__mat{
  background:var(--ground-2);aspect-ratio:4/5;
  display:grid;place-items:center;padding:clamp(14px,2.4vw,26px);overflow:hidden;
}
.plate__mat img{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain}
.plate__mat--wide{aspect-ratio:3/2}
.plate__mat--tall{aspect-ratio:3/4}

.plate__body{padding-top:var(--s2);display:flex;flex-direction:column;gap:2px}
.plate__name{font-size:var(--t-md);line-height:1.25;font-family:var(--serif)}
.plate__name .plate-no{margin-right:.45em}
.plate:hover .plate__name{text-decoration:underline;text-decoration-color:var(--brass);
  text-decoration-thickness:1px;text-underline-offset:3px}
.plate .price{color:var(--ink-3);font-weight:400}

.grid{display:grid;gap:var(--s5) var(--s4)}
.grid--3{grid-template-columns:repeat(3,1fr)}
.grid--2{grid-template-columns:repeat(2,1fr)}
.grid--4{grid-template-columns:repeat(4,1fr)}

/* ------------------------------------------------------------------ night -- */
/* Used for the after-sunset dial state and the commission panel. Every colour
   is re-declared, never inherited, so nothing goes dark-on-dark. */

.night{background:var(--night);color:#E4DFD3}
.night h1,.night h2,.night h3,.night h4{color:#F0EBE0}
.night .lede,.night p{color:#BEB8AA}
.night .motto{color:#C9C2B2}
.night .meta,.night .label,.night .motto cite{color:#8E8779}
.night .price{color:#F0EBE0}
.night a{color:#E4DFD3;text-decoration-color:#3A3F47}
.night a:hover{text-decoration-color:var(--brass-lit)}
.night .btn{color:#E4DFD3;border-color:#5A5F68}
.night .btn:hover{border-color:#E4DFD3;background:rgba(240,235,224,.06)}
.night .btn--brass{color:var(--brass-lit);border-color:#7A6330}
.night .btn--brass:hover{background:rgba(201,162,39,.1);border-color:var(--brass-lit)}
.night .rule{background:#2C313A}
.night ::selection{background:var(--brass-lit);color:var(--night)}

/* ----------------------------------------------------------------- chrome -- */

.site-head{
  position:sticky;top:0;z-index:40;
  background:var(--ground);
  border-bottom:1px solid var(--ground-3);
}
.site-head__in{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  min-height:66px;
}
.brand{font-family:var(--serif);font-size:var(--t-md);letter-spacing:.005em;
  text-decoration:none;color:var(--ink);display:flex;align-items:center;gap:10px;white-space:nowrap}
.brand b{font-weight:500}
.brand small{font-family:var(--serif);font-size:var(--t-sm);color:var(--ink-3)}

.nav{display:flex;align-items:center;gap:var(--s3);font-family:var(--serif);font-size:var(--t-base)}
.nav a{text-decoration:none;color:var(--ink-2);padding:6px 0}
.nav__commission{display:none}   /* desktop uses the button in the masthead */
.nav a:hover,.nav a[aria-current="page"]{color:var(--ink)}
.nav a[aria-current="page"]{text-decoration:underline;text-decoration-color:var(--brass);
  text-decoration-thickness:1px;text-underline-offset:5px}

/* The menu button. Two brass rules that become a cross when open.
   Never smaller than 44px, because it is the only way into the site on a phone. */
.navtoggle{
  display:none;
  width:44px;height:44px;flex:0 0 44px;
  align-items:center;justify-content:center;
  background:transparent;border:1px solid var(--ground-3);border-radius:1px;
  cursor:pointer;padding:0;position:relative;
}
.navtoggle span{
  position:absolute;left:12px;width:20px;height:1.5px;background:var(--ink);
  transition:transform .22s ease,opacity .18s ease;
}
.navtoggle span:first-child{transform:translateY(-4px)}
.navtoggle span:last-child{transform:translateY(4px)}
.navtoggle[aria-expanded="true"] span:first-child{transform:rotate(45deg)}
.navtoggle[aria-expanded="true"] span:last-child{transform:rotate(-45deg)}
.navtoggle:hover{border-color:var(--ink-3)}

.site-foot{background:var(--ground-2);border-top:1px solid var(--ground-3);
  padding-block:var(--s5) var(--s4);margin-top:var(--s6)}
.site-foot .cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:var(--s4)}
.site-foot h4{font-family:var(--serif);font-size:var(--t-sm);font-weight:500;
  color:var(--ink-3);margin-bottom:var(--s2)}
.site-foot ul{list-style:none;margin:0;padding:0;font-family:var(--serif);font-size:var(--t-base)}
.site-foot li{margin-bottom:7px}
.site-foot a{color:var(--ink-2);text-decoration:none}
.site-foot a:hover{color:var(--ink);text-decoration:underline;text-decoration-color:var(--brass)}
.colophon{margin-top:var(--s5);padding-top:var(--s3);border-top:1px solid var(--ground-3);
  font-family:var(--serif);font-size:var(--t-sm);color:var(--ink-3);
  display:flex;flex-wrap:wrap;gap:var(--s2) var(--s3);justify-content:space-between}
.colophon a{color:var(--ink-2)}

/* ------------------------------------------------------------------ forms -- */

/* Form controls stay in the grotesque: they are apparatus, not reading. */
label{font-family:var(--sans);font-size:var(--t-sm);font-weight:500;color:var(--ink);display:block}
.field{display:flex;flex-direction:column;gap:6px}
.field .hint{font-family:var(--sans);font-size:var(--t-xs);color:var(--ink-3)}
input,select,textarea{
  font-family:var(--sans);font-size:16px; /* 16 stops iOS zooming on focus */
  color:var(--ink);background:#F3EFE6;
  border:1px solid var(--ground-3);border-radius:1px;
  padding:12px 14px;min-height:48px;width:100%;
}
textarea{min-height:120px;line-height:1.5;resize:vertical}
input:focus,select:focus,textarea:focus{border-color:var(--brass);outline:none;
  box-shadow:0 0 0 2px rgba(138,109,40,.18)}
input[aria-invalid="true"],textarea[aria-invalid="true"]{border-color:#9B3B2C}
.err{font-family:var(--sans);font-size:var(--t-xs);color:#8B3325}

/* --------------------------------------------------------------- utilities -- */

.scroll-x{overflow-x:auto;-webkit-overflow-scrolling:touch}
.vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
.center{text-align:center}
.tnum{font-variant-numeric:tabular-nums}

/* ------------------------------------------------------------- responsive -- */

@media (max-width:960px){
  .grid--4{grid-template-columns:repeat(3,1fr)}
}
@media (max-width:860px){
  .site-head__in{gap:var(--s2)}
  .head-cta{display:none}          /* the commission route lives in the menu instead */
  .navtoggle{display:flex}
  .nav__commission{display:flex}
  .brand span{font-size:var(--t-sm)}
  .brand small{display:none}

  /* The menu becomes a sheet under the masthead. Not a drawer translated off
     the top: that leaks a strip below the header on some phones. */
  .nav{
    display:none;
    position:absolute;left:0;right:0;top:100%;
    flex-direction:column;align-items:stretch;gap:0;
    background:var(--ground);
    border-bottom:1px solid var(--ground-3);
    padding:var(--s2) var(--gut) var(--s3);
    box-shadow:0 14px 28px -22px rgba(33,30,25,.55);
  }
  .nav--open{display:flex}
  .nav a{
    padding:14px 0;min-height:48px;display:flex;align-items:center;
    border-bottom:1px solid var(--ground-3);font-size:var(--t-md);color:var(--ink);
  }
  .nav a:last-child{border-bottom:0}
  .nav__commission{color:var(--brass) !important;font-weight:500}
}
@media (max-width:760px){
  :root{--t-base:17px}
  .grid--3,.grid--4{grid-template-columns:repeat(2,1fr)}
  .grid{gap:var(--s4) var(--s3)}
  section{padding-block:var(--s5)}
  section.loose{padding-block:var(--s6)}
  /* Footer links are the site's densest tap targets. Give them real height. */
  .site-foot li{margin-bottom:0}
  .site-foot li a{display:inline-flex;align-items:center;min-height:40px}
}
@media (max-width:430px){
  .grid--2{grid-template-columns:1fr}
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important;
  }
}

@media print{
  .site-head,.nav,.btn{display:none}
  body{background:#fff;color:#000}
}

/* ------------------------------------------------------- collection head -- */
/* Jamb opens a category on an object, not on a title. So do we. */
.collection-head{
  display:grid;grid-template-columns:1fr minmax(280px,420px);
  gap:var(--s5) var(--s6);align-items:center;
}
.collection-intro .lede{margin:var(--s3) 0 var(--s3);max-width:38ch}
.collection-intro .meta{max-width:38ch;color:var(--ink-2);font-size:var(--t-base)}
.collection-figure{margin:0}
.collection-figure img{width:100%;height:auto}
@media (max-width:860px){
  .collection-head{grid-template-columns:1fr;gap:var(--s4)}
  .collection-figure{max-width:340px}
}

/* The plate grid is narrower than the page. THREE columns land at 250px, which
   is the width of the smallest plate crop the business owns (the Regency, whose
   only photograph is 400x267 and yields a 251px square). Nothing is ever
   upscaled, and the generous margin either side is exactly the air a catalogue
   wants. Three columns rather than four because a blind critic measured our
   pieces at "a 45px trinket" in a four-column grid: on a page selling one
   object at a time, the object has to be legible. */
.grid--plates{
  grid-template-columns:repeat(3,267px);
  justify-content:space-between;
  row-gap:var(--s6);column-gap:var(--s5);
  max-width:100%;margin-inline:0;
}
@media (max-width:1100px){
  .grid--plates{grid-template-columns:repeat(3,1fr);justify-content:stretch;column-gap:var(--s5)}
}
@media (max-width:760px){
  .grid--plates{grid-template-columns:repeat(2,1fr);row-gap:var(--s4);column-gap:var(--s3)}
}

/* A catalogue plate has already been cropped to exactly the shape and size its
   cell needs, so it always fills its frame. This outranks any per-photograph
   width cap a page sets for its uncropped images, which would otherwise leave
   the plate stranded in the middle of an empty rectangle. */
.plate .plate__frame img{width:100%;height:100%;max-width:none;max-height:none;object-fit:cover}

/* Every catalogue plate IN A GRID is the same physical size, whatever grid it
   is dropped into. 214px is the width of the smallest plate the business owns
   (the Regency, whose only photograph is 400x267), so nothing in a grid is ever
   upscaled and the collection keeps one scale from page to page.

   Deliberately scoped to grids. On a single dial's own page the object is the
   subject and has to be the largest thing on the screen, so it is sized there
   by the true pixels of its best photograph instead. */
.grid > .plate{max-width:267px;width:100%;justify-self:start}

/* Engraving note on a collection page: same left rule as the heading and the
   plate grid above it, with the prose held to a readable measure rather than
   the full page width. */
.engraving-note{padding-top:var(--s4)}
.engraving-note h2{font-size:var(--t-xl);margin-bottom:var(--s3)}
.engraving-note .prose{max-width:60ch}

/* The indoor armillary, given its own footing rather than orphaned at the end
   of a four column grid. */
.indoor-note{display:grid;grid-template-columns:1fr 250px;gap:var(--s5);align-items:center;padding-top:var(--s4)}
.indoor-note h2{font-size:var(--t-xl);margin-bottom:var(--s2)}
.indoor-note .prose{max-width:52ch;color:var(--ink-2)}
.indoor-note .meta{margin-top:var(--s2)}
.indoor-note__plate .plate{max-width:250px}
@media (max-width:760px){
  .indoor-note{grid-template-columns:1fr;gap:var(--s3)}
  .indoor-note__plate{max-width:250px}
}

/* The engraving note used a 60ch measure inside a full width container, which
   left the right half of the page an empty rectangle. Two columns of the same
   measure fills the width honestly instead of stretching the line length. */
.engraving-note__cols{columns:2;column-gap:var(--s6);max-width:100%}
.engraving-note__cols p{margin:0 0 1.1em;break-inside:avoid}
@media (max-width:760px){.engraving-note__cols{columns:1;max-width:62ch}}

/* The indoor piece keeps the grid's own caption stack and its plate number, so
   it reads as the thirteenth of thirteen rather than a different component. */
.indoor-note{grid-template-columns:1fr 267px}
.indoor-note__plate .plate{max-width:267px}
