/* Artie — main site. The 2026 pricelist template as a website, printed: full-bleed photo pages alternating with
   solid ink pages on paper. The photographs stay clean; everything around them looks pressed onto stock —
   paper grain under every ink, a second plate slightly off register, rubber stamps, a postmark, stencil numbers,
   portfolio thumbnails as perforated postage stamps, one watercolour wash.
   Type, taken from Artie's lettering: headlines are Tenor Sans caps run through the #hand filters (swelled, rounded at the
   ends, a little unsteady) so they read like the hand-drawn ARTIE under the bust and stay real text; EB Garamond for
   reading; Stardos Stencil for numbers. */
:root {
  --blue: #3764E4;   /* paper text on it 4.8:1 */
  --red: #CD392B;    /* Artie's red; paper text on it 4.75:1 */
  --red-ink: #B32A1E; /* the same red, deepened for small type on the cream paper: 5.2:1 (Artie's red there is 4.0:1) */
  --yellow: #FFC73D; /* ink on it 12:1 */
  --ink: #141413;
  --cream: #EDE7CF;  /* Artie's paper */
  --paper: #FFF9EC;  /* knock-out "white": the brightest paper, for text on red, blue and ink */
  --stencil: "Stardos Stencil", "Helvetica Neue", Arial, sans-serif;
  /* paper and cloth are photographs (tools/tex.ps1 makes them seamless and evenly lit), multiplied into whatever ink sits on them:
     recycled fibre paper for the cream stock, linen bookcloth under the yellow and blue, speckled board under the red */
  --grain: url("tex/paper-fibre.webp") 0 0 / 512px;
  --linen: url("tex/linen.webp") 0 0 / 512px;
  --laid: url("tex/paper-speckle.webp") 0 0 / 512px;  /* the lace on the red card stays drawn */
  --lace: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60' height='44' viewBox='0 0 60 44'%3E%3Cg fill='none' stroke='%23FFF9EC' stroke-linecap='round' opacity='.92'%3E%3Cpath stroke-width='1.2' d='M0 2.2H60M0 4.4H60'/%3E%3Cpath stroke-width='.35' d='M0 5l3 3 3-3 3 3 3-3 3 3 3-3 3 3 3-3 3 3 3-3 3 3 3-3 3 3 3-3 3 3 3-3 3 3 3-3 3 3 3-3M0 11l3-3 3 3 3-3 3 3 3-3 3 3 3-3 3 3 3-3 3 3 3-3 3 3 3-3 3 3 3-3 3 3 3-3 3 3 3-3 3 3 3-3'/%3E%3Cpath stroke-width='.35' d='M6 14h48M9 17.5h42M12 21h36M16 24.5h28M21 28h18M26 31.5h8M10 13l20 22 20-22M18 13l12 22 12-22'/%3E%3Cpath stroke-width='1.1' d='M0 12Q30 55 60 12'/%3E%3Cpath stroke-width='.5' d='M4 13Q30 50 56 13'/%3E%3Cg stroke-width='.5'%3E%3Ccircle cx='54.5' cy='20.1' r='1.1'/%3E%3Ccircle cx='51.5' cy='25.6' r='1.1'/%3E%3Ccircle cx='46.7' cy='30.2' r='1.1'/%3E%3Ccircle cx='40.6' cy='33.6' r='1.1'/%3E%3Ccircle cx='33.6' cy='35.3' r='1.1'/%3E%3Ccircle cx='26.4' cy='35.3' r='1.1'/%3E%3Ccircle cx='19.4' cy='33.6' r='1.1'/%3E%3Ccircle cx='13.3' cy='30.2' r='1.1'/%3E%3Ccircle cx='8.5' cy='25.6' r='1.1'/%3E%3Ccircle cx='5.5' cy='20.1' r='1.1'/%3E%3C/g%3E%3Cg stroke-width='.6'%3E%3Ccircle cx='30' cy='22' r='1.6'/%3E%3Cellipse cx='30' cy='18.2' rx='1.1' ry='2.2'/%3E%3Cellipse cx='30' cy='25.8' rx='1.1' ry='2.2'/%3E%3Cellipse cx='26.2' cy='22' rx='2.2' ry='1.1'/%3E%3Cellipse cx='33.8' cy='22' rx='2.2' ry='1.1'/%3E%3C/g%3E%3C/g%3E%3Cg fill='%23FFF9EC' opacity='.92'%3E%3Ccircle cx='12' cy='34.5' r='.8'/%3E%3Ccircle cx='17' cy='38' r='.8'/%3E%3Ccircle cx='23.5' cy='40.6' r='.8'/%3E%3Ccircle cx='30' cy='41.6' r='.9'/%3E%3Ccircle cx='36.5' cy='40.6' r='.8'/%3E%3Ccircle cx='43' cy='38' r='.8'/%3E%3Ccircle cx='48' cy='34.5' r='.8'/%3E%3C/g%3E%3C/svg%3E");
  --display: "Tenor Sans", Optima, Candara, serif;
  --text: "EB Garamond", Garamond, Georgia, serif;
  --pad: clamp(20px, 4.5vw, 64px);
  /* motion: one curve for the slow, printed arrivals, one strong ease-out for anything answering a press or a scroll */
  --ease-print: cubic-bezier(.2, .7, .2, 1);
  --ease-out: cubic-bezier(.23, 1, .32, 1);
}
@view-transition { navigation: auto; }
* { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body { font: 400 19px/1.5 var(--text); font-synthesis: none; font-kerning: normal; font-feature-settings: "kern", "liga", "onum"; color: var(--ink); background: var(--grain), var(--cream); background-blend-mode: multiply; }
img { display: block; width: 100%; height: 100%; object-fit: cover; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
:focus-visible { outline: 2px solid currentColor; outline-offset: 4px; }
h1, h2, h3, p { text-wrap: pretty; }

/* the big lines: a light serif in sentence case; the hero keeps its justified Helvetica caps */
/* the big lines: ARTIE's hand-lettered caps */
.say { font: 400 1em/1.16 var(--display); text-transform: uppercase; letter-spacing: .09em; text-wrap: balance; hyphens: none; filter: url(#hand); font-feature-settings: "kern"; }
.kicker, .no { font: 700 13px/1.3 var(--stencil); text-transform: uppercase; letter-spacing: .22em; }
.mark { display: block; aspect-ratio: 466 / 680; height: auto; fill: currentColor; filter: url(#print); }

/* printed matter, shared */
.stamp, .postmark { display: block; pointer-events: none; mix-blend-mode: multiply; }
.stamp text, .postmark text { font: 400 17px var(--display); fill: currentColor; letter-spacing: .1em; }
.perf, .strip img { --h: 14px; padding: 9px; background: var(--paper); /* a postage stamp: paper border, perforated edge */
  -webkit-mask: radial-gradient(circle, #0000 3.4px, #000 4px) calc(var(--h) / -2) calc(var(--h) / -2) / var(--h) var(--h) round,
                linear-gradient(#000 0 0) center / calc(100% - var(--h)) calc(100% - var(--h)) no-repeat;
          mask: radial-gradient(circle, #0000 3.4px, #000 4px) calc(var(--h) / -2) calc(var(--h) / -2) / var(--h) var(--h) round,
                linear-gradient(#000 0 0) center / calc(100% - var(--h)) calc(100% - var(--h)) no-repeat; }

/* ---------- cover (hero) ---------- */
.cover { position: relative; height: 100svh; min-height: 560px; overflow: hidden; color: #fff; background: var(--ink); font-family: var(--display); font-feature-settings: "kern", "lnum"; }
.cover .label { font: 400 .92em/1.2 var(--display); text-transform: uppercase; letter-spacing: .16em; filter: url(#hand-s); }
.cover[data-ink="red"] { color: var(--red); }
.cover > *:not(.slides) { transition: color .95s cubic-bezier(.76, 0, .24, 1); } /* the ink changes with the curtain, not ahead of it */
.cover { touch-action: pan-y pinch-zoom; } /* sideways swipes turn the cover (artie.js) */
.slides figure { position: absolute; inset: 0; visibility: hidden; }
.slides figure.on, .slides figure.was { visibility: visible; }
.slides figure.on { z-index: 1; }
.slides figure::after { content: ""; position: absolute; inset: 0; background: linear-gradient(transparent 55%, rgb(0 0 0 / .38)); }
.slides figure[data-ink="red"]::after { display: none; }
.top { position: absolute; z-index: 2; inset: 0 0 auto; display: flex; justify-content: space-between; align-items: flex-start; padding: var(--pad); }
.top .mark { width: clamp(44px, 4.4vw, 64px); }
.top nav { display: flex; gap: clamp(16px, 2.4vw, 36px); text-transform: uppercase; font-size: 13px; letter-spacing: .2em; }
.top nav a:hover { text-decoration: underline; text-underline-offset: 4px; }
.top nav a, .foot nav a { position: relative; }
.top nav a::before, .foot nav a::before { content: ""; position: absolute; inset: -13px -7px; } /* small caps, finger-sized target */
.year { position: absolute; z-index: 1; right: var(--pad); top: calc(var(--pad) + clamp(64px, 9vw, 120px)); font-size: clamp(64px, 10vw, 150px); filter: url(#hand-xl); line-height: .92; letter-spacing: -.02em; }
.base { position: absolute; z-index: 1; left: var(--pad); bottom: var(--pad); display: inline-grid; gap: clamp(16px, 2vw, 28px); }
.tag { display: inline-grid; font-size: clamp(28px, 5vw, 70px); text-transform: uppercase; line-height: 1.04; letter-spacing: .05em; filter: url(#hand-l); }
.tag > span { display: flex; justify-content: space-between; gap: .3em; }
.tag i { font-style: normal; }
.now { width: 0; min-width: 100%; font-size: clamp(13px, 1.1vw, 16px); } /* takes the tagline's width, never sets it */
.now .label { min-height: 2.1em; display: flex; align-items: flex-end; }
.dots { display: flex; gap: 6px; margin-top: 14px; }
.dots { margin-top: 6px; }
.dots button { flex: 1; height: 34px; border: 0; background: none; cursor: pointer; position: relative; color: inherit; } /* a thumb-sized bar around a 2px line */
.dots button::before, .dots button::after { content: ""; position: absolute; left: 0; right: 0; top: 16px; height: 2px; background: currentColor; opacity: .35; }
.dots button::after { opacity: 1; transform: scaleX(0); transform-origin: left; }
.dots button[aria-current="true"]::after { transform: scaleX(1); animation: fill 5.2s linear; }
@keyframes fill { from { transform: scaleX(0); } }
.cover.hold .dots button::after { animation-play-state: paused; } /* the bar is the cover's timer: holding it holds the cover */

/* the header, once the cover has gone: a printed strip that comes back when you scroll up, with the sheet's Nº */
.cover .top.stuck { position: fixed; z-index: 20; align-items: center; padding-block: 12px; color: var(--ink); background: var(--grain), var(--cream); background-blend-mode: multiply; box-shadow: 0 1px 0 rgb(20 20 19 / .14); translate: 0 -110%; }
.cover .top.stuck.armed { transition: translate .24s var(--ease-out); } /* comes back on every turn up the page: it answers, it doesn't perform */
.cover .top.stuck.show { translate: none; }
.cover .top.stuck .mark { width: 30px; }
.top .frame { display: none; }
.top.stuck .frame:not(:empty) { display: block; margin: 0 auto 0 20px; white-space: nowrap; font: 700 12px/1 var(--stencil); letter-spacing: .22em; }
@supports (animation-timeline: scroll()) {
  .cover .top.stuck::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: var(--red); transform-origin: 0 50%; animation: wind linear both; animation-timeline: scroll(root); } /* how far through the roll */
  @keyframes wind { from { transform: scaleX(0); } }
}

/* ---------- intro ---------- */
.intro { display: grid; grid-template-columns: 1.15fr 1fr; background: var(--linen), var(--blue); background-blend-mode: multiply; color: var(--paper); --ghost: rgb(255 199 61 / .45); }
.intro .text { position: relative; padding: calc(var(--pad) * 2) var(--pad); display: flex; flex-direction: column; justify-content: center; gap: 28px; }
.intro .text > * { position: relative; z-index: 1; }
.intro .say { font-size: clamp(28px, 3vw, 46px); max-width: 14em; }
.intro p:not(.say) { max-width: 30em; font-size: clamp(19px, 1.5vw, 22px); }
.intro figure { min-height: 70svh; }

/* ---------- spreads: photo page + colour page ---------- */
.spread { display: grid; grid-template-columns: 1fr 1fr; min-height: 100svh; background: var(--tex, var(--grain)), var(--bg); background-blend-mode: multiply; color: var(--fg); }
.spread.flip .photo { order: 2; }
.photo { position: relative; color: #fff; min-height: 100svh; }
.photo .mark { position: absolute; z-index: 1; top: var(--pad); left: var(--pad); width: 44px; pointer-events: none; }
.colour { display: flex; flex-direction: column; min-width: 0; padding: calc(var(--pad) * 1.6) 0 var(--pad); }
.colour .say, .colour > p { padding: 0 var(--pad); }
.colour .no { margin-bottom: clamp(18px, 2vw, 28px); opacity: .8; }
#brand { --ghost: rgb(205 57 43 / .4); --tex: var(--linen); }
#events { --ghost: rgb(205 57 43 / .55); }
#property { --ghost: rgb(255 199 61 / .45); --tex: var(--linen); }
#graduation { --ghost: rgb(20 20 19 / .3); --tex: var(--laid); }
#people { --ghost: rgb(55 100 228 / .35); }
.colour .say { font-size: clamp(26px, 2.8vw, 42px); max-width: 14em; }
.colour > p:not(.say):not(.no) { margin-top: 22px; max-width: 30em; font-size: clamp(19px, 1.45vw, 21px); }
.strip { margin-top: auto; padding: 40px var(--pad) 8px; display: flex; gap: 14px; overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding: 0 var(--pad); scrollbar-width: none; }
.strip::-webkit-scrollbar { display: none; }
.strip > * { flex: none; }
.strip img { width: auto; height: clamp(220px, 34svh, 360px); scroll-snap-align: start; }
.strip > img:nth-child(odd), .strip > :nth-child(odd) > img { rotate: -.7deg; } /* with or without artie.js's link around each stamp */
.strip > img:nth-child(even), .strip > :nth-child(even) > img { rotate: .5deg; }
.strip.more { -webkit-mask: linear-gradient(90deg, #000 calc(100% - 90px), #0000); mask: linear-gradient(90deg, #000 calc(100% - 90px), #0000); } /* more stamps wait off the edge */
.flick { display: flex; justify-content: flex-end; gap: 8px; margin-top: auto; padding: 32px var(--pad) 0; }
.flick[hidden] { display: none; }
.flick + .strip { margin-top: 0; padding-top: 14px; }
.flick button { display: grid; place-items: center; width: 42px; height: 42px; border: 1px solid; border-radius: 50%; background: none; color: inherit; cursor: pointer; transition: background .25s, color .25s, opacity .25s; }
.flick button:hover:not(:disabled) { background: var(--fg); color: var(--bg); }
.flick button:disabled { opacity: .28; cursor: default; }
.flick svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.3; stroke-linecap: round; stroke-linejoin: round; }

/* ---------- materials: every sheet is laid on the one before it ----------
   Each section is its own piece of stock (fibre paper, linen, speckled board) and throws a soft shadow up onto the
   sheet it overlaps, so the change of material reads as a change of layer. The linen panels are hemmed (a running
   stitch along the top and bottom edge), their big lines are embroidered (#stitch, in the page's <defs>), and light
   slides across the weave as the panel passes, the way cloth catches a lamp when it moves. */
.intro, .spread, .door, .reads, .end { position: relative; }
.intro, .spread, .door, .reads, .faq, .end { box-shadow: 0 -1px 0 rgb(20 20 19 / .1), 0 -14px 26px -16px rgb(20 20 19 / .5); }
.intro .text, #brand .colour, #property .colour { --thread: color-mix(in srgb, currentColor 55%, transparent); position: relative; overflow: clip;
  background:
    repeating-linear-gradient(90deg, var(--thread) 0 9px, #0000 0 15px) 0 18px / 100% 1.5px no-repeat,
    repeating-linear-gradient(90deg, rgb(20 20 19 / .22) 0 9px, #0000 0 15px) 1px 19.5px / 100% 1px no-repeat,
    repeating-linear-gradient(90deg, var(--thread) 0 9px, #0000 0 15px) 0 calc(100% - 18px) / 100% 1.5px no-repeat,
    repeating-linear-gradient(90deg, rgb(20 20 19 / .22) 0 9px, #0000 0 15px) 1px calc(100% - 16.5px) / 100% 1px no-repeat; }
.intro .text .say, #brand .say, #property .say { filter: url(#stitch); }
/* and none of it lies flat: slow swells and a few soft creases (tex/folds.svg, lit from the top left) lie in every
   panel, deep in the linen, faint in the paper; the cloth puffs up in the middle and sinks at the hem. Content sits
   above the folds and the light, so the photographs in the strips stay untouched. */
.colour { position: relative; overflow: clip; }
.colour > * { position: relative; z-index: 1; }
.intro .text::before, .colour::before { content: ""; position: absolute; inset: -6% -3%; pointer-events: none;
  background: url("tex/folds.svg") center / 100% 100%; mix-blend-mode: soft-light; opacity: var(--folds, .4); }
.intro .text, #brand .colour, #property .colour { --folds: 1; box-shadow: inset 0 -70px 90px -60px rgb(20 20 19 / .34), inset 0 40px 60px -50px rgb(255 255 255 / .2); }
.intro .text::after, #brand .colour::after, #property .colour::after { content: ""; position: absolute; inset: 0 -100%; pointer-events: none;
  background: linear-gradient(104deg, #0000 38%, rgb(255 255 255 / .2) 47%, rgb(255 255 255 / .32) 50%, rgb(255 255 255 / .2) 53%, #0000 62%);
  mix-blend-mode: soft-light; translate: -18% 0; }

/* ---------- wedding door ---------- */
.door { position: relative; display: grid; place-items: center; min-height: 100svh; color: var(--paper); text-align: center; overflow: hidden; background: #3a2a24; }
.door img { position: absolute; inset: 0; transition: transform 1.6s var(--ease-print); }
.door::before { content: ""; position: absolute; inset: 0; z-index: 1; background: rgb(28 20 16 / .34); }
.door .in { position: relative; z-index: 2; padding: var(--pad); display: grid; justify-items: center; gap: 18px; }
.door strong { font: italic 400 clamp(64px, 13vw, 200px)/.9 var(--text); letter-spacing: -.02em; }
.door p { max-width: 24em; font-size: clamp(19px, 1.5vw, 22px); }
.door .enter { margin-top: 10px; padding: 14px 28px; border: 1px solid; border-radius: 99px; font: 400 12px var(--display); text-transform: uppercase; letter-spacing: .18em; transition: background .3s, color .3s; }
@media (hover: hover) and (pointer: fine) { .door:hover img { transform: scale(1.04); } }
.door:hover .enter, .door:focus-visible .enter { background: var(--paper); color: var(--ink); }

/* ---------- journal: a contents page for the guides ---------- */
.reads { display: grid; grid-template-columns: 1fr 1.35fr; gap: var(--pad); align-items: start; padding: calc(var(--pad) * 2) var(--pad) var(--pad); }
.reads .kicker { margin-bottom: 20px; color: var(--red-ink); }
.reads .say { font-size: clamp(26px, 2.8vw, 42px); max-width: 11em; }
.reads .also { margin-top: 26px; font: 400 12px/1.8 var(--display); letter-spacing: .16em; text-transform: uppercase; }
.reads .also a { text-decoration: underline; text-underline-offset: 3px; }
.reads ol { list-style: none; counter-reset: r; border-bottom: 1px solid; }
.reads li { counter-increment: r; border-top: 1px solid; }
.reads li a { display: grid; grid-template-columns: 3em 1fr; gap: 12px; padding: 16px 0; font-size: clamp(19px, 1.5vw, 23px); line-height: 1.3; }
.reads li a::before { content: counter(r, decimal-leading-zero); padding-top: .3em; font: 700 13px/1 var(--stencil); letter-spacing: .18em; color: var(--red-ink); }
.reads li a:hover span { text-decoration: underline; text-underline-offset: 4px; text-decoration-thickness: 1px; }

/* ---------- questions ---------- */
.faq { position: relative; z-index: 1; overflow-x: clip; padding: calc(var(--pad) * 2) var(--pad); --ghost: rgb(55 100 228 / .35); }
.faq > * { position: relative; }
.faq .wash { position: absolute; z-index: 0; left: -8%; top: -38%; width: min(64vw, 820px); fill: var(--yellow); opacity: .5; mix-blend-mode: multiply; pointer-events: none; }
.faq .stamp { position: absolute; left: 36%; bottom: clamp(-90px, -6vw, -60px); width: clamp(120px, 12vw, 176px); color: var(--ink); rotate: -11deg; opacity: .85; } /* stamped across two sheets */
.faq .kicker { margin-bottom: clamp(28px, 4vw, 56px); }
.qs { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); gap: 40px var(--pad); }
.qs div { padding-top: 20px; border-top: 1px solid; }
.qs h3 { margin-bottom: 10px; font: 500 clamp(24px, 2.1vw, 30px)/1.15 var(--text); text-shadow: .035em .022em 0 var(--ghost); } /* the second plate, a hair off register */
.qs p { max-width: 30em; }

/* ---------- end page ---------- */
.end { position: relative; overflow-x: clip; /* the postmark lands from 1.7x; don't let it widen the page */ background: var(--laid), var(--red); background-blend-mode: multiply; color: var(--paper); --ghost: rgb(20 20 19 / .3); padding: calc(var(--pad) * 2 + 96px) var(--pad) calc(var(--pad) + 40px); display: grid; grid-template-columns: 1.1fr 1fr; gap: var(--pad); align-items: end; }
.thanks { display: block; width: min(100%, 640px); aspect-ratio: 1153 / 504; height: auto; fill: currentColor; filter: drop-shadow(4px 3px 0 var(--ghost, transparent)); }
.end::before { content: ""; position: absolute; inset: 0 0 auto; height: 44px; pointer-events: none; /* lace trim along the top of the red card */
  background: var(--lace) 0 0 / 60px 44px repeat-x; filter: drop-shadow(0 1px .5px rgb(60 10 6 / .45)); }
.end .postmark { position: absolute; top: clamp(56px, 5vw, 72px); right: var(--pad); width: clamp(180px, 21vw, 300px); color: var(--paper); opacity: .75; mix-blend-mode: normal; }
.end .say { font-size: clamp(26px, 2.8vw, 42px); max-width: 13em; margin-bottom: 20px; }
.end .note { max-width: 26em; margin-bottom: 36px; font-size: clamp(19px, 1.45vw, 21px); }
/* the WhatsApp line is a paper label pinned to the red card: it reads as the thing to press */
.reach a { display: flex; justify-content: space-between; gap: 16px; padding: 18px 22px; background: var(--paper); color: var(--red); font-size: clamp(19px, 1.5vw, 23px);
  box-shadow: 0 1px 1px rgb(60 10 6 / .25), 0 8px 18px -10px rgb(60 10 6 / .6); transition: background-color .2s var(--ease-out), color .2s var(--ease-out), scale .16s var(--ease-out); }
.reach a span { font: 700 13px var(--stencil); text-transform: uppercase; letter-spacing: .22em; align-self: center; }
.reach a:hover { background: var(--yellow); color: var(--ink); }
.reach a:active { scale: .98; }

/* asking about one service, right where it's shown, with that service already written into the message */
.chat { align-self: flex-start; display: inline-block; margin: 18px var(--pad) 0; padding: 12px 0; font-size: clamp(19px, 1.45vw, 21px);
  text-decoration: underline 1px color-mix(in srgb, currentColor 45%, transparent); text-underline-offset: 5px; transition: text-decoration-color .2s var(--ease-out), scale .16s var(--ease-out); }
.chat span { display: inline-block; margin-right: 14px; font: 700 12px var(--stencil); letter-spacing: .22em; text-transform: uppercase; } /* inline-block: the underline stays on the words */
.chat:hover { text-decoration-color: currentColor; }
.chat:active, .cover .book:active { scale: .97; }
.cover .book { justify-self: start; padding: 13px 24px; border: 1px solid; border-radius: 99px; font: 400 12px var(--display); text-transform: uppercase; letter-spacing: .18em; transition: background-color .2s var(--ease-out), scale .16s var(--ease-out); }
.cover .book:hover { background: color-mix(in srgb, currentColor 18%, transparent); }
/* the letter is closed with wax, pressed across the fold between the red page and the paper */
.foot { position: relative; z-index: 2; display: grid; justify-items: center; gap: 14px; padding: 0 var(--pad) 36px; color: var(--ink); font: 400 12px var(--display); letter-spacing: .2em; text-transform: uppercase; text-align: center; }
.foot .seal { width: clamp(136px, 12vw, 176px); height: auto; margin-top: clamp(-80px, -6.8vw, -60px); }
.foot nav { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 22px; }
.foot nav a:hover { text-decoration: underline; text-underline-offset: 4px; }

/* ---------- reveals: each line arrives once, on its own clock, as it comes into view (artie.js adds .reveal and .in).
   Not scrubbed by the scroll, so a page left half-scrolled never shows a half-printed line. ---------- */
.reveal .rise { transition: opacity .7s var(--ease-out), translate .7s var(--ease-out); }
.reveal .rise:not(.in) { opacity: 0; translate: 0 24px; }
.reveal .say.rise { transition: opacity .9s var(--ease-out), clip-path 1.1s var(--ease-print); clip-path: inset(-10% 0 -10% 0); } /* the roller passes over the line */
.reveal .say.rise:not(.in) { opacity: .3; translate: none; clip-path: inset(-10% 100% -10% 0); }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .dots button[aria-current="true"]::after { animation: none; }
  .reveal .rise:not(.in) { translate: none; clip-path: none; }   /* still arrives, as a fade only */
  .reveal .say.rise:not(.in) { opacity: 0; }
  .cover .top.stuck.armed { transition: opacity .2s; }
  .cover .top.stuck:not(.show) { translate: none; opacity: 0; visibility: hidden; }
}

/* ---------- alive: things get printed, stamped and sealed as you reach them ---------- */
.slides figure img { transform-origin: 60% 40%; }
.strip img { transition: transform .5s var(--ease-print), rotate .5s; }
@media (hover: hover) and (pointer: fine) { .strip img:hover { transform: translateY(-8px) scale(1.03); rotate: 0deg; } } /* a tap opens the viewer; no hover left stuck behind it */
.door .enter { position: relative; overflow: hidden; }
@media (prefers-reduced-motion: no-preference) {
  .slides figure.on img { animation: settle 7s cubic-bezier(.2, .6, .3, 1) both; }   /* each cover photo eases in */
  @keyframes settle { from { transform: scale(1.09); } }
  .cover.turned .slides figure.on { animation: curtain .95s cubic-bezier(.76, 0, .24, 1) both; }   /* a focal-plane shutter: the next frame is drawn down over the last (not the first, which loads plain) */
  @keyframes curtain { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0); } }
  @supports (animation-timeline: view()) {
    .stamp, .postmark { animation: thunk linear both; animation-timeline: view(); animation-range: entry 45% entry 85%; }
    @keyframes thunk { 0% { opacity: 0; transform: scale(1.7) rotate(-16deg); } 75% { opacity: .95; transform: scale(.96); } 100% { opacity: .85; transform: none; } }
    .foot .seal { animation: press-seal linear both; animation-timeline: view(); animation-range: entry 10% entry 90%; }
    @keyframes press-seal { 0% { opacity: 0; transform: translateY(-50px) scale(1.3) rotate(-8deg); } 70% { opacity: 1; transform: scale(.97); } 100% { transform: none; } }
    .photo { overflow: hidden; }
    .photo img { animation: drift linear both; animation-timeline: view(); animation-range: cover 0% cover 100%; }
    @keyframes drift { from { transform: scale(1.14) translateY(-4%); } to { transform: scale(1.03) translateY(3%); } }
    .intro figure { overflow: hidden; }
    .intro figure img { animation: drift linear both; animation-timeline: view(); animation-range: cover 0% cover 100%; }
    .strip img { animation: deal linear both; animation-timeline: view(); animation-range: entry 0% entry 100%; }
    @keyframes deal { from { opacity: 0; transform: translateY(40px) rotate(4deg); } }
    .faq .wash { animation: bloom linear both; animation-timeline: view(); animation-range: entry 0% cover 45%; }
    @keyframes bloom { from { opacity: 0; transform: scale(.6); } to { opacity: .5; transform: none; } }
    .no { animation: stencil linear both; animation-timeline: view(); animation-range: entry 20% entry 60%; }
    @keyframes stencil { from { opacity: 0; clip-path: inset(0 100% 0 0); } to { clip-path: inset(0); } }   /* sprayed through the stencil, left to right */
    .intro .text::after, #brand .colour::after, #property .colour::after { animation: sheen linear both; animation-timeline: view(); animation-range: cover 0% cover 100%; }
    @keyframes sheen { from { translate: -34% 0; } to { translate: 30% 0; } }
    .intro .text::before, .colour::before { animation: billow linear both; animation-timeline: view(); animation-range: cover 0% cover 100%; }
    @keyframes billow { from { translate: 0 -3%; scale: 1.06 1.1; } to { translate: 0 3%; scale: 1; } }   /* the folds shift and ease as the panel passes, like cloth settling */
  }
}

/* ---------- small screens: pages stack ---------- */
@media (max-width: 820px) {
  .top nav { gap: 14px; font-size: 12px; letter-spacing: .12em; }
  .top nav a:first-child { display: none; }
  .cover .top.stuck { padding-block: 10px; }
  .cover .top.stuck .mark { width: 26px; }
  .top.stuck .frame:not(:empty) { margin-left: 14px; font-size: 11px; letter-spacing: .16em; }
  .year { font-size: 64px; top: calc(var(--pad) + 76px); }
  .tag { font-size: clamp(26px, 8.4vw, 46px); filter: url(#hand); }
  .year { filter: url(#hand-l); }
  .say { filter: url(#hand-s); }
  .intro, .spread, .end, .reads { grid-template-columns: 1fr; }
  .intro figure { min-height: 0; aspect-ratio: 4 / 5; }
  .spread.flip .photo { order: 0; }
  .photo { min-height: 0; aspect-ratio: 4 / 5; }
  .colour { padding-top: calc(var(--pad) * 2); padding-bottom: calc(var(--pad) * 1.5); }
  .strip img { height: 260px; }
  .faq { padding-bottom: 96px; }
  .faq .stamp { width: 104px; left: auto; right: 10%; bottom: -46px; }
  .end .postmark { position: static; width: 220px; margin-bottom: 8px; }
  .end { min-height: 0; }
}
@media (max-width: 400px) {
  .top.stuck .frame:not(:empty) { display: none; } /* a phone's strip has room for the links or the Nº, not both */
}
