/* The interface font, Inter 4.1 (SIL Open Font License 1.1, its licence in public/fonts beside it), served
   from our own host as two variable cuts of the Inter project's own web file, InterVariable.woff2. Latin
   covers every character of the on-screen text and is preloaded by index.html. Latin-ext loads only when a
   name on screen holds one of its letters. Both keep the tailed l and serifed I (cv05 and cv08, turned on by
   --font-features) that keep I, l and 1 apart in task card and file names, the figure features and the
   layout features the earlier cuts had. The optical size axis is pinned at 14, the text design the page
   shows with optical sizing off, and the weight axis runs 400 to 700, the weights the page uses (400, 500,
   600 and 700). Each file also holds the few characters outside its range that the earlier cut's file held
   (five combining accents, and in Latin-ext the space and no-break space). Cut with fontTools 4.66.1 and
   its brotli module from the release file, so the same commands make the same files:
   fonttools varLib.instancer --no-recalc-timestamp InterVariable.woff2 opsz=14 wght=400:700 -o InterText.woff2
   pyftsubset InterText.woff2 --unicodes="U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD" --layout-features="calt,ccmp,cv05,cv08,dnom,frac,kern,locl,mark,mkmk,numr,pnum,tnum" --flavor=woff2 --output-file=inter-4.1-latin.woff2
   pyftsubset InterText.woff2 --unicodes="U+0000,U+0020,U+0041,U+00A0,U+00C4,U+0100-02FF,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF" --layout-features="calt,ccmp,cv05,cv08,dnom,frac,kern,locl,mark,mkmk,numr,pnum,tnum" --flavor=woff2 --output-file=inter-4.1-latin-ext.woff2 */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/fonts/inter-4.1-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/fonts/inter-4.1-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Until Inter arrives: Arial sized to Inter's measures (measured from the Inter 4.001 cut against Arial,
   whose widths and heights Inter 4.1 keeps), so the swap barely moves text */
@font-face {
  font-family: "Inter Fallback";
  src: local("Arial");
  size-adjust: 107.04%;
  ascent-override: 90.50%;
  descent-override: 22.53%;
  line-gap-override: 0%;
}

/* Design tokens: the colours, fonts, type sizes, line heights, spacing steps, radii, border widths,
   shadows, motion and sizes the rules below use, named once here. The look of phase 6: an off-white page,
   steel blue actions, headings and focus, copper accents, one 4 px spacing scale and no text under 12 px.
   Each colour pair a rule draws holds WCAG AA on the background it sits on: 4.5:1 for text, 3:1 for edges,
   symbols and large text. The older names below the new ones are aliases, so every rule keeps working
   while later commits move the rules onto the new names. */
:root {
  /* Colours, brand. The page is off-white, cards, the ribbon and dialogs are white. */
  --color-page: #F9F8F5;
  --color-surface: #FFFFFF;
  /* Hover fills, sunken areas and the annotate page area */
  --color-surface-2: #F3F2EE;
  /* Ink with a blue cast, 15.3:1 on the page and 16.3:1 on white */
  --color-text: #17212B;
  /* The brand grey, for secondary text on white only (4.59:1). On the page it measures 4.32, so text
     there takes the deeper grey (5.63:1 on the page, 5.25:1 on the blue tint). */
  --color-text-secondary: #767576;
  --color-text-secondary-page: #646364;
  /* Steel blue for actions, links, headings and focus, 7.16:1 on the page, white on it 7.61:1 */
  --color-primary: #175883;
  --color-primary-hover: #12476B;
  --color-primary-pressed: #0F3F5F;
  /* File bands, the Did you know card and selected rows, and the stronger tint for hover on them */
  --color-primary-tint: #EAF1F7;
  --color-primary-tint-strong: #DCE7F0;
  /* The brand copper, 3.48:1 on the page: fills, edges, symbols and large text only, never body text.
     Copper text is the deeper copper (5.54:1 on the copper tint). */
  --color-copper: #C2703D;
  --color-copper-deep: #8F4F24;
  --color-copper-tint: #F8EEE6;
  /* Dividers and card edges, and the edges of symbol and secondary buttons, decorative since the symbol
     or label tells the control. A field's edge is its only cue, so it holds 3:1 on white. */
  --color-border: #E3E2DE;
  --color-border-strong: #D5D4D0;
  --color-field-border: #898989;
  /* The dark band at the bottom: its text 10.76:1, its links white */
  --color-band: #132029;
  --color-on-band: #C5D2DC;
  /* The steel blue bench, its deep colour (Drop to load), the lighter strip of the Did you know note on
     Start's band (white on it 5.67:1), its secondary and greyed text and its grid */
  --color-bench: #175883;
  --color-bench-deep: #0F3F5F;
  --color-bench-light: #336C92;
  --color-on-bench-2: #D9E4ED;
  --color-on-bench-off: #9FB3C2;
  --color-blueprint: rgba(255, 255, 255, 0.07);
  /* The lines of the browser outline Start's loop plays in, white at 40% on the bench */
  --color-on-bench-line: rgba(255, 255, 255, 0.4);
  /* Under the pointer on the bench, a white fill at 12%, and the hairline under the file panel's top row */
  --color-on-bench-hover: rgba(255, 255, 255, 0.12);
  --color-on-bench-rule: rgba(255, 255, 255, 0.12);
  /* The disc under the play symbol on Start's paused animation, the band's ink at 72% */
  --color-loop-play: rgba(19, 32, 41, 0.72);

  /* Colours, function, apart from the brand. Caution red for overlap marks, caution symbols and edges,
     failure notices and refused fields, 6.57:1 on white. */
  --color-danger: #B42318;
  --color-caution-bg: #FEF3F2;
  --color-warning: #8A5A00;
  --color-success: #18794E;
  /* The band's hue behind dialogs, and the loading cover */
  --color-scrim: rgba(19, 32, 41, 0.55);
  --color-cover: rgba(249, 248, 245, 0.92);
  /* The band's hue at 40%, dimming the screen around Drop to load */
  --color-scrim-drop: rgba(19, 32, 41, 0.4);

  /* Colours, states and marks. Pressed toggles, the selected page frame and the selected marking are
     steel blue, never black. */
  --color-selected: var(--color-primary);
  /* The focus ring, steel blue, and white where a control sits on a dark or steel blue surface */
  --color-focus: var(--color-primary);
  --color-focus-on-dark: #FFFFFF;
  /* Disabled text and symbols, the disabled fill and edge. Disabled text holds 3.07:1 on its fill. */
  --color-disabled-fg: #898989;
  --color-disabled-bg: #F1F0EC;
  --color-disabled-border: #E3E2DE;
  /* The move mark of a moved page, the overlap check's caution mark, and the snap and split guides */
  --color-move-mark: var(--color-copper);
  --color-overlap-mark: var(--color-danger);
  /* The bell's badge, steel blue, red while an unread message is a failure or a warning */
  --color-badge: var(--color-primary);
  --color-badge-alert: var(--color-danger);
  /* The edge of the Review control's red tile on the ribbon */
  --color-caution-edge: #F2C4BF;
  /* A warning's pale amber in the bell's panel */
  --color-warning-tint: #FCF1DC;
  --color-guide: var(--color-copper);
  /* A page card not selected keeps a light dim, a removed page shows at 40% under a hatch of thin ink
     lines, and the box a mouse draws to select pages is a 40% steel blue tint */
  --opacity-unselected: 0.7;
  --opacity-removed: 0.4;
  --opacity-select-box: 0.4;
  --color-hatch: rgba(23, 33, 43, 0.22);
  /* A hint notice: the copper tint with ink, its label in the deeper copper (14.3:1 and 5.54:1) */
  --color-hint: var(--color-copper-tint);
  --color-hint-text: var(--color-text);
  --color-hint-label: var(--color-copper-deep);
  /* Text and symbols on a dark or steel blue background */
  --color-on-dark: white;
  /* Behind a page as it is drawn */
  --color-paper: white;
  /* The Save PDF dialog's page map (deck Screen 8): its band, a page with signoff in steel blue, the edge
     of a page without, a page that overlaps content in the caution red, the dashed strip of a signoff
     margin and the copper dot of a moved page. Each holds 3:1 on the band. */
  --color-map-band: var(--color-surface-2);
  --color-map-signoff: var(--color-primary);
  --color-map-empty: var(--color-text-secondary);
  --color-map-overlap: var(--color-danger);
  --color-map-margin: var(--color-text-secondary-page);
  --color-map-moved: var(--color-copper);
  /* The tick before the side panel's heading after a save, steel blue as a page with signoff */
  --color-saved: var(--color-primary);
  /* Older names. The page, muted text (the deeper grey, which holds 4.5:1 on the page, white and every
     tint), faint for disabled only, and the accent, which is the steel blue now. */
  --color-bg: var(--color-page);
  --color-text-muted: var(--color-text-secondary-page);
  --color-text-faint: var(--color-disabled-fg);
  --color-accent: var(--color-primary);
  --color-accent-hover: var(--color-primary-hover);
  --color-accent-light: var(--color-primary-tint);

  /* Shadows, tinted with the ink: raised cards and thumbnails, popovers, menus, tooltips and notices,
     dialogs, sheets and the side panel, and a page drawn on a card or in the annotate area */
  --shadow-raised: 0 0 2px rgba(23, 33, 43, 0.10), 0 1px 3px rgba(23, 33, 43, 0.12);
  --shadow-popover: 0 0 2px rgba(23, 33, 43, 0.12), 0 8px 16px rgba(23, 33, 43, 0.14);
  --shadow-dialog: 0 0 2px rgba(23, 33, 43, 0.12), 0 24px 48px rgba(23, 33, 43, 0.22);
  --shadow-page: 0 1px 3px rgba(23, 33, 43, 0.14);
  /* Older names */
  --shadow-sm: var(--shadow-raised);
  --shadow-md: var(--shadow-popover);
  --shadow-lg: var(--shadow-dialog);

  /* Font families */
  --font-sans: "Inter", "Inter Fallback", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "SF Mono", ui-monospace, Menlo, Monaco, Consolas, monospace;
  /* Inter's tailed l and serifed I, so I, l and 1 never read alike in names. Figures are set apart through
     font-variant-numeric, so these two never turn tabular figures off. */
  --font-features: "cv05" 1, "cv08" 1;
  /* Figures of one width for page numbers and counts, so Page 9 and Page 10 and the counts never jump */
  --numeric: tabular-nums;

  /* Type sizes, smallest first, nothing under 12 px. The file panel's heading is 28 px on phones. Start's
     heading grows with the window, from 21 px at 320 px wide and about 26 px at 375 px to 46 px from about
     600 px wide, on iPads and wider. */
  --text-xs: 12px;
  /* The count in a badge */
  --text-badge: 11px;
  --text-sm: 14px;
  --text-md: 16px;
  --text-lg: 20px;
  --text-2xl: 24px;
  --text-3xl: 32px;
  --text-3xl-phone: 28px;
  --text-hero-min: 21px;
  --text-hero-max: 46px;
  --text-hero: clamp(var(--text-hero-min), calc(9.091vw - 8.091px), var(--text-hero-max));
  /* Older names */
  --text-4xs: var(--text-xs);
  --text-3xs: var(--text-xs);
  --text-2xs: var(--text-xs);
  --text-base: var(--text-sm);
  --text-xl: var(--text-lg);

  /* Line heights on the 4 px grid, one for each type size */
  --leading-xs: 16px;
  --leading-sm: 20px;
  --leading-md: 24px;
  --leading-lg: 28px;
  --leading-2xl: 32px;
  --leading-3xl: 40px;
  --leading-3xl-phone: 36px;
  --leading-hero: 1.13;
  /* Older names, as ratios. 16 / 12 and 20 / 14 put 12 and 14 px text on the grid in whole pixels. */
  --leading-1: 1;
  --leading-2: 1.25;
  --leading-3: 1.25;
  --leading-4: calc(16 / 12);
  --leading-5: calc(20 / 14);
  --leading-6: calc(20 / 14);
  --leading-7: 1.5;
  --leading-8: 1.5;

  /* Font weights: captions and tags medium, controls, labels and band names semibold, the Start heading
     and dialog titles bold */
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;
  /* Letter spacing: tight at 24 px and above, snug from 16 to 20 px, none below */
  --tracking-tight: -0.02em;
  --tracking-snug: -0.01em;

  /* Spacing, one 4 px scale for padding, margins, gaps and offsets, smallest first, and the side gutter
     on phones */
  --space-2xs: 2px;
  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 12px;
  --space-lg: 16px;
  --space-xl: 20px;
  --space-2xl: 24px;
  --space-3xl: 32px;
  --space-4xl: 40px;
  --space-5xl: 48px;
  --space-gutter-phone: var(--space-lg);
  /* Older names, each on the nearest step of the scale. The 1 px step stays for hairline offsets only. */
  --space-1: 1px;
  --space-2: var(--space-2xs);
  --space-3: var(--space-xs);
  --space-4: var(--space-xs);
  --space-5: var(--space-sm);
  --space-6: var(--space-sm);
  --space-7: var(--space-sm);
  --space-8: var(--space-sm);
  --space-9: var(--space-md);
  --space-10: var(--space-md);
  --space-11: var(--space-md);
  --space-12: var(--space-lg);
  --space-13: var(--space-lg);
  --space-14: var(--space-lg);
  --space-15: var(--space-xl);
  --space-16: var(--space-2xl);
  --space-17: var(--space-2xl);
  --space-18: var(--space-3xl);
  --space-19: var(--space-4xl);

  /* Corner radii: tags, controls (buttons, fields, symbol buttons, thumbnails), cards (popovers, menus,
     notices, bands), panels (dialogs, sheet tops, the bench) */
  --radius-tag: 4px;
  --radius-control: 6px;
  --radius-card: 8px;
  --radius-panel: 12px;
  --radius-pill: 999px;
  --radius-round: 50%;
  /* Older names. The 2 px radius stays for inner marks. */
  --radius-xs: 2px;
  --radius-sm: var(--radius-tag);
  --radius-md: var(--radius-control);
  --radius-lg: var(--radius-panel);

  /* Border and outline widths, and the left edge of a caution */
  --border-thin: 1px;
  --border-medium: 2px;
  --border-thick: 3px;
  --border-edge: 4px;
  /* The edge of the copper Beta pill */
  --border-pill: 1.5px;
  /* The edge of a page without signoff on the Save PDF dialog's map, and the dashed strip of a margin */
  --border-map: 1.5px;

  /* Motion. Durations: a press, hover and a popover leaving, a popover coming and a notice leaving, the
     notice stack closing up and a dialog coming, a notice coming, a phone sheet, and Start's loop. */
  --dur-instant: 70ms;
  --dur-fast: 100ms;
  --dur-quick: 150ms;
  --dur-reflow: 200ms;
  --dur-toast: 240ms;
  --dur-sheet: 250ms;
  --dur-loop: 7600ms;
  /* One turn of the loading spinner */
  --dur-spin: 800ms;
  /* The bell's one short shake as a message comes */
  --dur-shake: 500ms;
  /* How long a tooltip shown by hover stays once the pointer has left its control and the tooltip, so the
     pointer can cross the gap onto it (WCAG 1.4.13). A wait read by src/tooltip.ts, not motion, so reduced
     motion keeps it. */
  --dur-tooltip-grace: 300ms;
  /* Curves for what comes in, what goes out and what moves on screen */
  --ease-enter: cubic-bezier(0, 0, 0.38, 0.9);
  --ease-exit: cubic-bezier(0.2, 0, 1, 0.9);
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);
  /* How far a popover and a notice slide, how far a notice moves down as it leaves, and the scale a
     dialog grows from */
  --move-popover: 8px;
  --move-notice: 16px;
  --move-notice-out: 8px;
  --scale-dialog: 0.96;

  /* Sizes */
  /* The smallest height of a control pressed by a finger */
  --size-touch: 44px;
  /* The symbol drawn in a symbol button, and a check box or radio */
  --size-symbol: 20px;
  /* A notice's close symbol and action, 44 px on touch screens */
  --size-notice-close: 32px;
  /* The tallest the notice stack grows on a phone before it scrolls inside: 40% of the window, which is
     half the room the workspace leaves between its bars at 390 by 844 and at 375 by 667, so at least half
     of what the user works on stays in view however many notices show */
  --size-notices-phone: 40dvh;
  --size-check: 16px;
  /* The notifications bell's badge, and the Review control's count */
  --size-badge: 16px;
  /* The bell and the menu symbol on phones, each this wide and the touch size tall */
  --size-header-round-phone: 40px;
  /* The bell's panel: its width and tallest height on the ribbon, each entry's unread dot, the margin it sits
     in and the kind's symbol */
  --size-notify-w: 340px;
  --size-notify-h: 480px;
  --size-notify-dot: 6px;
  --size-notify-dot-col: 22px;
  --size-notify-symbol: 16px;
  /* The header and the logo in it, lower on phones, the tool bars at the foot of the screen on the bar
     layout (the workspace's five symbol buttons and the annotate screen's four, a 24 px symbol alone in a
     56 px bar, owner 15 Oct), and the rows under the header there, the workspace's and the annotate screen's
     with the View group, Undo and Done.
     On a short landscape screen the bars and the header are slim rows and their controls a little lower. */
  --size-header: 64px;
  --size-header-phone: 48px;
  --size-header-short: 40px;
  --size-logo-h: 32px;
  --size-logo-h-phone: 28px;
  --size-bar: 56px;
  --size-bar-short: 40px;
  --size-bar-symbol: 24px;
  --size-phone-top-row: 52px;
  --size-touch-short: 36px;
  /* The hairline between two groups of the ribbon, as tall as a control with a little to spare */
  --size-ribbon-divider: 48px;
  /* Choose PDFs, taller than other buttons as Start's main action, the copper disc of the Did you know
     card, and the squares of the bench's blueprint grid */
  --size-choose: 48px;
  --size-tip-disc: 36px;
  /* The (i)'s symbol, and with a mouse beside Start's drop line its target, the smallest WCAG 2.5.8 asks
     for, and the gap between the drop line's words and the symbol (owner, 14 Oct) */
  --size-info-symbol: 18px;
  --size-drop-info: 24px;
  --size-drop-gap: 6px;
  --size-blueprint: 24px;
  /* The measure of Start's heading in its own size, so it breaks after its second word (measured in Inter
     bold: its last three words take 10.71 em, its first three 15.88 em) */
  --size-hero-measure: 13em;
  /* Start's animation at its widest, and at its smallest, the least height it keeps where Start fits the
     window (owner, 15 Oct), and the play symbol's disc on it while paused */
  --size-loop-max: 760px;
  --size-loop-min: 120px;
  --size-loop-play: 48px;
  /* The window height at and below which the Did you know strip and the step pills on Start's band keep
     their least padding. Each grows evenly with the window from there to its full padding 160 px higher. */
  --size-fit-low: 560px;
  /* A file band's number disc, and on a page card the selected tick disc and the move mark */
  --size-band-disc: 28px;
  --size-tick-disc: 20px;
  --size-move-mark: 20px;
  /* The narrowest a card in a grid of cards may be */
  --size-card: 200px;
  /* The height of every card on the bench in Cards view (owner, 11 Oct): the 200 px first page with the
     number's badge on its corner (owner, 17 Oct), a name of two lines, the Duplicate tag, the page count and
     the row of symbols, with the card's 16 px padding */
  --size-bench-card: 364px;
  /* The number's badge on a card's first page, round, smaller on phones */
  --size-bench-badge: 24px;
  --size-bench-badge-phone: 20px;
  /* On phones the grip's width at the row's start, and each half of the joined up and down control, a
     finger's size tall (owner, 18 Oct) */
  --size-bench-grip-phone: 24px;
  --size-bench-move-w: 40px;
  --size-bench-move-h: var(--size-touch);
  /* The narrowest card on the bench, its first page's box and padding, as the mockups draw four in a row */
  --size-bench-card-w: 184px;
  /* The content width of Start and the file panel, their sides included (the mockups'), and one row of
     the list */
  --size-bench-max: 1200px;
  --size-bench-row: 56px;
  /* On phones each card in Cards view is a row this tall (phase 6 P3), with its first page's box shown at
     this share of its size, 52 by 72 px (owner, 17 Oct), the row as tall as the joined up and down control,
     two 44 px halves and its three 1 px lines, with the 12 px padding (owner, 18 Oct). --size-bench-card
     takes the row's height there. */
  --size-bench-card-phone: 115px;
  --size-bench-thumb-zoom: 0.36;
  /* The three pages drawn in Drop to load, smaller on phones */
  --size-drop-art: 176px;
  --size-drop-art-phone: 128px;
  /* The width of a popover panel holding choices, as the copy panel, and of a dialog at its widest */
  --size-panel: 360px;
  --size-dialog: 480px;
  /* The width of the side panel after a save, which slides in from the right, and its heading's tick disc */
  --size-side-panel: 400px;
  --size-saved-tick: 28px;
  /* The loading spinner's ring */
  --size-spinner: 32px;
  /* The width of Help, a panel from the right on wider screens */
  /* A tray's padding, the width of a symbol's slot in it, the height of a row of words and the narrowest a tray
     of words may be */
  --size-tray-pad: 6px;
  --size-tray-item: 46px;
  --size-tray-row: 40px;
  /* Undo's tile in the annotate screen's row under the header, and how much more readily Undo gives way there
     than the row's gaps when the row is short of room, so they close only once Undo is a control's width */
  --size-row-tile: 64px;
  --shrink-first: 1000;
  --size-tray-words: 200px;
  /* The width of the header menu's sidebar, and the strip of the page it leaves in view on a phone */
  --size-sidebar: 340px;
  --size-sidebar-shade: 72px;
  /* A row of the sidebar */
  --size-sidebar-row: 56px;
  /* The width of the legal panel's text, as on the site's own pages */
  --size-legal-text: 820px;
  /* The grab line at the top of a sheet on phones, drawn for looks only */
  --size-grab-w: 36px;
  --size-grab-h: 4px;
  /* The footer's one line, its copper top line included, above any home indicator inset, lower on phones */
  --size-footer: 32px;
  --size-footer-phone: 28px;
  /* How tall a split line of a column is to a press where its rows allow (main.ts fitSplitHits), and its remove
     symbol, the smallest target WCAG 2.5.8 asks for (phase 7 fix run, audit finding 29), and the ring of a
     split line with keyboard focus or picked by a tap. On touch screens a split line takes a finger's width. */
  --size-split-hit: 24px;
  --size-split-ring: 12px;
  --size-split-remove: 24px;
  /* A not required cell's clear mark: the round symbol, as large as a split's remove symbol, and the box a
     press finds it in, the symbol and a gap from the marking's outline. On touch screens the box takes a
     finger's width. */
  --size-nr-clear: var(--size-split-remove);
  --size-nr-clear-hit: 32px;
  /* How far a resize handle of the selected column or N/A box reaches to a press, across its edge, and how
     much of that lies inside the marking, at most. On touch screens it takes a finger's width. The small
     square that shows it on the selection outline, the same size with a mouse as on touch. */
  --size-resize-hit: 16px;
  --size-resize-in: 5px;
  --size-resize-grip: 10px;
  /* The caution mark on a marking the overlap check flags, a target as large as the split remove symbol's,
     and the width of the popover of choices it opens */
  --size-overlap-mark: 24px;
  --size-overlap-panel: 240px;
  /* A mark of the Save PDF dialog's page map, page-shaped, at three sizes by the number of pages saved
     (save.ts), with the gap between marks and the moved dot over a mark. A tile's swatch, the legend of
     a mark. */
  --size-map-mark-w: 12px;
  --size-map-mark-h: 17px;
  --size-map-gap: 4px;
  --size-map-dot: 5px;
  --size-map-mark-w-medium: 7px;
  --size-map-mark-h-medium: 10px;
  --size-map-gap-medium: 3px;
  --size-map-dot-medium: 4px;
  --size-map-mark-w-small: 4px;
  --size-map-mark-h-small: 6px;
  --size-map-gap-small: 2px;
  --size-map-dot-small: 3px;
  --size-map-swatch-w: 8px;
  --size-map-swatch-h: 12px;
  --size-map-tile: 96px;

  /* Markings on screen. They show what the saved PDF holds, black lines in the server's drawing, so
     they are not interface colours, except the selected marking's steel blue outline. */
  --marking-ink: #000;
  --marking-font: "Marking Sans", Helvetica, Arial, sans-serif;
  --marking-outline: inset 0 0 0 1px var(--marking-ink);
  --marking-selected: var(--color-selected);
  --marking-selected-width: 1.5px;
  --marking-selected-offset: 2px;
  /* A resize handle's square: its steel blue border, two whole pixels so it never thins to one on a desktop
     screen as the outline's 1.5 px does, and a white ring that parts it from the outline and the page's lines */
  --marking-grip-width: 2px;
  --marking-grip-ring: 0 0 0 1px var(--color-surface);
  /* A cell of the selected block or column under the pointer while Not required is on, the selected
     marking's steel blue, faint enough to keep its lines readable */
  --marking-cell-hover: rgba(23, 88, 131, 0.12);
  /* The dotted line where a page ends and its signoff margin's strip begins, the brand grey (4.59:1 on
     white paper) apart from the selected marking's steel blue */
  --color-page-edge: var(--color-text-secondary);
}
/* With reduced motion nothing slides or grows and every duration over 100 ms becomes 100 ms, so only
   fades remain. Start's loop shows its last frame at once. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-quick: 100ms;
    --dur-reflow: 100ms;
    --dur-toast: 100ms;
    --dur-sheet: 100ms;
    --dur-loop: 0ms;
    --move-popover: 0px;
    --move-notice: 0px;
    --move-notice-out: 0px;
    --scale-dialog: 1;
  }
}
/* Under forced colours the focus ring takes the system's highlight colour, on every surface */
@media (forced-colors: active) {
  :root { --color-focus: Highlight; --color-focus-on-dark: Highlight; }
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  font-family: var(--font-sans);
  font-feature-settings: var(--font-features);
  /* Inter's text design at every size, as the earlier cut drew it, rather than its display design */
  font-optical-sizing: none;
  background: var(--color-bg);
  color: var(--color-text);
  min-height: 100vh;
  min-height: 100dvh;
  font-size: var(--text-base);
  line-height: var(--leading-7);
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
}

/* Page numbers and counts: Page n of N and its number box, the page cards' numbers, the file and card
   numbers with their page counts, the bands' changes, the bookmark counts and the Save dialog's pages line and tiles */
.annotate-title, .annotate-goto, .annotate-goto-field,
.thumb-page-num, .thumb-pending-label, .thumb-drag-count,
.file-band-number, .file-band-pages, .file-band-changes, .file-band-changes-short, .bench-card-number, .bench-card-pages,
.bookmark-file-number, .bookmark-pages,
.save-summary-pages, .save-tile-value { font-variant-numeric: var(--numeric); }

/* Buttons and fields set their own font in the browser's styles, which drops the page's font features */
button, input, select, textarea { font-feature-settings: inherit; font-optical-sizing: inherit; }

/* Check boxes and radios: the browser's own, ticked in steel blue, one size everywhere */
input[type="checkbox"], input[type="radio"] { width: var(--size-check); height: var(--size-check); accent-color: var(--color-primary); }

/* No double tap zooms the window from a control (owner, 15 Oct, view controls): two quick taps on Next page
   turn two pages, and two on a pad step move twice. Every control area takes manipulation, which a
   touch on anything inside it follows too: the header, the workspace's tool row under it on the bar layout
   (Thumbnail size, Undo, Settings, Files and Save), the workspace ribbon and bar with their pads, the annotate tool row and
   bar with the View group (the page strip, Zoom and its tray) and the copy panel, the trays, menus and
   popovers, dialogs and panels, the bench, the file bands, the review bar, the notices, Start's controls and
   the footer. One finger still scrolls and two fingers still pinch the window there (WCAG 1.4.4), so the
   viewport meta keeps its zoom. The page area keeps its own pan-x pan-y, with the tool's pinch (main.ts). */
:is(.header, .tool-row, .toolbar, .annotate-toolbar, .annotate-view, .tray, .menu, .popover, .save-modal-overlay,
  .file-panel, .file-band, .review-bar, .notices, .start-actions, .start-loop, .app-footer) { touch-action: manipulation; }

/* The bottom band, from the window's bottom up: the footer, pinned last with nothing under it, then the
   notices above it. The footer shows on Start, the bench and the files screen only (B20 point 5), and
   frame.ts keeps its height in --footer-h, 0 while it is hidden. What is scrolled into view stops
   above the band, and the page ends with room for it, so the last cards and Start's content stay above
   it. frame.ts keeps the header and toolbar's height in --top-bars-h, so what is scrolled into view, a
   card reached by Tab among them, also stops below the bars. While notices show
   (notices.ts adds notices-shown and keeps the stack's height in --notices-h), the room at the end and
   the stop reach up to the stack's top instead, so the last cards and a card reached by Tab can always
   be seen clear of the stack. --notices-above is how far the stack's bottom sits above the window's
   bottom, --notices-gap (8 px) above the band, the same as the gaps between notices. The footer keeps
   clear of the iPhone home bar, so the band above it does too, and so does the bar at the foot of the
   workspace and the annotate screen on the bar layout, which keeps the inset as its own bottom padding.
   Where neither shows (the workspace and the annotate screen on the full ribbon) the band is the home
   indicator inset alone, so an iPad's home indicator stays clear of the annotate screen and the notices.
   On Start with files, benchbar.ts keeps the heights of the file panel's rows held in place: the
   band's foot with Compile joins the band above the footer (--bench-bar-h), and the stop also clears
   the band's top bar under the header (--bench-top-h). Each is 0 wherever it does not apply.
   On the bar layout (layout.ts) the workspace toolbar is a bar held at the window's foot, and frame.ts keeps
   its height in --tools-bar-h (0 wherever the toolbar is not that bar). It joins the band while the
   workspace shows, and not while the annotate or files screen covers the workspace and hides it. The
   annotate screen's tool row is such a bar there too, and joins the band in its place while that screen
   shows.
   Until frame.ts first measures the footer, --footer-h is the footer's own height on Start, its band and the
   home indicator inset under it, so the first paint lays Start out as it stays (owner, 17 Oct). */
