/* camera chốn riêng, base: tokens, page column, screens and the stage. Controls are in camera-controls.css,
   the result sheet and editor in camera-sheet.css. Lamp yellow is kept for the shutter and the one primary
   button per view; selected items use the light ink. */
:root {
  --hue: 75;
  --bg: oklch(17% 0.016 var(--hue));
  --surface: oklch(21.5% 0.018 var(--hue));
  --surface-2: oklch(26% 0.02 var(--hue));
  --line: oklch(34% 0.022 var(--hue));
  --ink: oklch(94% 0.016 85);
  --ink-2: oklch(83% 0.02 82);
  --ink-3: oklch(70% 0.022 80);
  --lamp: oklch(86% 0.13 88);
  --lamp-ink: oklch(22% 0.03 80);
  --matcha: oklch(78% 0.09 135);
  --coral: oklch(74% 0.11 35);

  --font-hand: "Shantell Sans", "Be Vietnam Pro", system-ui, sans-serif;
  --font-bold: "League Spartan", "Be Vietnam Pro", system-ui, sans-serif;
  --font-body: "Be Vietnam Pro", system-ui, sans-serif;
  --font-round: "Baloo 2", "Be Vietnam Pro", system-ui, sans-serif; /* the camera's own controls: round and bold */

  --step--1: 0.84rem;
  --step-0: 1rem;
  --step-1: 1.25rem;
  --step-2: 1.65rem;

  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 24px; --space-6: 32px;
  --radius: 14px;
  --radius-sm: 8px;

  --dur-press: 120ms; --dur-state: 240ms;
  --ease-out: cubic-bezier(0.25, 1, 0.5, 1);
}
@media (prefers-reduced-motion: reduce) {
  :root { --dur-press: 0ms; --dur-state: 0ms; }
  .spin, .stage__count b, .stage__flash, .stage__rec i { animation: none !important; }
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; background: var(--bg); }
body {
  margin: 0; min-height: 100dvh; background: var(--bg); color: var(--ink);
  font: 400 var(--step-0) / 1.55 var(--font-body);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
}
a { color: inherit; }
button { font: inherit; color: inherit; cursor: pointer; }
h1, h2 { margin: 0; font-family: var(--font-hand); font-weight: 600; line-height: 1.15; letter-spacing: -0.01em; text-wrap: balance; }
h1 { font-size: var(--step-2); }
h2 { font-size: var(--step-1); }
p { margin: 0; text-wrap: pretty; }
:focus-visible { outline: 2px solid var(--lamp); outline-offset: 3px; border-radius: 6px; }
[hidden] { display: none !important; }

.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.ico { width: 22px; height: 22px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }

/* App column: full screen on phones, a phone-width card on desktop. */
.app {
  position: relative; display: flex; flex-direction: column;
  width: 100%; max-width: 440px; height: 100dvh; margin: 0 auto;
  padding: 0 var(--space-4);
  padding-bottom: max(var(--space-3), env(safe-area-inset-bottom));
  background: var(--bg);
}
@media (min-width: 600px) {
  body { display: grid; place-items: center; }
  .app {
    height: min(calc(100dvh - 32px), 880px); margin: 16px auto;
    border-radius: 28px; box-shadow: 0 0 0 1px var(--line), 0 24px 60px oklch(8% 0.02 var(--hue) / 0.55);
    overflow: hidden;
  }
}

/* The camera screen has its own top bar (back, mode, more) and gives the picture every pixel it can. */
.app[data-screen="camera"] { padding-inline: var(--space-2); padding-bottom: max(var(--space-2), env(safe-area-inset-bottom)); }
.app[data-screen="camera"] > .top { display: none; }
.top { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: max(var(--space-2), env(safe-area-inset-top)) 0 var(--space-2); flex: none; }
.back { display: inline-flex; align-items: center; gap: var(--space-1); min-height: 44px; padding-right: var(--space-2); font-size: var(--step--1); color: var(--ink-2); text-decoration: none; border-radius: 999px; }
.back:hover { color: var(--ink); }
.back .ico { width: 20px; height: 20px; }
.top__title { font-family: var(--font-hand); font-weight: 600; font-size: var(--step--1); color: var(--ink-3); }
/* Below 360px the back link keeps one line: the name on the right goes (every screen has its own heading). */
@media (max-width: 359.98px) { .top__title { display: none; } }

