/*
  milani - GILT NIGHTS. A dark editorial cover for her polished glam: a serif
  lowercase masthead with a gilt signature line, her photographs presented as
  framed prints, her destinations as a plain index, and one deep-red bar
  carrying her own phrase.

  Color jobs (one color, one job), extracted from her published photographs:

    token          value    job                                    contrast
    --ground       #0e0b0c  page ground                            -
    --ink          #f4ecef  reading text and the masthead          16.88:1 on ground
    --muted        #ccb4ab  secondary text (handles, footer)        9.97:1 on ground
    --gilt         #d4a253  signature lines and micro-labels        8.48:1 on ground
    --gilt-dim     #8a6b3f  frame hairlines and row rules           3.97:1 (non-text)
    --action       #a60f2d  the conversion bar, nowhere else       7.18:1 under on-action
    --action-hover #930b27  bar hover, one step deeper             8.45:1 under on-action
    --action-press #7d0a21  bar press, one step deeper again      10.11:1 under on-action
    --on-action    #fff5f2  text on the bar                        -
    --surface      #281a1c  index-row tint and the confirm card    14.42:1 under ink

  No status color: no live-status truth exists.

  Motion jobs, four total, everything else still:
    gilt-line     the masthead rule grows in once at load, left to right
    velvet-press  the bar deepens on hover and press, 120ms in / 240ms out
    row-light     index rows take a background tint, tint only
    confirm-fade  the age dialog enters as a centered card, fade plus 6px rise
  Photos never move: no selector in this file reaches an image. Base states
  below are fully composed (line at full width, text visible, dialog usable) so
  a visitor who asked for less motion loses only the interpolation, never a
  value. The motion layer at the end of this file holds the interpolation and
  the one entrance animation; the state values it smooths are composed here.
*/

/* ------------------------------------------------------------------ */
/* reset + ground                                                      */
/* ------------------------------------------------------------------ */

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

html {
  color-scheme: dark;
}

:root {
  --ground: #0e0b0c;
  --ink: #f4ecef;
  --muted: #ccb4ab;
  --gilt: #d4a253;
  --gilt-dim: #8a6b3f;
  --action: #a60f2d;
  --action-hover: #930b27;
  --action-press: #7d0a21;
  --on-action: #fff5f2;
  --surface: #281a1c;
  --serif: ui-serif, "New York", Georgia, "Times New Roman", serif;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
}

body {
  background: var(--ground);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.5;
  min-height: 100svh;
}

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

/* skip link */
.skip-link {
  background: var(--ink);
  border-radius: 4px;
  color: var(--ground);
  font-weight: 600;
  left: 12px;
  padding: 12px 18px;
  position: absolute;
  top: 12px;
  transform: translateY(-220%);
  z-index: 10;
}

.skip-link:focus-visible {
  transform: translateY(0);
}

/* focus discipline: 3px ink ring outside the control, never the action color */
:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
}

/* ------------------------------------------------------------------ */
/* masthead-hero                                                       */
/* ------------------------------------------------------------------ */

/* One grid at both breakpoints. The tagline and the bar live inside
   .masthead__rail so the desktop grid can hand them a single right-hand
   column; on mobile the wrapper is display: contents and the named areas set
   the composition, so there is one DOM order for both. */
.masthead {
  display: grid;
  grid-template-areas:
    "name"
    "line"
    "tagline"
    "photo"
    "bar";
  grid-template-columns: minmax(0, 1fr);
  padding: clamp(1.1rem, 4.5vw, 2.5rem);
  padding-block-start: clamp(2rem, 6svh, 3.5rem);
}

.masthead__name {
  color: var(--ink);
  font-family: var(--serif);
  font-size: clamp(4.4rem, 20vw, 6rem);
  font-weight: 600;
  grid-area: name;
  letter-spacing: -0.015em;
  line-height: 0.9;
}

/* the signature line: the page's single arrival gesture. Full width at rest,
   so nothing is stranded if the animation never runs. */
.masthead__line {
  background: var(--gilt);
  grid-area: line;
  height: 3px;
  margin-block: 0.9rem 0.7rem;
  width: 100%;
}

.masthead__rail {
  display: contents;
}

.masthead__tagline {
  color: var(--gilt);
  font-family: var(--sans);
  font-size: 0.82rem;
  grid-area: tagline;
  letter-spacing: 0.14em;
  margin-block-end: 1rem;
  text-transform: uppercase;
}

/* ------------------------------------------------------------------ */
/* framed prints: the photographs, hung                                */
/* ------------------------------------------------------------------ */

