/* ==========================================================================
   HOUSE OF PRESS

   The whole site is a print in a frame. The frame is fixed to the viewport
   and never moves; the sheet inside it is the only thing that scrolls. So
   the page does not scroll, a panel does, and everything downstream of that
   follows from it: no page-level scrollbar, sticky positions resolve against
   the sheet, and nothing can escape the moulding.

   The paper is Cordenons Wild, photographed and mirrored into a seamless
   tile. Every piece of type is pressed into it.
   ========================================================================== */

:root{
  /* the sheet */
  --paper:      #D7D0C6;
  --paper-hi:   #E2DCD3;
  --paper-lo:   #C4BCAF;

  /* ink, warm and never quite black */
  --ink:        #241E16;
  --ink-soft:   #4A4238;
  --ink-faint:  #6E6558;

  /* the wall the frame hangs on */
  --wall:       #171310;

  --rule:       rgba(42,36,28,.26);
  --rule-soft:  rgba(42,36,28,.13);

  /* faces */
  /* The highlight. Sparingly, and LETTERS ONLY: Megalito's numeral slots are
     drawn as ornaments, not figures, so anything with a digit in it set in
     this face comes out as a row of little decorations. Use --f-num. */
  --f-hi:   'Megalito Slab', Georgia, serif;
  /* for anything that has to read as a number: years, counts, prices */
  --f-num:  'Inria Serif', Georgia, serif;
  --f-body: 'Inria Serif', Georgia, serif;
  --f-mono: 'Xanh Mono', ui-monospace, monospace;

  /* the frame */
  --fw:   clamp(22px, 2.6vw, 40px);            /* moulding width */
  --gap:  8px;                                 /* wall showing round it */

  --gut:  clamp(1.3rem, 4.5vw, 4.5rem);
  --sect: clamp(4.5rem, 9vw, 9rem);
  --wrap: 1180px;

  --ease: cubic-bezier(.16,1,.3,1);
  color-scheme: light;
}

*,*::before,*::after{ box-sizing:border-box; }

/* The `hidden` attribute is only display:none in the UA stylesheet, so any
   author rule that sets display beats it and the element stays on screen.
   The order summary's design-service row is a flex row and was showing a
   price for a service nobody had ticked. */
[hidden]{ display:none !important; }

/* The page itself must not scroll. If it does, the frame scrolls with it and
   the illusion is gone the first time anyone flicks a trackpad. */
html,body{ height:100%; overflow:hidden; }

