/* skin.css — ysabelmarco (Ysabel & Marco). Site 3: minimal / editorial white, typography-led.
   The four loud axes (lab/docs/SITES.md): a Contents page for navigation · five pages with the
   weight in Story · a small photograph in wide white, names beneath it like a wall label · a strict
   12-column modular grid.
   Tokens and every visual rule for this site. Engine internals are never touched here.

   §1 type · §2 tokens · §3 base · §4 grid · §5 masthead + Contents · §6 dock · §7 cover ·
   §8 page heads · §9 story · §10 gallery + lightbox · §11 the day · §12 notes · §13 reply ·
   §14 page turn + footer · §15 motion · §16 print · §17 ornaments · §18 reading line */

/* §1 · type. Cormorant Garamond, self-hosted from demo/assets/type (verified feature-complete,
   assets/type/README.md). Body and labels are the system sans, so the serif only ever speaks large. */
@font-face { font-family: "Cormorant Garamond"; font-weight: 400; font-style: normal; font-display: swap;
  src: url("../assets/type/cormorant-garamond-400.woff2") format("woff2"); }
@font-face { font-family: "Cormorant Garamond"; font-weight: 400; font-style: italic; font-display: swap;
  src: url("../assets/type/cormorant-garamond-400i.woff2") format("woff2"); }
/* Lining figures for the counters (round 2). ⚠ The Cormorant subset here keeps onum and pnum but
   not lnum, so font-variant-numeric: lining-nums does nothing in it (measured round 2). EB Garamond
   draws lining figures by default, so it lends its digits, and only its digits. */
@font-face { font-family: "YM Figures"; font-weight: 400; font-style: normal; font-display: swap;
  src: url("../assets/type/eb-garamond-400.woff2") format("woff2"); unicode-range: U+0030-0039; }

/* §2 · tokens */
[data-skin="ysabelmarco"] {
  --paper: #fbfaf7;
  --white: #ffffff;
  --black: #161514;
  --stone: #5f5b55;
  --hair: #d8d4cc;
  --red: #a8261b;          /* printer's red: the one accent, used for numbers and the ampersand */

  --bg: var(--paper);
  --bg-raised: var(--white);
  --ink: var(--black);
  --muted: var(--stone);
  --rule: var(--hair);
  --accent: var(--red);
  --accent-soft: #f3e6e3;
  --on-accent: var(--paper);
  --field: var(--white);

  --display: "Cormorant Garamond", "Cormorant", Garamond, "Times New Roman", serif;
  --body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --ui: var(--body);

  --step--1: .8125rem;
  --step-0: 1rem;
  --step-1: 1.25rem;
  --step-2: clamp(1.6rem, 1.2rem + 1.4vw, 2.2rem);
  --step-3: clamp(2.2rem, 1.4rem + 3vw, 3.6rem);
  --step-4: clamp(3rem, 1.6rem + 6vw, 6.5rem);
  --step-5: clamp(4rem, 1rem + 12vw, 12rem);

  /* Softened 2026-10-01 (the user: "smoother edges", light touch): controls and photographs are
     gently rounded, the rules and the grid stay square. */
  --radius: 10px;          /* buttons, the reply choices, the dock, the Contents button */
  --radius-img: 6px;       /* every photograph */
  --rule-w: 1px;
  --gap: 1rem;
  --gutter: clamp(1rem, 2.5vw, 2rem);    /* the grid's column gap */
  --margin: clamp(1rem, 5vw, 5rem);      /* the page's side margin */
  --module: clamp(3rem, 8vw, 7rem);      /* the vertical module: sections stack in whole modules */
  --motion-fast: 240ms;
  --motion-slow: 900ms;
  --ease: cubic-bezier(.22, .61, .36, 1);
  --ease-soft: cubic-bezier(.16, .84, .24, 1);   /* long, unhurried settles */
  --focus-w: 1px;
  --focus-off: 4px;

  /* the reveal register (atelier §L2, driven by reveal.js): softer and slower than site 2's */
  --a-reveal-dur: 1100ms;
  --a-reveal-ease: var(--ease-soft);
  --a-rise-y: 22px;
  --a-step: 110ms;
  --a-mask-from: 1.04;
}

/* §3 · base */
[data-skin="ysabelmarco"] body {
  background: var(--bg);
  color: var(--ink);
  font: var(--step-0)/1.6 var(--body);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;   /* the sideways page turn (§15) and the margin ornaments never make a scrollbar */
}
/* And on the root, as site 1 learned (its skin.css, 2026-08-22): with `html` at `overflow-x:
   visible` the turn's 1.5rem from-state still widens the root's scrollWidth for the first frames,
   and a phone sizes its layout viewport from that, then zooms the whole page out to fit (found
   2026-10-01 in the iPhone stand-in run: 402 → 421 wide on The day). `clip`, never `hidden`, so
   the root does not become a scroll container. */
html[data-skin="ysabelmarco"] { overflow-x: clip; }
[data-skin="ysabelmarco"] a {
  color: inherit; text-decoration-thickness: 1px; text-underline-offset: .2em;
  transition: color var(--motion-fast) var(--ease), text-underline-offset var(--motion-fast) var(--ease), text-decoration-color var(--motion-fast) var(--ease);
}
[data-skin="ysabelmarco"] a:hover { color: var(--accent); text-underline-offset: .32em; }
[data-skin="ysabelmarco"] img { background: var(--rule); }
[data-skin="ysabelmarco"] main img { border-radius: var(--radius-img); }
.serif { font-family: var(--display); font-weight: 400; }
.label {
  font: 600 var(--step--1)/1.4 var(--ui);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}
.amp { font-family: var(--display); font-style: italic; color: var(--accent); }
.lede { font: var(--step-1)/1.55 var(--body); max-width: 34em; }
.prose p + p { margin-top: 1em; }
.prose { max-width: 34em; }

