/* ============================================================================
   BASE — identical on every Pittsburgh IT build. The visitor never sees any of it.
   Token NAMES are fixed; only the VALUES change per client. Everything below the
   token block is structural: the accessibility floor, the form skeleton, tap
   targets, the motion contract. Roughly 20 lines get rewritten per client and
   several hundred lines of quality are inherited.
   MOBILE FIRST — every rule here is the small-screen rule. Breakpoints add.
   ========================================================================== */
:root{
  --surface:#F4EFE3;
  --surface-2:#E8E4DC;
  --band:#22285E;
  --band-ink:#F4EFE3;
  --band-ink-2:#9897A8;
  --accent-on-band:#FFFBF0;
  --ink:#22285E;
  --ink-2:#3F4471;
  --ink-3:#5F6285;
  --accent:#22285E;
  --accent-2:#191E46;
  --accent-ink:#F4EFE3;
  --line:#C2BFC3;
  --maxw:1120px;
  --gutter:22px;
  --radius:0px;
  --font-display:'Big Shoulders Display','Arial Narrow',Helvetica,Arial,sans-serif;
  --font-body:'Newsreader',Georgia,'Times New Roman',serif;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{margin:0;background:var(--surface);color:var(--ink);
  font-family:var(--font-body);font-size:17px;line-height:1.62;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  overflow-x:hidden}
img,svg,video{max-width:100%;height:auto;display:block}
h1,h2,h3,h4{font-family:var(--font-display);margin:0;line-height:1.08;
  font-weight:700;letter-spacing:-.006em}
p{margin:0 0 1em}
a{color:inherit}
ul{margin:0;padding:0;list-style:none}

/* --- container ------------------------------------------------------------ */
.container{width:100%;max-width:var(--maxw);margin:0 auto;padding:0 var(--gutter)}
@media(min-width:760px){:root{--gutter:34px}}
@media(min-width:1180px){:root{--gutter:48px}}

/* --- accessibility floor -------------------------------------------------- */
.skip{position:absolute;left:-9999px;top:0;z-index:200;background:var(--accent);
  color:var(--accent-ink);padding:12px 18px;border-radius:0 0 var(--radius) 0;
  font-weight:700;text-decoration:none}
.skip:focus{left:0}
:focus-visible{outline:3px solid var(--accent);outline-offset:3px;border-radius:2px}
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);
  clip-path:inset(50%);white-space:nowrap}
/* honeypot: OFF-SCREEN, never display:none — a hidden field some bots skip,
   and a screen reader is told to leave it alone. */
.hp{position:absolute!important;left:-9999px;top:-9999px;width:1px;height:1px;
  opacity:0;pointer-events:none}

/* --- tap targets ---------------------------------------------------------- */
a,button,input,select,textarea,summary{font-family:inherit}
.btn,button,input[type=submit]{min-height:48px}
nav a,footer a{display:inline-block;min-height:24px}

/* --- button skeleton (templates restyle the skin, not the mechanics) ------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.55em;
  padding:14px 26px;border:1px solid transparent;border-radius:var(--radius);
  font-weight:650;font-size:16px;line-height:1.1;text-decoration:none;cursor:pointer;
  transition:transform .18s ease,background .18s ease,color .18s ease,border-color .18s ease,box-shadow .18s ease}
.btn:active{transform:translateY(1px)}
.btn-primary{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
.btn-ghost{background:transparent;color:var(--ink);border-color:var(--line)}

/* --- form skeleton -------------------------------------------------------- */
.form{display:grid;gap:16px}
.field{display:grid;gap:7px}
.field label{font-size:12.5px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--ink-2)}
.field input,.field select,.field textarea{
  width:100%;min-height:50px;padding:13px 15px;border:1px solid var(--line);
  border-radius:var(--radius);background:var(--surface);color:var(--ink);
  font-size:16px;/* 16px stops iOS zooming the page on focus */
  font-family:inherit;transition:border-color .18s ease,box-shadow .18s ease}
.field textarea{min-height:140px;resize:vertical;line-height:1.55}
.field input:focus,.field select:focus,.field textarea:focus{
  outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(34,40,94,.26)}
.field ::placeholder{color:var(--ink-3);opacity:1}
.frow{display:grid;gap:16px}
@media(min-width:680px){.frow{grid-template-columns:1fr 1fr}}
.thanks{display:none;border:1px solid var(--line);border-radius:var(--radius);
  padding:28px;background:var(--surface-2)}