/* the gilt hairline is the frame; there is no mat, no shadow, no lift */
.print {
  border: 1px solid var(--gilt-dim);
  border-radius: 4px;
  overflow: hidden;
  padding: 0;
}

.print img {
  display: block;
  height: auto;
  width: 100%;
}

.print--hero {
  grid-area: photo;
}

.print--hero img {
  height: clamp(300px, 54svh, 540px);
  object-fit: cover;
  object-position: 50% 12%;
}

/* ------------------------------------------------------------------ */
/* the conversion bar: the only red on the page                        */
/* ------------------------------------------------------------------ */

.bar {
  align-items: center;
  background: var(--action);
  border-radius: 4px;
  color: var(--on-action);
  display: flex;
  font-size: 1.06rem;
  font-weight: 650;
  justify-content: center;
  letter-spacing: 0.02em;
  margin-block-start: 0.9rem;
  min-height: 58px;
  text-decoration: none;
}

.masthead .bar {
  grid-area: bar;
}

/* ------------------------------------------------------------------ */
/* portrait-gallery                                                    */
/* ------------------------------------------------------------------ */

.gallery {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding-block: clamp(2.4rem, 7svh, 4.25rem);
  padding-inline: clamp(1.1rem, 4.5vw, 2.5rem);
}

.gallery__link {
  color: inherit;
  display: block;
  text-decoration: none;
}

.gallery__link:focus-visible {
  outline: 3px solid var(--gilt);
  outline-offset: 4px;
}

.gallery .print {
  align-self: start;
  width: 100%;
}

/* ------------------------------------------------------------------ */
/* destinations-index                                                  */
/* ------------------------------------------------------------------ */

.find {
  padding-block: 1rem 3rem;
  padding-inline: clamp(1.1rem, 4.5vw, 2.5rem);
}

.find__label {
  color: var(--gilt);
  font-family: var(--sans);
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  margin-block-end: 0.6rem;
  text-transform: uppercase;
}

.find__rows {
  list-style: none;
  margin: 0;
  padding: 0;
}

.find__row {
  align-items: center;
  border-block-start: 1px solid var(--gilt-dim);
  display: flex;
  justify-content: space-between;
  min-height: 56px;
  padding-inline: 0.4rem;
  text-decoration: none;
}

.find__rows li:last-child .find__row {
  border-block-end: 1px solid var(--gilt-dim);
}

.find__platform {
  color: var(--ink);
  font-weight: 600;
}

.find__handle {
  color: var(--muted);
  font-family: var(--sans);
  font-size: 0.95rem;
}

/* ------------------------------------------------------------------ */
/* closer-bookend: the masthead again, quiet                           */
/* ------------------------------------------------------------------ */

.bookend {
  padding-block: clamp(3.5rem, 8svh, 5.5rem);
  padding-inline: clamp(1.1rem, 4.5vw, 2.5rem);
  text-align: center;
}

.bookend__name {
  color: var(--ink);
  font-family: var(--serif);
  font-size: 2rem;
  line-height: 1.1;
}

/* the bookend line is static by contract: the arrival gesture happens once,
   at the top of the page, and is never repeated down here */
.bookend__line {
  background: var(--gilt);
  height: 3px;
  margin-block: 0.8rem;
  margin-inline: auto;
  width: 72px;
}

.bookend__handle {
  color: var(--muted);
  font-size: 0.95rem;
  margin-block-end: 1.4rem;
}

.bookend .bar {
  margin-inline: auto;
  max-width: 26rem;
}

/* ------------------------------------------------------------------ */
/* footer: utility only, quiet                                         */
/* ------------------------------------------------------------------ */

.site-footer {
  display: flex;
  justify-content: center;
  padding: 1.25rem 1.25rem 2.5rem;
}

.site-footer button {
  background: none;
  border: 1px solid var(--muted);
  border-radius: 999px;
  color: var(--muted);
  cursor: pointer;
  font: inherit;
  font-size: 0.9rem;
  min-height: 44px;
  padding: 0.6rem 1.4rem;
}

/* ------------------------------------------------------------------ */
/* interactive states: values, not motion                              */
/* ------------------------------------------------------------------ */

/* These are state feedback, so they are composed here rather than in the
   motion layer: a visitor who asked for reduced motion still gets the deeper
   red, the press dip, and the row tint, just instantly. Only the transitions
   that smooth them live under the motion gate. Hover stays behind real hover,
   and each :active follows its :hover because the two tie on specificity. */
@media (hover: hover) {
  .bar:hover {
    background-color: var(--action-hover);
  }

  .find__row:hover {
    background-color: var(--surface);
  }
}

/* velvet-press: the press value, deeper still, plus the smallest honest dip.
   No overshoot, no lift, no shadow. */