/* §4 · the grid. Twelve columns from 64em, eight from 48em, four below. Every block is placed on
   it by column; nothing is centred by margin. The empty modules are the design. */
.page { padding-inline: var(--margin); }
.grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: calc(var(--module) / 2);
}
.grid > * { grid-column: 1 / -1; min-width: 0; }
@media (min-width: 48em) { .grid { grid-template-columns: repeat(8, minmax(0, 1fr)); } }
@media (min-width: 64em) { .grid { grid-template-columns: repeat(12, minmax(0, 1fr)); } }
.section { padding-block: var(--module); }
.section + .section { border-top: var(--rule-w) solid var(--rule); }

/* §5 · the masthead and the Contents page. The name scrolls away; only the word "Contents" stays,
   and it opens a full-screen table of contents set like the front of a book.
   ⚠ The nav is AFTER the toggle in the DOM, so Tab goes from the button straight into the list. */
.mast {
  position: absolute;
  inset: 0 0 auto 0;
  z-index: 70;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.25rem var(--margin);
}
.mast-name { font: 600 var(--step--1)/1 var(--ui); letter-spacing: .14em; text-transform: uppercase; text-decoration: none; min-height: 44px; display: inline-flex; align-items: center; }
.mast-name .amp { font-size: 1.4em; letter-spacing: 0; margin-inline: .2em; text-transform: none; }
/* The design-study tab and Contents share one fixed group at the top right (round 2, D3): at the
   bottom left the tab sat over the Reply page's text at rest. On a phone the three pieces do not
   fit one row (measured 439px against 324 at 360), so below 32em the name becomes its initials
   and the tab's label takes two lines. The link's aria-label still reads the full names. */
.mast-ctl {
  position: fixed;
  top: 1.25rem;
  right: var(--margin);
  z-index: 85;
  display: flex;
  align-items: center;
  gap: .5rem;
}
@media (max-width: 31.99em) {
  .mast-name .mn-rest { display: none; }
  .mast-name .amp { margin-inline: .08em; }
  .mast-name { min-width: 44px; }   /* the initials alone are a 40px target */
  .dock-tab [data-i18n] { width: min-content; line-height: 1.15; }
}
.contents-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: 0 1rem 0 2.35rem;
  border: var(--rule-w) solid var(--ink);
  border-radius: var(--radius);
  background: var(--bg);
  font: 600 var(--step--1)/1 var(--ui);
  letter-spacing: .14em;
  text-transform: uppercase;
  transition: background var(--motion-fast) var(--ease), color var(--motion-fast) var(--ease), translate var(--motion-fast) var(--ease);
}
.contents-btn:hover { background: var(--ink); color: var(--bg); }
.contents-btn:active { translate: 0 1px; }
/* Two short rules that fold into a cross when the Contents page is open */
.contents-btn::before, .contents-btn::after {
  content: "";
  position: absolute;
  left: 1rem; top: calc(50% - 4px);
  width: .85rem; height: 1px;
  background: currentColor;
  transition: top 320ms var(--ease-soft), rotate 320ms var(--ease-soft);
}
.contents-btn::after { top: calc(50% + 3px); }
.contents-btn[aria-expanded="true"]::before { top: 50%; rotate: 45deg; }
.contents-btn[aria-expanded="true"]::after { top: 50%; rotate: -45deg; }
.contents-btn .say-close { display: none; }
.contents-btn[aria-expanded="true"] .say-open { display: none; }
.contents-btn[aria-expanded="true"] .say-close { display: inline; }

/* The Contents page opens like a sheet drawn down over the page (a wipe from the top), then its
   five entries arrive one after another. Closing is quicker than opening. */
.contents {
  position: fixed;
  inset: 0;
  z-index: 80;
  overflow-y: auto;
  background: var(--bg);
  padding: calc(var(--module) + 2rem) var(--margin) var(--module);
  visibility: hidden;
  clip-path: inset(0 0 100% 0);
  transition: clip-path 420ms var(--ease), visibility 0s linear 420ms;
}
.contents[data-open] {
  visibility: visible;
  clip-path: inset(0 0 0 0);
  transition: clip-path 720ms var(--ease-soft);
}
html:has(.contents[data-open]) { overflow: hidden; }
.contents-head, .contents li { opacity: 0; translate: 0 1rem; transition: opacity 300ms var(--ease), translate 300ms var(--ease); }
.contents[data-open] :is(.contents-head, li) {
  opacity: 1; translate: 0 0;
  transition: opacity 700ms var(--ease-soft), translate 700ms var(--ease-soft);
  transition-delay: calc(180ms + var(--c-i, 0) * 70ms);
}
.contents li:nth-child(1) { --c-i: 1; } .contents li:nth-child(2) { --c-i: 2; }
.contents li:nth-child(3) { --c-i: 3; } .contents li:nth-child(4) { --c-i: 4; }
.contents li:nth-child(5) { --c-i: 5; }
.contents-head { grid-column: 1 / -1; border-bottom: var(--rule-w) solid var(--ink); padding-bottom: 1rem; display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.contents-title { font: 400 var(--step-3)/1 var(--display); }
.contents ol { grid-column: 1 / -1; }
.contents li { position: relative; border-bottom: var(--rule-w) solid var(--rule); }
/* hover: a rule in ink draws itself along the entry, and the name steps in and turns italic */
.contents li::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -1px;
  height: 1px; background: var(--ink);
  transform: scaleX(0); transform-origin: left center;
  transition: transform 500ms var(--ease-soft);
}
.contents li:is(:hover, :focus-within)::after { transform: scaleX(1); }
.c-name { display: inline-block; transition: translate 420ms var(--ease-soft); }
.contents li a:is(:hover, :focus-visible, :active) .c-name { translate: .6rem 0; }
/* a warm wash slides in behind the entry; on a phone it shows while the finger is down, and
   motion.js's 260ms departure keeps it on screen long enough to be seen */
