/* A Touch of Love — base + rooms */

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

html {
  -webkit-text-size-adjust: 100%;
  /* Clipping on <body> alone does not contain the foliage: the overflow
     propagates up to <html>, which was still visible and produced a 9px
     sideways scroll. Both elements need it. */
  overflow-x: clip;
}

body {
  margin: 0;
  /* Foliage deliberately hangs past the outer edge of the content column.
     Clipping horizontally lets it bleed off the side of the screen instead
     of widening the page and producing a sideways scrollbar. `clip` rather
     than `hidden` so it cannot turn a descendant into a scroll container. */
  overflow-x: clip;
  font-family: var(--body);
  font-size: var(--t-body);
  line-height: 1.65;
  color: var(--ink);
  background: var(--cream);
  /* The room change is a temperature shift, not a cut. */
  transition: background-color 600ms ease;
}

body[data-room="events"] { background: var(--cream-deep); }

img { max-width: 100%; display: block; }

a { color: var(--room-accent-deep); text-underline-offset: 0.18em; }
a:hover { color: var(--ink); }

:focus-visible {
  outline: 2px solid var(--room-accent-deep);
  outline-offset: 3px;
}

/* ── The spine ────────────────────────────────────────────────────────────
   One rule down the left edge of the page, carrying the current room's
   colour. It is the temperature gauge: green while you are in Sympathy,
   red once you cross into Events. Information, not decoration — it is the
   only thing on the page that tells you which room you are standing in.  */

.spine {
  position: fixed;
  /* Sits against the left edge of the text column, not the browser window,
     so it reads as the margin rule of a page rather than a stray line. */
  left: max(0.5rem, calc(50% - 39rem - 1.75rem));
  top: 0;
  width: var(--spine-w);
  height: 100vh;
  background: var(--room-accent);
  transition: background-color 600ms ease;
  z-index: 50;
  /* The one orchestrated motion on the page: it draws down on load. */
  transform-origin: top;
  animation: spine-draw 900ms cubic-bezier(.16,.8,.3,1) both;
}

@keyframes spine-draw { from { transform: scaleY(0); } to { transform: scaleY(1); } }

@media (prefers-reduced-motion: reduce) {
  .spine { animation: none; }
  body, .spine, .door { transition: none; }
}

/* ── Shell ──────────────────────────────────────────────────────────────── */

.wrap {
  max-width: 78rem;
  margin: 0 auto;
  padding-inline: clamp(1.5rem, 1rem + 3vw, 5rem);
}

/* ── Masthead ───────────────────────────────────────────────────────────── */

.masthead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s5);
  padding-block: var(--s5) var(--s6);
  flex-wrap: wrap;
}

.wordmark {
  font-family: var(--display);
  font-size: 1.35rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}
.wordmark em {
  font-style: italic;
  color: var(--room-accent-deep);
  transition: color 600ms ease;
}

.masthead nav {
  display: flex;
  gap: var(--s5);
  align-items: baseline;
  flex-wrap: wrap;
  font-size: var(--t-small);
}
.masthead nav a { color: var(--muted); text-decoration: none; }
.masthead nav a:hover,
.masthead nav a[aria-current] { color: var(--ink); text-decoration: underline; }

.tel {
  font-family: var(--display);
  font-size: 1.05rem;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}
.tel:hover { color: var(--room-accent-deep); }

/* ── Room ───────────────────────────────────────────────────────────────── */

.room { padding-block: var(--s7) var(--s9); }

/* The room head is asymmetric on purpose: the text column is wider than the
   picture column, and the two are baseline-matched at the bottom rather than
   the top, so the headline sits high and alone. */
.room-head {
  display: grid;
  gap: var(--s7);
  grid-template-columns: minmax(0, 1fr);
  align-items: end;
}

@media (min-width: 60rem) {
  .room-head { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }
}

.room-intro { display: grid; gap: var(--s4); max-width: 46ch; }

