/* ═══════════════════════════════════════════════════════════════════════════
   Grey Café

   The page is one wall: a single coat of lime plaster in low afternoon sun,
   pargetted by hand. A frame runs round the whole page, trims divide it,
   small emblems are modelled into it, and the hero is a relief panel.

   None of that is drawn here. Every ornament is a light map baked offline by
   tools/parge — a real height field lit by one sun from the upper left, with
   cast shadows and occlusion — and laid on with mix-blend-mode: hard-light.
   128 grey changes nothing, so the plaster under each ornament is the same
   plaster as everywhere else, and the relief and its shadow are added to the
   wall instead of being pasted over it. That is the whole trick behind the
   page reading as one slab.

   Two rules keep it working:
   (a) A RELIEF LAYER IS ALWAYS z-index: -1 AND NEVER INSIDE A STACKING
       CONTEXT. It has to blend with the wall (the root background) and paint
       under the text. So nothing that contains one may take a transform,
       opacity, filter, isolation or z-index of its own.
   (b) THE WALL'S LIGHT IS THE ROOT BACKGROUND. Nothing between it and the
       relief layers may paint a background, or the relief blends with that
       instead and vanishes.

   Text is painted on the wall in ink and never moves.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  color-scheme: light only;              /* Chrome auto-dark must not invert a plaster wall */

  /* ── the plaster ──
     --wall is the flat coat in full sun, and the colour every light map was
     solved against (GROUND in tools/parge/engine.js — change both or
     neither). Everything else is that coat in more or less light. */
  --wall:        #E7D9C3;
  --wall-lit:    #F6EBD7;
  --wall-shade:  #D8C8AF;
  /* The wall as it actually renders at the top of the page — the top of the
     gradient with the sun's warm bloom over it and the grain averaged in
     (computed from the layers below, not picked by eye). The root's own
     background colour, which no layer covers only in the overscroll above
     the page and which newer Safari samples for its bar, and the
     theme-color meta in index.html are both this, so the browser's chrome
     runs straight on into the plaster. Change one, change both. */
  --wall-top:    #EDDBBF;

  /* ── the light ──  warm sun, cool sky. Triplets so layers pick a strength. */
  --sun:   255, 214, 156;
  --shade: 96, 108, 132;

  /* ── ink ─────────  measured contrast on --wall ───────────── */
  --ink:    #2A251E;   /* 11.0:1 */
  --ink-2:  #554C42;   /*  6.3:1 */
  --ink-3:  #5C5143;   /*  5.6:1  ← palest text on the site */
  --ember:  #7A4C0C;   /*  5.4:1  — the sun at its lowest. Carries meaning only. */
  /* The wall darkens a little toward the foot of the page (late light);
     measured there (#E3D2B8) the palest text still holds 5.1:1. */

  /* ── incised lines ──
     A line cut into a sunlit wall is two lines: the cut wall facing away from
     the sun, in shadow, and the far lip catching light just below it. */
  --groove:     rgba(92, 72, 44, .26);
  --groove-lit: rgba(255, 249, 236, .85);
  --hair:       var(--groove);
  --chrome-rule: rgba(92, 72, 44, .30);

  /* ── the frame round the page ──
     --frame is how far the moulding reaches in from the screen edge (content
     starts inside it); --frame-img the slice of its light map, in CSS px. */
  --frame:      20px;
  --frame-img:  34px;

  /* ── structure ───────────────────────────────────────────── */
  --shell:      1280px;
  --gutter:     clamp(16px, 3vw, 32px);
  --sec-lead:   clamp(40px, 5vw, 72px);
  --sec-trail:  clamp(56px, 7vw, 104px);
  --air-lg:     clamp(36px, 4.4vw, 64px);
  --air-md:     clamp(20px, 2.4vw, 32px);
  --air-sm:     16px;
  --rail:       clamp(104px, 12vw, 144px);
  --masthead:   56px;
  --trim-h:     40px;

  --r-tag: 2px;  --r-focus: 2px;

  /* ── type ────────────────────────────────────────────────────
     EB Garamond carries the page: an old-style face cut from the types of the
     same century as the pargetting it sits beside, with the long, calm
     italic of a printer's book. Karla is the plain-spoken voice underneath;
     IBM Plex Mono is the maker's pencil, for labels and numbers.
     Garamond sits small on its body, so the serif's x-height is matched to
     the size the layout was set for (font-size-adjust, below) rather than
     every size being nudged up by hand. */
  --serif: "EB Garamond", ui-serif, Georgia, "Times New Roman", serif;
  --sans:  "Karla", ui-sans-serif, "Helvetica Neue", Arial, sans-serif;
  --mono:  "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --serif-adjust: .47;
  --t-hero:  clamp(4rem, 10.5vw, 9rem);
  --t-h2:    clamp(1.75rem, 3vw, 2.375rem);
  --t-line:  clamp(1.375rem, 2.4vw, 1.875rem);
  --t-item:  clamp(1.0625rem, 1.2vw, 1.1875rem);
  --t-lead:  clamp(1.0625rem, 1.2vw, 1.25rem);
  --t-body:  1.0625rem;
  --t-desc:  .9375rem;
  --t-num:   .9375rem;
  --t-micro: .6875rem;

  /* ── motion ──────────────────────────────────────────────── */
  --ease: cubic-bezier(.22,.61,.36,1);
  --rev:  640ms;
  --ui:   180ms;
}