.contents li a { position: relative; padding-inline: .75rem; margin-inline: -.75rem; border-radius: var(--radius); -webkit-tap-highlight-color: transparent; transition: scale 160ms var(--ease); }
.contents li a::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit;
  background: var(--accent-soft); opacity: 0;
  transform: scaleX(0); transform-origin: left center;
  transition: transform 560ms var(--ease-soft), opacity 360ms var(--ease);
}
.contents li a:is(:hover, :focus-visible, :active)::before { transform: scaleX(1); opacity: .6; }
.contents li a:active { scale: .992; }
[data-skin="ysabelmarco"] .contents li a:hover { color: var(--ink); }   /* red stays on numbers and the current mark */
.contents li a:is(:hover, :focus-visible, :active) .c-page { color: var(--accent); }
.contents li a {
  display: grid;
  grid-template-columns: 2.5rem 1fr auto;
  align-items: baseline;
  gap: 1rem;
  padding-block: clamp(.75rem, 2vw, 1.25rem);
  text-decoration: none;
}
.c-no { font: italic 400 var(--step-2)/1 var(--display); color: var(--accent); }
.c-name { font: 400 var(--step-4)/1 var(--display); letter-spacing: -.01em; }
.c-sub { display: block; margin-top: .5rem; font: var(--step--1)/1.4 var(--ui); letter-spacing: .04em; color: var(--muted); }
.c-page { font: 600 var(--step--1)/1 var(--ui); letter-spacing: .14em; color: var(--muted); font-variant-numeric: tabular-nums; }
.contents li a:is(:hover, :focus-visible, :active) .c-name { font-style: italic; }
.contents li a[aria-current="page"] .c-page { color: var(--accent); }
.contents li a[aria-current="page"] .c-page::before { content: "You are here \2014\00a0"; letter-spacing: .08em; }
@media (min-width: 64em) {
  .contents ol { grid-column: 3 / 12; }
  .contents li a { grid-template-columns: 4rem 1fr auto; }
}

/* §6 · the design-study dock, in the masthead's top-right group (§5) since round 2. The marker is
   the tab and is always readable; its panel drops below the group, right-aligned to the margin. */
.demo-dock { display: flex; }
.dock-tab, .demo-btn {
  display: inline-flex; align-items: center; gap: .5rem;
  min-height: 44px; padding: 0 .9rem;
  border: var(--rule-w) solid var(--ink);
  border-radius: var(--radius);
  background: var(--bg);
  font: 600 var(--step--1)/1 var(--ui); letter-spacing: .1em; text-transform: uppercase;
  transition: background var(--motion-fast) var(--ease), color var(--motion-fast) var(--ease);
}
.dock-tab:hover, .demo-btn:hover { background: var(--ink); color: var(--bg); }
.dock-mark { width: .5rem; height: .5rem; border-radius: 50%; background: var(--accent); }
.dock-panel { position: absolute; top: calc(100% + .5rem); right: 0; width: min(22rem, calc(100vw - 2 * var(--margin))); padding: 1.25rem; background: var(--bg-raised); border: var(--rule-w) solid var(--ink); border-radius: calc(var(--radius) * 1.4); display: grid; gap: .9rem; }
@media (prefers-reduced-motion: no-preference) {
  .dock-panel:not([hidden]) { animation: ym-in 420ms var(--ease-soft) both; }
}
.dock-panel p { font-size: var(--step--1); line-height: 1.5; }
.dock-ctl { display: flex; flex-wrap: wrap; gap: .5rem; }

/* §7 · the cover. One small photograph in a wide white field, the names under it like the label
   beside a picture on a gallery wall. Almost nothing else. */
.cover { min-height: 100svh; padding-block: 5.5rem 4.5rem; align-content: center; row-gap: 0; }
/* ⚠ The photograph and the names share the first screen at every size: the height cap is what
   keeps the label above the fold on a short laptop, not the column span. */
.cover-photo img { width: auto; max-height: 50svh; }
.cover-photo { grid-column: 1 / 4; }   /* three of four on a phone: still a picture on a wall */
.cover-label { grid-column: 1 / -1; display: grid; gap: .35rem; padding-top: 1.25rem; border-top: var(--rule-w) solid var(--ink); }
.cover-names { font: 400 var(--step-4)/.95 var(--display); letter-spacing: -.015em; margin-bottom: .5rem; }
.cover-names .amp { display: inline-block; margin-inline: .08em; }
.cover-line { font-size: var(--step-0); }
.cover-medium { font-style: italic; color: var(--muted); }
.cover-count { margin-top: .75rem; }
/* The reply, on the first screen (the user, 2026-10-01). A real link to page V, set as a button,
   under the date lines at every width: with the names on one line (round 2) it clears the fold. */
.cover-cta { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1.25rem; margin-top: 1.25rem; }
.cover-cta .hint { margin: 0; }
/* The countdown rolls up into place once, on arrival: atelier.js builds the digit columns and
   sets each one's transform; this adds a `translate` from one whole column below, so every
   column spins up through its digits. The roll is skin-only and composes with the engine's. */
@media (prefers-reduced-motion: no-preference) {
  .cover-count .a-odo-col { animation: ym-roll 1.6s var(--ease-soft) .9s both; }
  .cover-count .a-odo-win:nth-child(2) .a-odo-col { animation-delay: 1.02s; }
  .cover-count .a-odo-win:nth-child(3) .a-odo-col { animation-delay: 1.14s; }
  .cover-count .a-odo-win:nth-child(4) .a-odo-col { animation-delay: 1.26s; }
}
@keyframes ym-roll { from { translate: 0 100%; } to { translate: 0 0; } }
.cover-count [data-when="after"] { display: none; }
[data-phase="after"] .cover-count [data-when="before"] { display: none; }
[data-phase="after"] .cover-count [data-when="after"] { display: inline; }
.cover-next { margin-top: 1rem; }
@media (min-width: 48em) {
  .cover-photo { grid-column: 3 / 7; }
  .cover-label { grid-column: 3 / 9; }
}
/* the label runs to the right edge on a laptop so the names hold one line (round 2, S2) */
@media (min-width: 64em) {
  .cover-photo { grid-column: 5 / 9; }
  .cover-label { grid-column: 5 / 13; }
}
/* a short laptop (768 tall): a lower cap keeps the Reply button on the first screen.
   Measured round 2: at 50svh it sat at 807px on 1366 × 768. */
