/* The desk's welcome rail.
 *
 * Owner review 2026-09-22: the first cut set the line loose on the wallpaper and
 * it read as text dropped in a corner, because everything else on this desk sits
 * on liquid glass and it did not. It is now the page's header object in the same
 * material as the panel beneath it -- .ws-liquid-glass, 24px radius, the same
 * hairline -- and it fills the same track, so the two stack instead of drifting.
 *
 * The motif moved from a small mark beside the words to a watermark riding the
 * right end, which is what gives the long empty half of the rail a reason to be
 * there. The motifs carry the studio's own sage and cream, so no second palette.
 *
 * No script: workspace-desk.js already publishes the live pane on
 * body[data-dash-pane], so the caption and the motif are selector work.
 */
.dash-greet {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 24px;
  padding: 16px 24px;
  color: var(--ink, #1c2218);
  /* A cream wash under the liquid gradients: the plate behind this strip is the
     busiest on the desk, and the line needs a clean bed to sit on. Still inside
     the 12-22% fill the desk glass works to. */
  background-color: color-mix(in srgb, var(--paper, #f2ead9) 20%, transparent);
  -webkit-backdrop-filter: var(--dash-blur, blur(22px) saturate(1.7));
  backdrop-filter: var(--dash-blur, blur(22px) saturate(1.7));
}

/* The motif fills the rail's empty half rather than crowding the words. */
.dash-greet-art {
  position: absolute;
  z-index: 0;
  inset: 9px 22px;
  background-position: left center, right center;
  background-repeat: no-repeat;
  /* Height-bound so each motif sits whole inside the rail: overflowing it reads
     as an accidental crop, not a flourish. */
  background-size: auto 78%, auto 78%;
  opacity: 0.34;
  pointer-events: none;
}

.dash-greet-copy {
  position: relative;
  z-index: 1;
  display: none;
  gap: 1px;
  min-width: 0;
  justify-items: center;
  text-align: center;
}
.dash-greet-copy cite {
  font-family: var(--sans, "DM Sans", sans-serif);
  font-size: 0.56rem;
  font-style: normal;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted, #6b7264);
  opacity: 0.85;
}
.dash-greet-copy small {
  font-family: var(--sans, "DM Sans", sans-serif);
  font-size: 0.6rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted, #6b7264);
}
/* The quote is set in Cormorant italic, which has a tall ascender and a deep
   descender, and it is clipped by `overflow: hidden` — which is here to give
   a long line its ellipsis, not to trim the type.
   Measured at 1440: font-size 25.92px, the face's own box asks for
   ascent 24 + descent 7 = 31px, and a 1.12 line-height gave it 29px. Two
   pixels short, which is exactly the top of an `l` and the tail of a `g`.
   So: a line-height that contains the face's box (1.32 = 34.2px, with room
   for a Georgia fallback whose box is deeper), and padding inside the clip
   with an equal negative margin outside it — the ink gets slack the overflow
   box never reaches, and the strip's layout height is still just the line.
   The glass plate keeps its own `overflow: hidden`; this is the text layer. */
.dash-greet-copy em {
  font-family: var(--serif, "Cormorant Garamond", Georgia, serif);
  font-size: 1.62rem;
  font-style: italic;
  font-weight: 500;
  line-height: 1.32;
  letter-spacing: -0.015em;
  padding-block: 0.16em;
  margin-block: -0.16em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body[data-dash-pane="home"] .dash-greet-copy[data-greet="home"] { display: grid; }
body[data-dash-pane="website"] .dash-greet-copy[data-greet="website"] { display: grid; }
body[data-dash-pane="intro"] .dash-greet-copy[data-greet="intro"] { display: grid; }
body[data-dash-pane="letter"] .dash-greet-copy[data-greet="letter"] { display: grid; }
body[data-dash-pane="card"] .dash-greet-copy[data-greet="card"] { display: grid; }
body[data-dash-pane="guests"] .dash-greet-copy[data-greet="guests"] { display: grid; }
body[data-dash-pane="rsvp"] .dash-greet-copy[data-greet="rsvp"] { display: grid; }
body[data-dash-pane="settings"] .dash-greet-copy[data-greet="settings"] { display: grid; }
body[data-dash-pane="account"] .dash-greet-copy[data-greet="account"] { display: grid; }
body[data-dash-pane="preview"] .dash-greet-copy[data-greet="preview"] { display: grid; }
/* Digital gifts is the second world on this desk; it gets its own line so the
   gift section never opens on a wedding epigraph. */
body[data-dash-pane="gifts"] .dash-greet-copy[data-greet="gifts"] { display: grid; }
body[data-dash-pane="giftsMine"] .dash-greet-copy[data-greet="giftsMine"] { display: grid; }
body[data-dash-pane="giftsBouquets"] .dash-greet-copy[data-greet="giftsBouquets"] { display: grid; }
body:not([data-dash-pane="home"]):not([data-dash-pane="website"]):not([data-dash-pane="intro"]):not([data-dash-pane="letter"]):not([data-dash-pane="card"]):not([data-dash-pane="guests"]):not([data-dash-pane="rsvp"]):not([data-dash-pane="settings"]):not([data-dash-pane="account"]):not([data-dash-pane="preview"]):not([data-dash-pane="gifts"]):not([data-dash-pane="giftsMine"]):not([data-dash-pane="giftsBouquets"]) .dash-greet-copy[data-greet="else"] { display: grid; }

body[data-dash-pane="home"] .dash-greet-art { background-image: url("../images/date.svg"), url("../images/date.svg"); }
body[data-dash-pane="website"] .dash-greet-art { background-image: url("../images/rings.svg"), url("../images/rings.svg"); }
body[data-dash-pane="intro"] .dash-greet-art { background-image: url("../images/doves.svg"), url("../images/doves.svg"); }
body[data-dash-pane="letter"] .dash-greet-art { background-image: url("../images/crest.svg"), url("../images/crest.svg"); }
body[data-dash-pane="card"] .dash-greet-art { background-image: url("../images/bouquet.svg"), url("../images/bouquet.svg"); }
body[data-dash-pane="guests"] .dash-greet-art { background-image: url("../images/crest.svg"), url("../images/crest.svg"); }
body[data-dash-pane="rsvp"] .dash-greet-art { background-image: url("../images/date.svg"), url("../images/date.svg"); }
body[data-dash-pane="settings"] .dash-greet-art { background-image: url("../images/rings.svg"), url("../images/rings.svg"); }
body[data-dash-pane="account"] .dash-greet-art { background-image: url("../images/doves.svg"), url("../images/doves.svg"); }
body[data-dash-pane="preview"] .dash-greet-art { background-image: url("../images/date.svg"), url("../images/date.svg"); }
body[data-dash-pane="gifts"] .dash-greet-art { background-image: url("../images/bow.svg"), url("../images/bow.svg"); }
body[data-dash-pane="giftsMine"] .dash-greet-art { background-image: url("../images/bouquet.svg"), url("../images/bouquet.svg"); }
body[data-dash-pane="giftsBouquets"] .dash-greet-art { background-image: url("../images/branch.svg"), url("../images/branch.svg"); }
body:not([data-dash-pane="home"]):not([data-dash-pane="website"]):not([data-dash-pane="intro"]):not([data-dash-pane="letter"]):not([data-dash-pane="card"]):not([data-dash-pane="guests"]):not([data-dash-pane="rsvp"]):not([data-dash-pane="settings"]):not([data-dash-pane="account"]):not([data-dash-pane="preview"]):not([data-dash-pane="gifts"]):not([data-dash-pane="giftsMine"]):not([data-dash-pane="giftsBouquets"]) .dash-greet-art { background-image: url("../images/doves.svg"), url("../images/doves.svg"); }

/* ── Digital gifts: one line, not a plate ─────────────────────────────────
   Owner review 2026-09-23: in the bouquet editor the epigraph took a 97px
   plate off the top of the stage, and the editor below is the surface that
   needs the height -- its canvas and the flower picker both scroll. So in the
   gifts world the rail becomes a single line: caption, quote and author on one
   baseline, the type a step down, the motif shorter. The material is the same
   glass; only its height changes. Same selector the brand copy already
   switches on, so a pane that moves between worlds moves the rail with it.
   Measured at 1280x800: 97px -> 40px, which the stage below gains. */
body[data-dash-world="gifts"] .dash-greet {
  padding: 8px 18px;
  border-radius: 18px;
}
body[data-dash-world="gifts"] .dash-greet-copy {
  grid-auto-flow: column;
  align-items: baseline;
  column-gap: 12px;
  row-gap: 0;
}
body[data-dash-world="gifts"] .dash-greet-copy small { font-size: 0.56rem; }
body[data-dash-world="gifts"] .dash-greet-copy em {
  font-size: 1.08rem;
  line-height: 1.32;
  min-width: 0;
}
body[data-dash-world="gifts"] .dash-greet-copy cite { font-size: 0.5rem; }
body[data-dash-world="gifts"] .dash-greet-art {
  inset: 4px 14px;
  background-size: auto 82%, auto 82%;
  opacity: 0.28;
}

/* The desk never reaches a phone -- the gate wants 960px in landscape -- and a
   narrow window keeps the old compact header. */
@media (max-width: 959px) {
  .dash-greet { display: none; }
}
/* Tablet landscape: the rail keeps its material, one step down in scale. */
@media (min-width: 960px) and (max-width: 1199px) {
  .dash-greet { padding: 14px 20px; }
  .dash-greet-copy em { font-size: 1.45rem; }
  .dash-greet-art { inset: 8px 18px; background-size: auto 74%, auto 74%; }
  body[data-dash-world="gifts"] .dash-greet { padding: 7px 16px; }
  body[data-dash-world="gifts"] .dash-greet-copy em { font-size: 1rem; }
  body[data-dash-world="gifts"] .dash-greet-art { inset: 4px 12px; background-size: auto 80%, auto 80%; }
}

/* Mount. The rail itself only fades: a transform on it would kill its own
   backdrop-filter, which is the lesson already written into the desk's page
   shell. The words and the motifs rise instead, a beat behind it, and the
   caption replays this whenever the pane changes because it is display:none
   until its page is live. */
@keyframes fw-greet-rail-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes fw-greet-child-in {
  from { opacity: 0; transform: translate3d(0, 10px, 0); }
  to { opacity: 1; transform: translate3d(0, 0, 0); }
}
@keyframes fw-greet-motif-in {
  from { opacity: 0; }
  to { opacity: 0.34; }
}
/* No fill mode and no delay, deliberately. `both` holds the from-state whenever
   the animation never advances -- an unfocused or throttled renderer -- and the
   rail would then sit at opacity 0 with nothing to show. Resting style is the
   visible one, so a suppressed animation costs the motion, never the content.
   The cascade comes from three durations starting together. */
.dash-greet {
  animation: fw-greet-rail-in var(--desk-enter, 280ms) var(--desk-ease-out, cubic-bezier(0.16, 1, 0.3, 1));
}
.dash-greet-copy[data-greet] {
  animation: fw-greet-child-in var(--desk-row-enter, 350ms) var(--desk-ease-out, cubic-bezier(0.16, 1, 0.3, 1));
}
.dash-greet-art {
  animation: fw-greet-motif-in 430ms var(--desk-ease-out, cubic-bezier(0.16, 1, 0.3, 1));
}

/* Reduced motion keeps the arrival legible without travel. */
@media (prefers-reduced-motion: reduce) {
  .dash-greet,
  .dash-greet-copy[data-greet],
  .dash-greet-art {
    animation-duration: 160ms;
  }
  /* Fade, never travel. */
  .dash-greet-copy[data-greet] { animation-name: fw-greet-rail-in; }
}