/* The lead piece: one photograph per room, larger than the grid below it. */
.room-lead { margin: 0; }
.room-lead img {
  width: 100%;
  height: auto;
  border-radius: var(--r-frame);
  background: var(--rule);
}


.room-name {
  font-family: var(--display);
  font-size: var(--t-h1);
  font-weight: 400;
  line-height: 0.92;
  letter-spacing: -0.02em;
  margin: 0;
  color: var(--room-accent-deep);
  transition: color 600ms ease;
}

.room-lede {
  margin: 0;
  font-size: clamp(1.0625rem, 1rem + 0.35vw, 1.3rem);
  line-height: 1.5;
  color: var(--ink);
  max-width: 44ch;
}

.room-note {
  margin: 0;
  font-size: var(--t-small);
  color: var(--muted);
  max-width: 52ch;
}

/* ── Work: photographs as delivery records, not product shots ───────────
   Every frame is captioned with when and where it arrived. That framing is
   what lets a small photograph read as evidence rather than as a thumbnail
   of something better.                                                    */

.work {
  display: grid;
  gap: var(--s6) var(--s5);
  margin-block: var(--s7) 0;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
}

/* Events photography is high-resolution, so it earns more room. */
.work--events {
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 21rem), 1fr));
}

.piece { margin: 0; }

.piece img {
  width: 100%;
  height: auto;
  border-radius: var(--r-frame);
  background: var(--rule);
}

/* Sympathy frames are fixed-ratio and modest, because the source files are
   small. Containing them is what keeps them from looking deficient. */
.work--sympathy .piece img {
  aspect-ratio: 3 / 4;
  object-fit: cover;
}

/* Captions carry a real description now, not a label, so they are set to be
   read: the name of the piece in the display face, the description beneath
   it at body-adjacent size with a measure short enough to scan. */
.piece figcaption,
.room-lead figcaption {
  margin-top: var(--s4);
  font-size: var(--t-small);
  line-height: 1.55;
  color: var(--muted);
  max-width: 46ch;
}

.piece figcaption b,
.room-lead figcaption b {
  display: block;
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--t-h3);
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin-bottom: var(--s2);
}

/* ── The door ───────────────────────────────────────────────────────────── */

.door {
  display: inline-block;
  margin-top: var(--s7);
  padding: 0.85rem 1.75rem;
  border-radius: var(--r-door);
  background: var(--room-accent-deep);
  color: var(--white);
  text-decoration: none;
  font-size: var(--t-small);
  transition: background-color 200ms ease;
}
.door:hover { background: var(--ink); color: var(--white); }

/* ── The threshold ──────────────────────────────────────────────────────
   Where the two rooms meet. The seam is two colours butted against each
   other with no gap — the building changing temperature, not a divider.  */

/* Full-bleed, and butted directly against the warmer panel below, no gap.
   The two colours meet edge to edge: the building changes temperature, it
   does not put up a divider. */
.threshold {
  height: 6px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin: var(--s8) 0 0;
}
.threshold span:first-child { background: var(--green); }
.threshold span:last-child { background: var(--red); }

/* ── Panels: the events room sits a shade warmer, even on the split page ── */



/* ── Foot ───────────────────────────────────────────────────────────────── */

.foot {
  border-top: 1px solid var(--rule);
  padding-block: var(--s6) var(--s7);
  font-size: var(--t-small);
  color: var(--muted);
  display: grid;
  gap: var(--s5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
}
.foot h2 {
  font-family: var(--display);
  font-size: var(--t-h3);
  font-weight: 400;
  margin: 0 0 var(--s2);
  color: var(--ink);
}
.foot p { margin: 0 0 var(--s2); }
.foot a { color: var(--muted); }

/* Unfilled facts are visible on purpose. Nothing about this business gets
   invented; if Linda has not told us, the page says so out loud. */
.todo {
  background: #fff6d6;
  border-bottom: 1px solid #d8b43a;
  color: #6b5312;
  padding: 0 0.25em;
  font-style: normal;
}

/* ── Prose ──────────────────────────────────────────────────────────────── */

.prose { max-width: var(--measure); }
.prose h2 {
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--t-h2);
  line-height: 1.1;
  letter-spacing: -0.015em;
  margin: var(--s8) 0 var(--s4);
  color: var(--ink);
}
.prose h3 {
  font-family: var(--display);
  font-weight: 500;
  font-size: var(--t-h3);
  margin: var(--s6) 0 var(--s2);
}
.prose p { margin: 0 0 var(--s4); }