html {
  --footer-h: calc(var(--size-footer) + env(safe-area-inset-bottom));
  --tools-band-h: var(--tools-bar-h, 0px);
  --bottom-band-h: max(calc(var(--footer-h, 0px) + var(--bench-bar-h, 0px) + var(--tools-band-h)), env(safe-area-inset-bottom));
  --notices-gap: var(--space-sm);
  --notices-above: calc(var(--bottom-band-h) + var(--notices-gap));
  --page-end: var(--bottom-band-h);
  scroll-padding-top: calc(var(--top-bars-h, 0px) + var(--bench-top-h, 0px));
  scroll-padding-bottom: var(--page-end);
}
html.notices-shown { --page-end: calc(var(--notices-above) + var(--notices-h, 0px)); }
/* The page is at least as tall as the window shows it now (dvh), so on an iPhone it follows Safari's toolbars
   as they show and hide, never the larger height the toolbars leave when hidden (100vh), and a page that
   fits has nothing to scroll. Start fills it and shrinks inside it (below). 100vh only for a browser
   without dvh. */
.app { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; padding-bottom: var(--page-end); }

/* Read by screen readers, never shown */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* The header and the toolbar under it stay at the top as one block while the page scrolls. frame.ts
   writes the header's height to --header-h and the block's to --top-bars-h. While a menu or popover in
   the block is open, the block shows above the notices (src/popover.ts). */
.top-bars { position: sticky; top: 0; z-index: 10; }
.top-bars.raised { z-index: 101; }

/* The header: white, --size-header tall (lower on phones), with a hairline under it. The wings mark at the
   logo's height, a hairline divider, the tool name, Beta beside it and the menu symbol at the right. The
   mark shows alone on every screen and at every width, with no wordmark (owner, 16 Oct, look check: the
   tools line is kept apart from the analytics business), and is named by header.logo. Swapping in an SVG is
   its src in index.html, since the width follows the file. */
.header {
  min-height: var(--size-header);
  background: var(--color-surface);
  border-bottom: var(--border-thin) solid var(--color-border);
  padding: 0 max(var(--space-2xl), env(safe-area-inset-right)) 0 max(var(--space-2xl), env(safe-area-inset-left));
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
}

.header-brand { display: flex; align-items: center; gap: var(--space-lg); min-width: 0; }

.header-logo { display: flex; align-items: center; flex-shrink: 0; }
.header-logo img { display: block; height: var(--size-logo-h); width: auto; }

/* The tool name, set off from the logo by a hairline as the mockups draw it */
.header-title {
  min-width: 0;
  padding-left: var(--space-lg);
  border-left: var(--border-thin) solid var(--color-border);
  font-size: var(--text-md);
  line-height: var(--leading-md);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-snug);
  color: var(--color-text);
}

/* Beta beside the tool name, a copper pill in a button the touch size tall, and its note below it.
   popover.ts moves the note sideways when the window is too narrow to hold it there. The focus ring
   goes round the pill. */
.beta { position: relative; flex-shrink: 0; margin-left: calc(-1 * var(--space-xs)); }
.beta-btn {
  display: inline-flex;
  align-items: center;
  min-height: var(--size-touch);
  padding: 0 var(--space-xs);
  border: none;
  background: transparent;
  font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.beta-tag {
  display: block;
  padding: var(--space-2xs) var(--space-sm);
  border: var(--border-pill) solid var(--color-copper);
  border-radius: var(--radius-pill);
  background: var(--color-copper-tint);
  color: var(--color-copper-deep);
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
  font-weight: var(--weight-semibold);
  transition: border-color var(--dur-fast);
}
.beta-btn:hover .beta-tag, .beta-btn[aria-expanded="true"] .beta-tag { border-color: var(--color-copper-deep); }
.beta-btn:focus-visible { outline: none; }
.beta-btn:focus-visible .beta-tag { outline: var(--border-medium) solid var(--color-focus); outline-offset: var(--space-2xs); }

/* The menu symbol at the right of the header (owner, 15 Oct, in Help's place): a round symbol button with no
   edge at rest (owner, 13 Oct). It keeps the
   touch size, the round sunken fill under the pointer and the focus ring. Like the other symbols without
   an edge (the close symbols), it draws no boundary of its own under forced colours. */
.header-actions { display: flex; align-items: center; gap: var(--space-sm); flex-shrink: 0; }
.icon-btn.icon-btn-round { border: 0; border-radius: var(--radius-round); }
/* The notifications bell (owner, 16 Oct), the same round button just left of the menu symbol, its badge at
   the symbol's top right: the unread count in white on steel blue, or on red while any unread message is a
   failure or a warning, ringed in the header's white. One short shake when a message comes (bell.ts), none
   under reduced motion. */
.bell-btn { position: relative; }
/* The bell and the menu symbol side by side with no gap between their targets, as the look images draw them
   (50 to 58), and on phones each 40 px wide, still the touch size tall, so the tool's name stays on one line
   beside the mark and Beta at 393 px. Under 390 px the mark, the name and the header's parts close up a
   little too, so it stays on one line at 375 px (the narrowest phone supported). */
.header-actions > .bell-btn ~ #menuBtn { margin-left: calc(-1 * var(--space-sm)); }
.bell-badge {
  position: absolute;
  top: var(--space-xs);
  right: var(--space-xs);
  box-sizing: border-box;
  min-width: var(--size-badge);
  height: var(--size-badge);
  padding: 0 var(--space-xs);
  border-radius: var(--radius-pill);
  background: var(--color-badge);
  box-shadow: 0 0 0 var(--border-pill) var(--color-surface);
  color: var(--color-on-dark);
  font-size: var(--text-badge);
  line-height: var(--size-badge);
  font-weight: var(--weight-semibold);
  font-variant-numeric: var(--numeric);
  text-align: center;
  pointer-events: none;
}
.bell-badge.is-alert { background: var(--color-badge-alert); }
.bell-btn.is-shaking .bell-symbol { animation: bell-shake var(--dur-shake) var(--ease-standard); transform-origin: 50% 8%; }
@keyframes bell-shake {
  15% { transform: rotate(14deg); }
  35% { transform: rotate(-12deg); }
  55% { transform: rotate(8deg); }
  75% { transform: rotate(-5deg); }
  to { transform: rotate(0); }
}
@media (prefers-reduced-motion: reduce) {
  .bell-btn.is-shaking .bell-symbol { animation: none; }
}
@media (forced-colors: active) {
  .bell-badge { forced-color-adjust: none; background: CanvasText; color: Canvas; box-shadow: none; }
}
/* The bell's panel (owner, 16 Oct, bell.ts): the tray card, in the top layer, its title fixed at its top and
   its list scrolling inside it, so the page behind never moves. On the ribbon and a short landscape screen
   340 px wide under the bell, no taller than 480 px or 60% of the window, on the upright bar layout across
   the window inside the 16 px gutters, and each no lower than 8 px above the bottom band. */
.notify-panel {
  position: fixed;
  z-index: 2;
  box-sizing: border-box;
  flex-direction: column;
  width: var(--size-notify-w);
  max-width: calc(100vw - 2 * var(--space-sm));
  max-height: min(var(--size-notify-h), 60dvh, calc(100dvh - var(--notify-top, 0px) - var(--bottom-band-h) - var(--space-sm)));
  padding: 0;
  overflow: hidden;
  background: var(--color-surface);
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius-panel);
  box-shadow: var(--shadow-popover);
  color: var(--color-text);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  touch-action: manipulation;
}
.notify-panel:not([hidden]) { display: flex; }
.notify-panel[popover] { inset: auto; margin: 0; }
:where(html.bar-layout:not(.bar-short)) .notify-panel[popover] {
  left: max(var(--space-gutter-phone), env(safe-area-inset-left));
  right: max(var(--space-gutter-phone), env(safe-area-inset-right));
  width: auto;
  max-width: none;
  max-height: calc(100dvh - var(--notify-top, 0px) - var(--bottom-band-h) - var(--space-sm));
}
.notify-title {
  flex: 0 0 auto;
  margin: 0;
  padding: var(--space-md) var(--space-lg);
  border-bottom: var(--border-thin) solid var(--color-border);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  font-weight: var(--weight-regular);
  color: var(--color-text-secondary-page);
}
.notify-empty { margin: 0; padding: var(--space-lg); color: var(--color-text-secondary-page); }
.notify-list {
  flex: 1 1 auto;
  min-height: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.notify-list:focus-visible { outline: var(--border-medium) solid var(--color-focus); outline-offset: calc(-1 * var(--border-medium)); }
/* One entry: the unread dot in its own narrow margin at the left, then the top line with the kind's symbol
   and label at its left and the time at its right, then the message, which starts at the same left edge in
   every entry, ragged at its right. A 1 px line between entries. Its kind's tint: an error pale red, a
   warning pale amber, a hint pale copper, done white. */
.notify-entry {
  display: grid;
  grid-template-columns: var(--size-notify-dot-col) minmax(0, 1fr);
  align-items: center;
  row-gap: var(--space-2xs);
  padding: var(--space-sm) var(--space-lg) var(--space-md) 0;
  background: var(--color-surface);
}
.notify-entry + .notify-entry { border-top: var(--border-thin) solid var(--color-border); }
.notify-entry[data-kind="failure"] { background: var(--color-caution-bg); }
.notify-entry[data-kind="warning"] { background: var(--color-warning-tint); }
.notify-entry[data-kind="hint"] { background: var(--color-hint); }
.notify-dot {
  grid-column: 1;
  grid-row: 1;
  justify-self: center;
  width: var(--size-notify-dot);
  height: var(--size-notify-dot);
  border-radius: var(--radius-round);
  background: var(--color-primary);
  visibility: hidden;
}
.notify-entry.is-unread > .notify-dot { visibility: visible; }
.notify-head {
  grid-column: 2;
  grid-row: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  margin: 0;
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
}
.notify-kind { display: inline-flex; align-items: center; gap: var(--space-xs); min-width: 0; font-weight: var(--weight-medium); color: var(--color-text-secondary-page); }
.notify-symbol { flex: 0 0 auto; width: var(--size-notify-symbol); height: var(--size-notify-symbol); overflow: visible; }
.notify-entry[data-kind="failure"] .notify-kind { color: var(--color-danger); }
.notify-entry[data-kind="warning"] .notify-kind { color: var(--color-warning); }
.notify-entry[data-kind="hint"] .notify-kind { color: var(--color-hint-label); }
.notify-time { flex: 0 0 auto; color: var(--color-text-secondary-page); font-variant-numeric: var(--numeric); white-space: nowrap; }
.notify-message {
  grid-column: 2;
  margin: 0;
  text-align: left;
  overflow-wrap: anywhere;
  color: var(--color-text);
}
@media (forced-colors: active) {
  .notify-dot { forced-color-adjust: none; background: CanvasText; }
}

@media (max-width: 640px) {
  .header {
    min-height: var(--size-header-phone);
    padding-left: max(var(--space-gutter-phone), env(safe-area-inset-left));
    padding-right: max(var(--space-gutter-phone), env(safe-area-inset-right));
    gap: var(--space-sm);
  }
  .header-brand { gap: var(--space-md); }
  .header-logo img { height: var(--size-logo-h-phone); }
  .header-title { padding-left: var(--space-md); }
}
/* The bell and the menu symbol on phones, and the header closed up under 390 px (above) */
@media (max-width: 640px) {
  :where(html:not(.bar-short)) .header-actions > :is(.bell-btn, #menuBtn) { min-width: var(--size-header-round-phone); width: var(--size-header-round-phone); }
}
@media (max-width: 389.98px) {
  :where(html:not(.bar-short)) .header { gap: var(--space-xs); }
  :where(html:not(.bar-short)) .header-brand { gap: var(--space-sm); }
  :where(html:not(.bar-short)) .header-title { padding-left: var(--space-sm); }
}

/* A popover: a white card with the popover shadow, its title and text, as the Beta note, the privacy note
   and the panels built on it have. The Beta note comes in with a short fade and slide down, and with
   reduced motion only fades. */
.popover {
  position: absolute;
  top: calc(100% + var(--space-xs));
  left: 0;
  z-index: 1;
  width: 320px;
  max-width: calc(100vw - 16px);
  padding: var(--space-lg);
  background: var(--color-surface);
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-popover);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
}
.popover-title { font-weight: var(--weight-semibold); margin-bottom: var(--space-sm); }
.popover-link { margin-top: var(--space-md); text-decoration: none; }
.beta .popover { animation: popover-in var(--dur-quick) var(--ease-enter); }
@keyframes popover-in { from { opacity: 0; transform: translateY(calc(-1 * var(--move-popover))); } }

/* The footer, the dark band pinned at the bottom of the landing screens, Start and the bench, and of the
   files screen (owner, 13 Oct, B20 point 5, frame.ts hides it on the workspace and the annotate screen),
   under notices, menus and dialogs. It never holds tools or links. One slim line of small text on every
   width (owner, 8 Oct), --size-footer tall with its copper line on top: the copyright notice on the left and
   the version on the right (owner, 15 Oct, navigation rework). Where the full notice and the version do not
   fit side by side, the short notice shows in its place (owner, 16 Oct, frame.ts), and only where even that
   has no room does it wrap. Its bottom padding keeps it clear of the iPhone home bar, under the
   line. The band's text holds 10.76:1. */
.app-footer {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 90;
  background: var(--color-band);
  border-top: var(--border-medium) solid var(--color-copper);
  padding: 0 max(var(--space-2xl), env(safe-area-inset-right)) env(safe-area-inset-bottom) max(var(--space-2xl), env(safe-area-inset-left));
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0 var(--space-2xl);
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
  color: var(--color-on-band);
}
.app-footer > p { display: flex; align-items: center; min-height: calc(var(--size-footer) - var(--border-medium)); margin: 0; }
.footer-copyright { flex: 0 1 auto; min-width: 0; }
/* The ruler frame.ts reads the full notice's width from, in the footer's own type, out of sight, out of the
   line and hidden from screen readers, in a box of no size that clips it, so it never reaches past the
   window */
.footer-ruler { position: absolute; left: 0; top: 0; width: 0; height: 0; overflow: hidden; visibility: hidden; pointer-events: none; }
.footer-ruler > span { position: absolute; left: 0; top: 0; white-space: nowrap; }
.footer-version { flex: 0 0 auto; white-space: nowrap; }

/* Start (owner, 12 Oct, the hero band). Desktop and iPad held sideways: the heading at the top left and
   Choose PDFs at the top right, level with it, then one steel blue band with the blueprint grid filling
   the screen down to the legal line, which sits on the page over the footer (owner, 14 Oct). iPad held
   upright, phones and narrow windows: the heading and Choose PDFs centred, one above the other, over the
   band, which runs from edge to edge. The band holds the animation, the three steps and the Did you know
   strip at its foot. The file panel takes the screen once files land (below), with its own width and
   padding.
   Side by side from 1000 px wide in landscape (owner, 13 Oct, testing item 14), switched before anything
   would wrap or narrow. The breakpoint comes from the real widths: the padding (2 by 24 px), the heading at
   its full measure (13em of 46 px, 598 px), the gap (40 px) and the widest Choose PDFs column (Choose PDFs,
   Undo and the (i) on touch screens, 271 px) take 957 px, and a scrollbar up to 17 px, so 26 px spare
   before the heading would narrow and about 130 px more before it would need a third line. Choose PDFs
   and its column never narrow or wrap. The message check's "Start: Choose files centred against the
   heading" fails when that column grows past the breakpoint.
   The whole of Start fits the window as it shows now, header to footer, with no page scroll (owner, 15
   Oct): the page is the window's height (.app) and the band takes what the heading, Choose PDFs and the
   legal line leave, so the animation and the band's inner spacing grow and shrink with the window while
   the heading, Choose PDFs, the drop line, the legal line and the footer keep their sizes. Once the
   animation is at --size-loop-min and the spacing at its least, the page scrolls as any page does and
   ends at the footer's foot. On phones the room above the heading is the small --space-lg (owner, 15 Oct). */
.start-screen {
  position: relative;
  flex: 1;
  width: 100%;
  margin: 0 auto;
  display: grid;
  grid-template: auto minmax(0, 1fr) auto / minmax(0, 1fr);
}
.start-intro {
  width: 100%;
  max-width: var(--size-bench-max);
  margin: 0 auto;
  padding: var(--space-lg) var(--space-gutter-phone) var(--space-2xl);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xl);
  text-align: center;
}
@media (min-width: 641px) {
  .start-intro { padding: var(--space-4xl) var(--space-2xl) var(--space-3xl); }
}
@media (min-width: 1000px) and (orientation: landscape) {
  .start-intro { flex-direction: row; justify-content: space-between; gap: var(--space-4xl); text-align: left; }
}

.start-heading { font-size: var(--text-2xl); font-weight: 700; line-height: var(--leading-3); letter-spacing: -0.01em; margin-bottom: var(--space-15); }
/* The heading before files land, the tagline: large bold ink, growing with the window from about 26 px on
   a 375 px phone to 46 px on an iPad and wider. Its measure, in its own size, is wider than its last three
   words and narrower than its first three, so it always breaks after "maintenance", one heading to screen
   readers. */
.start-intro .start-heading {
  max-width: var(--size-hero-measure);
  margin: 0;
  font-size: var(--text-hero);
  line-height: var(--leading-hero);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight);
}

/* Choose PDFs with the lines that can stand in its place, centred under the heading, or at the right */
.start-side {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  min-width: 0;
  max-width: min(100%, var(--size-dialog));
}
@media (min-width: 1000px) and (orientation: landscape) {
  .start-side { flex: none; align-items: flex-end; }
}

/* Choose PDFs and, with a mouse or trackpad, the drop line under it with its (i). On touch screens the
   line is hidden and the (i) sits beside Choose PDFs. Dropping still works everywhere. The note on how
   PDFs are handled opens right under the (i), with no gap, so the mouse can move onto it and it stays
   open. While it shows, this block shows above the notices (src/popover.ts). */
.start-actions {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0 var(--space-xs);
  max-width: 100%;
}
@media (min-width: 1000px) and (orientation: landscape) {
  .start-actions { justify-content: flex-end; }
}
.start-actions.raised { z-index: 101; }
.start-actions .popover { top: 100%; left: auto; right: 0; text-align: left; }
/* Choose PDFs, the main action of Start: taller than other buttons with larger words, its upload symbol
   before them (two classes, so it wins over .btn further down) */
.btn.start-choose {
  min-height: var(--size-choose);
  padding: 0 var(--space-2xl) 0 var(--space-xl);
  font-size: var(--text-md);
  line-height: var(--leading-md);
}
.start-choose svg { flex: none; width: var(--size-symbol); height: var(--size-symbol); }
/* Undo after Choose PDFs, while Start shows as before files and the bench's Undo is pending */
.start-undo { margin-left: var(--space-xs); }
/* The drop line, on one line always */
.start-drop {
  display: none;
  color: var(--color-text-secondary-page);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  white-space: nowrap;
}
/* Two rows, Choose PDFs with Undo, then the drop line with the (i) and its note. On touch screens the rows
   leave no box of their own, so Choose PDFs, Undo and the (i) share one line as before. */
.start-row { display: contents; }
/* With a mouse or trackpad (owner, 13 Oct, testing item 14) each row is centred on the other, a gap as
   wide as Undo before Choose PDFs while Undo shows after it. The drop line and its (i) are one unit
   centred under Choose PDFs (owner, 14 Oct): the (i) a smaller target here, its symbol --size-drop-gap
   after the words and centred on their line, its box reaching past the words and the row only by its
   padding, so the row ends where the symbol does. The note opens under the drop line's row, its right
   edge on the (i)'s. */
@media (any-pointer: fine) and (any-hover: hover) {
  .start-actions { flex-direction: column; flex-wrap: nowrap; gap: var(--space-xs); }
  .start-row { display: flex; align-items: center; gap: var(--space-xs); }
  .start-drop-row { position: relative; gap: 0; }
  .start-row:has(> .start-undo:not([hidden]))::before { content: ""; flex: none; width: var(--size-touch); }
  .start-undo { margin-left: 0; }
  .start-drop { display: block; }
  .start-drop-row .info-btn {
    --info-pad: calc((var(--size-drop-info) - var(--size-info-symbol)) / 2);
    min-width: var(--size-drop-info);
    min-height: var(--size-drop-info);
    margin: 0 calc(-1 * var(--info-pad)) 0 calc(var(--size-drop-gap) - var(--info-pad));
  }
}
/* The legal line (owner, 14 Oct): one small grey sentence on the page under Start's band, centred on the
   window with even room above and below it before the footer, its two links in the links' steel blue and
   each kept whole. One line on desktops and iPads, two even lines on phones: the last line holds at least
   the Privacy notice link's two words, and balancing keeps the first as long, so no line is a single
   word. Hidden with the band once files land. */
.start-legal {
  justify-self: center;
  width: max-content;
  max-width: calc(100% - 2 * var(--space-gutter-phone));
  margin: 0;
  padding: var(--space-md) 0;
  color: var(--color-text-secondary-page);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  text-align: center;
  text-wrap: balance;
}
.start-legal a { color: var(--color-primary); text-underline-offset: var(--space-2xs); white-space: nowrap; }
.start-legal a:hover { color: var(--color-primary-hover); }
.start-legal a:focus-visible { outline: var(--border-medium) solid var(--color-focus); outline-offset: var(--border-medium); border-radius: var(--radius-xs); }
@media (min-width: 641px) {
  .start-legal { max-width: calc(100% - 2 * var(--space-2xl)); }
}
/* The (i): a steel blue symbol (7.16:1 on the page) with a finger-sized target */
.info-btn svg { flex: none; width: var(--size-info-symbol); height: var(--size-info-symbol); }
.info-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--size-touch);
  min-height: var(--size-touch);
  padding: 0;
  border: none;
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--color-primary);
  cursor: pointer;
  transition: background-color var(--dur-fast), color var(--dur-fast);
  -webkit-tap-highlight-color: transparent;
}
.info-btn:hover { color: var(--color-primary-hover); background: var(--color-surface-2); }
.info-btn:focus-visible { outline: var(--border-medium) solid var(--color-focus); outline-offset: calc(-1 * var(--border-medium)); }

/* The bench (look plan, Hangar blueprint): one deep steel blue surface with a faint blueprint grid, white
   lines every 24 px drawn by the page, no image. Start's band is made of it, and the file panel and Drop
   to load share it. Text on it is white (7.61:1) or the pale blue (5.90:1), and focus rings turn white. */
.bench-surface {
  --color-focus: var(--color-focus-on-dark);
  background-color: var(--color-bench);
  background-image:
    linear-gradient(var(--color-blueprint) var(--border-thin), transparent var(--border-thin)),
    linear-gradient(90deg, var(--color-blueprint) var(--border-thin), transparent var(--border-thin));
  background-size: var(--size-blueprint) var(--size-blueprint);
  background-position: calc(-1 * var(--border-thin)) calc(-1 * var(--border-thin));
  border-radius: var(--radius-panel);
  color: var(--color-on-dark);
}

/* Start's band: the animation centred and as large as the band allows, the three steps in one row under
   it and the Did you know strip across its foot, ending above the legal line. Edge to edge and square on
   narrow and upright screens. On wide screens it lines up with the heading and Choose PDFs, its top
   corners rounded, the Did you know strip square across its foot. Its gaps (--band-gap at full size) grow
   and shrink with the room it has, never under --space-sm: the room above and below the animation inside
   its own box (below), and the gap between the steps and the strip, which takes its share of any room
   beyond the least until it is full. The strip comes after that gap by its order. */
.start-loop {
  --band-side: var(--space-gutter-phone);
  --band-gap: var(--space-xl);
  display: flex;
  flex-direction: column;
  padding: 0 var(--band-side);
  border-radius: 0;
}
.start-loop::after { content: ""; order: 1; flex: 1 0 var(--space-sm); max-height: var(--band-gap); }
@media (min-width: 641px) {
  .start-loop { --band-side: var(--space-2xl); --band-gap: var(--space-2xl); }
}
@media (min-width: 1000px) and (orientation: landscape) {
  .start-loop {
    --band-side: var(--space-3xl);
    width: calc(100% - 2 * var(--space-2xl));
    max-width: calc(var(--size-bench-max) - 2 * var(--space-2xl));
    margin: 0 auto;
    border-radius: var(--radius-panel) var(--radius-panel) 0 0;
  }
}
/* The room for the animation: all the band leaves, at least --size-loop-min tall with the least gap above
   and below. The drawing keeps its shape inside it, centred, never wider than --size-loop-max, and leaves
   a gap above and below of 6% of the room, from --space-sm up to the band's full gap. */
.loop-area {
  flex: 1 1 auto;
  min-height: calc(var(--size-loop-min) + 2 * var(--space-sm));
  container-type: size;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* The animation (owner, 12 Oct): inside a browser outline three pages drop in and stack into one task
   card (Load), a copper signoff block snaps onto its top right (Prepare), then the stack is labelled
   start.loop.result and a download arrow slides into its tray (Save), the finished frame holds, and the
   frame clears for the next run. Each run takes --dur-loop (7.6 s), and runs repeat. src/startloop.ts makes the drawing a button
   once the first run has played through, which pauses and plays it. The rules here draw the last frame,
   which is what shows with reduced motion, still and no button. The drawing is decorative for screen
   readers, who hear the steps under it. */
.loop-stage {
  --loop-gap: clamp(var(--space-sm), 6cqh, var(--band-gap));
  --loop-w: min(100cqw, (100cqh - 2 * var(--loop-gap)) * 360 / 252, var(--size-loop-max));
  position: relative;
  width: var(--loop-w);
  aspect-ratio: 360 / 252;
  border-radius: var(--radius-card);
  -webkit-tap-highlight-color: transparent;
}
.loop-stage[role="button"] { cursor: pointer; }
.loop-stage:focus-visible { outline: var(--border-medium) solid var(--color-focus); outline-offset: var(--space-2xs); }
.loop-art { display: block; width: 100%; height: auto; overflow: visible; }
.loop-frame { fill: none; stroke: var(--color-on-bench-line); stroke-width: 1.5; }
.loop-address { fill: var(--color-on-bench-line); }
.loop-shadow { flood-color: var(--color-band); flood-opacity: 0.4; }
.loop-paper { fill: var(--color-paper); }
.loop-ink { fill: var(--color-text); }
.loop-lines { fill: none; stroke: var(--color-border-strong); stroke-width: 3; stroke-linecap: round; }
.loop-block rect, .loop-block path { fill: none; stroke: var(--color-copper); stroke-width: 1.5; }
.loop-block .loop-block-labels { stroke-width: 1.5; stroke-linecap: round; }
.loop-arrow, .loop-tray { fill: none; stroke: var(--color-on-dark); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.loop-page, .loop-block, .loop-arrow, .loop-tray { transform-box: fill-box; transform-origin: center; }
/* start.loop.result, a label pinned across the foot of the top page, its words growing with the drawing
   from 12 to 16 px */
.start-result {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(184 / 252 * 100%);
  width: max-content;
  margin: calc(-1 * (var(--leading-4) * 1em + 2 * var(--space-2xs) + 2 * var(--border-thin)) / 2) auto 0;
  padding: var(--space-2xs) var(--space-sm);
  border: var(--border-thin) solid var(--color-on-bench-line);
  border-radius: var(--radius-tag);
  background: var(--color-bench-deep);
  color: var(--color-on-dark);
  font-size: clamp(var(--text-xs), var(--loop-w) / 30, var(--text-md));
  line-height: var(--leading-4);
  font-weight: var(--weight-semibold);
}
/* While paused, a mouse over the drawing shows a small white play symbol on a dark disc in its middle.
   Nothing shows while it plays, and a finger's tap shows nothing. */
.loop-play {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--size-loop-play);
  height: var(--size-loop-play);
  margin: calc(-1 * var(--size-loop-play) / 2) 0 0 calc(-1 * var(--size-loop-play) / 2);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-round);
  background: var(--color-loop-play);
  color: var(--color-on-dark);
  opacity: 0;
  pointer-events: none;
}
.loop-stage.is-paused .loop-play { transition: opacity var(--dur-fast); }
.loop-stage.is-paused.is-hovered .loop-play { opacity: 1; }

/* The three steps in one row on every width, by their titles alone (owner, 14 Oct). The step
   playing is lit, a white pill with steel blue words (7.61:1), the others pale blue words (5.90:1) in a
   faint outline. Their sentences are read by screen readers only. The pills' padding above and below
   their words halves on a short window (from --size-fit-low down), so the band fits. */
.start-steps {
  flex: none;
  list-style: none;
  display: flex;
  justify-content: center;
  gap: var(--space-sm);
}
.start-steps li {
  position: relative;
  padding: var(--space-xs) var(--space-md);
  padding-block: clamp(var(--space-2xs), calc(var(--space-2xs) + (100vh - var(--size-fit-low)) / 80), var(--space-xs));
  padding-block: clamp(var(--space-2xs), calc(var(--space-2xs) + (100svh - var(--size-fit-low)) / 80), var(--space-xs));
  border: var(--border-thin) solid var(--color-on-bench-line);
  border-radius: var(--radius-pill);
  color: var(--color-on-bench-2);
  white-space: nowrap;
}
.start-step-title {
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  font-weight: var(--weight-semibold);
}
@media (min-width: 641px) {
  .start-steps { gap: var(--space-md); }
  .start-steps li {
    padding: var(--space-sm) var(--space-lg);
    padding-block: clamp(var(--space-xs), calc(var(--space-xs) + (100vh - var(--size-fit-low)) / 40), var(--space-sm));
    padding-block: clamp(var(--space-xs), calc(var(--space-xs) + (100svh - var(--size-fit-low)) / 40), var(--space-sm));
  }
  .start-step-title { font-size: var(--text-md); line-height: var(--leading-md); }
}
.start-steps li:nth-child(3) { border-color: var(--color-on-dark); background-color: var(--color-on-dark); color: var(--color-bench); }

