/* ============================================================================
   BRIM COLLECTION — SYSTEM STYLESHEET                          v2.0 · light
   Implements design/DESIGN.md. Depends on tokens.css.

   v2.0 works on a LIGHT ground, and the cinematic mechanics were RE-THOUGHT
   rather than recoloured. What changed, and why:

     · No vignettes. A gradient to black is how you focus attention on a dark
       canvas; on paper it reads as a stain. Focus now comes from the picture
       being CONTAINED inside a generous paper margin.
     · No light type over dimmed photography. Type sits on the paper beside the
       picture, in ink. Nothing needs a scrim because nothing overlaps.
     · No film grain. Replaced by a much fainter paper tooth, multiplied rather
       than overlaid — the texture of the stock, not of the film.
     · Elevation is a real, warm cast shadow: on paper a shadow is what makes a
       photograph read as an object lying on a page. On the v1 dark ground a
       shadow did nothing and surface-lightness carried elevation instead.
     · The scroll parallax moves the picture INSIDE a still frame instead of
       drifting a full-bleed layer. The frame is the stage; the image breathes.

   Rules this file holds itself to:
     · no coloured side-stripe borders   · no gradient text
     · no glassmorphism                  · no z-index above 400
     · nothing is hidden by default and revealed by a transition
     · every animation has a prefers-reduced-motion answer
   ============================================================================ */

/* ── reset ────────────────────────────────────────────────────────────── */
*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth; color-scheme:light; }
html,body{ overflow-x:clip; }
@media (prefers-reduced-motion:reduce){ html{ scroll-behavior:auto; } }
body{
  margin:0; background:var(--cotton-100); color:var(--ink-900);
  font-family:var(--font-text); font-size:var(--t-base); line-height:var(--lh-body);
  font-synthesis-weight:none; -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
}
/* Paper tooth. Multiply, not overlay, and a third of the v1 grain's strength —
   this is the texture of the stock, not of the film. */
body::before{
  content:""; position:fixed; inset:0; z-index:1; pointer-events:none;
  opacity:.035; mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='2'/></filter><rect width='140' height='140' filter='url(%23n)'/></svg>");
}
img,svg,video{ display:block; max-width:100%; }
img{ height:auto; }
button,input,select,textarea{ font:inherit; color:inherit; }
h1,h2,h3,h4,p,figure,blockquote,ul,ol{ margin:0; }
ul,ol{ padding:0; list-style:none; }
a{ color:inherit; }

/* One focus treatment everywhere. Ink reads on the cotton ground (16:1) and on
   a thread fill (3.2:1), so a button never loses its ring on hover. */
:focus-visible{
  outline:2px solid var(--focus); outline-offset:3px; border-radius:var(--r-xs);
}
:focus:not(:focus-visible){ outline:none; }
::selection{ background:var(--thread); color:var(--cotton-50); }

.skip{
  position:absolute; left:var(--s-4); top:-100px; z-index:var(--z-toast);
  background:var(--ink-900); color:var(--cotton-50); padding:var(--s-3) var(--s-4);
  border-radius:var(--r-sm); font-weight:600; text-decoration:none;
}
.skip:focus{ top:var(--s-4); }
.vh{ position:absolute!important; width:1px; height:1px; margin:-1px; padding:0;
     overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; }

/* ── layout ───────────────────────────────────────────────────────────── */
.wrap{ width:100%; max-width:var(--maxw); margin-inline:auto; padding-inline:var(--gutter); }
.wrap--text{ max-width:calc(var(--maxw-text) + var(--gutter)*2); }
.section{ padding-block:var(--section-y); }
.section--tight{ padding-block:var(--section-y-tight); }
.section--first{ padding-block:var(--section-y-tight) var(--section-y); }
/* A recessed band — on paper this is how you separate two ideas without a rule. */
.band{ background:var(--cotton-200); }

/* ── type ─────────────────────────────────────────────────────────────── */
.display{
  font-family:var(--font-display); font-variation-settings:var(--display-vf);
  font-weight:400; line-height:var(--lh-tight); letter-spacing:var(--ls-display);
  text-wrap:balance; color:var(--ink-900);
}
.display--hero{ font-size:var(--t-4xl); }
.display--xl  { font-size:var(--t-3xl); }
.display--lg  { font-size:var(--t-2xl); }
.display--md  { font-size:var(--t-xl); line-height:var(--lh-snug); }
.display em{ font-style:normal; color:var(--thread); }