/* Facts list — used for cut-off times and delivery reach. Definition list
   because that is what it is: a term and its value. */
.facts {
  margin: var(--s5) 0 0;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s3) var(--s5);
  font-size: var(--t-small);
  align-items: baseline;
}
.facts dt { color: var(--muted); }
.facts dd { margin: 0; color: var(--ink); }

/* ── Request form ────────────────────────────────────────────────────────
   One form, both rooms. Which room you came from is a real answer, not a
   hidden field, because it changes what Linda needs to know next.        */

.form { max-width: 38rem; margin-top: var(--s7); display: grid; gap: var(--s5); }

.field { display: grid; gap: var(--s2); }

.field label { font-size: var(--t-small); color: var(--ink); }

.field .hint { font-size: var(--t-fine); color: var(--muted); }

.field input,
.field select,
.field textarea {
  font: inherit;
  font-size: var(--t-body);
  color: var(--ink);
  background: var(--white);  /* lifted off the cream so a field reads as a field */
  border: 1px solid var(--rule);
  border-radius: var(--r-input);
  padding: 0.7rem 0.8rem;
  width: 100%;
}
.field textarea { min-height: 8rem; resize: vertical; }

.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible { border-color: var(--room-accent-deep); }

/* The room choice is the first decision, so it is shown as two real options
   rather than a dropdown. */
.rooms-pick { display: grid; gap: var(--s3); grid-template-columns: 1fr 1fr; }

.rooms-pick label {
  border: 1px solid var(--rule);
  border-radius: var(--r-input);
  padding: var(--s4);
  cursor: pointer;
  display: grid;
  gap: var(--s1);
  background: var(--white);
}
.rooms-pick label { position: relative; }
.rooms-pick label span { font-size: var(--t-fine); color: var(--muted); }

/* The radio is hidden but still focusable and still the thing being clicked.
   It needs an explicit size: the .field input width rule above would
   otherwise stretch it to the full page and push the layout sideways. */
.rooms-pick input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  opacity: 0;
  pointer-events: none;
}
.rooms-pick label:has(input:checked) {
  border-color: var(--room-accent-deep);
  box-shadow: inset 0 0 0 1px var(--room-accent-deep);
}
.rooms-pick label:has(input:focus-visible) {
  outline: 2px solid var(--room-accent-deep);
  outline-offset: 3px;
}

.submit {
  justify-self: start;
  border: 0;
  font: inherit;
  font-size: var(--t-small);
  padding: 0.85rem 1.75rem;
  border-radius: var(--r-door);
  background: var(--room-accent-deep);
  color: var(--white);
  cursor: pointer;
}
.submit:hover { background: var(--ink); }
.submit[disabled] { background: var(--muted); cursor: progress; }

/* Says what happened and what to do next; never apologises, never vague. */
.form-status { font-size: var(--t-small); margin: 0; }
.form-status[data-state="error"] { color: var(--red-deep); }
.form-status[data-state="sent"] { color: var(--green-deep); }

@media (max-width: 34rem) { .rooms-pick { grid-template-columns: 1fr; } }

/* Fieldsets carry a default min-width that stops them shrinking inside a
   grid, so it is cleared explicitly along with the chrome. */
.pick-set { border: 0; padding: 0; margin: 0; min-width: 0; }
.pick-legend { padding: 0; font-size: var(--t-small); color: var(--ink); }