/* Buttons. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: 44px; padding: var(--space-2) var(--space-4); border: 0; border-radius: 999px;
  background: var(--surface-2); color: var(--ink); font-weight: 600; font-size: var(--step--1); line-height: 1.25; text-align: center; text-decoration: none;
  transition: background var(--dur-state) var(--ease-out), transform var(--dur-press) var(--ease-out);
}
.btn:hover { background: var(--line); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }
.btn--lamp { background: var(--lamp); color: var(--lamp-ink); font-size: var(--step-0); }
.btn--lamp:hover { background: oklch(90% 0.12 88); }
.btn--line { background: transparent; box-shadow: inset 0 0 0 1px var(--line); }
.btn--line:hover { background: var(--surface); }
.btn--wide { width: 100%; }
.roundbtn { display: grid; place-items: center; width: 52px; height: 52px; border: 0; border-radius: 50%; background: var(--surface-2); transition: background var(--dur-state) var(--ease-out), transform var(--dur-press) var(--ease-out); }
.roundbtn:hover { background: var(--line); }
.roundbtn:active { transform: scale(0.94); }
.roundbtn:disabled { opacity: 0.45; cursor: not-allowed; }
.roundbtn--sm { width: 44px; height: 44px; }
.roundbtn--glass { background: oklch(14% 0.016 var(--hue) / 0.5); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); }
.roundbtn--glass:hover { background: oklch(14% 0.016 var(--hue) / 0.7); }
.linkbtn { min-height: 44px; margin: -12px -8px -12px 0; padding: 0 var(--space-3); border: 0; background: none; color: var(--lamp); font-weight: 600; font-size: var(--step--1); text-decoration: underline; text-underline-offset: 3px; }

/* Full-column screens: intro and every blocked state share one layout. */
/* A scroll box clips at its padding edge: the 6px each side (out of the app's own padding) keeps the whole focus ring
   of a full-width button (2px plus 3px away) in view, and the content stays where it was. */