.h-ui{
  font-family:var(--font-text); font-weight:650; letter-spacing:var(--ls-tight);
  line-height:var(--lh-snug); font-size:var(--t-lg); text-wrap:balance;
}
.lede{ color:var(--ink-700); font-size:var(--t-md); max-width:var(--measure-lede); text-wrap:pretty; }
.prose{ color:var(--ink-700); max-width:var(--measure); text-wrap:pretty; }
.prose p + p{ margin-top:var(--s-4); }
.prose strong{ color:var(--ink-900); font-weight:600; }
.prose a{ color:var(--thread); text-underline-offset:.22em;
          text-decoration-thickness:1px;
          text-decoration-color:color-mix(in srgb,var(--thread) 45%,transparent); }
.prose a:hover{ text-decoration-color:var(--thread); }

/* The eyebrow. The rule in front of it is a running stitch — the system's
   signature line, and the only decoration allowed above a heading. */
.eyebrow{
  display:inline-flex; align-items:center; gap:var(--s-3);
  font-family:var(--font-mono); font-size:var(--t-2xs); font-weight:500;
  letter-spacing:var(--ls-label); text-transform:uppercase; color:var(--ink-500);
}
.eyebrow::before{
  content:""; flex:none; width:28px; height:1px; color:var(--thread); background:var(--stitch);
}
.eyebrow--plain::before{ display:none; }
.eyebrow--patch{ color:var(--denim); }
.eyebrow--patch::before{ color:var(--denim); }

.mono{ font-family:var(--font-mono); font-size:var(--t-2xs); letter-spacing:var(--ls-mono);
       text-transform:uppercase; color:var(--ink-500); }

.stitchrule{ height:1px; background:var(--stitch); color:var(--cotton-400); border:0; margin:0; }

/* ── buttons ──────────────────────────────────────────────────────────── */
.btn{
  --btn-bg:transparent; --btn-fg:var(--ink-900); --btn-edge:transparent;
  display:inline-flex; align-items:center; justify-content:center; gap:var(--s-2);
  min-height:46px; padding:.72em 1.35em;
  background:var(--btn-bg); color:var(--btn-fg); box-shadow:inset 0 0 0 1px var(--btn-edge);
  border:0; border-radius:var(--r-sm); cursor:pointer;
  font-weight:650; font-size:var(--t-sm); letter-spacing:.005em; text-decoration:none;
  white-space:nowrap;
  transition:background-color var(--d-fast) var(--ease),
             color var(--d-fast) var(--ease),
             box-shadow var(--d-fast) var(--ease),
             transform var(--d-fast) var(--ease);
}
.btn--primary{ --btn-bg:var(--thread); --btn-fg:var(--cotton-50); }
.btn--primary:hover{ --btn-bg:var(--thread-deep); transform:translateY(-1px); }
.btn--primary:active{ --btn-bg:var(--thread-press); transform:translateY(0); }
.btn--ghost{ --btn-edge:var(--ink-400); }
.btn--ghost:hover{ --btn-bg:var(--cotton-50); --btn-edge:var(--ink-900); transform:translateY(-1px); }
.btn--ghost:active{ --btn-bg:var(--cotton-200); transform:translateY(0); }
.btn--quiet{ padding-inline:0; min-height:auto; --btn-fg:var(--thread); }
.btn--quiet:hover{ --btn-fg:var(--thread-press); }
.btn[disabled],.btn[aria-disabled="true"]{
  --btn-bg:var(--cotton-200); --btn-fg:var(--ink-400); --btn-edge:var(--cotton-400);
  cursor:not-allowed; transform:none;
}
.btn[data-loading="true"]{ cursor:progress; }
.btn[data-loading="true"] .btn__label{ opacity:.55; }
.btn__arrow{ transition:transform var(--d-fast) var(--ease); }
.btn:hover .btn__arrow{ transform:translateX(3px); }