/* ══ Hero ═══════════════════════════════════════════════════════════════
   The reference opens with a photograph against a solid colour panel. Here
   the panel is flanked by one photograph from each room, matched to the same
   3:4 frame, so the two halves of the business are introduced as equals
   before either one gets a section of its own. The panel carries the logo on
   its own cream, so the mark sits in the page rather than on top of it.            */

.hero {
  display: grid;
  gap: 0;
  grid-template-columns: 1fr;
  margin-bottom: var(--s8);
}

/* The panel needs real width for the headline, so the flanking photographs
   stay narrow: they are accents introducing the two rooms, not the subject.
   Below this width they are hidden entirely rather than squeezed. */
@media (min-width: 58rem) {
  .hero { grid-template-columns: 0.8fr 2fr 0.8fr; align-items: stretch; }
}

.hero-figure { margin: 0; position: relative; }
.hero-figure img {
  width: 100%;
  height: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  border-radius: var(--r-frame);
}
/* On a phone the flanking photographs would push the words off the screen. */
@media (max-width: 57.99rem) { .hero-figure { display: none; } }

.hero-panel {
  background: var(--cream);
  padding: var(--s8) clamp(1.5rem, 1rem + 3vw, 3.5rem);
  display: grid;
  gap: var(--s5);
  justify-items: center;
  align-content: center;
  text-align: center;
}

/* Used once per page, above the one headline that needs framing. Not a label
   dropped on top of every section. */
.eyebrow {
  margin: 0;
  font-size: var(--t-fine);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.hero-name {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2.5rem, 1.5rem + 3.6vw, 4.25rem);
  line-height: 0.95;
  letter-spacing: -0.02em;
  margin: 0;
  color: var(--ink);
}
.hero-name em { font-style: italic; }

.hero-panel p {
  margin: 0;
  max-width: 42ch;
  color: var(--ink);
}

.hero-call {
  font-family: var(--display);
  font-size: 1.5rem;
  color: var(--ink);
  text-decoration: none;
}
.hero-call:hover { color: var(--red-deep); }
.hero-call small {
  display: block;
  font-family: var(--body);
  font-size: var(--t-fine);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--s1);
}

/* A single botanical mark, used only where a section genuinely ends. */
.ornament { display: block; width: 28px; height: auto; color: var(--muted); }

/* ══ About ══════════════════════════════════════════════════════════════ */

.about {
  display: grid;
  gap: var(--s7);
  grid-template-columns: 1fr;
  align-items: start;
  padding-block: var(--s8);
}
@media (min-width: 58rem) {
  .about { grid-template-columns: minmax(0, 20rem) minmax(0, 1fr); gap: var(--s8); }
}

.about-portrait { margin: 0; }
.about-portrait img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: var(--r-frame);
}
.about-portrait figcaption {
  margin-top: var(--s3);
  font-size: var(--t-fine);
  color: var(--muted);
}

.about h2 {
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--t-h2);
  line-height: 1.1;
  letter-spacing: -0.015em;
  margin: 0 0 var(--s4);
  color: var(--ink);
}
.about p { margin: 0 0 var(--s4); max-width: 58ch; }

/* ══ Questions ══════════════════════════════════════════════════════════
   A real accordion element rather than scripted divs: it opens without
   JavaScript, it is keyboard operable for free, and find-in-page reaches
   the answers.                                                           */

.questions { max-width: 52rem; padding-block: var(--s7); }

.questions h2 {
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--t-h2);
  line-height: 1.1;
  letter-spacing: -0.015em;
  margin: 0 0 var(--s5);
  color: var(--ink);
}

.questions details { border-top: 1px solid var(--rule); }
.questions details:last-of-type { border-bottom: 1px solid var(--rule); }

.questions summary {
  cursor: pointer;
  list-style: none;
  padding: var(--s4) var(--s6) var(--s4) 0;
  position: relative;
  font-family: var(--display);
  font-size: var(--t-h3);
  color: var(--ink);
}
.questions summary::-webkit-details-marker { display: none; }