@media (min-width: 48em) and (max-height: 50em) {
  .cover-photo img { max-height: 42svh; }
}
/* A phone: the photograph takes what the label leaves, so the Reply button is on the first screen
   of a short one too (2026-10-01, Claude's call at the user's request: at 50svh it sat 90px below
   on an iPhone SE, 102px on a 360 × 536 Android). Tall phones keep 50svh; 9rem is the floor. */
@media (max-width: 47.99em) {
  .cover-photo img { max-height: clamp(9rem, 100svh - 24rem, 50svh); }
}

.invite { align-items: end; }
.invite-no { font: italic 400 var(--step-3)/1 var(--display); color: var(--accent); }
.invite-say { font: 400 var(--step-3)/1.15 var(--display); }
@media (min-width: 64em) {
  .invite-no { grid-column: 1 / 3; }
  .invite-say { grid-column: 3 / 11; }
  .invite-meta { grid-column: 3 / 7; }
}
@media (min-width: 48em) and (max-width: 63.99em) {
  .invite-no { grid-column: 1 / 2; }
  .invite-say, .invite-meta { grid-column: 2 / -1; }
}

/* §8 · page heads. Every interior page opens on its title set enormous across the grid. */
.head { padding-top: calc(var(--module) * 1.5); padding-bottom: var(--module); }
.head-no { font: italic 400 var(--step-3)/1 var(--display); color: var(--accent); }
.head-title { font: 400 var(--step-5)/.9 var(--display); letter-spacing: -.02em; }
.head-lede { font: var(--step-1)/1.55 var(--body); }
@media (min-width: 64em) {
  .head-no { grid-column: 1 / 2; }
  .head-title { grid-column: 2 / -1; }
  .head-lede { grid-column: 8 / 12; }
}
@media (min-width: 48em) and (max-width: 63.99em) {
  .head-no { grid-column: 1 / 2; }
  .head-title { grid-column: 2 / -1; }
  .head-lede { grid-column: 4 / -1; }
}

/* §9 · the story. Four chapters, alternating sides of the grid; each photograph holds its own
   column span and the text sits in the modules beside it. */
.chapters { display: grid; gap: calc(var(--module) * 1.25); }
.chapter { align-items: start; }
.ch-no { font: italic 400 var(--step-4)/.8 var(--display); color: var(--accent); }
.ch-title { font: 400 var(--step-3)/1 var(--display); margin-bottom: .25rem; }
.ch-date { margin-bottom: 1.5rem; }
.ch-text .prose { font-size: var(--step-0); }
/* Each chapter opens on a red drop cap, two lines deep (round 2): the one accent use on a letter.
   initial-letter sizes and sinks it where the browser has it; the float is the fallback. */
.ch-text .prose > p:first-child::first-letter {
  float: left;
  margin: .02em .1em 0 0;
  font: 400 3.55em/.8 var(--display);
  color: var(--accent);
}
@supports (initial-letter: 2) or (-webkit-initial-letter: 2) {
  .ch-text .prose > p:first-child::first-letter {
    float: none;
    margin: 0 .12em 0 0;
    font-size: inherit; line-height: inherit;
    -webkit-initial-letter: 2;
    initial-letter: 2;
  }
}
.ch-shots figure { margin: 0; }
@media (min-width: 48em) {
  .ch-text { grid-column: 1 / 4; grid-row: 1; }
  .ch-shots { grid-column: 4 / -1; grid-row: 1; }
  .chapter:nth-child(even) .ch-text { grid-column: 6 / -1; }
  .chapter:nth-child(even) .ch-shots { grid-column: 1 / 6; }
}
@media (min-width: 64em) {
  .ch-text { grid-column: 1 / 5; }
  .ch-shots { grid-column: 6 / 13; }
  .chapter:nth-child(even) .ch-text { grid-column: 9 / 13; }
  .chapter:nth-child(even) .ch-shots { grid-column: 2 / 8; }
}
/* story.js stamps data-reveal only when motion is allowed; data-in when the chapter is in view */
.chapter[data-reveal] { opacity: 0; transform: translateY(1.5rem); transition: opacity var(--motion-slow) var(--ease), transform var(--motion-slow) var(--ease); }
.chapter[data-reveal][data-in] { opacity: 1; transform: none; }

/* §10 · the gallery: the story page's closing wall. Pictures hang on the grid at their own ratio;
   the empty modules between them are left empty on purpose. */
.wall { align-items: start; row-gap: var(--module); }
/* hover: the print lifts off the wall a little and a thin ink mat opens out around it, plate
   label and all (round 2: the mat replaced a drop shadow, which is not this site's idiom).
   `translate` on the FIGURE, so it never fights the reveal's transform on the image. The mat is
   the figure's own outline: .a-mask clips the figure's CONTENT (overflow: clip), never its
   outline, so a pseudo-element mat would be cut off where an outline is not. */