.bar:active {
  background-color: var(--action-press);
  transform: scale(0.995);
}

/* row-light: tint only. A row of links must never behave like the one action. */
.find__row:active {
  background-color: var(--surface);
}

/* ------------------------------------------------------------------ */
/* the quiet confirmation room (members page and dialog)               */
/* ------------------------------------------------------------------ */

.confirm-room {
  align-items: center;
  display: flex;
  justify-content: center;
  min-height: 100svh;
  padding: 1rem;
}

.confirm,
.age-dialog {
  background: var(--surface);
  border: 1px solid var(--gilt-dim);
  border-radius: 4px;
  color: var(--ink);
  max-width: 24rem;
  padding: 1.75rem 1.5rem;
  width: 100%;
}

.confirm__name,
.age-dialog__name {
  color: var(--muted);
  font-size: 0.95rem;
}

.confirm__title,
.age-dialog h2 {
  font-family: var(--serif);
  font-size: 1.4rem;
  font-weight: 600;
  margin-block: 0.25rem 1rem;
}

.form-error {
  color: var(--ink);
  font-weight: 600;
  margin-block-end: 0.75rem;
}

/* the checkbox stays the real control: a 44px invisible hit area over a
   painted box, so the touch floor holds without replacing the input */
.confirm label,
.age-dialog label {
  align-items: center;
  display: flex;
  min-height: 44px;
  padding-inline-start: 2.6rem;
  position: relative;
}

.confirm input[type="checkbox"],
.age-dialog input[type="checkbox"] {
  cursor: pointer;
  height: 44px;
  inset-block-start: 50%;
  inset-inline-start: 0;
  margin: 0;
  opacity: 0;
  position: absolute;
  translate: 0 -50%;
  width: 44px;
}

.confirm label span,
.age-dialog label span {
  display: block;
}

.confirm label span::before,
.age-dialog label span::before {
  border: 2px solid var(--ink);
  border-radius: 4px;
  content: "";
  height: 1.35rem;
  inset-block-start: 50%;
  inset-inline-start: 0.6rem;
  position: absolute;
  translate: 0 -50%;
  width: 1.35rem;
}

.confirm input[type="checkbox"]:checked ~ span::before,
.age-dialog input[type="checkbox"]:checked ~ span::before {
  background: var(--ink);
}

/* the check mark is two borders, no glyph, so it survives any font */
.confirm input[type="checkbox"]:checked ~ span::after,
.age-dialog input[type="checkbox"]:checked ~ span::after {
  border-block-end: 3px solid var(--surface);
  border-inline-start: 3px solid var(--surface);
  content: "";
  height: 0.3rem;
  inset-block-start: calc(50% - 0.1rem);
  inset-inline-start: 0.92rem;
  position: absolute;
  rotate: -48deg;
  translate: 0 -50%;
  width: 0.62rem;
}

.confirm input[type="checkbox"]:focus-visible ~ span::before,
.age-dialog input[type="checkbox"]:focus-visible ~ span::before {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
}

/* the confirmation room is a quiet room: the red bar belongs to the landing
   surface, so this submit stays ink on ground */
.confirm button[type="submit"],
.age-dialog button[type="submit"] {
  background: var(--ink);
  border: 0;
  border-radius: 999px;
  color: var(--ground);
  cursor: pointer;
  display: block;
  font: inherit;
  font-weight: 700;
  margin-block-start: 1.1rem;
  min-height: 44px;
  padding: 0.75rem 1.5rem;
}

.confirm a {
  align-items: center;
  color: var(--muted);
  display: inline-flex;
  margin-block-start: 1rem;
  margin-inline-start: -0.75rem;
  min-height: 44px;
  min-width: 44px;
  padding-inline: 0.75rem;
}

.age-dialog__close {
  background: none;
  border: 0;
  color: var(--muted);
  cursor: pointer;
  float: right;
  font: inherit;
  min-height: 44px;
  padding: 0.4rem 0.8rem;
}

/* dialog placement: one centered card at every width. Fixed positioning keeps
   the geometry identical whether the dialog is in the top layer (showModal) or
   merely [open] in a QA render. */
.age-dialog {
  height: fit-content;
  inset: 0;
  margin: auto;
  max-width: 24rem;
  position: fixed;
  width: calc(100% - 2rem);
}

.age-dialog::backdrop {
  background: rgba(6, 3, 5, 0.72);
}

/* ------------------------------------------------------------------ */
/* desktop: the masthead crown, then the photo and its rail             */
/* ------------------------------------------------------------------ */