.questions summary::after {
  content: "+";
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--body);
  font-size: 1.25rem;
  color: var(--room-accent-deep);
}
.questions details[open] summary::after { content: "–"; }

.questions summary:hover { color: var(--room-accent-deep); }

.questions details p {
  margin: 0 0 var(--s4);
  max-width: 60ch;
  color: var(--ink);
}

/* ══ Panels ═════════════════════════════════════════════════════════════ */



/* ══ Instagram ══════════════════════════════════════════════════════════
   Her Instagram is where the newest work actually appears, so it is a real
   destination on this site rather than a small icon in the footer. The mark
   is drawn inline and inherits currentColor, so it takes the room's
   temperature like everything else.                                      */

.ig {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: var(--r-door);
  padding: 0.6rem 1.15rem 0.6rem 0.95rem;
  transition: border-color 200ms ease, color 200ms ease;
}
.ig:hover { border-color: var(--room-accent-deep); color: var(--room-accent-deep); }
.ig svg { width: 1.25rem; height: 1.25rem; flex: none; }
.ig b { font-weight: 400; font-family: var(--display); font-size: 1.05rem; }
.ig small {
  display: block;
  font-size: var(--t-fine);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

/* The follow block that closes the page: her handle at a size worth reading. */
.follow {
  text-align: center;
  padding-block: var(--s8);
  display: grid;
  justify-items: center;
  gap: var(--s4);
}
.follow h2 {
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--t-h2);
  line-height: 1.1;
  letter-spacing: -0.015em;
  margin: 0;
  color: var(--ink);
}
.follow p { margin: 0; max-width: 46ch; color: var(--muted); font-size: var(--t-small); }

/* Footer variant: no box, just the mark beside the handle. */
.ig--plain {
  border: 0;
  padding: 0;
  color: var(--muted);
  gap: 0.45rem;
}
.ig--plain svg { width: 1rem; height: 1rem; }
.ig--plain b { font-family: var(--body); font-size: var(--t-small); }

/* ══ The mark and the full logo ═════════════════════════════════════════ */

/* Masthead: the heart-and-rose monogram beside the name. At this size the
   script in the full logo would be unreadable, so only the mark is used. */
.wordmark { display: inline-flex; align-items: center; gap: 0.6rem; }
.wordmark img { width: 34px; height: auto; display: block; }

/* Hero: the full logo, on its own cream, which is the page's cream. It
   replaces the typeset name entirely — there is no reason to set her name
   in Newsreader when she has it drawn. */
.hero-logo { width: min(100%, 25rem); height: auto; margin: 0 auto; display: block; }


/* ══ Foliage ════════════════════════════════════════════════════════════
   One rule governs every vine on this site:

       a vine must enter from an edge and leave past one.

   Nothing sits in open space with all four sides showing — that is what
   made the first attempt read as stickers dropped on the page. Each piece
   is anchored to the edge or corner of a container whose `overflow` clips
   it, so the growth visibly continues off-canvas and the page looks like
   something ivy has grown over rather than something ivy was placed on.

   Consequences of that rule, applied throughout:
     · corners get corner pieces, oriented so the cut stems point outward
     · long edges get horizontal strips, run past both ends
     · a hanging piece starts above its container's top edge, never below
     · negative offsets are always outward, never inward

   All of it is decorative: `aria-hidden`, or a CSS background, and `alt=""`.
*/

.vine {
  position: absolute;
  display: block;
  height: auto;
  pointer-events: none;
  user-select: none;
  z-index: 1;
}

/* Containers that clip their own foliage. Without this the vines would
   extend the page and create a horizontal scrollbar. */
.vine-frame { position: relative; overflow: hidden; }

/* ── Page head ──────────────────────────────────────────────────────────
   Ivy hangs into the top corners from above the viewport. It is cut off by
   the top of the page, so it reads as coming from outside the frame. */

