/* Scan documents to PDF. Loaded only when the scanner opens (loadCss in js/tools/scan.js).
   Colours and sizes come from the tokens in app.css, so the text-size button works here too. */

/* ---------- step 1 ---------- */
/* The first screen is drawn before this file arrives, so nothing here changes the size of its parts:
   the big camera block only changes colour. */
.scan-camera.big { border-color: var(--brand-2); background: var(--brand-soft); }

/* ---------- the working screens ---------- */
.scan-cancel { margin-top: 4px; }

/* ---------- step 2: the look, Download PDF and More options ---------- */
/* The check screen is drawn after this file has arrived (showCheck waits for it), so these rules never move it later. */
.scan-controls { display: grid; gap: 12px; min-width: 0; padding: 12px; border: 2px solid var(--line); border-radius: var(--radius); background: var(--surface); }
.scan-lookbox, .scan-go { display: grid; gap: 8px; align-content: start; min-width: 0; }
@media (min-width: 760px) {
  .scan-controls { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 22px; padding: 18px; }
  .scan-more-body { grid-column: 1 / -1; }
}
/* Color / Black & white: one switch in two halves. The chosen half is filled (white words on blue, against dark words
   on light grey), and Windows High Contrast, which drops the colours, fills it with its own highlight. (No tick: on a
   390 px phone "✓ Black & white" no longer fits on one line and the switch would grow when it is chosen.) */
.scan-switch { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 4px; padding: 4px; border: 2px solid var(--line-2); border-radius: var(--radius-md); background: var(--surface-2); }
.scan-switch .choice { display: flex; align-items: center; justify-content: center; min-width: 0; min-height: 52px; padding: 6px 8px; border: 2px solid transparent; border-radius: 10px; background: transparent; color: var(--ink); text-align: center; }
.scan-switch .choice:hover { border-color: var(--line-2); background: var(--surface); }
.scan-switch .choice.on { border-color: var(--brand-2); background: var(--brand-2); color: #fff; }
.scan-switch .choice.on::after { content: none; }
.scan-switch .choice-title { font-size: 1.05rem; overflow-wrap: anywhere; }
@media (forced-colors: active) { .scan-switch .choice.on { forced-color-adjust: none; border-color: Highlight; background: Highlight; color: HighlightText; } }
.scan-download { gap: 10px; }
.scan-more-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }
.scan-more-btn { display: inline-flex; flex: none; align-items: center; gap: 8px; min-height: 46px; padding: 0 16px; border: 2px solid var(--line-2); border-radius: 999px; background: var(--surface); color: var(--ink); font-size: 1rem; font-weight: 700; cursor: pointer; }
.scan-more-btn:hover { border-color: var(--brand-2); color: var(--brand); }
.scan-more-arrow { display: inline-block; font-size: .9em; line-height: 1; transition: transform .15s; }
.scan-more-btn[aria-expanded="true"] { border-color: var(--brand-2); background: var(--brand-soft); }
.scan-more-btn[aria-expanded="true"] .scan-more-arrow { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .scan-more-arrow { transition: none; } }
/* (beside the button while 7rem is left for it, else on its own line) */
.scan-summary { flex: 1 1 0; min-width: 7rem; color: var(--muted); font-size: .9rem; line-height: 1.3; }
.scan-more-body { display: grid; gap: 14px; min-width: 0; padding-top: 14px; border-top: 1px solid var(--line); }
.scan-more-body .choices.small .choice { flex: 1 1 8.5rem; min-height: 52px; padding: 8px 40px 8px 12px; }
.scan-more-body .check-row { min-height: 52px; }
/* A phone: a second Download PDF button stays at the bottom of the screen while the one above is out of view. It always
   keeps its room at the end of the screen and only turns visible or not, so nothing moves when it does. */
.scan-dock { display: none; }
@media (max-width: 759px) {
  .scan-dock { position: sticky; bottom: 0; z-index: 5; display: block; margin: 0 -16px; padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px)); border-top: 1px solid var(--line); background: var(--bg); box-shadow: 0 -6px 18px rgba(11, 18, 32, .08); }
  .scan-dock.off { visibility: hidden; }
  /* (a control the keyboard moves to is not left under the bar, and a message such as "1 page added." shows above it) */
  html:has(.scan-dock:not(.off)) { scroll-padding-bottom: 104px; }
  html:has(.scan-dock:not(.off)) .toast { bottom: calc(96px + env(safe-area-inset-bottom, 0px)); }
}

