/* ── The desk on a phone held upright ────────────────────────────────────
   Owner, 2026-09-25: couples must be able to make their wedding on a phone in
   portrait. This is the same desk, not a second app: the same panes, panels and
   send gates, laid out for a narrow screen and moved between from the top.

   Every rule is keyed off html[data-desk-device="phone"], which
   dashboard-device-gate.js sets only for a phone upright (or a window under
   600px held tall). A computer, an iPad, and anything in landscape never match
   it, so their layout is exactly what it was. The sheet loads last so an equal
   specificity rule elsewhere cannot win on a phone. */

/* ── Top bar: the public site's two glass rows ───────────────────────────── */
html[data-desk-device="phone"] .view-dashboard {
  --phone-glass-edge: color-mix(in srgb, #ffffff 42%, transparent);
  --phone-glass:
    linear-gradient(180deg, rgba(255, 253, 248, 0.34), rgba(246, 239, 230, 0.16));
  --phone-glass-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.48),
    0 10px 28px rgba(16, 12, 10, 0.12);
}
html[data-desk-device="phone"] #view-dashboard .dash-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 52px;
  grid-template-rows: auto auto;
  gap: 8px;
  align-items: center;
  /* Clear of the notch, the rounded corners and the home indicator whenever
     the page runs edge to edge (viewport-fit=cover); 0 otherwise. */
  padding:
    max(10px, env(safe-area-inset-top))
    max(12px, env(safe-area-inset-right))
    8px
    max(12px, env(safe-area-inset-left));
}
html[data-desk-device="phone"] .dash-top > .dash-greet { display: none; }
/* The account pane hides the strip on a desk; on a phone the strip is the
   navigation, so it stays. */
html[data-desk-device="phone"] body[data-dash-pane="account"] #view-dashboard .dash-top { display: grid; }
/* The markup carries `hidden` so no other screen ever shows these; the
   studio's `[hidden] { display: none !important }` is answered in kind. */
html[data-desk-device="phone"] .dash-phone-brand[hidden],
html[data-desk-device="phone"] .dash-phone-brand {
  grid-column: 1;
  grid-row: 1;
  display: flex !important;
  align-items: center;
  gap: 10px;
  min-width: 0;
  min-height: 52px;
  padding: 0 16px 0 10px;
  border: 1px solid var(--phone-glass-edge);
  border-radius: 999px;
  background: var(--phone-glass);
  box-shadow: var(--phone-glass-shadow);
  backdrop-filter: blur(18px) saturate(1.2);
  -webkit-backdrop-filter: blur(18px) saturate(1.2);
  color: var(--ink);
  text-decoration: none;
}
html[data-desk-device="phone"] .dash-phone-mark {
  display: grid;
  flex: 0 0 32px;
  width: 32px;
  height: 32px;
  overflow: hidden;
  border-radius: 10px;
}
html[data-desk-device="phone"] .dash-phone-mark img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
html[data-desk-device="phone"] .dash-phone-brand-copy {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  white-space: nowrap;
}
html[data-desk-device="phone"] .dash-phone-brand-copy strong {
  font-family: var(--serif);
  font-size: 1.4rem;
  font-style: italic;
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1;
}
html[data-desk-device="phone"] .dash-phone-brand-copy small {
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 0.6rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}
html[data-desk-device="phone"] #dashMenu {
  grid-column: 2;
  grid-row: 1;
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  margin: 0;
  border: 1px solid var(--phone-glass-edge);
  background: var(--phone-glass);
  box-shadow: var(--phone-glass-shadow);
  backdrop-filter: blur(18px) saturate(1.2);
  -webkit-backdrop-filter: blur(18px) saturate(1.2);
}
html[data-desk-device="phone"] .dash-phone-nav[hidden],
html[data-desk-device="phone"] .dash-phone-nav {
  grid-column: 1 / -1;
  grid-row: 2;
  display: grid !important;
  grid-template-columns: 1fr 0.8fr 1.3fr;
  gap: 2px;
  min-width: 0;
  padding: 3px;
  border: 1px solid var(--phone-glass-edge);
  border-radius: 999px;
  background: var(--phone-glass);
  box-shadow: var(--phone-glass-shadow);
  backdrop-filter: blur(18px) saturate(1.2);
  -webkit-backdrop-filter: blur(18px) saturate(1.2);
}
html[data-desk-device="phone"] .dash-phone-nav a {
  display: grid;
  place-items: center;
  min-width: 0;
  min-height: 44px;
  padding: 0 6px;
  border-radius: 999px;
  color: color-mix(in srgb, var(--ink) 72%, transparent);
  font-family: var(--sans);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  line-height: 1.1;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background-color var(--desk-hover, 160ms) ease, color var(--desk-hover, 160ms) ease;
  -webkit-tap-highlight-color: transparent;
}
html[data-desk-device="phone"] .dash-phone-nav a i { display: none; }
html[data-desk-device="phone"] .dash-phone-nav[data-world="gifts"] { grid-template-columns: 1.4fr 1fr 1fr; }