/* ── Hero panel ─────────────────────────────────────────────────────────
   Corner pieces tucked into the panel's own corners, growing inward from
   outside it. The panel clips them, so each one is a corner of a larger
   plant rather than a sprig sitting on a pink rectangle. */

.hero-panel { position: relative; overflow: hidden; }


/* ── Threshold ──────────────────────────────────────────────────────────
   A single strip laid along the seam and run past both ends of the screen,
   so the two rooms are joined by one continuous plant. */

/* The long pieces are TILED, not stretched. The asset sheet is only 1408px
   across, so a 400px strip blown up to full width was visibly pixelated.
   Repeating it at its own size keeps every leaf sharp and makes the garland
   genuinely continuous from edge to edge. `background-size: auto <height>`
   only ever scales down. */

.threshold-wrap .threshold {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  margin: 0;
  transform: translateY(-50%);
}

/* ── Room sections ──────────────────────────────────────────────────────
   A column down the outer edge, entering from the top of the section and
   leaving through the bottom. Replaces the sprig that used to float above
   each heading with nothing holding it up. */

.room-frame { position: relative; overflow: hidden; }

.vine--room-edge {
  top: -80px;
  width: clamp(70px, 7.5vw, 118px);
  opacity: 0.9;
}
.room-frame--left  .vine--room-edge { left: -34px; }
.room-frame--right .vine--room-edge { right: -34px; transform: scaleX(-1); }

/* It needs real gutter to live in; below this it would sit on the text. */
@media (max-width: 78rem) { .vine--room-edge { display: none; } }

/* ── Footer ─────────────────────────────────────────────────────────────
   A strip along the top edge, run past both sides. */

/* The footer garland sits in its own band above the columns. It used to be
   an oversized image lying across the whole footer, which buried the phone
   number and the opening hours. */
.foot-wrap { position: relative; }



/* Photograph figures are positioned so the single trailing vine below can
   be pinned inside them. */
.room-lead,
.piece { position: relative; }

/* ══ Panels ═════════════════════════════════════════════════════════════ */



/* ══ Instagram ══════════════════════════════════════════════════════════
   Her Instagram is where the newest work actually appears, so it is a real
   destination on this site rather than a small icon in the footer. The mark
   is drawn inline and inherits currentColor, so it takes the room's
   temperature like everything else.                                      */

.ig {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: var(--r-door);
  padding: 0.6rem 1.15rem 0.6rem 0.95rem;
  transition: border-color 200ms ease, color 200ms ease;
}
.ig:hover { border-color: var(--room-accent-deep); color: var(--room-accent-deep); }
.ig svg { width: 1.25rem; height: 1.25rem; flex: none; }
.ig b { font-weight: 400; font-family: var(--display); font-size: 1.05rem; }
.ig small {
  display: block;
  font-size: var(--t-fine);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

/* The follow block that closes the page: her handle at a size worth reading. */
.follow {
  text-align: center;
  padding-block: var(--s8);
  display: grid;
  justify-items: center;
  gap: var(--s4);
}
.follow h2 {
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--t-h2);
  line-height: 1.1;
  letter-spacing: -0.015em;
  margin: 0;
  color: var(--ink);
}
.follow p { margin: 0; max-width: 46ch; color: var(--muted); font-size: var(--t-small); }

/* Footer variant: no box, just the mark beside the handle. */
.ig--plain {
  border: 0;
  padding: 0;
  color: var(--muted);
  gap: 0.45rem;
}
.ig--plain svg { width: 1rem; height: 1rem; }
.ig--plain b { font-family: var(--body); font-size: var(--t-small); }

/* ══ The mark and the full logo ═════════════════════════════════════════ */

/* Masthead: the heart-and-rose monogram beside the name. At this size the
   script in the full logo would be unreadable, so only the mark is used. */
.wordmark { display: inline-flex; align-items: center; gap: 0.6rem; }
.wordmark img { width: 34px; height: auto; display: block; }

/* Hero: the full logo, on its own cream, which is the page's cream. It
   replaces the typeset name entirely — there is no reason to set her name
   in Newsreader when she has it drawn. */