/* ── nav ──────────────────────────────────────────────────────────────── */
.nav{
  /* Above the menu, not below it: the nav holds the control that closes the
     menu, so if the overlay covered the bar there would be no visible way back. */
  position:fixed; inset:0 0 auto; z-index:var(--z-overlay);
  display:flex; align-items:center; justify-content:space-between; gap:var(--s-4);
  padding:var(--s-4) var(--gutter);
  transition:background-color var(--d-mid) var(--ease), box-shadow var(--d-mid) var(--ease);
}
/* On paper the nav needs no scrim to be readable, so it stays plain until you
   leave the hero — then it takes a hairline so it detaches from the content
   scrolling under it. No blur, no glass. */
.nav[data-stuck="true"]{
  background:color-mix(in srgb,var(--cotton-100) 96%,transparent);
  box-shadow:0 1px 0 var(--cotton-300);
}
.nav__brand{ display:inline-flex; align-items:center; gap:var(--s-3); text-decoration:none;
             color:var(--ink-900); }
.nav__brand .mark{ width:30px; height:30px; color:var(--thread); flex:none;
                   transition:color var(--d-fast) var(--ease); }
.nav__brand:hover .mark{ color:var(--thread-press); }
.nav__name{ display:grid; gap:1px; }
.nav__name b{ font-family:var(--font-display); font-variation-settings:var(--display-vf);
              font-weight:500; font-size:1.08rem; line-height:1; letter-spacing:-.012em; }
.nav__name i{ font-family:var(--font-mono); font-style:normal; font-size:9.5px;
              letter-spacing:.24em; color:var(--ink-500); line-height:1; }
.nav__links{ display:none; align-items:center; gap:var(--s-5); }
.nav__links a{ font-size:var(--t-sm); font-weight:550; color:var(--ink-700); text-decoration:none;
               padding-block:var(--s-2); position:relative;
               transition:color var(--d-fast) var(--ease); }
.nav__links a:hover{ color:var(--ink-900); }
.nav__links a[aria-current="page"]{ color:var(--ink-900); }
.nav__links a[aria-current="page"]::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:1px;
  color:var(--thread); background:var(--stitch);
}
.nav__actions{ display:flex; align-items:center; gap:var(--s-3); }
.nav__toggle{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--s-2);
  min-height:40px; padding:.4em .8em; background:transparent; border:0; cursor:pointer;
  box-shadow:inset 0 0 0 1px var(--ink-400);
  border-radius:var(--r-sm); color:var(--ink-900); font-size:var(--t-sm); font-weight:600;
}
.nav__toggle .bars{ display:grid; gap:3px; width:15px; }
.nav__toggle .bars i{ height:1.5px; background:currentColor; border-radius:1px;
                      transition:transform var(--d-fast) var(--ease), opacity var(--d-fast); }
.nav__toggle[aria-expanded="true"] .bars i:nth-child(1){ transform:translateY(4.5px) rotate(45deg); }
.nav__toggle[aria-expanded="true"] .bars i:nth-child(2){ opacity:0; }
.nav__toggle[aria-expanded="true"] .bars i:nth-child(3){ transform:translateY(-4.5px) rotate(-45deg); }

.menu{
  position:fixed; inset:0; z-index:var(--z-sticky); display:grid; align-content:center;
  gap:var(--s-2); padding:var(--s-9) var(--gutter);
  background:var(--cotton-100); visibility:hidden; opacity:0;
  transition:opacity var(--d-mid) var(--ease), visibility 0s linear var(--d-mid);
}
.menu[data-open="true"]{ visibility:visible; opacity:1; transition-delay:0s; }
.menu a{ font-family:var(--font-display); font-variation-settings:var(--display-vf);
         font-weight:400; font-size:clamp(2rem,10vw,3rem); line-height:1.12;
         letter-spacing:var(--ls-display); text-decoration:none; color:var(--ink-900);
         padding-block:var(--s-2); }
.menu a[aria-current="page"]{ color:var(--thread); }
.menu .menu__meta{ margin-top:var(--s-6); }

@media (min-width:900px){
  .nav__links{ display:flex; }
  .nav__toggle{ display:none; }
  .menu{ display:none; }
}
/* Below the desktop breakpoint the bar has to carry brand + CTA + Menu in about
   335px. The compact lockup and a tighter button buy exactly the room needed. */