/* ---------- step 2: the pages ---------- */
.scan-status:empty { display: none; }
.scan-refresh { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; }
.scan-refresh .btn { flex: none; }
.scan-pages { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; margin: 0; padding: 0; list-style: none; }
@media (min-width: 760px) { .scan-pages { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.scan-card { display: grid; grid-template-columns: minmax(5.5rem, 34%) minmax(0, 1fr); align-items: start; gap: 12px; min-width: 0; padding: 12px; border: 2px solid var(--line); border-radius: 14px; background: var(--surface); }
/* A narrow phone, or big text on a phone: the picture sits above the buttons, so nothing runs past the card. */
@media (max-width: 359px) {
  .scan-card { grid-template-columns: minmax(0, 1fr); }
  .scan-thumb { width: min(100%, 11rem); }
}
@media (max-width: 479px) {
  html[data-text="lg"] .scan-card, html[data-text="xl"] .scan-card { grid-template-columns: minmax(0, 1fr); }
  html[data-text="lg"] .scan-thumb, html[data-text="xl"] .scan-thumb { width: min(100%, 11rem); }
}
.scan-card.busy { border-color: var(--brand-2); }
.scan-card.busy .scan-thumb { opacity: .45; }
.scan-thumb { display: block; padding: 0; border: 1px solid var(--line-2); border-radius: 8px; background: var(--surface-2); overflow: hidden; cursor: zoom-in; }
.scan-thumb.plain { cursor: default; } /* a browser that cannot open the bigger view: the picture is only a picture */
.scan-thumb img { width: 100%; height: auto; }
.scan-card-main { display: grid; gap: 8px; align-content: start; min-width: 0; }
.scan-card-title { font-size: 1.1rem; }
.scan-warn { padding: 8px 10px; border-radius: 10px; background: var(--pro-soft); color: var(--pro); font-size: .9rem; font-weight: 700; }
.scan-tip { padding: 8px 10px; border-radius: 10px; background: var(--surface-2); color: var(--ink-2); font-size: .9rem; }
.scan-adjust { width: 100%; min-width: 0; padding: 0 10px; white-space: normal; overflow-wrap: anywhere; }
/* Turn, up, down, remove: four 44 px buttons in one row (they wrap on a narrow phone or with big text). */
.scan-order { display: flex; flex-wrap: wrap; gap: 6px; }
.scan-order .icon-btn { width: 44px; height: 44px; }
.scan-add { display: grid; gap: 10px; }
.scan-count { color: var(--muted); font-size: .92rem; font-weight: 700; }
.scan-add-btns { display: flex; flex-wrap: wrap; gap: 10px; }
.scan-add-btns .btn { flex: 1 1 15rem; }
.scan-zoom { width: min(94vw, 46rem); max-height: 92vh; padding: 16px; border: 0; border-radius: var(--radius); background: var(--surface); color: var(--ink); }
.scan-zoom::backdrop { background: var(--ink); opacity: .65; }
.scan-zoom h3 { margin-bottom: 10px; }
.scan-zoom img { width: auto; max-width: 100%; max-height: 66vh; margin: 0 auto 14px; border: 1px solid var(--line-2); }

/* "Leave and lose your pages?" (the phone's Back gesture, or a link to another page, while pages are waiting) */
.scan-leave { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 70; display: grid; place-items: center; padding: 16px; background: rgba(11, 18, 32, .72); overflow: auto; }
.scan-leave-box { display: grid; gap: 12px; width: min(100%, 26rem); padding: 20px; border-radius: var(--radius); background: var(--surface); color: var(--ink); box-shadow: var(--shadow); }

/* ---------- adjust corners ---------- */
.scan-edit { display: grid; gap: 12px; min-width: 0; }
.scan-stage { position: relative; margin-inline: auto; border-radius: 4px; background: var(--surface-2); box-shadow: 0 0 0 1px var(--line-2), var(--shadow); }
.scan-stage-photo, .scan-stage-outline { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
/* The handle is a big square to grab (3rem, about 54 px); the round dot inside is what the eye sees. */
.scan-handle { position: absolute; z-index: 2; display: grid; place-items: center; width: 3rem; height: 3rem; margin: -1.5rem 0 0 -1.5rem; padding: 0; border: 0; border-radius: 50%; background: transparent; cursor: grab; touch-action: none; }
.scan-handle:focus-visible { outline: none; }
.scan-handle-dot { width: 1.5rem; height: 1.5rem; border: 3px solid var(--surface); border-radius: 50%; background: var(--brand); box-shadow: 0 0 0 2px var(--ink), var(--shadow); }
.scan-handle:focus-visible .scan-handle-dot { box-shadow: 0 0 0 2px var(--ink), 0 0 0 6px var(--brand), 0 0 0 9px var(--surface); }
/* An older browser (before :focus-visible) drops the rules above, so it shows the ring for any focus. */
@supports not selector(:focus-visible) {
  .scan-handle:focus { outline: none; }
  .scan-handle:focus .scan-handle-dot { box-shadow: 0 0 0 2px var(--ink), 0 0 0 6px var(--brand), 0 0 0 9px var(--surface); }
}
/* Windows High Contrast drops shadows, so the ring is a real outline there. */
@media (forced-colors: active) {
  .scan-handle:focus-visible { outline: 3px solid Highlight; outline-offset: 2px; }
  .scan-handle-dot { forced-color-adjust: none; border-color: Canvas; background: ButtonText; box-shadow: 0 0 0 2px CanvasText; }
  .scan-handle.drag .scan-handle-dot { background: Highlight; }
}
.scan-handle.drag { cursor: grabbing; }
.scan-handle.drag .scan-handle-dot { background: var(--brand-2); box-shadow: 0 0 0 2px var(--ink), 0 0 0 5px var(--surface); }
.scan-loupe { position: absolute; z-index: 3; width: 120px; height: 120px; overflow: hidden; border: 4px solid var(--surface); border-radius: 50%; background: var(--ink); box-shadow: 0 0 0 2px var(--ink), var(--shadow); pointer-events: none; }
.scan-loupe canvas { width: 100%; height: 100%; }
.scan-edit-warn { padding: 12px 14px; border: 2px solid var(--bad-line); border-radius: var(--radius-md); background: var(--bad-soft); color: var(--bad); font-weight: 700; }
.scan-edit-tools { display: flex; flex-wrap: wrap; gap: 10px; }
.scan-edit-tools .btn { flex: 1 1 14rem; }
.scan-edit-go { display: grid; gap: 10px; }
/* Moving a corner with buttons: for people who cannot drag, and for screen readers that keep the arrow keys. */
.scan-nudge { border: 2px solid var(--line); border-radius: var(--radius-md); background: var(--surface); }
.scan-nudge > summary { min-height: 48px; padding: 12px 14px; font-weight: 700; cursor: pointer; }
.scan-nudge-body { display: grid; gap: 12px; padding: 0 14px 14px; }
.scan-nudge-pad { display: grid; grid-template-columns: repeat(3, 4rem); grid-template-areas: ". up ." "left . right" ". down ."; gap: 8px; justify-content: center; }
.scan-nudge-pad .icon-btn { width: 4rem; height: 4rem; font-size: 1.4rem; }
.scan-nudge-pad [data-dir="up"] { grid-area: up; }
.scan-nudge-pad [data-dir="left"] { grid-area: left; }
.scan-nudge-pad [data-dir="right"] { grid-area: right; }
.scan-nudge-pad [data-dir="down"] { grid-area: down; }

/* ---------- the camera ---------- */
.cam-open { overflow: hidden; }
/* The view covers the screen from all four edges (no 100vh or 100dvh: on a phone they can be taller than what is
   visible, which pushed the round button under the browser's toolbar). The padding keeps everything out from under
   a notch or rounded corner when the phone is held on its side. */
.cam { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 60; display: flex; flex-direction: column; padding-top: env(safe-area-inset-top, 0px); padding-right: env(safe-area-inset-right, 0px); padding-left: env(safe-area-inset-left, 0px); background: var(--ink); color: var(--surface); }
.cam :focus-visible { outline-color: var(--surface); }
.cam .btn-ghost { border-color: var(--line-2); color: var(--surface); }
.cam-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 12px; }
.cam-count { margin: 0; font-size: 1rem; font-weight: 700; }
/* (the border is a light grey: the darker --muted was 2.9 to 1 against the black, less than the 3 to 1 a control's outline needs) */
.cam-btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 48px; padding: 0 14px; border: 2px solid var(--line-2); border-radius: var(--radius-md); background: var(--ink-2); color: var(--surface); font-size: .98rem; font-weight: 700; line-height: 1.15; text-align: center; cursor: pointer; }
.cam-btn:hover { border-color: var(--surface); }
.cam-btn:disabled { opacity: .4; cursor: not-allowed; }
.cam-btn[aria-pressed="true"] { border-color: var(--surface); background: var(--brand-2); }
.cam-ic { display: inline-flex; flex: none; width: 1.4rem; height: 1.4rem; }
.cam-ic svg { width: 100%; height: 100%; }
.cam-done { border-color: var(--surface); background: var(--brand-2); }
.cam-stage { position: relative; flex: 1 1 auto; min-height: 0; overflow: hidden; }
.cam-video, .cam-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
.cam-video { object-fit: contain; background: var(--ink); }
.cam-overlay { pointer-events: none; }
/* The message sits under the picture and always keeps room for two lines, so the picture does not jump when it changes. */
.cam-status { display: grid; place-items: center; min-height: 3.4rem; margin: 6px 12px 0; padding: 6px 16px; border: 2px solid var(--line-2); border-radius: var(--radius-md); background: var(--ink); color: var(--surface); font-size: .95rem; font-weight: 700; line-height: 1.3; text-align: center; }
.cam-status:empty { visibility: hidden; }
.cam-status[data-state="found"] { border-color: var(--ok-line); background: var(--ok); }
.cam-flash { position: absolute; top: 0; right: 0; bottom: 0; left: 0; background: var(--surface); opacity: 0; pointer-events: none; }
.cam-flash.go { animation: cam-flash .25s ease-out; }
@keyframes cam-flash { from { opacity: .8; } to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .cam-flash.go { animation: none; } }
.cam-strip { display: flex; gap: 6px; margin: 0; padding: 6px 12px; list-style: none; overflow-x: auto; }
.cam-strip li { flex: none; }
.cam-strip img { width: auto; height: 3rem; border: 2px solid var(--surface); border-radius: 4px; }
.cam-bar { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 12px; padding: 10px 12px calc(12px + env(safe-area-inset-bottom, 0px)); }
.cam-side { display: grid; gap: 8px; align-content: center; min-width: 0; }
.cam-side:last-child { justify-items: end; }
.cam-side:first-child .cam-btn { justify-self: start; }
.cam-shutter { display: grid; place-items: center; width: 80px; height: 80px; padding: 5px; border: 4px solid var(--surface); border-radius: 50%; background: transparent; cursor: pointer; }
.cam-shutter-dot { width: 100%; height: 100%; border-radius: 50%; background: var(--surface); }
.cam-shutter:active .cam-shutter-dot { transform: scale(.88); }
.cam-shutter:disabled { opacity: .4; cursor: not-allowed; }
/* A narrow phone, or big text: the side buttons put the picture above the word and the word may wrap, so the
   round button never sits on top of Done, Undo or Other camera. */
@media (max-width: 400px) {
  .cam-btn { flex-direction: column; gap: 2px; padding: 4px 8px; font-size: .85rem; }
  .cam-top .cam-btn { flex-direction: row; gap: 8px; padding: 0 14px; font-size: .98rem; }
  .cam-shutter { width: 72px; height: 72px; }
  .cam-bar { gap: 8px; }
}
html[data-text="xl"] .cam-bar .cam-btn, html[data-text="lg"] .cam-bar .cam-btn { flex-direction: column; gap: 2px; padding: 4px 8px; font-size: .82rem; }
/* A short screen (a small phone, or any phone held on its side) gives the picture every pixel it can. */
@media (max-height: 700px) {
  .cam-top { padding: 4px 12px; }
  .cam-status { min-height: 2.4rem; margin-top: 4px; padding: 4px 12px; font-size: .88rem; }
  .cam-strip { padding: 4px 12px; }
  .cam-strip img { height: 2.2rem; }
  .cam-bar { padding-top: 6px; padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px)); }
}
/* The camera could not start: the message sits in the middle when it fits. When the screen is too short it starts at
   the top and scrolls, so the heading and the last button can always be reached (margin auto on the first and last
   child centres the group without cutting off its top). The bar of buttons is hidden then: none of them work. */
