/* ═════════════════════════════════════════════════════════════════════════════
   five-sixty-one · warm dusk
   The whole rebrand is the six tokens and two faces below. scrollcraft.css is
   the mechanism and is never edited; everything here is this page's own.
   ═════════════════════════════════════════════════════════════════════════════ */

:root {
  --sc-canvas:     #FDF4F1;   /* cream, with a pink cast rather than a peach one */
  --sc-surface:    #F8E3E0;   /* warm pink plate                  */
  --sc-ink:        #46203A;   /* deep plum                        */
  --sc-ink-soft:   #7A4A4E;   /* warm rose brown, 5.1:1 on the darkest ground */
  --sc-accent:     #9E3450;   /* warm rose, 4.9:1 on the darkest ground */
  --sc-accent-ink: #FDF4F1;

  --sc-font-display: "Fraunces", Georgia, serif;
  --sc-font-text:    "Archivo", system-ui, sans-serif;
  /* A third face, which the taste floor calls a costume by default. It is
     earned here: the captions are ink written ON the photographs, a content
     voice rather than a third UI font, and they are the only thing that uses
     it. Nothing in the chrome, headings or body is ever set in this. */
  --font-hand:       "Caveat", "Bradley Hand", cursive;

  /* This page's own. The accent is locked for the whole page, per the taste
     floor, so the variety comes from the GROUNDS: each room sits on its own
     hue rather than a lighter or darker version of one hue. */
  --rose:      #D68FA6;
  --pink:      #F6DDE4;
  --mauve:     #B98BB2;
  --lilac:     #EEDDEC;
  --gold:      #D8A44E;       /* one non-text role only: the blooms */

  /* One hue per room, not one hue at six lightnesses. Room III is the cool one
     on purpose: it is the hush in the feeling curve, and a cooler ground makes
     the visitor feel they have walked into a different room rather than the
     same room repainted. */
  --ground-i:     #FDF4F1;    /* cream pink  */
  --ground-ii:    #F7EDE2;    /* warm sand   */
  --ground-iii:   #E4DCEA;    /* dusty lilac */
  --ground-iv:    #FCF3F4;    /* cream rose  */
  --ground-v:     #F0D8DE;    /* rose pink   */
  --ground-close: #F5E4E7;    /* warm pink   */

  --shadow: 0 18px 44px -18px rgba(70, 32, 58, .32), 0 3px 10px -4px rgba(70, 32, 58, .17);
  --shadow-lift: 0 30px 70px -22px rgba(70, 32, 58, .4), 0 4px 12px -4px rgba(70, 32, 58, .19);
  --edge: inset 0 1px 0 rgba(255, 252, 251, .85);
}