.thanks.show{display:block}
.thanks h3{font-size:24px;margin-bottom:10px}
.formerror{color:#191E46;font-size:15px;font-weight:600;margin-top:10px}

/* --- MOTION CONTRACT ------------------------------------------------------
   Nothing starts hidden unless JavaScript has already run. The `js` class is set
   by an inline <head> script, and ONLY when prefers-reduced-motion is not set.
   No JS, blocked JS, old browser, or reduced motion => the page is simply visible.
   This is the inverse of how most sites do it, and it is why a script failure
   here cannot produce a blank page on a lead-generating site. */
html.js .reveal{opacity:0;transform:translateY(18px);
  transition:opacity .7s cubic-bezier(.22,.61,.36,1),transform .7s cubic-bezier(.22,.61,.36,1)}
html.js .reveal.in{opacity:1;transform:none}
html.js .reveal.d1{transition-delay:.08s}
html.js .reveal.d2{transition-delay:.16s}
html.js .reveal.d3{transition-delay:.24s}
@media(prefers-reduced-motion:reduce){
  html.js .reveal,html.js .reveal.in{opacity:1!important;transform:none!important;transition:none!important}
  *{animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important}
}

/* --- nav skeleton --------------------------------------------------------- */
#nav{position:fixed;top:0;left:0;right:0;z-index:100;
  transition:background .25s ease,box-shadow .25s ease,border-color .25s ease}
.nav-inner{display:flex;align-items:center;justify-content:space-between;
  gap:16px;min-height:60px}
.navtoggle{display:inline-flex;align-items:center;justify-content:center;
  width:48px;height:48px;margin-right:-10px;background:none;border:0;
  color:inherit;cursor:pointer}
@media(min-width:940px){.navtoggle{display:none}}
.nav-links{display:none}
.nav-links.open{display:flex}
.nav-links{gap:0}
/* Desktop nav reset. Deliberately scoped to #nav so its specificity (1,1,0) beats any
   later `.nav-links{position:absolute…}` a template writes for its mobile drawer —
   equal specificity later in the file wins over a media query, which silently left the
   drawer stacked at the left edge on six of seven templates before this was scoped.
   It sets ONLY the structural properties that must not leak from mobile to desktop;
   gap, colour and type stay the template's business. */
@media(min-width:940px){
  #nav .nav-links,#nav .nav-links.open{display:flex;position:static;inset:auto;
    flex-direction:row;align-items:center;padding:0;margin:0;border:0;background:none;
    width:auto;height:auto;min-height:0;max-height:none;box-shadow:none;transform:none;
    visibility:visible;opacity:1;overflow:visible;
    gap:var(--nav-gap,32px)}
}
html.menu-open,html.menu-open body{overflow:hidden}

/* --- footer skeleton ------------------------------------------------------ */
footer a{text-decoration:none}
.credit{font-size:13.5px}
.credit a{text-decoration:underline;text-underline-offset:3px}

/* --- button rows ----------------------------------------------------------
   On a phone two CTAs sitting side by side at different intrinsic widths look
   accidental, and neither is a comfortable thumb target. They go full width until
   there is room for a row. Scoped as `.btnrow > .btn` (0,2,0) so a template's own
   `.btn{}` rule later in the file cannot silently undo it — the same cascade trap
   that left the desktop nav stacked. */
.btnrow{display:flex;flex-wrap:wrap;gap:12px}
.btnrow > .btn{flex:1 1 100%}
@media(min-width:560px){.btnrow > .btn{flex:0 0 auto}}

/* --- long-string guard ----------------------------------------------------
   A client email address or a compound word set in a heavy display face at
   20px uppercase does not wrap, and pushes a 390px page sideways. Found on the
   Ironworks contact page: dispatch@vantagemechanical.com forced the document to
   462px. Plumbing, so every template inherits the fix. */
/* Headings are deliberately NOT in this guard. break-word on a display heading
   shatters a word mid-syllable the moment its container is narrower than the word —
   it turned "Everything we make," into "Everyth / ing we / make," on Marquee. A
   heading that does not fit is a LAYOUT bug; fix the column, do not hyphenate it. */
h1,h2,h3,h4{overflow-wrap:normal;word-break:normal}
a[href^="mailto:"],a[href^="tel:"]{overflow-wrap:anywhere}
.crow span,.crow b,.cinfo span,address{overflow-wrap:anywhere}

/* --- utility -------------------------------------------------------------- */
.sec{padding:64px 0}
@media(min-width:760px){.sec{padding:96px 0}}
@media(min-width:1180px){.sec{padding:124px 0}}
.eyebrow{font-size:12px;font-weight:750;letter-spacing:.16em;text-transform:uppercase;
  color:var(--accent);margin:0 0 14px}
