@super-ic/web-patterns 0.0.0-oidc-bootstrap.0 → 0.1.9

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.
package/README.md CHANGED
@@ -1,3 +1,311 @@
1
1
  # @super-ic/web-patterns
2
2
 
3
- This prerelease reserves the package name for initial GitHub Actions OIDC trusted-publisher setup. It contains no runtime, exports, or API. Do not use it in production. Real design-system versions are released separately through the trusted GitHub workflow.
3
+ Marketing web patterns built on the SuperIC foundation token layer:
4
+
5
+ - `CaseStudyCard` (aliased as `CaseStudyCardShell`): the structural case-study
6
+ card: one whole-card control, a full-bleed 16:10 product-proof band, an
7
+ identity-first body, and an open/locked access contract.
8
+ - `SURFACE_RADIUS_TOKENS`, `SURFACE_RADIUS_CLASSES`, `nestedSurfaceRadius`: the
9
+ shared surface-radius scale used to keep nested surfaces concentric.
10
+ - `CaseStudyCardProvenance`, `CaseStudyCardProductAccess`: the **shape** of the
11
+ presentation metadata a consumer passes in.
12
+
13
+ The package ships no card records. There is no roster, no slug list and no
14
+ copy in this package: every card's destination, identity mark, product proof,
15
+ headline and result is consumer-owned and passed as props. That is deliberate,
16
+ and it is why the type is exported but the data is not.
17
+
18
+ ## Install
19
+
20
+ ```sh
21
+ npm install @super-ic/web-patterns @super-ic/foundation @super-ic/primitives react react-dom
22
+ ```
23
+
24
+ `@super-ic/foundation` (`^0.2.0`) and `react` (`>=19`) are **peer
25
+ dependencies**. Install them yourself; this package will not pull them in.
26
+ `@super-ic/icon-contracts` is a hard dependency and comes along automatically;
27
+ the card renders its forward chevron through it.
28
+
29
+ ## Three mandatory setup steps
30
+
31
+ The existing case-study card ships JSX and Tailwind class strings. Its layout
32
+ requires the token and Tailwind steps below. NeighborhoodLanding additionally
33
+ ships its own exported recipe stylesheet, documented below. Skip the
34
+ nucleo bind and `Icon` throws `IconGlyphsNotBoundError` at render.
35
+
36
+ ### 1. Import the token stylesheet once
37
+
38
+ ```ts
39
+ import "@super-ic/foundation/tokens.css";
40
+ ```
41
+
42
+ Import it once at the application root, before anything renders. It defines the
43
+ `:root` layer the card's classes resolve against, including `--radius-card`,
44
+ `--radius-card-frame`, `--elev-card`, `--elev-pill`, `--motion-hover-duration`
45
+ and `--motion-ease-quiet`. Without it the card has square corners, no
46
+ elevation, and no hover transition.
47
+
48
+ ### 2. Import the package Tailwind bridge
49
+
50
+ Tailwind v4 does not scan `node_modules`, so the utility classes this package
51
+ emits generate no CSS unless the package's built output is scanned. Import
52
+ Tailwind once, then import the public bridge. The bridge scans this package's
53
+ distributed JavaScript and includes the public primitives bridge:
54
+
55
+ ```css
56
+ @import "tailwindcss";
57
+ @import "@super-ic/web-patterns/tailwind.css";
58
+ ```
59
+
60
+ Omit the owning bridge and the card renders as unstyled markup with correct
61
+ semantics.
62
+
63
+ ### 3. Bind Nucleo glyphs once at the application root
64
+
65
+ The card draws its control chevron through `@super-ic/icon-contracts` `Icon`.
66
+ That component throws `IconGlyphsNotBoundError` unless the consumer evaluates
67
+ the nucleo subpath before the first render:
68
+
69
+ ```ts
70
+ import "@super-ic/icon-contracts/nucleo";
71
+ ```
72
+
73
+ Import it once in a module that runs on both the server and the client. A
74
+ server-only import leaves the client unbound after hydration. The package
75
+ contract test binds this subpath before it renders a card. Product tests should
76
+ do the same, or they will mask a production outage.
77
+
78
+ ## Access contract: `locked` requires `onUnlock`
79
+
80
+ `access` defaults to `"open"`, which renders an anchor to `href`. Setting
81
+ `access="locked"` renders a single `role="button"` control with
82
+ `aria-haspopup="dialog"` and **no** `href`, so the consumer's own gate decides
83
+ what happens.
84
+
85
+ That control has to do something, so the component fails closed rather than
86
+ rendering a dead card:
87
+
88
+ ```tsx
89
+ /* Throws: Locked case-study cards require an unlock handler */
90
+ <CaseStudyCard href="/case-studies/example" access="locked" {...rest} />
91
+ ```
92
+
93
+ ```tsx
94
+ /* Correct */
95
+ <CaseStudyCard
96
+ href="/case-studies/example"
97
+ access="locked"
98
+ onUnlock={() => setGateOpen(true)}
99
+ lockedControlRef={gateReturnFocusRef}
100
+ {...rest}
101
+ />
102
+ ```
103
+
104
+ The throw happens during render, in development and production alike. Pass
105
+ `lockedControlRef` so focus can return to the card after your dialog closes.
106
+
107
+ ## Framework-native navigation
108
+
109
+ An open card renders a plain `<a>` by default. To route through a framework
110
+ link, supply `renderOpenControl`. It receives the full set of control props
111
+ (`href`, `className`, the `data-*` slots, `aria-label`, `aria-describedby`) and
112
+ must spread all of them onto whatever it renders:
113
+
114
+ ```tsx
115
+ <CaseStudyCard
116
+ href="/case-studies/example"
117
+ renderOpenControl={({ children, ...props }) => <Link {...props}>{children}</Link>}
118
+ {...rest}
119
+ />
120
+ ```
121
+
122
+ ## Known gap
123
+
124
+ One token family the card's class names is **not** in
125
+ `@super-ic/foundation/tokens.css` today:
126
+
127
+ - `--enterprise-bg` / `--enterprise-fg` (via `bg-enterprise-bg` and
128
+ `text-enterprise-fg`) are excluded from the generated layer on purpose. In
129
+ the source they are a site-local plate bound to the dark ramp, so emitting
130
+ them would ship a permanently dark card. See the `@super-ic/foundation` README.
131
+ The public Tailwind bridge supplies the foundation mappings for `border-border`,
132
+ `ring-ring` and `ring-offset-background`. Until the enterprise plate is closed in
133
+ a consumer's own stylesheet, its surface inherits the page background. Everything
134
+ else (geometry, hierarchy, radii, elevation, motion and the whole accessibility
135
+ contract) resolves from the token layer and public bridge.
136
+
137
+
138
+ ## NeighborhoodLanding (candidate)
139
+
140
+ Sharing-tab foreground, background and borders change together without a color
141
+ transition. This preserves readable inactive and selected labels during theme
142
+ initialization as well as keyboard selection. Verify both themes at natural phone
143
+ size; a difference between background colors alone does not prove legibility.
144
+
145
+ `NeighborhoodLanding` is an object-led public community landing recipe. It pairs
146
+ a tangible illustrative example with two ways to participate, a residency and
147
+ joining section, practical disclosures, and legal/help destinations. Its CSS
148
+ belongs to the package; product consumers must not recreate this composition.
149
+ This is a review candidate, not an accepted product or release claim.
150
+
151
+ ```tsx
152
+ import { NeighborhoodLanding, type NeighborhoodLandingProps } from "@super-ic/web-patterns";
153
+ import "@super-ic/foundation/tokens.css";
154
+ import "@super-ic/web-patterns/neighborhood-landing.css";
155
+ // Bind the approved semantic glyph provider at server and client roots.
156
+ import "@super-ic/icon-contracts/nucleo";
157
+
158
+ const page: NeighborhoodLandingProps = /* product-owned content and routes */;
159
+ <NeighborhoodLanding {...page} />;
160
+ ```
161
+
162
+ The consuming Tailwind v4 entry must compile the public primitive bridge:
163
+
164
+ ```css
165
+ @import "tailwindcss";
166
+ @import "@super-ic/web-patterns/tailwind.css";
167
+ ```
168
+
169
+ The package bridge scans web-patterns and the primitives' built output and
170
+ provides foundation utility mappings and Accordion animations. Recipe layout comes from
171
+ `neighborhood-landing.css`; do not scan a private DS source path. The recipe uses
172
+ public `buttonVariants` on real anchors so navigation retains link semantics,
173
+ plus public Tabs, Accordion and semantic icons. It does not use a button role on
174
+ an anchor or implement replacement keyboard behavior. The recipe's module has a
175
+ client directive because its disclosures and tabs are interactive.
176
+
177
+ The product supplies brand, media, copy, eligibility, join availability, routes,
178
+ and each claim. `membership.join` is a required discriminated union:
179
+
180
+ - `available`: one destination with `label` and real `href`, plus a truthful note.
181
+ - `unavailable`: reason/title, explanation and a real help destination. No
182
+ disabled fake submit button or implicit waitlist is rendered.
183
+
184
+ `hero.availability` is also required. Keep it consistent with the product's
185
+ actual activation state. An unfinished DS build does not determine production
186
+ membership availability. This component never creates accounts, verifies
187
+ residency, collects email, sends support messages, or claims backend readiness.
188
+
189
+ `renderLink` may adapt external page destinations to a framework link. Forward
190
+ all received anchor properties, including href, className, children and focus
191
+ behavior. Internal skip, how-it-works and join anchors remain native document
192
+ navigation. The calling application supplies its route implementation and
193
+ back/forward behavior. Do not replace real destinations with `#` or silently
194
+ swallow links. The specimen's dialog destinations are explicitly labeled local
195
+ previews and are not part of this package.
196
+
197
+ ### Contract and proof
198
+
199
+ - Two participation examples are required, each with a stable unique ID and
200
+ three real explanatory steps. These are examples, not fabricated posts.
201
+ Asking/offering copy belongs to the tenant. Keyboard Left/Right selects tabs;
202
+ Enter/Space operates disclosure triggers. The underlying public primitives
203
+ own these semantics.
204
+ - Every link has visible text or the brand's accessible name. The main, sharing
205
+ and membership sections have stable per-instance IDs and programmatic focus
206
+ targets for native anchor navigation. FAQ questions name their own buttons.
207
+ - Hero media requires src, nonempty alt, intrinsic dimensions and a visible
208
+ caption. Optional possibility and example media use the public
209
+ `NeighborhoodLandingMedia` shape. Possibility IDs must be unique. Test failures
210
+ both before hydration and after handlers attach; neither path may leave a broken
211
+ image or hide the associated copy and action. These images are
212
+ informative only, lazy-load outside the hero, use contain presentation, and disappear
213
+ independently on error; their surrounding copy and actions remain. A new `src` resets
214
+ that failure state. Media never establishes runtime availability, membership or authority. The consumer retains the rights/provenance record. No supplied media
215
+ or participation example may imply existing inventory or real demand without
216
+ evidence. The package contains no photos or tenant records.
217
+ - Layout uses the foundation's type, spacing, surface, action, border, radius
218
+ and focus roles. The optional tenant accent-quiet role falls back to surface-2
219
+ for a brand without that role. Width responds to the actual recipe container,
220
+ not only the viewport. Reduced motion preserves all content and actions.
221
+ - Allowed composition: a page-level landing, with a brand mark, short copy,
222
+ illustrative photo, two participation explanations and plain-text/linked FAQ
223
+ answers. Keep links and small paragraphs inside answers, not nested modals,
224
+ primary actions or another page recipe.
225
+ - Anti-patterns: fake member counts, listings, testimonials or trust scores;
226
+ blanket safety/insurance claims; public addresses or residency evidence;
227
+ inactive paid/service modes presented as available; repeated feature-card
228
+ walls; an application form that the consumer cannot actually submit.
229
+ - Limits: one landing/main landmark per page; exactly two examples and three
230
+ steps per example; unique IDs within each repeated collection; no invented
231
+ density modes or loading states. Text can grow without clipping, but long
232
+ hero copy weakens the first-viewport composition and needs editorial review.
233
+ - Ownership: shared recipe and its browser contract belong to SuperIC DS;
234
+ resident policy, routes, activation, claims and support belong to the
235
+ consuming product. The candidate has no automatic promotion path.
236
+ - Migration: replace page-local marketing shells with the public recipe and
237
+ exported CSS after review. Existing marketing exports remain unchanged; this
238
+ addition does not retroactively accept their legacy behavior.
239
+
240
+ Executable requirements in `contracts/neighborhood-landing.json` bind to the
241
+ candidate stories and the actual `neighborhood-landing.browser.test.ts` titles.
242
+ Those bindings are an input to the coordinator's canonical catalog integration,
243
+ not a fabricated accepted-registry record. A file being present is not proof of
244
+ execution. Record the executed report and exact source/package hashes when this
245
+ candidate is integrated; repeat installed-consumer checks on the final graph.
246
+ # Public help and documents
247
+
248
+ Import `PublicSiteFrame`, `PublicArticle`, `HelpDirectory` and `PublicAvailability`
249
+ from `@super-ic/web-patterns`, with `@super-ic/web-patterns/public-content.css`.
250
+ These are candidate recipes. Compile the public foundation/primitives Tailwind
251
+ bridge and load the tenant's public font sheets at the consumer root.
252
+
253
+ `PublicSiteFrame` owns the public header, one main landmark, skip link and footer.
254
+ Compose exactly one h1-owning article, help directory or availability boundary.
255
+ Pass real links and preserve normal browser modifier-key behavior in `onNavigate`.
256
+ Navigation IDs must be unique and at most one item is current. Marks use their
257
+ natural aspect ratio at a 100px width; the consumer supplies the actual tenant mark.
258
+
259
+ `PublicArticle` receives a title, introduction, optional factual date/version label,
260
+ optional notice, stable section slugs, trusted React prose and related routes. Use
261
+ paragraphs, lists, description lists, links and h3 subheadings in section bodies.
262
+ Do not inject raw HTML or another page/main/h1. Section IDs must be unique lowercase
263
+ slugs. The table of contents uses native fragment links and a native disclosure so
264
+ document navigation and all prose remain usable without JavaScript. This native
265
+ document disclosure is intentional; it does not replace application dialogs or
266
+ shadcn form controls. Supplied metadata is not a legal-readiness or acceptance claim.
267
+ Set `anchorId` to a stable lowercase slug when a document needs stable deep links.
268
+ The consumer must keep each supplied `anchorId` unique within the rendered document;
269
+ omitting it retains instance-safe fragment IDs. Article prose supports semantic tables
270
+ with a muted, left-aligned caption and token-bound reading rows.
271
+
272
+ `HelpDirectory` uses public Input and Button controls. The consumer supplies query,
273
+ search commands and mutually exclusive ready, empty, loading or failed results.
274
+ Ready groups need unique IDs and useful topic links. Keep the query on failure,
275
+ invalidate old results after a newer query/route and never interpret a successful
276
+ search as a support submission. The separate contact action is a real supplied route.
277
+ Set `search.action` for a native GET fallback before hydration, and optionally set
278
+ `search.queryName` when the query parameter is not `q`. Hydrated submission prevents
279
+ the native navigation and calls the controlled search callback.
280
+
281
+ `PublicAvailability` displays a public-safe closed, restricted, sign-in, unavailable
282
+ or loading projection. The product supplies the reason, permitted recovery links
283
+ and retained intent. Do not infer authorization from query parameters or render an
284
+ old private action during loading. No waitlist, membership or legal document exists
285
+ merely because the recipe renders.
286
+
287
+ The nine historical `marketing.tsx` values are removed from this candidate public
288
+ API. Their original examples remain privately under `stories/legacy-support/`.
289
+ NeighborhoodLanding replaces MarketingHero/ValueHypothesisBlock/HowItWorksSteps;
290
+ PublicArticle replaces DocumentPage/DocumentSection/DocumentVersionNotice and can
291
+ show a supplied notice; the controlled app-patterns SupportIntake replaces the
292
+ inert SupportIntakeForm/SupportReceivedState. The removal manifest is
293
+ `design-system/retired-web-exports.json` in the authoring repository. Retirement
294
+ does not close the complete product responsibilities or confer acceptance.
295
+
296
+ `PublicDocumentDialog` is the controlled document reader for policy, privacy and other
297
+ reference content opened from a form. Import `@super-ic/web-patterns/public-content.css`.
298
+ Supply `open`, `onOpenChange`, `title`, `description`, `contentLabel`, `returnLabel` and
299
+ trusted React prose as children. Put h3 headings inside its sections. The viewport
300
+ layout keeps the heading and return action visible while the prose scrolls. It uses
301
+ the public Sheet focus behavior and restores the opener; allow Base UI's scheduled
302
+ focus-guard handoff before asserting the resulting target. Place the consumer's public
303
+ PortalContainerProvider inside the active tenant/theme scope. Opening or closing the
304
+ reader must not accept any consent or submit/clear the form. Document validity,
305
+ publication status and authorization remain product responsibilities.
306
+
307
+ ### Powered by SuperIC
308
+
309
+ Import `PoweredBySuperIC` from `@super-ic/web-patterns` or its `/powered-by-superic` subpath. The normal `@super-ic/web-patterns/tailwind.css` aggregate includes its styling automatically; the dedicated `@super-ic/web-patterns/powered-by-superic.css` subpath remains available with the shared foundation stylesheet. The exact approved outlined wordmark is provided by the peer package `@super-ic/brand-contracts/superic-logo`.
310
+
311
+ The neutral attribution preserves `href`, `variant` (`auto`, `light`, `dark`), `size` (`sm`, `md`), `label`, `source`, and `className`. Auto uses the nearest inherited semantic theme without client state or SVG swapping. Sizes preserve 14px/18px logos with 11px/12px labels. The small label is supplementary attribution, not an instruction or form label. Explicit variant secondary text uses the existing readable semantic role. HTTP(S) and root-relative destinations are accepted; referral parameters preserve existing query fields and hashes. External-link target behavior is `_blank` with `noopener noreferrer`.
@@ -0,0 +1,23 @@
1
+ {
2
+ "schema": "superic.component-contract/v1",
3
+ "id": "contact-section",
4
+ "status": "candidate",
5
+ "package": "@super-ic/web-patterns",
6
+ "export": "ContactSection",
7
+ "publicImport": "@super-ic/web-patterns/contact-section",
8
+ "cssImport": "@super-ic/web-patterns/contact-section.css",
9
+ "origin": {
10
+ "implementation": "Original implementation of the root functional and layout brief.",
11
+ "referenceIntake": "design-system/intake/contact2.json",
12
+ "distributionReview": "pending",
13
+ "note": "An original implementation does not itself establish redistribution clearance for the referenced vendor material."
14
+ },
15
+ "purpose": "A controlled contact introduction and form presentation recipe.",
16
+ "imports": ["@super-ic/primitives/button", "@super-ic/primitives/input", "@super-ic/primitives/textarea", "@super-ic/primitives/label", "@super-ic/primitives/card"],
17
+ "consumerOwns": ["copy", "field values", "validation", "submission transport", "approved media"],
18
+ "recipeOwns": ["responsive composition", "field labels", "state presentation", "focus management"],
19
+ "states": ["idle", "invalid", "submitting", "success", "failure", "unavailable"],
20
+ "invalidState": "Consumers supply a new validationId for each completed validation attempt. The recipe focuses the first invalid field when that ID changes, without moving focus for value edits.",
21
+ "limits": ["No transport is performed.", "No tenant branding or media is supplied.", "The local package candidate exposes a reviewable import; registry publication and accepted consumer integration remain unproven."],
22
+ "accessibility": ["The section has an instance-safe accessible heading.", "Invalid state focuses the first invalid field for a new validationId.", "Success state receives focus.", "Unavailable state retains supplied contact details.", "Media captions remain meaningful when image loading fails."]
23
+ }
@@ -0,0 +1,162 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "kind": "candidate-recipe-binding",
4
+ "id": "neighborhood-landing",
5
+ "maturity": "candidate",
6
+ "owner": "SuperIC DS",
7
+ "accepted": false,
8
+ "public": {
9
+ "imports": {
10
+ "@super-ic/web-patterns": [
11
+ "NeighborhoodLanding",
12
+ "NeighborhoodLandingProps",
13
+ "NeighborhoodLandingJoin",
14
+ "NeighborhoodLandingLink",
15
+ "NeighborhoodLandingExample",
16
+ "NeighborhoodLandingStep",
17
+ "NeighborhoodLandingMedia"
18
+ ]
19
+ },
20
+ "css": [
21
+ "@super-ic/foundation/tokens.css",
22
+ "@super-ic/primitives/tailwind.css",
23
+ "@super-ic/web-patterns/neighborhood-landing.css"
24
+ ],
25
+ "dependencies": [
26
+ "@super-ic/primitives/button",
27
+ "@super-ic/primitives/tabs",
28
+ "@super-ic/primitives/accordion",
29
+ "@super-ic/icon-contracts"
30
+ ]
31
+ },
32
+ "source": [
33
+ "src/neighborhood-landing.tsx",
34
+ "css/neighborhood-landing.css",
35
+ "src/public-content.tsx",
36
+ "css/public-content.css",
37
+ "src/editorial-image.tsx"
38
+ ],
39
+ "tokens": [
40
+ "--background",
41
+ "--border",
42
+ "--brand-accent-quiet",
43
+ "--foreground",
44
+ "--muted-foreground",
45
+ "--primary-foreground",
46
+ "--radius-card",
47
+ "--radius-card-inset",
48
+ "--radius-xl",
49
+ "--radius-xs",
50
+ "--ring",
51
+ "--space-unit",
52
+ "--surface",
53
+ "--surface-2",
54
+ "--type-body-large-line-height",
55
+ "--type-body-large-size",
56
+ "--type-body-medium-family",
57
+ "--type-body-medium-line-height",
58
+ "--type-body-medium-size",
59
+ "--type-body-small-line-height",
60
+ "--type-body-small-size",
61
+ "--type-caption-size",
62
+ "--type-display-large-family",
63
+ "--type-display-large-size",
64
+ "--type-display-large-tracking",
65
+ "--type-display-large-weight",
66
+ "--type-display-small-family",
67
+ "--type-display-small-line-height",
68
+ "--type-display-small-size",
69
+ "--type-display-small-tracking",
70
+ "--type-display-small-weight",
71
+ "--type-h1-family",
72
+ "--type-h1-line-height",
73
+ "--type-h1-size",
74
+ "--type-h1-tracking",
75
+ "--type-h2-size",
76
+ "--type-h3-family",
77
+ "--type-h3-line-height",
78
+ "--type-h3-size",
79
+ "--type-h3-tracking",
80
+ "--type-h3-weight",
81
+ "--type-numeric-family",
82
+ "--type-overline-size",
83
+ "--type-overline-tracking",
84
+ "--type-overline-weight"
85
+ ],
86
+ "states": {
87
+ "membership": [
88
+ "available",
89
+ "unavailable"
90
+ ],
91
+ "examples": [
92
+ "first",
93
+ "second"
94
+ ],
95
+ "disclosure": [
96
+ "open",
97
+ "closed"
98
+ ],
99
+ "density": {
100
+ "applicable": false,
101
+ "reason": "One container-responsive editorial composition; no density variants."
102
+ },
103
+ "submission": {
104
+ "applicable": false,
105
+ "reason": "Consumer-owned route navigation; no form or command in this recipe."
106
+ },
107
+ "media": [
108
+ "omitted",
109
+ "loaded",
110
+ "failed",
111
+ "src-replaced"
112
+ ]
113
+ },
114
+ "stories": [
115
+ "candidates-neighborhood-landing--sandbrock",
116
+ "candidates-neighborhood-landing--dark",
117
+ "candidates-neighborhood-landing--joining-available",
118
+ "candidates-neighborhood-landing--long-content",
119
+ "candidates-neighborhood-landing--narrow-container"
120
+ ],
121
+ "testFile": "stories/candidates/neighborhood-landing.browser.test.ts",
122
+ "requirements": [
123
+ {
124
+ "id": "LANDING-01",
125
+ "behavior": "Recognizable object and join action within initial view; correct theme and readable unclipped layout; axe in 375/1280 and light/dark."
126
+ },
127
+ {
128
+ "id": "LANDING-02",
129
+ "behavior": "Keyboard tabs expose each complete example without simultaneous duplicate content."
130
+ },
131
+ {
132
+ "id": "LANDING-03",
133
+ "behavior": "Skip and join links move focus to correct sections; closed state contains no application link."
134
+ },
135
+ {
136
+ "id": "LANDING-04",
137
+ "behavior": "Available join uses actual consumer href; fixture previews destination and restores focus, without claiming account creation."
138
+ },
139
+ {
140
+ "id": "LANDING-05",
141
+ "behavior": "Disclosure keyboard behavior, correct fee text and distinct privacy/help routes, themed open-state axe."
142
+ },
143
+ {
144
+ "id": "LANDING-06",
145
+ "behavior": "Long text and nested narrow container reflow; all visible navigation/tab targets reach 44px."
146
+ },
147
+ {
148
+ "id": "LANDING-07",
149
+ "behavior": "Reduced motion retains content and interaction."
150
+ },
151
+ {
152
+ "id": "LANDING-08",
153
+ "behavior": "Optional informative hero, possibility, example and article media reserve supplied dimensions; failures both before and after hydration hide only that image and source replacement restores it. Media remains illustrative and creates no availability authority."
154
+ }
155
+ ],
156
+ "proof": {
157
+ "state": "not-accepted",
158
+ "execution": "External candidate report required; this file is a binding, not an execution receipt.",
159
+ "integration": "Coordinator must project into canonical catalog and bind final source/package hashes before acceptance."
160
+ },
161
+ "agentGuidance": "README.md#neighborhoodlanding-candidate"
162
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "version": "0.1.6",
4
+ "status": "candidate-pending-product-proof",
5
+ "source": "packages/web-patterns/src/public-content.tsx",
6
+ "imports": [
7
+ "@super-ic/web-patterns",
8
+ "@super-ic/web-patterns/public-content.css"
9
+ ],
10
+ "contracts": {
11
+ "PublicArticle": {
12
+ "anchorId": "Optional lowercase document slug unique within the page; prefix for stable section fragments. Omission uses unique instance IDs.",
13
+ "sections": "Unique lowercase slugs, trusted semantic prose, optional contextual informative media with alt and dimensions.",
14
+ "tables": "Native table, caption, scoped row/column headers. Token-bound strokes and responsive wrapping.",
15
+ "failure": "Failed media is omitted; adjacent copy and links remain available.",
16
+ "keyboard": "Native disclosure and focusable section targets work without JavaScript.",
17
+ "links": "Prose, back and related links are explicitly underlined so consumer resets cannot erase their affordance."
18
+ },
19
+ "HelpDirectory": {
20
+ "search": "Controlled draft and committed query belong to product. action provides native GET destination, queryName defaults to q.",
21
+ "states": [
22
+ "ready",
23
+ "empty",
24
+ "loading",
25
+ "failed"
26
+ ],
27
+ "keyboard": "Visible search label and Enter submission; product preserves input focus and URL/Back/Forward state.",
28
+ "noJavaScript": "Native GET requires a real route that renders its query. The recipe alone does not implement that route.",
29
+ "limits": "No fabricated network states for a synchronous local catalog; a help result is not a persisted support case.",
30
+ "reset": "Optional reset.href renders a real link for empty-state recovery without JavaScript; omission retains controlled onAction button."
31
+ }
32
+ },
33
+ "proof": [
34
+ "packages/web-patterns/src/public-content.test.tsx",
35
+ "SBR actual installed-package help/fees proof is tracked separately"
36
+ ],
37
+ "acceptance": "Historical receipt hashes are not renewed by this candidate."
38
+ }
@@ -0,0 +1,29 @@
1
+ /* The public presentation marker is emitted by CaseStudyCard. These rules
2
+ deliberately affect only the recovered SuperIC presentation. */
3
+ [data-card-presentation="superic"] [data-slot="case-study-card-surface"] {
4
+ font-family: var(--font-superic-case-study, "Inter Display"), "Inter Display", ui-sans-serif, system-ui, sans-serif;
5
+ }
6
+
7
+ [data-card-presentation="superic"] [data-slot="case-study-card-identity"],
8
+ [data-card-presentation="superic"] [data-slot="case-study-card-headline"],
9
+ [data-card-presentation="superic"] [data-slot="case-study-card-control-label"] {
10
+ color: var(--enterprise-fg);
11
+ font-family: var(--font-superic-case-study, "Inter Display"), "Inter Display", ui-sans-serif, system-ui, sans-serif;
12
+ }
13
+
14
+ [data-card-presentation="superic"] [data-slot="case-study-card-relationship"] {
15
+ color: var(--enterprise-muted);
16
+ font-family: var(--font-superic-case-study, "Inter Display"), "Inter Display", ui-sans-serif, system-ui, sans-serif;
17
+ }
18
+
19
+ [data-card-presentation="superic"] [data-slot="case-study-card-result"] {
20
+ color: var(--enterprise-subtle);
21
+ font-family: var(--font-superic-case-study, "Inter Display"), "Inter Display", ui-sans-serif, system-ui, sans-serif;
22
+ }
23
+
24
+ /* Consumer Tailwind `font-sans` and `font-mono` utilities otherwise reset
25
+ coded-art typography to the tenant defaults. */
26
+ [data-card-presentation="superic"] [data-slot="case-study-card-art"] .font-sans,
27
+ [data-card-presentation="superic"] [data-slot="case-study-card-art"] .font-mono {
28
+ font-family: var(--font-superic-case-study, "Inter Display"), "Inter Display", ui-sans-serif, system-ui, sans-serif;
29
+ }
@@ -0,0 +1,39 @@
1
+ .sic-contact-section { container: contact-section / inline-size; width: min(calc(100% - 2rem), 72rem); margin-inline: auto; color: var(--foreground); font-family: var(--type-body-medium-family); font-size: var(--type-body-medium-size); line-height: var(--type-body-medium-line-height); overflow-wrap: anywhere; }
2
+ .sic-contact-section *, .sic-contact-section *::before, .sic-contact-section *::after { box-sizing: border-box; }
3
+ .sic-contact-section :where(h1,h2,h3,p,dl,dd,figure) { margin: 0; }
4
+ .sic-contact-section :where(h1,h2,h3) { font-family: var(--type-h1-family); text-wrap: balance; }
5
+ .sic-contact-section h1 { font-size: var(--type-display-small-size); line-height: var(--type-display-small-line-height); font-weight: var(--type-display-small-weight); letter-spacing: var(--type-display-small-tracking); }
6
+ .sic-contact-section h2 { font-size: var(--type-h2-size); line-height: var(--type-h2-line-height); font-weight: var(--type-h2-weight); letter-spacing: var(--type-h2-tracking); }
7
+ .sic-contact-section h3 { font-size: var(--type-h3-size); line-height: var(--type-h3-line-height); font-weight: var(--type-h3-weight); }
8
+ .sic-contact-section a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: .22em; }
9
+ .sic-contact-section :where(a,button,input,textarea):focus-visible { outline: 2px solid var(--ring); outline-offset: 3px; }
10
+ .sic-contact-section__layout { display: grid; gap: calc(var(--space-unit) * 8); max-inline-size: 72rem; }
11
+ .sic-contact-section__introduction { display: grid; align-content: start; gap: 1rem; min-inline-size: 0; }
12
+ .sic-contact-section__eyebrow { color: var(--brand-accent-strong, var(--foreground)); font-family: var(--type-overline-family); font-size: var(--type-overline-size); font-weight: var(--type-overline-weight); letter-spacing: var(--type-overline-tracking); line-height: var(--type-overline-line-height); text-transform: uppercase; }
13
+ .sic-contact-section__description { max-inline-size: 62ch; color: var(--muted-foreground); font-size: var(--type-body-large-size); line-height: var(--type-body-large-line-height); }
14
+ .sic-contact-section__media { max-inline-size: 20rem; margin-top: .5rem; }
15
+ .sic-contact-section__media img { display: block; inline-size: 100%; block-size: auto; aspect-ratio: 3 / 2; object-fit: contain; border: 1px solid var(--border); border-radius: var(--radius-card); background: var(--muted); }
16
+ .sic-contact-section__media figcaption { margin-top: .5rem; color: var(--muted-foreground); font-size: var(--type-caption-size); }
17
+ .sic-contact-section__details { display: grid; gap: .75rem; margin-top: 1rem; color: var(--muted-foreground); font-size: var(--type-body-small-size); }
18
+ .sic-contact-section__details > div { display: grid; gap: .25rem; }
19
+ .sic-contact-section__details dt { color: var(--foreground); font-weight: 600; }
20
+ .sic-contact-section__details dd { overflow-wrap: anywhere; }
21
+ .sic-contact-section__details a, .sic-contact-section__hint a { align-items: center; display: inline-flex; min-block-size: var(--control-target-min); min-inline-size: var(--control-target-min); }
22
+ .sic-contact-section__card { border-color: var(--border); background: var(--card); box-shadow: none; }
23
+ .sic-contact-section__form, .sic-contact-section__success { display: grid; gap: calc(var(--space-unit) * 6); }
24
+ .sic-contact-section__form fieldset { display: grid; gap: 1rem; min-inline-size: 0; margin: 0; padding: 0; border: 0; }
25
+ .sic-contact-section__field { display: grid; gap: .5rem; min-inline-size: 0; }
26
+ .sic-contact-section__field [data-slot=input], .sic-contact-section__field [data-slot=textarea] { min-block-size: 44px; }
27
+ .sic-contact-section__field [data-slot=textarea] { min-block-size: 8rem; resize: vertical; }
28
+ .sic-contact-section__hint { color: var(--muted-foreground); font-size: var(--type-caption-size); }
29
+ .sic-contact-section__error, .sic-contact-section__message { color: var(--destructive); font-size: var(--type-body-small-size); }
30
+ .sic-contact-section__form [role=status] { color: var(--muted-foreground); }
31
+ .sic-contact-section__form [data-slot=button], .sic-contact-section__success [data-slot=button] { min-block-size: 44px; white-space: normal; justify-content: center; }
32
+ .sic-contact-section__success:focus-visible { outline: 2px solid var(--ring); outline-offset: 4px; border-radius: var(--radius-card); }
33
+ @container contact-section (min-width: 48rem) { .sic-contact-section__layout { grid-template-columns: minmax(0, 1fr) minmax(20rem, .9fr); gap: calc(var(--space-unit) * 12); align-items: start; } }
34
+ @container contact-section (max-width: 47.99rem) { .sic-contact-section h1 { font-size: var(--type-h1-size); line-height: var(--type-h1-line-height); letter-spacing: var(--type-h1-tracking); } .sic-contact-section h2 { font-size: var(--type-h3-size); line-height: var(--type-h3-line-height); } .sic-contact-section__description { font-size: var(--type-body-medium-size); } .sic-contact-section__media { max-inline-size: 12rem; } }
35
+
36
+ .sic-contact-form { min-inline-size: 0; color: var(--foreground); font-family: var(--type-body-medium-family); font-size: var(--type-body-medium-size); line-height: var(--type-body-medium-line-height); overflow-wrap: anywhere; }
37
+ .sic-contact-form :where(a,button,input,textarea):focus-visible { outline: 2px solid var(--ring); outline-offset: 3px; }
38
+ .sic-contact-form :where(h2,h3,p) { margin: 0; }
39
+ .sic-contact-form :where(h2,h3) { font-family: var(--type-h3-family); font-size: var(--type-h3-size); line-height: var(--type-h3-line-height); font-weight: var(--type-h3-weight); text-wrap: balance; }