/* One section at a time: Wedding invites or Digital gifts, from
   body[data-dash-world], which the view boot writes before first paint (so
   /dashboard/gifts/* never flashes the wedding tabs) and every pane change
   keeps current. The drawer stays the way across. */
html[data-desk-device="phone"] body[data-dash-world="gifts"] .dash-phone-nav[data-world="wedding"],
html[data-desk-device="phone"] body:not([data-dash-world="gifts"]) .dash-phone-nav[data-world="gifts"] {
  display: none !important;
}
html[data-desk-device="phone"] body[data-dash-world="gifts"] .dash-phone-brand-copy[data-world="wedding"],
html[data-desk-device="phone"] body:not([data-dash-world="gifts"]) .dash-phone-brand-copy[data-world="gifts"] {
  display: none;
}
html[data-desk-device="phone"] .dash-phone-nav a[aria-current="page"] {
  background: color-mix(in srgb, #fffdf8 70%, transparent);
  box-shadow: 0 2px 8px rgba(37, 53, 35, 0.08);
  color: var(--ink);
}
html[data-desk-device="phone"] .dash-phone-nav a:active { background: color-mix(in srgb, #fffdf8 50%, transparent); }
html[data-desk-device="phone"] .dash-phone-nav a:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* The drawer opens from the menu disc and holds the rest: Digital gifts, the
   account, and the legal pages. It covers the top bar and every pane while
   open. The gift desk's loading curtain is z-index 40 inside its stage; the
   stage is isolated on a phone so that number stays inside it (owner review:
   the curtain painted over the open drawer on Digital gifts). */
html[data-desk-device="phone"] .dash-nav { z-index: 60; }
html[data-desk-device="phone"] .dash-nav-scrim { z-index: 59; }
html[data-desk-device="phone"] .ws-gift-stage { isolation: isolate; }

/* ── One scroller under the bar ─────────────────────────────────────────── */
html[data-desk-device="phone"] .dash-main,
html[data-desk-device="phone"] body[data-dash-pane] .dash-main {
  display: block;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding:
    4px
    max(12px, env(safe-area-inset-right))
    calc(28px + env(safe-area-inset-bottom))
    max(12px, env(safe-area-inset-left));
}
/* Gifts keep their framed compose desk, which fills the stage itself. */
html[data-desk-device="phone"] body[data-dash-pane="gifts"] .dash-main,
html[data-desk-device="phone"] body[data-dash-pane="giftsMine"] .dash-main,
html[data-desk-device="phone"] body[data-dash-pane="giftsBouquets"] .dash-main {
  display: grid;
  overflow: hidden;
}
html[data-desk-device="phone"] .wedding-margin-art { display: none; }

/* ── Editors: the design on top, everything to change below it ──────────── */
html[data-desk-device="phone"] .dash-pane.dash-editor {
  display: block;
  height: auto;
  min-height: 0;
  max-height: none;
  overflow: visible;
}
html[data-desk-device="phone"] .dash-pane.dash-editor[hidden] { display: none !important; }
html[data-desk-device="phone"] .dash-editor .ed-split,
html[data-desk-device="phone"] .dash-editor .ed-split-flow {
  display: flex;
  flex-direction: column;
  gap: 12px;
  height: auto;
  min-height: 0;
  max-height: none;
  overflow: visible;
  grid-template-rows: none;
}
html[data-desk-device="phone"] .dash-editor .ed-split-flow > * { flex-shrink: 0; }
html[data-desk-device="phone"] .dash-editor .ed-split-flow > .ed-preview {
  order: -1;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  min-height: 0;
  height: auto;
  overflow: visible;
  background: transparent;
}
/* The canvases are sized by id on the desk (height: 100% of their grid row),
   so the phone answers by id too. The desk's fit code scales the artboard to
   whatever box this gives it. */
html[data-desk-device="phone"] .dash-editor .ed-canvas,
html[data-desk-device="phone"] :is(#wsLetterCanvas, #wsSiteCanvas, #wsCardCanvas, #wsRsvpCanvas) {
  position: relative;
  flex: none;
  width: 100%;
  height: min(60svh, 560px);
  min-height: 320px;
}
html[data-desk-device="phone"] .dash-editor .ed-split-flow > .ed-panel {
  height: auto;
  max-height: none;
  min-height: 0;
  overflow: visible;
  padding: 14px;
  border-radius: 24px;
}
html[data-desk-device="phone"] .dash-editor .ed-panel-scroll {
  height: auto;
  max-height: none;
  overflow: visible;
}

/* The preview's bar: device or size tabs on their own row, the page capsule
   and Unlock & send below, nothing clipped at 375px. */
html[data-desk-device="phone"] .dash-editor .ed-bar {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px;
  min-width: 0;
}
html[data-desk-device="phone"] .dash-editor .ed-bar .ed-devices {
  flex: 1 1 100%;
  display: flex;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
html[data-desk-device="phone"] .dash-editor .ed-bar .ed-devices::-webkit-scrollbar { display: none; }
html[data-desk-device="phone"] .dash-editor .ed-bar .ed-devices button {
  flex: 1 1 0;
  min-width: 0;
  min-height: 44px;
  white-space: nowrap;
}
html[data-desk-device="phone"] .dash-editor .ed-bar-actions {
  display: flex;
  flex: 1 1 auto;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
  margin-left: auto;
}
html[data-desk-device="phone"] .dash-editor .ed-bar-actions .btn {
  min-height: 44px;
}

/* The letter and the website preview as a phone guest sees them (see
   deskPreviewDevice in workspace-desk.js), so their frame tabs go. The card
   keeps its size tabs: those choose the saved image's shape. The page capsule
   and Unlock & send then share one row. */
html[data-desk-device="phone"] .dash-pane:is([data-pane="letter"], [data-pane="website"]) .ed-bar .ed-devices { display: none; }
html[data-desk-device="phone"] .dash-editor .ed-bar .fw-pager {
  flex: 0 1 auto;
  min-width: 0;
  margin: 0;
}
html[data-desk-device="phone"] .dash-editor .ed-bar .ed-bar-actions {
  flex: 0 0 auto;
  width: auto;
  max-width: 100%;
}
html[data-desk-device="phone"] .dash-editor .ed-bar .ed-bar-actions .js-ws-send {
  width: auto;
  min-width: 96px;
  padding-inline: 20px;
}
/* One row, whatever the button says: "Unlock & send" is wider than "Send",
   and the capsule used to keep its full width, so the button dropped to a
   row of its own (owner, 2026-09-28). The capsule gives way and scrolls. */
html[data-desk-device="phone"] .dash-pane:is([data-pane="letter"], [data-pane="website"]) .ed-bar {
  flex-wrap: nowrap;
  align-items: center;
}
html[data-desk-device="phone"] .dash-pane:is([data-pane="letter"], [data-pane="website"]) .ed-bar .fw-pager {
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
html[data-desk-device="phone"] .dash-pane:is([data-pane="letter"], [data-pane="website"]) .ed-bar .fw-pager::-webkit-scrollbar { display: none; }
html[data-desk-device="phone"] .dash-pane:is([data-pane="letter"], [data-pane="website"]) .ed-bar .ed-bar-actions {
  flex: 0 0 auto;
  flex-wrap: nowrap;
}
html[data-desk-device="phone"] .dash-pane:is([data-pane="letter"], [data-pane="website"]) .ed-bar .ed-bar-actions .js-ws-send {
  white-space: nowrap;
  padding-inline: 16px;
}

/* ── The invitation collection and the guest preview: full-screen sheets ── */
html[data-desk-device="phone"] :is(.fw-design-collection, .fw-guest-experience) {
  width: 100vw;
  max-width: 100vw;
  height: 100dvh;
  max-height: 100dvh;
  margin: 0;
  padding:
    0
    max(16px, env(safe-area-inset-right))
    calc(24px + env(safe-area-inset-bottom))
    max(16px, env(safe-area-inset-left));
  border: 0;
  border-radius: 0;
  scrollbar-gutter: auto;
}
html[data-desk-device="phone"] :is(.fw-design-collection, .fw-guest-experience) .fw-dialog-heading {
  position: sticky;
  top: 0;
  z-index: 2;
  margin: 0 -16px 16px;
  padding: max(16px, env(safe-area-inset-top)) 16px 14px;
  background: linear-gradient(180deg, #fff6e9 82%, color-mix(in srgb, #fff6e9 0%, transparent));
}
html[data-desk-device="phone"] :is(.fw-design-collection, .fw-guest-experience) .fw-dialog-heading h2 { font-size: 32px; }
/* Below 700px the desk turned the collection into a two-row sideways
   carousel, which hid most of the 33 designs off to the right. On a phone
   upright it is a plain two-column grid that scrolls down, so every design is
   one thumb-scroll away. */
html[data-desk-device="phone"] .fw-design-collection .fw-design-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: none;
  grid-auto-flow: row;
  grid-auto-columns: auto;
  gap: 18px 12px;
  overflow: visible;
  scroll-snap-type: none;
  padding: 0;
}
html[data-desk-device="phone"] .fw-design-collection .fw-design-art {
  height: auto;
  aspect-ratio: 1;
}
html[data-desk-device="phone"] .fw-design-collection .fw-design-card-copy { padding-top: 8px; }
html[data-desk-device="phone"] .fw-design-collection .fw-design-card-copy small {
  font-size: 9px;
  letter-spacing: 0.14em;
  overflow-wrap: anywhere;
}
html[data-desk-device="phone"] .fw-design-collection .fw-design-card-copy strong { font-size: 21px; }
html[data-desk-device="phone"] .fw-guest-experience .fw-guest-toolbar { flex-wrap: wrap; }
html[data-desk-device="phone"] .fw-guest-experience .fw-guest-devices { flex: 1 1 100%; }
html[data-desk-device="phone"] .fw-guest-experience .fw-guest-devices button { flex: 1 1 0; }
html[data-desk-device="phone"] .fw-guest-experience .fw-guest-stage { min-height: 60dvh; }

/* ── Touch targets: 44px on everything the couple taps ─────────────────── */
html[data-desk-device="phone"] .dash-editor .fw-pager button,
html[data-desk-device="phone"] .dash-editor .fw-pager a {
  min-width: 44px;
  min-height: 44px;
}
html[data-desk-device="phone"] .dash-nav-foot a {
  display: flex;
  align-items: center;
  min-height: 44px;
}
html[data-desk-device="phone"] .desk-select-trigger,
html[data-desk-device="phone"] #view-dashboard select:not(.desk-select-native),
html[data-desk-device="phone"] #view-dashboard input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]) {
  min-height: 44px;
}
html[data-desk-device="phone"] #view-dashboard .ed-panel a:not(.btn):not([class*="fw-"]) {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* ── Guest & Send: the design tiles as a grid ───────────────────────────
   Below 700px the desk laid these out as a two-row sideways strip whose last
   column was cut at the edge ("Br…"). On a phone upright they are a plain
   two-column grid, every tile whole. */
html[data-desk-device="phone"] #wsGeneralSend .ws-send-opts {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: none;
  grid-auto-flow: row;
  grid-auto-columns: auto;
  gap: 16px 12px;
  overflow: visible;
  scroll-snap-type: none;
  padding: 4px;
}
html[data-desk-device="phone"] #wsGeneralSend .ws-send-opt-ring {
  height: auto;
  aspect-ratio: 4 / 3;
}

/* ── Intro tiles: the art fills its frame ───────────────────────────────
   The openings' posters are landscape stills (about 16:9). On a desk the
   catalog frames them in a tall box with object-fit: contain, which on a
   390px phone left each poster floating in ~60% blank cream. On a phone the
   frame takes the poster's own shape and the art covers it; the frame is
   reserved by aspect-ratio before the image arrives, so nothing jumps. */
html[data-desk-device="phone"] #view-dashboard #wsIntroCatalog .ws-intro-option img {
  display: block;
  flex: none;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  object-position: center;
  border-radius: 13px;
  background: #f2ead9;
}

/* ── The open drawer holds the scroll ──────────────────────────────────
   Owner review on an iPhone: with the menu open, the page behind must stay
   still and only the drawer may scroll. The scroller behind is frozen with
   overflow: hidden, which keeps its scrollTop, so closing the drawer returns
   the couple to exactly where they were. The drawer's list is its scroller
   (the drawer itself carries the frost layer and stays put), contained so its
   ends never chain to the page; the scrim takes no pan at all. studio.js
   cancels the drags iOS would otherwise turn into a viewport rubber-band. */
html[data-desk-device="phone"] body.dash-nav-open {
  overflow: hidden;
  overscroll-behavior: none;
}
html[data-desk-device="phone"] body.dash-nav-open .dash-main {
  overflow: hidden;
  overscroll-behavior: none;
  touch-action: none;
}
html[data-desk-device="phone"] .dash-nav-scrim {
  touch-action: none;
  overscroll-behavior: none;
}
html[data-desk-device="phone"] .dash-nav {
  overscroll-behavior: contain;
}
html[data-desk-device="phone"] .dash-nav .dash-nav-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

/* ── No zoom on focus ───────────────────────────────────────────────────
   iOS Safari zooms the page into any form field set under 16px, and does not
   zoom back out; the sign-in fields (11px), the guest search (14px) and the
   selects (13.3px) all did, which threw the layout sideways mid-sign-in on the
   owner's iPhone. On a phone every field reads at least 16px. The second selector
   outranks id-scoped sizes such as `#view-dashboard .ws-filters .ws-search
   input`, which kept the guest search at 14px and still zoomed Guest & Send
   sideways (owner, 2026-10-02). */
html[data-desk-device="phone"] :is(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]), select, textarea),
html[data-desk-device="phone"] :is(#view-dashboard, #create) :is(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]), select, textarea) {
  font-size: max(16px, 1em);
}
/* The letter pane sized itself to the bar (443px in a 351px column) because the
   pane and preview kept min-width:auto, so nothing ever made the pager shrink. */