@media (max-width:899px){
  .nav{ padding-inline:var(--s-4); gap:var(--s-2); }
  .nav__name i{ display:none; }
  .nav__actions{ gap:var(--s-2); }
  .nav__actions .btn{ padding:.62em .85em; font-size:var(--t-xs); }
  .nav__toggle{ padding:.45em .7em; font-size:var(--t-xs); }
}
/* On the narrowest phones the word "Menu" goes. The button keeps
   aria-label="Menu" and a hard 44px box so the tap target survives. */
@media (max-width:400px){
  .nav__toggle{ font-size:0; padding:0; min-width:44px; min-height:44px; }
  .nav__toggle .bars{ width:17px; }
}

/* ── the plate ────────────────────────────────────────────────────────────
   The single most important object in the light system. A photograph is held in
   a frame, sat on the paper with a warm cast shadow and a hairline, and given
   room on every side. This is what replaced the bleed-to-black: the picture is
   an object lying on a page, not a hole cut in the screen. */
.plate{ position:relative; }
.plate__crop{
  position:relative; overflow:clip; border-radius:var(--r-sm);
  background:var(--cotton-200);
  box-shadow:var(--plate-shadow), inset 0 0 0 1px rgba(64,48,32,.16);
  aspect-ratio:4/3;
}
.plate__crop img,.plate__crop video{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  will-change:transform;
}
.plate figcaption{
  margin-top:var(--s-3); font-family:var(--font-mono); font-size:var(--t-3xs);
  letter-spacing:var(--ls-mono); text-transform:uppercase; color:var(--ink-500);
}

/* ── hero ─────────────────────────────────────────────────────────────── */
.hero{ position:relative; min-height:100svh; display:grid; align-items:center; }
.hero__inner{
  display:grid; gap:var(--s-7);
  padding-block:clamp(6rem,15vh,8.5rem) clamp(4.5rem,11vh,6.5rem);
}
.hero__copy{ display:grid; gap:var(--s-4); justify-items:start; align-content:center; }
.hero__actions{ display:flex; flex-wrap:wrap; gap:var(--s-3); margin-top:var(--s-2); }
.hero__plate .plate__crop{ aspect-ratio:5/4; }
@media (min-width:900px){
  .hero__inner{ grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);
                gap:clamp(2.5rem,5vw,5rem); align-items:center; }
  /* 62vh, not more: the plate plus its caption plus the hero's own padding has to
     leave the scroll cue somewhere to sit inside one viewport. */
  .hero__plate .plate__crop{ aspect-ratio:4/5; max-height:62vh; }
}

.scrollcue{
  position:absolute; left:var(--gutter); bottom:var(--s-5); z-index:1;
  display:inline-flex; align-items:center; gap:var(--s-3);
  font-family:var(--font-mono); font-size:var(--t-3xs); letter-spacing:var(--ls-label);
  text-transform:uppercase; color:var(--ink-500);
}
.scrollcue::before{ content:""; width:34px; height:1px; background:currentColor; opacity:.7;
                    transform-origin:left; animation:cue 2.4s var(--ease) infinite; }
@keyframes cue{ 0%,100%{ transform:scaleX(.4); opacity:.35 } 50%{ transform:scaleX(1); opacity:.85 } }
@media (prefers-reduced-motion:reduce){ .scrollcue::before{ animation:none; transform:none; } }

/* ── cinematic scenes (home only) ─────────────────────────────────────────
   Same skeleton as v1 — a tall .scene holding a sticky .stage — but the stage
   is paper, the picture is a plate held inside generous margins, and the scroll
   drives the IMAGE INSIDE ITS FRAME rather than a full-bleed layer. The frame
   stays perfectly still; the picture breathes. */
.scene{ position:relative; height:180vh; }
.scene--last{ height:150vh; }
.stage{ position:sticky; top:0; height:100svh; display:grid; align-items:center; overflow:clip; }
.stage__inner{ display:grid; gap:var(--s-6); padding-block:var(--plate-inset-y); }
.stage__copy{ display:grid; gap:var(--s-4); justify-items:start; align-content:center; }
.stage__copy .prose{ max-width:40ch; }
.stage .plate__crop{ aspect-ratio:4/3; max-height:56vh; }
@media (min-width:900px){
  .stage__inner{ grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);
                 gap:clamp(2.5rem,5vw,4.5rem); align-items:center; }
  .stage .plate__crop{ aspect-ratio:5/4; max-height:72vh; }
  .scene--flip .stage .plate{ order:2; }
}