.wall figure {
  margin: 0;
  outline: 1px solid transparent;
  outline-offset: 2px;
  transition: translate 600ms var(--ease-soft), outline-offset 600ms var(--ease-soft), outline-color 420ms var(--ease);
}
.wall img { width: 100%; cursor: zoom-in; }
.wall figure:is(:hover, :focus-within) { translate: 0 -4px; outline-color: var(--ink); outline-offset: 10px; }
/* a revealed photograph keeps its rounding while it is still over-scaled */
.a-mask { border-radius: var(--radius-img); }
/* the plates: "Pl. 1"–"Pl. 8", set like the Contents' page numbers, a short line after each */
.wall figcaption { margin-top: .6rem; font-size: var(--step--1); color: var(--muted); }
.pl { margin-right: .5em; font-weight: 600; letter-spacing: .14em; color: var(--accent); }
.wall-head { align-self: end; }
@media (min-width: 48em) {
  .w1 { grid-column: 1 / 6; } .w2 { grid-column: 6 / 9; margin-top: 30%; }
  .w3 { grid-column: 2 / 5; } .w4 { grid-column: 5 / 9; }
  .w5 { grid-column: 1 / 7; } .w6 { grid-column: 5 / 9; }
  .w7 { grid-column: 1 / 4; } .w8 { grid-column: 3 / 9; }
}
@media (min-width: 64em) {
  .wall-head { grid-column: 1 / 4; grid-row: 1; }
  .w1 { grid-column: 4 / 10; grid-row: 1; margin-top: 0; }
  .w2 { grid-column: 10 / 13; grid-row: 1; margin-top: 40%; }
  .w3 { grid-column: 1 / 4; } .w4 { grid-column: 5 / 9; margin-top: 25%; }
  .w5 { grid-column: 9 / 13; margin-top: 10%; } .w6 { grid-column: 2 / 6; }
  .w7 { grid-column: 7 / 10; margin-top: 30%; } .w8 { grid-column: 4 / 13; }
}

[data-wsd="lightbox"] { background: rgba(251, 250, 247, .97); }
[data-wsd="lightbox"] [data-wsd-el="image"] { border-radius: var(--radius-img); }
@media (prefers-reduced-motion: no-preference) {
  [data-wsd="lightbox"]:not([hidden]) { animation: ym-fade 360ms var(--ease) both; }
  [data-wsd="lightbox"]:not([hidden]) [data-wsd-el="image"] { animation: ym-lift 620ms var(--ease-soft) both; }
}
[data-wsd="lightbox"] figure { margin: 0; display: grid; gap: .75rem; justify-items: center; }
[data-wsd="lightbox"] [data-wsd-el="caption"] { font-size: var(--step--1); color: var(--muted); max-width: 40em; text-align: center; }
.lb-bar { display: flex; gap: .5rem; align-items: center; }
.lb-bar [data-wsd-el="position"] { min-width: 4rem; text-align: center; font: 600 var(--step--1)/1 var(--ui); letter-spacing: .14em; }

/* §11 · the day. The schedule is a typeset table on the grid: time, event, note. */
.venues { align-items: start; }
.venue figure { margin: 0 0 1rem; }
.venue h2 { font: 400 var(--step-2)/1.1 var(--display); }
.venue p { margin-top: .5rem; }
@media (min-width: 48em) {
  .venue--hall { grid-column: 1 / 5; } .venue--roof { grid-column: 6 / 9; margin-top: 20%; }
}
@media (min-width: 64em) {
  .venue--hall { grid-column: 1 / 7; } .venue--roof { grid-column: 8 / 12; margin-top: 12%; }
}
.day-head { align-self: start; }
.sched { grid-column: 1 / -1; }
.sched-item { display: grid; grid-template-columns: 5.5rem 1fr; gap: .25rem 1rem; padding-block: 1.25rem; border-top: var(--rule-w) solid var(--rule); }
.sched-item:last-child { border-bottom: var(--rule-w) solid var(--rule); }
/* the times keep Cormorant's old-style figures on purpose (2026-10-01): the font has no lnum, and in
   a row of times they read well. Only the lone counters borrow lining digits (§1). */
.sched-time { font: 400 var(--step-2)/1 var(--display); grid-row: span 3; }
.sched-title { font: 400 var(--step-2)/1.1 var(--display); }
.sched-where { color: var(--muted); }
@media (min-width: 64em) {
  .day-head { grid-column: 1 / 4; }
  .sched { grid-column: 4 / 13; }
  .sched-item { grid-template-columns: 8rem 1fr 1fr; }
  .sched-time { grid-row: auto; }
  .sched-note { grid-column: 3; grid-row: 1 / span 2; }
}
.dress { align-items: start; }
.dress-say { font: 400 var(--step-3)/1.1 var(--display); }
@media (min-width: 64em) {
  .dress-head { grid-column: 1 / 4; }
  .dress-say { grid-column: 4 / 11; }
  .dress-note { grid-column: 4 / 8; }
}

/* §12 · notes. Questions and answers as a two-column typeset list. */
.notes dl { display: grid; gap: 0; }
.note { display: grid; gap: .5rem; padding-block: 1.5rem; border-top: var(--rule-w) solid var(--rule); }
.note dt { font: 400 var(--step-2)/1.15 var(--display); }
.note dd { max-width: 34em; }
@media (min-width: 64em) {
  .notes-head { grid-column: 1 / 4; }
  .notes dl { grid-column: 4 / 13; }
  .note { grid-template-columns: 5fr 4fr; gap: 2rem; }
}
.notes-card figure { margin: 0; }
@media (min-width: 48em) { .notes-card { grid-column: 3 / 7; } }
@media (min-width: 64em) { .notes-card { grid-column: 7 / 11; } }