/* The parts' moments, as parts of --dur-loop (7.6 s): Load from 0 to 1.6 s (21.1%), the pages dropping
   one after another and gathering into one stack. Prepare to 3.0 s (39.5%), the block snapping on at
   1.75 s. Save to the end, the label and the arrow from 3.05 s, every part in place at 4.25 s (55.9%).
   The finished frame then holds for 3 s (owner, 17 Oct), so someone reading Start sees it at rest, and
   all of it clears from 7.25 s (95.4%) over the last 0.35 s, so the next run starts on an empty frame. The
   motion keeps its pace: each moment is where it was in seconds when a run took 4.6 s. src/startloop.ts
   reads the clearing's moment from loop-clear's keyframes and shows the frame just before it for a
   remembered pause. Each part holds its first keyframe while it waits. The parts play only where motion
   is welcome. */
@media (prefers-reduced-motion: no-preference) {
  .loop-pages, .loop-save { animation: loop-clear var(--dur-loop) linear infinite both; }
  .loop-page-1 { animation: loop-page-1 var(--dur-loop) linear infinite both; }
  .loop-page-2 { animation: loop-page-2 var(--dur-loop) linear infinite both; }
  .loop-page-3 { animation: loop-page-3 var(--dur-loop) linear infinite both; }
  .loop-block { animation: loop-block var(--dur-loop) linear infinite both; }
  .start-result { animation: loop-result var(--dur-loop) linear infinite both; }
  .loop-arrow { animation: loop-arrow var(--dur-loop) linear infinite both; }
  .loop-tray { animation: loop-tray var(--dur-loop) linear infinite both; }
  .start-steps li:nth-child(1) { animation: loop-step1 var(--dur-loop) linear infinite both; }
  .start-steps li:nth-child(2) { animation: loop-step2 var(--dur-loop) linear infinite both; }
  .start-steps li:nth-child(3) { animation: loop-step3 var(--dur-loop) linear infinite both; }
}
@keyframes loop-clear {
  0%, 95.4% { opacity: 1; animation-timing-function: var(--ease-exit); }
  100% { opacity: 0; }
}
/* The back page lands at the left, the middle one at the right, the top one in the middle, then the two
   slide in under the top one */
@keyframes loop-page-1 {
  0%, 1.21% { transform: translate(-92px, -210px); animation-timing-function: var(--ease-enter); }
  6.66% { transform: translate(-92px, 3px); }
  7.87%, 13.32% { transform: translate(-92px, 0); animation-timing-function: var(--ease-standard); }
  17.55%, 100% { transform: none; }
}
@keyframes loop-page-2 {
  0%, 3.93% { transform: translate(92px, -210px); animation-timing-function: var(--ease-enter); }
  9.38% { transform: translate(92px, 3px); }
  10.59%, 13.32% { transform: translate(92px, 0); animation-timing-function: var(--ease-standard); }
  17.55%, 100% { transform: none; }
}
@keyframes loop-page-3 {
  0%, 6.66% { transform: translateY(-210px); animation-timing-function: var(--ease-enter); }
  12.11% { transform: translateY(3px); }
  13.32%, 100% { transform: none; }
}
@keyframes loop-block {
  0%, 23% { opacity: 0; transform: scale(1.8); animation-timing-function: var(--ease-enter); }
  26.63% { opacity: 1; transform: scale(0.92); animation-timing-function: var(--ease-standard); }
  28.45%, 100% { opacity: 1; transform: none; }
}
@keyframes loop-result {
  0%, 40.13% { opacity: 0; transform: translateY(var(--space-xs)); animation-timing-function: var(--ease-enter); }
  43.58%, 95.4% { opacity: 1; transform: none; animation-timing-function: var(--ease-exit); }
  100% { opacity: 0; transform: none; }
}
@keyframes loop-arrow {
  0%, 42.07% { opacity: 0; transform: translateY(-14px); animation-timing-function: var(--ease-enter); }
  49.99%, 100% { opacity: 1; transform: none; }
}
@keyframes loop-tray {
  0%, 42.07% { opacity: 0; }
  45.39%, 100% { opacity: 1; }
}
/* The step playing is the white pill, the others pale blue words in a faint outline */
@keyframes loop-step1 {
  0%, 20.76% { border-color: var(--color-on-dark); background-color: var(--color-on-dark); color: var(--color-bench); }
  21.06%, 100% { border-color: var(--color-on-bench-line); background-color: transparent; color: var(--color-on-bench-2); }
}
@keyframes loop-step2 {
  0%, 20.76% { border-color: var(--color-on-bench-line); background-color: transparent; color: var(--color-on-bench-2); }
  21.06%, 39.16% { border-color: var(--color-on-dark); background-color: var(--color-on-dark); color: var(--color-bench); }
  39.46%, 100% { border-color: var(--color-on-bench-line); background-color: transparent; color: var(--color-on-bench-2); }
}
@keyframes loop-step3 {
  0%, 39.16% { border-color: var(--color-on-bench-line); background-color: transparent; color: var(--color-on-bench-2); }
  39.46%, 100% { border-color: var(--color-on-dark); background-color: var(--color-on-dark); color: var(--color-bench); }
}

/* Did you know? A lighter steel blue strip across the band's foot, a copper disc with a white bulb at its
   start and white words (5.67:1), left-aligned. Smaller words on phones. Its padding above and below its
   words halves on a short window, as the step pills' does. */
.tip-card {
  order: 2;
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  margin: 0 calc(-1 * var(--band-side));
  padding: var(--space-lg) var(--band-side);
  padding-block: clamp(var(--space-sm), calc(var(--space-sm) + (100vh - var(--size-fit-low)) / 20), var(--space-lg));
  padding-block: clamp(var(--space-sm), calc(var(--space-sm) + (100svh - var(--size-fit-low)) / 20), var(--space-lg));
  background: var(--color-bench-light);
  color: var(--color-on-dark);
  text-align: left;
}
.tip-disc {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--size-tip-disc);
  height: var(--size-tip-disc);
  border-radius: var(--radius-round);
  background: var(--color-copper);
  color: var(--color-on-dark);
}
.tip-body { min-width: 0; }
.tip-label {
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  font-weight: var(--weight-semibold);
}
.tip-label + p { font-size: var(--text-sm); line-height: var(--leading-sm); }
@media (min-width: 641px) {
  .tip-label + p { font-size: var(--text-md); line-height: var(--leading-md); }
}

/* Drop to load, over Start's content while a file is held over the page: the deep bench colour with a
   copper edge, three pages drawn over it and Drop to load in large white words, the screen around it
   dimmed. It is held in the window between the bars at the top and the bottom band, so it reaches down to
   the row with Compile on the file panel, or the footer, with nothing showing under it, and its words stay
   in view however far the files scroll. Its sides line up with Start's band on wide screens, or the
   bench's band once files are on it. Over the workspace, where a drop opens the file
   panel, it spans the pages, as wide as the window less the same gap. The drawing is written with no
   space between its parts in index.html, so the box's text is only its words. */
.drop-hint {
  position: fixed;
  top: calc(var(--top-bars-h, 0px) + var(--space-md));
  bottom: var(--bottom-band-h);
  left: max(var(--space-md), calc((100% - var(--size-bench-max)) / 2 + var(--space-2xl)));
  right: max(var(--space-md), calc((100% - var(--size-bench-max)) / 2 + var(--space-2xl)));
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xl);
  padding: var(--space-2xl);
  background-color: var(--color-bench-deep);
  border: var(--border-thick) solid var(--color-copper);
  box-shadow: 0 0 0 100vmax var(--color-scrim-drop);
  font-size: var(--text-2xl);
  line-height: var(--leading-2xl);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight);
  text-align: center;
  pointer-events: none;
}
.drop-hint[hidden] { display: none; }
/* Once files are on the bench it covers the band: from edge to edge and square, or on wide screens as
   wide as the band */
.start-screen.has-files > .drop-hint { left: 0; right: 0; border-radius: 0; }
@media (min-width: 1024px) and (orientation: landscape) {
  .start-screen.has-files > .drop-hint {
    left: max(var(--space-2xl), calc((100% - var(--size-bench-max)) / 2 + var(--space-2xl)));
    right: max(var(--space-2xl), calc((100% - var(--size-bench-max)) / 2 + var(--space-2xl)));
    border-radius: var(--radius-panel);
  }
}
.workspace > .drop-hint { left: var(--space-md); right: var(--space-md); }
.drop-art { width: var(--size-drop-art); height: auto; overflow: visible; }
.drop-paper { fill: var(--color-paper); filter: drop-shadow(0 var(--space-xs) var(--space-sm) var(--color-scrim)); }
.drop-ink { stroke: var(--color-text); stroke-width: 4; }
.drop-lines { stroke: var(--color-border-strong); stroke-width: 2.5; }
@media (max-width: 640px) {
  .drop-art { width: var(--size-drop-art-phone); }
}

/* The file panel (E3, owner, 12 Oct, the bench as Start's hero band): once files land, Start shows it in
   place of its heading, Choose PDFs and band. One slim title row at every width (owner, 17 Oct): Check the
   order at its start and how many files and pages at its end. Below it one steel blue band with the blueprint grid,
   from edge to edge where Start's band is, reaching down to the footer. Its top bar is held under the
   header as the files scroll, and its foot with Cancel and Compile above the footer (below). On phones
   the title row is the smaller heading's, close under the header. */
.start-screen.has-files > .start-intro,
.start-screen.has-files > .start-loop,
.start-screen.has-files > .start-legal { display: none; }
.start-screen.has-files { grid-template: minmax(0, 1fr) / minmax(0, 1fr); }
.file-panel {
  --band-side: var(--space-gutter-phone);
  grid-column: 1 / -1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
@media (min-width: 641px) {
  .file-panel { --band-side: var(--space-2xl); }
}
@media (min-width: 1024px) and (orientation: landscape) {
  .file-panel { --band-side: var(--space-3xl); }
}
.file-panel[hidden] { display: none; }
/* The title row on the page's light background, lined up with the band's sides. The hint that sat under the
   heading comes once as a hint (main.ts hintBench), and Add files is the band's plus symbol. */
.file-panel-intro {
  width: 100%;
  max-width: var(--size-bench-max);
  margin: 0 auto;
  padding: var(--space-sm) var(--space-gutter-phone);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-lg);
}
@media (min-width: 641px) {
  .file-panel-intro { padding: var(--space-3xl) var(--space-2xl) var(--space-2xl); }
}
.file-panel-heading {
  min-width: 0;
  margin: 0;
  font-size: var(--text-3xl);
  line-height: var(--leading-3xl);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight);
}
/* Focused by the code when files land, for screen readers, so it shows no focus ring */
.file-panel-heading:focus { outline: none; }
/* How many files and pages, in the page's grey at the row's end */
.file-panel-summary {
  flex: none;
  margin: 0;
  color: var(--color-text-secondary-page);
  font-size: var(--text-md);
  line-height: var(--leading-md);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* The band: edge to edge and square on narrow and upright screens, on wide screens lined up with the
   heading and Add files with its top corners rounded, as Start's. It reaches down to the footer: the
   room the page keeps at its end for the held foot and the notices (--page-end) is kept inside the band,
   so no page colour shows between the band and the foot or behind the notices. */
.file-panel-bench {
  flex: 1 0 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  border-radius: 0;
  margin-bottom: calc(var(--footer-h, 0px) - var(--page-end));
  padding-bottom: calc(var(--page-end) - var(--footer-h, 0px));
}
@media (min-width: 1024px) and (orientation: landscape) {
  .file-panel-bench {
    width: calc(100% - 2 * var(--space-2xl));
    max-width: calc(var(--size-bench-max) - 2 * var(--space-2xl));
    margin-inline: auto;
    border-radius: var(--radius-panel) var(--radius-panel) 0 0;
  }
}
/* The top bar, one row at every width with no captions. Compile never scrolls out of reach (Q7 (a)): the
   page scrolls and this bar stays under the header, in the band's colour without the grid, so the cards
   pass out of sight under it, with a hairline under it. At its start Add files (a plus, owner, 17 Oct), Undo
   and Restore file-name order as outlined symbol buttons, white on the band, their words in their tooltips
   and names. At its end Cards or List, the quietest. */
.file-panel-top {
  position: sticky; top: var(--top-bars-h, 0px); z-index: 1;
  display: flex; align-items: center; gap: var(--space-sm);
  padding: var(--space-md) var(--band-side);
  background: var(--color-bench);
  border-bottom: var(--border-thin) solid var(--color-on-bench-rule);
}
@media (min-width: 1024px) and (orientation: landscape) {
  .file-panel-top { border-radius: var(--radius-panel) var(--radius-panel) 0 0; }
}
.file-panel-top .icon-btn { flex: none; background: transparent; border-color: var(--color-on-bench-2); color: var(--color-on-dark); }
.file-panel-top .icon-btn:hover { background: var(--color-on-bench-hover); color: var(--color-on-dark); }
/* With nothing to restore or undo, the button keeps its shape, its edge and symbol in the band's greyed
   blue (3.51:1), never plain grey words */
.file-panel-top .icon-btn:is(:disabled, [aria-disabled="true"], .is-unavailable) {
  background: transparent;
  border-color: var(--color-on-bench-off);
  color: var(--color-on-bench-off);
}
/* Cards or List, two symbol buttons joined in a faint white edge, the one that shows white with a steel
   blue symbol, the other the pale blue symbol on the band, at the bar's end */
.bench-view {
  flex: none;
  margin-left: auto;
  display: flex;
  border: var(--border-thin) solid var(--color-on-bench-line);
  border-radius: var(--radius-control);
}
.file-panel-top .bench-view .icon-btn { border: 0; border-radius: 0; color: var(--color-on-bench-2); }
.file-panel-top .bench-view .icon-btn:first-child { border-radius: var(--radius-xs) 0 0 var(--radius-xs); }
.file-panel-top .bench-view .icon-btn:last-child { border-radius: 0 var(--radius-xs) var(--radius-xs) 0; }
.file-panel-top .bench-view .icon-btn:hover { background: var(--color-on-bench-hover); color: var(--color-on-dark); }
.file-panel-top .bench-view .icon-btn[aria-pressed="true"],
.file-panel-top .bench-view .icon-btn[aria-pressed="true"]:hover { background: var(--color-surface); color: var(--color-primary); }
.bench-list {
  position: relative; list-style: none;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--size-bench-card-w), 1fr));
  gap: var(--space-lg);
  margin: var(--space-2xl) var(--band-side);
}
.bench-list:empty { display: none; }
/* On the files screen with no file left, the bench says so, centred */
.bench-empty {
  padding: var(--space-5xl) var(--space-2xl);
  text-align: center;
  font-size: var(--text-md);
  line-height: var(--leading-md);
  color: var(--color-on-dark);
}
/* A file's card: white on the bench, raised, its first page with the number's badge on its corner and the
   grip at the card's top corner, its name with its page count under it, and a row with its earlier and
   later symbols joined in one control and its bin at the foot. Focus rings on it are steel blue again. */
.bench-card {
  --color-focus: var(--color-primary);
  position: relative;
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 0 var(--space-sm);
  background: var(--color-surface);
  color: var(--color-text);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-raised);
  padding: var(--space-lg);
  font-size: var(--text-sm); line-height: var(--leading-sm);
}
.bench-card-number {
  font-size: var(--text-2xl); line-height: var(--leading-2xl);
  font-weight: var(--weight-bold);
  color: var(--color-primary);
}
/* The name as it shows, hidden from screen readers, which hear its one-run copy (main.ts, owner, 11 Oct).
   It breaks at its spaces and after an underscore, hyphen or dot (a wbr after each), and inside a run
   only where the run has none and is wider than the line. */
.bench-card-name { font-weight: var(--weight-semibold); overflow-wrap: break-word; }
.bench-card-pages { grid-column: 2; font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--color-text-secondary); }
.bench-card-controls { grid-column: 1 / -1; display: flex; align-items: center; gap: var(--space-xs); }
.bench-remove { margin-left: auto; }
/* The first page, centred in the thumbnail box, a sunken box one size on every card and centred on it
   (main.ts sets the sizes). It shows as an empty page until it is drawn, and stays so if it cannot be.
   A long press on it selects nothing and opens no menu of the browser's own (E3 commit 11). The box sits in
   a frame that also holds the number's badge (owner, 17 Oct): the accent's round disc at its top left
   corner, white bold figures, widening for more digits. */
.bench-thumb-frame {
  position: relative;
  grid-column: 1 / -1;
  justify-self: center;
  margin: 0 0 var(--space-md);
}
.bench-card-badge {
  position: absolute; top: var(--space-xs); left: var(--space-xs);
  display: flex; align-items: center; justify-content: center;
  min-width: var(--size-bench-badge); height: var(--size-bench-badge);
  padding: 0 var(--space-xs);
  border-radius: var(--radius-pill);
  background: var(--color-primary);
  color: var(--color-on-dark);
  font-size: var(--text-sm); line-height: 1;
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}
.bench-thumb {
  display: flex; align-items: center; justify-content: center;
  background: var(--color-surface-2);
  border-radius: var(--radius-control);
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
.bench-thumb canvas { display: block; background: var(--color-paper); box-shadow: var(--shadow-page); }
.bench-thumb.pending canvas, .bench-thumb.failed canvas { background: var(--color-border); }
/* The grip, in the card's top corner at a finger's size. Only the grip takes a drag, so a finger
   anywhere else on the card still scrolls the page, and pressing it selects no text and opens no
   menu of the browser's own (E3 commit 9). */
.bench-grip {
  grid-column: 3; grid-row: 1 / span 2; align-self: start;
  display: flex; align-items: center; justify-content: center;
  width: var(--size-touch); height: var(--size-touch);
  margin: calc(-1 * var(--space-md)) calc(-1 * var(--space-md)) 0 0;
  color: var(--color-text-secondary);
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
/* The card being dragged follows the pointer above the other cards, and the line shows where it would
   go, above the dragged card too: in the gap between two cards, or across in one column, white on the
   bench */
.bench-card.is-dragging { z-index: 2; box-shadow: var(--shadow-dialog); will-change: transform; }
.bench-card.is-dragging .bench-grip { cursor: grabbing; }
.bench-insert {
  position: absolute; z-index: 3;
  width: var(--border-medium);
  transform: translateX(-50%);
  background: var(--color-on-dark);
  border-radius: var(--radius-xs);
  pointer-events: none;
}
.bench-insert.is-across { height: var(--border-medium); transform: translateY(-50%); }
.bench-insert[hidden] { display: none; }
/* A card that has just moved or arrived flashes for 700 ms (E3 commit 8). With reduced motion it holds a
   steady highlight for the same time. */
.bench-card.is-flashing { animation: bench-flash 700ms ease-out; }
@keyframes bench-flash { from { background: var(--color-primary-tint-strong); } }
@media (prefers-reduced-motion: reduce) {
  .bench-card.is-flashing { animation-timing-function: step-end; }
}
/* List view (E3 commit 12): one white card on the bench holding a row per file, 56 px tall and parted by
   hairlines, with no thumbnail: its number, grip, name, page count, then its up and down symbols and its
   bin. The rows share the list's columns, so the names and page counts line up. While a row is dragged,
   the rows it passes slide aside in place of the insertion line. */
.bench-list.is-list {
  grid-template-columns: auto auto minmax(0, 1fr) auto auto; gap: 0;
  background: var(--color-surface);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-raised);
}
.bench-list.is-list > .bench-card {
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  align-items: center;
  --row-pad: var(--space-lg);
  column-gap: var(--space-md);
  min-height: var(--size-bench-row);
  padding: var(--space-xs) var(--row-pad);
  border-radius: 0;
  box-shadow: none;
}
.bench-list.is-list > .bench-card + .bench-card { border-top: var(--border-thin) solid var(--color-border); }
.bench-list.is-list > .bench-card:first-child { border-top-left-radius: var(--radius-card); border-top-right-radius: var(--radius-card); }
.bench-list.is-list > .bench-card:last-child { border-bottom-left-radius: var(--radius-card); border-bottom-right-radius: var(--radius-card); }
.bench-list.is-list > .bench-card.is-dragging { box-shadow: var(--shadow-dialog); }
.bench-list.is-list > .bench-card > .bench-card-number { grid-column: 1; grid-row: 1; text-align: end; font-size: var(--text-md); line-height: var(--leading-md); }
.bench-list.is-list > .bench-card > .bench-grip { grid-column: 2; grid-row: 1; margin: 0; align-self: center; }
.bench-list.is-list > .bench-card > .bench-card-name { grid-column: 3; grid-row: 1; }
.bench-list.is-list > .bench-card > .bench-card-pages { grid-column: 4; grid-row: 1; white-space: nowrap; }
.bench-list.is-list > .bench-card > .bench-card-controls { grid-column: 5; grid-row: 1; }
.bench-list.is-sliding > .bench-card:not(.is-dragging) { transition: transform 150ms ease-out; }
@media (prefers-reduced-motion: reduce) {
  .bench-list.is-sliding > .bench-card:not(.is-dragging) { transition: none; }
}
/* Damaged, protected and password files, at the top of the file list before the numbered files: a red
   edge at the start, the name with its tag under it, and Skip this file in words at the end. The tag is
   red words on the pale red with the caution symbol, so it never says it by colour alone. No number, so
   in Cards view the name takes the first column, and the card is a numbered card's size (see Cards view
   below). As a list row the name and its tag take the name column, so the names line up, and Skip takes
   the last column. */
.bench-card-blocked { grid-template-columns: minmax(0, 1fr) auto; align-self: start; border-left: var(--border-edge) solid var(--color-danger); }
.bench-card-tag {
  grid-column: 1; justify-self: start;
  display: inline-flex; align-items: center; gap: var(--space-xs);
  margin-top: var(--space-xs);
  padding: var(--space-2xs) var(--space-sm) var(--space-2xs) var(--space-xs);
  border-radius: var(--radius-tag);
  background: var(--color-caution-bg);
  color: var(--color-danger);
  font-size: var(--text-xs); line-height: var(--leading-xs); font-weight: var(--weight-semibold);
}
.bench-card-tag::before {
  content: "";
  flex: none;
  width: var(--leading-xs); height: var(--leading-xs);
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.3 3.9L1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z'/%3E%3Cpath d='M12 9v4'/%3E%3Cpath d='M12 17h.01'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.3 3.9L1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z'/%3E%3Cpath d='M12 9v4'/%3E%3Cpath d='M12 17h.01'/%3E%3C/svg%3E") center / contain no-repeat;
}
.bench-skip { grid-column: 2; grid-row: 1 / span 2; align-self: center; min-height: var(--size-touch); }
.bench-list.is-list > .bench-card > .bench-card-tag { grid-column: 3; grid-row: 2; }
.bench-list.is-list > .bench-card > .bench-skip { grid-column: -2; grid-row: 1 / span 2; justify-self: end; }
.bench-list.is-list > .bench-card-blocked { padding-left: calc(var(--row-pad) - var(--border-edge)); }
/* Cards view (owner, 11 Oct): every card is one size, cards that cannot be compiled and later copies
   included, so a long name never stretches its card or its row. The first page sits at the top with the
   number's badge on its corner and the grip in the card's top corner (owner, 17 Oct, image 60), the name
   under it, with the Duplicate tag and the page count under the name. The name keeps to two
   lines, cut with an ellipsis, and shows in full in its tooltip while it is cut (main.ts). The row of
   symbols sits at the card's foot, the earlier and later symbols joined in one control with a line between
   them and the greyed half in the greyed fill, then the bin at the end, and the room above it takes what the
   name and page count leave. A card that cannot be compiled has no first page: its name and tag stay at the
   top and Skip this file sits at the foot, at the end, where a numbered card has its bin. List view keeps
   its own layout, its number in its own column and its symbols apart. */
.bench-list:not(.is-list) > .bench-card { height: var(--size-bench-card); grid-template-rows: auto auto auto auto 1fr auto; }
.bench-list:not(.is-list) > .bench-card > .bench-card-number { display: none; }
.bench-list:not(.is-list) > .bench-card > .bench-grip { position: absolute; top: 0; right: 0; margin: 0; }
.bench-list:not(.is-list) > .bench-card > .bench-thumb-frame { grid-row: 1; }
.bench-list:not(.is-list) > .bench-card > .bench-card-name { grid-row: 2; grid-column: 1 / -1; }
/* The name keeps to two lines in either view, cut with an ellipsis and shown in full in its tooltip while
   it is cut (main.ts fitBenchName), so a long name never makes its row taller (owner, 15 Oct) */
.bench-list > .bench-card > .bench-card-name {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
  overflow: hidden;
}
.bench-list:not(.is-list) > .bench-card > .bench-card-pages { grid-row: 4; grid-column: 1 / -1; }
.bench-list:not(.is-list) > .bench-card > .bench-card-controls { grid-row: 6; }
.bench-list:not(.is-list) .bench-move { display: inline-flex; border: var(--border-thin) solid var(--color-border-strong); border-radius: var(--radius-control); }
.bench-list:not(.is-list) .bench-move > .icon-btn { border: 0; border-radius: 0; }
.bench-list:not(.is-list) .bench-move > .icon-btn:first-child { border-radius: calc(var(--radius-control) - var(--border-thin)) 0 0 calc(var(--radius-control) - var(--border-thin)); }
.bench-list:not(.is-list) .bench-move > .icon-btn:last-child { border-radius: 0 calc(var(--radius-control) - var(--border-thin)) calc(var(--radius-control) - var(--border-thin)) 0; }
.bench-list:not(.is-list) .bench-move > .icon-btn + .icon-btn { border-left: var(--border-thin) solid var(--color-border-strong); }
.bench-list.is-list .bench-move { display: contents; }
.bench-list:not(.is-list) > .bench-card-blocked { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto 1fr auto; }
.bench-list:not(.is-list) > .bench-card-blocked > .bench-card-name { grid-row: 1; }
.bench-list:not(.is-list) > .bench-card-blocked > .bench-card-tag { grid-row: 2; }
.bench-list:not(.is-list) > .bench-card-blocked > .bench-skip { grid-column: 1; grid-row: 4; justify-self: end; }
/* A later copy of a file (G3 (a)): the pale blue behind the card and the Duplicate tag, steel blue words in
   a steel blue edge, so the word says it and never the colour alone (G-A3). In Cards view the tag sits
   under the name. In List view it takes the name column's second line, with the row's
   other parts across both lines, and on phones the page count goes under the tag. */
.bench-card.is-duplicate { background: var(--color-primary-tint); }
/* The brand grey falls below AA on the pale blue, so the page count there takes the deeper grey (5.25:1) */
.bench-card.is-duplicate > .bench-card-pages { color: var(--color-text-secondary-page); }
.bench-card-dup {
  grid-column: 2; justify-self: start; align-self: center;
  padding: 0 var(--space-sm);
  border: var(--border-thin) solid var(--color-primary);
  border-radius: var(--radius-tag);
  background: var(--color-surface);
  color: var(--color-primary);
  font-size: var(--text-xs); line-height: var(--leading-xs); font-weight: var(--weight-semibold);
}
.bench-list:not(.is-list) > .bench-card > .bench-card-dup { grid-row: 3; grid-column: 1 / -1; margin: var(--space-2xs) 0; }
.bench-list.is-list > .bench-card > .bench-card-dup { grid-column: 3; grid-row: 2; margin-top: var(--space-2xs); }
.bench-list.is-list > .bench-card.is-duplicate > .bench-card-number,
.bench-list.is-list > .bench-card.is-duplicate > .bench-grip,
.bench-list.is-list > .bench-card.is-duplicate > .bench-card-pages,
.bench-list.is-list > .bench-card.is-duplicate > .bench-card-controls { grid-row: 1 / span 2; }
/* Phones (phase 6 P3). In Cards view each card becomes a row, one column of rows as mockup A5 notes, every
   row one size (--size-bench-card takes the row's height, the 11 Oct rule). From the row's start (owner,
   17 Oct, image 59): the grip at the left edge, then its first page in a 52 by 72 px box (the same box and
   drawing as on wider screens, shown smaller) with the number's badge on its corner, then its name on up to
   two lines and its page count under it, after the Duplicate tag on a later copy. At the end the earlier
   and later symbols joined in one control, one above the other and pointing up and down as the rows run,
   each half 44 px tall (owner, 18 Oct), then the bin, each centred on the row's height. A card that cannot be compiled keeps its name and tag at
   the start and Skip this file at the end.
   List view fills the band from edge to edge under its top bar, square as the band is. As in Cards, the
   name (on up to two lines) and the page count under it take the room between the number and grip and the
   up and down symbols, one above the other with the bin beside them, all centred on the row's height
   (owner, 15 Oct). A later copy's tag goes under the name and the page count under it. A row that cannot
   be compiled keeps its tag under its name with Skip this file beside the tag. */
@media (max-width: 640px) {
  :root { --size-bench-card: var(--size-bench-card-phone); }
  .bench-list:not(.is-list) { grid-template-columns: minmax(0, 1fr); }
  .bench-list:not(.is-list) > .bench-card {
    grid-template-columns: auto auto auto minmax(0, 1fr) auto;
    grid-template-rows: auto auto;
    align-content: center;
    column-gap: var(--space-sm);
    padding: var(--space-md) var(--space-md) var(--space-md) 0;
  }
  .bench-list:not(.is-list) > .bench-card > .bench-grip {
    position: static;
    grid-column: 1; grid-row: 1 / -1; align-self: center;
    width: var(--size-bench-grip-phone);
  }
  .bench-list:not(.is-list) > .bench-card > .bench-thumb-frame { grid-column: 2; grid-row: 1 / -1; align-self: center; margin: 0 var(--space-xs) 0 0; }
  .bench-list:not(.is-list) > .bench-card .bench-thumb { zoom: var(--size-bench-thumb-zoom); }
  .bench-card-badge { top: var(--space-2xs); left: var(--space-2xs); min-width: var(--size-bench-badge-phone); height: var(--size-bench-badge-phone); font-size: var(--text-xs); }
  .bench-list:not(.is-list) > .bench-card > .bench-card-name { grid-column: 3 / 5; grid-row: 1; align-self: end; }
  .bench-list:not(.is-list) > .bench-card > .bench-card-pages { grid-column: 3 / 5; grid-row: 2; align-self: start; white-space: nowrap; }
  .bench-list:not(.is-list) > .bench-card > .bench-card-dup { grid-column: 3; grid-row: 2; align-self: start; margin: 0 var(--space-sm) 0 0; }
  .bench-list:not(.is-list) > .bench-card.is-duplicate > .bench-card-pages { grid-column: 4; justify-self: start; }
  .bench-list:not(.is-list) > .bench-card > .bench-card-controls {
    grid-column: 5; grid-row: 1 / -1; align-self: center;
    gap: var(--space-sm);
  }
  .bench-list:not(.is-list) .bench-move { flex-direction: column; }
  .bench-list:not(.is-list) .bench-move > .icon-btn { min-width: var(--size-bench-move-w); min-height: var(--size-bench-move-h); }
  .bench-list:not(.is-list) .bench-move > .icon-btn:first-child { border-radius: calc(var(--radius-control) - var(--border-thin)) calc(var(--radius-control) - var(--border-thin)) 0 0; }
  .bench-list:not(.is-list) .bench-move > .icon-btn:last-child { border-radius: 0 0 calc(var(--radius-control) - var(--border-thin)) calc(var(--radius-control) - var(--border-thin)); }
  .bench-list:not(.is-list) .bench-move > .icon-btn + .icon-btn { border-left: 0; border-top: var(--border-thin) solid var(--color-border-strong); }
  .bench-list .bench-earlier { grid-column: 1; grid-row: 1; }
  .bench-list .bench-later { grid-column: 1; grid-row: 2; }
  .bench-list .bench-remove { grid-column: 2; grid-row: 1 / span 2; align-self: center; margin: 0; }
  .bench-list:not(.is-list) :is(.bench-earlier, .bench-later) svg { transform: rotate(90deg); }
  .bench-list:not(.is-list) > .bench-card-blocked { grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto auto; padding-left: calc(var(--space-md) - var(--border-edge)); }
  .bench-list:not(.is-list) > .bench-card-blocked > .bench-card-name { grid-column: 1; grid-row: 1; }
  .bench-list:not(.is-list) > .bench-card-blocked > .bench-card-tag { grid-column: 1; grid-row: 2; }
  .bench-list:not(.is-list) > .bench-card-blocked > .bench-skip { grid-column: 2; grid-row: 1 / -1; align-self: center; }

  .bench-list.is-list { grid-template-columns: auto auto minmax(0, 1fr) auto; margin: 0; border-radius: 0; box-shadow: none; }
  .bench-list.is-list > .bench-card { row-gap: 0; column-gap: var(--space-sm); --row-pad: var(--space-sm); }
  .bench-list.is-list > .bench-card:first-child,
  .bench-list.is-list > .bench-card:last-child { border-radius: 0; }
  .bench-list.is-list > .bench-card > .bench-card-number,
  .bench-list.is-list > .bench-card > .bench-grip { grid-row: 1 / span 2; }
  .bench-list.is-list > .bench-card > .bench-card-name { grid-column: 3; align-self: end; }
  .bench-list.is-list > .bench-card > .bench-card-pages { grid-column: 3; grid-row: 2; align-self: start; }
  .bench-list.is-list > .bench-card > .bench-card-controls {
    grid-column: 4; grid-row: 1 / span 2; justify-self: end; align-self: center;
    display: grid; grid-template-columns: auto auto; gap: 0 var(--space-xs);
  }
  .bench-list.is-list > .bench-card.is-duplicate > .bench-card-pages { grid-row: 3; }
  .bench-list.is-list > .bench-card.is-duplicate > .bench-card-number,
  .bench-list.is-list > .bench-card.is-duplicate > .bench-grip { grid-row: 1 / span 3; }
  .bench-list.is-list > .bench-card.is-duplicate > .bench-card-controls { grid-row: 1 / span 3; }
  .bench-list.is-list > .bench-card > .bench-skip { grid-column: 4; grid-row: 2; }
}
/* The band's foot, in the place of Start's Did you know strip: Cancel and then Compile at the end,
   Compile as a white button with steel blue words, the main button's style on the band. It is held at
   the bottom of the window in the bottom band, directly above the footer, with the notices above it, so
   it never cuts across a card and never moves when a notice comes or goes (owner, 8 Oct), at every
   width. It is the band's colour without the grid with a hairline on top, lined up with the band: from
   edge to edge, or on wide screens as wide as the band (below). On the files screen the band is narrower by the
   room kept for that screen's scrollbar (--files-gutter, benchbar.ts), so the foot's controls keep clear
   of it too. */
.file-panel-actions {
  --color-focus: var(--color-focus-on-dark);
  --foot-gutter: 0px;
  position: fixed;
  left: 0; right: 0; bottom: var(--footer-h, 0px);
  z-index: 90;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--space-sm) var(--space-md);
  padding: var(--space-sm) max(calc(var(--band-side) + var(--foot-gutter)), env(safe-area-inset-right)) var(--space-sm) max(var(--band-side), env(safe-area-inset-left));
  background: var(--color-bench);
  border-top: var(--border-thin) solid var(--color-on-bench-rule);
  color: var(--color-on-dark);
}
.files-screen .file-panel-actions { --foot-gutter: var(--files-gutter, 0px); }
/* On wide screens the foot still spans the window, so nothing behind shows beside it, and only the
   band's part of it, with its hairline, takes the band's colour. The rest is the page's. That part is
   placed by a share of the room left beside it (50% of it, less half the files screen's gutter). */