body{
  margin:0;
  background:var(--wall);
  color:var(--ink);
  font-family:var(--f-body); font-weight:300;
  font-size:clamp(1rem,.95rem + .2vw,1.08rem);
  line-height:1.75;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

h1,h2,h3,h4{ margin:0; font-weight:400; }
p{ margin:0; }
img{ max-width:100%; }
a{ color:inherit; }
:focus-visible{ outline:2px solid var(--ink); outline-offset:3px; }

/* For headings a page needs in its outline but not on its face. Clipped
   rather than display:none, which would take it out of the accessibility
   tree along with the layout. */
.sr-only{
  position:absolute; width:1px; height:1px;
  margin:-1px; padding:0; border:0;
  clip-path:inset(50%); overflow:hidden; white-space:nowrap;
}


/* ==========================================================================
   THE FRAME
   Fixed, and drawn with border-image so the corners mitre at 45 degrees the
   way a real moulding is cut. The artwork carries the profile, the grain and
   the wear; CSS only decides how wide it is. See tools/make-frame.py.
   ========================================================================== */
.frame{
  position:fixed; inset:var(--gap);
  border:var(--fw) solid transparent;
  border-image:url('img/frame.png') 128 fill / var(--fw) / 0 stretch;
  box-shadow:
    0 2px 4px rgba(0,0,0,.5),
    0 18px 40px rgba(0,0,0,.55),
    0 40px 90px rgba(0,0,0,.45);
}

/* On a wide screen the frame goes to the edge of the glass. The dark strip
   that used to show round it is --gap, the wall the frame hangs on, and at
   26px it read as a browser letterboxing the page rather than as a wall.
   It is kept on small screens, where the frame needs to look like an object
   you are holding rather than a chrome. */
@media (min-width: 900px){
  :root{ --gap:0px; }
}

/* the sheet. absolutely positioned children resolve against the padding box,
   which is the inside of the moulding, so this fills the window exactly */
.sheet{
  position:absolute; inset:0;
  overflow-y:auto; overflow-x:hidden;
  overscroll-behavior:contain;
  background:url('img/paper.jpg') repeat, var(--paper);
  /* The tile is a 2x2 mirror, so its symmetry repeats at this interval.
     Drawn small the butterfly is obvious; at 1100px the mirror falls outside
     what the eye groups and the sheet reads as one continuous surface.
     The photograph is high-passed before mirroring, which is what removes
     the lighting blotches that made the seam findable in the first place. */
  background-size:1100px auto;
  /* the rebate throws a shadow onto the paper just inside the moulding */
  box-shadow:
    inset 0 0 3px rgba(0,0,0,.34),
    inset 0 0 26px rgba(60,45,30,.16);
  scrollbar-width:none;
}
.sheet::-webkit-scrollbar{ display:none; }

@media (prefers-reduced-motion: no-preference){
  .sheet{ scroll-behavior:smooth; }
}

/* the maker's name, stamped on the bottom rail.

   An absolutely positioned child of the frame resolves its offsets against
   the padding box, which is the inside of the moulding, so a bottom of minus
   one rail width puts this exactly over the wood and a height of one rail
   width centres it in the moulding without a single magic number.

   Painted on rather than cut in: dark type on dark walnut would be a credit
   nobody can read. Light warm ink with the shadow under it reads as stencil
   on old wood and clears AA against the moulding's mean. */
.plate{
  position:absolute; left:50%; bottom:calc(-1 * var(--fw));
  transform:translateX(-50%);
  height:var(--fw);
  display:flex; align-items:center;
  white-space:nowrap; text-decoration:none;
  font-family:var(--f-mono);
  font-size:clamp(.46rem, .3rem + .34vw, .66rem);
  letter-spacing:.22em; text-transform:uppercase;
  color:rgba(236,219,193,.88);
  /* The halo is not decoration. The rail runs from L76 in the cove to L110
     on a bare chip, and light type at .88 clears 5:1 on the first and 2.8:1
     on the second. Darkening the ground immediately around each letter is
     what holds it legible across both without lighting the whole line. */
  text-shadow:0 0 6px rgba(0,0,0,.55), 0 1px 2px rgba(0,0,0,.75);
  transition:color .3s var(--ease);
}
.plate:hover{ color:rgba(250,242,229,1); }


/* ==========================================================================
   THE IMPRESSION

   Everything on the sheet is pressed into it. Two treatments only:

   .press   ink, driven into the paper. A light catch below the letter and a
            soft shadow above is what the eye reads as a recess. This is the
            default for all type, applied on body.
   .blind   no ink at all, the letter the same colour as the sheet and read
            entirely by its shadow. For marks, not for reading.

   The catch has to stay subtle. Push it past about .55 and the type starts
   to look bevelled rather than pressed, which is the difference between
   letterpress and a 2004 web gradient. A deeper pass was tried across the
   whole site and put back: scaled up, the recess stops reading as paper and
   starts reading as 3D type sitting on top of it.
   ========================================================================== */
body{
  /* Three layers, and each does a different job. The white catch below the
     letter is the lip of the recess lifting into the light. The dark line
     directly above is the far wall of it. The soft cast underneath is the
     depth. Drop the middle one and it flattens into a highlight; drop the
     last and it reads as a stamp rather than a bite. */
  text-shadow:
    0 1px 0 rgba(255,255,255,.82),
    0 -1px 0 rgba(42,36,28,.30),
    0 2px 3px rgba(42,36,28,.14);
}

.blind{
  /* No ink at all, so the shadow is doing every bit of the work and can
     take far more than inked type can. */
  color:var(--paper);
  text-shadow:
    0 2px 0 rgba(255,255,255,.95),
    0 -1px 0 rgba(42,36,28,.55),
    0 -2px 3px rgba(42,36,28,.30),
    0 4px 8px rgba(42,36,28,.16);
}
/* the deeper the impression, the larger the letter has to be to carry it */
.blind--xl{
  text-shadow:
    0 3px 0 rgba(255,255,255,1),
    0 -2px 0 rgba(42,36,28,.62),
    0 -4px 5px rgba(42,36,28,.34),
    0 12px 24px rgba(42,36,28,.18);
}

/* Illustrations get the same press. A drop-shadow filter follows the alpha
   of the artwork rather than its box, so line art is genuinely embossed
   instead of sitting on a rectangle of shadow. */
.pressed{
  filter:
    drop-shadow(0 1px 0 rgba(255,255,255,.8))
    drop-shadow(0 -1px 0 rgba(42,36,28,.42))
    drop-shadow(0 3px 4px rgba(42,36,28,.16));
}


/* ---------- type roles ---------- */
.hi{
  font-family:var(--f-hi); font-weight:400;
  letter-spacing:.01em; line-height:.94;
}
.mono{
  font-family:var(--f-mono); font-weight:400;
  font-size:.7rem; letter-spacing:.18em; text-transform:uppercase;
  line-height:1.7;
}
.mono--faint{ color:var(--ink-faint); }

.rule{ border:0; border-top:1px solid var(--rule); margin:0; }

.lnk{
  display:inline-flex; align-items:center; gap:.6em;
  font-family:var(--f-mono); font-size:.7rem;
  letter-spacing:.18em; text-transform:uppercase;
  text-decoration:none; color:var(--ink);
  padding-bottom:.35rem;
  border-bottom:1px solid var(--rule);
  transition:gap .3s var(--ease), border-color .3s var(--ease);
}
.lnk:hover{ gap:1.1em; border-color:var(--ink); }

.btn{
  display:inline-flex; align-items:center; justify-content:center;
  padding:.95rem 1.9rem; white-space:nowrap;
  background:var(--ink); color:var(--paper-hi);
  border:1px solid var(--ink);
  font-family:var(--f-mono); font-size:.68rem;
  letter-spacing:.18em; text-transform:uppercase; text-decoration:none;
  text-shadow:none;
  box-shadow:0 1px 0 rgba(255,255,255,.4);
  transition:background-color .3s var(--ease), color .3s var(--ease);
}
.btn:hover{ background:transparent; color:var(--ink); }
/* both used by the timeline: the masthead button and the closing call */
.btn--sm{ padding:.62rem 1.2rem; font-size:.62rem; letter-spacing:.16em; }
.btn--lg{ padding:1.15rem 2.6rem; }


/* ==========================================================================
   NAV
   Sticky to the sheet, not the window, so it rides inside the moulding.
   ========================================================================== */
/* A masthead, not a toolbar. It carries the badge at a size that can hold
   the top of the sheet, and the links are set as small capitals with the
   tracking opened up, which is how a printer would set them and the only way
   type this small holds any authority. */
.nav{
  position:sticky; top:0; z-index:20;
  display:grid; grid-template-columns:1fr auto 1fr; align-items:center;
  gap:clamp(1rem,3vw,2.5rem);
  padding:clamp(1.2rem,2.6vw,2rem) var(--gut) clamp(1rem,2.2vw,1.6rem);
  /* solid for most of its depth, then a fade, so type passing underneath
     goes out cleanly instead of colliding with a hard edge. The paper is low
     contrast enough that the flat patch does not read against the tile. */
  background:linear-gradient(var(--paper) 68%, rgba(215,208,198,.92) 86%, rgba(215,208,198,0));
}
.nav__set{ display:flex; gap:clamp(1.5rem,3.2vw,3rem); align-items:center; }
/* the two sets push away from the badge in the middle */
.nav__set--l{ justify-content:flex-start; }
.nav__set--r{ justify-content:flex-end; }
.nav a{
  font-family:var(--f-mono);
  font-size:clamp(.76rem,.72rem + .25vw,.9rem);
  letter-spacing:.2em; text-transform:uppercase;
  text-decoration:none; color:var(--ink-soft);
  padding-bottom:.2rem;
  border-bottom:1px solid transparent;
  transition:color .25s var(--ease), border-color .25s var(--ease);
}
.nav a:hover{ color:var(--ink); border-bottom-color:var(--rule); }
/* the page you are on, marked the way a printer marks a proof */
.nav a[aria-current="page"]{ color:var(--ink); border-bottom-color:var(--ink); }

/* The studio's badge, in its own colour. The maroon runs edge to edge in the
   artwork, so there is no white ground to drop out and no blend mode needed;
   it just gets the same impression as everything else on the sheet, which is
   what stops a full-colour block reading as a sticker laid on top. */
.nav__mark{ display:block; line-height:0; }
.nav__mark img{
  /* the source is 150px square, so this stays inside its real resolution
     even on a 2x screen */
  display:block; width:clamp(52px,6vw,74px); height:auto;
  filter:
    drop-shadow(0 1px 0 rgba(255,255,255,.7))
    drop-shadow(0 -1px 0 rgba(42,36,28,.38))
    drop-shadow(0 3px 5px rgba(42,36,28,.20));
}
/* Five real pages, so nothing in here may be hidden to make it fit. The
   three columns collapse to one, the badge takes the top of it, and the
   links wrap under it centred. */
@media (max-width:720px){
  .nav{
    grid-template-columns:1fr; justify-items:center;
    gap:.55rem; text-align:center;
    padding:.9rem var(--gut) .7rem;
  }
  .nav__mark{ order:-1; }
  .nav__mark img{ width:44px; }
  .nav__set{ flex-wrap:wrap; justify-content:center; gap:.5rem 1.1rem; }
  .nav__set--r{ justify-content:center; }
  /* Stacked, this is three rows of furniture at the top of every page. Left
     at the desktop scale it stood 172px tall on an 812px screen, which is a
     fifth of the sheet given over to navigation before a word of the page. */
  .nav a{ font-size:.7rem; letter-spacing:.16em; }
}


/* ==========================================================================
   SECTIONS
   ========================================================================== */
.sec{ padding:var(--sect) var(--gut); max-width:var(--wrap); margin:0 auto; }
.sec__eyebrow{ margin-bottom:1.6rem; }
.sec__t{
  font-family:var(--f-body); font-weight:400;
  font-size:clamp(1.7rem,4vw,3.2rem); line-height:1.12;
  max-width:20ch;
}
.sec__lede{
  margin-top:1.6rem; max-width:52ch;
  font-size:clamp(1.05rem,1.7vw,1.3rem); line-height:1.6;
}
.sec__body{ margin-top:1.6rem; max-width:56ch; color:var(--ink-soft); }
.sec__body p + p{ margin-top:1.1rem; }
.sec__foot{ margin-top:2.6rem; }

.two{
  display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(2rem,5vw,5rem); align-items:start;
}
@media (max-width:860px){ .two{ grid-template-columns:1fr; } }

/* a numbered index that opens */
.acc{ border-top:1px solid var(--rule); }
.acc:last-of-type{ border-bottom:1px solid var(--rule); }
.acc > summary{
  display:grid; grid-template-columns:3.2rem minmax(0,1fr) auto;
  align-items:center; gap:1.4rem;
  padding:1.1rem 0; cursor:pointer; list-style:none;
}
.acc > summary::-webkit-details-marker{ display:none; }
.acc__n{
  font-family:var(--f-mono); font-size:.72rem; color:var(--ink-faint);
}
.acc__t{ font-family:var(--f-body); font-size:1.05rem; }
.acc__sign{ position:relative; width:12px; height:12px; }
.acc__sign::before,.acc__sign::after{
  content:''; position:absolute; inset:0; margin:auto; background:var(--ink);
  transition:transform .35s var(--ease);
}
.acc__sign::before{ width:12px; height:1px; }
.acc__sign::after { width:1px; height:12px; }
.acc[open] .acc__sign::after{ transform:scaleY(0); }
.acc__body{
  padding:0 0 1.4rem 4.6rem; max-width:56ch;
  color:var(--ink-soft); font-size:.95rem;
}
@media (max-width:600px){ .acc__body{ padding-left:0; } }

/* plates */
.plate{ margin:0; }
.plate img{
  display:block; width:100%; height:auto;
  filter:grayscale(1) contrast(1.06) brightness(1.02);
  mix-blend-mode:multiply;
}
.plate figcaption{
  margin-top:.7rem;
  font-family:var(--f-mono); font-size:.63rem;
  letter-spacing:.15em; text-transform:uppercase; color:var(--ink-faint);
}

.strip{
  display:grid; grid-template-columns:repeat(4,minmax(0,1fr));
  gap:clamp(1.2rem,3vw,2.6rem); align-items:center;
  padding:0 var(--gut) var(--sect); max-width:var(--wrap); margin:0 auto;
}
.strip img{
  display:block; width:100%; height:auto;
  max-height:clamp(120px,15vw,190px); object-fit:contain;
  mix-blend-mode:multiply;
}
@media (max-width:820px){ .strip{ grid-template-columns:repeat(2,minmax(0,1fr)); } }

/* the close */
.foot{
  padding:var(--sect) var(--gut) calc(var(--sect) * .6);
  max-width:var(--wrap); margin:0 auto;
  border-top:1px solid var(--rule);
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(1.6rem,4vw,3rem);
}
.foot h4{
  font-family:var(--f-mono); font-size:.65rem;
  letter-spacing:.18em; text-transform:uppercase; margin-bottom:1rem;
}
.foot p, .foot li{ font-size:.92rem; color:var(--ink-soft); }
.foot ul{ list-style:none; margin:0; padding:0; }
.foot a{ text-decoration:none; }
.foot a:hover{ text-decoration:underline; text-underline-offset:3px; }
@media (max-width:720px){ .foot{ grid-template-columns:1fr; } }

.colophon{
  max-width:var(--wrap); margin:0 auto;
  padding:0 var(--gut) calc(var(--sect) * .5);
  display:flex; flex-wrap:wrap; gap:.5rem 1.4rem; justify-content:space-between;
  font-family:var(--f-mono); font-size:.64rem;
  letter-spacing:.16em; text-transform:uppercase; color:var(--ink-faint);
}
.colophon a{ text-decoration:none; border-bottom:1px solid var(--rule-soft); }
.colophon a:hover{ color:var(--ink); border-bottom-color:var(--ink); }


/* ==========================================================================
   REVEALS
   Nothing is hidden in the base state: the motion lives inside @supports, so
   without scroll timelines the sheet simply renders finished. The timelines
   are anchored to the sheet, because the sheet is the scroller.
   ========================================================================== */
@keyframes inkIn{ from{ opacity:0; transform:translateY(14px); } to{ opacity:1; transform:none; } }
@keyframes wipeIn{ from{ clip-path:inset(0 100% 0 0); } to{ clip-path:inset(0 0 0 0); } }

@supports (animation-timeline: view()){
  @media (prefers-reduced-motion: no-preference){
    [data-in],[data-wipe]{
      animation-duration:auto; animation-fill-mode:both;
      animation-timeline:view();
    }
    [data-in]{
      animation-name:inkIn; animation-range:entry 8% entry 56%;
      animation-timing-function:var(--ease);
    }
    [data-wipe]{
      animation-name:wipeIn; animation-range:entry 12% entry 64%;
      animation-timing-function:cubic-bezier(.22,.68,.16,1);
    }
  }
}

@media (prefers-reduced-motion: reduce){
  .hero__scroll i{ animation:none; }
  .sheet{ scroll-behavior:auto; }
}

/* the nav lifts off the sheet once you have moved away from the top */
.nav.is-off{ border-bottom:1px solid var(--rule-soft); }