.screen { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: var(--space-5); padding: var(--space-4) 6px; margin-inline: -6px; overflow-y: auto; }
.screen__art { display: grid; place-items: center; padding-top: var(--space-4); }
.art { width: min(72%, 260px); height: auto; }
.screen-light { position: fixed; inset: 0; z-index: 50; background: #fff6e6; opacity: 0; pointer-events: none; transition: opacity 120ms linear; }
.screen-light.is-on { opacity: 1; }
.perf { position: absolute; left: var(--space-3); top: 64px; margin: 0; padding: var(--space-2); border-radius: var(--radius-sm); background: oklch(10% 0.01 var(--hue) / 0.75); color: var(--matcha); font: 500 11px / 1.35 "Chivo Mono", ui-monospace, monospace; pointer-events: none; white-space: pre; }
.screen__body { display: grid; gap: var(--space-3); margin-block: auto; }
.screen__body p { color: var(--ink-2); }
.screen__actions { display: grid; gap: var(--space-3); }
.privacy { display: flex; align-items: flex-start; gap: var(--space-2); padding: var(--space-3) var(--space-4); border-radius: var(--radius); background: var(--surface); color: var(--ink-2); font-size: var(--step--1); }
.privacy .ico { width: 20px; height: 20px; margin-top: 2px; color: var(--matcha); }
.inapp-tip { display: grid; gap: var(--space-2); justify-items: start; padding: var(--space-3) var(--space-4); border-radius: var(--radius); background: var(--surface); box-shadow: inset 0 0 0 1px var(--lamp); font-size: var(--step--1); }
.inapp-tip b { color: var(--ink); }
.inapp-tip__link { font-family: ui-monospace, Menlo, monospace; font-size: 12px; word-break: break-all; -webkit-user-select: all; user-select: all; }
.inapp-tip__status:empty { display: none; }
html[data-inapp] [data-screen-name="denied"] .steps { display: none; } /* the address-bar steps do not exist in an app's browser */
.steps { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.steps li { display: grid; gap: 2px; padding: var(--space-3) var(--space-4); border-radius: var(--radius); background: var(--surface); font-size: var(--step--1); color: var(--ink-2); }
.steps b { font-family: var(--font-hand); font-weight: 600; color: var(--ink); font-size: var(--step-0); }

/* Camera layout, after Locket: a top bar, the picture as one big rounded frame, the tabs and the effect ring.
   The frame takes whatever height the controls leave, in the shape of the picture being made (--ar, --arn: set
   from the stage size each time it changes), so a 3:4 photo fills it with no bands at the sides. */
.cam { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 6px; }
/* The bar is two or three glass buttons laid over the picture's top corners (back at the left, the camera switch at the
   right, "⋯" between them while there is something to open), so the picture keeps the room a bar of its own would take. */
.cam__bar {
  position: absolute; top: max(var(--space-3), env(safe-area-inset-top)); left: var(--space-3); right: var(--space-3); z-index: 3;
  display: flex; align-items: center; gap: var(--space-2); pointer-events: none;
}
.cam__bar > * { pointer-events: auto; }
.cam__bar > a { color: var(--ink); text-decoration: none; }
.cam__bar > [data-action="flip"] { margin-left: auto; }
.cam__bar > #more-btn { margin-left: auto; }
.cam__bar > #more-btn + [data-action="flip"] { margin-left: 0; }
/* "⋯" is there for what the first screen leaves out (timer, ratio, screen light, the photobooth and video options):
   in Tuỳ chỉnh, and in the modes that have options of their own. */
.app:not([data-view="custom"]):not([data-family="photobooth"]):not([data-family="video"]) #more-btn { display: none; }
/* The picture and the dock after it share one cell, sized by the picture alone (the dock is a size container, so its
   contents take no room): upright, the dock lies exactly over the picture. */
.cam__fit { flex: 1; min-height: 0; container-type: size; display: grid; place-content: center; place-items: center; }
.cam__fit > * { grid-area: 1 / 1; }
/* The stage is a container too: the tools on it follow the size of the picture, not of the screen. */
.stage {
  position: relative; width: min(100cqw, 100cqh * var(--arn, 0.75)); aspect-ratio: var(--ar, 3 / 4); border-radius: 40px; overflow: hidden; background: oklch(12% 0.012 var(--hue)); container: stage / size;
}
/* The adjust panel, the hint and the mode note are in their own box after the picture, the dock, so a phone on its side
   can put them in the column on the right. Upright the dock lies over the picture and is a container of the same name
   and size, so they follow the picture as when they were in it. It is a grid for the two boxes that stack at its foot,
   the adjust panel (camera-controls.css) on the hint and the hint on the corner buttons, so a hint of any length pushes
   the panel up instead of running under it. With no hint the bottom row keeps 62px, which leaves the panel 70px from
   the bottom. Taps on the picture go through the dock. */
.stage-dock {
  position: relative; place-self: stretch; container: stage / size; pointer-events: none;
  display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) minmax(0, auto) minmax(62px, auto);
}
.stage-dock > :not(.toast) { pointer-events: auto; }
/* Drawn as when the panel and the hint were in the picture: over the hint, under the panel (which comes later, with the
   same z-index) and the mode note. */
.stage__count, .stage__print, .stage__flash, .stage__loading { z-index: 1; }
.stage__layer { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; display: block; }
#overlay-canvas { pointer-events: none; }
.source-video { position: absolute; width: 2px; height: 2px; left: 0; top: 0; opacity: 0; pointer-events: none; }

.stage__status, .stage__rec, .stage__hint {
  position: absolute; display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-1) var(--space-3); border-radius: 999px; font-size: var(--step--1);
  background: oklch(14% 0.016 var(--hue) / 0.78); color: var(--ink);
}
/* Top of the picture: the row of the bar's buttons (kept free), the status chip under it. Drawn over the effect's name, which shows a moment in the middle of the picture, so the chip's words stay
   clear of it; the video's time, the countdown, the print, the flash and the loading veil come later with the same
   z-index and stay over the bar. */
.stage__top {
  position: absolute; inset: var(--space-3) var(--space-3) auto; z-index: 1;
  display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-2); min-height: 44px; /* the row the bar's buttons fill (the panel and the status chip sit under it) */
  pointer-events: none;
}
.stage__top > * { pointer-events: auto; }
/* The status chip, at every size and on a phone on its side: laid over the picture in a row of its own under the tools,
   8px under them as the mode note is (64px from the top of the picture, 116px when the tools stack in columns, below),
   so showing it moves neither the picture nor a tool. Centred and as wide as its words, at most as wide as the row of
   tools (the frame less 24px). A "\n" in its text breaks the line there; a line too long for the chip wraps into even
   lines, left-aligned, and the chip grows taller rather than cut a word. "thử lại" ends the row; with it the chip is
   44px tall, so the button (44px tall, its margins giving back 24px of that) is 44×44 inside the chip. */