@media (min-width: 1024px) and (orientation: landscape) {
  .file-panel-actions {
    --foot-side: max(var(--space-2xl), calc((100% - var(--foot-gutter) - var(--size-bench-max)) / 2 + var(--space-2xl)));
    --foot-band: calc(100% - 2 * var(--foot-side) - var(--foot-gutter));
    border-top-color: transparent;
    padding-left: calc(var(--foot-side) + var(--band-side));
    padding-right: calc(var(--foot-side) + var(--band-side) + var(--foot-gutter));
    background:
      linear-gradient(var(--color-on-bench-rule), var(--color-on-bench-rule)) calc(50% - var(--foot-gutter) / 2) 0 / var(--foot-band) var(--border-thin) no-repeat border-box,
      linear-gradient(var(--color-bench), var(--color-bench)) calc(50% - var(--foot-gutter) / 2) 0 / var(--foot-band) 100% no-repeat border-box,
      var(--color-page);
  }
}
.file-panel-actions .btn { min-height: var(--size-touch); }
.file-panel-actions .btn-ghost { color: var(--color-on-dark); }
.file-panel-actions .btn-ghost:hover { background: var(--color-on-bench-hover); }
.file-panel-actions .btn-primary { background: var(--color-surface); border-color: var(--color-surface); color: var(--color-primary); }
.file-panel-actions .btn-primary:hover { background: var(--color-primary-tint); border-color: var(--color-primary-tint); }
.file-panel-actions .btn-primary:active { background: var(--color-primary-tint-strong); border-color: var(--color-primary-tint-strong); }
/* Compile or Apply changes greyed (Q9, Q20 (a)): no fill, its edge and words in the band's greyed blue
   (3.51:1) */
.file-panel-actions .btn:is(:disabled, [aria-disabled="true"], .is-unavailable) {
  background: transparent;
  border-color: var(--color-on-bench-off);
  color: var(--color-on-bench-off);
}
/* Phones: the smaller heading and summary, so the title row keeps one slim line, and the cards closer
   together */
@media (max-width: 640px) {
  .file-panel-heading { font-size: var(--text-lg); line-height: var(--leading-lg); }
  .file-panel-summary { font-size: var(--text-sm); line-height: var(--leading-sm); }
  .bench-list { margin: var(--space-lg) var(--band-side); gap: var(--space-md); }
}

/* The link to the tool when the page is shown inside another one */
.start-link { text-decoration: none; }
.start-link[hidden] { display: none; }

/* Start's line when the page is shown inside another one or the browser is below the minimum, where the
   tool cannot be used: the caution style, its pale red with a red edge at the start and ink words */
.start-notice {
  padding: var(--space-md) var(--space-lg);
  background: var(--color-caution-bg);
  border-left: var(--border-edge) solid var(--color-danger);
  border-radius: 0 var(--radius-card) var(--radius-card) 0;
  color: var(--color-text);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  text-align: left;
}

/* Cloudflare's browser check in the session dialog, shown only when it needs the user */
.check-widget { display: flex; justify-content: center; }
.check-widget:not(:empty) { margin-top: var(--space-11); }
/* The session dialog: above everything, the loading screen included */
.save-modal-overlay.session-overlay { z-index: 300; }

/* Buttons in words: primary (the main action, steel blue), secondary (white with an edge) and ghost
   (steel blue words with no edge), each the touch size tall. Under the pointer each turns a shade deeper,
   and a press darkens a primary and shrinks any of them a little for a moment. */
.btn {
  font-family: inherit;
  font-size: var(--text-sm); line-height: var(--leading-sm); font-weight: var(--weight-semibold);
  padding: 0 var(--space-lg);
  border-radius: var(--radius-control);
  border: var(--border-thin) solid transparent;
  cursor: pointer;
  display: inline-flex; align-items: center; gap: var(--space-sm);
  transition: background-color var(--dur-fast), border-color var(--dur-fast), color var(--dur-fast), transform var(--dur-instant);
  min-height: var(--size-touch);
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
}
.btn:active { transform: scale(0.98); }
.btn-primary { background: var(--color-primary); color: var(--color-on-dark); border-color: var(--color-primary); }
.btn-primary:hover { background: var(--color-primary-hover); border-color: var(--color-primary-hover); }
.btn-primary:active { background: var(--color-primary-pressed); border-color: var(--color-primary-pressed); }
.btn-secondary { background: var(--color-surface); color: var(--color-text); border-color: var(--color-border-strong); }
.btn-secondary:hover { background: var(--color-surface-2); }
.btn-ghost { background: transparent; color: var(--color-primary); border-color: transparent; }
.btn-ghost:hover { background: var(--color-primary-tint); }
.btn-small { padding: var(--space-sm) var(--space-md); font-size: var(--text-xs); min-height: 32px; }

/* The toolbar: groups of controls, each with its caption under it as on a ribbon, then at the end Undo,
   Block settings and the File group. The groups wrap onto more rows when the window is narrow. */
.toolbar {
  --ribbon-pad: var(--space-2xl);
  /* 16 px between groups, the divider in its middle (owner, 17 Oct: room for the 11 inch iPad held sideways
     taken from the gaps, never from the controls) */
  --ribbon-gap: calc(2 * var(--space-sm));
  --ribbon-half: calc(var(--ribbon-gap) / 2);
  position: relative;
  background: var(--color-surface);
  border-bottom: var(--border-thin) solid var(--color-border);
  padding: var(--space-sm) var(--ribbon-pad);
  display: flex; align-items: flex-start;
  gap: var(--space-sm) var(--ribbon-gap); flex-wrap: wrap;
}
.toolbar-group { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); min-width: 0; max-width: 100%; }
.toolbar-controls { display: flex; align-items: center; gap: var(--space-7); flex-wrap: wrap; max-width: 100%; }
.toolbar-caption { font-size: var(--text-2xs); line-height: var(--leading-4); color: var(--color-text-muted); }
/* In the workspace ribbon a group's controls sit 4 px apart and its caption is small medium words in the
   brand grey (4.59:1 on white), centred under them */
.toolbar .toolbar-controls { gap: var(--space-xs); }
.toolbar .toolbar-caption { font-size: var(--text-xs); line-height: var(--leading-xs); font-weight: var(--weight-medium); color: var(--color-text-secondary); text-align: center; }
/* A hairline divider in the 16 px gap before each group after the first, about 8 px from each, as tall
   as a control with a little to spare. A group that starts a new row has its divider in the toolbar's side
   padding, where the toolbar's own strip at its left edge covers it, so no row starts with a stray line.
   The strip sits under every menu and panel that opens from the toolbar. */
.toolbar > .toolbar-group + .toolbar-group, .toolbar-end > .toolbar-group { position: relative; }
.toolbar > .toolbar-group + .toolbar-group::before, .toolbar-end > .toolbar-group::before {
  content: '';
  position: absolute;
  top: 0;
  left: calc(-1 * var(--ribbon-half));
  width: var(--border-thin);
  height: var(--size-ribbon-divider);
  background: var(--color-border);
}
.toolbar::before {
  content: '';
  position: absolute;
  z-index: 1;
  top: 0;
  bottom: 0;
  left: 0;
  width: calc(var(--ribbon-pad) - var(--ribbon-half) + var(--border-thin));
  background: var(--color-surface);
  pointer-events: none;
}
.toolbar .menu, .toolbar .popover { z-index: 2; }
/* A group made of captioned parts, as the Edit group is (Pages, Order, then Done editing under the group's
   own caption). The parts sit side by side and wrap as the toolbar's groups do, each caption under its own
   controls. */
.toolbar-parts { flex-direction: row; align-items: flex-start; flex-wrap: wrap; gap: var(--space-7) var(--space-17); }
/* While Edit Document is on its group reads as a mode: its parts on a pale steel blue panel with a 2 px
   steel blue top edge. The panel reaches into the toolbar's padding, so its controls and captions line up
   with the groups beside it and the row keeps its height. Its captions and count take the deeper grey,
   5.25:1 on the tint. */
#editGroup:not(.tray) {
  padding: var(--space-2xs) var(--space-md) var(--space-xs);
  margin: calc(-1 * var(--space-xs)) 0;
  border-top: var(--border-medium) solid var(--color-primary);
  border-radius: var(--radius-card);
  background: var(--color-primary-tint);
}
#editGroup .toolbar-caption { color: var(--color-text-secondary-page); }
/* Its divider lines up with the others, from the top of the controls beside it */
#editGroup::before { top: calc(var(--space-xs) - var(--border-medium)); }
.toolbar .btn { min-height: 44px; }
/* Undo and Settings, 4 px apart, then the File group last (owner, 7 Oct), all kept together and
   pushed to the right of the row, Edit Document or not. */
.toolbar-end { margin-left: auto; display: flex; align-items: flex-start; flex-wrap: wrap; gap: var(--space-sm) var(--space-xs); }
.toolbar-end > .toolbar-group { margin-left: calc(var(--ribbon-gap) - var(--space-xs)); }
/* On the full ribbon (wherever the window is as wide as its widest state, layout.ts) they are held at the
   right end of its first row, so Undo keeps one place in every
   mode, whatever shows, greys or wraps before it (testing item 5, owner 13 Oct). The ribbon keeps room for
   them at its right, their width (--ribbon-end-room, kept by frame.ts) and a gap, so its groups wrap onto
   the next row before reaching them. The annotate tool row holds its end the same way (below). */
:where(html:not(.bar-layout)) .toolbar { padding-right: calc(var(--ribbon-pad) + var(--ribbon-end-room, 0px) + var(--ribbon-gap)); }
:where(html:not(.bar-layout)) .toolbar-end { position: absolute; top: var(--space-sm); right: var(--ribbon-pad); flex-wrap: nowrap; }

/* A symbol button. Its text is its tooltip and its screen reader label. White with a quiet edge and an
   ink symbol, under the pointer a sunken fill and a steel blue symbol. */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--size-touch);
  min-height: var(--size-touch);
  padding: 0;
  border: var(--border-thin) solid var(--color-border-strong);
  border-radius: var(--radius-control);
  background: var(--color-surface);
  color: var(--color-text);
  cursor: pointer;
  transition: background-color var(--dur-fast), border-color var(--dur-fast), color var(--dur-fast), transform var(--dur-instant);
  -webkit-tap-highlight-color: transparent;
}
.icon-btn > svg { width: var(--size-symbol); height: var(--size-symbol); flex: 0 0 auto; }
.icon-btn:hover { background: var(--color-surface-2); color: var(--color-primary); }
.icon-btn:active { transform: scale(0.98); }
/* A symbol button whose menu or panel is open shows the sunken fill while it is */
.icon-btn[aria-expanded="true"] { background: var(--color-surface-2); color: var(--color-primary); }
/* A toggle that is on, and the pressed one of a set (Cards or List, a label preset):
   a steel blue fill with a white symbol or white words, more than a change of hue */
.icon-btn[aria-pressed="true"], .btn[aria-pressed="true"] { background: var(--color-selected); color: var(--color-on-dark); border-color: var(--color-selected); }
.icon-btn[aria-pressed="true"]:hover, .btn[aria-pressed="true"]:hover { background: var(--color-primary-hover); border-color: var(--color-primary-hover); }
/* Under forced colours, which replace that fill and those colours, a pressed or checked symbol button (a tool
   or switch that is on, Edit Document, Cards or List, the chosen thumbnail size, in a tray or not) takes the
   system's highlight colours, as the selected page does (phase 7 fix run, audit finding 28). They win over
   every layout's and tray's own pressed look and the pointer resting on the button. */
@media (forced-colors: active) {
  .icon-btn:is([aria-pressed="true"], [aria-checked="true"]) {
    forced-color-adjust: none;
    background: Highlight !important;
    color: HighlightText !important;
    border-color: Highlight !important;
  }
}
/* Save PDF, the main action of the File group, and Keep only selected pages, the Edit group's primary (owner,
   13 Oct): a steel blue filled symbol button */
.icon-btn-primary { background: var(--color-primary); color: var(--color-on-dark); border-color: var(--color-primary); }
.icon-btn-primary:hover { background: var(--color-primary-hover); color: var(--color-on-dark); border-color: var(--color-primary-hover); }
.icon-btn-primary:active { background: var(--color-primary-pressed); border-color: var(--color-primary-pressed); }

/* Disabled controls look disabled through colour, never through fading alone: the disabled fill, edge and
   text or symbol, no shadow, and no shrinking when pressed. A primary loses its steel blue fill, so a
   disabled Save, Compile, Copy or Move plainly cannot act. A truly disabled button shows the not-allowed
   pointer. A control that cannot act yet looks greyed the same way but can still be pressed, so a tap on a
   touch screen still gets an answer (answer 5), with the plain pointer. */
.btn:disabled, .btn[aria-disabled="true"], .btn.is-unavailable,
.icon-btn:disabled, .icon-btn[aria-disabled="true"], .icon-btn.is-unavailable {
  background: var(--color-disabled-bg);
  border-color: var(--color-disabled-border);
  color: var(--color-disabled-fg);
  box-shadow: none;
  transform: none;
  cursor: default;
}
.btn:disabled, .icon-btn:disabled { cursor: not-allowed; }
.is-unavailable { cursor: default; }
/* A menu item that cannot act yet: greyed words, its fill still showing where the pointer or focus is */
.menu-item.is-unavailable, .menu-item[aria-disabled="true"] { color: var(--color-disabled-fg); }

/* One tray style everywhere (owner, 15 Oct, navigation rework, look.md Trays): a white card with a 1 px edge,
   12 px corners and the popover shadow, 6 px inside, its items plain symbols in 46 by 44 px slots 4 px apart,
   with no edge of their own. A chosen or switched-on item sits on a pale steel blue tile with a steel blue
   symbol, a greyed one on the grey tile with a grey symbol. tray.ts places it by its button, toward the page,
   and popover.ts shows it in the browser's top layer, over the pages and the notices. The button that opened
   it shows the pale steel blue tile while it is open. */
.tray {
  position: fixed;
  z-index: 2;
  box-sizing: border-box;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--space-xs);
  width: max-content;
  padding: var(--size-tray-pad);
  background: var(--color-surface);
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius-panel);
  box-shadow: var(--shadow-popover);
  color: var(--color-text);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
}
.tray[hidden] { display: none; }
.tray[popover] { inset: auto; margin: 0; overflow: visible; }
.tray .icon-btn { min-width: var(--size-tray-item); min-height: var(--size-touch); border-color: transparent; background: transparent; }
.tray .icon-btn:hover { background: var(--color-surface-2); color: var(--color-primary); }
/* The chosen or switched-on item also takes a 2 px steel blue edge inside its slot (phase 7 fix run, audit
   finding 27, owner's answer 18 (a)), as the pale tile alone is under 3 to 1 against the tray, and under
   forced colours that edge takes the highlight colour */
.tray .icon-btn:is([aria-checked="true"], [aria-pressed="true"]) { background: var(--color-primary-tint-strong); color: var(--color-primary); border: var(--border-medium) solid var(--color-primary); }
@media (forced-colors: active) {
  .tray .icon-btn:is([aria-checked="true"], [aria-pressed="true"]) { border-color: Highlight; }
}
.tray .icon-btn:is(:disabled, [aria-disabled="true"], .is-unavailable) { background: var(--color-disabled-bg); color: var(--color-disabled-fg); border-color: transparent; }
/* So does a button whose tray holds a switch that is on (Cells while Split column or Not required is on, main.ts) */
.icon-btn[aria-controls]:is([aria-expanded="true"], .is-on) { background: var(--color-primary-tint-strong); color: var(--color-primary); border-color: var(--color-primary); }
/* A tray of words, the signoff block's positions: a small grey title, then its rows 40 px tall, the chosen
   one tinted pale steel blue with steel blue words and a check mark at its end (owner, 18 Oct), so it is not
   told by colour alone. It takes focus as the tray opens, so a mouse or a finger sees that one highlight
   and the keyboard its focus ring on it. */
.tray-words { flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 0; min-width: var(--size-tray-words); }
.tray-words .menu-list { gap: var(--space-2xs); }
.tray-title { margin: 0; padding: var(--space-xs) var(--space-md) var(--space-xs); font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--color-text-secondary); }
.tray-words .menu-item {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-md);
  min-height: var(--size-tray-row); padding: 0 var(--space-md); border-radius: var(--radius-card);
}
.tray-words .menu-item[aria-checked="true"] { background: var(--color-primary-tint-strong); color: var(--color-primary); }
.tray-words .menu-item[aria-checked="true"]::after {
  content: '';
  flex: none;
  width: var(--size-check);
  height: var(--size-check);
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / contain no-repeat;
}
@media (forced-colors: active) {
  .tray-words .menu-item[aria-checked="true"]::after { forced-color-adjust: none; background: CanvasText; }
}
/* A tray with groups, the Edit group on the bar layout: each group's symbols with its small grey caption
   under them, a thin line between groups. Keep only selected pages loses its fill there, as every item is a
   plain symbol. */
.tray > .toolbar-group { flex-direction: column; align-items: center; gap: var(--space-2xs); }
.tray > .toolbar-group + .toolbar-group { padding-left: var(--space-xs); border-left: var(--border-thin) solid var(--color-border); }
.tray > .toolbar-group > .toolbar-controls { gap: var(--space-xs); flex-wrap: nowrap; }
.tray .toolbar-caption { font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--color-text-secondary); text-align: center; }
#editGroup.tray { flex-wrap: nowrap; align-items: stretch; gap: var(--space-xs); }
.tray .icon-btn-primary:not(:hover) { background: transparent; color: var(--color-text); border-color: transparent; }
.tray-part { display: contents; }
.tray-part[hidden] { display: none; }

/* Keyboard focus, one look for every control: a 2 px steel blue ring 2 px outside it. On a dark or steel
   blue surface --color-focus turns white there, and under forced colours it is the system's highlight
   colour. A few controls draw the ring inside instead, where outside would be cut (their own rules). */
.btn:focus-visible, .icon-btn:focus-visible, a:focus-visible,
.help-close:focus-visible, .saved-panel-close:focus-visible,
.notice-close:focus-visible, .notice-action:focus-visible,
.select:focus-visible, .save-modal-input:focus-visible {
  outline: var(--border-medium) solid var(--color-focus);
  outline-offset: var(--space-2xs);
}

/* A menu, right-aligned under its button. popover.ts moves it sideways when the window is too narrow to
   hold it there. A menu comes in with a short fade and slide down, and with reduced motion only fades. */
.menu {
  position: absolute;
  top: calc(100% + var(--space-xs));
  right: 0;
  min-width: 220px;
  max-width: calc(100vw - 16px);
  padding: var(--space-xs);
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-popover);
  animation: menu-in var(--dur-quick) var(--ease-enter);
}
@keyframes menu-in { from { opacity: 0; transform: translateY(calc(-1 * var(--move-popover))); } }
.menu[hidden] { display: none; }
.menu-item {
  min-height: var(--size-touch);
  padding: 0 var(--space-md);
  border: none;
  border-radius: var(--radius-tag);
  background: transparent;
  color: var(--color-text);
  font: inherit;
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  text-align: left;
  cursor: pointer;
}
/* The grey under the pointer or the keyboard's focus only, never under focus a press or a tray's opening gave,
   so a mouse or a finger sees one highlight (owner, 18 Oct) */
.menu-item:hover, .menu-item:focus-visible { background: var(--color-surface-2); }
.menu-item:focus-visible { outline: var(--border-medium) solid var(--color-focus); outline-offset: calc(-1 * var(--border-medium)); }
/* A menu's heading above its items, as the position choice of Add signoff blocks has: small semibold
   words in the brand grey (4.59:1 on white) */
.menu-title { padding: var(--space-sm) var(--space-md) var(--space-xs); font-size: var(--text-xs); line-height: var(--leading-xs); font-weight: var(--weight-semibold); color: var(--color-text-secondary); }
.menu-list { display: flex; flex-direction: column; }
/* A menu opening upward, from the bar at the foot of the screen, slides up instead */
@keyframes menu-up { from { opacity: 0; transform: translateY(var(--move-popover)); } }
/* On the bar layout (html.bar-layout, layout.ts: windows narrower than the full ribbon needs and touch
   screens under 500 px tall, owner 13 Oct, B20) a menu or popover opened from a button is a sheet
   (popover.ts gives it is-sheet, phase 6 look plan section 7): the position menu,
   the bookmark list and the overlap choices open above the bar at the foot of the screen, which stays in
   view under them, across the window within the phone gutter, below the bars at the top and scrolling
   inside when the window is short. They slide up a little as they come. The copy panel is a sheet from the
   bottom, as the dialogs are on phones (Sheets, with the dialogs). The Beta note and the
   privacy note stay under their buttons. */
:root:where(.bar-layout) { --sheet-top: var(--top-bars-h, 0px); }
html:where(.bar-layout).annotate-open { --sheet-top: calc(var(--header-h, 0px) + var(--size-phone-top-row)); }
:where(html.bar-layout) :is(.menu, .popover).is-sheet:not(.copy-panel) {
  position: fixed;
  top: auto;
  left: max(var(--space-gutter-phone), env(safe-area-inset-left));
  right: max(var(--space-gutter-phone), env(safe-area-inset-right));
  bottom: calc(var(--bottom-band-h) + var(--space-sm));
  width: auto;
  min-width: 0;
  max-width: none;
  max-height: calc(100dvh - var(--sheet-top) - var(--bottom-band-h) - 2 * var(--space-sm));
  overflow-y: auto;
  overscroll-behavior: contain;
  border-radius: var(--radius-panel);
  animation: menu-up var(--dur-quick) var(--ease-enter);
}
:where(html.bar-layout) .copy-panel.is-sheet {
  position: fixed;
  top: auto; right: 0; bottom: 0; left: 0;
  width: auto;
  --sheet-max-h: calc(100dvh - var(--header-h, 0px));
}


/* The bookmark list (bookmarks plan commit 5, A21): a panel under the toolbar, starting below its symbol's
   group, up to 420 px wide and full width on phones, as tall as the room between the top bars and the
   bottom band, its tree scrolling inside it. popover.ts moves it sideways when the window is too narrow
   to hold it there. Rows indent by level and are at least the touch size tall. A selected row takes the
   selected card's fill and a tick, a row that selects nothing looks greyed. Final looks in phase 6. */
.bookmarks-panel {
  top: calc(100% + var(--space-3));
  left: auto;
  width: 420px;
  max-height: calc(100dvh - var(--top-bars-h, 0px) - var(--bottom-band-h) - 2 * var(--space-3));
  padding: var(--space-7);
  display: flex;
  flex-direction: column;
}
.bookmarks-panel[hidden] { display: none; }
.bookmarks-title { font-size: inherit; padding: var(--space-xs) var(--space-sm) 0; }
.bookmarks-tree, .bookmark-group { list-style: none; }
.bookmarks-tree { min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.bookmark-row { outline: none; }
.bookmark-row[aria-expanded="false"] > .bookmark-group { display: none; }
.bookmark-line {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--size-touch);
  padding: var(--space-xs) var(--space-sm) var(--space-xs) calc(var(--indent, 0) * var(--space-lg));
  border-radius: var(--radius-control);
  cursor: pointer;
}
.bookmark-line:hover { background: var(--color-surface-2); }
.bookmark-row:focus-visible > .bookmark-line { outline: var(--border-medium) solid var(--color-focus); outline-offset: -2px; }
.bookmark-row[aria-selected="true"] > .bookmark-line { background: var(--color-primary-tint-strong); }
/* A row that selects nothing: its words in the disabled grey, its twisty still plain, as it still opens */
.bookmark-row[aria-disabled="true"] > .bookmark-line { color: var(--color-disabled-fg); cursor: default; }
.bookmark-row[aria-disabled="true"] > .bookmark-line :is(.bookmark-file-number, .bookmark-pages) { color: var(--color-disabled-fg); }
.bookmark-twisty {
  flex-shrink: 0;
  align-self: stretch;
  width: var(--space-3xl);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text-secondary);
}
.bookmark-twisty svg { transition: transform var(--dur-quick); }
.bookmark-row[aria-expanded="true"] > .bookmark-line > .bookmark-twisty svg { transform: rotate(90deg); }
.bookmark-text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.bookmark-title { overflow-wrap: anywhere; line-height: var(--leading-sm); }
.bookmark-file > .bookmark-line .bookmark-title { font-weight: var(--weight-semibold); }
.bookmark-file-number { margin-right: var(--space-sm); color: var(--color-primary); }
.bookmark-pages { font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--color-text-muted); overflow-wrap: anywhere; }
.bookmark-tick { flex-shrink: 0; display: flex; visibility: hidden; color: var(--color-primary); }
.bookmark-row[aria-selected="true"] > .bookmark-line > .bookmark-tick { visibility: visible; }
@media (prefers-reduced-motion: reduce) {
  .bookmark-twisty svg { transition: none; }
}