.lead{font-size:19px;line-height:1.6;color:var(--ink-2)}
@media(min-width:760px){.lead{font-size:21px}}


/* ============================================================================
   PRESS — one impression, one ink, on paper.

   LIGHT LOGIC: NONE, and that is the design. Nothing on this page was
   photographed; it was PRINTED. There is no source, no direction, no cast and no
   falloff anywhere in it. There is not one shadow declaration in this file and not
   one gradient of any kind: the two words appear here, in this paragraph, and in
   the ORIENTATION note below, and nowhere else in the stylesheet. Every separation
   on the page is a rule, a change of paper, or a reversal out of solid ink.

   THE INK: --press-ink is the entire palette. It is declared ONCE below as
   var(--accent) and nothing else in this file names a colour of its own — the
   plates' shadow end, the second impression behind the headline, the rules, the
   reversed section tabs, the masthead mark, the tag slugs, the empty-price quad,
   the register band, the buttons, the accordion marker and the focus ring are all
   that property or a color-mix() of it with the paper. Change it and the
   PHOTOGRAPHS change with everything else, because the duotone is composited in
   the browser rather than baked into the JPGs. That is the reskin distance no
   other skeleton in the set has.

   MOBILE FIRST. Every rule here is the phone rule; breakpoints only add.
   ========================================================================== */

:root{
  --grade:grayscale(1) contrast(.86) brightness(1.26);
  --nav-h:60px;
  --nav-gap:28px;

  /* ---- THE INK, and the paper. Everything else is derived from these two. ---- */
  --press-ink:var(--accent);
  --press-paper:var(--surface);
  /* the ink at 88% over the paper — the darkest value a plate is allowed to reach,
     so a plate can never crush to black however dark the client's photograph is */
  --press-shade:#3B406E;
  /* the ink at 30% over the paper — the second impression behind hero.h1b */
  --ink-ghost:#B5B3BB;

  --rule:1px solid var(--line);
  --rule-hard:2px solid var(--press-ink);
  --rule-head:3px solid var(--press-ink);
  --rule-rev:1px solid rgba(244,239,227,.16);
}
@supports (color: color-mix(in srgb, #000 50%, #fff)){
  :root{
    --press-shade:color-mix(in srgb, var(--press-ink) 88%, var(--press-paper));
    --ink-ghost:color-mix(in srgb, var(--press-ink) 30%, var(--press-paper));
  }
}
/* Jon works on a 28-inch display. A 1120px measure centred in 2560px of paper is a
   sheet, not a stalled phone layout — but the trim opens once so the rate card and
   the run breathe at that width. */
@media(min-width:1700px){:root{--maxw:1320px;--gutter:64px}}

/* ---------------------------------------------------------------- type ----- */
body{background:var(--surface)}
h1{font-size:clamp(44px,10.8vw,104px);line-height:.92;letter-spacing:-.012em;margin:0}
.h-lg{font-size:clamp(30px,4.4vw,56px);line-height:1.02;letter-spacing:-.01em}
.h-md{font-size:clamp(25px,3vw,36px);line-height:1.08;letter-spacing:-.008em}
h3{font-size:20px;line-height:1.2;letter-spacing:0;font-weight:700}
.measure{max-width:60ch}
.lead{color:var(--ink-2)}
p{margin:0 0 1.05em}

/* The display face carries every label, every number and every piece of furniture
   on the page; the serif carries running text and nothing else. Two faces, one job
   each — a printed page does not need a third. */
.stab,.sdat,.slug,.rprice,.mgh,.mnote,.mp,.wd,.wt,.cbig,.pd-lab,.pd-line,.towns span,
.imprint,.hero-date,.brandtype,.mark,.fh,.fnav,.drawlab,.navcta,.field label,
.unset-h,.unset-go,.cut figcaption b,.cut figcaption span,.facts h3,.btn{
  font-family:var(--font-display)}

/* ------------------------------------------------------------ preview bar --
   Demo-only chrome. It is pinned above the masthead and the masthead is given a
   matching padding-top, published as --tpl-h. No `top` and no `position` is
   declared on #nav: the shared floor owns those and houserules.py enforces it. */
.tplbar{position:fixed;top:0;left:0;right:0;z-index:130;
  background:var(--press-ink);color:var(--band-ink-2);
  font-family:var(--font-display);font-size:12.5px;line-height:1.45;
  letter-spacing:.05em;padding:8px var(--gutter);text-align:center}
.tplbar b{color:var(--accent-on-band)}
:root:has(.tplbar){--tpl-h:52px}
@media(min-width:760px){:root:has(.tplbar){--tpl-h:32px}}
#nav{padding-top:var(--tpl-h,0px)}

/* -------------------------------------------------------------- masthead --- */
/* A printed masthead: the paper, the mark reversed out of a solid square of the
   ink, the name in the condensed face and one hard ink rule under all of it. It
   does not change on scroll, because nothing on this page reacts to light. */
#nav{background:var(--surface);border-bottom:var(--rule-hard)}
.nav-inner{gap:12px;flex-wrap:wrap;min-height:var(--nav-h)}
.brand{display:inline-flex;align-items:center;gap:11px;text-decoration:none;
  color:var(--ink);min-height:44px}
.mark{display:inline-flex;align-items:center;justify-content:center;
  width:31px;height:31px;background:var(--press-ink);color:var(--accent-ink);
  font-size:15px;font-weight:700;letter-spacing:.01em;line-height:1}
.markimg{width:auto;height:31px;background:none}
.brandtype{font-size:23px;font-weight:700;letter-spacing:-.008em;white-space:nowrap;
  line-height:1}
.navtel{display:none}
.navtoggle .bars{display:block;width:22px}
.navtoggle .bars i{display:block;height:2px;margin:5px 0;background:var(--press-ink)}
.navtoggle .bars i:nth-child(2){width:14px}
.nav-links{flex:1 0 100%;flex-direction:column;align-items:stretch;gap:0;width:100%;
  padding:2px 0 14px;margin-top:4px;border-top:var(--rule)}
.nav-links a{color:var(--ink-2);text-decoration:none;font-size:17px;
  padding:11px 0;min-height:44px;display:flex;align-items:center;
  border-bottom:var(--rule)}
.nav-links a:hover{color:var(--press-ink)}
.drawlab{font-size:11px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--press-ink);margin:12px 0 2px}
.drawhours{font-size:15px;color:var(--ink-2);margin:0 0 8px}
.drawtel{font-family:var(--font-display)!important;font-size:22px!important;
  color:var(--ink)!important}
