/* 내컷네컷 — MOBILE tier: phones (portrait), phone landscape (rotate prompt)
   and small landscape windows. Loaded after style.css.
   One top-level wrapper only (final-decisions.md 1.1); sub-variants
   (short phone, short phone 370+ wide, narrow phone, landscape coverage,
   rotate prompt) are nested inside it.
   Geometry only: no chrome colours, visibility-of-behaviour rules or copy.
   Chrome states, the gear hide, the post-QR hides and the download-mode
   hides all live in shared style.css (final-decisions.md 2.1 / 2.2). */

@media (max-width: 699.98px),
       (orientation: landscape) and (max-width: 767.98px),
       (orientation: landscape) and (max-width: 999.98px) and (max-height: 500.98px) {
  :root {
    --tier-mobile: 1;

    --m-gutter: 16px;
    --m-progress-h: 52px;
    --m-action-h: 56px;
    --m-action-gap: 12px;
    --m-safe-top: env(safe-area-inset-top, 0px);
    --m-safe-bottom: env(safe-area-inset-bottom, 0px);
    --m-action-reserve: calc(var(--m-action-h) + var(--m-action-gap) * 2 + var(--m-safe-bottom));
    --m-h2: clamp(21px, 5.8vw, 25px);
    --m-shutter: 112px;
    --m-qr: 136px;
    --stepper-h: var(--m-progress-h);
  }

  body {
    /* Heights every phone formula derives from (--shot-ratio is set inline on body). */
    --m-content-h: calc(100dvh - var(--m-progress-h) - var(--m-safe-top));
    --m-screen-h: calc(var(--m-content-h) - var(--m-action-reserve));
    /* Select: 2 columns at full gutter width. Classic (3:2) keeps all 4 rows in
       view; 3:4 and 1:1 keep the first 2 rows whole plus a peek of the third,
       and #photoGrid scrolls for the rest. */
    --m-select-cols: 2;
    --m-select-fit-rows: 2;
    --m-select-fit-gaps: 2;
    --m-select-peek: 28px;
    --m-track-w: min(calc(100vw - 2 * var(--m-gutter)), 420px);
    --m-track-cols: 8;
    --m-track-h: calc((var(--m-track-w) - 42px) / 8 / var(--shot-ratio));
    --m-capture-panel: calc(12px + var(--m-track-h) + 72px + var(--m-shutter) + 16px + var(--m-safe-bottom));
  }

  body[data-frame-type="classic"] {
    --m-track-cols: 4;
    --m-track-h: calc((var(--m-track-w) - 18px) / 4 / var(--shot-ratio) * 2 + 6px);
    --m-select-fit-rows: 4;
    --m-select-fit-gaps: 3;
    --m-select-peek: 0px;
  }

  .app-shell {
    width: 100%;
  }

  /* ---------- Progress row (the stepper moves to the top) ----------
     Bars: active and done in ink, upcoming in --line (final-decisions 2.3). */
  .stepper {
    order: -1;
    position: relative;
    flex: none;
    margin: 0;
    height: calc(var(--m-progress-h) + var(--m-safe-top));
    padding: calc(10px + var(--m-safe-top)) 68px 0 var(--m-gutter);
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    grid-template-rows: 20px 4px;
    align-content: start;
    column-gap: 4px;
    row-gap: 8px;
    border-top: 0;
    border-bottom: 1px solid var(--line);
    background: var(--surface);
  }

  .step {
    grid-row: 2;
    min-width: 0;
    height: 4px;
    padding: 0;
    border-radius: 2px;
    background: var(--line);
    display: block;
  }

  .step.active,
  .step:has(~ .step.active) {
    background: var(--ink);
  }

  .step span,
  .step strong {
    display: none;
  }

  .step.active strong,
  .step.active span {
    display: block;
    position: absolute;
    top: calc(10px + var(--m-safe-top));
    height: 20px;
    line-height: 20px;
    white-space: nowrap;
  }

  .step.active strong {
    left: var(--m-gutter);
    max-width: calc(100% - 150px);
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 14px;
    font-weight: 800;
  }

  /* The circle becomes a "2 / 5" counter. */
  .step.active span {
    right: 68px;
    width: auto;
    border: 0;
    border-radius: 0;
    background: none;
    color: var(--muted);
    font-size: 13px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
  }

  .step.active span::after {
    content: " / 5";
  }

  /* Setup has no active step: an empty row of faint bars read as "0 of 5".
     The row collapses to the safe area and the h2 sits beside the active gear. */
  body[data-screen="setup"] .stepper {
    height: var(--m-safe-top);
    padding: 0;
    border-bottom: 0;
    overflow: hidden;
    visibility: hidden;
  }

  body[data-screen="setup"] .setup-intro {
    min-height: 32px;
    padding-right: 48px;
  }

  /* ---------- Operator entry: top-right inside the progress row ---------- */
  .settings-button,
  .home-button {
    top: calc(4px + var(--m-safe-top));
    right: 12px;
    left: auto;
    width: 44px;
    height: 44px;
  }

  .settings-button span {
    font-size: 20px;
  }

  /* ---------- Screens + bottom action bar ---------- */
  #setupScreen,
  #typeScreen,
  #timerScreen,
  #selectScreen,
  #frameScreen {
    margin-bottom: var(--m-action-reserve);
  }

  .next-button,
  #uploadButton {
    position: fixed;
    left: var(--m-gutter);
    right: var(--m-gutter);
    bottom: calc(var(--m-action-gap) + var(--m-safe-bottom));
    z-index: 12;
    width: auto;
    height: var(--m-action-h);
    min-height: var(--m-action-h);
    border-radius: 16px;
    font-size: 17px;
  }

  /* The progress label replaces the eyebrow on phones. */
  .type-intro p {
    display: none;
  }

  .type-intro h2,
  .section-heading h2 {
    font-size: var(--m-h2);
    line-height: 32px;
    word-break: keep-all;
  }

  /* Korean body copy wraps at word boundaries, never inside a word. */
  .section-heading p,
  .upload-status,
  .field-help,
  .timer-panel span,
  .type-note {
    word-break: keep-all;
    overflow-wrap: break-word;
  }

  /* ---------- Setup (operator; may scroll) ---------- */
  .setup-layout {
    flex: 1 0 auto;
    padding: 12px var(--m-gutter) 24px;
    display: grid;
    grid-template-columns: clamp(84px, 26vw, 112px) minmax(0, 1fr);
    grid-template-areas:
      "intro intro"
      "preview panel";
    align-items: start;
    align-content: start;
    gap: 12px;
  }

  .setup-intro { grid-area: intro; }

  .setup-preview {
    grid-area: preview;
    position: sticky;
    top: 12px;
    display: block;
  }

  .setup-preview .sample-frame {
    width: 100%;
    max-width: 100%;
    max-height: none;
  }

  .setup-panel {
    grid-area: panel;
    padding: 0;
    border-radius: 0;
    background: none;
    gap: 14px;
  }

  .field-group {
    gap: 6px;
    color: var(--ink);
    font-size: 14px;
  }

  .field-group input,
  .field-group select {
    min-height: 48px;
    font-size: 16px;
  }

  .field-group input[type="file"] {
    min-height: 48px;
    font-size: 14px;
  }

  .field-help {
    font-size: 13px;
  }

  #clearFrameDesignButton {
    min-height: 44px;
    font-size: 14px;
  }

  /* ---------- Type (step 1) ---------- */
  /* No filter panel any more: the sample takes the flexible row and the cards'
     mini frames grow with the phone height (52-72px). */
  .type-layout {
    --m-mini-h: clamp(52px, 8dvh, 72px);
    flex: 1 0 auto;
    padding: 12px var(--m-gutter);
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(120px, 1fr) auto auto;
    grid-template-areas:
      "intro"
      "preview"
      "note"
      "options";
    gap: 12px;
  }

  .type-layout .type-intro { grid-area: intro; }

  .type-preview {
    grid-area: preview;
    container-type: size;
    min-height: 0;
    display: grid;
    place-items: center;
  }

  .type-preview .sample-frame {
    width: min(100cqw, calc(100cqh * var(--output-ratio)));
    max-width: 100%;
    max-height: none;
  }

  .type-note {
    grid-area: note;
    padding: 0;
    border-radius: 0;
    background: none;
    text-align: center;
    font-size: 14px;
    line-height: 20px;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  .type-options {
    grid-area: options;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
  }

  .type-card {
    min-height: 0;
    padding: 10px 6px 12px;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: var(--m-mini-h) auto;
    justify-items: center;
    align-items: start;
    row-gap: 8px;
    text-align: center;
    border-radius: 14px;
  }

  /* Shared check badge, scaled to clear the centred mini frame in a ~104px card. */
  .type-card.active::after {
    top: 6px;
    right: 6px;
    width: 20px;
    height: 20px;
    font-size: 12px;
  }

  .type-card .mini-frame {
    grid-row: 1;
    height: var(--m-mini-h);
  }

  .type-card strong {
    font-size: 14px;
    line-height: 18px;
    word-break: keep-all;
  }

  .type-card small {
    display: none;
  }

  /* ---------- Timer (step 2) ---------- */
  /* The question and its answers read as one group, centred (slightly above
     the optical middle) in the space between the progress row and the bar. */
  .timer-layout {
    flex: 1 0 auto;
    padding: 12px var(--m-gutter) 48px;
    display: grid;
    grid-template-rows: auto auto;
    align-content: center;
    gap: 24px;
  }

  .timer-panel {
    align-self: start;
    padding: 0;
    border-radius: 0;
    background: none;
    gap: 16px;
  }

  .timer-panel strong { font-size: 17px; }
  .timer-panel span { font-size: 15px; line-height: 1.45; }

  .timer-choice {
    min-height: 72px;
    font-size: 20px;
  }

  /* ---------- Capture (step 3): no action bar ---------- */
  #captureScreen.active {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
    overflow: hidden;
  }

  #captureScreen .camera-stage {
    width: min(100%, calc((var(--m-content-h) - var(--m-capture-panel)) * var(--shot-scale)));
    height: auto;
    justify-self: center;
  }

  .record-pill {
    top: 12px;
    gap: 8px;
    padding: 8px 14px;
    font-size: 14px;
    white-space: nowrap;
  }

  .dot { width: 10px; height: 10px; }

  .timer-overlay {
    font-size: clamp(96px, 30vw, 150px);
  }

  #captureScreen .capture-panel {
    min-height: 0;
    padding: 12px var(--m-gutter) calc(16px + var(--m-safe-bottom));
    display: grid;
    /* Track and status stay together under the camera; the shutter is centred
       in whatever height is left (camera-app control area), so the leftover is
       split evenly around it instead of pooling between status and shutter. */
    grid-template-rows: auto auto 1fr;
    row-gap: 0;
  }

  #captureScreen .shot-track {
    grid-row: 1;
    width: 100%;
    max-width: var(--m-track-w);
    justify-self: center;
    margin: 0;
    grid-template-columns: repeat(var(--m-track-cols), minmax(0, 1fr));
    gap: 6px;
  }

  #captureScreen .center-copy {
    grid-row: 2;
    align-self: start;
    min-height: 0;
    margin: 12px 0;
    font-size: 18px;
    line-height: 24px;
    word-break: keep-all;
  }

  #captureScreen .capture-actions {
    grid-row: 3;
    align-self: center;
    margin: 0;
  }

  .shutter {
    width: var(--m-shutter);
    height: var(--m-shutter);
    border-width: 10px;
    font-size: 44px;
  }

  /* ---------- Select (step 4): heading, the 8 photos, 다음 (fixed bar) ----------
     The layout fills the screen exactly, so the page never scrolls; when the
     photos are taller than their row, #photoGrid scrolls inside it. */
  .select-layout {
    flex: 1 1 auto;
    min-height: 0;
    padding: 12px var(--m-gutter);
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
    gap: 6px;
    overflow: hidden;
  }

  .section-heading p {
    margin-top: 4px;
    font-size: 14px;
    line-height: 20px;
    text-wrap: pretty;
  }

  /* Two lines are kept so the photos do not jump when the hint swaps to the
     one-line "다 골랐어요" copy. */
  .select-layout .section-heading p {
    min-height: 40px;
  }

  /* #photoGrid is a size container: each card is the column width, capped by
     the rows that must stay in view (--m-select-fit-*) at the frame's photo
     ratio. The 6px padding (taken back by the margin) keeps the shared focus
     ring inside the scroll box; the visible gap under the heading is 12px.
     Rows are max-content: auto rows would shrink to the scroll box (the cards
     clip their overflow, so their minimum contribution is 0) and overlap. */
  .select-layout .photo-grid {
    --m-card-gap: 10px;
    container-type: size;
    margin: 0 -6px;
    padding: 6px;
    grid-template-columns: repeat(var(--m-select-cols), max-content);
    grid-auto-rows: max-content;
    justify-content: center;
    align-content: start;
    gap: var(--m-card-gap);
  }

  .select-layout .photo-card {
    width: min(
      calc((100cqw - (var(--m-select-cols) - 1) * var(--m-card-gap)) / var(--m-select-cols)),
      calc((100cqh - var(--m-select-fit-gaps) * var(--m-card-gap) - var(--m-select-peek)) / var(--m-select-fit-rows) * var(--shot-ratio))
    );
  }

  /* Order badge: about a fifth of a card, readable at arm's length. */
  .select-layout .photo-card span {
    top: 8px;
    left: 8px;
    min-width: 32px;
    height: 32px;
    padding: 0 6px;
    box-shadow: 0 0 0 2px #fff;
    font-size: 18px;
  }

  /* ---------- Frame & QR (step 5) ----------
     The strips are height-bound: --m-frame-h is what is left of the screen
     after the heading (108 with paddings and gaps) and the tools. The budget
     lives on #frameScreen so the state rules below (failed, QR, download page)
     only change the term that differs and the formula re-resolves there. */
  #frameScreen {
    /* Before the QR: colour group (label 20 + 6 + swatch row 44) + 12 +
       filter group (20 + 6 + one row of 44) = 152, then 12 + status 44. */
    --m-choices-h: calc(20px + 6px + 44px + 12px + 20px + 6px + 44px);
    --m-status-h: 44px;
    --m-tools-h: calc(var(--m-choices-h) + 12px + var(--m-status-h));
    --m-frame-h: calc(var(--m-screen-h) - 108px - var(--m-tools-h));
    padding: 12px var(--m-gutter);
  }

  #frameScreen > .section-heading {
    flex: none;
    margin-bottom: 12px;
  }

  .composer {
    flex: 1 0 auto;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: minmax(0, 1fr) auto;
    grid-template-areas:
      "photo video"
      "tools tools";
    column-gap: 12px;
    row-gap: 16px;
    align-items: center;
  }

  #printFrame { grid-area: photo; }
  #videoPrintFrame { grid-area: video; }

  /* 2:3 frames (multi4/multi6) are column-bound, never height-bound: give the
     photo frame the larger column so the operator's frame is the hero, sit
     both strips on one baseline, and centre strips + tools as one group so the
     spare height is not split into two blank bands. */
  body:not([data-mode="download"]):not([data-frame-type="classic"]) .composer {
    grid-template-columns: minmax(0, 1.8fr) minmax(0, 1fr);
    grid-template-rows: auto auto;
    align-content: center;
    align-items: end;
  }

  #frameScreen .print-frame {
    width: min(100%, calc(var(--m-frame-h) * var(--output-ratio)));
    max-width: 100%;
    margin: 0 auto;
  }

  .frame-tools {
    grid-area: tools;
    order: 0;
    align-self: end;
    gap: 12px;
  }

  /* .frame-choices (first child of .frame-tools): colour group, then filter
     group, each a 20px label over one 44px row (--m-choices-h). */
  .frame-choices {
    gap: 12px;
  }

  .choice-group {
    gap: 6px;
  }

  .choice-group > strong {
    font-size: 14px;
    line-height: 20px;
  }

  .swatches {
    --swatch-size: 44px;
    gap: 12px;
  }

  /* 6 x 1: about 50px each at 360 wide, enough for "차가움" at 14px. */
  .filter-options {
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 6px;
  }

  .filter-choice {
    min-height: 44px;
    padding: 0 2px;
    font-size: 14px;
    line-height: 18px;
  }

  .upload-status {
    min-height: 44px;
    font-size: 14px;
    line-height: 20px;
  }

  /* failed: the staff message may wrap to 2 lines (64px) on narrow phones, so
     the strips give up 20px; the box itself stays 44px when it fits on one. */
  body:not([data-mode="download"]) #frameScreen[data-upload="failed"] {
    --m-status-h: 64px;
  }

  .qr-box {
    grid-template-columns: var(--m-qr);
    justify-content: center;
    gap: 12px;
  }

  .qr-box img {
    width: var(--m-qr);
    height: var(--m-qr);
  }

  /* QR shown on the booth: swatches and #uploadButton are hidden (shared), so
     no action-bar reserve; the QR and the scan instruction sit side by side.
     Scoped to #frameScreen because #qrBox.show outlives the session. */
  body:not([data-mode="download"]) #frameScreen:has(#qrBox.show) {
    --m-tools-h: calc(var(--m-qr) + 24px);
    --m-screen-h: calc(var(--m-content-h) - var(--m-safe-bottom));
    margin-bottom: var(--m-safe-bottom);
  }

  body:not([data-mode="download"]) #frameScreen:has(#qrBox.show) .frame-tools {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
  }

  body:not([data-mode="download"]) #frameScreen:has(#qrBox.show) #qrBox {
    grid-column: 1;
    grid-row: 1;
  }

  body:not([data-mode="download"]) #frameScreen:has(#qrBox.show) #uploadStatus {
    grid-column: 2;
    grid-row: 1;
    align-self: stretch;
    display: flex;
    align-items: center;
    font-size: 15px;
    line-height: 22px;
  }

  /* 처음으로 (#resetButton; shared style.css shows it once an upload attempt
     has finished) is the secondary button of the bottom action bar, same
     height as the primary. done: the QR hid #uploadButton, so it takes the
     whole bar and the screen keeps the bar reserve. failed: it shares the bar
     with the staff retry (#uploadButton), half each, so the strips keep their
     pre-upload size. The armed label wraps to 2 lines in the half bar. */
  #resetButton {
    position: fixed;
    left: var(--m-gutter);
    right: var(--m-gutter);
    bottom: calc(var(--m-action-gap) + var(--m-safe-bottom));
    z-index: 12;
    width: auto;
    height: var(--m-action-h);
    min-height: var(--m-action-h);
    padding: 0 12px;
    font-size: 17px;
  }

  body:not([data-mode="download"]) #frameScreen[data-upload="done"]:has(#qrBox.show) {
    --m-screen-h: calc(var(--m-content-h) - var(--m-action-reserve));
    margin-bottom: var(--m-action-reserve);
  }

  body:not([data-mode="download"]) #frameScreen[data-upload="failed"] #resetButton {
    right: calc(50% + var(--m-action-gap) / 2);
  }

  body:not([data-mode="download"]) #frameScreen[data-upload="failed"] #uploadButton {
    left: calc(50% + var(--m-action-gap) / 2);
  }

  /* Download page (visitor opened the QR link on their own phone): no
     progress row, no action bar; the two 52px links (shared look) run full
     width under the strips. Status may wrap to 2 lines (64) + 12 + links 112. */
  body[data-mode="download"] #frameScreen {
    --m-content-h: calc(100dvh - var(--m-safe-top));
    --m-screen-h: calc(var(--m-content-h) - var(--m-safe-bottom));
    --m-tools-h: 188px;
    --m-frame-h: calc(var(--m-screen-h) - 128px - var(--m-tools-h));
    padding-top: calc(12px + var(--m-safe-top));
    margin-bottom: var(--m-safe-bottom);
  }

  body[data-mode="download"] .qr-box {
    grid-template-columns: minmax(0, 1fr);
    justify-content: stretch;
  }

  /* ---------- Short phones: browser toolbars, iPhone SE ---------- */
  @media (max-height: 700px) {
    :root {
      --m-shutter: 88px;
    }

    .type-layout {
      gap: 8px;
    }

    .shutter {
      border-width: 8px;
      font-size: 36px;
    }
  }

  /* ---------- Short phones at least 370 wide (iPhone SE, Safari with toolbars):
     each choice label sits beside its row ("프레임 / 컬러" on two lines), which
     gives the strips 54px back. Filters stay 6 x 1, 45px or wider. */
  @media (orientation: portrait) and (max-height: 700px) and (min-width: 370px) {
    #frameScreen {
      --m-choices-h: calc(44px + 10px + 44px);
    }

    .frame-choices {
      gap: 10px;
    }

    .choice-group {
      grid-template-columns: min-content minmax(0, 1fr);
      align-items: center;
      column-gap: 10px;
    }

    /* the row is 306px at 390 wide: six circles need gap 8px to stay at 44px */
    .swatches {
      gap: 8px;
    }

    .choice-group > strong {
      line-height: 18px;
      word-break: keep-all;
    }

    .filter-options {
      gap: 4px;
    }

    .filter-choice {
      padding: 0;
    }
  }

  /* ---------- Narrow phones (320-349 wide): tighter filter row so each of the
     6 stays at least 44px wide (44.7 at 320); the widest label is 3 syllables. */
  @media (max-width: 349.98px) {
    .filter-options {
      gap: 4px;
    }

    .filter-choice {
      padding: 0;
    }
  }

  /* ---------- Landscape windows 700–767 wide, taller than 500: coverage only.
     The phone layout applies; the active screen may scroll (final-decisions 2.5). */
  @media (orientation: landscape) and (min-height: 501px) {
    .screen.active,
    #captureScreen.active {
      overflow-y: auto;
    }

    /* Select: 4 x 2, all 8 in view for every photo ratio. */
    body,
    body[data-frame-type] {
      --m-select-cols: 4;
      --m-select-fit-rows: 2;
      --m-select-fit-gaps: 1;
      --m-select-peek: 0px;
    }

    /* Frame: strips and tools in one row, so the strips get the full height
       (heading 92 = paddings 24 + heading 56 + margin 12). */
    #frameScreen {
      --m-frame-h: calc(var(--m-screen-h) - 92px);
    }

    body[data-mode="download"] #frameScreen {
      --m-frame-h: calc(var(--m-screen-h) - 112px);
    }

    .composer,
    body:not([data-mode="download"]):not([data-frame-type="classic"]) .composer {
      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(300px, 1.3fr);
      grid-template-rows: minmax(0, 1fr);
      grid-template-areas: "photo video tools";
      align-content: stretch;
      align-items: center;
    }

    body:not([data-mode="download"]):not([data-frame-type="classic"]) .composer {
      grid-template-columns: minmax(0, 1.8fr) minmax(0, 1fr) minmax(300px, 1.6fr);
    }

    .frame-tools {
      align-self: center;
    }

    .filter-options {
      grid-template-columns: repeat(3, minmax(0, 1fr));
    }
  }

  /* ---------- Phone held in landscape (under 1000 wide, 500 or less tall) ---------- */
  @media (orientation: landscape) and (max-height: 500.98px) {
    /* Rotate prompt: pseudo-elements over the running app; DOM, camera stream
       and countdown are untouched. Not on the download page. */
    body:not([data-mode="download"])::before {
      content: "휴대폰을 세로로 돌려 주세요";
      position: fixed;
      inset: 0;
      z-index: 100;
      display: grid;
      place-content: center;
      padding: 64px 24px 0;
      background: var(--surface);
      color: var(--ink);
      text-align: center;
      font-size: 22px;
      font-weight: 800;
    }

    body:not([data-mode="download"]) .app-shell::before {
      content: "";
      position: fixed;
      z-index: 101;
      left: 50%;
      top: calc(50% - 52px);
      width: 38px;
      height: 64px;
      border: 3px solid var(--ink);
      border-radius: 8px;
      transform: translate(-50%, -50%);
    }

    body:not([data-mode="download"]) .app-shell::after {
      content: "세로 화면에서 촬영할 수 있어요";
      position: fixed;
      z-index: 101;
      left: 0;
      right: 0;
      top: calc(50% + 50px);
      color: var(--muted);
      text-align: center;
      font-size: 15px;
      font-weight: 700;
    }

    /* Download page sideways: strips and links in one row; scrolls if needed. */
    body[data-mode="download"] #frameScreen {
      --m-frame-h: calc(var(--m-screen-h) - 112px);
      padding-left: max(var(--m-gutter), env(safe-area-inset-left, 0px));
      padding-right: max(var(--m-gutter), env(safe-area-inset-right, 0px));
    }

    body[data-mode="download"] .composer {
      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.4fr);
      grid-template-rows: minmax(0, 1fr);
      grid-template-areas: "photo video tools";
    }

    body[data-mode="download"] .frame-tools {
      align-self: center;
    }
  }
}