/* The copy panel (E12, deck Screen 7, mockups 19 and 20): a popover --size-panel wide under the tool row,
   starting below the Page group, and on the bar layout a sheet from the bottom, scrolling inside
   when the window is short. Its heading and the two legends 14/20 semibold ink, tick boxes and choices one
   to a row, each the touch size tall, the margin line 12/16 in the brand grey under Signoff blocks, lined
   up with the words. The N/A caution is the shared caution box. Cancel and Copy at the foot, at the right.
   Copy looks greyed while nothing is ticked. */
.copy-panel {
  top: calc(100% + var(--space-xs));
  left: auto;
  width: var(--size-panel);
  text-align: left;
}
.copy-panel-title { margin: 0; font-size: inherit; line-height: inherit; font-weight: var(--weight-semibold); }
.copy-panel-group { border: none; margin: var(--space-md) 0 0; padding: 0; min-width: 0; }
.copy-panel-legend { padding: 0; font-weight: var(--weight-semibold); color: var(--color-text); }
.copy-panel-option { display: flex; align-items: center; gap: var(--space-sm); min-height: var(--size-touch); color: var(--color-text); cursor: pointer; }
.copy-panel-option input { flex: 0 0 auto; margin: 0; cursor: pointer; }
.copy-panel-hint { margin: 0 0 var(--space-xs) calc(var(--size-check) + var(--space-sm)); font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--color-text-secondary); }
.copy-panel-caution { margin-top: var(--space-sm); }
.copy-panel-actions { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: var(--space-sm); margin-top: var(--space-lg); }

/* A drop-down list, drawn as a text field with a chevron at its right (the chevron the secondary grey,
   written into the drawing, as a drawing cannot read a token) */
.select {
  font-family: inherit;
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  padding: 0 var(--space-3xl) 0 var(--space-md);
  border: var(--border-thin) solid var(--color-field-border);
  border-radius: var(--radius-control);
  background: var(--color-surface);
  cursor: pointer;
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%23646364' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' d='M2 4.5l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-md) center;
  background-size: 12px;
  min-height: var(--size-touch); color: var(--color-text); font-weight: var(--weight-regular);
}
@media (max-width: 640px) {
  .select { font-size: var(--text-md); }
}

.workspace { padding: var(--space-15); flex: 1; position: relative; }

/* The box a mouse draws from empty space in the workspace to select the pages it touches (range
   selection, A17): a 1 px dashed steel blue edge on a light steel blue tint the cards show through, over
   the cards and under the bars, the notices and the footer. While it is drawn no text is selected and the
   pointer stays the arrow. */
.select-box {
  position: absolute; z-index: 5;
  border: var(--border-thin) dashed var(--color-primary);
  pointer-events: none;
}
.select-box::before { content: ''; position: absolute; inset: 0; background: var(--color-primary-tint); opacity: var(--opacity-select-box); }
html.is-boxing, html.is-boxing * { user-select: none; -webkit-user-select: none; cursor: default; }
@media (forced-colors: active) {
  .select-box { border-color: Highlight; }
  .select-box::before { display: none; }
}

/* The pages, grouped by file (M8). Each file has a band: a pale steel blue bar with the file's number in a
   steel blue disc, its name, its page count and Select all pages, then its cards. */
.thumbs { display: flex; flex-direction: column; gap: var(--space-2xl); }
/* Review's overview banner above the grid (E5, phase 5 C-2.5, and the owner's one Review flow of 17 Oct): one
   slim line in the shared caution look (.caution, with the dialogs' cautions), how many pages show at its
   left and Show all pages at its right, the short forms of both on phones (640 px and below). It never
   wraps: the count gives way with an ellipsis before the button would. */
.review-bar { margin-bottom: var(--space-2xl); }
.review-bar-text { flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-weight: var(--weight-semibold); }
.review-bar-text:focus { outline: none; }
.review-bar-all { flex: none; margin-left: auto; white-space: nowrap; }
.review-short { display: none; }
@media (max-width: 640px) {
  .review-wide { display: none; }
  .review-short { display: inline; }
}
.file-band { display: flex; flex-direction: column; gap: var(--space-lg); min-width: 0; }
.file-band-head {
  display: flex; align-items: center; flex-wrap: nowrap;
  gap: var(--space-md);
  background: var(--color-primary-tint);
  border-radius: var(--radius-card);
  padding: 0 var(--space-xs) 0 var(--space-lg);
  min-height: var(--size-touch);
}
/* One slim line at every width, as tall as Select all pages (testing item 10): the number disc and the
   name, the page count and the pages moved and removed beside them, and the button at the bar's end. The
   title takes the room left over, up to its own width, and keeps at least the disc and two letters, so a
   long name is cut first, then the changes. */
.file-band-title {
  flex: 1 1 0; min-width: calc(var(--size-band-disc) + var(--space-md) + 2em); max-width: max-content;
  display: flex; align-items: center; gap: var(--space-md);
  font-size: var(--text-md); line-height: var(--leading-md); font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-snug);
  color: var(--color-text);
}
/* The file's number in white on a steel blue disc (7.61:1), wider for two figures */
.file-band-number {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: var(--size-band-disc); height: var(--size-band-disc);
  padding: 0 var(--space-xs);
  border-radius: var(--radius-pill);
  background: var(--color-primary);
  color: var(--color-on-dark);
  font-size: var(--text-sm); line-height: var(--leading-sm); font-weight: var(--weight-semibold);
  letter-spacing: 0;
}
.file-band-name { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The page count and the changes in the deeper grey, 5.25:1 on the band's tint, the changes after a thin
   rule and cut short only once the name can give no more. Their short words show on phones only (below). */
.file-band-pages { flex: 0 0 auto; font-size: var(--text-sm); line-height: var(--leading-sm); color: var(--color-text-secondary-page); white-space: nowrap; }
.file-band-changes-short { display: none; }
.file-band-changes, .file-band-changes-short {
  flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding-left: var(--space-md); border-left: var(--border-thin) solid var(--color-border-strong);
  font-size: var(--text-sm); line-height: var(--leading-sm); color: var(--color-text-secondary-page);
}
/* Select all pages, steel blue words with no edge, a deeper tint under the pointer than the band's own */
.file-band-select { flex: 0 0 auto; margin-left: auto; }
.file-band-select:hover { background: var(--color-primary-tint-strong); }
/* Its symbols show on phones only (below) */
.file-band-symbol { display: none; }

/* Each band's grid of cards. Its columns follow the thumbnail size, set on #thumbs: small, medium (the
   default) or large. The rows sit further apart than the columns, for the page-number line. */
.file-band-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--space-2xl) var(--space-lg); }
.thumbs.size-small .file-band-cards { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
.thumbs.size-large .file-band-cards { grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr)); }

/* A page card (phase 6 look): the page itself is the card, drawn with the page shadow on the page colour
   with no frame of its own, and under it the page-number line. The card keeps a rounded shape for its
   focus ring and the flash after a move. */
.thumb {
  position: relative;
  border-radius: var(--radius-card);
  -webkit-tap-highlight-color: transparent;
}
/* When the cards change, the browser keeps the page's scroll by a whole card, never by a part inside one
   (overflow-anchor, set on every part, since the browser looks inside a part left out). A part can move
   inside its card, as the page does when a signoff margin widens it and the page number line does when the
   Removed tag takes its place, and keeping the scroll by that part would scroll the whole page by its move. */
.thumb * { overflow-anchor: none; }
/* Selected: a 2 px steel blue frame 2 px outside the page and a steel blue disc with a white tick on the
   frame's top left corner, half outside it, above the marks, with a white ring. The tick is drawn white
   into the image, as a drawing cannot read a token. */
.thumb.selected .thumb-page { outline: var(--border-medium) solid var(--color-selected); outline-offset: var(--border-medium); }
.thumb.selected .thumb-page::after {
  content: '';
  position: absolute; z-index: 3;
  top: calc(var(--size-tick-disc) / -2 - 1.5 * var(--border-medium));
  left: calc(var(--size-tick-disc) / -2 - 1.5 * var(--border-medium));
  width: var(--size-tick-disc); height: var(--size-tick-disc);
  border-radius: var(--radius-round);
  background: var(--color-selected) url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / var(--space-md) no-repeat;
  box-shadow: 0 0 0 var(--border-pill) var(--color-surface);
}
/* Not selected means no markings will be added, not that the page is left out, so only a light dim, of
   the page and its markings, never of the frame, the tick or the move and caution marks, which keep their
   full colour */
.thumb.deselected .thumb-page > :not(.thumb-moved, .thumb-caution), .thumb.deselected :is(.thumb-pending-label, .thumb-failed) { opacity: var(--opacity-unselected); }
/* The page is the button that selects it. Its focus shows around the whole card, clear of the selected
   frame, and the card is not clipped. */
.thumb-select {
  display: block; width: 100%;
  padding: 0; border: 0; border-radius: 0;
  background: none; color: inherit; font: inherit; text-align: center;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.thumb-select:focus-visible { outline: none; }
.thumb:has(> .thumb-select:focus-visible) { outline: var(--border-medium) solid var(--color-focus); outline-offset: var(--space-sm); }

.thumb-canvas-wrapper {
  position: relative;
  display: flex; align-items: center; justify-content: center;
}

/* The thumbnail box (THUMB_BOX in geometry.ts): as wide as US Letter and as tall as A4 at the thumbnail
   size, both set on #thumbs from main.ts, and narrower with the column where the column is narrower.
   Every card of a size has the same box, so the page number lines sit at one height. */
.thumb-box {
  display: flex; align-items: center; justify-content: center;
  width: min(100%, var(--thumb-box-width));
  aspect-ratio: var(--thumb-box-shape);
}

/* The page as drawn, with its markings laid over it, centred in the box. Its width is set as a share of
   the box's from the page's size and fit, and the canvas, drawn at the screen's pixel density, fills it. */
.thumb-page { display: block; position: relative; min-width: 0; }

.thumb canvas {
  width: 100%; height: auto; display: block;
  box-shadow: var(--shadow-page);
  background: var(--color-paper);
  transition: box-shadow var(--dur-fast);
}
/* Under a mouse the page lifts a little */
@media (hover: hover) {
  .thumb-select:hover canvas { box-shadow: var(--shadow-popover); }
}

/* Until a thumbnail is drawn, and when it cannot be: a sunken page. Until it is drawn the page number
   sits in its middle, in the deeper grey (5.34:1 on the sunken fill). */
.thumb-canvas-wrapper:is(.pending, .failed) canvas { background: var(--color-surface-2); }
.thumb-pending-label { display: none; }
.thumb-canvas-wrapper.pending .thumb-pending-label {
  display: flex; align-items: center; justify-content: center;
  position: absolute; inset: 0;
  font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--color-text-secondary-page);
  pointer-events: none;
}
/* A page that could not be drawn says so in place of the page, in the deeper grey under a grey page
   symbol that carries no caution, as the page is still saved */
.thumb-failed { display: none; }
.thumb-canvas-wrapper.failed .thumb-failed {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-sm);
  position: absolute; inset: 0; padding: var(--space-sm);
  font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--color-text-secondary-page);
  text-align: center;
  pointer-events: none;
}
.thumb-canvas-wrapper.failed .thumb-failed::before {
  content: '';
  flex: 0 0 auto;
  width: var(--size-symbol); height: var(--size-symbol);
  background: var(--color-disabled-fg);
  -webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 3H6a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V8z'/%3E%3Cpath d='M14 3v5h5'/%3E%3Cpath d='M8 13h8M8 17h5'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 3H6a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V8z'/%3E%3Cpath d='M14 3v5h5'/%3E%3Cpath d='M8 13h8M8 17h5'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* The page-number line under the page: Page n in small semibold ink figures, then the open symbol, a
   symbol button with no edge so a grid of pages stays quiet */
.thumb-footer {
  padding-top: var(--space-xs);
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-xs);
}
/* Small cards can be too narrow for the page number and the button side by side */
.thumbs.size-small .thumb-footer { flex-wrap: wrap; }
.thumb-info { display: flex; flex-direction: column; gap: var(--space-2xs); min-width: 0; }
.thumb-page-num {
  font-size: var(--text-xs); line-height: var(--leading-xs); font-weight: var(--weight-semibold);
  color: var(--color-text);
}
.thumb-open { border-color: transparent; background: transparent; }
@media (forced-colors: active) {
  .thumb.selected .thumb-page::after { forced-color-adjust: none; background-color: Highlight; }
  .thumb-canvas-wrapper.failed .thumb-failed::before { forced-color-adjust: none; background: CanvasText; }
}
/* The annotate screen (final styling in phase 6). It covers the workspace under the shared header, from
   the header's bottom edge to the top of the bottom band, which has no footer here (B20 point 5), so the
   thumbnails behind keep their pixels and the workspace its scroll position. Above the header and
   toolbar block (10), under notices and dialogs (100). While a menu of it is open it is
   raised above the notices, so the menu is never covered. On the bar layout the bottom band holds the
   screen's tool row, held as a bar at the window's foot, and the screen starts with its top row (below). */
.annotate-screen {
  position: fixed;
  left: 0; right: 0;
  top: var(--header-h, 0px);
  bottom: var(--bottom-band-h);
  z-index: 50;
  background: var(--color-surface);
  display: flex; flex-direction: column;
}
.annotate-screen.raised { z-index: 101; }
/* While it shows the page behind does not scroll, and the toolbar is hidden too, so a raised header block
   (Beta open) never shows it over the screen. The page's scrollbar goes with its scrolling, and the room
   it had (--root-gutter, main.ts adds annotate-gutter only when there was one) is kept at the right of the
   page's content, so the workspace behind keeps its layout while this screen and the header reach the
   window's right edge (owner, 13 Oct). The header reaches over that room. The files screen below does
   the same, its footer reaching the edge too. */
html.annotate-open, html.files-open { overflow: hidden; }
html.annotate-open.annotate-gutter .app, html.files-open.files-gutter .app { padding-right: var(--root-gutter, 0px); }
html.annotate-open.annotate-gutter .header, html.files-open.files-gutter .header { margin-right: calc(-1 * var(--root-gutter, 0px)); }
html.annotate-open :is(#toolbar, #toolRow), html.files-open :is(#toolbar, #toolRow) { visibility: hidden; }
/* On the bar layout the bar at the foot of the workspace leaves the bottom band while it is hidden, and the
   room at the workspace's end keeps its height, so the workspace behind keeps its scroll position. On the
   annotate screen the band holds that screen's own bar instead there (below), which the room at the
   workspace's end leaves out for the same reason. */
html.annotate-open, html.files-open { --tools-band-h: 0px; }
html.annotate-open .app, html.files-open .app { padding-bottom: calc(var(--page-end) - var(--tools-band-h) + var(--tools-bar-h, 0px)); }

/* The files screen (E3 commit 15, final styling in phase 6): the file panel opened from the workspace by
   Files. Like the annotate screen it covers the workspace under the header, from the header's bottom edge
   to the top of the bottom band, and never hides it, so the thumbnails behind keep their pixels and the
   workspace its scroll position. The panel scrolls inside it, laid out as on Start, with the band's top
   bar held at the top of the screen and its foot with Cancel and Apply changes held above the footer, as
   on Start. The band reaches down to the foot and keeps room at its end as tall as the notices, so its
   last card can be scrolled clear of them. Drop to load lines up with the band, which is narrower than
   the window by the room kept for this screen's scrollbar (--files-gutter). */
.files-screen {
  position: fixed;
  left: 0; right: 0;
  top: var(--header-h, 0px);
  bottom: var(--bottom-band-h);
  z-index: 50;
  background: var(--color-bg);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
  scroll-padding-top: var(--bench-top-h, 0px);
  scroll-padding-bottom: calc(var(--notices-h, 0px) + 12px);
}
.files-screen > .file-panel { min-height: 100%; }
.files-screen .file-panel-bench { margin-bottom: 0; padding-bottom: var(--notices-h, 0px); }
.files-screen .file-panel-top { top: 0; }
.files-screen .drop-hint {
  top: calc(var(--header-h, 0px) + var(--space-md));
  left: 0;
  right: var(--files-gutter, 0px);
  border-radius: 0;
}
@media (min-width: 1024px) and (orientation: landscape) {
  .files-screen .drop-hint {
    left: max(var(--space-2xl), calc((100% - var(--files-gutter, 0px) - var(--size-bench-max)) / 2 + var(--space-2xl)));
    right: calc(max(var(--space-2xl), calc((100% - var(--files-gutter, 0px) - var(--size-bench-max)) / 2 + var(--space-2xl))) + var(--files-gutter, 0px));
    border-radius: var(--radius-panel);
  }
}

/* The tool row, in the workspace ribbon's look (L5): white with a hairline under it, groups of controls 4
   px apart with their captions under them (Mark, Selected while a marking is selected, Page, View), 24 px
   apart with a hairline divider between them, then Undo and Done at the end. It
   wraps onto more rows when the window is narrow. It sits above the page area, so its menus show over
   the page. A group that starts a new row has its divider in the row's side padding, where the row's own
   strip at its left edge covers it, as on the workspace toolbar. */
.annotate-toolbar {
  --ribbon-pad: var(--space-2xl);
  --ribbon-gap: calc(2 * var(--space-sm));
  --ribbon-half: calc(var(--ribbon-gap) / 2);
  position: relative;
  z-index: 5;
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm) var(--ribbon-gap);
  padding: var(--space-sm) max(var(--ribbon-pad), env(safe-area-inset-right)) var(--space-sm) max(var(--ribbon-pad), env(safe-area-inset-left));
  border-bottom: var(--border-thin) solid var(--color-border);
  background: var(--color-surface);
  flex-wrap: wrap;
}
.annotate-toolbar .btn { min-height: 44px; }
.annotate-toolbar .toolbar-controls { gap: var(--space-xs); }
.annotate-toolbar .toolbar-caption { font-size: var(--text-xs); line-height: var(--leading-xs); font-weight: var(--weight-medium); color: var(--color-text-secondary); text-align: center; }
.annotate-toolbar > .toolbar-group + .toolbar-group { position: relative; }
.annotate-toolbar > .toolbar-group + .toolbar-group::before {
  content: '';
  position: absolute;
  top: 0;
  left: calc(-1 * var(--ribbon-half));
  width: var(--border-thin);
  height: var(--size-ribbon-divider);
  background: var(--color-border);
}
.annotate-toolbar::before {
  content: '';
  position: absolute;
  z-index: 1;
  top: 0;
  bottom: 0;
  left: 0;
  width: calc(max(var(--ribbon-pad), env(safe-area-inset-left)) - var(--ribbon-half) + var(--border-thin));
  background: var(--color-surface);
  pointer-events: none;
}
.annotate-toolbar .menu, .annotate-toolbar .popover { z-index: 2; }
/* The Selected group is contextual, so while a marking is selected it reads as a mode, as the Edit group
   does: its controls on a pale steel blue panel with a 2 px steel blue top edge, its caption in the deeper
   grey (5.25:1 on the tint). The panel reaches into the row's padding above and below, so the row keeps
   its height, and into the gaps at its sides as far as the dividers would sit, so it takes no more width
   than its controls and its own edges stand in for the dividers beside it. */
.annotate-selected-group {
  padding: var(--space-2xs) var(--ribbon-half) var(--space-xs);
  margin: calc(-1 * var(--space-xs)) calc(-1 * var(--ribbon-half));
  border-top: var(--border-medium) solid var(--color-primary);
  border-radius: var(--radius-card);
  background: var(--color-primary-tint);
}
.annotate-toolbar > .toolbar-group.annotate-selected-group::before, .annotate-toolbar > .annotate-selected-group:not([hidden]) + .toolbar-group::before { content: none; }
.annotate-selected-group .toolbar-caption { color: var(--color-text-secondary-page); }
/* The Marking controls in task order (testing item 12, owner 13 Oct): Deselect, then Move, Size, Cells
   (its tray of Split column, Not required and Clear N/R on every layout) and Delete, each part after the
   first with a hairline divider before it, 6 px clear on both sides (owner, 17 Oct, 2 px each side given to the 11 inch iPad held sideways) and the
   height of a symbol button less 8 px above and below. A part with no
   control for the selected marking hides with its divider (Size for a block, Cells for an N/A box). On the
   ribbon they start at Move, Deselect left to a click beside the page or on empty page and to Escape
   (owner, 14 Oct, open question 7 (b)). The bar layout keeps Deselect. */