.navcta{background:var(--press-ink);color:var(--accent-ink)!important;
  justify-content:center!important;border-bottom:0!important;margin-top:12px;
  font-size:13px!important;font-weight:700;letter-spacing:.16em;text-transform:uppercase}
html.menu-open #nav{border-bottom:var(--rule-hard)}
@media(min-width:940px){
  .nav-inner{flex-wrap:nowrap;gap:26px}
  .navtel{display:inline-flex;align-items:center;min-height:44px;margin-left:auto;
    padding-right:24px;border-right:var(--rule);
    font-family:var(--font-display);font-size:17px;letter-spacing:.01em;
    color:var(--ink);text-decoration:none}
  .navtel:hover{color:var(--press-ink)}
  .nav-links{flex:0 0 auto;width:auto;padding:0;margin:0;border:0}
  /* two classes, not one: `.nav-links a` is (0,1,1) and would beat a bare
     `.drawtel` (0,1,0), which is how a drawer's 22px telephone number ends up
     printed in a desktop masthead. */
  .nav-links a{width:auto;padding:0;border-bottom:0;font-family:var(--font-display);
    font-size:13px;font-weight:600;letter-spacing:.15em;text-transform:uppercase;
    color:var(--ink-2)}
  .nav-links .drawlab,.nav-links .drawhours,.nav-links .drawtel{display:none}
  .navcta{height:40px;margin-top:0;padding:0 18px!important;font-size:12.5px!important}
}

/* ============================================================================
   THE PLATE — the duotone, composited in the browser and never baked into a JPG.

   Three layers, and the order is the whole mechanism:
     1. the frame's background is --press-shade, the ink at 88% over the paper
     2. the greyscale image sits on it in mix-blend-mode:screen  → screen(shade,L)
        can never go BELOW the shade, so the darkest possible pixel on this page
        is a screened ink and never black. That is a floor by construction, not by
        tuning, and it is the defect 04 shipped
     3. a --press-paper layer multiplies over the result → the highlight end lands
        on the paper rather than on white
   So the tone runs paper → ink and nothing else, whatever arrives in the slot.

   THE FALLBACK IS THE POINT. Both the blend and the paper layer live inside
   @supports (mix-blend-mode:screen). A browser without blend modes gets the
   greyscale image, opaque, over the ink — a plain black-and-white photograph, and
   never an ink rectangle sitting on top of a picture nobody can see.

   ORIENTATION: there is no aspect-ratio, no object-fit and no fixed height on any
   frame below the hero, and no width/height attributes on any image below it.
   The asset sets the box; the column-flow absorbs the change. A duotone plate is
   orientation-blind because the ink is doing the work and not the crop.
   ========================================================================== */