/* §13 · the reply. rsvp-simple.js hydrates the form; everything visible here is the skin's. */
.reply { align-items: start; }
@media (min-width: 64em) {
  .reply-head { grid-column: 1 / 4; }
  .reply-body { grid-column: 5 / 12; }
}
@media (min-width: 48em) and (max-width: 63.99em) {
  .reply-body { grid-column: 2 / -1; }
}
.field { display: grid; gap: .4rem; margin-bottom: 1.5rem; }
.field label, .reply-q, .plus .label { font: 600 var(--step--1)/1.4 var(--ui); letter-spacing: .14em; text-transform: uppercase; color: var(--ink); }
.field input, .field textarea {
  width: 100%;
  min-height: 48px;
  padding: .7rem 0;
  border: 0;
  border-bottom: var(--rule-w) solid var(--ink);
  background: transparent;
  font: var(--step-1)/1.4 var(--body);
}
.field textarea { resize: vertical; }
.field input:focus-visible, .field textarea:focus-visible { outline: none; border-bottom-width: 2px; border-bottom-color: var(--accent); }
.hint { font-size: var(--step--1); color: var(--muted); }
.reply-ask { margin-bottom: 2rem; }
.choices { display: grid; gap: .75rem; margin-top: .75rem; }
@media (min-width: 40em) { .choices { grid-template-columns: 1fr 1fr; } }
.choice { position: relative; display: block; }
.choice input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.choice span {
  display: flex; align-items: center; min-height: 64px; padding: 1rem 1.25rem;
  border: var(--rule-w) solid var(--ink);
  border-radius: var(--radius);
  font: 400 var(--step-2)/1.1 var(--display);
  transition: background var(--motion-fast) var(--ease), color var(--motion-fast) var(--ease), border-color var(--motion-fast) var(--ease);
}
.choice:hover input:not(:checked) + span { background: var(--accent-soft); border-color: var(--accent); }
.choice input:checked + span { background: var(--ink); color: var(--bg); }
.choice input:focus-visible + span { outline: var(--focus-w) solid var(--accent); outline-offset: var(--focus-off); }
.plus { margin-bottom: 2rem; }
.stepper { display: flex; align-items: center; gap: 1rem; margin-top: .75rem; }
.step-btn { width: 48px; height: 48px; border: var(--rule-w) solid var(--ink); border-radius: 50%; background: transparent; font-size: 1.25rem; transition: background var(--motion-fast) var(--ease), color var(--motion-fast) var(--ease), scale 120ms var(--ease); }
.step-btn:hover { background: var(--ink); color: var(--bg); }
.step-btn:active { scale: .94; }
.step-out { font: 400 var(--step-3)/1 var(--display); min-width: 2ch; text-align: center; }
.step-label { color: var(--muted); }
.plus-names { margin-top: 1.25rem; }
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 52px; padding: 0 1.75rem;
  border: var(--rule-w) solid var(--ink);
  border-radius: var(--radius);
  background: var(--ink); color: var(--bg);
  font: 600 var(--step--1)/1 var(--ui); letter-spacing: .14em; text-transform: uppercase;
  text-decoration: none;
  transition: background var(--motion-fast) var(--ease), border-color var(--motion-fast) var(--ease), color var(--motion-fast) var(--ease), translate var(--motion-fast) var(--ease);
}
[data-skin="ysabelmarco"] a.btn { color: var(--bg); }   /* over the base rule's `a { color: inherit }` */
[data-skin="ysabelmarco"] .btn:hover { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn:active { translate: 0 1px; }
/* an arrow that moves on with the pointer, on links set as buttons */
.btn-go::after { content: "\2192"; margin-left: .75rem; letter-spacing: 0; transition: translate var(--motion-fast) var(--ease); }
.btn-go:hover::after { translate: .25rem 0; }
.btn--quiet { background: transparent; color: var(--ink); }
[data-skin="ysabelmarco"] .btn--quiet:hover { background: var(--ink); border-color: var(--ink); color: var(--bg); }
.error { padding: 1rem 0; color: var(--accent); font-weight: 600; }
.confirm { display: grid; gap: 1rem; padding-block: 1rem 2rem; }
.confirm h2 { font: 400 var(--step-3)/1.05 var(--display); }
/* The place card (round 2): the guest's name set on a printed card, the kind the Notes page says
   is printed downstairs. A white card on the paper, a hairline edge, no shadow. It settles onto
   the page, then the name comes up as if pressed. */
.place-card { display: grid; gap: .6rem; margin-block: .5rem 1rem; }
.card-face {
  position: relative;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: .9rem;
  justify-self: start;
  width: 100%;
  max-width: 21rem;   /* ⚠ not min(21rem, 100%): that percentage is cyclic here and pushed the Reply column past a 360 screen */
  aspect-ratio: 7 / 4;
  padding: 1.5rem 1.25rem 1.75rem;
  background: var(--white);
  border: var(--rule-w) solid var(--hair);
  border-radius: 3px;
  text-align: center;
}
/* the fold of a tent card, a hairline a little way below the top edge */
.card-face::before {
  content: "";
  position: absolute; left: 0; right: 0; top: 14%;
  border-top: var(--rule-w) dashed var(--hair);
}
/* the site's sprig, small, under the name */
.card-face::after {
  content: "";
  width: 64px; height: 18px;
  background: url("../assets/ysabelmarco/orn-sprig.svg") center / contain no-repeat;
  opacity: .75;
}
.card-top { font: 600 .6875rem/1.4 var(--ui); letter-spacing: .16em; text-transform: uppercase; color: var(--muted); }
.card-top .amp { font-size: 1.35em; letter-spacing: 0; text-transform: none; }
.card-name { font: italic 400 var(--step-3)/1.05 var(--display); color: var(--ink); overflow-wrap: anywhere; }
@media (prefers-reduced-motion: no-preference) {
  .place-card:not([hidden]) .card-face { animation: ym-card 1.1s var(--ease-soft) .15s both; }
  .place-card:not([hidden]) .card-name { animation: ym-press 900ms var(--ease-soft) .75s both; }
}
@keyframes ym-card { from { opacity: 0; transform: translateY(1.25rem) rotate(-1.5deg); } to { opacity: 1; transform: none; } }
@keyframes ym-press { from { opacity: 0; transform: scale(1.06); } to { opacity: 1; transform: none; } }
.summary-row { display: flex; justify-content: space-between; gap: 1rem; padding-block: .6rem; border-top: var(--rule-w) solid var(--rule); }
.summary-row .answer { color: var(--muted); }
.stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.5rem var(--gutter); margin-top: var(--module); padding-top: 1.5rem; border-top: var(--rule-w) solid var(--ink); }
@media (min-width: 48em) { .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.stat b { display: block; font: 400 var(--step-3)/1 var(--display); font-weight: 400; }
.stat span { font: 600 var(--step--1)/1.4 var(--ui); letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
/* Cormorant's figures are old-style, and an old-style zero reads as a letter "o" ("o replies in").
   The counters borrow EB Garamond's lining digits (§1, "YM Figures"; round 2, S1).
   ⚠ It stays after the `font` shorthands above, which reset the family. */
.step-out, .stat b { font-family: "YM Figures", var(--display); }

/* §14 · the page turn and the footer. Every page ends by naming the next one, like a book. */
/* Previous and next since 2026-10-01: the way back is small and on the left, the way on is large
   and keeps its old place. The arrow travels a little on hover. */
.turn { padding-block: var(--module); border-top: var(--rule-w) solid var(--ink); align-items: end; }
.turn a { display: grid; gap: .5rem; text-decoration: none; }
.turn-say { font: 400 var(--step-4)/1 var(--display); transition: translate 520ms var(--ease-soft); }
.turn-next .label::after { content: "\2192"; display: inline-block; margin-left: .6rem; letter-spacing: 0; transition: translate 520ms var(--ease-soft); }
.turn-prev .label::before { content: "\2190"; display: inline-block; margin-right: .6rem; letter-spacing: 0; transition: translate 520ms var(--ease-soft); }
.turn-prev .turn-say { font-size: var(--step-2); color: var(--muted); }
[data-skin="ysabelmarco"] .turn a:hover .turn-say { font-style: italic; color: var(--ink); }
.turn-next:hover .turn-say, .turn-next:hover .label::after { translate: .5rem 0; }
.turn-prev:hover .turn-say, .turn-prev:hover .label::before { translate: -.5rem 0; }
.turn-prev { order: 1; }   /* on a phone the way on comes first, the way back under it */
@media (min-width: 48em) {
  .turn-prev { order: 0; grid-column: 1 / 3; grid-row: 1; }
  .turn-next { grid-column: 3 / -1; grid-row: 1; }
}
@media (min-width: 64em) {
  .turn-prev { grid-column: 1 / 5; }
  .turn-next { grid-column: 5 / 13; }
}

.foot { padding-block: var(--module) calc(var(--module) + 4rem); border-top: var(--rule-w) solid var(--rule); font-size: var(--step--1); color: var(--muted); }
.foot-names { font: 400 var(--step-2)/1 var(--display); color: var(--ink); }
.foot-mark { max-width: 40em; }
.wsd-mark { display: flex; align-items: center; gap: .5rem; grid-column: 1 / 3; font: 600 var(--step--1)/1 var(--ui); letter-spacing: .14em; text-transform: uppercase; }
.wsd-mark i { width: .5rem; height: .5rem; background: var(--ink); transform: rotate(45deg); }
/* The colophon, and the folio: this page's number from the Contents (p. 1, 3, 21, 27, 31), so the
   Contents' numbers mean something (round 2, S5). The folio sits at the outer edge, like a book's. */
.colophon { font: italic 400 var(--step-0)/1.4 var(--display); }   /* set in the face it names */
.folio { grid-column: 3 / -1; justify-self: end; align-self: center; font: 600 var(--step--1)/1 var(--ui); letter-spacing: .14em; color: var(--accent); }
@media (min-width: 48em) {
  .wsd-mark { grid-column: 1 / 5; }
  .folio { grid-column: 5 / -1; }
}
@media (min-width: 64em) {
  .foot-id { grid-column: 1 / 5; }
  .foot-mark { grid-column: 5 / 11; }
  .wsd-mark { grid-column: 1 / 5; grid-row: 2; }
  .colophon { grid-column: 5 / 11; grid-row: 2; }
  .folio { grid-column: 11 / 13; grid-row: 2; }
}

.wsd-skip { display: inline-flex; align-items: center; min-height: 44px; font: 600 var(--step--1)/1 var(--ui); letter-spacing: .1em; text-transform: uppercase; border: var(--rule-w) solid var(--ink); }

/* §15 · motion. Everything is slow, soft and short in travel; engine.css flattens all of it under
   reduced motion, and every finished state is also the default state.
   · the first screen arrives in order (the cover; each interior page's head)
   · scroll reveals: atelier §L2's classes, driven by reveal.js, tuned by the tokens in §2
   · page to page: motion.js holds the click for its 260ms departure; the arrival and the
     departure are a page turn, sideways, in the direction of travel through the Contents order */
@media (prefers-reduced-motion: no-preference) {
  .cover-photo, .cover-label { animation: ym-in 1.3s var(--ease-soft) both; }
  .cover-label { animation-delay: .3s; }
  .head-no, .head-title, .head-lede { animation: ym-in 1.2s var(--ease-soft) both; }
  .head-title { animation-delay: .12s; }
  .head-lede { animation-delay: .32s; }

  [data-skin="ysabelmarco"][data-atelier~="motion"] #main { animation: ym-turn-in 640ms var(--ease-soft) both; }
  [data-skin="ysabelmarco"][data-atelier~="motion"][data-arriving="back"] #main { animation-name: ym-turn-in-back; }
  html[data-skin="ysabelmarco"][data-leaving] #main { animation: ym-turn-out 260ms var(--ease) both; }
  html[data-skin="ysabelmarco"][data-leaving="back"] #main { animation-name: ym-turn-out-back; }
}
@keyframes ym-in { from { opacity: 0; transform: translateY(.75rem); } to { opacity: 1; transform: none; } }
@keyframes ym-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes ym-lift { from { opacity: 0; transform: translateY(.75rem) scale(.985); } to { opacity: 1; transform: none; } }
@keyframes ym-turn-in { from { opacity: 0; transform: translateX(1.5rem); } to { opacity: 1; transform: none; } }
@keyframes ym-turn-in-back { from { opacity: 0; transform: translateX(-1.5rem); } to { opacity: 1; transform: none; } }
@keyframes ym-turn-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateX(-1rem); } }
@keyframes ym-turn-out-back { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateX(1rem); } }

