#cropDialog {
  box-sizing: border-box; width: min(1120px, calc(100vw - 24px));
  height: min(880px, calc(100dvh - 24px)); max-width: none; max-height: none;
  margin: auto; padding: 0; border: 1px solid var(--border, #3c3c3c);
  border-radius: 16px; color: var(--text, #eee); background: var(--panel, #202020);
  font: inherit; overflow: hidden;
}
#cropDialog[open] { display: grid; grid-template-rows: auto auto minmax(0, 1fr) auto auto; grid-template-columns: minmax(0, 1fr); }
#cropDialog::backdrop { background: rgba(0, 0, 0, .8); }
#cropDialog button, #cropDialog select { min-height: 44px; box-sizing: border-box; font: inherit; }
#cropDialog button:focus-visible, #cropDialog select:focus-visible, #cropFrame:focus-visible { outline: 2px solid var(--accent, #dda958); outline-offset: 3px; }
.crop-header, .crop-controls, .crop-footer { display: flex; align-items: center; gap: 12px; padding: 10px 20px; }
.crop-header { justify-content: space-between; border-bottom: 1px solid var(--border, #383838); }
.crop-header h2 { font-size: 16px; margin: 0; font-weight: 500; }
#cropClose { width: 44px; padding: 0; display: grid; place-items: center; }
.crop-tabs { display: none; } /* tabbed layouts only, see the media blocks below */
.crop-controls { flex-wrap: wrap; }
.crop-controls label, .crop-field { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.crop-field-label { color: var(--muted, #aaa); }
#cropRatio { display: flex; flex-wrap: wrap; gap: 6px; }
/* a pair carries ONE outer border and background; the chips inside are bare,
   so the active accent ring never sits next to a chip border (double border) */
#cropRatio .ratio-pair { display: inline-flex; border: 1px solid var(--border, #3c3c3c); border-radius: 6px; background: var(--panel2, #292929); }
#cropDialog #cropRatio .chip { min-width: 44px; justify-content: center; padding: 4px 10px; }
#cropDialog #cropRatio .chip.active { background: #33290f; color: var(--accent, #dda958); box-shadow: inset 0 0 0 1px var(--accent, #dda958); }
#cropDialog #cropRatio .ratio-pair .chip { border: none; background: none; border-radius: 0; }
#cropDialog #cropRatio .ratio-pair .chip:first-child { border-radius: 5px 0 0 5px; }
#cropDialog #cropRatio .ratio-pair .chip:last-child { border-radius: 0 5px 5px 0; }
#cropDialog #cropRatio .ratio-pair .chip + .chip { border-left: 1px solid var(--border, #3c3c3c); }
/* the divider next to the active chip would double up with its accent ring */
#cropDialog #cropRatio .ratio-pair .chip.active + .chip,
#cropDialog #cropRatio .ratio-pair .chip + .chip.active { border-left-color: transparent; }
.crop-controls select { min-width: 120px; padding: 0 12px; color: inherit; background: var(--panel2, #292929); border: 1px solid var(--border, #444); border-radius: 8px; }
.crop-stage { display: flex; align-items: center; justify-content: center; min-height: 0; overflow: hidden; background: #101010; }
.crop-picture { position: relative; flex: none; }
.crop-picture > canvas { display: block; width: 100%; height: 100%; }
#cropFrame { position: absolute; box-sizing: border-box; border: 2px solid var(--accent, #dda958); box-shadow: 0 0 0 2000px rgba(0, 0, 0, .58); cursor: move; touch-action: none; }
#cropGuides { width: 100%; height: 100%; display: block; pointer-events: none; }
#cropDialog .crop-handle { position: absolute; width: 44px; height: 44px; min-width: 44px; padding: 0; background: transparent; border: none; border-radius: 0; box-shadow: none; touch-action: none; }
.crop-handle::before { content: ''; position: absolute; width: 12px; height: 12px; border: 3px solid #fff; background: var(--accent, #dda958); border-radius: 3px; left: 14px; top: 14px; }
.crop-handle[data-handle=nw] { left: -23px; top: -23px; cursor: nwse-resize; }
.crop-handle[data-handle=ne] { right: -23px; top: -23px; cursor: nesw-resize; }
.crop-handle[data-handle=sw] { left: -23px; bottom: -23px; cursor: nesw-resize; }
.crop-handle[data-handle=se] { right: -23px; bottom: -23px; cursor: nwse-resize; }
/* round picture-edge markers steer the perspective draft — shape carries the
   difference from the square crop corners, the palette stays amber/white
   (corners: amber fill + white ring; edges: white fill + amber ring) */
#cropDialog .geo-handle { position: absolute; width: 44px; height: 44px; min-width: 44px; padding: 0; background: transparent; border: none; border-radius: 0; box-shadow: none; touch-action: none; z-index: 2; }
.geo-handle::before { content: ''; position: absolute; width: 14px; height: 14px; border: 3px solid var(--accent, #dda958); background: #fff; border-radius: 50%; left: 12px; top: 12px; }
.geo-handle[data-edge=n] { left: calc(50% - 22px); top: -23px; cursor: ew-resize; }
.geo-handle[data-edge=s] { left: calc(50% - 22px); bottom: -23px; cursor: ew-resize; }
.geo-handle[data-edge=e] { right: -23px; top: calc(50% - 22px); cursor: ns-resize; }
.geo-handle[data-edge=w] { left: -23px; top: calc(50% - 22px); cursor: ns-resize; }
/* the alignment zone reads as one unit: hairline above, Auto inside the row
   (it sets these three sliders — it is not a dialog action like Apply) */
.crop-geo { display: flex; align-items: center; gap: 20px; padding: 12px 20px; border-top: 1px solid var(--border, #383838); }
.crop-geo label { flex: 1; display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted, #aaa); white-space: nowrap; }
.crop-geo label svg { flex: none; opacity: .8; }
.crop-geo input[type=range] { flex: 1 1 auto; width: auto; min-width: 0; }
.crop-geo label span { min-width: 46px; text-align: right; font-variant-numeric: tabular-nums; }
#cropDialog .crop-geo #geoAuto { flex: none; padding: 0 16px; }
.crop-footer { flex-wrap: wrap; justify-content: space-between; padding-bottom: max(12px, env(safe-area-inset-bottom)); }
.crop-status { flex: 1; min-width: 160px; color: var(--muted, #aaa); font-size: 12px; line-height: 1.5; }
.crop-status p { margin: 0; }
.crop-actions { display: flex; gap: 8px; }
.crop-actions button { padding: 0 18px; }
/* .primary drops the 1px button border globally; in a flex-equal footer that
   makes Apply 2px narrower than its siblings — keep the border, transparent */
#cropDialog .crop-actions button.primary { border: 1px solid transparent; }
/* every screen narrower than 721px or shorter than 501px: the title gives
   way to a Crop | Align switch and ONE tool panel shows at a time. Both panels
   share a grid cell, so the cell is as tall as the taller panel and a switch
   never moves the photo; visibility also drops the hidden panel from tab
   order and the accessibility tree. Stacking every control left the photo a
   38px strip on a 390x664 Safari viewport. Default placement is the sheet:
   tool row and actions under the photo */
@media (max-width: 720px), (max-height: 500px) {
  #cropDialog { width: 100%; height: 100dvh; border: 0; border-radius: 0; }
  #cropDialog[open] { grid-template-rows: auto minmax(0, 1fr) auto auto; grid-template-areas: "head" "stage" "tool" "foot"; }
  .crop-header { grid-area: head; padding: max(2px, env(safe-area-inset-top)) 8px 2px 12px; }
  /* still names the dialog and the ratio group, just not on screen */
  .crop-header h2, .crop-field-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .crop-tabs { display: inline-flex; border: 1px solid var(--border, #3c3c3c); border-radius: 8px; background: var(--panel2, #292929); }
  #cropDialog .crop-tabs [role=tab] { min-width: 76px; padding: 0 16px; border: none; border-radius: 0; background: none; color: var(--muted, #aaa); }
  #cropDialog .crop-tabs [role=tab]:first-child { border-radius: 7px 0 0 7px; }
  #cropDialog .crop-tabs [role=tab]:last-child { border-radius: 0 7px 7px 0; }
  #cropDialog .crop-tabs [role=tab] + [role=tab] { border-left: 1px solid var(--border, #3c3c3c); }
  #cropDialog .crop-tabs [aria-selected=true] { background: #33290f; color: var(--accent, #dda958); box-shadow: inset 0 0 0 1px var(--accent, #dda958); }
  #cropDialog .crop-tabs [aria-selected=true] + [role=tab], #cropDialog .crop-tabs [role=tab] + [aria-selected=true] { border-left-color: transparent; }
  .crop-stage { grid-area: stage; --crop-inset: 20px; }
  .crop-controls, .crop-geo { grid-area: tool; border-top: 1px solid var(--border, #383838); padding: 8px 12px; }
  #cropDialog[data-tool=align] .crop-controls, #cropDialog:not([data-tool=align]) .crop-geo { visibility: hidden; }
  .crop-controls { flex-direction: column; flex-wrap: nowrap; align-items: stretch; justify-content: center; gap: 8px; }
  /* min-width:0: a scroll row's min-content would otherwise propagate up and
     stretch the whole dialog wider than the viewport */
  .crop-field { min-width: 0; }
  .crop-controls label { justify-content: space-between; }
  .crop-controls select { flex: 1; min-width: 0; max-width: 220px; }
  /* ratios scroll sideways in one row and fade over the last 24px so the row
     reads as scrollable; 5px of padding keeps the focus ring (2px + 3px
     offset) out of the clip */
  #cropRatio { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding: 5px 24px 5px 5px; margin: -5px; -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent); }
  #cropRatio::-webkit-scrollbar { display: none; }
  #cropRatio .chip, #cropRatio .ratio-pair { flex: none; }
  /* one 44px line per axis (name, slider, value), Auto beside all three */
  .crop-geo { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-auto-rows: 44px; gap: 0 12px; align-content: center; padding-block: 4px; }
  .crop-geo label { grid-column: 1; display: grid; grid-template-columns: 36px minmax(0, 1fr) 52px; column-gap: 8px; }
  .crop-geo label svg { display: none; } /* the text label carries it */
  .crop-geo label span { min-width: 0; }
  #cropDialog .crop-geo #geoAuto { grid-column: 2; grid-row: 1 / 4; align-self: center; }
  .crop-footer { grid-area: foot; gap: 8px; padding: 8px 12px max(10px, env(safe-area-inset-bottom)); border-top: 1px solid var(--border, #383838); }
  /* readout beside the buttons; under ~370px it takes its own line above them
     and the three equal buttons share the full row */
  .crop-status { flex: 1 1 100px; min-width: 0; font-size: 11.5px; line-height: 1.35; }
  .crop-status #cropHelp { display: none; }
  .crop-actions { flex: 1 0 auto; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; }
  .crop-actions button { padding: 0 14px; }
}
/* side panel for short screens (phones held sideways): photo left, one tool
   column right, padding clear of the notch and the home indicator */
@media (max-height: 500px) and (min-width: 480px) {
  #cropDialog { padding: 0 env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); }
  #cropDialog[open] { grid-template-columns: minmax(0, 1fr) 264px; grid-template-rows: auto minmax(0, 1fr) auto; grid-template-areas: "head head" "stage tool" "stage foot"; }
  .crop-controls, .crop-geo { border-top: 0; border-left: 1px solid var(--border, #383838); overflow-y: auto; }
  /* the narrow column stacks the guides label over its select and drops Auto
     under the sliders */
  .crop-controls label { flex-direction: column; align-items: stretch; gap: 4px; }
  .crop-controls select { flex: none; max-width: none; }
  .crop-geo { grid-template-columns: minmax(0, 1fr); }
  #cropDialog .crop-geo #geoAuto { grid-column: 1; grid-row: auto; justify-self: stretch; }
  .crop-footer { flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 6px; padding: 8px 12px; border-left: 1px solid var(--border, #383838); }
  .crop-status, .crop-actions { flex: none; }
}