.plate{display:block;position:relative;background:var(--press-shade);isolation:isolate}
.plate img{display:block;width:100%;filter:var(--grade)}
@supports (mix-blend-mode:screen){
  .plate img{mix-blend-mode:screen}
  .plate::after{content:"";position:absolute;inset:0;background:var(--press-paper);
    mix-blend-mode:multiply;pointer-events:none}
}

/* --------------------------------------------------------------- buttons -- */
.btn{border-radius:0;font-size:14.5px;font-weight:700;letter-spacing:.15em;
  text-transform:uppercase;padding:15px 26px;border-width:2px}
.btn-primary{background:var(--press-ink);color:var(--accent-ink);
  border-color:var(--press-ink)}
.btn-primary:hover{background:var(--accent-2);border-color:var(--accent-2)}
.btn-ghost{background:transparent;color:var(--press-ink);border-color:var(--press-ink)}
.btn-ghost:hover{background:var(--press-ink);color:var(--accent-ink)}

/* ============================================================================
   THE FORME — the hero.
   The cut FLOATS and the wordmark sets around it. The figure precedes the h1 in
   the source, so the headline's line boxes wrap round the picture while the h1's
   own block box spans the full measure: the plate is inside the wordmark's field
   (DESIGN-FLOOR A1) and yet no glyph is ever set over a photograph, at any width
   or any copy length, because float semantics forbid it. Measured: 58% of the
   measure on the phone (three short lines beside the cut, then the line opens to
   full width), 46% from 900 (two lines beside it). The rag is different at the two
   widths because the cut is a different proportion of the measure, which is what
   makes the phone hero its own composition rather than a shrunk desktop one.
   ========================================================================== */
.hero{background:var(--surface);
  padding-top:calc(var(--nav-h) + var(--tpl-h,0px) + 20px);
  padding-bottom:54px}
.hero-in::after{content:"";display:block;clear:both}
.hero-date{display:flex;justify-content:space-between;gap:14px;align-items:baseline;
  font-size:12.5px;font-weight:600;letter-spacing:.19em;text-transform:uppercase;
  color:var(--ink-3);border-bottom:var(--rule);padding-bottom:9px;margin:0 0 16px}
.hd-k{color:var(--press-ink)}
.hd-d{text-align:right}
.hero-cut{float:right;width:58%;margin:0 0 14px 16px}
.h1a{color:var(--ink)}
/* THE DRAWN MOMENT — the second impression, out of register. It lives on the
   glyphs, so it wraps with the phrase as ONE mark and can never become two bars or
   a slab under the last line (DESIGN-FLOOR D1). It is not a shadow: zero blur, a
   screened ink, and it moves sideways rather than away from a light. */
.h1b{font-style:normal;color:var(--press-ink);
  text-shadow:.055em .05em 0 var(--ink-ghost)}
.hero-sub{margin:24px 0 0;max-width:52ch}
.hero .btnrow{clear:right;margin-top:26px}
.imprint{clear:right;display:flex;flex-wrap:wrap;gap:5px 22px;margin:28px 0 0;
  padding-top:13px;border-top:var(--rule);font-size:12.5px;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3)}
.imprint a{color:var(--press-ink);text-decoration:none}
.imprint a:hover{color:var(--accent-2)}
@media(min-width:900px){
  .hero{padding-bottom:76px}
  .hero-cut{width:46%;margin:0 0 24px 36px}
  .hero-sub{font-size:22px}
}

/* -------------------------------------------------- the standing head ------
   Every section below the hero opens on a hard ink rule with a reversed tab
   hanging off it and a real datum of the business printed at the right. No datum
   is printed twice in adjacent rows: the hero's imprint carries the hours, the
   address and the telephone, so the first head under it carries the service area
   and nothing else. Delete the datum and you lose the information — that is the
   test it has to pass to be there. */
.shead{border-top:var(--rule-head);margin:0 0 32px}
.stab{display:inline-block;background:var(--press-ink);color:var(--accent-ink);
  font-size:12.5px;font-weight:700;letter-spacing:.19em;text-transform:uppercase;
  padding:6px 11px 5px;margin:0 0 20px;line-height:1}
.shead h2{margin:0 0 14px}
.shead .lead{margin:0}
.sdat{font-size:12.5px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-3);margin:16px 0 0}
.sdat a{color:var(--press-ink);text-decoration:none}
@media(min-width:900px){
  .shead{display:grid;grid-template-columns:1fr auto;column-gap:44px}
  .stab{grid-column:1;grid-row:1;justify-self:start}
  .sdat{grid-column:2;grid-row:1;margin:2px 0 0;text-align:right}
  .shead h2{grid-column:1;grid-row:2}
  .shead .lead{grid-column:1;grid-row:3}
}