.stage__status {
  top: calc(100% + var(--space-2)); left: 0; right: 0; width: fit-content; max-width: 100%; margin-inline: auto;
  min-height: 32px; border-radius: 16px;
}
.stage__status:has(> .linkbtn:not([hidden])) { min-height: 44px; }
.stage__status [data-text] { white-space: pre-line; text-wrap: balance; text-align: left; overflow-wrap: anywhere; }
.stage__status > .linkbtn { flex: none; min-width: 44px; padding-inline: 0; margin-right: 0; }
/* The mode note shows in the chip's band. While it shows, the chip fades out as the note fades in, and back in as the
   note fades out. By its opacity: the chip stays in the accessibility tree, so a line it shows meanwhile is still read
   out (role="status"), and keeps its box, so the panel and the tools stay put; a tap goes through it. It does not fade
   while "thử lại" has the focus. On a phone on its side the note is in the column on the right, away from the chip. */
@media not all and (orientation: landscape) and (max-height: 500px) {
  .stage__status { transition: opacity var(--dur-state) var(--ease-out); }
  :where(.stage:has(+ .stage-dock > .toast.is-on)) .stage__status:not(:focus-within) { opacity: 0; pointer-events: none; }
}
/* The chosen effect's name, big in the middle of the picture for a moment, as a lens app shows it. */
.stage__name { position: absolute; left: 50%; top: 42%; margin: 0; transform: translate(-50%, -50%) scale(0.96); max-width: calc(100% - 48px); padding: 6px 16px; border-radius: 999px; background: oklch(14% 0.016 var(--hue) / 0.5); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); font: 700 1.15rem / 1.3 var(--font-round); text-align: center; color: var(--ink); opacity: 0; pointer-events: none; transition: opacity var(--dur-state) var(--ease-out), transform var(--dur-state) var(--ease-out); }
.stage__name.is-on { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.stage__name:empty { display: none; }
/* Bottom-left corner: the last result, as on a phone camera. The camera switch sits with the light at the top, so the
   date printed in the picture's bottom-right corner stays in view. */
.stage > .thumb { position: absolute; left: var(--space-3); bottom: var(--space-3); width: 46px; height: 46px; border-radius: 14px; }
/* The video's time while it records, over the bar of tools as the layers above (same z-index, later in the markup): a
   9:16 picture on a small phone lays it over the camera switch. On one line: from the middle of the picture (left: 50%)
   its box has only half the picture's width before it wraps, and "0:00 / 0:15" went onto two lines in a 9:16 picture
   on a 320×568 screen. On one line it covers the edges of the tools beside it, which are dimmed and take no tap while
   it records (.app[data-busy="1"] in camera-controls.css). */
.stage__rec { top: var(--space-3); left: 50%; transform: translateX(-50%); z-index: 1; white-space: nowrap; font-variant-numeric: tabular-nums; font-weight: 600; }
.stage__rec i { width: 10px; height: 10px; border-radius: 50%; background: var(--coral); animation: blink 1s steps(2, start) infinite; }
/* The hint sits in the bottom row of the dock's grid, 16px from the bottom, clear of the small picture in the corner
   (12px in, 46px wide, then 8px): centred while it fits between that and the same room on the right, otherwise its left
   edge stops at 66px and it wraps 12px from the right edge. Its box is as wide as its text (a box set from the middle
   would get half the picture at most). With no small picture yet it may take the whole width. A frame narrower than
   360px leaves too little room beside the small picture (the first line of the mask note is 242px of words, plus 102px
   of padding and clearance, and some fonts set wider), so there the hint goes over it instead, 8px above, as wide as the
   frame less 24px: two wide lines, not a narrow column. Lines are balanced: "pretty" (from p) breaks a line that fits
   its box in WebKit, which adds a line to a box exactly as wide as its words. */
.stage__hint { position: relative; grid-area: 3 / 1; align-self: end; justify-self: start; margin-bottom: 16px; left: 50%; width: max-content; max-width: calc(100% - 78px); transform: translateX(max(-50%, 66px - 50cqw)); text-align: center; white-space: pre-line; text-wrap: balance; }
/* Whether the small picture shows is read on the picture; :where() keeps these rules as weak as the side layout's. */
:where(.stage:has(> .thumb[hidden])) + .stage-dock > .stage__hint { max-width: calc(100% - 24px); transform: translateX(-50%); }
@container stage (max-width: 359.98px) {
  :where(.stage:has(> .thumb:not([hidden]))) + .stage-dock > .stage__hint { max-width: calc(100% - 24px); transform: translateX(-50%); margin-bottom: 66px; }
}
/* An auto-shoot sentence over a group's note comes as two lines of their own (screens.js), stacked with no gap as the
   two lines of one text were, so a short column on a phone on its side can let the first one go. */
.stage__hint > span { display: block; }
.stage__hint:has(> span) { flex-direction: column; gap: 0; }
@keyframes blink { to { opacity: 0.25; } }

.stage__count { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }
.stage__count b { font-family: var(--font-hand); font-weight: 700; font-size: 7rem; line-height: 1; color: var(--ink); text-shadow: 0 2px 24px oklch(8% 0.02 var(--hue) / 0.7); animation: pop 0.9s var(--ease-out) both; }
@keyframes pop { from { transform: scale(1.5); opacity: 0; } 25% { opacity: 1; } to { transform: scale(0.9); opacity: 0.85; } }
.stage__count small { position: absolute; bottom: 14%; font-size: var(--step--1); color: var(--ink); background: oklch(14% 0.016 var(--hue) / 0.78); padding: var(--space-1) var(--space-3); border-radius: 999px; }
/* Lấy liền: the print develops over the darkened picture like instant film: cream paper, tilted a little, with the
   thick bottom margin of an instant print (three times the side) where the line is handwritten. "xem ảnh luôn" sits under
   the print in cream; the film over the picture is dark enough for it to read 4.5:1 even over a white picture.
   The print is sized to the stage: 72% of its width at most (360px), and low enough that the print and the button
   fit with 8px clear above and below, whatever the photo's shape (--print-ratio, width over height, set by
   developing-print.js). --print-room is everything but the photo: 12px of paper above it, the 36px margin, the 12px
   gap, the 44px button, and 8px clear plus 6.3px for the tilted corners (180px × sin 2°) at the top and the bottom.
   The line on the paper follows the print's width but never goes under 11px; on a narrow print it takes two lines. */
.stage__print { --print-room: 133px; position: absolute; inset: 0; container-type: size; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-3); background: rgba(21, 18, 15, 0.75); }
.print { container-type: inline-size; display: grid; justify-items: center; width: min(72cqw, 360px, (100cqh - var(--print-room)) * var(--print-ratio, 0.75) + 24px); padding: 12px 12px 0; border-radius: 4px; background: #f6f1e6; box-shadow: 0 10px 30px oklch(8% 0.02 var(--hue) / 0.5); transform: rotate(-2deg); }
.print__photo { display: block; width: 100%; height: auto; background: #4a463c; }
.print__note { display: grid; place-items: center; min-height: 36px; margin: 0; text-align: center; text-wrap: balance; line-height: 1.2; font-family: var(--font-hand); font-weight: 600; font-size: clamp(11px, 6.5cqi, var(--step-0)); color: #3a2b1e; font-variant-numeric: tabular-nums; }
.stage__print > .print__now { margin: 0; color: #fff4dc; }
/* While the print shows, the adjust panel and the hint go with the camera behind the film, the moment it shows and the
   moment it goes: the panel is drawn over the picture (camera-controls.css), so it would cover the print or the button
   under it, and the hint would show through the film. They keep their place, so they come back where they were. The
   mode note goes with them: it would lie over the top of the print, whose own line says the same. */
:where(.stage:has(> .stage__print:not([hidden]))) + .stage-dock > :is(.panel, .stage__hint, .toast) { visibility: hidden; }
.stage__flash { position: absolute; inset: 0; background: #fff; opacity: 0; pointer-events: none; }
.stage__flash.is-on { animation: flash 0.28s ease-out; }
@keyframes flash { from { opacity: 0.9; } to { opacity: 0; } }

.stage__loading { position: absolute; inset: 0; display: grid; place-content: center; justify-items: center; gap: var(--space-3); background: oklch(14% 0.016 var(--hue) / 0.9); color: var(--ink-2); font-size: var(--step--1); }
.spin { width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--line); border-top-color: var(--lamp); animation: spin 0.8s linear infinite; }
.spin--lg { width: 32px; height: 32px; border-width: 3px; }
@keyframes spin { to { transform: rotate(360deg); } }

/* As wide as its words up to the frame less 32px (a box set from the middle would get half the frame at most), with
   even lines so the last is not a lone word. Corners of 20px: a note of several lines is a rounded box whose first and
   last lines keep clear of the curve, and a one-line note (about 37px tall) still has round ends. */
.toast { position: absolute; left: 50%; bottom: var(--space-4); transform: translate(-50%, 8px); width: max-content; max-width: calc(100% - 32px); padding: var(--space-2) var(--space-4); border-radius: 20px; background: var(--ink); color: var(--bg); font-size: var(--step--1); font-weight: 600; text-wrap: balance; opacity: 0; pointer-events: none; transition: opacity var(--dur-state) var(--ease-out), transform var(--dur-state) var(--ease-out); text-align: center; }
.toast.is-on { opacity: 1; transform: translate(-50%, 0); }
.stage-dock > .toast { bottom: auto; top: 64px; z-index: 1; } /* the bottom of the picture holds the sliders and the corner buttons; drawn over the adjust panel, which a long note can reach */

/* A phone on its side (landscape, at most 500px tall): the camera takes the whole screen, with no desktop card, and keeps
   clear of the notch at the sides. The controls are a column anchored to the right, its right edge 12px in from the safe
   area, and as wide on a given screen whatever the shape of the picture or the mode, so the shutter never moves: the
   width the screen leaves after a square picture at full height (the widest the camera makes) and the 8px before the
   column, up to 440px. It never goes under 288px, which the mode menu needs for its three columns of names (285px; the
   top bar needs 248px with "photobooth"); on a small screen the square picture gives way instead. The bar sits at the
   top of the column, the tabs and the ring with the shutter at its bottom. The picture is centred in the rest of the
   screen at full height, in its own shape. The dock (the adjust panel, the hint and the mode note) fills the room
   between the bar and the tabs, so nothing but the tools, the small picture and the date is on the picture. The sizes
   are on :root because the result screen (camera-sheet.css) is laid out on the same columns. */
@media (orientation: landscape) and (max-height: 500px) {
  :root {
    --side-l: max(var(--space-2), env(safe-area-inset-left));
    --side-r: calc(env(safe-area-inset-right) + var(--space-3));
    --side-b: max(var(--space-2), env(safe-area-inset-bottom));
    --frame-h: calc(100dvh - var(--space-2) - var(--side-b));
    --controls-w: clamp(288px, 100vw - var(--side-l) - var(--side-r) - var(--frame-h) - var(--space-2), 440px);
  }
  .app[data-screen="camera"] {
    max-width: none; height: 100dvh; margin: 0; border-radius: 0; box-shadow: none;
    padding: var(--space-2) var(--side-r) var(--side-b) var(--side-l);
  }
  .cam {
    display: grid; gap: 0;
    grid-template-columns: minmax(0, 1fr) var(--space-2) var(--controls-w);
    grid-template-rows: auto minmax(0, 1fr) auto;
  }
  .cam__bar { position: static; grid-area: 1 / 3; justify-content: flex-end; }
  /* The picture's box steps aside, so the picture and the dock are placed on the columns themselves. */
  .cam__fit { display: contents; }
  .stage { grid-area: 1 / 1 / 4 / 2; place-self: center; width: min(100vw - var(--side-l) - var(--side-r) - var(--space-2) - var(--controls-w), var(--frame-h) * var(--arn, 0.75)); }
  /* In the column: the mode note at its top, then room, then the hint and the panel 8px apart, 8px above the tabs. With
     too little room whole items give way, never half a line (stage-dock-fit.js sets data-fit): the panel's note first
     (camera-controls.css), then the auto-shoot sentence over a group's note; then the panel keeps the rows that fit
     whole, its name row at least, and scrolls the rest. Still short (a large text size), the hint scrolls. */
  .stage-dock {
    grid-area: 2 / 3; container-type: normal; min-height: 0;
    display: flex; flex-direction: column; justify-content: flex-end; gap: var(--space-2); padding-bottom: var(--space-2);
  }
  .stage-dock > .stage__hint { order: -1; align-self: stretch; position: static; left: auto; width: auto; max-width: none; margin: 0; transform: none; flex: 0 1 auto; min-height: 0; overflow-y: auto; display: block; }
  .stage-dock > .panel { margin: 0; max-height: none; flex: 0 1000 auto; min-height: 48px; }
  .stage-dock[data-fit~="auto"] .stage__hint-auto { display: none; }
  .stage-dock > .toast { top: var(--space-2); left: 0; right: 0; width: auto; max-width: none; transform: translateY(8px); }
  .stage-dock > .toast.is-on { transform: none; }
}