/* §16 · print: the page as a document, no chrome */
@media print {
  .mast-ctl, .contents, .wsd-skip, [data-wsd="lightbox"], .reading { display: none !important; }
  .chapter[data-reveal] { opacity: 1; transform: none; }
}

/* §17 · ornaments (2026-10-01, the user: "minimal leaf or branch outlines on the sides and
   corners", light touch). Three single-line drawings in stone ink, made by
   lab/tools/ornaments-ysabelmarco.js. Every one is a pseudo-element: no markup, no hit target,
   never announced. ⚠ The gate's "veiled" check cannot see pseudo-elements, so their clearance
   from text is checked by eye at every width. Background images, not masks: a mask is a CORS
   fetch, and these demos open from a file path.
     · the cover: a branch laid over the photograph's top-right corner, a sprig on the label's rule
     · each interior page: a sprig after the page numeral, and a vine in the right margin at 64em+
     · the Contents page and the footer: a branch in the bottom-right corner
   They draw themselves in on the first screen (a wipe along the stem). */
.cover-photo, .cover-label, .head, .foot { position: relative; }
.cover-photo { justify-self: start; }   /* the figure hugs the photograph, so its corner is the picture's corner */
.foot { isolation: isolate; }
.cover-photo::after, .cover-label::before, .head-no::after, .head::after, .contents::after, .foot::after {
  content: "";
  pointer-events: none;
  background: center / contain no-repeat;
}
.cover-photo::after {
  position: absolute;
  top: -1.9rem; right: -2.1rem;
  width: clamp(88px, 11vw, 150px); aspect-ratio: 1;
  background-image: url("../assets/ysabelmarco/orn-corner.svg");
  opacity: .8;
}
.cover-label::before {
  position: absolute;
  top: -15px; right: 0;
  width: clamp(76px, 8vw, 104px); height: 30px;
  background-color: var(--bg);
  background-image: url("../assets/ysabelmarco/orn-sprig.svg");
  background-origin: content-box;
  padding-left: 10px;
  opacity: .9;
}
.head-no::after {
  display: inline-block;
  width: 1.9em; height: .6em;
  margin-left: .35em;
  vertical-align: .1em;
  background-image: url("../assets/ysabelmarco/orn-sprig.svg");
  opacity: .75;
}
/* where the numeral has a column of its own, the sprig hangs under it instead of beside it */
@media (min-width: 48em) {
  .head-no::after { display: block; width: min(1.7em, 100%); margin: .3em 0 0; }
}
@media (min-width: 64em) {
  .head::after {
    position: absolute;
    top: calc(var(--module) * 1.5);
    right: calc(-1 * var(--margin) + var(--margin) * .18);
    width: calc(var(--margin) * .6); height: min(26rem, 80%);
    background-image: url("../assets/ysabelmarco/orn-vine.svg");
    opacity: .6;
  }
}
.contents::after {
  position: fixed;
  right: 0; bottom: 0;
  width: clamp(110px, 12vw, 180px); aspect-ratio: 1;   /* in the columns the list leaves empty */
  background-image: url("../assets/ysabelmarco/orn-corner.svg");
  transform: scaleY(-1);
  opacity: .4;
  z-index: -1;   /* under the entries: .contents is its own stacking context */
}
/* On a phone the list is taller than the screen, so the page numbers scroll under a corner pinned
   to the window (measured 2026-10-01, 360–430 wide: "p. 21", "p. 27", "p. 31" and the Reply line).
   There the sprig is a tailpiece instead, after the last entry, at the right margin. */