/* ============================================================================
   THE RATE CARD — paper, dense, no imagery. The second axis is services[].tag,
   set as an outlined slug BEFORE the name because on a rate card the duration is
   what gets read first.
   ========================================================================== */
.row{display:grid;grid-template-columns:auto 1fr auto;column-gap:14px;row-gap:7px;
  align-items:baseline;padding:17px 0;border-top:var(--rule)}
.card > .row:last-child{border-bottom:var(--rule)}
.slug{grid-column:1;grid-row:1;align-self:center;
  font-size:11.5px;font-weight:700;letter-spacing:.15em;text-transform:uppercase;
  color:var(--press-ink);border:1px solid var(--press-ink);padding:4px 8px 3px;
  white-space:nowrap;line-height:1}
.rname{grid-column:2;grid-row:1;margin:0}
.rprice{grid-column:3;grid-row:1;justify-self:end;font-size:clamp(27px,3.6vw,40px);
  font-weight:700;color:var(--press-ink);line-height:.9}
/* THE QUAD — the shape of a figure that has not been sent. A ruled blank in the
   price column, the same width on every row so the column stays a column. Never a
   collapsed cell, and never an invented price. */
.quad{grid-column:3;grid-row:1;justify-self:end;display:block;
  width:84px;height:30px;border:2px solid var(--press-ink);position:relative}
.quad::after{content:"";position:absolute;left:9px;right:9px;top:50%;height:1px;
  background:var(--press-ink)}
.rblurb{grid-column:1/-1;grid-row:2;margin:0;color:var(--ink-2);max-width:62ch;
  font-size:16.5px}
.row.notag{grid-template-columns:1fr auto}
.row.notag .rname{grid-column:1}
.row.notag .rprice,.row.notag .quad{grid-column:2}
/* the standing note, printed ONCE above the first blank row however many there are */
.unset{background:var(--press-ink);color:var(--band-ink);padding:24px 22px;margin:0 0 2px}
.unset ~ .unset{display:none}
.unset-h{font-size:24px;font-weight:700;color:var(--accent-on-band);margin:0 0 9px;
  line-height:1.06}
.unset-b{margin:0 0 16px;color:var(--band-ink-2);max-width:58ch;font-size:16.5px}
.unset-go{display:inline-block;font-size:13px;font-weight:700;letter-spacing:.17em;
  text-transform:uppercase;color:var(--accent-on-band);text-decoration:none;
  border-bottom:2px solid var(--accent-on-band);padding-bottom:4px;min-height:44px}
.cardfoot{margin:28px 0 0;color:var(--ink-3);font-size:16px}
.mgroup{margin-top:40px}
.mgh{font-size:13px;font-weight:700;letter-spacing:.17em;text-transform:uppercase;
  color:var(--press-ink);margin:0 0 6px}
.mrow{display:grid;grid-template-columns:1fr auto;column-gap:16px;padding:11px 0;
  border-top:var(--rule)}
.mn{grid-column:1;grid-row:1}
.mnote{grid-column:1;grid-row:2;color:var(--ink-3);font-size:12.5px;
  letter-spacing:.11em;text-transform:uppercase}
.mp{grid-column:2;grid-row:1;font-size:20px;font-weight:700;color:var(--press-ink)}

/* ============================================================================
   THE RUN — the press run of pictures. A COLUMN-FLOW, never a grid with fixed
   rows: each plate keeps the proportion of its own asset and the column absorbs
   the difference, so four portraits, four landscapes or a mixture all read the
   same and nothing in this file changes.
   ========================================================================== */
.facts{display:grid;gap:20px;margin:0 0 34px;padding-top:20px;border-top:var(--rule)}
.facts h3{margin:0 0 5px;color:var(--press-ink);font-size:19px;letter-spacing:.02em}
.facts p{margin:0;color:var(--ink-2);font-size:16.5px}
@media(min-width:760px){.facts{grid-template-columns:repeat(3,1fr);column-gap:34px}}
.unsetnote{border:2px solid var(--press-ink);padding:18px 20px;margin:0 0 26px;
  color:var(--ink);font-size:17px;max-width:62ch}
.sheet{columns:1;column-gap:26px}
.cut{display:block;margin:0 0 28px;-webkit-column-break-inside:avoid;break-inside:avoid}
.cut figcaption{display:flex;justify-content:space-between;gap:14px;align-items:baseline;
  border-top:1px solid var(--press-ink);padding-top:8px;margin-top:10px}