.cam-error { position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 4; display: flex; flex-direction: column; align-items: center; gap: 16px; padding: 24px; overflow: auto; background: var(--ink); text-align: center; }
.cam-error > :first-child { margin-top: auto; }
.cam-error > :last-child { margin-bottom: auto; }
.cam.has-error .cam-bar, .cam.has-error .cam-strip, .cam.has-error .cam-status { display: none; }
.cam-error-title { font-size: 1.5rem; }
.cam-error p { max-width: 30rem; font-size: 1.08rem; }
.cam-error-btns { display: grid; gap: 12px; width: min(100%, 22rem); }
.cam-confirm { position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 6; display: grid; place-items: center; padding: 16px; background: var(--ink); overflow: auto; }
.cam-confirm-box { display: grid; gap: 12px; width: min(100%, 26rem); padding: 20px; border-radius: var(--radius); background: var(--surface); color: var(--ink); }
.cam-confirm-box :focus-visible { outline-color: var(--brand); }
/* A phone held on its side: the buttons move to the right-hand edge. */
@media (orientation: landscape) and (max-height: 520px) {
  .cam { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto minmax(0, 1fr) auto auto; grid-template-areas: "top bar" "stage bar" "status bar" "strip bar"; }
  .cam-top { grid-area: top; }
  .cam-stage { grid-area: stage; }
  .cam-status { grid-area: status; min-height: 2.6rem; }
  .cam-strip { grid-area: strip; }
  .cam-bar { grid-area: bar; grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto auto; align-content: space-between; justify-items: center; padding: 10px 12px; }
  .cam-side, .cam-side:last-child { justify-items: center; }
  .cam-side:first-child .cam-btn { justify-self: center; }
  .cam-error { padding: 12px 16px; gap: 10px; }
  .cam-error-title { font-size: 1.2rem; }
  .cam-error p { font-size: .98rem; }
  .cam-error-btns { grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); width: min(100%, 44rem); gap: 8px; }
  .cam-error-btns .btn { min-height: 3rem; font-size: 1rem; }
}