@media (max-width: 47.99em) {
  .contents::after { position: static; display: block; margin: 1.5rem 0 0 auto; }
}
.foot::after {
  position: absolute;
  right: 0; bottom: 0;
  width: clamp(110px, 12vw, 170px); aspect-ratio: 1;   /* 170 at most: it stays under the folio (round 2) */
  background-image: url("../assets/ysabelmarco/orn-corner.svg");
  transform: scaleY(-1);
  opacity: .4;
  z-index: -1;
}
@media (prefers-reduced-motion: no-preference) {
  .cover-photo::after { animation: ym-draw-rtl 1.8s var(--ease-soft) .7s both; }
  .cover-label::before { animation: ym-draw 1.4s var(--ease-soft) 1s both; }
  .head-no::after { animation: ym-draw 1.2s var(--ease-soft) .5s both; }
  .head::after { animation: ym-draw-up 2.2s var(--ease-soft) .4s both; }
  .contents[data-open]::after { animation: ym-draw-up 1.6s var(--ease-soft) .35s both; }
}
@keyframes ym-draw { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes ym-draw-rtl { from { clip-path: inset(0 0 0 100%); } to { clip-path: inset(0 0 0 0); } }
@keyframes ym-draw-up { from { clip-path: inset(100% 0 0 0); } to { clip-path: inset(0 0 0 0); } }

/* §18 · the reading line. A hairline of printer's red across the top of the window, as long as the
   share of the page already read. rail.js in progress-only mode writes --rail-progress; nothing
   here listens to scroll. Hidden while the Contents page is open. */
.reading {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 86;
  height: 2px;
  pointer-events: none;
}
.reading i {
  display: block;
  height: 100%;
  background: var(--accent);
  transform: scaleX(var(--rail-progress, 0));
  transform-origin: left center;
  transition: opacity var(--motion-fast) var(--ease);
}
html:has(.contents[data-open]) .reading i { opacity: 0; }