.cut figcaption b{font-size:16px;font-weight:700;letter-spacing:.01em;color:var(--ink)}
.cut figcaption span{font-size:11.5px;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3);text-align:right}
@media(min-width:760px){.sheet{columns:2}}
@media(min-width:1180px){.sheet{columns:3;column-gap:30px}}

/* ============================================================================
   THE REGISTER — the one solid-ink surface on the page and the only thing that
   runs off the trim. There is no second colour to change voice with, so the
   change of paper IS the change of voice.
   ========================================================================== */
.band{background:var(--press-ink);color:var(--band-ink)}
.band .shead{border-top-color:var(--accent-on-band)}
.band .stab{background:var(--accent-on-band);color:var(--press-ink)}
.band h2{color:var(--band-ink)}
.band .lead{color:var(--band-ink-2)}
.band .sdat{color:var(--band-ink-2)}
.regwrap{display:grid;gap:36px}
.reg li{border-top:var(--rule-rev);padding:16px 0}
.reg li:first-child{border-top:0;padding-top:0}
.reg h3{margin:0 0 5px;color:var(--accent-on-band);font-size:19px}
.reg p{margin:0;color:var(--band-ink-2);font-size:16.5px}
.pull{margin:0;border-left:3px solid var(--accent-on-band);padding-left:24px}
.pull blockquote{margin:0;font-family:var(--font-display);font-weight:600;
  font-size:clamp(23px,2.8vw,32px);line-height:1.14;color:var(--accent-on-band)}
.pull figcaption{margin-top:18px;font-family:var(--font-display);font-size:12.5px;
  font-weight:600;letter-spacing:.15em;text-transform:uppercase;color:var(--band-ink-2)}
@media(min-width:980px){.regwrap{grid-template-columns:1fr 1fr;gap:58px}}

/* ============================================================================
   QUESTIONS — a paper accordion in a narrow column beside its own standing head
   from 900. Four short rows run across a 1120px measure is restraint that reads as
   unfinished, which is a D5 deduction rather than minimalism.
   ========================================================================== */
.asklist{border-top:var(--rule-hard)}
.ask{border-bottom:var(--rule)}
.ask summary{display:flex;justify-content:space-between;align-items:center;gap:18px;
  cursor:pointer;list-style:none;padding:16px 0;min-height:48px;
  font-family:var(--font-display);font-size:20px;font-weight:600;color:var(--ink)}
.ask summary::-webkit-details-marker{display:none}
.ask summary:hover{color:var(--press-ink)}
.ask summary i{position:relative;flex:0 0 auto;width:14px;height:14px}
.ask summary i::before,.ask summary i::after{content:"";position:absolute;
  background:var(--press-ink)}
.ask summary i::before{left:0;right:0;top:6px;height:2px}
.ask summary i::after{top:0;bottom:0;left:6px;width:2px;
  transition:transform .22s cubic-bezier(.22,.61,.36,1)}
.ask[open] summary i::after{transform:scaleY(0)}
.ask > p{margin:0 0 18px;color:var(--ink-2);max-width:62ch}
@media(min-width:900px){
  .asks .container{display:grid;grid-template-columns:1fr 1.3fr;column-gap:56px;
    align-items:start}
  .asks .shead{grid-column:1;margin-bottom:0}
  .asklist{grid-column:2}
}

/* ============================================================================
   THE ORDER — the second paper. The week ruled beside the form.
   ========================================================================== */
.order{background:var(--surface-2)}
.ogrid{display:grid;gap:36px}
.week{border-top:var(--rule-hard)}
.wrow{display:flex;justify-content:space-between;gap:16px;align-items:baseline;
  padding:13px 0;border-bottom:var(--rule)}
.wd{font-size:17px;font-weight:600;letter-spacing:.02em;color:var(--ink)}
.wt{font-size:16px;color:var(--ink-2);letter-spacing:.02em}
/* THE PRESS DAY — what prints when hours[] is absent. Not an empty table and not
   seven invented rows: the one line they did give us, set large, and the ask. */
.pressday{border-top:var(--rule-hard);padding-top:18px}
.pd-lab{font-size:12.5px;font-weight:700;letter-spacing:.17em;text-transform:uppercase;
  color:var(--press-ink);margin:0 0 10px}
.pd-line{font-size:clamp(25px,3vw,34px);font-weight:700;line-height:1.08;
  color:var(--ink);margin:0 0 12px}
.pd-ask{margin:0;color:var(--ink-3);font-size:16px;max-width:46ch}
.crow{margin-top:28px;display:grid;gap:4px}
.cbig{font-size:clamp(23px,2.6vw,29px);font-weight:600;color:var(--press-ink);
  text-decoration:none;letter-spacing:.01em;line-height:1.24}