html[data-desk-device="phone"] .dash-pane:is([data-pane="letter"], [data-pane="website"]),
html[data-desk-device="phone"] .dash-pane:is([data-pane="letter"], [data-pane="website"]) :is(.ed-split, .ed-preview, .ed-bar) { min-width: 0; max-width: 100%; }
html[data-desk-device="phone"] .dash-pane:is([data-pane="letter"], [data-pane="website"]) .ed-preview { flex: 0 1 auto; }
html[data-desk-device="phone"] .dash-pane:is([data-pane="letter"], [data-pane="website"]) .ed-bar .fw-pager button { flex: 0 0 auto; }

/* Inside the Flowers app (owner, 2026-09-28). The app opens the gift desk in
   its own WebView under its own toolbar and close button, and Garden already
   carries My gifts and Bouquets, so Create's header, rail and tabs stay out.
   `data-native-app` is set by the app before first paint and again by
   studio.js (nativeAppDesk). */
html[data-native-app="1"] #view-dashboard .dash-top,
html[data-native-app="1"] #view-dashboard .dash-nav,
html[data-native-app="1"] #view-dashboard .dash-rail-tab {
  display: none !important;
}
/* The stage is a two-row grid (header, then main: auto / minmax(0, 1fr)).
   With the header gone the main would drop into the auto row and shrink to
   its content, squashing the composer frame; give it the one full row. */