.progress{
  position:fixed; inset:0 auto auto 0; height:2px; width:0; z-index:var(--z-nav);
  background:var(--thread); transition:width 80ms linear;
}
@media (prefers-reduced-motion:reduce){ .progress{ transition:none; } }

/* ── masked line reveal ───────────────────────────────────────────────────
   The visible state is the DEFAULT. The mask applies only when JS has confirmed
   it is running (html.js) and motion is allowed. A page that fails to load its
   script, or renders headless, still shows its words. */
.reveal > span{ display:inline-block; }
html.js .reveal:not([data-shown="true"]) > span{ transform:translateY(108%); }
html.js .reveal{ display:inline-block; overflow:hidden; vertical-align:top; padding-bottom:.08em; }
html.js .reveal > span{
  transition:transform var(--d-type) var(--ease-out);
  transition-delay:calc(var(--i,0) * 60ms);
}
@media (prefers-reduced-motion:reduce){
  html.js .reveal{ overflow:visible; }
  html.js .reveal > span{ transform:none!important; transition:none; }
}

/* Quiet enter. TRANSLATE ONLY, deliberately: an opacity fade would leave every
   section below the fold at opacity:0 for anything that renders without
   scrolling — a print, a PDF, a screenshot tool, a scraper. It is also the
   quieter choice; a fade on every section is the tell that a template did it. */
html.js .enter{ transform:translateY(14px); transition:transform var(--d-slow) var(--ease); }
html.js .enter[data-shown="true"]{ transform:none; }
@media (prefers-reduced-motion:reduce){
  html.js .enter{ transform:none; transition:none; }
}

/* ── service lanes ────────────────────────────────────────────────────────
   Three services, so three lanes — not a grid of interchangeable cards.
   Embroidery carries thread; patching carries denim (which on a light ground
   can finally hold text, so that lane gets a real voice); DTF transfers take
   neutral ink rather than a third brand hue. See tokens.css §4. */
.lane{ display:grid; gap:var(--s-6); align-items:center; padding-block:var(--section-y-tight); }
.lane + .lane{ border-top:var(--rule); }
.lane__body{ display:grid; gap:var(--s-4); justify-items:start; }
.lane__body .prose{ max-width:44ch; }
.lane__num{ font-family:var(--font-mono); font-size:var(--t-2xs); letter-spacing:var(--ls-mono);
            color:var(--ink-500); }
.lane__list{ display:grid; gap:var(--s-2); margin-top:var(--s-1); }
.lane__list li{ display:grid; grid-template-columns:14px 1fr; gap:var(--s-3);
                color:var(--ink-700); font-size:var(--t-sm); align-items:baseline; }
.lane__list li::before{ content:""; height:1px; margin-top:.7em; color:var(--thread);
                        background:var(--stitch); }
.lane--patch .lane__list li::before{ color:var(--denim); }
.lane--patch .lane__num{ color:var(--denim); }
.lane--dtf .lane__list li::before{ color:var(--ink-500); }
@media (min-width:860px){
  .lane{ grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:clamp(2.5rem,5vw,4.5rem); }
  .lane--flip .plate{ order:2; }
}

/* ── work grid ────────────────────────────────────────────────────────────
   Deliberately uneven. Equal cards in an equal grid is the template look. */
.workgrid{ display:grid; gap:var(--s-6);
           grid-template-columns:repeat(auto-fit,minmax(min(100%,280px),1fr)); }
.work{ position:relative; display:grid; gap:var(--s-3); text-decoration:none; color:inherit; }
.work .plate__crop{ aspect-ratio:4/3; }
.work .plate__crop img{ transition:transform var(--d-slow) var(--ease); }
.work:hover .plate__crop img{ transform:scale(1.035); }
.work__meta{ display:flex; align-items:baseline; justify-content:space-between; gap:var(--s-3); }
.work__meta h3{ font-size:var(--t-base); font-weight:600; letter-spacing:var(--ls-tight); }
.work__tag{ font-family:var(--font-mono); font-size:var(--t-3xs); letter-spacing:var(--ls-mono);
            text-transform:uppercase; color:var(--ink-500); white-space:nowrap; }