.hero-logo { width: min(100%, 25rem); height: auto; margin: 0 auto; display: block; }


/* ══ Foliage ════════════════════════════════════════════════════════════
   One rule governs every vine on this site:

       a vine must enter from an edge and leave past one.

   Nothing sits in open space with all four sides showing — that is what
   made the first attempt read as stickers dropped on the page. Each piece
   is anchored to the edge or corner of a container whose `overflow` clips
   it, so the growth visibly continues off-canvas and the page looks like
   something ivy has grown over rather than something ivy was placed on.

   Consequences of that rule, applied throughout:
     · corners get corner pieces, oriented so the cut stems point outward
     · long edges get horizontal strips, run past both ends
     · a hanging piece starts above its container's top edge, never below
     · negative offsets are always outward, never inward

   All of it is decorative: `aria-hidden`, or a CSS background, and `alt=""`.
*/

.vine {
  position: absolute;
  display: block;
  height: auto;
  pointer-events: none;
  user-select: none;
  z-index: 1;
}

/* Containers that clip their own foliage. Without this the vines would
   extend the page and create a horizontal scrollbar. */
.vine-frame { position: relative; overflow: hidden; }

/* ── Page head ──────────────────────────────────────────────────────────
   Ivy hangs into the top corners from above the viewport. It is cut off by
   the top of the page, so it reads as coming from outside the frame. */

/* ── Hero panel ─────────────────────────────────────────────────────────
   Corner pieces tucked into the panel's own corners, growing inward from
   outside it. The panel clips them, so each one is a corner of a larger
   plant rather than a sprig sitting on a pink rectangle. */

.hero-panel { position: relative; overflow: hidden; }


/* ── Threshold ──────────────────────────────────────────────────────────
   A single strip laid along the seam and run past both ends of the screen,
   so the two rooms are joined by one continuous plant. */

/* The long pieces are TILED, not stretched. The asset sheet is only 1408px
   across, so a 400px strip blown up to full width was visibly pixelated.
   Repeating it at its own size keeps every leaf sharp and makes the garland
   genuinely continuous from edge to edge. `background-size: auto <height>`
   only ever scales down. */
.threshold-wrap {
  position: relative;
  height: 62px;
  background-image: url("/media/vine-strip-b.webp");
  background-repeat: repeat-x;
  background-position: center center;
  background-size: auto 62px;
}
.threshold-wrap .threshold {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  margin: 0;
  transform: translateY(-50%);
}

/* ── Room sections ──────────────────────────────────────────────────────
   A column down the outer edge, entering from the top of the section and
   leaving through the bottom. Replaces the sprig that used to float above
   each heading with nothing holding it up. */

.room-frame { position: relative; overflow: hidden; }

.vine--room-edge {
  top: -80px;
  width: clamp(70px, 7.5vw, 118px);
  opacity: 0.9;
}
.room-frame--left  .vine--room-edge { left: -34px; }
.room-frame--right .vine--room-edge { right: -34px; transform: scaleX(-1); }

/* It needs real gutter to live in; below this it would sit on the text. */
@media (max-width: 78rem) { .vine--room-edge { display: none; } }

/* ── Footer ─────────────────────────────────────────────────────────────
   A strip along the top edge, run past both sides. */

/* The footer garland sits in its own band above the columns. It used to be
   an oversized image lying across the whole footer, which buried the phone
   number and the opening hours. */
.foot-wrap { position: relative; }

.foot-band {
  height: 54px;
  margin-bottom: var(--s4);
  background-image: url("/media/vine-strip.webp");
  background-repeat: repeat-x;
  background-position: center center;
  background-size: auto 54px;
  opacity: 0.9;
}




/* ── Events panel ───────────────────────────────────────────────────────
   The panel runs the full width of the window, so its right edge IS the
   screen edge — the strongest anchor on the page. A column drops in from
   above the panel and is cut off by it top and bottom. */