/* ── utilities ───────────────────────────────────────────────────────────── */
.u-sr {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

body { background: var(--sc-canvas); }
body.is-locked { overflow: hidden; }

/* ═══ THE DOOR ═══════════════════════════════════════════════════════════════
   The gate does the title-page job, which is why the collection itself starts
   on object one with no hero treatment. */

.door {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center;
  padding: var(--sc-gutter);
  background:
    radial-gradient(90% 70% at 78% 12%, rgba(216, 164, 78, .26) 0%, rgba(216, 164, 78, 0) 55%),
    radial-gradient(100% 80% at 18% 82%, rgba(185, 139, 178, .42) 0%, rgba(185, 139, 178, 0) 60%),
    linear-gradient(168deg, #FAE7EA 0%, #EFC1CC 48%, #D2919F 100%);
}
.door::after {                      /* film grain, so the plate sits in a room */
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .4;
  background-image: radial-gradient(rgba(70, 32, 58, .5) .5px, transparent .5px);
  background-size: 3px 3px;
}
.door.is-open {
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1100ms cubic-bezier(.62, .01, .3, 1);
}
.door__plate {
  position: relative; z-index: 1;
  width: min(30rem, 100%);
  padding: clamp(1.9rem, 4.5vw, 3.1rem);
  text-align: center;
  background: linear-gradient(180deg, #FEFAF6 0%, #FBF0E7 100%);
  border-radius: 4px;
  box-shadow: var(--shadow-lift), var(--edge);
}
.door__plate::before {              /* the hairline a real museum plate has */
  content: ""; position: absolute; inset: 9px; border: 1px solid rgba(70, 32, 58, .16);
  border-radius: 2px; pointer-events: none;
}
.door__eyebrow {
  font-family: var(--font-hand); font-size: 1.3rem; font-weight: 600;
  color: var(--sc-accent); margin: 0 0 var(--sc-2); transform: rotate(-1.5deg);
}
.door__title {
  font-family: var(--sc-font-display); font-weight: 400;
  font-size: clamp(2rem, 7vw, 2.9rem); line-height: 1.02;
  letter-spacing: var(--sc-track-tight); color: var(--sc-ink);
  margin: 0 0 var(--sc-3); text-wrap: balance;
}
.door__body {
  font-size: .95rem; line-height: 1.6; color: var(--sc-ink-soft);
  margin: 0 auto var(--sc-6); max-width: 24ch; text-wrap: pretty;
}
.door__form { display: grid; gap: var(--sc-4); justify-items: center; }

/* the pips are the visible field; the real input sits on top, transparent */
.door__field { position: relative; width: max-content; }
.door__pips { display: flex; gap: var(--sc-3); }
.door__pip {
  width: 3.1rem; height: 3.9rem; border-radius: 3px;
  display: grid; place-items: center;
  font-family: var(--sc-font-display); font-size: 1.9rem; color: var(--sc-ink);
  background: #FFFDFB;
  border: 1px solid rgba(70, 32, 58, .22);
  box-shadow: inset 0 2px 5px rgba(70, 32, 58, .07);
  transition: border-color 160ms var(--sc-ease-out), box-shadow 160ms var(--sc-ease-out);
}
.door__pip.is-next {
  border-color: var(--sc-accent);
  box-shadow: 0 0 0 3px rgba(158, 52, 80, .18), inset 0 2px 5px rgba(70, 32, 58, .07);
}
.door__input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  font-size: 16px;                          /* 16px stops iOS zooming on focus */
  color: transparent; background: transparent; border: 0; caret-color: transparent;
  text-align: center; letter-spacing: 2em;
}
.door__input:focus { outline: none; }
.door__input:focus-visible ~ .door__pips .door__pip.is-next {
  outline: 2px solid var(--sc-accent); outline-offset: 3px;
}
.door__go {
  font-family: var(--sc-font-text); font-size: .86rem; font-weight: 600;
  letter-spacing: .04em;
  color: var(--sc-accent-ink); background: var(--sc-accent);
  border: 0; border-radius: var(--sc-r-pill); padding: .85rem 2.1rem; cursor: pointer;
  transition: background 140ms var(--sc-ease-out), transform 110ms var(--sc-ease-out);
}
.door__go:hover { background: #85293F; }
.door__go:active { transform: translateY(1px); }
.door__go:focus-visible { outline: 2px solid var(--sc-ink); outline-offset: 3px; }
.door__msg {
  min-height: 1.35rem; margin: 0;
  font-size: .88rem; color: var(--sc-accent); font-style: italic;
}
.door__plate.is-wrong { animation: shake 420ms var(--sc-ease-out); }
@keyframes shake {
  10%, 90% { transform: translateX(-2px); }
  30%, 70% { transform: translateX(4px); }
  50%      { transform: translateX(-5px); }
}
@media (prefers-reduced-motion: reduce) {
  .door.is-open { transition-duration: 1ms; }
  .door__plate.is-wrong { animation: none; }
}

/* ═══ CHROME · an index of objects, and it jumps ════════════════════════════ */

.chrome {
  position: fixed; top: 0; left: 0; right: 0; z-index: var(--sc-z-chrome);
  display: flex; align-items: center; gap: var(--sc-4);
  padding: var(--sc-3) var(--sc-gutter);
  background: rgba(253, 246, 240, .9);
  backdrop-filter: blur(9px);
  border-bottom: 1px solid rgba(70, 32, 58, .1);
}
.chrome__mark {
  font-family: var(--sc-font-display); font-size: 1.02rem; font-weight: 400;
  letter-spacing: .01em; color: var(--sc-ink); margin: 0; margin-right: auto;
}
.chrome__mark span { color: var(--sc-accent); }
.chrome__btn {
  font-family: var(--sc-font-text); font-size: .84rem; font-weight: 500;
  letter-spacing: .01em;
  color: var(--sc-ink-soft); background: none; border: 0; cursor: pointer;
  padding: .5rem .3rem; border-bottom: 2px solid transparent;
  transition: color 140ms var(--sc-ease-out), border-color 140ms var(--sc-ease-out);
}
.chrome__btn:hover { color: var(--sc-ink); }
.chrome__btn[aria-current="true"] { color: var(--sc-ink); border-bottom-color: var(--sc-accent); }
.chrome__btn:focus-visible { outline: 2px solid var(--sc-accent); outline-offset: 2px; }

/* At 390px the wordmark wrapped to three lines and took the bar with it. */
@media (max-width: 620px) {
  .chrome { gap: .3rem; padding-inline: .75rem; }
  .chrome__mark { font-size: .84rem; white-space: nowrap; }
  .chrome__btn { font-size: .78rem; padding: .5rem .25rem; white-space: nowrap; }
}

.index {
  position: fixed; z-index: calc(var(--sc-z-chrome) - 1);
  top: 3.4rem; right: var(--sc-gutter);
  width: min(19rem, calc(100vw - 2 * var(--sc-gutter)));
  padding: var(--sc-5);
  background: #FFFCF9; border: 1px solid rgba(70, 32, 58, .14);
  border-radius: var(--sc-r-md); box-shadow: var(--shadow);
}
.index[hidden] { display: none; }
.index__title {
  font-family: var(--font-hand); font-size: 1.3rem; font-weight: 600;
  color: var(--sc-accent); margin: 0 0 var(--sc-3);
}
.index__list { list-style: none; margin: 0; padding: 0; }
.index__list li + li { margin-top: 1px; }
.index__link {
  display: flex; align-items: baseline; gap: var(--sc-3); width: 100%;
  font-family: var(--sc-font-text); font-size: .9rem; text-align: left;
  color: var(--sc-ink); background: none; border: 0; cursor: pointer;
  padding: .5rem .55rem; border-radius: var(--sc-r-sm);
  transition: background 130ms var(--sc-ease-out);
}
.index__link:hover { background: var(--sc-surface); }
.index__link:focus-visible { outline: 2px solid var(--sc-accent); outline-offset: -2px; }
.index__num {
  font-family: var(--sc-font-display); font-size: .8rem; color: var(--sc-accent);
  min-width: 2.1rem; font-variant-numeric: tabular-nums;
}
.index__count { margin-left: auto; font-size: .74rem; color: var(--sc-ink-soft); }

/* ═══ VIEWS ════════════════════════════════════════════════════════════════ */
.view[hidden] { display: none; }

/* ═══ THE PHOTOS ═══════════════════════════════════════════════════════════
   Prints, not exhibits. Deep white border with the weight at the bottom the
   way an instant photo has it, a caption written into that bottom margin, a
   piece of tape, and a small tilt that is deterministic per photo rather than
   random, so the wall does not reshuffle itself on every reload.
   ═════════════════════════════════════════════════════════════════════════════ */

.object { margin: 0; }

.object__frame {
  display: block; position: relative;
  background: #FFFCFA;
  padding: clamp(.55rem, 1.1vw, .8rem);
  border-radius: 2px;
  box-shadow: var(--shadow), var(--edge);
  transform: rotate(var(--tilt, 0deg));
  transition: transform 260ms var(--sc-ease-out), box-shadow 260ms var(--sc-ease-out);
}
.object__frame img {
  display: block; width: 100%; height: auto;
  border-radius: 1px;
}
/* no caption to hold the bottom margin open, so hold it open directly */
.object__frame--bare { padding-bottom: clamp(1.5rem, 2.6vw, 2.2rem); }

/* a strip of tape, alternating corner so the wall does not look stamped out */
.object__frame::before {
  content: ""; position: absolute; z-index: 2;
  top: -.55rem; left: 12%;
  width: clamp(2.6rem, 5vw, 4rem); height: clamp(.9rem, 1.6vw, 1.25rem);
  background: rgba(214, 143, 166, .38);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .5);
  transform: rotate(-4deg);
}
.object:nth-child(even) .object__frame::before { left: auto; right: 12%; transform: rotate(5deg); }

/* straighten and lift when she goes to look at one */
@media (hover: hover) and (pointer: fine) {
  .object__frame:hover {
    transform: rotate(0deg) translateY(-5px) scale(1.012);
    box-shadow: var(--shadow-lift), var(--edge);
  }
}
@media (prefers-reduced-motion: reduce) {
  .object__frame { transition: none; }
  .object__frame:hover { transform: rotate(var(--tilt, 0deg)); }
}

/* ── the caption, in the print's bottom margin ───────────────────────────────
   In normal flow rather than absolutely positioned. A fixed padding-bottom on
   the frame is a magic number that has to guess the caption's height, and it
   guessed wrong the moment one wrapped to two lines: the words sat on top of
   the photograph. Letting the caption occupy real space cannot overlap, and it
   means a long caption grows the margin instead of being truncated. */
.cap {
  display: flex; align-items: baseline; gap: .55rem;
  padding: clamp(.7rem, 1.4vw, 1rem) clamp(.2rem, .5vw, .4rem) clamp(.15rem, .4vw, .3rem);
}
.cap__text {
  font-family: var(--font-hand); font-weight: 600;
  font-size: clamp(1.05rem, 1.5vw, 1.3rem); line-height: 1.2;
  color: var(--sc-ink); margin: 0;
  text-wrap: pretty;
}
.cap__when {
  font-family: var(--font-hand); font-weight: 400;
  font-size: clamp(.9rem, 1.2vw, 1.05rem); line-height: 1.15;
  color: var(--sc-accent); margin: 0 0 0 auto; flex: none;
}

/* ═══ ROOM I · the vestibule ════════════════════════════════════════════════ */

.room { position: relative; }
.room--i {
  background: var(--ground-i);
  min-height: 100svh; display: grid; align-items: center;
  overflow: hidden;
}
.vestibule {
  position: relative; z-index: 1;
  width: 100%; max-width: var(--sc-maxw); margin-inline: auto;
  padding-inline: var(--sc-gutter);
  display: grid; gap: clamp(1.5rem, 4vw, 3.5rem);
  grid-template-columns: minmax(0, 1fr) minmax(0, .8fr);
  align-items: end;
}
.vestibule__planes { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
/* planes carry max-width:none and a fixed size, or a global img rule shrinks
   them to the viewport on phones */
.plane { position: absolute; max-width: none; will-change: transform; }
.plane--bloom {
  width: min(44rem, 116vw); aspect-ratio: 1; right: -12%; top: -26%;
  background: radial-gradient(circle, rgba(216, 164, 78, .42) 0%, rgba(216, 164, 78, 0) 66%);
}
.plane--far {
  width: min(36rem, 94vw); aspect-ratio: 1; left: -16%; bottom: -26%;
  background: radial-gradient(circle, rgba(185, 139, 178, .46) 0%, rgba(185, 139, 178, 0) 68%);
}
.plane--mid {
  left: 0; right: 0; bottom: 0; height: 44%;
  background: linear-gradient(180deg, rgba(246, 221, 228, 0) 0%, rgba(246, 221, 228, .78) 100%);
}
.vestibule__object { justify-self: start; }
.vestibule__object .object__frame img { max-height: 62svh; width: auto; max-width: min(34rem, 86vw); }
.vestibule__plate { padding-bottom: clamp(.5rem, 3vw, 2.2rem); }
.vestibule__room {
  font-family: var(--font-hand); font-size: 1.25rem; font-weight: 600;
  color: var(--sc-accent); margin: 0 0 var(--sc-3); transform: rotate(-1.5deg);
}
.vestibule__hed {
  font-family: var(--sc-font-display); font-weight: 400;
  font-size: clamp(2rem, 4.4vw, 3.2rem); line-height: 1.02;
  letter-spacing: var(--sc-track-tight); color: var(--sc-ink);
  margin: 0 0 var(--sc-4); text-wrap: balance;
}
.vestibule__sub {
  font-size: .98rem; line-height: 1.6; color: var(--sc-ink-soft);
  margin: 0; max-width: 32ch; text-wrap: pretty;
}
@media (max-width: 800px) {
  .vestibule { grid-template-columns: 1fr; align-items: start; gap: var(--sc-5); }
  .vestibule__object { max-width: 100%; }
  .vestibule__plate { padding-bottom: 0; }
}

/* ═══ ROOM II · the long wall ══════════════════════════════════════════════
   A native horizontal scroll region, not a scroll-driven pan. Lateral travel
   still reads as breadth, which is the point of the device, but the visitor
   drives it with the gesture that already means "sideways" instead of having
   their vertical wheel reinterpreted. It also costs the page about six
   viewport-heights, which the wall was spending on travel rather than content.
   ═════════════════════════════════════════════════════════════════════════════ */

.room--ii {
  background: var(--ground-ii);
  padding-block: var(--sc-section);
}
.wall { max-width: var(--sc-maxw); margin-inline: auto; }
.wall__head {
  display: flex; align-items: flex-end; gap: var(--sc-5);
  padding-inline: var(--sc-gutter); margin-bottom: var(--sc-6);
}
.wall__head > div:first-child { margin-right: auto; }
.wall__head h2 {
  font-family: var(--sc-font-display); font-weight: 400;
  font-size: clamp(1.9rem, 4.2vw, 3.1rem); line-height: 1.04;
  letter-spacing: var(--sc-track-tight); color: var(--sc-ink);
  margin: 0 0 var(--sc-4); text-wrap: balance;
}
.wall__head p {
  font-size: .98rem; line-height: 1.62; color: var(--sc-ink-soft);
  margin: 0; max-width: 40ch; text-wrap: pretty;
}
.rail__eyebrow {
  font-family: var(--font-hand); font-size: 1.25rem; font-weight: 600;
  color: var(--sc-accent); margin: 0 0 var(--sc-2); transform: rotate(-1.2deg);
}

.wall__nav { display: flex; gap: var(--sc-3); flex: none; }
.wall__arrow {
  width: 2.9rem; height: 2.9rem; display: grid; place-items: center;
  color: var(--sc-ink); background: #FFFCFB;
  border: 1px solid rgba(70, 32, 58, .2); border-radius: 50%; cursor: pointer;
  transition: background 140ms var(--sc-ease-out), transform 110ms var(--sc-ease-out),
              opacity 160ms var(--sc-ease-out);
}
.wall__arrow svg { width: 1.15rem; height: 1.15rem; }
.wall__arrow:hover { background: var(--sc-surface); }
.wall__arrow:active { transform: translateY(1px); }
.wall__arrow:focus-visible { outline: 2px solid var(--sc-accent); outline-offset: 3px; }
.wall__arrow[disabled] { opacity: .3; cursor: default; }
.wall__arrow[disabled]:hover { background: #FFFCFB; }

.wall__rail {
  display: flex; align-items: center;
  gap: clamp(1.4rem, 3.6vw, 3.6rem);
  padding-inline: var(--sc-gutter); padding-block: var(--sc-3) var(--sc-5);
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
  scrollbar-color: rgba(70, 32, 58, .28) transparent;
  cursor: grab;
  /* Without this, injecting objects ahead of the closing note makes scroll
     anchoring shove the rail to its far end on load. */
  overflow-anchor: none;
}
.wall__rail.is-dragging { cursor: grabbing; scroll-snap-type: none; scroll-behavior: auto; }
.wall__rail img { -webkit-user-drag: none; user-select: none; }
/* Deliberately NOT pointer-events:none on the children while dragging. Changing
   hit-testing mid-gesture can make the browser fire pointercancel, which kills
   the drag; the pointer capture set on pointerdown is what keeps the gesture. */
.wall__rail:focus-visible { outline: 2px solid var(--sc-accent); outline-offset: 4px; }
.wall__rail::-webkit-scrollbar { height: 8px; }
.wall__rail::-webkit-scrollbar-track { background: transparent; }
.wall__rail::-webkit-scrollbar-thumb {
  background: rgba(70, 32, 58, .24); border-radius: 99px;
}
.wall__rail::-webkit-scrollbar-thumb:hover { background: rgba(70, 32, 58, .38); }

/* Mixed orientations on one wall: hang them all to a common PICTURE HEIGHT
   and let the width follow the shape. A fixed width instead makes a portrait
   half again as tall as the landscape beside it and the wall reads as a
   ragged column of different objects rather than one hang. */
.rail__obj { flex: none; scroll-snap-align: center; }
.rail__obj .object__frame img {
  height: clamp(13rem, 36vh, 21rem);
  width: auto; max-width: min(78vw, 30rem);
}

/* arrival, driven by the rail's own observer. Opacity and transform only, and
   the floor is 0.55 rather than 0 so an object that has not settled yet reads
   as arriving rather than as failing to load. */
@media (prefers-reduced-motion: no-preference) {
  .rail__enter {
    opacity: .55; transform: translateY(12px);
    transition: opacity 520ms var(--sc-ease-out), transform 520ms var(--sc-ease-out);
  }
  .rail__enter.is-in { opacity: 1; transform: none; }
}
/* the floor is .55, not 0, so even a total failure of the observer leaves the
   wall readable rather than blank */
.rail__obj .plate { margin-top: var(--sc-4); }
/* the closing note is a rail item in its own right: it gives the wall an
   ending rather than just running out */
.rail__tail { flex: none; width: min(20rem, 68vw); align-self: center; scroll-snap-align: center; }
.rail__tail p:first-child {
  font-family: var(--font-hand); font-weight: 600; font-size: 1.7rem;
  color: var(--sc-ink); margin: 0 0 var(--sc-3); max-width: 22ch;
  transform: rotate(-1deg);
}
.rail__tail p {
  font-size: .95rem; line-height: 1.6; color: var(--sc-ink-soft); margin: 0;
  max-width: 28ch; text-wrap: pretty;
}

/* a readout, so it is obvious the wall has more of itself to the right */
.wall__progress {
  height: 2px; margin: 0 var(--sc-gutter);
  background: rgba(70, 32, 58, .12); border-radius: 99px; overflow: hidden;
}
.wall__progress span {
  display: block; height: 100%; width: 0;
  background: var(--sc-accent); border-radius: 99px;
  transition: width 120ms linear;
}
@media (max-width: 620px) {
  .wall__head { flex-direction: column; align-items: flex-start; }
  .wall__nav { order: -1; }
}

/* ═══ ROOM III · the vitrine (pin) · authored silence ═══════════════════════ */

.room--iii { background: var(--ground-iii); }
.vitrine { display: grid; place-items: center; padding: var(--sc-gutter); }
.vitrine__hed {
  position: absolute; top: clamp(2.5rem, 8vh, 6rem); left: 50%;
  transform: translateX(-50%) rotate(-1.5deg); z-index: 2;
  font-family: var(--font-hand); font-weight: 600; font-size: 1.9rem;
  color: var(--sc-ink-soft); margin: 0; white-space: nowrap;
}
/* the case is the ground: it is already there before any cue fires */
.vitrine__objs { position: relative; z-index: 1; display: grid; place-items: center; }
.vitrine__obj {
  grid-area: 1 / 1; margin: 0;
  display: grid; gap: var(--sc-5); justify-items: center; text-align: center;
}
.vitrine__obj .object__frame img {
  max-height: 54svh; width: auto; max-width: min(23rem, 76vw);
}


/* ═══ EVERYTHING AT ONCE · the big pile ═════════════════════════════════════ */

.room--iv {
  background: var(--ground-iv);
  /* a flow section straight after a pinned act takes reduced top padding, or
     its first content is another screen away */
  padding-block: var(--sc-7) var(--sc-section);
}
.salon__head { max-width: var(--sc-maxw); margin: 0 auto var(--sc-7); padding-inline: var(--sc-gutter); }
.salon__hand { font-family: var(--font-hand); }
.salon__head h2 {
  font-family: var(--sc-font-display); font-weight: 400;
  font-size: clamp(1.9rem, 4.2vw, 3.1rem); line-height: 1.04;
  letter-spacing: var(--sc-track-tight); color: var(--sc-ink); margin: 0 0 var(--sc-4);
  text-wrap: balance;
}
.salon__head p {
  font-size: .98rem; line-height: 1.62; color: var(--sc-ink-soft);
  margin: 0; max-width: 46ch; text-wrap: pretty;
}
.salon__stage { position: relative; max-width: var(--sc-maxw); margin-inline: auto; padding-inline: var(--sc-gutter); }
/* an asymmetric hanging, not a grid of equal cells */
/* Columns, not a span grid: a span grid has to guess each photo's shape and
   leaves holes when it guesses wrong. These are real flex columns filled in
   app.js rather than CSS multicol, because multicol fragments any print taller
   than the column box and cuts the bottom off the photograph. */
.salon { display: flex; align-items: flex-start; gap: clamp(.8rem, 1.8vw, 1.6rem); }
.salon__col {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; gap: clamp(.8rem, 1.8vw, 1.6rem);
}
.salon__obj { margin: 0; }
.salon__obj { margin: 0; }
.salon__obj .plate { margin-top: var(--sc-3); }
.salon__obj .plate__title { font-size: .92rem; }
.salon__obj .plate__meta { font-size: .76rem; }


/* ═══ ROOM V · the principal work (the peak) ════════════════════════════════ */

.room--v { background: var(--ground-v); }
/* The print sits above its plate rather than under a translucent panel. An
   absolutely positioned grid child resolves left:50% against its own grid
   area, not the stage, which is why the overlaid version sat off centre; and
   a plate laid over a photograph is a scrim problem this composition does not
   need to have. Print above, label below, which is how the room would hang it. */
.principal {
  display: grid; justify-items: center; align-content: center;
  gap: clamp(1rem, 2.4vw, 1.7rem);
  padding: var(--sc-gutter);
}
.principal__frame {
  margin: 0; position: relative; width: fit-content;
  background: #FFFCFA;
  padding: clamp(.6rem, 1.4vw, 1.1rem);
  border-radius: 2px; box-shadow: var(--shadow-lift), var(--edge);
  /* the print is the ground: present from p = 0, and it settles as she scrolls */
  transform: rotate(calc(var(--tilt, 0deg) * 0.5))
             scale(calc(.94 + .06 * clamp(0, var(--sc-p, 0) * 2.4, 1)));
}
.principal__frame::before {
  content: ""; position: absolute; z-index: 2;
  top: -.6rem; left: 50%;
  width: clamp(3rem, 5.5vw, 4.4rem); height: clamp(1rem, 1.7vw, 1.3rem);
  background: rgba(214, 143, 166, .38);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .5);
  transform: translateX(-50%) rotate(-3deg);
}
.principal__frame img {
  display: block; width: auto; height: auto;
  max-width: min(68vw, 50rem); max-height: 58svh;
  border-radius: 1px;
}
.principal__plate { text-align: center; max-width: min(34rem, 88vw); }
.principal__kicker {
  font-family: var(--font-hand); font-weight: 600; font-size: 1.9rem;
  color: var(--sc-accent); margin: 0; transform: rotate(-1.4deg);
}
@media (max-width: 720px) {
  .principal__frame img { max-width: 80vw; max-height: 48svh; }
}
@media (prefers-reduced-motion: reduce) {
  .principal__frame { transform: none; }
}

/* ═══ THE NOTE AT THE END ══════════════════════════════════════════════════ */

.room--close {
  background: var(--ground-close);
  min-height: 100svh;
  display: grid; align-content: center;
  padding-block: var(--sc-7);
}
.inquiry {
  max-width: 32rem; margin-inline: auto;
  padding: clamp(2rem, 4.5vw, 3rem) clamp(1.6rem, 4vw, 2.6rem);
  text-align: center; position: relative;
  background: #FFFCFA; border-radius: 3px;
  box-shadow: var(--shadow), var(--edge);
  transform: rotate(-1deg);
}
.inquiry::before {                       /* tape, same as the photographs */
  content: ""; position: absolute; z-index: 2;
  top: -.6rem; left: 50%;
  width: clamp(3rem, 6vw, 4.6rem); height: clamp(1rem, 1.8vw, 1.35rem);
  background: rgba(214, 143, 166, .38);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .5);
  transform: translateX(-50%) rotate(-3deg);
}
/* The sign-off is the whole note now, so it carries the size on its own and
   needs the breathing room the second line used to provide. */
.inquiry__hand {
  font-family: var(--font-hand); font-weight: 600;
  font-size: clamp(2.3rem, 6vw, 3.4rem); line-height: 1.1;
  color: var(--sc-ink); margin: 0 0 var(--sc-6); text-wrap: balance;
}
.inquiry__cta {
  display: inline-block;
  font-family: var(--sc-font-text); font-size: .82rem; font-weight: 600;
  letter-spacing: .1em;
  color: var(--sc-accent-ink); background: var(--sc-accent);
  border: 0; border-radius: var(--sc-r-pill); cursor: pointer;
  padding: .8rem 1.6rem;
  transition: background 140ms var(--sc-ease-out), transform 110ms var(--sc-ease-out);
}
.inquiry__cta:hover { background: #85293F; transform: translateY(-1px); }
.inquiry__cta:active { transform: translateY(1px); }
.inquiry__cta:focus-visible { outline: 2px solid var(--sc-ink); outline-offset: 3px; }

/* ═══ THE PUZZLE ROOM ══════════════════════════════════════════════════════ */

.puzzle { padding: 5rem var(--sc-gutter) var(--sc-9); }
.puzzle__head { max-width: var(--sc-maxw); margin: 0 auto var(--sc-7); }
.puzzle__eyebrow {
  font-family: var(--font-hand); font-size: 1.3rem; font-weight: 600;
  color: var(--sc-accent); margin: 0 0 var(--sc-2); transform: rotate(-1.2deg);
}
.puzzle__head h2 {
  font-family: var(--sc-font-display); font-weight: 400;
  font-size: clamp(1.9rem, 4.2vw, 3.1rem); line-height: 1.04;
  letter-spacing: var(--sc-track-tight); color: var(--sc-ink); margin: 0 0 var(--sc-4);
}
.puzzle__head p { font-size: .98rem; line-height: 1.62; color: var(--sc-ink-soft); margin: 0; max-width: 52ch; }

.puzzle__body {
  max-width: var(--sc-maxw); margin-inline: auto;
  display: grid; gap: clamp(1.6rem, 3.5vw, 3rem);
  grid-template-columns: minmax(0, auto) minmax(15rem, 1fr);
  align-items: start;
}
@media (max-width: 900px) { .puzzle__body { grid-template-columns: 1fr; } }

.grid__scroll { overflow-x: auto; padding-bottom: .4rem; }
.xw {
  display: grid; gap: 0; width: max-content;
  /* the floor is a tap target, not a type size: below about 22px a square is
     hard to hit with a thumb */
  --cell: clamp(1.4rem, 2.6vw, 2.1rem);
  background: rgba(70, 32, 58, .16);
  padding: 1px; border-radius: 2px; box-shadow: var(--shadow);
}
.xw__cell {
  position: relative; width: var(--cell); height: var(--cell);
  background: #FFFDFB; border: 0; margin: 0; padding: 0;
  outline: 1px solid rgba(70, 32, 58, .1); outline-offset: -1px;
  font-family: var(--sc-font-text); font-size: calc(var(--cell) * .58);
  font-weight: 500; line-height: 1; color: var(--sc-ink);
  display: grid; place-items: center; cursor: pointer;
}
.xw__cell--block { background: transparent; outline: 0; cursor: default; }
.xw__cell--in-entry { background: var(--pink); }
.xw__cell--active { background: var(--rose); }
.xw__cell--wrong { color: var(--sc-accent); text-decoration: line-through; }
.xw__cell:focus-visible { outline: 2px solid var(--sc-accent); outline-offset: -2px; z-index: 2; }
.xw__num {
  position: absolute; top: 1px; left: 2px;
  font-size: calc(var(--cell) * .3); line-height: 1; color: var(--sc-ink-soft);
  font-variant-numeric: tabular-nums; pointer-events: none;
}
.xw__cell--solved { background: #DFEAD8; }

.xw__input {                             /* keeps a soft keyboard available */
  position: absolute; opacity: 0; pointer-events: none; width: 1px; height: 1px;
}

.xw__bar {
  display: flex; flex-wrap: wrap; gap: var(--sc-3); align-items: center;
  margin-top: var(--sc-5);
}
.xw__btn {
  font-family: var(--sc-font-text); font-size: .74rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--sc-ink); background: #FFFDFB;
  border: 1px solid rgba(70, 32, 58, .22); border-radius: var(--sc-r-sm);
  padding: .58rem 1rem; cursor: pointer;
  transition: background 130ms var(--sc-ease-out), transform 100ms var(--sc-ease-out);
}
.xw__btn:hover { background: var(--sc-surface); }
.xw__btn:active { transform: translateY(1px); }
.xw__btn:focus-visible { outline: 2px solid var(--sc-accent); outline-offset: 2px; }
.xw__status { font-size: .82rem; color: var(--sc-ink-soft); margin: 0; }

.xw__current {
  position: sticky; top: 3.4rem; z-index: 1;
  padding: var(--sc-4) var(--sc-5); margin-bottom: var(--sc-5);
  background: var(--sc-surface); border-radius: var(--sc-r-sm);
  border-left: 1px solid var(--sc-accent);
}
.xw__current b {
  display: block; font-family: var(--sc-font-text); font-size: .68rem;
  font-weight: 600; letter-spacing: .18em; text-transform: uppercase;
  color: var(--sc-accent); margin-bottom: .3rem;
}
.xw__current span { font-size: .98rem; color: var(--sc-ink); line-height: 1.45; }

.clues { display: grid; gap: var(--sc-6); grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); }
.clues h3 {
  font-family: var(--sc-font-text); font-size: .68rem; font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase; color: var(--sc-ink-soft);
  margin: 0 0 var(--sc-4); padding-bottom: var(--sc-3);
  border-bottom: 1px solid rgba(70, 32, 58, .14);
}
.clues ol { list-style: none; margin: 0; padding: 0; }
.clue {
  display: flex; gap: .55rem; width: 100%; text-align: left;
  font-family: var(--sc-font-text); font-size: .87rem; line-height: 1.45;
  color: var(--sc-ink); background: none; border: 0; cursor: pointer;
  padding: .34rem .4rem; border-radius: 3px;
}
.clue:hover { background: var(--sc-surface); }
.clue[aria-current="true"] { background: var(--pink); }
.clue:focus-visible { outline: 2px solid var(--sc-accent); outline-offset: -2px; }
.clue.is-done { color: var(--sc-ink-soft); text-decoration: line-through; text-decoration-color: rgba(122, 74, 78, .5); }
.clue__n { font-variant-numeric: tabular-nums; color: var(--sc-accent); min-width: 1.4rem; }

/* solved */
.solved {
  margin-top: var(--sc-6); padding: var(--sc-6);
  background: #FFFCF9; border-radius: 3px; box-shadow: var(--shadow), var(--edge);
  text-align: center;
}
.solved[hidden] { display: none; }
.solved p:first-child {
  font-family: var(--sc-font-display); font-style: italic; font-size: 1.3rem;
  color: var(--sc-ink); margin: 0 0 var(--sc-3);
}
.solved p:last-child { font-size: .92rem; color: var(--sc-ink-soft); margin: 0; }

/* ═══ TYPE FLOOR ═══════════════════════════════════════════════════════════ */
/* light-on-dark compensation is not needed here: this page is dark-on-light */
h1, h2, h3 { text-wrap: balance; }
p { text-wrap: pretty; }
::selection { background: var(--pink); color: var(--sc-ink); }