.work--wide{ grid-column:span 2; }
.work--wide .plate__crop{ aspect-ratio:16/9; }
@media (max-width:659px){ .work--wide{ grid-column:span 1; } .work--wide .plate__crop{ aspect-ratio:4/3; } }

/* ── panels ───────────────────────────────────────────────────────────── */
.panel{ background:var(--cotton-50); border:var(--rule); border-radius:var(--r-md);
        padding:clamp(1.15rem,2.6vw,2rem); box-shadow:var(--lift-1); }
.panel--raised{ box-shadow:var(--lift-2); }

/* Steps — a numbered sequence, because it genuinely is one. */
.steps{ display:grid; gap:var(--s-5);
        grid-template-columns:repeat(auto-fit,minmax(min(100%,230px),1fr)); }
/* Contact has five routes, and auto-fit lands 4+1 at desktop widths — one
   orphan card reads like a mistake. Cap it at three so it breaks 3+2. */
@media (min-width:900px){ .steps--contact{ grid-template-columns:repeat(3,1fr); } }
.step{ display:grid; gap:var(--s-2); align-content:start; padding-top:var(--s-4);
       border-top:1px solid var(--cotton-400); }
.step__n{ font-family:var(--font-mono); font-size:var(--t-2xs); letter-spacing:var(--ls-mono);
          color:var(--thread); }
.step h3{ font-size:var(--t-base); font-weight:650; letter-spacing:var(--ls-tight); }
.step p{ color:var(--ink-700); font-size:var(--t-sm); }

.quote{ display:grid; gap:var(--s-4); max-width:56ch; }
.quote blockquote{ font-family:var(--font-display); font-variation-settings:var(--display-vf);
                   font-weight:300; font-size:var(--t-lg); line-height:1.34;
                   letter-spacing:var(--ls-tight); color:var(--ink-900); text-wrap:pretty; }
.quote figcaption{ font-size:var(--t-sm); color:var(--ink-500); }
.quote figcaption b{ color:var(--ink-700); font-weight:600; }

/* Anything waiting on the client is marked, not faked. */
.pending{
  display:grid; place-items:center; gap:var(--s-2); min-height:180px; padding:var(--s-5);
  border:1px dashed var(--ink-400); border-radius:var(--r-sm); background:var(--cotton-200);
  text-align:center; color:var(--ink-500); font-size:var(--t-sm);
}
.pending .mono{ color:var(--thread); }

/* Contact lines — a label/value ledger, not a bullet list. The mono label column
   is fixed so the values align down the page like a spec sheet. */
.contact__lines{ list-style:none; padding:0; margin:0; display:grid; gap:var(--s-2); }
.contact__lines li{ display:grid; gap:var(--s-1) var(--s-4); align-items:baseline;
                    padding-block:var(--s-1); border-bottom:var(--rule); }
@media (min-width:560px){ .contact__lines li{ grid-template-columns:8rem 1fr; } }
.contact__lines .mono{ font-family:var(--font-mono); font-size:var(--t-2xs);
                       letter-spacing:var(--ls-label); text-transform:uppercase;
                       color:var(--ink-500); }
.contact__lines a{ color:var(--ink-900); text-decoration:none; font-size:var(--t-sm);
                   display:inline-block; padding-block:4px;
                   border-bottom:1px solid var(--ink-400);
                   transition:color var(--d-fast) var(--ease),
                              border-color var(--d-fast) var(--ease); }
.contact__lines a:hover{ color:var(--thread); border-color:var(--thread); }

/* ── forms ────────────────────────────────────────────────────────────────
   The quote form is the point of the site, so it is laid out like a job ticket:
   mono field names, hints under the field they belong to, one action. */
.quotelayout{ display:grid; gap:var(--s-7); align-items:start; }
@media (min-width:940px){
  .quotelayout{ grid-template-columns:minmax(0,1.55fr) minmax(0,1fr); gap:var(--s-8); }
}
.form{ display:grid; gap:var(--s-5); }
.form__grid{ display:grid; gap:var(--s-4);
             grid-template-columns:repeat(auto-fit,minmax(min(100%,230px),1fr)); }
/* align-content:start stops a field with no hint text from stretching its input
   to match a neighbour that has one. */
