@incodetech/prizma-core-screens 0.2.24 → 0.2.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,28 @@
1
1
  import React from 'react';
2
2
  import { type PrizmaFormScreenProps } from './FormScreen';
3
3
  import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
4
- import type { ElectronicSignatureDrawState, ElectronicSignatureStrings } from './ElectronicSignatureStrings';
4
+ import type { ElectronicSignatureDrawState, ElectronicSignatureMethod, ElectronicSignatureStrings } from './ElectronicSignatureStrings';
5
5
  import './ScreenLayout.css';
6
+ import './ElectronicSignatureLayout.css';
6
7
  export interface ElectronicSignatureDrawScreenProps extends Omit<PrizmaFormScreenProps, 'title' | 'subtitle' | 'ctaLabel' | 'ctaDisabled' | 'verifiedLabel' | 'children' | 'navLabel' | 'linkLabel' | 'linkContent'> {
7
8
  /** Module copy — this screen reads the `draw` slice. */
8
9
  strings: ElectronicSignatureStrings;
9
- /** Which purple section to render: `draw` (empty) or `signed`. Default `draw`. */
10
+ /**
11
+ * Which pose to render: `draw` (empty pad), `signed` (ink on the pad) or
12
+ * `type` (type mode, `typedName` in the field). Default `draw`.
13
+ */
10
14
  state?: ElectronicSignatureDrawState;
15
+ /**
16
+ * Draw or Type, when the host owns it. Left out, the screen keeps its own,
17
+ * starting from `state`. Only read when `strings.type` is supplied.
18
+ */
19
+ method?: ElectronicSignatureMethod;
20
+ /** Called when the person switches between Draw and Type. */
21
+ onMethodChange?: (method: ElectronicSignatureMethod) => void;
22
+ /** The typed name, when the host owns it. Left out, the screen keeps its own. */
23
+ typedName?: string;
24
+ /** Called on every change to the typed name. */
25
+ onTypedNameChange?: (name: string) => void;
11
26
  /**
12
27
  * Core's own extension point for the drawing engine
13
28
  * (`PrizmaSignaturePad.onCanvasReady`: "consumers wire their drawing engine
@@ -1,9 +1,13 @@
1
1
  'use client';
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
- import { forwardRef } from 'react';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { forwardRef, useEffect, useId, useState } from 'react';
4
+ import { PrizmaSegmentedControl } from '@incodetech/prizma-core-web/segmented-control';
4
5
  import { PrizmaSignaturePad } from '@incodetech/prizma-core-web/signature-pad';
6
+ import { PrizmaSignaturePreview } from '@incodetech/prizma-core-web/signature-preview';
7
+ import { PrizmaTextField } from '@incodetech/prizma-core-web/text-field';
5
8
  import { PrizmaFormScreen } from './FormScreen';
6
9
  import './ScreenLayout.css';
10
+ import './ElectronicSignatureLayout.css';
7
11
  /**
8
12
  * Electronic Signature — the signature-pad screen, built on the Form archetype
9
13
  * (GUIDELINES.md §6-E, `PrizmaFormScreen`).
@@ -36,18 +40,62 @@ import './ScreenLayout.css';
36
40
  * in-flight treatment, if this module ever gains one, rides the CTA rather than
37
41
  * the field (#PI-5) — Core explicitly ships no Loading state for the pad.
38
42
  */
39
- export const ElectronicSignatureDrawScreen = forwardRef(({ strings, state = 'draw', onCanvasReady, screenId = `electronic-signature-${state}`, overrides, onAction, ...shell }, ref) => {
43
+ export const ElectronicSignatureDrawScreen = forwardRef(({ strings, state = 'draw', method: methodProp, onMethodChange, typedName: typedNameProp, onTypedNameChange, onCanvasReady, screenId = `electronic-signature-${state}`, overrides, onAction, ...shell }, ref) => {
40
44
  const signed = state === 'signed';
41
- return (_jsx(PrizmaFormScreen, { ref: ref, title: strings.draw.title, subtitle: strings.draw.subtitle, ctaLabel: strings.draw.ctaLabel,
45
+ const alt = strings.type;
46
+ // Draw / Type: controlled when the host passes `method` / `typedName`,
47
+ // otherwise the screen holds them, starting from the pose.
48
+ const [ownMethod, setOwnMethod] = useState(state === 'type' ? 'type' : 'draw');
49
+ const [ownName, setOwnName] = useState(state === 'type' ? typedNameProp ?? '' : '');
50
+ useEffect(() => {
51
+ setOwnMethod(state === 'type' ? 'type' : 'draw');
52
+ }, [state]);
53
+ const method = alt ? methodProp ?? ownMethod : 'draw';
54
+ const name = typedNameProp ?? ownName;
55
+ const typing = method === 'type';
56
+ const [padKey, setPadKey] = useState(0);
57
+ const panelId = useId();
58
+ const setName = (next) => {
59
+ if (typedNameProp === undefined)
60
+ setOwnName(next);
61
+ onTypedNameChange?.(next);
62
+ };
63
+ // Switching clears what the other mode held, the Document Electronic
64
+ // Signature rule (Elena, 2026-11-12), so Done only turns on for the
65
+ // signature on screen. A fresh pad is a remount of Core's pad.
66
+ const switchMethod = (next) => {
67
+ if (next === method)
68
+ return;
69
+ setPadKey((k) => k + 1);
70
+ setName('');
71
+ if (methodProp === undefined)
72
+ setOwnMethod(next);
73
+ onMethodChange?.(next);
74
+ };
75
+ const ready = typing ? name.trim().length > 1 : signed;
76
+ const title = typing && alt ? alt.title : strings.draw.title;
77
+ const subtitle = typing && alt ? alt.subtitle : strings.draw.subtitle;
78
+ const pad = (ghost) => (_jsx(PrizmaSignaturePad, { isFilled: ghost ? false : signed,
79
+ /* Full-signature sub-type, not the initials one. */
80
+ isInitials: false, placeholder: strings.draw.placeholder, canvasLabel: strings.draw.canvasLabel, clearLabel: strings.draw.clearLabel,
81
+ /* Clearing the canvas is a different flow from submitting it, so it
82
+ emits its own event rather than collapsing into the CTA
83
+ (DEVIATIONS #PI-10). */
84
+ onClear: ghost ? undefined : () => onAction?.({ type: 'secondary', screenId }), onCanvasReady: ghost ? undefined : onCanvasReady }, ghost ? 'ghost' : padKey));
85
+ // No `type` copy: the pad-only screen the module shipped with.
86
+ const middle = !alt ? (pad(false)) : (_jsxs("div", { className: "electronic-signature-method", children: [_jsx(PrizmaSegmentedControl, { "aria-label": alt.methodLabel, value: method, onValueChange: (v) => switchMethod(v === 'type' ? 'type' : 'draw'), options: [
87
+ { value: 'draw', label: alt.drawLabel, controls: !typing ? panelId : undefined },
88
+ { value: 'type', label: alt.typeLabel, controls: typing ? panelId : undefined },
89
+ ] }), !typing ? (_jsx("div", { id: panelId, role: "tabpanel", "aria-label": alt.drawLabel, className: "electronic-signature-method__body", children: pad(false) })) : (_jsxs("div", { id: panelId, role: "tabpanel", "aria-label": alt.typeLabel, className: "electronic-signature-method__body electronic-signature-method__body--type", children: [_jsx("div", { className: "electronic-signature-method__floor", "aria-hidden": "true", inert: '', children: pad(true) }), _jsxs("div", { className: "electronic-signature-method__type", children: [_jsx(PrizmaTextField, { label: alt.nameLabel, value: name, onValueChange: setName, autoComplete: "name", autoCapitalize: "words", autoCorrect: "off", spellCheck: false, enterKeyHint: "done", onKeyDown: (e) => {
90
+ if (e.key === 'Enter' && ready) {
91
+ e.preventDefault();
92
+ onAction?.({ type: 'cta', screenId });
93
+ }
94
+ } }), _jsx(PrizmaSignaturePreview, { label: alt.previewLabel, name: name, placeholder: alt.previewPlaceholder })] })] }))] }));
95
+ return (_jsx(PrizmaFormScreen, { ref: ref, title: title, subtitle: subtitle, ctaLabel: strings.draw.ctaLabel,
42
96
  /* `eSign.draw` draws `Done` on Button/Primary/Surface/Disabled — there
43
- is nothing to submit until the canvas has ink. */
44
- ctaDisabled: !signed, verifiedLabel: strings.verifiedLabel, navLabel: strings.navLabel, screenId: screenId, overrides: overrides, onAction: onAction, ...shell, children: _jsx(PrizmaSignaturePad, { isFilled: signed,
45
- /* Full-signature sub-type, not the initials one. */
46
- isInitials: false, placeholder: strings.draw.placeholder, canvasLabel: strings.draw.canvasLabel, clearLabel: strings.draw.clearLabel,
47
- /* Clearing the canvas is a different flow from submitting it, so it
48
- emits its own event rather than collapsing into the CTA
49
- (DEVIATIONS #PI-10). */
50
- onClear: () => onAction?.({ type: 'secondary', screenId }), onCanvasReady: onCanvasReady }) }));
97
+ is nothing to submit until the canvas has ink, or a name is typed. */
98
+ ctaDisabled: !ready, verifiedLabel: strings.verifiedLabel, navLabel: strings.navLabel, screenId: screenId, overrides: overrides, onAction: onAction, ...shell, children: middle }));
51
99
  });
52
100
  ElectronicSignatureDrawScreen.displayName = 'ElectronicSignatureDrawScreen';
53
101
  export default ElectronicSignatureDrawScreen;
@@ -84,3 +84,35 @@
84
84
  letter-spacing: var(--prizma-headline-h5-letter-spacing);
85
85
  color: var(--prizma-text-body-800-primary);
86
86
  }
87
+
88
+ /* ── Draw / Type (`strings.type` supplied) ───────────────────────────────────
89
+ * Core's Segmented control over the mode's body, the same composition as
90
+ * Document Electronic Signature's sheet (`.document-signature-sheet-body`):
91
+ * Spacing/8 between the control and the body, and between field and preview.
92
+ * Type mode keeps the Draw body's height: an inert copy of Core's pad shares
93
+ * the grid cell with the field + preview, so the CTA does not jump. */
94
+ .electronic-signature-method,
95
+ .electronic-signature-method__body,
96
+ .electronic-signature-method__type {
97
+ display: flex;
98
+ flex-direction: column;
99
+ gap: var(--prizma-spacing-8);
100
+ }
101
+
102
+ .electronic-signature-method__body--type {
103
+ display: grid;
104
+ }
105
+
106
+ .electronic-signature-method__body--type > * {
107
+ grid-area: 1 / 1;
108
+ min-width: 0;
109
+ }
110
+
111
+ .electronic-signature-method__floor {
112
+ visibility: hidden;
113
+ pointer-events: none;
114
+ }
115
+
116
+ .electronic-signature-method__type {
117
+ align-self: start;
118
+ }
@@ -3,7 +3,9 @@
3
3
  * placeholder visible, both actions inert) and `eSign.signed` (ink on the
4
4
  * canvas, Clear live, Done live). One screen, one Figma-drawn axis.
5
5
  */
6
- export type ElectronicSignatureDrawState = 'draw' | 'signed';
6
+ export type ElectronicSignatureDrawState = 'draw' | 'signed' | 'type';
7
+ /** How the person signs: drawing on the pad, or typing their name. */
8
+ export type ElectronicSignatureMethod = 'draw' | 'type';
7
9
  export interface ElectronicSignatureStrings {
8
10
  /** "verified by" attribution copy for the footer tag. */
9
11
  verifiedLabel: string;
@@ -33,6 +35,29 @@ export interface ElectronicSignatureStrings {
33
35
  /** Primary CTA — "Done". */
34
36
  ctaLabel: string;
35
37
  };
38
+ /**
39
+ * Draw / Type — the accessible alternative to the pad (Elena, 2026-11-13,
40
+ * the same switch as Document Electronic Signature's sheet). Optional: a
41
+ * host that leaves it out keeps the pad-only screen it shipped with.
42
+ */
43
+ type?: {
44
+ /** Accessible name for the Draw / Type Segmented control — "Signature method". */
45
+ methodLabel: string;
46
+ /** Segmented control, the draw option — "Draw". */
47
+ drawLabel: string;
48
+ /** Segmented control, the type option — "Type". */
49
+ typeLabel: string;
50
+ /** H2 in type mode — "Type your name". */
51
+ title: string;
52
+ /** H5 in type mode — "Use your full name". */
53
+ subtitle: string;
54
+ /** Field label — "Full name". */
55
+ nameLabel: string;
56
+ /** Core's Signature preview label, under the field — "Preview". */
57
+ previewLabel: string;
58
+ /** Signature preview while the field is empty — "Your signature". */
59
+ previewPlaceholder: string;
60
+ };
36
61
  /** `eSign.success` — the verdict, reported with no action. */
37
62
  success: {
38
63
  /** H2 — "Signed successfully!". */
@@ -103,7 +103,7 @@ export const FaceCaptureCapturingScreen = forwardRef(({ strings, state = 'initia
103
103
  const offer = strings.extendTime;
104
104
  // No copy, no notice: a host that has not localized this must not get
105
105
  // English, and the flag alone is not permission to invent it.
106
- const notice = extendTime && offer ? (_jsxs(PrizmaSnackbar, { state: "neutral", isMultiline: true,
106
+ const notice = extendTime && offer ? (_jsxs(PrizmaSnackbar, { state: "neutral",
107
107
  // Assertive on purpose — see the live-region note in this file's
108
108
  // header. The component default here would be `status`.
109
109
  role: "alert", linkLabel: offer.linkLabel, onLinkClick: onExtendTime, children: [_jsx("strong", { children: offer.title }), _jsx("br", {}), offer.description] })) : undefined;
@@ -121,7 +121,7 @@ export const IdCaptureStageScreen = forwardRef(({ strings, documentType = 'id',
121
121
  // No copy, no notice: a host that has not localized this must not get
122
122
  // English, and the flag alone is not permission to invent it.
123
123
  const band = notice ??
124
- (extendTime && offer ? (_jsxs(PrizmaSnackbar, { state: "neutral", isMultiline: true,
124
+ (extendTime && offer ? (_jsxs(PrizmaSnackbar, { state: "neutral",
125
125
  // Assertive on purpose — a polite region can queue behind the
126
126
  // stage's own state announcements and be read out after the 20 s
127
127
  // has already run out. FaceCaptureCapturingScreen's header has the
package/dist/index.d.ts CHANGED
@@ -81,11 +81,13 @@ export { CurpGenerateScreen, type CurpGenerateScreenProps } from './CurpGenerate
81
81
  export { CurpConfirmScreen, type CurpConfirmScreenProps } from './CurpConfirmScreen';
82
82
  export { CurpProcessingScreen, type CurpProcessingScreenProps } from './CurpProcessingScreen';
83
83
  export { CurpResultScreen, type CurpResultScreenProps } from './CurpResultScreen';
84
- export { type ElectronicSignatureDrawState, type ElectronicSignatureStrings } from './ElectronicSignatureStrings';
84
+ export { type ElectronicSignatureDrawState, type ElectronicSignatureMethod, type ElectronicSignatureStrings, } from './ElectronicSignatureStrings';
85
85
  export { ElectronicSignatureDrawScreen, type ElectronicSignatureDrawScreenProps } from './ElectronicSignatureDrawScreen';
86
86
  export { ElectronicSignatureErrorScreen, type ElectronicSignatureErrorScreenProps } from './ElectronicSignatureErrorScreen';
87
87
  export { ElectronicSignatureReviewScreen, type ElectronicSignatureReviewScreenProps } from './ElectronicSignatureReviewScreen';
88
88
  export { ElectronicSignatureSuccessScreen, type ElectronicSignatureSuccessScreenProps } from './ElectronicSignatureSuccessScreen';
89
+ export { documentSignatureResultStrings, type DocumentSignatureState, type DocumentSignatureStrings, } from './DocumentSignatureStrings';
90
+ export { DocumentSignatureReviewScreen, type DocumentSignatureDocument, type DocumentSignatureReviewScreenProps, type DocumentSignatureSignature, } from './DocumentSignatureReviewScreen';
89
91
  export { type QualifiedSignatureAcceptVariant, type QualifiedSignatureAcceptState, type QualifiedSignatureDocumentVariant, type QualifiedSignatureResultVariant, type QualifiedSignatureProcessingVariant, type QualifiedSignatureTerm, type QualifiedSignatureAcceptCopy, type QualifiedSignatureStrings, } from './QualifiedSignatureStrings';
90
92
  export { QualifiedSignatureAcceptScreen, type QualifiedSignatureAcceptScreenProps } from './QualifiedSignatureAcceptScreen';
91
93
  export { QualifiedSignatureDocumentScreen, type QualifiedSignatureDocumentScreenProps } from './QualifiedSignatureDocumentScreen';
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ // from the `read-and-sign-in-one-screen` exploration
1
2
  // @incodetech/prizma-core-screens — barrel.
2
3
  //
3
4
  // Foundation: shell, nav, capture overlay, and the seven screen archetypes
@@ -79,6 +80,9 @@ export { ElectronicSignatureDrawScreen } from './ElectronicSignatureDrawScreen';
79
80
  export { ElectronicSignatureErrorScreen } from './ElectronicSignatureErrorScreen';
80
81
  export { ElectronicSignatureReviewScreen } from './ElectronicSignatureReviewScreen';
81
82
  export { ElectronicSignatureSuccessScreen } from './ElectronicSignatureSuccessScreen';
83
+ // Document Electronic Signature: from the `read-and-sign-in-one-screen` exploration.
84
+ export { documentSignatureResultStrings, } from './DocumentSignatureStrings';
85
+ export { DocumentSignatureReviewScreen, } from './DocumentSignatureReviewScreen';
82
86
  export { QualifiedSignatureAcceptScreen } from './QualifiedSignatureAcceptScreen';
83
87
  export { QualifiedSignatureDocumentScreen } from './QualifiedSignatureDocumentScreen';
84
88
  export { QualifiedSignatureProcessingScreen } from './QualifiedSignatureProcessingScreen';
package/dist/styles.css CHANGED
@@ -18,6 +18,7 @@
18
18
  @import './DemoScreensLayout.css';
19
19
  @import './DigitalIdProvidersLayout.css';
20
20
  @import './DocumentCaptureLayout.css';
21
+ @import './DocumentSignatureLayout.css';
21
22
  @import './EkycLayout.css';
22
23
  @import './ElectronicSignatureLayout.css';
23
24
  @import './FaceCaptureLayout.css';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@incodetech/prizma-core-screens",
3
- "version": "0.2.24",
3
+ "version": "0.2.26",
4
4
  "description": "Prizma Design System — SDK module screens: composed, responsive, brand-themeable React screens built from @incodetech/prizma-core-web.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -215,6 +215,11 @@
215
215
  "types": "./dist/DocumentCaptureTutorialScreen.d.ts",
216
216
  "import": "./dist/DocumentCaptureTutorialScreen.js"
217
217
  },
218
+ "./document-signature-review-screen": {
219
+ "source": "./src/DocumentSignatureReviewScreen.tsx",
220
+ "types": "./dist/DocumentSignatureReviewScreen.d.ts",
221
+ "import": "./dist/DocumentSignatureReviewScreen.js"
222
+ },
218
223
  "./ekyb-address-details-screen": {
219
224
  "source": "./src/EkybAddressDetailsScreen.tsx",
220
225
  "types": "./dist/EkybAddressDetailsScreen.d.ts",
@@ -787,6 +792,7 @@
787
792
  "./demo-screens-layout.css": "./dist/DemoScreensLayout.css",
788
793
  "./digital-id-providers-layout.css": "./dist/DigitalIdProvidersLayout.css",
789
794
  "./document-capture-layout.css": "./dist/DocumentCaptureLayout.css",
795
+ "./document-signature-layout.css": "./dist/DocumentSignatureLayout.css",
790
796
  "./ekyc-layout.css": "./dist/EkycLayout.css",
791
797
  "./electronic-signature-layout.css": "./dist/ElectronicSignatureLayout.css",
792
798
  "./face-capture-layout.css": "./dist/FaceCaptureLayout.css",
@@ -847,8 +853,8 @@
847
853
  },
848
854
  "dependencies": {
849
855
  "@incodetech/prizma-core-icons": "^0.4.0",
850
- "@incodetech/prizma-core-tokens": "^0.20.0",
851
- "@incodetech/prizma-core-web": "^0.20.0"
856
+ "@incodetech/prizma-core-tokens": "^0.21.0",
857
+ "@incodetech/prizma-core-web": "^0.21.0"
852
858
  },
853
859
  "devDependencies": {
854
860
  "@types/react": "^18.3.12",
@@ -62,7 +62,7 @@ export const DemoScreensConfigSheetScreen = forwardRef<HTMLDivElement, DemoScree
62
62
  <PrizmaScreenShell ref={ref} data-screen-id={screenId} {...shell}>
63
63
  {state === 'saved' ? (
64
64
  <div className="demo-screens-toast">
65
- <PrizmaSnackbar state="success" contentResizing="fill" isMultiline>
65
+ <PrizmaSnackbar state="success" contentResizing="fill">
66
66
  {s.savedSnackbar}
67
67
  </PrizmaSnackbar>
68
68
  </div>
@@ -0,0 +1,160 @@
1
+ /* from the `read-and-sign-in-one-screen` exploration
2
+ *
3
+ * Document Electronic Signature — layout glue only. No archetype value is
4
+ * redeclared (the gutters, the title block, the CTA band and the tag stay the
5
+ * foundation's) and nothing here draws a component: the viewer frame is
6
+ * Electronic Signature's `.electronic-signature-document`, the Stepper,
7
+ * Scroll pill, Segmented control, pad, field, Signature preview and sheet are
8
+ * Core's. Every value is a --prizma-*
9
+ * token. Ported from Option B (`read-and-sign.css`) of the exploration.
10
+ */
11
+
12
+ /* The viewer fills what the Stepper leaves. Electronic Signature's frame
13
+ carries a Spacing/16 bottom margin for its List screen; in the Form
14
+ archetype the field stack closes at Spacing/16 instead, so it is released
15
+ here and the stack takes it (the same gap, the same token). */
16
+ .document-signature-screen .prizma-form-screen__fields {
17
+ margin-bottom: var(--prizma-spacing-16);
18
+ }
19
+
20
+ .document-signature-screen .prizma-form-screen__fields > :not(.document-signature-viewer) {
21
+ flex-shrink: 0;
22
+ }
23
+
24
+ .document-signature-viewer.electronic-signature-document {
25
+ flex: 1 1 auto;
26
+ min-height: 0;
27
+ margin-bottom: 0;
28
+ /* The sections' offset parent, so the screen reads where each document is
29
+ in layout pixels, whatever transform a spec card scales the frame with. */
30
+ position: relative;
31
+ }
32
+
33
+ /* One document: its title, then the host's prose. No divider between
34
+ documents: the count is the Stepper's caption. Electronic Signature's frame already spaces its direct
35
+ children; a section spaces its own. */
36
+ .document-signature-doc {
37
+ display: flex;
38
+ flex-direction: column;
39
+ gap: var(--prizma-spacing-12);
40
+ }
41
+
42
+ .document-signature-doc + .document-signature-doc {
43
+ margin-top: var(--prizma-spacing-24);
44
+ }
45
+
46
+ .document-signature-doc > * {
47
+ margin: 0;
48
+ }
49
+
50
+ /* A document's title is a step above its section headings: Headline/H4 on the
51
+ frame's own Text/Body/800. */
52
+ .electronic-signature-document .document-signature-doc__title {
53
+ font-size: var(--prizma-headline-h4-font-size);
54
+ line-height: var(--prizma-headline-h4-line-height);
55
+ font-weight: var(--prizma-headline-h4-font-weight);
56
+ letter-spacing: var(--prizma-headline-h4-letter-spacing);
57
+ }
58
+
59
+ /* The sheet body: Core's Segmented control (Draw / Type), then the mode's
60
+ body. Spacing/8 between them, and between the field and the preview, the
61
+ exploration's own gap (`.rs-b-sheet`). */
62
+ .document-signature-sheet-body,
63
+ .document-signature-sheet-mode,
64
+ .document-signature-sheet-mode__type {
65
+ display: flex;
66
+ flex-direction: column;
67
+ gap: var(--prizma-spacing-8);
68
+ }
69
+
70
+ /* Type mode keeps the Draw body's height: an invisible copy of Core's pad and
71
+ the field + preview share one grid cell, so the cell is as tall as the taller
72
+ of the two and the sheet does not jump when the mode switches. */
73
+ .document-signature-sheet-mode--type {
74
+ display: grid;
75
+ }
76
+
77
+ .document-signature-sheet-mode--type > * {
78
+ grid-area: 1 / 1;
79
+ min-width: 0;
80
+ }
81
+
82
+ .document-signature-sheet-mode__floor {
83
+ visibility: hidden;
84
+ pointer-events: none;
85
+ }
86
+
87
+ .document-signature-sheet-mode__type {
88
+ align-self: start;
89
+ }
90
+
91
+ /* ── Short panels: the sheet stops under the status bar ──────────────────────
92
+ * The signing sheet is 652 tall (Draw, and Type keeps that height). On the
93
+ * Galaxy Z Fold 8 cover (416 x 657) it rose to 5px from the top, over the
94
+ * status bar (measured 2026-11-13); on every other frame Core Lab offers it
95
+ * clears with room (iPhone Duo closed 26, open 17, Fold main 164, the 844
96
+ * reference 192). Under the 720 short-panel line the panel stops at the status
97
+ * bar plus Spacing/24, the Demo screens sheet's own top, and the one element
98
+ * that gives ground is the pad's drawing area (step 1 of the order of
99
+ * concessions: it is space, not task information), 256 to 190 on the Fold
100
+ * cover. The title, the consent, Draw / Type, Clear canvas, Confirm and
101
+ * continue and Core's 34 safe area keep their size. Type keeps the field and
102
+ * the preview whole: only the invisible Draw floor gives way. Outside the
103
+ * query not one declaration exists, so the reference is untouched. */
104
+ @container pcs-screen (max-height: 720px) {
105
+ .document-signature-screen .prizma-screen-layout__sheet-panel {
106
+ max-height: calc(100% - var(--pcs-status-bar, 47px) - var(--prizma-spacing-24));
107
+ display: flex;
108
+ flex-direction: column;
109
+ }
110
+
111
+ .document-signature-screen .prizma-screen-layout__sheet-panel .prizma-bottom-sheet,
112
+ .document-signature-screen .prizma-screen-layout__sheet-panel .prizma-bottom-sheet__content,
113
+ .document-signature-screen .prizma-screen-layout__sheet-panel .prizma-bottom-sheet__body,
114
+ .document-signature-screen .document-signature-sheet-body,
115
+ .document-signature-screen .document-signature-sheet-mode,
116
+ .document-signature-screen .document-signature-sheet-mode .prizma-signature-pad,
117
+ .document-signature-screen .document-signature-sheet-mode .prizma-signature-pad__canvas-wrapper {
118
+ flex: 0 1 auto;
119
+ min-height: 0;
120
+ }
121
+
122
+ .document-signature-screen .prizma-screen-layout__sheet-panel .prizma-bottom-sheet__body {
123
+ display: flex;
124
+ flex-direction: column;
125
+ }
126
+
127
+ .document-signature-screen .prizma-bottom-sheet__content > :not(.prizma-bottom-sheet__body),
128
+ .document-signature-screen .document-signature-sheet-body > :not(.document-signature-sheet-mode) {
129
+ flex-shrink: 0;
130
+ }
131
+
132
+ /* The grid cell may be shorter than the invisible Draw copy it holds. */
133
+ .document-signature-screen .document-signature-sheet-mode--type {
134
+ grid-template-rows: minmax(0, auto);
135
+ }
136
+ }
137
+
138
+ /* ── The sheet's motion (2026-11-13) ─────────────────────────────────────────
139
+ Interactive only (`--moving` is set when the screen is live; static spec
140
+ cards stay still, as ScreenLayout's sheet rules intend). Core's Sheet/Motion
141
+ tokens and Core's own keyframes (`prizma-sheet-scrim-in/out`,
142
+ `prizma-sheet-slide-in/out` in bottom-sheet.css), as Core's presenter does: the scrim fades
143
+ in and the panel rises on Enter + Decelerate, and both leave on Exit +
144
+ Accelerate. Nothing moves under reduced motion. */
145
+ .document-signature-sheet-scrim--moving {
146
+ animation: prizma-sheet-scrim-in var(--prizma-sheet-motion-enter-duration) var(--prizma-sheet-motion-enter-easing) both;
147
+ }
148
+ .document-signature-sheet-panel--moving {
149
+ animation: prizma-sheet-slide-in var(--prizma-sheet-motion-enter-duration) var(--prizma-sheet-motion-enter-easing) both;
150
+ }
151
+ .document-signature-sheet-scrim--moving.is-closing {
152
+ animation: prizma-sheet-scrim-out var(--prizma-sheet-motion-exit-duration) var(--prizma-sheet-motion-exit-easing) both;
153
+ }
154
+ .document-signature-sheet-panel--moving.is-closing {
155
+ animation: prizma-sheet-slide-out var(--prizma-sheet-motion-exit-duration) var(--prizma-sheet-motion-exit-easing) both;
156
+ }
157
+ @media (prefers-reduced-motion: reduce) {
158
+ .document-signature-sheet-scrim--moving,
159
+ .document-signature-sheet-panel--moving { animation: none; }
160
+ }