.marking-part { display: flex; align-items: center; gap: var(--space-xs); }
.marking-part[hidden] { display: none; }
:where(html:not(.bar-layout)) .marking-part:has(> #annotDeselectBtn) { display: none; }
:where(html:not(.bar-layout)) .marking-part:has(> #annotDeselectBtn) + .marking-part::before { content: none; }
.marking-part + .marking-part::before {
  content: '';
  flex: none;
  width: var(--border-thin);
  height: calc(var(--size-touch) - 2 * var(--space-sm));
  margin: 0 var(--space-2xs);
  background: var(--color-border-strong);
}
/* Undo, then Done, the screen's main action, kept together at the end of the row */
.annotate-end { margin-left: auto; display: flex; align-items: flex-start; flex-wrap: wrap; gap: var(--space-sm) var(--space-xs); }
.annotate-end > #modalDone { margin-left: calc(var(--ribbon-gap) - var(--space-xs)); }
/* Held at the right end of its first row, as on the workspace ribbon, so Undo stays put when a
   marking is selected or a tool turns on, at every width the row shows in full (testing item 5) */
:where(html:not(.bar-layout)) .annotate-toolbar { padding-right: calc(max(var(--ribbon-pad), env(safe-area-inset-right)) + var(--ribbon-end-room, 0px) + var(--ribbon-gap)); }
:where(html:not(.bar-layout)) .annotate-end { position: absolute; top: var(--space-sm); right: max(var(--ribbon-pad), env(safe-area-inset-right)); flex-wrap: nowrap; }
/* View (owner, 15 Oct, view controls rework): the page strip, Previous page, the page number as 1/4 and Next
   page in one box, then Zoom, a symbol button that opens its tray of Fit page, Zoom out and Zoom in (main.ts),
   on one row at every width. The strip and Zoom are --size-touch tall, the strip's edge and corners those of
   a symbol button, its buttons borderless inside it. The same group shows on the ribbon, in the row under the
   header of the bar layout and in the slim header of its short variant, where the header's controls are
   --size-touch-short tall. Ctrl or Cmd with the wheel, a pinch and the keys zoom as before. */
.annotate-view { flex-wrap: nowrap; }
.annotate-nav {
  --strip-btn: var(--size-touch);
  display: flex;
  align-items: stretch;
  box-sizing: border-box;
  height: var(--strip-btn);
  border: var(--border-thin) solid var(--color-border-strong);
  border-radius: var(--radius-control);
  background: var(--color-surface);
}
/* Each part takes the strip's whole height over its edge, so the edge is pressed with it, and its fill keeps
   inside the edge */
.annotate-nav > .icon-btn, .annotate-nav > .annotate-title { margin-top: calc(-1 * var(--border-thin)); margin-bottom: calc(-1 * var(--border-thin)); }
.annotate-nav > .icon-btn {
  min-width: var(--strip-btn);
  min-height: var(--strip-btn);
  border-color: transparent;
  background: transparent;
  background-clip: padding-box;
}
.annotate-nav > .icon-btn:first-child { margin-left: calc(-1 * var(--border-thin)); }
.annotate-nav > .icon-btn:last-child { margin-right: calc(-1 * var(--border-thin)); }
.annotate-nav > .icon-btn:hover { background: var(--color-surface-2); }
.annotate-nav > .icon-btn:is(.is-unavailable, [aria-disabled="true"]) { border-color: transparent; background: transparent; }
/* The workspace's View (owner, 15 Oct, view controls rework): Thumbnail size, a symbol button showing the
   chosen size's symbol, opens its tray of Small, Medium and Large (main.ts), a set of radio buttons with the
   chosen size tinted pale steel blue under a steel blue symbol. It replaces the strip of three and its room
   rule. On the ribbon it stands after Pages, captioned View, and on the bar layout in the tool row under the
   header before Undo and Save, or in the slim header on a short landscape screen (frame.ts), its caption kept
   for screen readers. */
.annotate-title { min-height: var(--strip-btn, var(--size-touch)); display: flex; align-items: center; font-size: var(--text-sm); line-height: var(--leading-sm); font-weight: var(--weight-semibold); white-space: nowrap; }
.annotate-title:focus { outline: none; }
.annotate-title:focus-visible { outline: var(--border-medium) solid var(--color-focus); outline-offset: var(--space-2xs); }
.annotate-title-text { display: inline-flex; align-items: center; }
/* The page number is Go to page's button, and its number field takes its place. The number, 1/4, is never
   cut: it shares one grid cell with the widest number of the task card drawn unseen (data-widest, main.ts),
   so with tabular figures it keeps one width from page to page, with 8 px sides, and the field opens in the
   same room (main.ts), so nothing moves when it opens. The number is borderless as the symbols are, its fill
   showing on hover inside the box the field is drawn in, a field's edge in the field grey (3.50:1 on white),
   so a press swaps two boxes of one size. */
.annotate-goto, .annotate-goto-field {
  box-sizing: border-box;
  margin: 0;
  border: 0;
  border-radius: var(--radius-control);
  background: transparent;
  font: inherit;
  letter-spacing: inherit;
  text-align: center;
  color: inherit;
}
.annotate-goto {
  position: relative;
  z-index: 0;
  display: inline-grid;
  grid-template-areas: "number";
  align-items: center;
  justify-items: center;
  height: var(--strip-btn, var(--size-touch));
  padding: 0 var(--space-sm);
  white-space: nowrap;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.annotate-goto-number { grid-area: number; }
.annotate-goto::after { content: attr(data-widest); grid-area: number; visibility: hidden; }
.annotate-goto::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: var(--space-xs) 0;
  border-radius: var(--radius-control);
}
.annotate-goto:hover::before { background: var(--color-surface-2); }
.annotate-goto:focus { outline: none; }
/* The ring drawn just inside the number */
.annotate-goto:focus-visible { outline: var(--border-medium) solid var(--color-focus); outline-offset: calc(-1 * var(--border-medium)); }
.annotate-goto-field {
  height: calc(var(--strip-btn, var(--size-touch)) - 2 * var(--space-xs));
  margin: var(--space-xs) 0;
  padding: 0 var(--space-sm);
  border: var(--border-thin) solid var(--color-field-border);
  background: var(--color-surface);
}
.annotate-goto-field:focus { outline: var(--border-medium) solid var(--color-focus); outline-offset: 0; }
.annotate-goto[hidden], .annotate-goto-field[hidden] { display: none; }

.page-preview-wrapper {
  position: relative;
  background: var(--color-surface-2);
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--space-lg) max(var(--space-lg), env(safe-area-inset-right)) var(--space-lg) max(var(--space-lg), env(safe-area-inset-left));
  /* Room above and below the page that holds it still while the tool row changes height (main.ts
     keepPageStill), none at all most of the time */
  padding-top: calc(var(--space-lg) + var(--hold-top, 0px));
  /* Room under the page as tall as the notices in the corner (notices.ts), so it can be scrolled clear.
     The bottom band below keeps clear of the iPhone home bar. */
  padding-bottom: calc(var(--space-lg) + var(--notices-h, 0px) + var(--hold-bottom, 0px));
  /* A marking shown whole after a selection, a key or a tap (main.ts revealSelected) stops 8 px under the
     tool row, so its selection outline and focus ring are never cut by it (phase 6 list) */
  scroll-padding-top: var(--space-sm);
  min-height: 0;
  flex: 1;
  /* A scrollbar that takes room has it kept from the start, so the page never moves sideways when the
     area gains or loses a scrollbar, and on phones, where the page fits this area's width (main.ts), a
     tall page never pushes the area into a sideways scroll. */
  scrollbar-gutter: stable;
  /* One finger scrolls the page area, and a pinch on it zooms the page itself (main.ts), never the whole
     window, which the browser's pinch still zooms from the bars around it (Q13) */
  touch-action: pan-x pan-y;
}
/* The page area takes focus by Tab, so a zoomed page can be scrolled by keyboard (A14) */
.page-preview-wrapper:focus { outline: none; }
.page-preview-wrapper:focus-visible { outline: var(--border-medium) solid var(--color-focus); outline-offset: calc(-1 * var(--border-medium)); }
/* Focus moved there by a key that took the selected marking away shows no ring (main.ts focusPageArea) */
.page-preview-wrapper.no-ring:focus-visible { outline: none; }
/* The page and its markings, centred; markings are placed from its corner. A page wider than the area
   scrolls from its left edge. */
.annotate-page { position: relative; margin: 0 auto; isolation: isolate; }
/* The page's canvas and its margin's strip lie below everything else in the page box, set apart in their
   own layer, so the markings and their controls always draw above them in one layer, also where a control
   reaches past its marking over the page (a block in the strip, its N/R clear mark over the page's edge).
   Safari otherwise keeps a marking that does not overlap the drawn page below the page's layer, covering
   the part of a control over the page and leaving a removed control's image behind (owner, 15 Oct). */
.annotate-page > canvas { position: relative; z-index: -1; }
/* A page with a signoff margin: the strip on the canvas's right is part of the page, blank and white
   (F-A8), with only the dotted screen line below at the old edge, and the page's shadow goes round both */
.annotate-strip {
  position: absolute; top: 0; right: 0; height: 100%;
  z-index: -1;
  background: var(--color-paper);
  touch-action: none;
}
.annotate-strip[hidden] { display: none; }
/* Where the page ends and its strip begins, a thin dotted line the page's full height on the strip's side
   of the edge, so it never covers the page's own content (owner, 11 Oct). It is on screen only, lies over
   the page and the strip and under every marking and control, and takes no pointer. */
.annotate-edge {
  position: absolute; top: 0; left: 0; height: 100%;
  width: 0;
  border-left: var(--border-thin) dotted var(--color-page-edge);
  pointer-events: none;
}
.annotate-page.has-margin { background: var(--color-paper); box-shadow: var(--shadow-page); }
.page-preview-wrapper .annotate-page.has-margin canvas { box-shadow: none; }
/* In place of the page when it cannot be drawn: thumb.failed centred in the deeper grey (5.34:1 on the
   sunken area) */
.annotate-failed { padding: var(--space-lg); text-align: center; font-size: var(--text-sm); line-height: var(--leading-sm); color: var(--color-text-secondary-page); }
.page-preview-wrapper canvas {
  background: var(--color-paper);
  box-shadow: var(--shadow-page);
  cursor: crosshair;
  display: block;
}

/* The loading cover: the page colour at 92% over everything but the session dialog, a steel blue ring
   turning on its pale steel blue track, and the progress words under it, 16/24 in the deeper grey (4.9:1
   at worst, over the bench). With reduced motion the ring stands still, whole, and the words tell the
   progress. */
.loading {
  position: fixed; inset: 0;
  background: var(--color-cover);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  z-index: 200; gap: var(--space-lg);
  padding: 0 var(--space-lg);
}

.spinner {
  width: var(--size-spinner); height: var(--size-spinner);
  border: var(--border-thick) solid var(--color-primary-tint-strong);
  border-top-color: var(--color-primary);
  border-radius: var(--radius-round);
  animation: spin var(--dur-spin) linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .spinner { animation: none; border-color: var(--color-primary); }
}

.loading-msg {
  font-size: var(--text-md); line-height: var(--leading-md);
  font-weight: var(--weight-medium);
  color: var(--color-text-secondary-page);
  text-align: center;
}

/* Annotation overlays on the page in the annotate screen */
.page-preview-wrapper canvas { touch-action: none; }

.annotation {
  position: absolute;
  box-sizing: border-box;
  pointer-events: auto;
  cursor: move;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
.annotation.dragging { z-index: 3; will-change: transform; }
/* A marking takes keyboard focus (keyboard markings plan, A3). The browser's own focus outline gives way
   to the selection outline below, and keyboard focus adds a ring just outside it. */
.annotation:focus { outline: none; }
/* The selected marking: a steel blue outline just outside it, on screen only */
.annotation.selected { outline: var(--marking-selected-width) solid var(--marking-selected); outline-offset: var(--marking-selected-offset); }
.annotation:focus-visible::after {
  content: '';
  position: absolute;
  inset: calc(-1 * (var(--marking-selected-offset) + var(--marking-selected-width) + var(--border-medium)));
  border: var(--border-medium) solid var(--color-focus);
  pointer-events: none;
}

/* Split columns (E9). Each split of the selected column is a line across it that a press drags and the
   keys move, its box taller than the line so a finger finds it, with its remove symbol beside the column's
   right edge, or where main.ts places it to stay in view (placeSplitRemoves). The server's drawing shows
   the line itself, and the box draws it only while the column shows its plain outline (a split moving, or
   the drawing not here yet). With Split column on, a press on the
   column adds a split, so the lines let presses through, and the dotted guide shows where it would go.
   A split line a tap picked, for Move up and Move down to move it, shows the ring of a split line with
   keyboard focus. */
.split {
  position: absolute;
  left: 0; right: 0;
  height: 0;
}
/* Its press area reaches --split-up above the line and --split-down below it, each half the press height or
   half the room to the next line or edge if that is less (main.ts) */
.split-line {
  --split-up: min(var(--size-split-hit) / 2, var(--split-room-up, var(--size-split-hit)));
  --split-down: min(var(--size-split-hit) / 2, var(--split-room-down, var(--size-split-hit)));
  position: absolute;
  left: 0; right: 0;
  top: calc(-1 * var(--split-up));
  height: calc(var(--split-up) + var(--split-down));
  cursor: row-resize;
  touch-action: none;
}
.split-line:focus { outline: none; }
.annotation.awaiting .split-line::before {
  content: '';
  position: absolute;
  left: 0; right: 0;
  top: var(--split-up);
  border-top: var(--border-thin) solid var(--marking-ink);
}
.split-line:focus-visible::after,
.split.picked > .split-line::after {
  content: '';
  position: absolute;
  left: calc(-1 * var(--border-medium));
  right: calc(-1 * var(--border-medium));
  top: calc(var(--split-up) - var(--size-split-ring) / 2);
  height: var(--size-split-ring);
  border: var(--border-medium) solid var(--color-focus);
  pointer-events: none;
}
.split-mode .split-line { pointer-events: none; }
.split-mode .annotation.selected.column { cursor: crosshair; }
.split-remove {
  position: absolute;
  left: calc(100% + var(--space-3));
  top: calc(var(--size-split-remove) / -2);
  width: var(--size-split-remove);
  height: var(--size-split-remove);
  padding: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--color-surface);
  color: var(--marking-selected);
  border: var(--border-thin) solid var(--marking-selected);
  border-radius: var(--radius-round);
  cursor: pointer;
}
/* The dotted guide at a split being placed or moved, across the whole page and its margin's strip, so it
   lines up with the step text (owner, 11 Oct), in copper apart from the selection's steel blue. It comes
   before the markings in the page box, so it lies over the page and under them and their controls. */
.split-guide {
  position: absolute;
  left: 0; right: 0;
  height: 0;
  border-top: var(--border-thin) dotted var(--color-guide);
  pointer-events: none;
}

/* Not required cells (E10). While Not required is on, each cell of the selected block or column is a
   button over the cell, its dotted steel blue edge just inside the cell's lines, so the user sees where a
   tap marks or clears N/R. The server's drawing shows the mark itself. A block's cell is its half, label
   included, and a column's each half of a row under the label band. */
.nr-cell {
  position: absolute;
  width: 50%;
  padding: 0;
  background: transparent;
  border: 0;
  cursor: pointer;
  touch-action: manipulation;
}
.nr-cell.left { left: 0; }
.nr-cell.right { left: 50%; }
.nr-cell::before {
  content: '';
  position: absolute;
  inset: var(--space-2);
  border: var(--border-thin) dotted var(--marking-selected);
  pointer-events: none;
}
@media (hover: hover) { .nr-cell:hover { background: var(--marking-cell-hover); } }
.nr-cell:focus { outline: none; }
.nr-cell:focus-visible::after {
  content: '';
  position: absolute;
  inset: 0;
  border: var(--border-medium) solid var(--color-focus);
  pointer-events: none;
}
.nr-mode .annotation.selected { cursor: default; }
/* A cell's clear mark (testing item 16): the split remove symbol's round look, centred in its box beside the
   marking's outer edge on the cell's side at the cell's middle height (main.ts placeNrClears), so it never
   covers the cell's N/R. It shows only while its cell holds N/R, with the pointer on the cell or the mark,
   with keyboard focus on the cell, or on touch screens while the cell is the last one tapped. */
.nr-clear {
  position: absolute;
  display: none;
  width: var(--size-nr-clear-hit);
  height: var(--size-nr-clear-hit);
  margin-top: calc(var(--size-nr-clear-hit) / -2);
  padding: 0;
  align-items: center; justify-content: center;
  background: transparent;
  border: 0;
  cursor: pointer;
  touch-action: manipulation;
}
.nr-clear-symbol {
  width: var(--size-nr-clear);
  height: var(--size-nr-clear);
  display: flex; align-items: center; justify-content: center;
  background: var(--color-surface);
  color: var(--marking-selected);
  border: var(--border-thin) solid var(--marking-selected);
  border-radius: var(--radius-round);
  pointer-events: none;
}
.nr-cell.marked:is(:focus-visible, .recent) + .nr-clear { display: flex; }
@media (hover: hover) {
  .nr-cell.marked:hover + .nr-clear, .nr-cell.marked + .nr-clear:hover { display: flex; }
  .nr-clear:hover .nr-clear-symbol { background: var(--marking-selected); color: var(--color-surface); }
}

/* Resizing by edges (phase 5 B20). The selected column has a handle on its top and bottom edges and the
   selected N/A box on its four edges and corners, each shown by a small square on the selection outline.
   A handle reaches mostly outside the marking: inside it by --size-resize-in at most and never past a
   quarter of its width or height, so the middle of even the smallest marking still moves it, and outside
   by the rest of --size-resize-hit (44 px in all on touch screens). It lies under the marking's split
   lines, which come after it, so where the two meet the split line takes the press. The splits' remove
   symbols sit beside the column's right edge, which has no handle, and a top or bottom handle reaches no
   wider than the column. The selected marking stands above the others, so its handles and remove symbols
   are reachable over a marking beside it. */
.annotation.selected:not(.dragging) { z-index: 1; }
.resize-handle {
  --resize-out: calc(var(--size-resize-hit) - var(--size-resize-in));
  --resize-reach: calc(var(--resize-out) + min(var(--size-resize-in), 25%));
  /* Where the square's outer side sits from the handle's outer side, the square centred on the outline */
  --resize-grip-at: calc(var(--resize-out) - var(--marking-selected-offset) - var(--marking-selected-width) / 2 - var(--size-resize-grip) / 2);
  position: absolute;
  touch-action: none;
}
.resize-handle::before {
  content: '';
  position: absolute;
  box-sizing: border-box;
  width: var(--size-resize-grip);
  height: var(--size-resize-grip);
  background: var(--color-surface);
  border: var(--marking-grip-width) solid var(--marking-selected);
  box-shadow: var(--marking-grip-ring);
  pointer-events: none;
}
/* With a mouse the square under the pointer fills, beside the resize cursor of its edge */
@media (hover: hover) { .resize-handle:hover::before { background: var(--marking-selected); } }
.resize-handle.top, .resize-handle.bottom { left: 0; right: 0; height: var(--resize-reach); cursor: ns-resize; }
.resize-handle.left, .resize-handle.right { top: 0; bottom: 0; width: var(--resize-reach); cursor: ew-resize; }
.resize-handle.top-left, .resize-handle.top-right, .resize-handle.bottom-left, .resize-handle.bottom-right { width: var(--resize-reach); height: var(--resize-reach); }
.resize-handle.top-left, .resize-handle.bottom-right { cursor: nwse-resize; }
.resize-handle.top-right, .resize-handle.bottom-left { cursor: nesw-resize; }
.resize-handle.top, .resize-handle.top-left, .resize-handle.top-right { top: calc(-1 * var(--resize-out)); }
.resize-handle.bottom, .resize-handle.bottom-left, .resize-handle.bottom-right { bottom: calc(-1 * var(--resize-out)); }
.resize-handle.left, .resize-handle.top-left, .resize-handle.bottom-left { left: calc(-1 * var(--resize-out)); }
.resize-handle.right, .resize-handle.top-right, .resize-handle.bottom-right { right: calc(-1 * var(--resize-out)); }
.resize-handle.top::before, .resize-handle.top-left::before, .resize-handle.top-right::before { top: var(--resize-grip-at); }
.resize-handle.bottom::before, .resize-handle.bottom-left::before, .resize-handle.bottom-right::before { bottom: var(--resize-grip-at); }
.resize-handle.left::before, .resize-handle.top-left::before, .resize-handle.bottom-left::before { left: var(--resize-grip-at); }
.resize-handle.right::before, .resize-handle.top-right::before, .resize-handle.bottom-right::before { right: var(--resize-grip-at); }
.resize-handle.top::before, .resize-handle.bottom::before { left: calc(50% - var(--size-resize-grip) / 2); }
.resize-handle.left::before, .resize-handle.right::before { top: calc(50% - var(--size-resize-grip) / 2); }

/* The overlap choices (phase 5 C-2.3, deck Annotate view brief, Overlaps, mockup N3). A block or column the
   overlap check flags carries the caution symbol filled in the overlap mark's red with a white
   exclamation mark (6.57:1), centred on its top-right corner and above its handles, with a white ring
   1.5 px wide that keeps it off the page's content, as on the page cards. Its shape and its name carry
   it, never the colour alone. A press on it opens the popover of choices beside the marking, inside the page
   area in view (main.ts placeChoices), and its marking stands above the others while it shows:
   its title, or both causes' titles, then the choices as full-width buttons 8 px apart, Add margin to
   this page the primary one when it shows. */
.annotation.raised { z-index: 4; }
.overlap-choice {
  position: absolute; z-index: 2;
  top: calc(var(--size-overlap-mark) / -2);
  right: calc(var(--size-overlap-mark) / -2);
  width: var(--size-overlap-mark);
  height: var(--size-overlap-mark);
  cursor: default;
}
.overlap-mark {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
  padding: 0;
  border: 0;
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--color-overlap-mark);
  cursor: pointer;
  touch-action: manipulation;
}
.overlap-mark .caution-symbol { width: var(--size-overlap-mark); height: var(--size-overlap-mark); margin: 0; overflow: visible; }
.overlap-mark .caution-shape { fill: currentColor; stroke: var(--color-surface); stroke-width: calc(2 * var(--border-pill) * 24 / 20); paint-order: stroke; }
.overlap-mark .caution-sign { stroke: var(--color-on-dark); }
.overlap-mark:focus { outline: none; }
.overlap-mark:focus-visible { outline: var(--border-medium) solid var(--color-focus); outline-offset: var(--space-2xs); }
.overlap-panel {
  top: calc(100% + var(--space-3));
  right: 0;
  left: auto;
  width: var(--size-overlap-panel);
  display: flex; flex-direction: column; gap: var(--space-sm);
  text-align: left;
  cursor: default;
}
.overlap-panel[hidden] { display: none; }
/* Drawn in the top layer and placed beside the marking by main.ts (placeChoices, owner 17 Oct), scrolling
   inside when the page area in view is shorter than it */
.overlap-panel[popover] { position: fixed; inset: auto; margin: 0; overflow-y: auto; }
.overlap-panel .popover-title { margin: 0; }
/* Both causes, when both apply, each on its own line 4 px apart */
.overlap-panel-titles { display: flex; flex-direction: column; gap: var(--space-xs); }
.overlap-panel-choice { width: 100%; justify-content: flex-start; }
.overlap-panel-choice[hidden] { display: none; }

/* A guide line while an edge of a block or column snaps to another's (snap.ts), on screen only and
   centred on the edge, a 1 px dashed copper line apart from the selection's steel blue. It never takes
   the pointer. */
.snap-guide {
  position: absolute;
  pointer-events: none;
  z-index: 4;
}
.snap-guide.upright { width: 0; margin-left: -0.5px; border-left: var(--border-thin) dashed var(--color-guide); }
.snap-guide.level { height: 0; margin-top: -0.5px; border-top: var(--border-thin) dashed var(--color-guide); }

/* Drawing preview while dragging — base styles */
.drawing-preview {
  position: absolute;
  pointer-events: none;
  z-index: 2;
}
/* While a column or N/A box is drawn: a plain outline, until the user lets go and the server draws it */
.drawing-preview.na, .drawing-preview.column { box-shadow: var(--marking-outline); }
.drawing-preview.column {
  display: flex;
  align-items: flex-start;
  justify-content: center;
}
/* The column's height in mm while it is drawn, white on the deeper steel blue (9.82:1) */
.drawing-preview.column .column-badge {
  margin-top: var(--space-xs);
  padding: var(--space-2xs) var(--space-sm);
  background: var(--color-primary-hover);
  color: var(--color-on-dark);
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
  font-weight: var(--weight-semibold);
  font-variant-numeric: var(--numeric);
  border-radius: var(--radius-tag);
  white-space: nowrap;
}