.panel--events { position: relative; overflow: hidden; }


@media (max-width: 64rem) {  }

/* ── About panel ────────────────────────────────────────────────────────
   The clematis arch spans the top of the panel and is run wider than the
   screen so both ends leave the frame rather than tapering to a stop. */

.panel--paper { position: relative; }

/* A shallow band across the very top of the panel. The arch is anchored to
   the BOTTOM of it, so its top is cut away and only the hanging fringe
   shows — a garland along the edge rather than a whole arch lying across
   the text, which is what it was doing before. The band's height is the
   only thing controlling how much foliage appears. */


/* Centred on the band, not anchored to its bottom: the lower edge of the
   arch is mostly empty space between its two ends, so anchoring there showed
   nothing. The middle slice is where the foliage actually is. */


/* Content clears the crown and sits above it. */
.panel--paper > .wrap { position: relative; z-index: 1; }
.panel--paper .about { padding-top: calc(clamp(54px, 7vw, 82px) + var(--s6)); }


/* ══ Vines framing the photographs ═════════════════════════════════════
   A vine runs all four sides of every picture, in a strip the photograph
   reserves with its own padding. Because the strip is real space, the
   foliage cannot touch the picture or the caption — it is beside them, not
   over them.

   Each frame is drawn with FOUR background layers on a single pseudo
   element: two tiled down the sides, two tiled across the top and bottom.
   They tile at their own scale rather than stretching, so the frame lines
   up exactly whatever the picture's proportions are and every leaf stays
   sharp.

   Two plants alternate between pictures — variegated ivy and jasmine — and
   each frame uses only one of them, so a frame always looks like a single
   vine rather than a collage. The side strips are phase-shifted against the
   top and bottom so the corners do not repeat identically.                */

:root { --vine-strip: 46px; }

.shot { position: relative; display: block; padding: var(--vine-strip); }
.shot img { display: block; width: 100%; }

.shot::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-repeat: repeat-y, repeat-y, repeat-x, repeat-x;
  background-position: left top, right center, left top, left bottom;
  background-size:
    var(--vine-strip) auto,
    var(--vine-strip) auto,
    auto var(--vine-strip),
    auto var(--vine-strip);
}

/* Variegated ivy. */
.piece:nth-child(odd) .shot::before,
.room-lead .shot::before {
  background-image:
    url("/media/ivyA-v.webp"), url("/media/ivyA-v.webp"),
    url("/media/ivyA-h.webp"), url("/media/ivyA-h.webp");
}

/* Jasmine — finer and more open, so neighbours never look identical. */
.piece:nth-child(even) .shot::before,
.hero-figure .shot::before {
  background-image:
    url("/media/ivyB-v.webp"), url("/media/ivyB-v.webp"),
    url("/media/ivyB-h.webp"), url("/media/ivyB-h.webp");
}

.hero-figure .shot { height: 100%; }
.hero-figure .shot img { height: 100%; object-fit: cover; }

/* A phone cannot spare 46px on every side of a small picture. */
@media (max-width: 46rem) {
  .shot { padding: 0; }
  .shot::before { display: none; }
}

/* ── The page's own corner ──────────────────────────────────────────────
   One large piece at the top-left of the hero, bleeding off the top and
   left edges of the window. This is the confident gesture in the reference
   that sets the tone; everything else on the page is deliberately smaller
   than it. */

.hero { position: relative; }

.hero::before {
  content: "";
  position: absolute;
  z-index: 4;
  pointer-events: none;
  top: -78px;
  left: -13vw;
  width: clamp(240px, 30vw, 460px);
  aspect-ratio: 764 / 654;
  background-image: url("/media/frame-tl.webp");
  background-repeat: no-repeat;
  background-size: contain;
  background-position: left top;
}

.hero-figure .shot,
.hero-figure .shot img { height: 100%; }

@media (max-width: 46rem) {
  .hero::before { left: -22vw; width: 240px; top: -54px; }
}