.cbig:hover{color:var(--accent-2)}
.crow address{font-style:normal;color:var(--ink-2);margin-top:8px}
.area{margin-top:30px;padding-top:20px;border-top:var(--rule)}
.area h3{margin:0 0 6px;color:var(--press-ink);font-family:var(--font-display)}
.area p{margin:0;color:var(--ink-2);font-size:16.5px}
.towns{display:flex;flex-wrap:wrap;gap:7px;margin:12px 0 0}
.towns span{font-size:11.5px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--press-ink);border:1px solid var(--press-ink);padding:4px 8px 3px;line-height:1}
.formpanel{background:var(--surface);border:var(--rule-hard);padding:22px}
.field label{font-size:12px;font-weight:700;letter-spacing:.15em;color:var(--ink-2)}
.field input,.field select,.field textarea{border-radius:0;border-width:1px;
  border-color:var(--line);background:var(--surface)}
.fineprint{margin:16px 0 0;font-size:13.5px;color:var(--ink-3)}
.thanks{border:var(--rule-hard);border-radius:0;background:var(--surface)}
.thanks h3{font-family:var(--font-display);color:var(--press-ink)}
.formerror{font-family:var(--font-display);letter-spacing:.04em}
@media(min-width:760px){.formpanel{padding:30px}}
@media(min-width:980px){.ogrid{grid-template-columns:1fr 1.1fr;column-gap:58px}}

/* ---------------------------------------------------------------- footer --
   The colophon. Paper, one hard ink rule across the top, and the tagline — the
   one sentence about the business that appears nowhere else on the page. */
footer{background:var(--surface);border-top:var(--rule-head);padding:52px 0 42px}
.fgrid{display:grid;gap:32px}
.mark.big{width:46px;height:46px;font-size:21px}
.fname{font-size:26px;font-weight:700;font-family:var(--font-display);margin:14px 0 6px;
  line-height:1.06}
.fabout{color:var(--ink-2);margin:0;font-size:16.5px;max-width:38ch}
.fh{font-size:12.5px;font-weight:700;letter-spacing:.17em;text-transform:uppercase;
  color:var(--press-ink);margin:0 0 12px}
.fcol a,.fcol address,.fplain{display:block;color:var(--ink-2);text-decoration:none;
  font-style:normal;margin-bottom:6px}
.fcol a:hover{color:var(--press-ink)}
.fplain.lab{color:var(--ink)}
.fnav{display:flex;flex-wrap:wrap;gap:9px 24px;margin-top:36px;padding-top:16px;
  border-top:var(--rule);font-size:12.5px;font-weight:600;letter-spacing:.15em;
  text-transform:uppercase}
.fnav a{color:var(--ink-3);text-decoration:none}
.fnav a:hover{color:var(--press-ink)}
.colophon{margin:20px 0 0;color:var(--ink-3);font-size:15.5px;max-width:70ch}
.fbase{display:flex;flex-wrap:wrap;justify-content:space-between;gap:8px 20px;
  margin-top:22px;padding-top:15px;border-top:var(--rule);font-size:13.5px;
  color:var(--ink-3)}
@media(min-width:760px){.fgrid{grid-template-columns:1.3fr 1fr 1fr;column-gap:42px}}

/* ============================================================================
   MOTION — three moments, none of which moves a layout box.
   1. THE HOUSE REVEAL lives in base.css, gated behind html.js.
   2. THE SECOND IMPRESSION: the hero ghost slides out of register on load. It
      animates a text-shadow offset, so no box moves and no content is ever
      withheld — the end state is exactly what a no-JS visitor gets immediately.
   3. THE INK DRIES: a plate arrives at full ink and clears to its duotone as the
      figure reveals. It animates the paper layer's opacity INSIDE an element that
      has already been revealed, so no observer ever watches a zero-area box.
   ========================================================================== */
html.js .h1b{animation:register .7s cubic-bezier(.22,.61,.36,1) .3s 1 both}
@keyframes register{
  from{text-shadow:0 0 0 var(--ink-ghost)}
  to{text-shadow:.055em .05em 0 var(--ink-ghost)}
}
@supports (mix-blend-mode:screen){
  html.js .cut.reveal .plate::after{opacity:0;
    transition:opacity .8s cubic-bezier(.22,.61,.36,1) .12s}
  html.js .cut.reveal.in .plate::after{opacity:1}
}
@media(prefers-reduced-motion:reduce){
  html.js .h1b{animation:none}
  html.js .cut.reveal .plate::after,html.js .cut.reveal.in .plate::after{
    opacity:1;transition:none}
}