.field{ display:grid; gap:var(--s-2); align-content:start; }
.field--full{ grid-column:1/-1; }
.field > label:not(.file__drop){
  font-family:var(--font-mono); font-size:var(--t-2xs); letter-spacing:var(--ls-mono);
  text-transform:uppercase; color:var(--ink-700);
}
.field__opt{ color:var(--ink-400); text-transform:none; letter-spacing:0; }
.field__hint{ font-size:var(--t-xs); color:var(--ink-500); }
.input,.select,.textarea{
  width:100%; min-height:48px; padding:.7em .85em;
  background:var(--cotton-50); color:var(--ink-900);
  /* --edge, not a hairline: an input outline is the only thing identifying the
     control, so WCAG 1.4.11 wants 3:1 against the ground. */
  border:var(--edge); border-radius:var(--r-sm);
  transition:border-color var(--d-fast) var(--ease), box-shadow var(--d-fast) var(--ease);
}
.textarea{ min-height:130px; resize:vertical; line-height:1.55; }
/* iOS Safari gives date/time inputs a native intrinsic width and ignores the
   width:100% above, so #q-date rendered wider than its card and broke the right
   edge of the quote form on iPhone. Neutralising the native appearance is what
   makes the declared width apply; max-width caps it either way, and min-width:0
   stops the intrinsic size winning inside a flex/grid parent. The explicit
   line-height keeps the control the same height as its siblings once the native
   styling is off, and -webkit-date-and-time-value left-aligns the value, which
   iOS otherwise centres. */
.input[type="date"],.input[type="time"],.input[type="datetime-local"]{
  -webkit-appearance:none; appearance:none;
  max-width:100%; min-width:0; line-height:1.2;
}
.input[type="date"]::-webkit-date-and-time-value{ text-align:left; }
.input::placeholder,.textarea::placeholder{ color:var(--ink-500); opacity:1; }
.input:hover,.select:hover,.textarea:hover{ border-color:var(--ink-700); }
.input:focus,.select:focus,.textarea:focus{
  border-color:var(--thread); box-shadow:0 0 0 3px var(--thread-wash);
}
.select{ appearance:none; cursor:pointer; padding-right:2.4em;
  background-image:linear-gradient(45deg,transparent 50%,var(--ink-700) 50%),
                   linear-gradient(135deg,var(--ink-700) 50%,transparent 50%);
  background-position:calc(100% - 18px) 50%, calc(100% - 12px) 50%;
  background-size:6px 6px, 6px 6px; background-repeat:no-repeat;
}
.field[data-invalid="true"] .input,
.field[data-invalid="true"] .select,
.field[data-invalid="true"] .textarea{ border-color:var(--error); }
.field__error{ font-size:var(--t-xs); color:var(--error); }
.field__error:empty{ display:none; }

/* The native file control is unstyleable, so the real input is visually hidden
   and its own <label> is the button — keyboard and screen-reader behaviour are
   unchanged because the label is still the label. */
.file{ display:grid; gap:var(--s-2); }
.file input[type=file]{ position:absolute; width:1px; height:1px; opacity:0; }
.file__drop{
  display:grid; gap:var(--s-1); place-items:center; padding:var(--s-5) var(--s-4);
  border:1px dashed var(--ink-400); border-radius:var(--r-sm); background:var(--cotton-50);
  cursor:pointer; text-align:center; color:var(--ink-700);
  transition:border-color var(--d-fast) var(--ease), background-color var(--d-fast) var(--ease);
}
.file__drop:hover{ border-color:var(--thread); background:var(--thread-wash); }
.file input[type=file]:focus-visible + .file__drop{ outline:2px solid var(--focus); outline-offset:3px; }
.file__drop b{ color:var(--ink-900); font-weight:600; font-size:var(--t-sm); }
.file__drop span{ font-size:var(--t-xs); color:var(--ink-500); }

.check{ display:grid; grid-template-columns:auto 1fr; gap:var(--s-3); align-items:start;
        font-size:var(--t-sm); color:var(--ink-700); cursor:pointer; }
.check input{ width:18px; height:18px; margin-top:.18em; accent-color:var(--thread); cursor:pointer; }