@media (min-width: 960px) {
  /* the name and the line cross the full page; below them the photograph
     takes the wide column and the rail answers from the narrow one. The rail
     stretches to the photograph's full height and centers its pair against it,
     so the tagline and the bar sit level with the print instead of stranding an
     empty cell beneath them. */
  .masthead {
    align-items: start;
    column-gap: clamp(2.5rem, 5vw, 5rem);
    grid-template-areas:
      "name  name"
      "line  line"
      "photo rail";
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
  }

  .masthead__name {
    font-size: clamp(7rem, 11vw, 10rem);
  }

  /* the rail becomes a real box on desktop, so the tagline and the bar stack
     inside the narrow column instead of taking their own page rows. It fills
     the photograph's row and centers the pair vertically; the gap is the only
     spacing between them, so the bar drops its own top margin here. */
  .masthead__rail {
    align-self: stretch;
    display: flex;
    flex-direction: column;
    gap: 1.4rem;
    grid-area: rail;
    justify-content: center;
  }

  .masthead__tagline {
    font-size: 1rem;
  }

  .masthead .bar {
    margin-block-start: 0;
    max-width: 26rem;
    width: 100%;
  }

  .print--hero img {
    height: min(84svh, 880px);
  }

  .gallery {
    align-items: start;
    display: grid;
    gap: 1.2rem;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin-inline: auto;
    max-width: 1240px;
  }

  .find {
    margin-inline: auto;
    max-width: 1240px;
  }

  .find__rows {
    max-width: 760px;
  }
}

/* ------------------------------------------------------------------ */
/* forced colors: the frames, the bar, and the rows keep honest edges   */
/* ------------------------------------------------------------------ */

@media (forced-colors: active) {
  /* forced colors leaves photographs painted, so the frames need real borders
     rather than a substitute */
  .print {
    border: 1px solid CanvasText;
  }

  .confirm,
  .age-dialog {
    border: 1px solid CanvasText;
  }

  /* the gilt rules are backgrounds, which forced colors flattens; CanvasText
     keeps both of them visible as rules */
  .masthead__line,
  .bookend__line {
    background: CanvasText;
  }

  .bar,
  .confirm button[type="submit"],
  .age-dialog button[type="submit"],
  .site-footer button {
    border: 2px solid ButtonText;
  }

  .find__row {
    border: 1px solid LinkText;
  }

  /* the painted checkbox box takes system colors; the real input stays the
     44px control underneath */
  .confirm label span::before,
  .age-dialog label span::before {
    background: Canvas;
    border-color: ButtonText;
  }

  .confirm input[type="checkbox"]:checked ~ span::before,
  .age-dialog input[type="checkbox"]:checked ~ span::before {
    background: SelectedItem;
    forced-color-adjust: none;
  }

  .confirm input[type="checkbox"]:checked ~ span::after,
  .age-dialog input[type="checkbox"]:checked ~ span::after {
    border-color: SelectedItemText;
    forced-color-adjust: none;
  }
}

/* ================================================================== */
/* MOTION LAYER. Contract: every animation and transition for the four  */
/* jobs lives inside the single motion gate below. The state values they */
/* smooth are composed above, so a reduced-motion visitor still gets the */
/* deeper red, the press dip, and the row tint as instant changes. No    */
/* selector below reaches a photograph or an image of any kind, by       */
/* construction. The bookend line is absent by design: the lights come    */
/* up once. A reduce clamp closes the file.                              */
/* ================================================================== */

@media (prefers-reduced-motion: no-preference) {
  /* gilt-line: the masthead rule grows in once, left to right, and then the
     page is still for good. The only animation on the landing surface. */
  @keyframes milani-gilt-line {
    from {
      transform: scaleX(0);
    }

    to {
      transform: scaleX(1);
    }
  }

  /* confirm-fade: the age dialog enters as a centered card at every width */
  @keyframes milani-confirm-fade {
    from {
      opacity: 0.01;
      transform: translateY(6px);
    }

    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  .masthead__line {
    animation: milani-gilt-line 420ms ease-out both;
    transform-origin: left;
  }

  /* velvet-press: the release is the slow half, so the base transition is the
     long one and the press-in overrides it below */
  .bar {
    transition: background-color 240ms ease, transform 240ms ease;
  }

  /* the press-in is faster than the release; it ties any hover rule on
     specificity, so it stays after them */
  .bar:active {
    transition: background-color 120ms ease, transform 120ms ease;
  }

  /* row-light */
  .find__row {
    transition: background-color 160ms ease;
  }

  .age-dialog[open] {
    animation: milani-confirm-fade 160ms ease-out both;
  }
}

/* the clamp: anything that slipped through is reduced to nothing */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