/* Multi-annotation container in thumbnails */
.thumb-annotations {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
/* The move mark on a moved page (edit-document plan commit 4, A28): a copper disc with two white arrows
   (3.70:1) at the page's bottom right, over the markings, with a white ring that keeps it off the page's
   content, copper as the Save PDF dialog's moved dot. It takes the pointer so its tooltip shows, and a tap
   on it still picks the page. */
.thumb-moved {
  position: absolute; z-index: 2;
  right: var(--space-xs); bottom: var(--space-xs);
  display: flex; align-items: center; justify-content: center;
  width: var(--size-move-mark); height: var(--size-move-mark);
  border-radius: var(--radius-round);
  background: var(--color-move-mark);
  color: var(--color-on-dark);
  box-shadow: 0 0 0 var(--border-pill) var(--color-surface), var(--shadow-raised);
}
.thumb-moved[hidden] { display: none; }
/* The caution mark on a page with a signoff issue (phase 5 B16, mockup W3): the caution symbol filled in
   the overlap mark's red with a white exclamation mark (6.57:1), at the page's bottom left, over the
   markings, with a white ring 1.5 px wide that keeps it off the page's content. The symbol is drawn at
   20 of its 24 units, so the ring's stroke is twice 1.5 px in its units, half of it under the fill. Its
   shape and its tooltip carry it, never the colour alone. It takes the pointer so its tooltip shows, and a
   tap on it still picks the page. */
.thumb-caution {
  position: absolute; z-index: 2;
  left: var(--space-xs); bottom: var(--space-xs);
  display: flex;
  color: var(--color-overlap-mark);
}
.thumb-caution[hidden] { display: none; }
.thumb-caution .caution-symbol { width: var(--size-symbol); height: var(--size-symbol); margin: 0; overflow: visible; }
.thumb-caution .caution-shape { fill: currentColor; stroke: var(--color-surface); stroke-width: calc(2 * var(--border-pill) * 24 / 20); paint-order: stroke; }
.thumb-caution .caution-sign { stroke: var(--color-on-dark); }
@media (forced-colors: active) {
  .thumb-moved { forced-color-adjust: none; background: Highlight; color: HighlightText; }
}
/* A removed page (edit-document plan commit 9, mockup 17): greyed in place at 40% under a diagonal hatch,
   its thumbnail still drawn so the user sees what to restore (A29), with the Removed tag in the page
   number's place (the deeper grey on the sunken fill, 5.34:1) and no open symbol. Selected, it keeps the
   selected frame and tick at full strength. */
.thumb.removed .thumb-page > :not(.thumb-moved, .thumb-caution), .thumb.removed :is(.thumb-pending-label, .thumb-failed) { opacity: var(--opacity-removed); filter: grayscale(1); }
.thumb.removed .thumb-page::before {
  content: '';
  position: absolute; inset: 0; z-index: 1;
  background: repeating-linear-gradient(-45deg, transparent 0 calc(var(--space-sm) - var(--border-thin)), var(--color-hatch) calc(var(--space-sm) - var(--border-thin)) var(--space-sm));
  pointer-events: none;
}
.thumb-removed-tag {
  align-self: flex-start;
  padding: var(--space-2xs) var(--space-sm);
  border-radius: var(--radius-tag);
  background: var(--color-surface-2);
  font-size: var(--text-xs); line-height: var(--leading-xs); font-weight: var(--weight-semibold);
  color: var(--color-text-secondary-page);
}
.thumb-removed-tag[hidden] { display: none; }
/* The open symbol's room is kept, so a removed card is as tall as the others and a Remove or Restore never
   changes the height of a row of cards, which would move the cards in view. It outranks the page-wide
   [hidden] rule below, which would take the room away. */
.thumb-open[hidden] { display: inline-flex !important; visibility: hidden; }
/* The grip on a page that may be dragged while Edit Document is on (edit-document plan commit 5): six dots
   on a small light square at the card's top left, as the mockup draws it, inside a press area of a
   finger's size. Only the grip takes a drag, so a finger anywhere else on the card still scrolls the page,
   and pressing it selects no text and opens no menu of the browser's own. Its look is for phase 6. */
.thumb-grip {
  position: absolute; z-index: 3;
  top: 0; left: 0;
  display: flex; align-items: center; justify-content: center;
  width: var(--size-touch); height: var(--size-touch);
  color: var(--color-text-muted);
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
.thumb-grip[hidden] { display: none; }
.thumb-grip-face {
  display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px;
  background: var(--color-surface);
  border: var(--border-thin) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
}
/* The card being dragged follows the pointer above the other cards and their grips, the batch's other
   cards dim, and the line shows where the batch would go, above the dragged card too: in the gap between
   two cards, or across in one column. The count of a batch of more than one page sits at the dragged
   card's top right. */
.thumb.is-dragging { z-index: 4; background: var(--color-surface); box-shadow: var(--shadow-dialog); will-change: transform; }
.thumb.is-dragging .thumb-grip { cursor: grabbing; }
.thumb.is-batch { opacity: 0.4; }
.thumb-insert {
  position: absolute; z-index: 5;
  width: var(--border-medium);
  transform: translateX(-50%);
  background: var(--color-accent);
  border-radius: var(--radius-xs);
  pointer-events: none;
}
.thumb-insert.is-across { height: var(--border-medium); transform: translateY(-50%); }
.thumb-insert[hidden] { display: none; }
.thumb-drag-count {
  position: absolute; z-index: 3;
  top: var(--space-3); right: var(--space-3);
  display: flex; align-items: center; justify-content: center;
  min-width: 24px; height: 24px; padding: 0 var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--color-accent);
  color: var(--color-on-dark);
  font-size: var(--text-xs); line-height: var(--leading-xs); font-weight: var(--weight-semibold);
  pointer-events: none;
}
/* A page card that has just moved flashes for 700 ms, as a moved file's card does on the bench. With
   reduced motion it holds a steady highlight for the same time. */
.thumb.is-flashing { animation: page-flash 700ms ease-out; }
@keyframes page-flash { from { background: var(--color-primary-tint); } }
@media (prefers-reduced-motion: reduce) {
  .thumb.is-flashing { animation-timing-function: step-end; }
}
.thumb-annot {
  position: absolute;
  pointer-events: none;
}

/* A marking as the server draws it, the same black outlines, lines and labels as the saved PDF.
   Outlines sit on the marking's edge, half outside it, as in the PDF. */
.marking-art {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  overflow: visible;
  pointer-events: none;
}
.marking-art rect, .marking-art line { fill: none; stroke: var(--marking-ink); }
.marking-art text {
  fill: var(--marking-ink);
  font-family: var(--marking-font);
  font-kerning: none;
  font-variant-ligatures: none;
  white-space: pre;
  text-rendering: geometricPrecision;
}
/* Until its drawing arrives, or when the drawing cannot be fetched: a plain outline */
.annotation.awaiting, .thumb-annot.awaiting { box-shadow: var(--marking-outline); }

[hidden] { display: none !important; }

/* On the bar layout (html.bar-layout, set by layout.ts below the full ribbon's threshold and on touch
   screens under 500 px tall, owner 13 Oct, B20 points 2 and 3, phase 6 review run commit 40) the workspace
   toolbar is a bar of five symbol buttons held at the window's foot, --size-bar tall with the home
   indicator inset under it as its own bottom padding, since the workspace has no footer (B20 point 5):
   Select, Signoff, Margin, Edit Document and Clear markings, in five equal slots, each its symbol alone (owner,
   15 Oct, navigation rework). The bar never scrolls and keeps one height. The groups' captions are hidden but
   still name their groups (phase 6 look plan assumption 12). Select opens the Select group's own controls as a
   tray, and the Edit Document slot opens the Edit group as a tray while Edit Document is on (main.ts).
   Thumbnail size, Undo, Settings, Files and Save are in the tool row under the header (below).
   frame.ts adds the bar's height to the bottom band, so the notices and the page's end keep clear of it. */
:where(html.bar-layout) .toolbar {
  position: fixed;
  left: 0; right: 0;
  bottom: 0;
  height: calc(var(--size-bar) + env(safe-area-inset-bottom));
  flex-wrap: nowrap;
  align-items: stretch;
  gap: 0;
  padding: 0 max(var(--space-2xs), env(safe-area-inset-right)) env(safe-area-inset-bottom) max(var(--space-2xs), env(safe-area-inset-left));
  border-top: var(--border-thin) solid var(--color-border);
  border-bottom: none;
}
:where(html.bar-layout) .toolbar::before { content: none; }
/* Each slot takes a fifth of the bar: the Select and Signoff groups, and the Pages group with Margin, Edit
   Document and Clear markings taking three. The end, whose controls go to the tool row under the header,
   leaves the bar, and the dividers between groups go. */
:where(html.bar-layout) .toolbar > .toolbar-group, :where(html.bar-layout) .toolbar-end {
  position: static;
  flex: 1 1 0;
  min-width: 0;
  max-width: none;
  flex-direction: row;
  align-items: stretch;
  gap: 0;
  margin: 0;
}
:where(html.bar-layout) .toolbar > .toolbar-group:has(#marginBtn) { flex-grow: 3; }
:where(html.bar-layout) .toolbar > .toolbar-group + .toolbar-group::before { content: none; }
:where(html.bar-layout) .toolbar-end { display: none; }
:where(html.bar-layout) .toolbar > .toolbar-group > .toolbar-controls:not(.bar-pad), :where(html.bar-layout) .toolbar .addblocks {
  position: static;
  flex: 1 1 0;
  min-width: 0;
  max-width: none;
  display: flex;
  flex-wrap: nowrap;
  align-items: stretch;
  gap: 0;
}
:where(html.bar-layout) .toolbar .toolbar-caption:not(#editGroup *) {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}
/* The five buttons: the symbol, --size-bar-symbol, alone, on every bar layout (owner, 15 Oct, as the short
   landscape bar had it since review run commit 44). Its label stays for screen readers (the name holds it)
   and its name shows as its tooltip on hover and on a long press. Each fills its slot less 4 px all round,
   at least 44 px tall upright, with no edge at rest, so the sunken fill under the pointer, the pressed fill
   of Edit Document and the greyed look show as a tile. */
.bar-only, .bar-label { display: none; }
:where(html.bar-layout) .bar-btn {
  display: flex;
  flex: 1 1 0;
  min-width: 0;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-2xs);
  margin: var(--space-xs) var(--space-2xs);
  padding: 0 var(--space-2xs);
  border-color: transparent;
}
:where(html.bar-layout) .bar-btn > svg { width: var(--size-bar-symbol); height: var(--size-bar-symbol); }
:where(html.bar-layout) .bar-btn > .bar-label {
  display: block;
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}
/* The workspace's tool row on the bar layout (owner, 15 Oct, view controls rework point 4): a row under the
   header, --size-phone-top-row tall, white with its hairline under it as the annotate screen's row under the
   header is, holding Thumbnail size, Undo, Settings, Files and Save (frame.ts, navigation rework, 15 Oct) in
   even slots across it, Save last. It shows with the workspace's toolbar, so only once a task card is open, and
   not on a short landscape screen, whose slim header holds the five. It is shown from the layout's class,
   before frame.ts moves the five into it, so a control moved there with focus keeps it. It is part of the
   block held at the top (.top-bars),
   so the workspace starts below it, and what keeps clear of that block (--top-bars-h: the stop for what is
   scrolled into view, the sheets, the notices) keeps clear of it too. While the annotate screen or the files
   screen covers the workspace the row keeps its room unseen, as the toolbar does (above), so the workspace
   behind keeps its scroll position, and the files screen's sheets reach up to the header as before. Its
   sides keep clear of the Dynamic Island as the header's do. */
.tool-row { display: none; }
:where(html.bar-layout:not(.bar-short)) .top-bars:has(> #toolbar:not([hidden])) > .tool-row {
  box-sizing: border-box;
  height: var(--size-phone-top-row);
  display: flex;
  align-items: stretch;
  gap: 0;
  padding: 0 max(var(--space-2xs), env(safe-area-inset-right)) 0 max(var(--space-2xs), env(safe-area-inset-left));
  background: var(--color-surface);
  border-bottom: var(--border-thin) solid var(--color-border);
}
:where(html.bar-layout) .tool-row > .toolbar-group { flex-direction: row; align-items: center; }
/* Its five controls in even slots (owner, 15 Oct, navigation rework): Thumbnail size, Undo, Settings, Files and
   Save, each filling its slot less 4 px above and below and 2 px at its sides, as the bar's are */
:where(html.bar-layout:not(.bar-short)) .tool-row > :is(.toolbar-group, .icon-btn), :where(html.bar-layout:not(.bar-short)) .tool-row > .tray-part > .icon-btn {
  flex: 1 1 0;
  min-width: 0;
  margin: var(--space-xs) var(--space-2xs);
}
:where(html.bar-layout:not(.bar-short)) .tool-row > .toolbar-group { align-items: stretch; border: var(--border-thin) solid transparent; }
:where(html.bar-layout:not(.bar-short)) .tool-row .size-view { flex: 1 1 0; display: flex; align-items: stretch; }
/* Thumbnail size reaches over its group's clear edge, so its slot is as wide as the others, whose own edges
   count in their share of the row */
:where(html.bar-layout:not(.bar-short)) .tool-row #sizeBtn { flex: 1 1 0; margin: calc(-1 * var(--border-thin)); }
/* Bars and top rows in the plain style (owner, 15 Oct, navigation rework, look.md Bars and top rows): plain
   symbols with no edge around a control. A greyed control sits on the grey tile, a control whose tray is open
   or whose tool is on on the pale steel blue tile with a steel blue symbol. One filled main button per row:
   Save on the workspace, Done on the annotate screen. The slim header of a short landscape screen takes its
   controls the same way, Files in its tray part among them (phase 7 fix run, audit finding 74). */
html.bar-layout :is(.bar-btn, .tool-row .icon-btn:not(.icon-btn-primary, .tray *), #annotUndoBtn, .annotate-nav-group .icon-btn:not(.tray *), .header-actions > .icon-btn:not(.icon-btn-primary, .icon-btn-round), .header-actions > .toolbar-group .icon-btn:not(.tray *), .header-actions > .tray-part > .icon-btn) {
  border-color: transparent;
  background: transparent;
}
html.bar-layout :is(.bar-btn, .tool-row .icon-btn:not(.icon-btn-primary, .tray *), #annotUndoBtn, .header-actions > .icon-btn:not(.icon-btn-primary, .icon-btn-round), .header-actions > .toolbar-group .icon-btn:not(.annotate-nav > .icon-btn, .tray *), .header-actions > .tray-part > .icon-btn):is(:disabled, [aria-disabled="true"], .is-unavailable) {
  border-color: transparent;
  background: var(--color-disabled-bg);
}
html.bar-layout :is(.bar-btn, .tool-row .icon-btn:not(.icon-btn-primary, .tray *), #annotUndoBtn, .annotate-nav-group .icon-btn:not(.tray *), .header-actions > .icon-btn:not(.icon-btn-primary, .icon-btn-round), .header-actions > .toolbar-group .icon-btn:not(.tray *), .header-actions > .tray-part > .icon-btn):is([aria-expanded="true"], [aria-pressed="true"], .is-on) {
  border-color: transparent;
  background: var(--color-primary-tint-strong);
  color: var(--color-primary);
}
/* The page strip's turns stay plain when greyed, their symbol in the disabled grey, as the strip has no edge */
html.bar-layout .annotate-nav > .icon-btn:is(.is-unavailable, [aria-disabled="true"]) { background: transparent; }
/* The Review control (owner, 16 Oct, main.ts): the caution triangle, greyed on the grey tile with no open flag
   as any greyed control is, and with open flags a pale red tile with the symbol in red and their count in
   white on a red badge at the symbol's top right, on the ribbon, in the tool row, on the annotate bar and in
   the slim header alike. Its slot on the annotate bar shows only on the upright bar layout, where Review is
   in it. */
.review-btn { position: relative; --review-symbol: 18px; }
:where(html.bar-layout) .review-btn.bar-btn { --review-symbol: var(--size-bar-symbol); }
.review-badge {
  position: absolute;
  left: calc(50% + var(--review-symbol) / 2 - var(--size-badge) / 2);
  top: calc(50% - var(--review-symbol) / 2 - var(--size-badge) / 2);
  box-sizing: border-box;
  min-width: var(--size-badge);
  height: var(--size-badge);
  padding: 0 var(--space-xs);
  border-radius: var(--radius-pill);
  background: var(--color-danger);
  box-shadow: 0 0 0 var(--border-pill) var(--color-caution-bg);
  color: var(--color-on-dark);
  font-size: var(--text-badge);
  line-height: var(--size-badge);
  font-weight: var(--weight-semibold);
  font-variant-numeric: var(--numeric);
  text-align: center;
  pointer-events: none;
}
.icon-btn.review-btn.has-flags, html.bar-layout :is(#reviewBtn, #annotReviewBtn).has-flags {
  background: var(--color-caution-bg);
  color: var(--color-danger);
  border-color: var(--color-caution-edge);
}
html.bar-layout :is(#reviewBtn, #annotReviewBtn).has-flags { border-color: transparent; }
.review-slot:empty { display: none; }
@media (forced-colors: active) {
  .review-badge { forced-color-adjust: none; background: CanvasText; color: Canvas; box-shadow: none; }
}
html:where(.bar-layout).files-open { --sheet-top: var(--header-h, 0px); }
@media (max-width: 640px) {
  .workspace { padding: var(--space-12); }
  /* A file band on phones keeps its one line with closer spacing, and the name may give way down to the
     disc alone, so the pages moved and removed keep as much room as they can (testing item 10). Select all
     pages is a symbol in a 44 px target, steel blue with no edge as its words are on wider screens, and its words
     are kept for screen readers only (review run open question 3). A band with both a moved and a removed
     count shows them in short words, the full words kept for screen readers only, and the page count and
     the changes take the bench cards' page count size, so the name keeps a few letters beside both counts
     at 375 px (open question 5). */
  .file-band-head { gap: var(--space-sm); padding-left: var(--space-md); }
  .file-band-title { gap: var(--space-sm); min-width: var(--size-band-disc); }
  .file-band-pages, .file-band-changes, .file-band-changes-short { font-size: var(--text-xs); line-height: var(--leading-xs); }
  .file-band-changes, .file-band-changes-short { padding-left: var(--space-sm); }
  .file-band-changes-short:not([hidden]) { display: block; }
  .file-band-head:has(> .file-band-changes-short:not([hidden])) > .file-band-changes {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
  }
  .file-band-select { position: relative; padding: 0; width: var(--size-touch); justify-content: center; }
  .file-band-select:not(.is-deselect) .file-band-symbol-select, .file-band-select.is-deselect .file-band-symbol-deselect {
    display: block; flex: 0 0 auto; width: var(--size-symbol); height: var(--size-symbol);
  }
  .file-band-select-text {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
  }
  .file-band-cards { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: var(--space-2xl) var(--space-lg); }
  .thumbs.size-small .file-band-cards { grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); }
  .thumbs.size-large .file-band-cards { grid-template-columns: minmax(0, 1fr); }
}
/* The annotate screen on the bar layout (phase 6 look plan section 7, B20 point 3, phase 6 review run commit
   42, navigation rework 15 Oct): a row --size-phone-top-row tall under the header with the View group (the page
   strip and Zoom) at its left and Undo and Done at its right, then the page area, then the tool row as a bar
   of four symbol buttons held at the window's foot, --size-bar tall over the home indicator inset, as the
   workspace's is: Mark, Margin, Copy and Clear this page in four equal slots, each its symbol alone, in the
   look of the workspace's (.bar-btn). The bar never scrolls and keeps one height. Mark opens the Mark group's
   three tools as a tray above the bar (main.ts). While a marking is selected its controls take the whole bar
   (the B20 plan's question 4 (a), review run commit 43): Deselect, Move, Size, Cells and Delete in even
   slots, and Deselect or Escape brings Mark, Margin, Copy and Clear this page back.
   Both rows keep one height whatever is selected, so the page never moves for a selection (8 Oct) and a
   marking near the top is never covered. The View group and the end with Undo and Done reach the top row by
   position fixed, so
   the markup, the ids and the Tab order stay as they are. The bar joins the bottom band while the screen shows
   (--tools-band-h), so the screen ends at its top and the notices and menus keep clear of it. Captions are
   hidden but still name their groups (assumption 12). */
html:where(.bar-layout).annotate-open { --tools-band-h: calc(var(--size-bar) + env(safe-area-inset-bottom)); }
:where(html.bar-layout) .annotate-screen::before {
  content: '';
  box-sizing: border-box;
  flex: 0 0 var(--size-phone-top-row);
  border-bottom: var(--border-thin) solid var(--color-border);
  background: var(--color-surface);
}
:where(html.bar-layout) .annotate-toolbar {
  position: fixed;
  left: 0; right: 0;
  bottom: 0;
  height: calc(var(--size-bar) + env(safe-area-inset-bottom));
  flex-wrap: nowrap;
  align-items: stretch;
  gap: 0;
  padding: 0 max(var(--space-2xs), env(safe-area-inset-right)) env(safe-area-inset-bottom) max(var(--space-2xs), env(safe-area-inset-left));
  border-top: var(--border-thin) solid var(--color-border);
  border-bottom: none;
}
:where(html.bar-layout) .annotate-toolbar::before { content: none; }
/* On the bar layout the toolbar stands just before the screen in the page (main.ts), so it shows only while
   the screen does, over the screen and under the notices, and above the notices while one of its trays or
   menus shows (owner, 16 Oct, look check, item 9: every tray draws over every notice), the screen raised for
   one of its menus raising it too. The bar keeps clear of the stack, which ends above it, so only the open
   tray or menu reaches over a notice. */
:where(html.bar-layout) .annotate-toolbar { z-index: 51; }
:where(html.bar-layout:not(.annotate-open)) .annotate-toolbar { display: none; }
:where(html.bar-layout) .annotate-toolbar:is(:has(.tray:not([hidden]), .menu:not([hidden]), .popover:not([hidden])), :has(+ .annotate-screen.raised)) { z-index: 101; }
/* Each slot takes a quarter of the bar (owner, 15 Oct, navigation rework): the Mark group, and the Page group
   with Margin, Copy and Clear this page taking three. The View group, Undo and Done are in the row under the
   header, and the dividers between groups go. */
:where(html.bar-layout) .annotate-toolbar > .toolbar-group:not(.annotate-nav-group) {
  position: static;
  flex: 1 1 0;
  min-width: 0;
  max-width: none;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: stretch;
  gap: 0;
  margin: 0;
}
:where(html.bar-layout) .annotate-toolbar > .toolbar-group:has(#annotMarginBtn) { flex-grow: 3; }
:where(html.bar-layout) .annotate-toolbar > .toolbar-group + .toolbar-group::before { content: none; }
:where(html.bar-layout) .annotate-toolbar > .toolbar-group:not(.annotate-nav-group, .annotate-selected-group) > .toolbar-controls:not(.bar-pad) {
  position: static;
  flex: 1 1 0;
  min-width: 0;
  max-width: none;
  display: flex;
  flex-wrap: nowrap;
  align-items: stretch;
  gap: 0;
}
:where(html.bar-layout) .annotate-toolbar .toolbar-caption {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}
/* Mark while a tool is on: the tool's symbol (main.ts) on the pressed fill, as a toggle that is on */
/* While a marking is selected its controls show in place of Mark, Margin, Copy and Clear this page */
:where(html.bar-layout) .annotate-toolbar:has(> .annotate-selected-group:not([hidden])) > .toolbar-group:not(.annotate-selected-group, .annotate-nav-group) { display: none; }
/* The Marking controls take the whole bar in the plain style (owner, 15 Oct, navigation rework): Deselect, Move,
   Size, Cells and Delete, each a symbol button as the bar's others are, in equal slots, a part the marking lacks
   left out (Size for a block and a picked split line, Cells for an N/A box), with no dividers and no tint.
   Cells opens Split, Not required and Clear N/R as a tray above the bar (main.ts), and shows on the pale steel
   blue tile while Split or Not required is on, as Mark does for a tool. Undo is in the row under the header,
   so the bar never scrolls and Delete and Clear N/R are always in view. */
:where(html.bar-layout) .annotate-toolbar > .toolbar-group.annotate-selected-group {
  flex-grow: 1;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
}
:where(html.bar-layout) .annotate-selected-group > .toolbar-controls, :where(html.bar-layout) .annotate-toolbar .marking-part {
  flex: 1 1 0;
  min-width: 0;
  max-width: none;
  display: flex;
  flex-wrap: nowrap;
  align-items: stretch;
  gap: 0;
  padding: 0;
}
:where(html.bar-layout) .marking-part + .marking-part::before { content: none; }
/* The row under the header (owner, 15 Oct, navigation rework): the View group at its left, the page strip with
   no edge, then Zoom, and Undo and Done at its right. The four are one row (frame.ts moves the View group and
   the end into #annotTopRow), which gives way in a set order when a long task card's strip leaves it short of
   room (phase 7 fix run, audit finding 17, owner's answer 9 (a)): the room between Zoom and Undo goes first,
   then Undo narrows from its 64 px tile to a control's 44 px, then the gaps close, so nothing overlaps at
   375 px with 1,000 pages or on a walk-through over hundreds of flags. Undo, the gap before Done and Done are
   items of the row itself (the end is no box there), Undo giving way a thousand times as readily as the gap
   before Done, an empty box, and the View group (--shrink-first). The View group gives way down to the strip
   and Zoom with no gap between them: its gap is a grid track of at most 4 px, which the group's narrowest size
   leaves out. */
.annotate-top-row { display: none; }
:where(html.bar-layout:not(.bar-short)) .annotate-top-row {
  position: fixed;
  top: var(--header-h, 0px);
  left: max(var(--space-gutter-phone), env(safe-area-inset-left));
  right: max(var(--space-gutter-phone), env(safe-area-inset-right));
  height: var(--size-phone-top-row);
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
}
:where(html.bar-layout) .annotate-top-row > .annotate-nav-group {
  flex: 0 1 auto;
  min-width: auto;
  flex-direction: row;
  align-items: center;
}
:where(html.bar-layout) .annotate-top-row .annotate-view {
  display: grid;
  grid-template-columns: auto minmax(0, var(--space-xs)) auto;
  align-items: center;
  gap: 0;
}
:where(html.bar-layout) .annotate-top-row .annotate-view > .annotate-nav { grid-area: 1 / 1; }
:where(html.bar-layout) .annotate-top-row .annotate-view > #annotZoomBtn { grid-area: 1 / 3; }
:where(html.bar-layout:not(.bar-short)) .annotate-top-row > .annotate-end { display: contents; }
:where(html.bar-layout) .annotate-top-row > .annotate-end::before {
  content: '';
  order: 2;
  flex: 0 1 calc(var(--space-sm) + var(--space-2xs));
  min-width: 0;
}
:where(html.bar-layout) .annotate-end > #annotUndoBtn { order: 1; flex: 0 var(--shrink-first) var(--size-row-tile); min-width: var(--size-touch); margin-left: auto; margin-right: 0; }
:where(html.bar-layout) .annotate-end > #modalDone { order: 3; flex: none; margin: 0; }
/* Under 360 px, the stress width, Done takes closer room */
@media (max-width: 359.98px) {
  :where(html.bar-layout) .annotate-end > #modalDone { padding-left: var(--space-md); padding-right: var(--space-md); }
}
:where(html.bar-layout) .annotate-nav { border-color: transparent; }
:where(html.bar-short) .annotate-end { display: none; }
/* Undo in the slim header keeps a control's size there, as its neighbours do */
:where(html.bar-short) .header-actions > :is(#annotUndoBtn, #annotReviewBtn) { flex: 0 0 auto; min-width: var(--size-touch); margin: 0; }
/* The bar's short landscape variant (html.bar-short, layout.ts: the bar layout on a touch screen under 500 px
   tall and wider than tall, a phone held sideways, owner 13 Oct, B20 point 3, phase 6 review run commit 44).
   Both bars are --size-bar-short tall over the home indicator inset, every rule that keeps clear of a bar
   following through --size-bar, and each button shows its symbol alone as on the upright bar. Every
   control in the bars and the header is --size-touch-short tall. The header is one slim row,
   --size-header-short tall, with the wings mark (index.html) and the tool's name cut with an ellipsis where
   the row is short of room, and its sides keep clear of the Dynamic Island by the side insets, whichever
   way the phone is turned. On the annotate screen the View group and Done join that row between the tool's
   name and Help (frame.ts), so the row under the header goes and the page area takes its room. */
html.bar-short { --size-bar: var(--size-bar-short); }
:where(html.bar-short) .bar-btn {
  min-height: var(--size-touch-short);
  margin: calc((var(--size-bar-short) - var(--border-thin) - var(--size-touch-short)) / 2) var(--space-2xs);
}
/* On the Marking controls' panel, under its 2 px top edge, the buttons start at the edge, so they keep clear
   of the home indicator inset as the others do */
:where(html.bar-short) .header {
  --size-touch: var(--size-touch-short);
  min-height: var(--size-header-short);
  padding-left: max(var(--space-gutter-phone), env(safe-area-inset-left));
  padding-right: max(var(--space-gutter-phone), env(safe-area-inset-right));
  gap: var(--space-md);
}
:where(html.bar-short) .header-brand { gap: var(--space-md); }
:where(html.bar-short) .header-logo img { height: var(--size-logo-h-phone); }
:where(html.bar-short) .header-title { padding-left: var(--space-md); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
:where(html.bar-short) .header > .annotate-nav-group { flex: 0 0 auto; flex-direction: row; align-items: center; }
/* A group's caption in the header or the tool row, the annotate View group's here and the workspace's on any
   bar layout, is kept for screen readers only */
:where(html.bar-layout) :is(.header, .tool-row) .toolbar-caption {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}
/* They show there only while the annotate screen does */
html:not(.annotate-open) .header > .annotate-nav-group, html:not(.annotate-open) .header-actions > :is(#modalDone, #annotUndoBtn, #annotReviewBtn) { display: none; }
:where(html.bar-short) .annotate-screen::before { content: none; }
html:where(.bar-short).annotate-open { --sheet-top: var(--header-h, 0px); }
/* The workspace keeps its bands, cards and their controls clear of the Dynamic Island too */
:where(html.bar-short) .workspace {
  padding-left: max(var(--space-15), env(safe-area-inset-left));
  padding-right: max(var(--space-15), env(safe-area-inset-right));
}
@media (max-width: 640px) {
  :where(html.bar-short) .workspace {
    padding-left: max(var(--space-12), env(safe-area-inset-left));
    padding-right: max(var(--space-12), env(safe-area-inset-right));
  }
}
@media (max-width: 640px) {
  /* The same line closer to the sides, the band --size-footer-phone tall */
  html { --footer-h: calc(var(--size-footer-phone) + env(safe-area-inset-bottom)); }
  .app-footer {
    padding-left: max(var(--space-gutter-phone), env(safe-area-inset-left));
    padding-right: max(var(--space-gutter-phone), env(safe-area-inset-right));
  }
  .app-footer > p { min-height: calc(var(--size-footer-phone) - var(--border-medium)); }
}
/* The shared dialog (src/dialog.ts): the band's hue over everything, the dialog a white panel with the
   dialog shadow, 24 px inside and at most --size-dialog wide, its title 20/28 bold ink and its words
   14/20. The shade fades in over 200 ms while the dialog grows from 0.96 to its size and fades in. When it
   closes, dialog.ts leaves a copy of it that fades out over 150 ms, hidden from everything and taking no
   presses (.dialog-leaving). With reduced motion it only fades. The dialog keeps clear of the window's
   safe-area insets (the Dynamic Island and the home indicator) where they are wider than its margin. */
.save-modal-overlay {
  position: fixed;
  inset: 0;
  background: var(--color-scrim);
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: max(var(--space-lg), env(safe-area-inset-top)) max(var(--space-lg), env(safe-area-inset-right)) max(var(--space-lg), env(safe-area-inset-bottom)) max(var(--space-lg), env(safe-area-inset-left));
  animation: dialog-shade-in var(--dur-reflow) var(--ease-enter);
}
.save-modal {
  background: var(--color-surface);
  border-radius: var(--radius-panel);
  box-shadow: var(--shadow-dialog);
  width: 100%;
  max-width: var(--size-dialog);
  padding: var(--space-2xl);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  color: var(--color-text);
  animation: dialog-in var(--dur-reflow) var(--ease-enter);
}
@keyframes dialog-shade-in { from { opacity: 0; } }
@keyframes dialog-in { from { opacity: 0; transform: scale(var(--scale-dialog)); } }
@keyframes dialog-fade-in { from { opacity: 0; } }
/* The copy of a dialog that has closed, fading out where the dialog was */
.dialog-leaving {
  position: fixed;
  inset: 0;
  z-index: 100;
  pointer-events: none;
  animation: dialog-out var(--dur-quick) var(--ease-exit) forwards;
}
@keyframes dialog-out { to { opacity: 0; } }
.save-modal-header {
  font-size: var(--text-lg);
  line-height: var(--leading-lg);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-snug);
  color: var(--color-text);
  margin-bottom: var(--space-md);
}
/* A field's label above it, in sentence case as written */
.save-modal-label {
  display: block;
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-text);
  margin-bottom: var(--space-sm);
}
/* A text field: white, the touch size tall, its edge in the field grey (3.50:1 on white), since the edge
   is its only cue. Keyboard focus draws the shared ring. A field holding what the dialog refuses takes
   the caution red edge, with the reason under it. On phones the text is 16 px, so Safari does not zoom
   in when the field takes focus. */
.save-modal-input {
  width: 100%;
  box-sizing: border-box;
  min-height: var(--size-touch);
  font-family: inherit;
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  font-variant-numeric: var(--numeric);
  padding: 0 var(--space-md);
  border: var(--border-thin) solid var(--color-field-border);
  border-radius: var(--radius-control);
  background: var(--color-surface);
  color: var(--color-text);
  outline: none;
}
.save-modal-input[aria-invalid="true"] { border-color: var(--color-danger); }
@media (max-width: 640px) {
  .save-modal-input { font-size: var(--text-md); }
}
/* A hint under a field, on the dialog's white. Faint is for disabled only, so the hint takes the brand
   grey, which holds 4.5:1 on white. */
.save-modal-hint {
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
  color: var(--color-text-secondary);
  margin-top: var(--space-sm);
}
/* The reason a field is refused, or a save could not be written: small caution red words under the field
   (6.57:1 on white), taking no room while empty */
.save-modal-error { color: var(--color-danger); font-size: var(--text-xs); line-height: var(--leading-xs); margin: var(--space-sm) 0 0; }
.save-modal-error:empty { margin: 0; }
/* The buttons at the dialog's foot, at its right: Cancel in words with no edge, then the main action */
.save-modal-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--space-sm);
  margin-top: var(--space-2xl);
}
/* Sheets on phones (phase 6 look plan section 7). Every dialog but Help and the legal panel (unlock, Save PDF, Block settings,
   Move to position, the choices, the session dialog and the side panel after a save), and the copy panel
   wherever it opens as a sheet (the bar layout, below), is a sheet from the bottom across the window's width: the panel radius on its top corners, the phone
   gutter at its sides, a grab line at its top drawn for looks only (nothing drags it), never taller than
   the window less a strip of shade at the top, and scrolling inside. Its title row stays at its top and its
   row of buttons at its foot while the rest scrolls between them, the buttons clear of the home indicator.
   It comes up from below over 250 ms, and with reduced motion only fades in. It leaves as every dialog
   does (.dialog-leaving). Help and the legal panel are sheets over the whole screen (below). Menus and popovers opened
   from a button are sheets too on the bar layout (popover.ts gives them is-sheet, above). */
@media (max-width: 640px) {
  .save-modal-overlay:not(.help-dialog, .legal-dialog, .sidebar-dialog) { align-items: flex-end; padding: 0; }
  :is(.save-modal-overlay:not(.help-dialog, .legal-dialog, .sidebar-dialog) > .save-modal) {
    --sheet-pad-l: max(var(--space-gutter-phone), env(safe-area-inset-left));
    --sheet-pad-r: max(var(--space-gutter-phone), env(safe-area-inset-right));
    max-width: none;
    max-height: var(--sheet-max-h, calc(100% - max(var(--space-2xl), env(safe-area-inset-top))));
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    padding: 0 var(--sheet-pad-r) 0 var(--sheet-pad-l);
    border: 0;
    border-radius: var(--radius-panel) var(--radius-panel) 0 0;
    box-shadow: var(--shadow-dialog);
    animation: sheet-in var(--dur-sheet) var(--ease-enter);
  }
  :is(.save-modal-overlay:not(.help-dialog, .legal-dialog, .sidebar-dialog) > .save-modal)::before {
    content: '';
    display: block;
    flex: 0 0 auto;
    width: var(--size-grab-w);
    height: var(--size-grab-h);
    margin: var(--space-sm) auto;
    border-radius: var(--radius-pill);
    background: var(--color-border-strong);
  }
  :is(.save-modal-overlay:not(.help-dialog, .legal-dialog, .sidebar-dialog) > .save-modal) > :is(.save-modal-header, .saved-panel-top, .copy-panel-title) {
    position: sticky;
    top: 0;
    z-index: 1;
    margin: 0 calc(-1 * var(--sheet-pad-r)) var(--space-sm) calc(-1 * var(--sheet-pad-l));
    padding: var(--space-sm) var(--sheet-pad-r) var(--space-sm) var(--sheet-pad-l);
    background: var(--color-surface);
  }
  :is(.save-modal-overlay:not(.help-dialog, .legal-dialog, .sidebar-dialog) > .save-modal) > :is(.save-modal-actions, .copy-panel-actions) {
    position: sticky;
    bottom: 0;
    z-index: 1;
    margin: var(--space-sm) calc(-1 * var(--sheet-pad-r)) 0 calc(-1 * var(--sheet-pad-l));
    padding: var(--space-lg) var(--sheet-pad-r) max(var(--space-2xl), env(safe-area-inset-bottom)) var(--sheet-pad-l);
    background: var(--color-surface);
  }
  /* A sheet with no row of buttons, as the session dialog after a failure, keeps the same room at its foot */
  .save-modal-overlay:not(.help-dialog, .legal-dialog, .sidebar-dialog) > .save-modal:not(:has(> .save-modal-actions)) { padding-bottom: max(var(--space-2xl), env(safe-area-inset-bottom)); }
}
@media (max-width: 640px) and (prefers-reduced-motion: reduce) {
  :is(.save-modal-overlay:not(.help-dialog, .legal-dialog, .sidebar-dialog) > .save-modal) { animation-name: dialog-fade-in; }
}
/* The copy panel opens from the bar at the foot of the screen on the bar layout, which takes in windows
   wider than a phone (layout.ts), so there it is the same sheet as the dialogs on phones, at every width */
:where(html.bar-layout) .copy-panel.is-sheet {
  --sheet-pad-l: max(var(--space-gutter-phone), env(safe-area-inset-left));
  --sheet-pad-r: max(var(--space-gutter-phone), env(safe-area-inset-right));
  max-width: none;
  max-height: var(--sheet-max-h, calc(100% - max(var(--space-2xl), env(safe-area-inset-top))));
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 0 var(--sheet-pad-r) 0 var(--sheet-pad-l);
  border: 0;
  border-radius: var(--radius-panel) var(--radius-panel) 0 0;
  box-shadow: var(--shadow-dialog);
  animation: sheet-in var(--dur-sheet) var(--ease-enter);
}
:where(html.bar-layout) .copy-panel.is-sheet::before {
  content: '';
  display: block;
  flex: 0 0 auto;
  width: var(--size-grab-w);
  height: var(--size-grab-h);
  margin: var(--space-sm) auto;
  border-radius: var(--radius-pill);
  background: var(--color-border-strong);
}
:where(html.bar-layout) .copy-panel.is-sheet > .copy-panel-title {
  position: sticky;
  top: 0;
  z-index: 1;
  margin: 0 calc(-1 * var(--sheet-pad-r)) var(--space-sm) calc(-1 * var(--sheet-pad-l));
  padding: var(--space-sm) var(--sheet-pad-r) var(--space-sm) var(--sheet-pad-l);
  background: var(--color-surface);
}
:where(html.bar-layout) .copy-panel.is-sheet > .copy-panel-actions {
  position: sticky;
  bottom: 0;
  z-index: 1;
  margin: var(--space-sm) calc(-1 * var(--sheet-pad-r)) 0 calc(-1 * var(--sheet-pad-l));
  padding: var(--space-lg) var(--sheet-pad-r) max(var(--space-2xl), env(safe-area-inset-bottom)) var(--sheet-pad-l);
  background: var(--color-surface);
}
@media (prefers-reduced-motion: reduce) {
  :where(html.bar-layout) .copy-panel.is-sheet { animation-name: dialog-fade-in; }
}
@keyframes sheet-in { from { transform: translateY(100%); } }

/* A caution (deck Screens 5, 7 and 8, mockups 15, 20 and 22), one look for the unlock dialog, the copy
   panel, the Save PDF dialog and the Review filter's bar: the pale red with a 4 px red edge at the start,
   rounded at its other corners, the red caution symbol before the line with a white sign in it, ink words
   (15:1 on the pale red) and, where there is one, the action at the right. */
.caution {
  display: flex;
  align-items: flex-start;
  gap: var(--space-md);
  padding: var(--space-md) var(--space-lg);
  background: var(--color-caution-bg);
  border-left: var(--border-edge) solid var(--color-danger);
  border-radius: 0 var(--radius-card) var(--radius-card) 0;
  color: var(--color-text);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
}
.caution > .caution-symbol { flex: 0 0 auto; width: var(--size-symbol); height: var(--size-symbol); color: var(--color-danger); overflow: visible; }
.caution > .caution-symbol .caution-shape { fill: currentColor; }
.caution > .caution-symbol .caution-sign { stroke: var(--color-on-dark); }
.caution-text { flex: 1 1 auto; min-width: 0; }
/* With an action (Review, Show all pages), the box is a little tighter around the button, which sits at
   the right and wraps under the line when the box is too narrow for both */
.caution.has-action { flex-wrap: wrap; align-items: center; padding: var(--space-sm) var(--space-sm) var(--space-sm) var(--space-lg); }
/* Review's banner stays on one line, its button 4 px from the box's edge */
.caution.review-bar { flex-wrap: nowrap; align-items: center; padding: var(--space-xs) var(--space-xs) var(--space-xs) var(--space-lg); }
.caution.has-action .caution-text { flex: 1 1 12em; }
.caution-action { margin-left: auto; }
@media (forced-colors: active) {
  .caution > .caution-symbol .caution-shape { fill: none; stroke: CanvasText; }
  .caution > .caution-symbol .caution-sign { stroke: CanvasText; }
}

/* The unlock dialog of Edit Document (edit-document plan commit 3, mockup 15): the lead line, the four
   points with steel blue bullets, then the caution. On phones the dialog is a full-width sheet from the
   bottom, scrolling inside when the window is short (A2). */
.unlock-points { margin: var(--space-md) 0 0; padding-left: var(--space-xl); }
.unlock-points li + li { margin-top: var(--space-xs); }
.unlock-points li::marker { color: var(--color-primary); }
.save-modal .caution { margin-top: var(--space-lg); }

/* The Save PDF dialog (deck Screen 8, mockups 22 and 23). Its cautions sit between the summary and the
   file name field, 8 px apart, with the same room below as above. With no caution the field keeps that
   room under the tiles. */
.save-modal .caution + .caution { margin-top: var(--space-sm); }
.save-modal .caution + .save-modal-label, .save-modal .save-tiles + .save-modal-label { margin-top: var(--space-lg); }
/* The summary of changes' choice (phase 5 C-4.3): the tick box, then its two choices under its words, each
   the touch size tall, greyed while turned off. The file name field keeps the same room under it. */
.save-changes { margin-top: var(--space-md); }
.save-changes-option { display: flex; align-items: center; gap: var(--space-sm); min-height: var(--size-touch); color: var(--color-text); cursor: pointer; }
.save-changes-option input { flex: 0 0 auto; margin: 0; cursor: pointer; }
.save-changes-check { font-weight: var(--weight-semibold); }
.save-changes-choices { border: none; margin: 0; padding: 0 0 0 calc(var(--size-check) + var(--space-sm)); min-width: 0; }
.save-changes-option:has(input:disabled) { color: var(--color-disabled-fg); cursor: default; }
.save-changes-option input:disabled { cursor: default; }
/* Why At the end of the saved PDF is turned off (phase 5 C-4.4), under its words, in the brand grey on white */
.save-changes-reason { margin: 0 0 0 calc(var(--size-check) + var(--space-sm)); font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--color-text-secondary); }
.save-modal .save-changes + .save-modal-label { margin-top: var(--space-lg); }
/* The file name field with .pdf at its right inside the same edge, as the name is saved with it. The
   words after the name are drawn, not read, since the field's label and hint say what it holds. */
.save-name-field {
  display: flex;
  align-items: center;
  min-height: var(--size-touch);
  border: var(--border-thin) solid var(--color-field-border);
  border-radius: var(--radius-control);
  background: var(--color-surface);
}
.save-name-field .save-modal-input { flex: 1 1 auto; min-width: 0; border: none; background: transparent; }
.save-name-field .save-modal-input:focus-visible { outline: none; }
.save-name-field:has(.save-modal-input:focus-visible) { outline: var(--border-medium) solid var(--color-focus); outline-offset: var(--space-2xs); }
.save-name-field:has(.save-modal-input[aria-invalid="true"]) { border-color: var(--color-danger); }
.save-name-suffix { flex: 0 0 auto; padding-right: var(--space-md); color: var(--color-text-secondary); pointer-events: none; white-space: nowrap; }
@media (max-width: 640px) {
  .save-name-suffix { font-size: var(--text-md); }
}

/* The Save PDF dialog is never taller than the window and scrolls inside, with Cancel and Save held at its
   foot, so they stay in reach however long the summary runs. On phones it is a full-width sheet from the
   bottom, its buttons clear of the home indicator. */
.save-dialog .save-modal { max-height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch; padding-bottom: 0; }
.save-dialog .save-modal-actions {
  position: sticky;
  bottom: 0;
  margin-top: var(--space-sm);
  padding: var(--space-lg) 0 var(--space-2xl);
  background: var(--color-surface);
}

/* The side panel after a save (phase 5 C-3.4, deck Screen 8, mockup 24): a white panel from the right as
   tall as the window, over the dimmed page, scrolling inside when the window is short. The heading with
   its steel blue tick disc and the close symbol at its right, then the file rows, each a white card with
   the red PDF file symbol, then Start a new task card and Back to the task card one above the other at the
   panel's foot, full width. On phones it is a full-width sheet from the bottom, its buttons clear of the
   home indicator. It slides in, and with reduced motion only fades in. Beside a right inset (an iPhone held
   sideways) its padding takes the inset and the close symbol's reach past it, so the symbol and the
   buttons keep clear of the inset. */
.saved-panel { justify-content: flex-end; align-items: stretch; padding: 0; }
.saved-panel .save-modal {
  display: flex;
  flex-direction: column;
  max-width: var(--size-side-panel);
  max-height: 100%;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  border-radius: 0;
  padding-top: max(var(--space-2xl), env(safe-area-inset-top));
  padding-right: max(var(--space-2xl), calc(env(safe-area-inset-right) + var(--space-md)));
  padding-bottom: max(var(--space-2xl), env(safe-area-inset-bottom));
  animation: saved-panel-in var(--dur-reflow) var(--ease-enter);
}
@keyframes saved-panel-in { from { transform: translateX(100%); } }
.saved-panel-top { display: flex; align-items: center; gap: var(--space-sm); margin-bottom: var(--space-lg); }
.saved-panel .save-modal-header { display: flex; align-items: center; gap: var(--space-md); flex: 1 1 auto; min-width: 0; margin: 0; }
.saved-panel .save-modal-header:focus { outline: none; }
/* The tick disc: a steel blue disc with a white tick (7.61:1) */
.saved-panel-tick { flex: 0 0 auto; width: var(--size-saved-tick); height: var(--size-saved-tick); color: var(--color-saved); }
.saved-panel-tick path:first-child { fill: currentColor; }
.saved-panel-tick path:last-child { stroke: var(--color-on-dark); stroke-width: 2.5; }
@media (forced-colors: active) {
  .saved-panel-tick path:first-child { fill: none; stroke: CanvasText; }
  .saved-panel-tick path:last-child { stroke: CanvasText; }
}
.saved-panel-close { flex: 0 0 auto; margin: calc(-1 * var(--space-sm)) calc(-1 * var(--space-md)) calc(-1 * var(--space-sm)) 0; }
.saved-files { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-sm); }
.saved-file {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-md) var(--space-lg);
  background: var(--color-surface);
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius-card);
}
/* The PDF file symbol: a page in the brand grey with a red band across its foot */
.saved-file-symbol { flex: 0 0 auto; width: var(--space-2xl); height: var(--space-2xl); color: var(--color-text-secondary); }
.saved-file-symbol path:nth-child(3) { fill: var(--color-danger); stroke: var(--color-danger); }
.saved-file-name { min-width: 0; font-weight: var(--weight-semibold); overflow-wrap: anywhere; color: var(--color-text); }
.saved-panel-where { margin: var(--space-md) 0 0; font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--color-text-secondary); }
/* The share still to happen (owner, 17 Oct): save.share.sub under the heading, and a failed share's line under
   the rows */