@media (min-width: 1000px){
  :root{ --frame: 62px; --frame-img: 84px; --trim-h: 52px; }
}

/* ─────────────────────────── base ─────────────────────────── */

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

/* The sunlight. The root background is the wall, and it carries the light:
   the coat in full sun, a warm bloom where the light pours in from the upper
   left, and the whole wall warming by a shade toward the foot of the page as
   the afternoon goes on. It scrolls with the page, because the light is ON
   the wall — and because nothing fixed means nothing re-blends on scroll. */
html{
  background-color: var(--wall-top);
  background-image:
    radial-gradient(110vw 80vh at 6% 0%,
      rgba(var(--sun), .34) 0%, rgba(var(--sun), .14) 42%, rgba(var(--sun), 0) 78%),
    radial-gradient(90vw 70vh at 100% 100%,
      rgba(var(--shade), .07) 0%, rgba(var(--shade), 0) 70%),
    linear-gradient(180deg, #EADCC6 0%, var(--wall) 30%, var(--wall) 70%, #E3D2B8 100%);
  background-repeat: no-repeat;
  scroll-behavior: smooth;
  scroll-padding-top: 24px;
  -webkit-text-size-adjust: 100%;
}

body{
  margin: 0;
  color: var(--ink);
  font: 400 var(--t-body)/1.55 var(--sans);
  letter-spacing: -.002em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img{ max-width: 100%; display: block; }
/* a class-level `display` beats the UA stylesheet's [hidden], which would leave
   the status chip on screen as an empty capsule when app.js never runs */
[hidden]{ display: none !important; }
h1, h2, h3, p, dl, dd, figure, blockquote{ margin: 0; }
ol, ul{ margin: 0; padding: 0; list-style: none; }
address{ font-style: normal; }
a{ color: inherit; }

:focus-visible{
  outline: 2px solid var(--ink);
  outline-offset: 3px;
  border-radius: var(--r-focus);
  box-shadow: 0 0 0 5px rgba(255,250,240,.85);
}

.shell{ max-width: var(--shell); margin-inline: auto; padding-inline: var(--gutter); }
.mono{ font-family: var(--mono); font-variant-numeric: tabular-nums; }

.micro{
  font: 500 var(--t-micro)/1 var(--mono);
  letter-spacing: .10em;
  color: var(--ink-3);
  text-transform: lowercase;
  font-variant-numeric: tabular-nums;
}
.micro--dim{ font-weight: 400; }

.vh{
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}

/* The skip link, hidden the way .vh hides things rather than nudged off the
   top edge: on iOS an overscroll or URL-bar collapse used to slide a
   translated chip back into the corner. A clipped, zero-opacity box has
   nothing to slide into view, and stays in the focus order. */
.skip{
  position: fixed; top: calc(12px + env(safe-area-inset-top, 0px)); left: 12px;
  z-index: 60;
  padding: 10px 16px; border-radius: var(--r-tag);
  font: 500 var(--t-micro)/1 var(--mono); letter-spacing: .10em;
  color: var(--ink); text-decoration: none;
  background: var(--wall-lit);
  border: 1px solid var(--chrome-rule);
  clip-path: inset(50%);
  opacity: 0;
  pointer-events: none;
}
.skip:focus{ clip-path: none; opacity: 1; pointer-events: auto; }

.h2{
  font: 400 var(--t-h2)/1.08 var(--serif);
  font-size-adjust: var(--serif-adjust);
  font-optical-sizing: auto;
  letter-spacing: -.014em;
  color: var(--ink);
  text-wrap: balance;
}
.h2 .line{ display: block; }
@media (max-width: 599px){ .h2 .line{ display: inline; } }

/* ══════════════════ the wall ══════════════════ */

.wall{
  position: relative;            /* containing block for the frame — NOT a stacking context (rule a) */
  min-height: 100vh;
  padding: var(--frame);
  padding-top: calc(var(--frame) + env(safe-area-inset-top, 0px));
}

/* every baked ornament */
.relief{
  position: relative; z-index: -1;
  mix-blend-mode: hard-light;
  pointer-events: none;
  user-select: none; -webkit-user-select: none;
}

/* the grain of the coat: sand and pits on a 256 tile, laid hard-light over the
   lie of the float on a 640 tile — two light maps that only line up again
   every 1280px, combined into one and then laid on the wall */
.wall::before{
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    url("assets/parge/ground.webp?v=2") 0 0 / 256px 256px repeat,
    url("assets/parge/coat.webp?v=1") 0 0 / 640px 640px repeat;
  background-blend-mode: hard-light, normal;
  mix-blend-mode: hard-light;
}

/* ── the trim sets ──
   The frame and the dividers come in interchangeable sets that share one
   slicing contract (phone frame c34/p24, desktop frame c84/p144, divider
   c44/p132 at 52 tall), so a set is only three images. html[data-trim]
   picks one; the inline script at the top of <body> sets it from ?trim=.
     ornate  the vine, the cable and the leaf scroll
     quiet   a single fillet
     soft    soft geometry, rounded corners
   (a fourth, line-and-pellet, was tried and dropped; its sources are still
   in tools/parge/pieces) */
:root{
  --trim-frame-sm: url("assets/parge/frame-page-sm.webp?v=5");
  --trim-frame-lg: url("assets/parge/frame-page-lg.webp?v=5");
  --trim-band:     url("assets/parge/band.webp?v=6");
}
html[data-trim="quiet"]{
  --trim-frame-sm: url("assets/parge/frame-quiet-sm.webp?v=1");
  --trim-frame-lg: url("assets/parge/frame-quiet-lg.webp?v=1");
  --trim-band:     url("assets/parge/band-quiet.webp?v=2");
}
html[data-trim="soft"]{
  --trim-frame-sm: url("assets/parge/frame-soft-sm.webp?v=1");
  --trim-frame-lg: url("assets/parge/frame-soft-lg.webp?v=1");
  --trim-band:     url("assets/parge/band-soft.webp?v=2");
}

/* the frame round the whole page. Nine-slice, so the moulding runs the whole
   height of the page however long it grows. */
.wall::after{
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  border: var(--frame-img) solid transparent;
  border-image: var(--trim-frame-sm) 68 / var(--frame-img) round;
  mix-blend-mode: hard-light;
}
@media (min-width: 1000px){
  .wall::after{ border-image: var(--trim-frame-lg) 168 / var(--frame-img) round; }
}

/* A trim: the running leaf scroll that divides the wall into its sections.
   It spans the wall from one side of the frame to the other and butts into
   it: two scrolled ends, and a run that repeats between them.

   Every slice of the band must scale by the SAME factor or the scroll
   stretches. The run's width is scaled by the top slice's factor and its
   height by the ends', so the top and bottom slices are a quarter of the
   band (26 of 104 image px) and drawn at a quarter of its height — a real
   width at every size. It used to be a 2-px slice drawn at trim-h/52, which
   on a phone is 0.77px; Chrome rounds a border that thin up to 1px, the run
   took a 0.5 factor while the ends took 0.385, and the scroll came out a
   third too wide. */
.trim{
  position: relative; z-index: -1; pointer-events: none;
  height: var(--trim-h);
  margin-inline: 4px;
  border-style: solid; border-color: transparent;
  border-width: calc(var(--trim-h) / 4) calc(var(--trim-h) * 44 / 52);
  border-image: var(--trim-band) 26 88 fill / calc(var(--trim-h) / 4) calc(var(--trim-h) * 44 / 52) round stretch;
  mix-blend-mode: hard-light;
}

/* ══════════════════ the wordmark ══════════════════ */

.mark{
  display: inline-flex; align-items: baseline; white-space: nowrap;
  font: 400 1em/1 var(--serif); font-size-adjust: var(--serif-adjust);
  font-optical-sizing: auto; letter-spacing: -.012em; color: var(--ink);
}
.mark__gate{
  align-self: center; display: inline-block;
  width: 1px; height: .62em; margin-inline: .30em;
  background: var(--ember);
}

/* ══════════════════ masthead ══════════════════
   In the flow at the top of the wall, inside the frame. Nothing on the page
   is fixed or sticky, so nothing overlays anything.
   position: relative is for the absolutely centred clock. */

.masthead{
  position: relative;
  height: calc(var(--masthead) + var(--frame-img) - var(--frame));
  padding: calc(var(--frame-img) - var(--frame)) var(--gutter) 0;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  max-width: var(--shell); margin-inline: auto;
}

/* The café's clock: centred on the bar, tabular so the digits don't jitter. */
.masthead__clock{
  position: absolute; left: 50%; top: calc(50% + (var(--frame-img) - var(--frame)) / 2);
  transform: translate(-50%, -50%);
  font: 500 var(--t-micro)/1 var(--mono); letter-spacing: .10em;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap; pointer-events: none;
}
/* inside the frame a 375 phone has ~300px of bar; the clock only fits with the
   wordmark and nav from 400 up */
@media (max-width: 399px){ .masthead__clock{ display: none; } }

.masthead__mark{ font-size: 19px; text-decoration: none; padding: 6px 2px; }
.masthead__nav{ display: flex; align-items: center; gap: 22px; }
.masthead__nav a{
  font: 500 var(--t-micro)/1 var(--mono); letter-spacing: .10em;
  color: var(--ink); text-decoration: none;
  padding: 16px 2px; min-height: 44px; display: inline-flex; align-items: center;
}
.masthead__nav a:hover{ text-decoration: underline; text-underline-offset: .4em;
                        text-decoration-thickness: 1px; }

/* ══════════════════ hero ══════════════════
   No panel and no frame: the hares are modelled straight onto the wall and
   the scene comes first, with the wordmark painted on the wall beneath it
   like the lettering under a relief. On a phone the scene runs from one side
   of the page frame to the other; on a wide screen it is a broad scene
   across the whole section, and the wordmark runs along under it on one
   line with its two small lines set to the right.

   The source order stays wordmark-then-picture, so the h1 is still the first
   thing a screen reader or a no-CSS reader meets; only the painting order
   flips. */

.hero{
  position: relative;
  padding-block: clamp(8px, 2vw, 24px) clamp(20px, 3vw, 40px);
}

.hero__stage{ width: 100%; display: flex; flex-direction: column; }
.hero__copy{ position: relative; margin-top: clamp(4px, 1.6vw, 20px); }

/* the light map is neutral everywhere the plaster isn't modelled, so the
   picture has no edge — only the figures rise out of the coat */
.hero__art{ order: -1; margin: 0; }
.hero__art picture{ display: block; margin-inline: auto; }
.hero__relief{ width: 100%; height: auto; }

@media (max-width: 899px){
  .hero__art{ margin: 0 calc(-1 * var(--gutter)); }
  .hero__art picture{ max-width: 520px; }
}

/* The page's name is painted once, in the masthead; the relief is the hero.
   The h1 stays — it is still the page's title for a screen reader and for
   search — but it is hidden the way .vh hides things, so nothing paints a
   second, larger wordmark under the hares. */
.hero__title{
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}

/* What is left reads like the inscription under a relief: centred beneath
   the scene, the line and then the café's open/closed state. */
.hero__copy{ text-align: center; }
.hero__sub{
  font: 300 var(--t-lead)/1.4 var(--sans); color: var(--ink-2);
  letter-spacing: .01em;
}
.hero__foot{
  margin-top: 12px; display: flex; align-items: center; justify-content: center;
  gap: 20px; flex-wrap: wrap;
}

/* the status chip — a mark and two words, no capsule */
.chip{
  display: inline-flex; align-items: center; gap: 9px;
  padding-left: 10px; border-left: 2px solid var(--ember);
  font: 500 var(--t-micro)/1 var(--mono); letter-spacing: .10em;
  color: var(--ink-2); white-space: nowrap;
}
.chip__dot{
  width: 7px; height: 7px; border-radius: 50%; flex: none;
  border: 1.5px solid var(--ember); background: transparent;   /* closed: hollow */
}
.chip.is-open .chip__dot{ background: var(--ember); }          /* open: filled */
.chip__state{ color: var(--ink); }
.chip__detail{ color: var(--ink-2); font-weight: 400; }

.rail{ margin-bottom: var(--air-md); }

/* ══════════════════ menu ══════════════════
   Twelve rows of type painted on the wall, each group headed by a small
   modelled emblem — a sun, a clouded sun, a moon. */

.menu{ position: relative; padding-top: var(--sec-lead); padding-bottom: var(--sec-trail); }
.menu__shell{ position: relative; }
.groups{ margin-top: var(--air-lg); display: flex; flex-direction: column; gap: var(--air-lg); }

.group{ position: relative; }
.group__head{
  min-height: 56px;
  display: flex; align-items: center; gap: 10px;
  padding-bottom: 6px;
}
.group__head .micro:last-child{ margin-left: auto; }
.emblem{ width: 56px; height: 56px; flex: none; margin: -6px 0 -8px -6px; }

.rows{ position: relative; }
.row{
  position: relative;
  display: grid; grid-template-columns: 3.25rem 1fr auto;
  column-gap: 12px; align-items: baseline;
  padding: 13px 0 15px;
}
.row__no{
  grid-column: 1; grid-row: 1;
  font: 400 var(--t-micro)/1 var(--mono); letter-spacing: .08em;
  color: var(--ink-3); padding-top: .55em;
}
.row__name{
  grid-column: 2; grid-row: 1;
  font: 400 var(--t-item)/1.25 var(--serif); font-size-adjust: var(--serif-adjust);
  font-optical-sizing: auto; letter-spacing: -.004em; color: var(--ink);
}
.row__desc{
  grid-column: 2; grid-row: 2; margin-top: 3px; max-width: 58ch;
  font: 400 var(--t-desc)/1.5 var(--sans); color: var(--ink-2);
}
.row__price{
  grid-column: 3; grid-row: 1; text-align: right;
  font: 500 var(--t-num)/1 var(--mono); color: var(--ink);
}
.row__sig{ color: var(--ember); white-space: nowrap; }

/* every rule is cut: the shadowed cut, then the lit lip below it */
.rows::before,
.row + .row::before{
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: linear-gradient(180deg, var(--groove) 0 1px, var(--groove-lit) 1px 2px);
}

.row--signature .row__name{ font-weight: 600; }
.row--signature .row__no{ color: var(--ember); }

.note{
  margin-top: var(--air-lg); max-width: 56ch;
  font: 400 .8125rem/1.7 var(--mono); letter-spacing: 0; color: var(--ink-2);
}

@media (min-width: 980px){
  .menu__shell > *{ margin-left: calc(var(--rail) + var(--air-md)); }
  .group{ max-width: 680px; }
  .group__head{
    position: absolute; top: -6px;
    left: calc(-1 * (var(--rail) + var(--air-md)));
    width: var(--rail); min-height: 0;
    display: block; padding: 0;
  }
  .emblem{ width: 72px; height: 72px; margin: 0 0 10px -10px; }
  .group__head .micro{ display: block; }
  .group__when{ margin-top: 6px; }
}

@media (max-width: 599px){
  .row{ grid-template-columns: auto 1fr auto; column-gap: 10px; padding: 12px 0 14px; }
  .row__no{ padding-top: .35em; }
  .row__desc{ grid-column: 1 / -1; font-size: .90625rem; max-width: none; }
}

/* ══════════════════ visit ══════════════════ */

.visit{ position: relative; padding-top: var(--sec-lead); padding-bottom: var(--sec-trail); }
.visit__shell{ position: relative; }
.visit__head{ display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--air-md); }
.visit__head .h2{ max-width: 30ch; }

.plates{
  margin-top: var(--air-lg);
  display: grid; grid-template-columns: 1fr; gap: var(--air-md);
  align-items: stretch;
  max-width: min(860px, 100%);
}

/* A plate: the information painted straight onto the wall. These had their
   own moulded frames for a while; inside the page frame, between two trims,
   a third ring of moulding was one too many. */
.plate{ position: relative; }
.plate .micro{ display: block; margin-bottom: 14px; }

.hours{ display: grid; }
.hrow{
  position: relative;
  display: grid; grid-template-columns: 1fr auto; align-items: baseline;
  gap: 12px; min-height: 44px; padding-block: 9px;
}
.hrow + .hrow::after,
.frow + .frow::after{
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: linear-gradient(180deg, var(--groove) 0 1px, var(--groove-lit) 1px 2px);
}
.hrow dt{ font-size: var(--t-body); color: var(--ink-2); }
.hrow dd{
  margin: 0; font-size: var(--t-num); color: var(--ink);
  display: inline-flex; align-items: baseline; gap: .7ch;
}
/* 5ch is exactly "10 pm" in a mono face, so right-aligning both ends keeps
   the column ruled to the pixel */
.hrow .t{ min-width: 5ch; text-align: right; }
.hrow .t-to{ color: var(--ink-2); }
.hrow[aria-current]{ font-weight: 500; }
.hrow[aria-current] dt, .hrow[aria-current] dd{ color: var(--ink); }
.hrow[aria-current]::before{
  content: ""; position: absolute; left: -12px; top: 50%; margin-top: -5px;
  width: 2px; height: 10px; background: var(--ember);
}

/* Same row geometry as .hrow and the same number of rows, so the two plates
   rule across the gap. Each dt is .vh, so the value rules to the right edge. */
.find{ display: grid; }
.frow{
  position: relative;
  display: grid; align-items: baseline;
  min-height: 44px; padding-block: 9px;
}
.frow dd{ margin: 0; font-size: var(--t-body); color: var(--ink); text-align: right; }
.find a{
  display: inline-flex; align-items: center; min-height: 44px; margin-block: -9px;
  color: var(--ember); text-decoration: underline;
  text-decoration-thickness: 1px; text-underline-offset: .28em;
  transition: text-decoration-thickness var(--ui) linear, color var(--ui) linear;
}
.find a:hover{ text-decoration-thickness: 2px; }

@media (min-width: 680px){
  .plates{ grid-template-columns: 1fr 1fr; gap: var(--air-lg); }
}
@media (min-width: 980px){
  .visit__head, .plates{ margin-left: calc(var(--rail) + var(--air-md)); }
  .plates{ max-width: min(860px, calc(100% - var(--rail) - var(--air-md))); }
  .rail--visit{
    position: absolute; left: var(--gutter); top: 0;
    width: var(--rail); margin: 0;
  }
}

/* ══════════════════ closing ══════════════════
   The one symmetric moment on the page: two lines and, between them, the
   vase of flowers modelled into the wall. */

.closing{ position: relative; padding-block: var(--sec-trail); text-align: center; }
.closing__line{
  font-family: var(--serif); font-size-adjust: var(--serif-adjust);
  font-optical-sizing: auto;
  font-size: var(--t-line); line-height: 1.3; letter-spacing: -.008em;
  text-wrap: balance;
}
.closing__line--1{ font-weight: 300; color: var(--ink-2); font-style: italic; }
.closing__line--2{ font-weight: 400; color: var(--ink); }
.closing__vase{
  width: clamp(120px, 16vw, 176px); height: auto;
  margin: clamp(18px, 3vw, 32px) auto clamp(12px, 2vw, 22px);
}

/* ══════════════════ footer ══════════════════ */

.trim--foot{ margin-top: 0; }
.foot{
  padding-block: 24px;
  padding-bottom: calc(var(--frame-img) - var(--frame) + 28px + env(safe-area-inset-bottom, 0px));
}
.foot__inner{
  display: flex; flex-direction: column; align-items: center; gap: 16px; text-align: center;
}
.foot__mark{ font-size: 19px; }
.foot__nav{ display: flex; gap: 22px; }
.foot__nav a{
  font: 500 var(--t-micro)/1 var(--mono); letter-spacing: .10em;
  color: var(--ink-2); text-decoration: none;
  min-height: 44px; display: inline-flex; align-items: center; padding-inline: 2px;
  transition: color var(--ui) linear;
}
.foot__nav a:hover{ color: var(--ink); }

.social{ display: flex; gap: 8px; }
.social a{
  width: 44px; height: 44px; display: grid; place-items: center;
  color: var(--ink-3); transition: color var(--ui) linear;
}
.social a:hover{ color: var(--ink); }
.social svg{
  width: 20px; height: 20px; fill: none;
  stroke: currentColor; stroke-width: 1.4;
  stroke-linecap: round; stroke-linejoin: round;
}
.social .glyph-dot{ fill: currentColor; stroke: none; }

/* ══════════════════ the hero copy load-in ══════════════════
   The only motion on the page: the painted wordmark settling once, above the
   fold. It contains no relief layer, so its momentary stacking context while
   it fades isolates nothing (rule a). The panel does not fade: walls don't. */

.js .reveal{
  opacity: 0; transform: translate3d(0, 12px, 0);
  transition: opacity var(--rev) var(--ease), transform var(--rev) var(--ease);
}
.js .reveal.in{ opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal{ opacity: 1 !important; transform: none !important; }
  a, .social a{
    transition: color 120ms linear, text-decoration-color 120ms linear,
                text-decoration-thickness 120ms linear !important;
  }
}

@media (prefers-contrast: more){
  /* firm the ink and the cut lines; take the grain of the coat out from under
     the text, and keep the ornaments — they never sit under a word */
  :root{ --ink-2: #3F382F; --ink-3: #3F382F; --groove: rgba(40, 30, 18, .5); }
  .wall::before{ display: none; }

}

/* ══════════════════ 360px floor ══════════════════ */

@media (max-width: 400px){
  .masthead__nav{ gap: 16px; }
}