.formnote{ font-size:var(--t-xs); color:var(--ink-500); max-width:52ch; }
.formstatus{ font-size:var(--t-sm); }
.formstatus[data-state="ok"]{ color:var(--ok); }
.formstatus[data-state="error"]{ color:var(--error); }

/* ── footer ───────────────────────────────────────────────────────────── */
.foot{ border-top:var(--rule); background:var(--cotton-200); }
.foot__grid{ display:grid; gap:var(--s-7); padding-block:var(--section-y-tight); }
@media (min-width:760px){ .foot__grid{ grid-template-columns:1.4fr 1fr 1fr; } }
.foot h2{ font-size:var(--t-2xs); font-family:var(--font-mono); letter-spacing:var(--ls-label);
          text-transform:uppercase; color:var(--ink-500); margin-bottom:var(--s-3); }
.foot ul{ display:grid; gap:var(--s-1); }
/* A standalone link needs a 24px target (WCAG 2.5.8) and a 14px line is only
   16px tall, so this padding is structural, not decoration. */
.foot a{ color:var(--ink-700); text-decoration:none; font-size:var(--t-sm);
         display:inline-block; padding-block:5px;
         transition:color var(--d-fast) var(--ease); }
.foot a:hover{ color:var(--ink-900); }
.foot__base{ display:flex; flex-wrap:wrap; gap:var(--s-3) var(--s-5); align-items:center;
             justify-content:space-between; padding-block:var(--s-4);
             border-top:var(--rule); font-size:var(--t-xs); color:var(--ink-500); }
.foot__legal{ display:flex; gap:var(--s-4); flex-wrap:wrap; }
.foot__legal a{ padding-block:5px; }
/* Social row sits under the brand blurb, so it reads as part of the identity
   block rather than as a fourth navigation column. Overrides the grid on
   `.foot ul` — these are peers on one line, not a stacked list. */
.foot__social{ display:flex !important; flex-wrap:wrap; gap:0 var(--s-5);
               margin-top:var(--s-3); list-style:none; padding:0; }
.foot__social a{ color:var(--ink-500); }
.foot__social a:hover{ color:var(--thread); }

/* CTA band before the footer, on every page. The only repeated block on the
   site, because the site has exactly one job. */
.cta{ border-top:var(--rule); background:var(--cotton-50); }
.cta__inner{ display:grid; gap:var(--s-5); padding-block:var(--section-y-tight); justify-items:start; }
@media (min-width:860px){
  .cta__inner{ grid-template-columns:1fr auto; align-items:center; gap:var(--s-7); }
}

/* ── documents (terms, privacy) ───────────────────────────────────────────
   v1 gave these their own light "paper" theme because the site was dark. Now
   the whole site is paper, so a document is just a document: same ground, wider
   measure, looser leading. The .doc theme is gone. */
.legal{ max-width:var(--measure-legal); }
.legal h2{ font-family:var(--font-text); font-weight:700; font-size:var(--t-lg);
           letter-spacing:var(--ls-tight); margin:var(--s-8) 0 var(--s-3); color:var(--ink-900); }
.legal h3{ font-weight:650; font-size:var(--t-base); margin:var(--s-5) 0 var(--s-2); }
.legal p,.legal li{ color:var(--ink-700); line-height:var(--lh-loose); }
.legal p + p{ margin-top:var(--s-4); }
.legal ul{ list-style:disc; padding-left:1.25rem; margin:var(--s-3) 0; display:grid; gap:var(--s-2); }
.legal ol{ list-style:decimal; padding-left:1.25rem; margin:var(--s-3) 0; display:grid; gap:var(--s-2); }
.legal a{ color:var(--thread); text-underline-offset:.2em; }
.legal strong{ color:var(--ink-900); }
.legal .callout{ border:1px solid var(--cotton-400); border-radius:var(--r-sm);
                 background:var(--cotton-50); padding:var(--s-4) var(--s-5); margin:var(--s-5) 0; }
.legal .callout p{ color:var(--ink-900); }

@media print{
  .nav,.menu,.cta,.progress,.scrollcue,.skip{ display:none!important; }
  body::before{ display:none; }
  body{ background:#fff; color:#000; }
  .legal p,.legal li{ color:#000; }
  a[href^="http"]::after{ content:" (" attr(href) ")"; font-size:.85em; color:#555; }
}