.saved-panel-ready { margin: calc(-1 * var(--space-sm)) 0 var(--space-lg); color: var(--color-text-secondary); }
.saved-panel-error { margin: var(--space-md) 0 0; }
/* The summary of changes' row (phase 5 C-4.3): its name, Summary of changes under it and a line when its
   write fails, with its own Save at the row's right. Once the file is written Save reads Saved, in the
   success green (5.41:1 on white) with a tick before it, and does nothing more. */
.saved-file-text { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; }
.saved-file-sub { font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--color-text-secondary); }
.saved-file-error { margin-top: var(--space-xs); font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--color-danger); }
.saved-file-error:empty { display: none; }
.saved-file-save { flex: 0 0 auto; align-self: center; }
.saved-file-save[aria-disabled="true"] { background: var(--color-surface); border-color: var(--color-success); color: var(--color-success); cursor: default; }
.saved-file-save[aria-disabled="true"]::before {
  content: '';
  flex: 0 0 auto;
  width: var(--size-check);
  height: var(--size-check);
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / contain no-repeat;
}
@media (forced-colors: active) {
  .saved-file-save[aria-disabled="true"]::before { forced-color-adjust: none; background: CanvasText; }
}
.saved-panel .save-modal-actions { flex-direction: column; flex-wrap: nowrap; justify-content: flex-start; margin-top: auto; padding-top: var(--space-2xl); }
.saved-panel .save-modal-actions .btn { width: 100%; justify-content: center; }
@media (prefers-reduced-motion: reduce) {
  .saved-panel .save-modal { animation-name: dialog-fade-in; }
}

/* The summary (deck Screen 8): the pages line, the page map in its band, then the tiles. A mark is
   page-shaped, filled steel blue with signoff, hollow with a grey edge without, red where it overlaps. A
   signoff margin shows as a dashed strip over the mark's right side, a moved page as a copper dot above
   it. The map's rows leave room for the dot. A mark shows its tooltip on hover or a long-press and opens
   its page when pressed. The tiles share the row, as many as there are, white cards that carry the
   numbers and are the map's legend, each with its mark as a swatch before its number. */
.save-summary-pages { margin-top: var(--space-lg); font-weight: var(--weight-semibold); }
.save-map {
  --map-w: var(--size-map-mark-w);
  --map-h: var(--size-map-mark-h);
  --map-gap: var(--size-map-gap);
  --map-dot: var(--size-map-dot);
  --map-edge: var(--border-map);
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--map-dot) + var(--map-gap)) var(--map-gap);
  margin-top: var(--space-sm);
  padding: var(--space-md);
  background: var(--color-map-band);
  border-radius: var(--radius-card);
}
.save-map[data-size="medium"] {
  --map-w: var(--size-map-mark-w-medium);
  --map-h: var(--size-map-mark-h-medium);
  --map-gap: var(--size-map-gap-medium);
  --map-dot: var(--size-map-dot-medium);
  --map-edge: var(--border-thin);
}
.save-map[data-size="small"] {
  --map-w: var(--size-map-mark-w-small);
  --map-h: var(--size-map-mark-h-small);
  --map-gap: var(--size-map-gap-small);
  --map-dot: var(--size-map-dot-small);
  --map-edge: var(--border-thin);
}
.save-map-mark {
  position: relative;
  flex: 0 0 auto;
  width: var(--map-w);
  height: var(--map-h);
  border: var(--map-edge) solid var(--color-map-empty);
  border-radius: var(--radius-xs);
  cursor: pointer;
}
.save-map-mark.is-signoff { background: var(--color-map-signoff); border-color: var(--color-map-signoff); }
.save-map-mark.is-flagged { background: var(--color-map-overlap); border-color: var(--color-map-overlap); }
.save-map-mark.has-margin::before {
  content: '';
  position: absolute;
  top: calc(-1 * var(--map-edge));
  bottom: calc(-1 * var(--map-edge));
  right: calc(-1 * var(--map-edge));
  width: 40%;
  background: var(--color-map-band);
  border: var(--map-edge) dashed var(--color-map-margin);
  border-radius: 0 var(--radius-xs) var(--radius-xs) 0;
}
.save-map-mark.is-moved::after {
  content: '';
  position: absolute;
  left: 50%;
  top: calc(-1 * var(--map-dot) - var(--border-medium));
  width: var(--map-dot);
  height: var(--map-dot);
  transform: translateX(-50%);
  border-radius: var(--radius-round);
  background: var(--color-map-moved);
}
.save-map-mark:hover { outline: var(--border-medium) solid var(--color-text); outline-offset: var(--border-thin); }
.save-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--size-map-tile), 1fr));
  gap: var(--space-sm);
  margin-top: var(--space-sm);
  list-style: none;
}
.save-tile {
  padding: var(--space-sm) var(--space-md);
  background: var(--color-surface);
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius-card);
}
.save-tile-value { display: block; font-size: var(--text-md); line-height: var(--leading-md); font-weight: var(--weight-semibold); white-space: nowrap; }
.save-tile-label { display: block; font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--color-text-secondary); }
.save-swatch {
  display: inline-block;
  width: var(--size-map-swatch-w);
  height: var(--size-map-swatch-h);
  margin-right: var(--space-sm);
  vertical-align: calc(-1 * var(--space-2xs));
  border-radius: var(--radius-xs);
}
.save-swatch.is-signoff { background: var(--color-map-signoff); }
.save-swatch.has-margin { border: var(--border-map) dashed var(--color-map-margin); }
.save-swatch.is-moved { width: var(--size-map-dot); height: var(--size-map-dot); vertical-align: var(--space-2xs); border-radius: var(--radius-round); background: var(--color-map-moved); }

/* Block settings (E7). The panel's preview shows the chosen block at two CSS px per pt in a sunken band,
   never wider than the panel: the server's drawing once there is one, a plain outline until then. */
.settings-preview-block { position: relative; display: block; max-width: 100%; height: auto; background: var(--color-surface); }
.settings-preview-block:not(.has-drawing) { box-shadow: var(--marking-outline); }
.settings-preview {
  display: flex;
  justify-content: center;
  margin-top: var(--space-lg);
  padding: var(--space-lg);
  background: var(--color-surface-2);
  border-radius: var(--radius-card);
}
/* The panel: never taller than the window, scrolling inside. Fields side by side in pairs, Standard and
   Tall as one segmented control directly under the stamp area field, which they set (owner, 16 Oct): as wide
   as the field, as tall as it and with its corners, each button exactly half (the line between them is the
   pair's own colour showing through a 1 px gap), its words on two lines where one
   does not fit, breaking before the size in brackets, the pressed one steel blue. Under 375 px the two fields stack, the pair still under
   the stamp area field at its full width. The label set menu as wide as the panel, the line weights in a row,
   Restore defaults at the start of the buttons. */
.settings-dialog .save-modal { max-height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.settings-intro { color: var(--color-text-secondary); }
.settings-sizes { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-md); margin-top: var(--space-lg); }
.settings-field { min-width: 0; }
.settings-presets {
  display: flex;
  box-sizing: border-box;
  width: 100%;
  min-height: var(--size-touch);
  gap: var(--border-thin);
  margin-top: var(--space-sm);
  border: var(--border-thin) solid var(--color-border-strong);
  border-radius: var(--radius-control);
  background: var(--color-border-strong);
}
.settings-presets .btn {
  flex: 1 1 0;
  min-width: 0;
  min-height: 0;
  justify-content: center;
  padding: 0 var(--space-xs);
  border: 0;
  border-radius: 0;
  line-height: var(--leading-xs);
  white-space: normal;
  text-align: center;
}
.settings-preset-size { white-space: nowrap; }
.settings-presets .btn:first-child { border-radius: calc(var(--radius-control) - var(--border-thin)) 0 0 calc(var(--radius-control) - var(--border-thin)); }
.settings-presets .btn:last-child { border-radius: 0 calc(var(--radius-control) - var(--border-thin)) calc(var(--radius-control) - var(--border-thin)) 0; }
.settings-presets .btn:focus-visible { position: relative; z-index: 1; }
@media (max-width: 374px) {
  .settings-sizes { grid-template-columns: 1fr; }
}
.settings-dialog > .save-modal > .settings-field { margin-top: var(--space-lg); }
.settings-select { width: 100%; }
.settings-lines { border: none; margin-top: var(--space-lg); display: flex; flex-wrap: wrap; gap: 0 var(--space-2xl); }
.settings-line { display: inline-flex; align-items: center; gap: var(--space-sm); min-height: var(--size-touch); color: var(--color-text); cursor: pointer; }
.settings-dialog [data-action="defaults"] { margin-right: auto; }
@media (max-width: 640px) {
  /* The preview's band tighter on phones, so the sheet with a field's error lines still fits an iPhone */
  .settings-preview { margin-top: var(--space-md); padding: var(--space-sm); }
}

/* The close symbol on Help, on the side panel after a save and on a failed session check: a symbol button
   the touch size, with no edge, under the pointer the sunken fill and a steel blue symbol. On the session
   check it floats at the box's top right, reaching into the box's padding. */
.help-close, .saved-panel-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--size-touch);
  height: var(--size-touch);
  padding: 0;
  border: none;
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--color-text);
  font-family: inherit;
  font-size: var(--text-2xl);
  line-height: var(--leading-1);
  cursor: pointer;
  transition: background-color var(--dur-fast), color var(--dur-fast);
  -webkit-tap-highlight-color: transparent;
}
.help-close:hover, .saved-panel-close:hover { background: var(--color-surface-2); color: var(--color-primary); }
.session-close { float: right; margin: calc(-1 * var(--space-md)) calc(-1 * var(--space-md)) var(--space-sm) var(--space-md); }

/* A symbol button's tooltip (src/tooltip.ts): an ink bubble with small white words (16.3:1), fading in.
   Above the dialogs, the loading cover and the session dialog. One shown by hover takes the pointer, so
   the pointer can rest on it to read it (WCAG 1.4.13). Any other takes no pointer events, so it never
   covers a control. */
.tooltip {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 400;
  max-width: calc(100vw - 16px);
  padding: calc(var(--space-xs) + var(--space-2xs)) var(--space-sm);
  border-radius: var(--radius-tag);
  background: var(--color-text);
  color: var(--color-on-dark);
  box-shadow: var(--shadow-popover);
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
  font-weight: var(--weight-medium);
  /* A caution mark with more than one cause shows one to a line */
  white-space: pre-line;
  pointer-events: none;
  animation: tooltip-in var(--dur-fast) var(--ease-enter);
}
.tooltip[data-by="hover"] { pointer-events: auto; }
/* Shown as a popover where its control sits in the top layer (the bell's panel, a tray), placed by its
   own top and left as before */
.tooltip[popover] { inset: auto; margin: 0; border: 0; overflow: visible; }
@keyframes tooltip-in { from { opacity: 0; } }
/* A long-press shows the tooltip, so iOS shows no menu and selects no text */
[data-tooltip] {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

/* Help (src/help.ts), a full page in the tool as the legal pages are (owner, 16 Oct, look check, the
   legal-dialog rules below): its sections in the legal text's type, the headings in steel blue */
.help-body { font-size: var(--text-sm); line-height: var(--leading-6); }
.help-heading {
  font-size: var(--text-md);
  line-height: var(--leading-md);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-snug);
  color: var(--color-primary);
  margin: var(--space-2xl) 0 var(--space-sm);
}
.help-heading:first-child { margin-top: var(--space-xl); }
.help-text { margin: 0 0 var(--space-sm); }
/* The header menu's sidebar (src/sidebar.ts, owner 15 Oct, navigation rework): a white panel from the right as
   tall as the window over the dimmed page, --size-sidebar wide and on phones leaving a strip of the page in
   view, at every width. Its top row, as tall as the header, holds the title in medium ink words and the
   close symbol at its right over a hairline. Then Help, Terms of use, Privacy and Third-party notices, each a
   row with its symbol and its words, a hairline after Help, and on the workspace and the annotate screen the
   version in the brand grey at the panel's foot. It slides in as Help does, and with reduced motion only
   fades in. */
.sidebar-dialog { justify-content: flex-end; align-items: stretch; padding: 0; }
.sidebar-dialog .save-modal {
  display: flex;
  flex-direction: column;
  width: min(var(--size-sidebar), calc(100% - var(--size-sidebar-shade)));
  max-width: none;
  height: 100%;
  max-height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0;
  border-radius: 0;
  font-size: var(--text-md);
  line-height: var(--leading-md);
  animation: help-panel-in var(--dur-reflow) var(--ease-enter);
}
.sidebar-top {
  box-sizing: border-box;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  min-height: calc(var(--size-header) + env(safe-area-inset-top));
  padding: env(safe-area-inset-top) max(var(--space-md), env(safe-area-inset-right)) 0 var(--space-2xl);
  border-bottom: var(--border-thin) solid var(--color-border);
}
.sidebar-top .save-modal-header {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  font-size: var(--text-md);
  line-height: var(--leading-md);
  font-weight: var(--weight-medium);
  letter-spacing: normal;
}
.sidebar-top .sidebar-close { order: 1; flex: 0 0 auto; }
.sidebar-list { margin: 0; padding: var(--space-sm) max(var(--space-2xl), env(safe-area-inset-right)) 0 var(--space-2xl); list-style: none; }
.sidebar-help { border-bottom: var(--border-thin) solid var(--color-border); }
.sidebar-item {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  width: 100%;
  min-height: var(--size-sidebar-row);
  padding: 0;
  border: none;
  background: transparent;
  color: var(--color-text);
  font: inherit;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.sidebar-item > svg { flex: 0 0 auto; width: var(--size-symbol); height: var(--size-symbol); }
.sidebar-item:hover { color: var(--color-primary); }
.sidebar-item:focus-visible { outline: var(--border-medium) solid var(--color-focus); outline-offset: calc(-1 * var(--border-medium)); }
.sidebar-version {
  margin: auto 0 0;
  padding: var(--space-2xl) max(var(--space-2xl), env(safe-area-inset-right)) max(var(--space-2xl), env(safe-area-inset-bottom)) var(--space-2xl);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  color: var(--color-text-secondary);
}
@media (max-width: 640px) {
  .sidebar-top { min-height: calc(var(--size-header-phone) + env(safe-area-inset-top)); padding-left: var(--space-2xl); }
}
@media (prefers-reduced-motion: reduce) {
  .sidebar-dialog .save-modal { animation: help-fade-in var(--dur-fast) var(--ease-enter); }
}

/* Help, the terms of use, the privacy notice and the third-party notices in the tool (src/legalpanel.ts), on
   the shared dialog: a panel over the whole window in the pages' own background, scrolling inside. Its top
   row, one close symbol at the right (owner, 16 Oct, look check), stays at the top of the panel while the
   page scrolls under it. The title and the text are as wide as the pages are and read as they do, in the
   app's tokens. The row and the text keep clear of the safe-area insets on every side (the notch or the
   Dynamic Island and the home indicator), the text as a column no wider than the window less the wider side
   inset each side, so it stays centred. It fades in, and on phones comes up from below, with reduced motion
   only fading. */
.legal-dialog { padding: 0; align-items: stretch; }
.legal-dialog .save-modal {
  max-width: none;
  height: 100%;
  max-height: 100%;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 0;
  border-radius: 0;
  box-shadow: none;
  background: var(--color-bg);
  animation: dialog-fade-in var(--dur-reflow) var(--ease-enter);
}
.legal-top {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-sm);
  padding: max(var(--space-sm), env(safe-area-inset-top)) max(var(--space-md), env(safe-area-inset-right)) var(--space-sm) max(var(--space-md), env(safe-area-inset-left));
  background: var(--color-surface);
  border-bottom: var(--border-thin) solid var(--color-border);
}
.legal-main { max-width: min(var(--size-legal-text), calc(100% - 2 * max(env(safe-area-inset-left), env(safe-area-inset-right)))); margin: 0 auto; padding: var(--space-3xl) var(--space-lg) max(var(--space-3xl), env(safe-area-inset-bottom)); }
.legal-main .save-modal-header { font-size: var(--text-2xl); line-height: var(--leading-2xl); margin: 0 0 var(--space-sm); }
.legal-content { font-size: var(--text-sm); line-height: var(--leading-6); }
.legal-content > p { margin: 0 0 var(--space-md); }
/* The terms of use and the privacy notice: numbered lists spaced as the paragraphs are, and long words
   wrapping on a phone */
.legal-content > :is(p, ol) { overflow-wrap: break-word; }
.legal-content > ol { margin: 0 0 var(--space-md); padding-left: var(--space-2xl); }
.legal-content > ol > li + li { margin-top: var(--space-xs); }
.legal-content .lead, .legal-failed { color: var(--color-text-muted); }
.legal-content h2 { font-size: var(--text-lg); line-height: var(--leading-lg); margin: var(--space-4xl) 0 var(--space-md); }
.legal-content h3 { font-size: var(--text-base); margin: 0 0 var(--space-sm); overflow-wrap: anywhere; }
.legal-content article { background: var(--color-surface); border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-md); padding: var(--space-lg); margin: 0 0 var(--space-md); }
.legal-content dl { margin: 0; display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--space-xs) var(--space-lg); }
.legal-content dt { color: var(--color-text-muted); }
.legal-content dd { margin: 0; overflow-wrap: anywhere; }
.legal-content dl > div { display: contents; }
.legal-content dd ul { list-style: none; margin: 0; padding: 0; }
.legal-content dd li + li { margin-top: var(--space-xs); }
.legal-content details { margin-top: var(--space-md); }
.legal-content summary { cursor: pointer; color: var(--color-accent); }
.legal-content pre { font-family: var(--font-mono); font-size: var(--text-2xs); white-space: pre-wrap; overflow-wrap: anywhere; background: var(--color-surface-2); border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-xs); padding: var(--space-md); margin: var(--space-sm) 0 0; }
@media (max-width: 640px) {
  .legal-dialog .save-modal { animation: sheet-in var(--dur-sheet) var(--ease-enter); }
  .legal-top {
    padding: max(var(--space-xs), env(safe-area-inset-top)) max(var(--space-xs), env(safe-area-inset-right)) var(--space-xs) max(var(--space-xs), env(safe-area-inset-left));
  }
  .legal-main {
    padding: var(--space-2xl) max(var(--space-gutter-phone), env(safe-area-inset-right)) max(var(--space-2xl), env(safe-area-inset-bottom)) max(var(--space-gutter-phone), env(safe-area-inset-left));
  }
}
@media (prefers-reduced-motion: reduce) {
  .legal-dialog .save-modal { animation: help-fade-in var(--dur-fast) var(--ease-enter); }
}
@keyframes help-fade-in { from { opacity: 0; } }

/* Notices (phase 6 look, L11). In the corner, the bottom right 8 px above the bottom band: the footer on
   Start, on Start with files and on the files screen the file panel's row with Compile or Apply changes on
   it, on the bar layout the bar at the window's foot, and on the workspace and the annotate screen on the
   full ribbon the window's foot, or the home indicator inset where there is one. The newest at the bottom,
   on every screen, the annotate screen too. They never cover the footer, that row or the bar.
   notices.ts keeps the bottom edge of the bar at the top of the screen in --notices-top, so the stack
   scrolls inside itself (is-full) before it reaches that bar. The same layer as dialogs and above the
   annotate screen: earlier in the page than dialogs, which are added at the end of the page and cover
   them. --notices-above is set on the page root, where the page's room for the stack uses it too. On the
   bar layout the stack keeps that one place in every state, an open pad or sheet drawing over it (owner,
   13 Oct, B20 point 6).
   The stack's box paints nothing and takes no presses. Until it is full what it holds shows past its
   box, so shadows show whole, and it is cut at the top of the bottom band, so a notice sliding in from
   below never covers the footer, Compile or Apply changes. */
.notices {
  position: fixed;
  right: max(var(--space-lg), env(safe-area-inset-right));
  bottom: var(--notices-above);
  width: min(420px, calc(100vw - 32px));
  max-height: calc(100dvh - var(--notices-above) - var(--notices-top, 8px));
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: var(--notices-gap);
  pointer-events: none;
  clip-path: inset(-100vh -100vw calc(-1 * var(--notices-gap)) -100vw);
}
.notices.is-full { overflow-y: auto; overscroll-behavior: contain; }
/* Full width at the bottom on phones, inside the safe area (phase 6 P5): every notice shows in full in the
   one stack directly above the bottom bar or the bench's foot, the newest nearest it, and the stack grows
   no taller than --size-notices-phone, nor up to the bar at the top of the screen, scrolling inside once
   its notices are taller. The page keeps room at its end for that height only (--notices-h). */
@media (max-width: 640px) {
  .notices {
    left: max(var(--space-lg), env(safe-area-inset-left));
    width: auto;
    max-height: min(var(--size-notices-phone), calc(100dvh - var(--notices-above) - var(--notices-top, 8px)));
  }
}
/* One box for the kinds shown on screen, guidance, warnings and failures (hints and results go into the bell
   only, owner, 16 Oct, guidance on screen too, owner, 17 Oct): white, the card radius and the popover shadow,
   the kind's symbol first, then the text, an action such as Review, and the close symbol, with a 4 px edge at
   the start in the kind's colour for a warning or a failure, so the kind shows by its symbol as well as its
   colour. The symbol, the text, the action and the
   close symbol are each centred on the box's height, for one line and several (owner, 15 Oct). A notice
   comes in sliding up 16 px as it fades in (only fading with reduced motion). */
.notice {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-md) var(--space-md) var(--space-md) var(--space-lg);
  background: var(--color-surface);
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-popover);
  color: var(--color-text);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  pointer-events: auto;
  animation: notice-in var(--dur-toast) var(--ease-enter);
}
@keyframes notice-in { from { opacity: 0; transform: translateY(var(--move-notice)); } }
.notice[data-kind="warning"], .notice[data-kind="failure"] {
  border-left: var(--border-edge) solid var(--color-warning);
  padding-left: calc(var(--space-lg) - var(--border-edge) + var(--border-thin));
}
.notice[data-kind="failure"] { border-left-color: var(--color-danger); }
/* Compact on phones, so more of each notice and of the page shows: 4 px round the close symbol, which
   keeps its 44 px, and 12 px before the kind's symbol */
@media (max-width: 640px) {
  .notice { gap: var(--space-sm); padding: var(--space-xs) var(--space-xs) var(--space-xs) var(--space-md); }
  .notice[data-kind="warning"], .notice[data-kind="failure"] { padding-left: calc(var(--space-md) - var(--border-edge) + var(--border-thin)); }
}
/* The kind's symbol, centred on the box's height as the close symbol is: guidance's steel blue information
   circle, the warning triangle and the danger circle, each shape filled with its sign in white */
.notice-symbol {
  flex: 0 0 auto;
  display: flex;
  width: var(--size-symbol);
  height: var(--size-symbol);
  color: var(--color-primary);
}
.notice-symbol svg { width: 100%; height: 100%; overflow: visible; }
.notice-symbol .notice-shape { fill: currentColor; }
.notice-shape ~ .notice-sign { stroke: var(--color-on-dark); }
.notice[data-kind="warning"] .notice-symbol { color: var(--color-warning); }
.notice[data-kind="failure"] .notice-symbol { color: var(--color-danger); }
@media (forced-colors: active) {
  .notice-symbol .notice-shape { fill: none; stroke: CanvasText; }
  .notice-shape ~ .notice-sign { stroke: CanvasText; }
}
/* The text centred on the box's height, a single line on the close symbol's row. A long file name breaks
   rather than widen the box. */
.notice-text {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}
.notice-close {
  flex: 0 0 auto;
  width: var(--size-notice-close); height: var(--size-notice-close);
  border: none;
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--color-text-muted);
  font-size: var(--text-lg);
  line-height: var(--leading-1);
  cursor: pointer;
}
.notice-close:hover { background: var(--color-surface-2); color: var(--color-primary); }
/* An action such as Review, before the close symbol */
.notice-action {
  flex: 0 0 auto;
  height: var(--size-notice-close);
  min-width: var(--size-notice-close);
  padding: 0 var(--space-md);
  border: var(--border-thin) solid var(--color-border-strong);
  border-radius: var(--radius-control);
  background: var(--color-surface);
  color: var(--color-text);
  font: inherit;
  font-weight: var(--weight-semibold);
  cursor: pointer;
}
.notice-action:hover { background: var(--color-surface-2); color: var(--color-primary); }
/* A notice leaving (notices.ts leave): a copy of it where it was, which fades and moves 8 px down over
   150 ms, then shrinks to nothing over 200 ms so the notices above it close the gap, and is taken away.
   With reduced motion it only fades, for 100 ms, and notices.ts takes it away at once after. */
.notice-leaving {
  flex: 0 0 auto;
  pointer-events: none;
  animation: notice-out var(--dur-quick) var(--ease-exit) forwards;
}
.notice-leaving.is-closing {
  opacity: 0;
  overflow: hidden;
  animation: notice-close var(--dur-reflow) var(--ease-standard) forwards;
}
@keyframes notice-out { to { opacity: 0; transform: translateY(var(--move-notice-out)); } }
@keyframes notice-close {
  from { height: var(--leaving-h); }
  to { height: 0; margin-top: calc(-1 * var(--notices-gap)); }
}
/* 44 px targets on touch screens */
@media (pointer: coarse) {
  :root { --size-split-hit: var(--size-touch); --size-split-ring: 20px; --size-resize-hit: 44px; --size-resize-in: 12px; --size-notice-close: var(--size-touch); --size-nr-clear-hit: var(--size-touch); }
}