html[data-native-app="1"] #view-dashboard .dash-stage {
  grid-template-rows: minmax(0, 1fr);
}
/* The rail is gone, so its track must go too: on a tablet the grid kept the
   208px rail column and the stage fell into it, a 182px composer on an iPad
   (2026-09-29). */
html[data-native-app="1"] #view-dashboard .dash-app {
  grid-template-columns: minmax(0, 1fr);
}

/* Inside the Flowers app the WebView already stops above the app's own tab
   bar, so the gift panes drop the phone scroller's bottom padding: it left an
   empty cream band under the composer on Android (Redmi, 2026-09-30).
   data-in-app marks the app on both platforms (layout.tsx boot); this was keyed
   on data-app-pay, which only iOS sets, so Android kept 28px plus its 48px
   gesture inset (Redmi, 2026-10-01). */
html[data-in-app="1"][data-desk-device="phone"] body[data-dash-pane="gifts"] .dash-main,
html[data-in-app="1"][data-desk-device="phone"] body[data-dash-pane="giftsMine"] .dash-main,
html[data-in-app="1"][data-desk-device="phone"] body[data-dash-pane="giftsBouquets"] .dash-main,
html[data-app-pay="hidden"][data-desk-device="phone"] body[data-dash-pane="gifts"] .dash-main,
html[data-app-pay="hidden"][data-desk-device="phone"] body[data-dash-pane="giftsMine"] .dash-main,
html[data-app-pay="hidden"][data-desk-device="phone"] body[data-dash-pane="giftsBouquets"] .dash-main {
  padding-bottom: 0;
}
