diff --git a/.gitignore b/.gitignore index 82b7f232..5605f8a7 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,9 @@ mockups/canvases/*/assets/refs/ # spotify-ios is the exception: prototyping.rescience.com is built from the checkout, so # its captures sit under the replicas on the hosted page only as committed boards. !mockups/canvases/spotify-ios/ref-*.html +# grok-ios shows one capture on the hosted page, under board 14, by request: a native +# screenshot, not a Mobbin one, parked where the replica can be compared against it. +!mockups/canvases/grok-ios/ref-14-grok-bot-sheet.html # Same rule for the walkthrough row and its crops: they show the capture itself. mockups/canvases/*/w[0-9]-*.html mockups/canvases/*/walkassets.json diff --git a/AGENTS.md b/AGENTS.md index 702bd439..1274008e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -58,8 +58,10 @@ Rules inside a canvas folder: hands it back as a vector asset. - Never commit `ref-*.html` or `assets/refs/`. They hold third-party captures, the root `.gitignore` already excludes them, and the - clone-prototype skill rebuilds them. `spotify-ios` is the one exception: - its five `ref-*` boards are committed so the hosted canvas shows them. + clone-prototype skill rebuilds them. `spotify-ios` is the exception: its + five `ref-*` boards are committed so the hosted canvas shows them. So is + `grok-ios/ref-14-grok-bot-sheet.html`, a native screenshot kept under + board 14 for comparison on request. - Put everything else a run makes in `scratch/`. The root `.gitignore` ignores it at any depth. Do not use the repo root or a dot directory. - Give every canvas folder a `README.md`: it carries the evidence, and diff --git a/mockups/canvases/README.md b/mockups/canvases/README.md index a7269f7f..f691cc0d 100644 --- a/mockups/canvases/README.md +++ b/mockups/canvases/README.md @@ -224,6 +224,46 @@ declares a box other than the default 478 x 980. is worthless on grey, and that a blur which monotonically improves a band is hiding a content defect rather than an antialiasing one. The 25 `ref-*` boards are gitignored, so a fresh clone has 29. +- `grok-ios/`: the run to read when the ask is that the icons match the + source exactly, and the one with two devices on one canvas. Fifteen + screens of the Grok iOS app - the Home Screen widget, two pages of the + widget guide, the Voice Settings sheet over the 3D companion scene, the + SuperGrok paywall, the Terms update, the SuperGrok home with its composer, + the voice picker on two voices, the Settings sheet at three scroll + positions, the Terms update signing out, the Introducing Grok Bot sheet + and the App Store page for Grok Bot. Twenty-six boards in three rows: a + token board, a type board and nine evidence boards for 167 tokens, the + fifteen replicas, and the capture of each parked underneath. Ten are + Mobbin captures of a 393pt phone at 2.2417 px/pt; five are native 1206 x + 2622 captures of a 402pt phone at exactly 3 px/pt, rendered and scored on + their own grid with the template's status bar in place of the capture's. + Mean absolute delta is 0.27-1.41 on the three Mobbin screens that are + mostly crops or a drawn illustration, 9.53 on the Voice Settings sheet, + whose companion scene under the sheet is the one ground the capture does + not hold and is a gpt-image-2 edit with the sheet drawn over it, 5.77 on + the paywall (eighteen lines of white type over an inpainted hero), + 0.80-0.95 on the three native white pages, 2.12 on the App Store page, + 3.83 on the Grok Bot sheet, whose card wash, glass and vibrant copy are + drawn in CSS and fitted, and 0.74-1.66 on the voice picker and the settings sheet, + which are flat grounds, white cards and crops. Every icon but three, 66 of + them, is a crop of the capture at its measured ink box rather than a + drawing, because a crop scores 0 by construction and most of the glyphs + are SF Symbols whose outlines cannot be redistributed; the three side + glyphs on the voice screen are SVGs in `assets/icons/`, traced against the + capture's coverage maps by request. Its `README.md` records the inpainting + that clears the type off the crops before they are cut (a Coons fill from + each box's own edges, and a card whose material is un-applied and + re-applied by CSS), the five alphas solved against those patched frames, + the shadows and the glass fitted by sweep, a colour cast on three of the Mobbin exports + taken out with a per-channel lookup before anything was sampled, and the + type sizes that are not on the iOS ladder because the widths said so - + including a title that measured as 400 at 42px by width and turned out to + be 500 at 40.5px by ink mass, which halved its band's delta. The widget + guide's illustration is the one picture that is drawn rather than cropped: + a phone in CSS on 03, and on 02 a sheet over it with the widget card as a + flat rectangle under one fitted `matrix3d`. Fourteen of the fifteen `ref-*` + boards are gitignored; `ref-14-grok-bot-sheet` is committed so the hosted + canvas shows the capture under its replica, and a fresh clone has 27. - `substack-ios/`: the run to read when a translucent bar sits over content the board does not control. Seven screens of the Substack iOS home feed - a note, the Keep reading toast, three notes in a row, your own just-published diff --git a/mockups/canvases/grok-ios/00-design-tokens.html b/mockups/canvases/grok-ios/00-design-tokens.html new file mode 100644 index 00000000..a9268f1d --- /dev/null +++ b/mockups/canvases/grok-ios/00-design-tokens.html @@ -0,0 +1,253 @@ + + + + +Grok iOS - Design Tokens + + + +

Grok iOS

Ten Mobbin captures at 2.2417 px per pt, five native 1206 × 2622 captures at 3 px per pt. One face (SF Pro), one type ladder, surfaces from white and light grey to black and a blurred photograph. Translucent surfaces are materials, not fills: the ground under them is not flat.

Colour

--k-ground#D5D5D5
--k-card#FFFFFF
--k-well#E5E5E5
--k-dim#CBCBCB
--k-sheet#F6F6F6
--k-illo-frame#AAAAAA
--k-illo-screen#FAFAFA
--k-illo-tile#DDDDDD
--k-illo-scrimrgba(0,0,0,.12)
--k-illo-grabber#CCCCCC
--k-night#010101
--k-skip#121212
--k-materialrgba(255,255,255,.067)
--k-discrgba(255,255,255,.17)
--k-price#131313
--k-plan-lo#282828
--k-plan-hi#333536
--k-free-bg#341A0E
--k-scrim-btnrgba(0,0,0,.32)
--k-glassrgba(255,255,255,.09)
--k-grabberrgba(255,255,255,.35)
--k-sheet-vrgba(0,0,0,.40)
--k-side-ink#CDCECF
--k-voice-pill#767676
--k-rec#F09540
--k-page#FFFFFF
--k-chip#F5F5F5
--k-composer#FEFEFE
--k-ctl#F4F3F4
--k-btn#000000
--k-scrim-sheetrgba(0,0,0,.19)
--k-glass-sheetrgba(255,255,255,.5)
--k-grabber-pro#A4A4A6
--k-store-dim#BDBFBC
--k-store-disc#FAFAFA
--k-store-pill#EEEEEF
--k-card-blue#80BEFD
--k-card-pale#E8F3FE
--k-voice-sheet#EDEDEE
--k-nav-well#C8C8C9
--k-avatar#F0F0F0
--k-toggle-off#C5C4C7
--k-material-linergba(255,255,255,.16)
--k-price-line#252525
--k-plan-linergba(255,255,255,.17)
--k-composer-shadowrgba(0,0,0,.07)
--k-composer-line#F9F9F9
--k-sheet-linergba(0,0,0,.45)
--k-store-rule#E7E7E8
--k-illo-card-shadowrgba(0,0,0,.24)
--k-row-linergba(255,255,255,.10)
--k-illo-sheet-shadowrgba(0,0,0,.12)
--k-card-line#EAEAEA
--k-voice-shadowrgba(0,0,0,.11)
--k-ink#000000
--k-ink-inv#FFFFFF
--k-mute#A9A9A9
--k-skip-ink#BBBBBB
--k-foot#838383
--k-free-ink#E07D54
--k-dots#C5C5C5
--k-copy-mute#7F7F7F
--k-placeholder#7E7E7E
--k-sheet-copy#818181
--k-store-mute#8A8A8D
--k-store-val#8E8E92
--k-store-label#B1B1B4
--k-store-link#0088FF
--k-store-pill-ink#CFCFD1
--k-illo-label#333333
--k-illo-sub#5A5A5A
--k-voice-sub#5E5E5E
--k-dot-off#A6A3A7
--k-voice-btn#090709
--k-section-ink#787878
--k-sec-ink#7C7C7C
--k-danger#BE484C
--k-version-ink#C2C2C2

Radius

27px
26px
30px
53.5px
14.3px
26.8px
22px
35px
13px
32px
18px
15px
22px
28px
37px
38px
18px
14px
999px
37.5px
39.5px
25.5px

Metrics

--k-w: 393px
--k-h: 852px
--k-status: 54px
--k-gutter: 16px
--k-gutter-w: 20px
--k-tap: 44px
--k-sheet-top: 59px
--k-sheet-top-v: 403.6px
--k-widget: 162.4px
--k-disc: 40px
--k-w-pro: 402px
--k-h-pro: 874px
--k-sheet-v-blur: 4px
--k-illo-stroke: 10px
--k-status-pro: 59px
--k-row-s: 52px
--k-sheet-blur: 19px
--k-sheet-top-s: 58.7px
+ + diff --git a/mockups/canvases/grok-ios/00a-type-tokens.html b/mockups/canvases/grok-ios/00a-type-tokens.html new file mode 100644 index 00000000..38fac3c8 --- /dev/null +++ b/mockups/canvases/grok-ios/00a-type-tokens.html @@ -0,0 +1,253 @@ + + + + +Grok iOS - Type Tokens + + + +

Grok iOS type

Every size is fitted to a measured width on the board, so several are off the iOS ladder. The evidence rows carry the widths.

Grok--k-t-time · 600 15px/20px
Grok--k-t-widget · 600 19.5px/24px
Grok--k-t-h · 600 17px/22px
Grok--k-t-body · 400 17px/22px
Grok--k-t-feat · 400 17.5px/22px
Grok--k-t-row · 400 16.5px/21px
Grok--k-t-sheet · 600 16px/21px
Grok--k-t-h1 · 500 40.5px/50px
Grok--k-t-h2 · 600 20px/25px
Grok--k-t-sub · 400 13.25px/18px
Grok--k-t-plan · 600 15px/20px
Grok--k-t-unit · 400 15.4px/20px
Grok--k-t-price · 700 20px/26px
Grok--k-t-free · 700 12.5px/14px
Grok--k-t-title · 600 21px/26px
Grok--k-t-copy · 400 14px/19px
Grok--k-t-link · 400 16.75px/22px
Grok--k-t-btn · 600 15.5px/20px
Grok--k-t-hdr · 600 22px/28px
Grok--k-t-chip · 500 14px/20px
Grok--k-t-ask · 400 16px/21px
Grok--k-t-ctl · 400 14px/18px
Grok--k-t-speak · 600 14.5px/18px
Grok--k-t-sheet-h · 600 18.2px/22px
Grok--k-t-sheet-copy · 400 15.25px/20px
Grok--k-t-card · 500 36.5px/44px
Grok--k-t-store-h · 700 21px/26px
Grok--k-t-store-title · 600 21px/26px
Grok--k-t-store-sub · 400 14px/19px
Grok--k-t-store-label · 600 11px/13px
Grok--k-t-store-val · 700 21px/25px
Grok--k-t-store-small · 400 11.5px/14px
Grok--k-t-store-bundle · 400 16px/19px
Grok--k-t-store-body · 400 14px/19px
Grok--k-t-store-btn · 600 13px/16px
Grok--k-t-illo-label · 500 11.5px/14px
Grok--k-t-illo-title · 600 21.25px/26px
Grok--k-t-illo-sub · 400 11.25px/15px
Grok--k-t-illo-pill · 600 15.5px/20px
Grok--k-t-nav · 500 16px/22px
Grok--k-t-voice · 600 16.25px/21px
Grok--k-t-mail · 400 15.9px/20px
Grok--k-t-section · 600 15px/20px
Grok--k-t-voice-sub · 400 16px/21px
Grok--k-t-hint · 400 14.25px/18px
Grok--k-t-version · 400 11.65px/16px
+ + diff --git a/mockups/canvases/grok-ios/00b-evidence.html b/mockups/canvases/grok-ios/00b-evidence.html new file mode 100644 index 00000000..9368123e --- /dev/null +++ b/mockups/canvases/grok-ios/00b-evidence.html @@ -0,0 +1,253 @@ + + + + +Grok iOS - Evidence 1/9 + + + +

Evidence 1/9

One row per token. A token with no evidence is a guess.

--k-font-apple-system,BlinkMacSystemFont,"SF Pro Text","SF Pro Display","Helvetica Neue",Helvetica,Arial,sans-serifrefkit font on 02 'Widget', 05 'SuperGrok' and 'Unlock the full power of Grok': SF Pro top on all three, weak call each time. The platform face
--k-ground#D5D5D501 flat census left of the widget (x 0-20, y 100-240): #D5D5D5 100%
--k-card#FFFFFF01 widget body, col x68 y 80.7-94.5; 02 card interior, row y300 x 60-340; 02 the drawn sheet x 221-311 y 339-352 #FFFFFF on 100% of the flats
--k-well#E5E5E501 pill and both circles: row y125 x 39-172 and row y196 x 39-100 flat #E5E5E5; 02 the drawn widget's pill x 150-163 y 437-472 #E5E5E5 100%
--k-dim#CBCBCB02/03 the band above the sheet, y 0-58.9 flat #CBCBCB: the dimmed parent
--k-sheet#F6F6F602/03 col x100 from 59.0 down and row y700 outside the card: #F6F6F6
--k-illo-frame#AAAAAA02/03 the guide illustration's phone: frame col x 49.7 y 316-428 and island x 163-230 y 232-247 flat #AAAAAA on 100% of the flats
--k-illo-screen#FAFAFA03 inside the drawn frame, x 132-257 y 258-272: #FAFAFA, five under the card, on 100% of the flats
--k-illo-tile#DDDDDD03 tile core x 83-119 y 290-330: #DDDDDD on 99.5% of the flats
--k-illo-scrimrgba(0,0,0,.12)02 the drawn screen under its sheet: #FAFAFA reads #DBDBDB at col x87 y 218-278 and #DDDDDD at col x200 y 252-274, (250-219..221)/250 = .116-.124; the island still reads #A9A9A9, so the scrim lies under it
--k-illo-grabber#CCCCCC02 sheet grabber x 183.8-209.2 y 302.4-306.0: mode #CCCCCC, flat #CDCDCD
--k-night#01010105 flat census x 20-372 at y 718-728 and y 822-838, above the CTA and below the footer: #010101 on 73% and 100% of the flats. The band between the feature card and the plan group is not flat (#171717-#1D1D1D, the smoke's tail) and stays in the crop
--k-skip#12121205 row y83 across the Skip pill 316.1-371.8 reads #111111, col x344 68-98.4 reads #141414; the mean
--k-materialrgba(255,255,255,.067)05 feature card censuses #131313 at y 203-213, 264-276 and 500-518 and #111111 at y 384-396, over a ground of #000000-#030303 outside it: (19-2)/253 = .067 white. At its top edge it reads #333033 with the smoke behind it, so a fill would be wrong and a material is right
--k-discrgba(255,255,255,.17)05 icon discs solved against the patched frame i5 over a ring r 11-18.5 around each glyph: alpha .185/.183/.167/.165/.182 on the five rows
--k-price#13131305 census x 30-190 y 695-715, the blank of the Monthly side of the plan group: #131313 on 99.8% of the flats
--k-plan-lo#28282805 Yearly card, bottom-left blank x 212-228 y 700-712: #282828 on 99.8% of the flats. The card is a diagonal ramp, not a fill: its four corners census 45/52/40/45 mean level (TL/TR/BL/BR)
--k-plan-hi#33353605 Yearly card, top-right blank x 340-358 y 626-636: #333536 on 72% of the flats; the light end of the ramp, laid to top right in the builder
--k-free-bg#341A0E05 FREE badge interior, rows 643-648 x 134-140: #321B10 #371B10 #33170C
--k-scrim-btnrgba(0,0,0,.32)04 X and grid buttons solved against the patched frame i4 over a ring r 9-20: black at .325 (sd .02) and .320; the close disc on the sheet .28
+ + diff --git a/mockups/canvases/grok-ios/00c-evidence.html b/mockups/canvases/grok-ios/00c-evidence.html new file mode 100644 index 00000000..2d522e7f --- /dev/null +++ b/mockups/canvases/grok-ios/00c-evidence.html @@ -0,0 +1,253 @@ + + + + +Grok iOS - Evidence 2/9 + + + +

Evidence 2/9

One row per token. A token with no evidence is a guess.

--k-glassrgba(255,255,255,.09)04 side-stack discs solved against the patched frame i4 over a ring r 10-14.5: white at .089 and .090 over sky, .037 over the cloud where the ground is too bright to resolve
--k-grabberrgba(255,255,255,.35)04 grabber #8B7467 over the patched sheet #412A1C at y 410-412: white at .39/.35/.33 per channel
--k-sheet-vrgba(0,0,0,.40)04 fitted through the drawn sheet at the 4px blur: at .40 the band under the sheet's edge (y 406-428) reads -0.2 signed and the body band (y 606-740) +0.6; .35 leaves both +4, .45 both -5 (README)
--k-side-ink#CDCECF04 ink of the three vector side glyphs: top 3% of each box 203-208 over grounds 163/180/194, so flat, not white at an alpha (.16-.49 would fit)
--k-voice-pill#76767604 the voice pill reads #474747 flat through the sheet (x 300-370, y 772-797, std 3.6): 71/.60 = 118 under the .40 tint
--k-rec#F0954004 the recording dot inside the island, x 215.0-220.8 y 26.8-32.6: #F09540 #F29442 #F09444
--k-page#FFFFFF06 flat census x 40-360 y 520-700, 07 x 100-300 y 200-300: #FFFFFF on 100% of the flats
--k-chip#F5F5F507 suggestion chips y 675-727, census x 20-60 y 680-690 above the bot glyph: #F5F5F5 on 100% of the flats
--k-composer#FEFEFE07 composer interior census x 140-300 y 765-785, right of the placeholder and above the controls: #FEFDFE on 84% of the flats; the 2pt inside its edge reads #F9F9F9, the inset the line token carries
--k-ctl#F4F3F407 the Auto pill x 59.3-134 y 789.3-822, census y 792-797 above its glyph: #F4F3F4 on 98% of the flats; the + and mic discs the same
--k-btn#00000006 Got it pill 20-382 x 730.7-784.7, census x 40-150 y 740-775: #000000 on 100% of the flats; 07 Speak pill, 14 CTA the same
--k-scrim-sheetrgba(0,0,0,.19)14 the Terms page under the sheet: its white reads #CCCCCC on 100% of the flats (x 20-380 y 150-250) and the title's ink stays #000000; (255-204)/255 = .20, the pill under the glass reads #8E8E8E at .19 and #8B8B8B at .20, so .19
--k-glass-sheetrgba(255,255,255,.5)14 the sheet over the scrimmed page: #E6E6E6 over #CCCCCC on 95% of the flats (x 60-340 y 840-855) is white at .51; over the black Got it pill it reads #8E8E8E, white at .56 with the pill's edges blurred in. At the 19px blur the flats read .48 -0.48, .5 +0.74, .52 +1.74, .55 +2.79 signed, and .5 is the alpha the blur was swept at over the pill
--k-grabber-pro#A4A4A614 grabber 172.3-229.7 x 451.3-455.0: #A4A4A6 on 78% of its flats
--k-store-dim#BDBFBC15 the App Store page above the sheet, census x 100-300 y 20-50: #BDBFBC, green one and two levels over red and blue in the capture itself
--k-store-disc#FAFAFA15 the close and share discs (d 45.4 at 15.3 and 341.3, y 77.3-122.7): interior mode #FAFAFA left of the X glyph (x 20-32 y 100-112), rim two capture px of #D7D7D7 at the sides, #EEEEEE at the top
--k-store-pill#EEEEEF15 the Purchased pill 289-382 x 440-472, census x 300-382 y 440-448: #EEEEEF on 94% of the flats
--k-card-blue#80BEFD14 the Grok Bot card 23.3-378.7 x 460.7-660.7: #80BEFD on a 20pt grid over its right half and lower two thirds (x 66-366 y 583-643), every cell within a level
+ + diff --git a/mockups/canvases/grok-ios/00d-evidence.html b/mockups/canvases/grok-ios/00d-evidence.html new file mode 100644 index 00000000..c172d13b --- /dev/null +++ b/mockups/canvases/grok-ios/00d-evidence.html @@ -0,0 +1,253 @@ + + + + +Grok iOS - Evidence 3/9 + + + +

Evidence 3/9

One row per token. A token with no evidence is a guess.

--k-card-pale#E8F3FE14 the pale shape in the card's top-left, cells x 46-106 y 463-513: #E8F3FE, #E8F2FE. Along row 481 it holds 243 to x 108 and falls to 189 by x 208, along column 88 it falls from 240 to 190 over y 521-537, and a darker ring runs 20-30pt outside it (162-167 at x 208 y 505, x 168 y 541). Its ellipse, fade and ring are one fit to the card at 1pt, mean |d| 3.13 to 1.87 over the card outside its crops and title (README)
--k-material-linergba(255,255,255,.16)05 card edge peaks #3B3B3B over one 0.9pt band at y 522.8-523.6 and #5C5A5D at 198.9-199.8 with smoke behind; .16 over #131313 is #393939
--k-price-line#25252505 col x100 618.4-619.3 #252525 and 713.8-714.7 #222222: the plan group's 1pt edge
--k-plan-linergba(255,255,255,.17)05 Yearly card edge peaks #505052 (row 623.5), #565658 (625), #535557 (row 660 right); .17 over the ramp's #333536 top is #565758
--k-composer-shadowrgba(0,0,0,.07)07 the halo under the composer: the page reads #F5F5F5 at y 833, a pt under the card's bottom edge (832.3), and climbs to #FDFDFD by y 848; beside the card (x 392-395, row 780) #FAFAFA-#FCFCFC. Swept with the line at #F9F9F9 over the composer band y 728-862: blur 6px reads 4.63, 4.59, 4.63 at alpha .05, .07, .09 and blur 14px 4.45, 4.39, 4.51
--k-composer-line#F9F9F907 the card's edge, row y 780: x 10.33 #DEDEDE, 10.67 #A9A9A9, 11.0 #DFDFDF, 11.33 #E0E0E0, 11.67 #EFEFEF, then the #F9F9F9 inset; the right edge x 390.3-391.3 #E0E0E0 #E0E0E0 #BABABA #C5C5C5, the top at 737.33-737.67 #EFEFEF #E5E5E5 and the bottom at 832.0-832.3 #DBDBDB #E6E6E6: a line 2 capture px wide, darkest at the sides. Drawn at .67pt any grey is too dark, because the halo carries the edge: swept #A9A9A9 to #FFFFFF over the band y 728-862, #A9A9A9 5.25, #E4E4E4 4.59, #EEEEEE 4.48, #F6F6F6 4.40, #F9F9F9 4.39, #FFFFFF 4.41
--k-sheet-linergba(0,0,0,.45)14 the sheet's outline, row y 600: x 7.33 #9A9A9A and 7.67 #696969 over a scrim of #C0C0C0 beside it, x 394.0 #696969 and 394.33 #9A9A9A on the right; two capture px of black at .45 mean over #C0C0C0 (.25 and .59), and the scrim beside it is #C0C0C0-#C4C4C4 against #CCCCCC away from it, the sheet's own soft shadow
--k-store-rule#E7E7E815 the rules at y 278.67 and 366.67 x 20-402 and the three column separators at x 124.67, 229.67, 334.67 y 305.7-339.7: one capture px, #E7E7E8 on 100% of the pixels, no solve needed at 3 px/pt
--k-illo-card-shadowrgba(0,0,0,.24)02 the drawn widget card's halo: col x 176.8 climbs #FCFBFC to #E9E9E9 over the 21pt above its top edge, row y 455 #F9F9F9 to #E5E5E5 over the 20.5pt left of it, row y 473 #E2E2E2 to #FEFEFE over 20pt to the right: 22-29 levels at the edge. One box-shadow swept dy 0-8 / blur 14-44 / alpha .12-.30 over the 25pt above the card: minimum .85 at 4px 28px .24, 0 28px .18 costs .1, 4px 20px .18 costs 2.6
--k-row-linergba(255,255,255,.10)04 the row cards are a 1pt line and no fill: coverage solve over x 230-300 of both rows' top and bottom edges (486.8, 537.7, 549.3, 600.3), white at .087-.114, and .06-.14 on their sides, mean .10; inside a row reads #42401C against #423F19 outside
--k-illo-sheet-shadowrgba(0,0,0,.12)02 above the drawn sheet's top edge 299.1, col x200: #DDDDDD to 274.6, #DADADA to 285.3, #D7D7D7 to 292.4, #D4D4D4 to 298.7, nine levels over 46pt on top of the scrim. One box-shadow swept blur 12-56 / alpha .05-.20 over that band: minimum 1.51 at 24px / .12, 40px / .08 costs .2
+ + diff --git a/mockups/canvases/grok-ios/00e-evidence.html b/mockups/canvases/grok-ios/00e-evidence.html new file mode 100644 index 00000000..90f4a2f0 --- /dev/null +++ b/mockups/canvases/grok-ios/00e-evidence.html @@ -0,0 +1,253 @@ + + + + +Grok iOS - Evidence 4/9 + + + +

Evidence 4/9

One row per token. A token with no evidence is a guess.

--k-ink#00000001 'Grok' and icon core; 02/03 body ink core #010101; 05 CTA label
--k-ink-inv#FFFFFF05 title and feature titles ink core #FFFFFF; 04 title reads #FDF8F4 through the warm blur
--k-mute#A9A9A905 feature subtitles #ACA9AB and #A5A4A5, 'Monthly' #A6A6A7, '/year' and '$25 /month' #ACACAC: one grey, four readings, the mean
--k-skip-ink#BBBBBB05 'Skip' ink core #B8B8B8-#BBBBBB
--k-foot#83838305 footer line ink core, x 34.8-358.2 y 805-817
--k-free-ink#E07D5405 FREE ink core (brightest 2%) inside x 135-180 y 645-662
--k-dots#C5C5C502/03 page dots, mode of each 6.2pt disc: #C4C4C4-#C5C5C5
--k-copy-mute#7F7F7F06 body ink core on a grey-only window, 'review them.' x 200-245 y 482-493: #7F7F7F; a window that takes in the black 'Terms of Service' span reads the span's pixels, not the grey
--k-placeholder#7E7E7E07 'Ask Anything' ink core x 27-121 y 755-770
--k-sheet-copy#81818114 the three body lines under 'Introducing Grok Bot', a plus-darker grey: each ink pixel is the ground under it plus this minus white, against the capture's ground at its 97th percentile over x 60-330 every 2pt of y 704-766 (228 at 704, 146 at 752). Line 1's core over 227 reads #5B5B5B and line 3's over 146 #0E0E0E. Swept over the copy (x 20-390 y 700-770): #727272 9.30, #7C7C7C 8.52, #818181 8.32, #868686 8.37, #8C8C8C 8.50
--k-store-mute#8A8A8D15 'AI agents that do real work' (x 155-326 y 173-187), 'News', 'Version 1.8.0', '1d ago' and the chevron: ink core #8A8A8D on each
--k-store-val#8E8E9215 '4.9' x 52-84 y 318-334 ink core #8E8E92; '18+', '#19', 'Years', 'Productivity', 'X Corp' and the stars the same to a level
--k-store-label#B1B1B415 '3.3K RATINGS' x 30-107 y 295-303: ink core #B1B1B4
--k-store-link#0088FF15 'more' x 350-382 y 638-647 and the cloud glyph x 157-183 y 231-256: ink core #0088FF on both
--k-store-pill-ink#CFCFD115 'Purchased' x 302-369 y 451-461 on the #EEEEEF pill: ink core #CFCFD1
--k-illo-label#33333302 'Grok' beside the drawn app icon, x 98-124 y 321-330: ink core #333333
--k-illo-sub#5A5A5A02 'Quickly start a new chat with Grok.' x 104-289 y 388-398: ink core #5A5A5A; the title above it (x 174-219 y 361-377) and the pill's 'Grok' (x 192-227 y 450-465) core #000000 and #080808, the ink token
--k-r-phone52pxiPhone 14 Pro/15/16 display corner, this repo's stand-in
--k-r-widget27px01 widget corner insets 21.3/12.4/8.4/2.1 at 0.7/3.7/6.7/15.7 down: r 27
--k-r-card26px02 card corner insets 16.2/12.2/8.6/5.1/2.4 at 2/4/7/11/16 down: r 26
--k-r-sheet30px02 sheet corner insets 20.5/13.8/8.5/4.5 at 2.1/5.1/9.1/14.1 down: r 30
--k-r-illo53.5px03 frame outer arc, leftmost frame pixel 28.5/13.8/5.4pt in at 8/21.4/39.3pt down from 205.9: a 53.5pt circle; the inner arc (32.6/22.8/14.7 at 7.4/16.3/34.1 down from 215.5) is 42.4, the stroke less
--k-r-illo-tile14.3px03 tile corner insets 10.7/6.2/3.6/0.9pt at 0.2/2/4.7/9.1 down from 278.4: r 14.3
--k-r-illo-sheet26.8px02 drawn sheet corner: row y300, 1pt under the top edge at 299.1, white begins at 76.9 against a sheet edge of 55.9: the inset of a 26.8 radius
+ + diff --git a/mockups/canvases/grok-ios/00f-evidence.html b/mockups/canvases/grok-ios/00f-evidence.html new file mode 100644 index 00000000..355392dc --- /dev/null +++ b/mockups/canvases/grok-ios/00f-evidence.html @@ -0,0 +1,253 @@ + + + + +Grok iOS - Evidence 5/9 + + + +

Evidence 5/9

One row per token. A token with no evidence is a guess.

--k-r-illo-card22px02 the widget card's left edge leaves its fitted line 23pt below the top-left corner and the top edge 25pt right of it, at a local scale of .80 down and 1.09 across: 22 in the card's own plane
--k-r-sheet-v35px04 sheet corner insets 20.9/15.1/10.2/6.2/2.7 at 3.4/6.4/10.4/15.4/21.4 down from 403.6, left edge 8.5: r 35
--k-r-row13px04 row card corner: the top edge's 1pt line reaches full coverage 8.1pt in from the left edge (x 28.5 against 20.4), and r - sqrt(2r - 1) = 8.1 at r 13 (12 gives 7.2, 14 gives 8.8)
--k-r-feat32px05 feature card insets 14.9/10.5/6.9/3.8/1.7 at 5/8/12/17/23 down: r 32
--k-r-price18px05 plan group insets 10.9/7.3/4.2/1.7 at 1.6/3.6/6.6/10.6 down: r 18
--k-r-plan15px05 Yearly card insets 7.3/4.5/2.2/0.8 at 2.4/4.4/7.4/11.4 down: r 15
--k-r-chip22px07 chip corner: the first chip's left edge (x 11) reaches full coverage at y 697 and the top edge (675) at x 33, on a 52 tall chip whose ends are not full semicircles; circle fit on the arc r 22
--k-r-composer28px07 composer corner insets 21.3/15.0/10.3/6.3/3.0/1.0 at 1/3/6/10/15/21 down from 737.3, left edge 10.3: r 28
--k-r-sheet-pro37px14 the sheet's top-left corner, where its glass clears the scrim by 25 levels: insets 18.67/9.0/3.33 at 4.7/12.7/21.7 down from its top edge (outline 444.67-445.0, first white row 445.67) against a left edge of 8.0. r 37 gives 18.95/9.1/3.3, 36 gives 18.2/8.6/3.0, 38 19.7/9.6/3.7
--k-r-store38px15 the App Store sheet's corner (top 62, left edge 0): insets 17.7/10.7/6.0/3.3/1.7/0.7 at 5.7/11.3/17/22.7/28.3/34 down; r 38 gives 17.3/10.4/6.4/3.5/1.6/0.5
--k-r-card18px14 the Grok Bot card's bottom-left corner (left edge 23.3, bottom 660.7): insets 7.3/3.7/2.0/0.7 at 3.3/6.7/10/13.3 up; r 18 gives 7.0/3.6/1.9/0.7
--k-r-tip14px07 tooltip corner insets 9.7/7.7/6.0/4.0/1.7 at 1/2/3/5/8 down from 773, left edge 215.3: r 14
--k-r-pill999px01 pill 61.6 tall, 05 Skip 31.4, FREE 27.7 and CTA 56: all fully round (CTA inset 19.5 at 1.5 down fits r 28)
--k-t-time600 15px/20px var(--k-font)iOS status bar clock
--k-t-widget600 19.5px/24px var(--k-font)01 'Grok' 42.4 wide, G 14.3 tall with overshoot; 20px sets 43.3 x 15.0 and 19.5px 42.2 x 14.6
--k-t-h600 17px/22px var(--k-font)02 'Widget' 55.8 wide, 'Home Screen Widget' 166.4 wide, both 16.1 cap-to-descender: 17px; 05 CTA 'Upgrade to SuperGrok' 177.1 wide at the same
--k-t-body400 17px/22px var(--k-font)02/03 body pitch 21.9, F cap to g descender 15.6, line 1 315.8 wide on both boards; 17px sets it 315.8
--k-t-feat400 17.5px/22px var(--k-font)05 'Longer conversations in Chat' 224.8 wide and 'Skip' 32.6: 17px sets 219.3 and 31.3, 17.5px 225.3 and 32.3. Same cap as t-body, wider set
--k-t-row400 16.5px/21px var(--k-font)04 'Select Audio Device' 147.7 x 12.9, 'Microphone Selection' 161.0 x 15.2: 17px sets 150.3/163.3, 16px 143.3/155.7, 16.5px 147.0/159.0
--k-t-sheet600 16px/21px var(--k-font)04 'Voice Settings' V cap 11.6 and 108.4 wide: one size under the nav
+ + diff --git a/mockups/canvases/grok-ios/00g-evidence.html b/mockups/canvases/grok-ios/00g-evidence.html new file mode 100644 index 00000000..b16189bf --- /dev/null +++ b/mockups/canvases/grok-ios/00g-evidence.html @@ -0,0 +1,253 @@ + + + + +Grok iOS - Evidence 6/9 + + + +

Evidence 6/9

One row per token. A token with no evidence is a guess.

--k-t-h1500 40.5px/50px var(--k-font)05 'SuperGrok' 194.0 x 36.1 from S top to p foot with 10332 ink px; swept in the board: 42px regular with .5px tracking hits the width but sets 37.5 tall with 9116 ink px, 40.5px medium with .6px tracking sets 194.0 x 36.1 with 10053 and halves the title band's delta (16.5 to 10.9)
--k-t-h2600 20px/25px var(--k-font)05 'Unlock the full power of Grok' U cap 14.3, 263.2 wide
--k-t-sub400 13.25px/18px var(--k-font)05 feature subtitles W cap 9.4, pitch 21.8 under the title; footer T cap 9.4. Widths disagree on the size: 13px sets the two long subtitles 2.1% narrow (211.0 for 215.5, 230.2 for 235.5) and the footer 1.2% narrow, while '$25 /month' 67.8 x 12.5 is what 13px sets. 13.25px splits it
--k-t-plan600 15px/20px var(--k-font)05 'Monthly' M cap 10.3, 'Yearly' Y cap 10.7
--k-t-unit400 15.4px/20px var(--k-font)05 '/month' 11.2 tall (slash to h ascender), '/year' 13.8 (to y descender); '/month' runs 85.0-133.6 (48.6) and '/year' 270.7-305.0 (34.3), which 15px sets 47.3 and 33.5, 2.5% narrow
--k-t-price700 20px/26px var(--k-font)05 '300' digits 14.7 tall, '30' 15.2, which reads as 21px bold, but '$300' runs 215.8-265.3 (49.5) and '$30' 42.1-80.9 (38.8), which 21px sets 52.2 and 40.6, 5% wide, and the whole string 17.0 tall against 21px's 18.7. 20px carries the width
--k-t-free700 12.5px/14px var(--k-font)05 FREE 29.4 x 8.9; 12px bold sets 28.7 x 8.3, 12.5px 29.7 x 8.7, 13px 30.7 x 9.0
--k-t-title600 21px/26px var(--k-font)06 'Updates to our Terms of Service and' 304.0 wide (x 49.3-353.3), its U cap 15.0 (y 379.0-394.0), cap tops 379.0 and 405.0: a 26 pitch; 21px semibold has a 15.05 cap
--k-t-copy400 14px/19px var(--k-font)06 body: W cap 10.0, cap tops 444.7 / 463.7 / 482.7 (19 pitch), line 2 305.3 wide (48.0-353.3); 14px has a 10.03 cap
--k-t-link400 16.75px/22px var(--k-font)06 'Sign out' 61.7 wide (170.0-231.7), S 12.0 tall with overshoot; 17px sets 63.0, 16.5px 61.1, 16.75px 62.1. The underline is one pt of ink 1.7 under the baseline (y 817.67-818.67)
--k-t-btn600 15.5px/20px var(--k-font)06 'Got it' 39.7 wide (181.3-221.0), G 11.7 tall with overshoot, the 'o' 8.3 wide; 14 'Upgrade to Access' 138.7 wide (132.0-270.7), U 11.0 flat top to overshoot; 16px semibold sets 40.8 and 143.2, 15.5px 39.6 and 138.8
--k-t-hdr600 22px/28px var(--k-font)07 'SuperGrok' 107.7 wide (x 53.3-161.0), 20.0 from S top to p foot, and its glyphs wider than medium's at the same height: S 12.7 against 11.7, G 15.3 against 14.0, k 11.0 against 10.0 on the board at 500; semibold sets 106.7, with .12px tracking 107.7
--k-t-chip500 14px/20px var(--k-font)07 'Build a Bot' 69.0 wide (58.0-127.0), 'Try Finance' 75.0 (198.0-273.0), caps 10.0-10.3; 14px medium sets 69.3 and 74.7
--k-t-ask400 16px/21px var(--k-font)07 'Ask Anything' 93.0 x 14.3, A top to y foot (x 27.3-120.3); 17px (t-body) sets 98.3 x 15.7 on the board, 16px 92.5 x 14.8
--k-t-ctl400 14px/18px var(--k-font)07 'Auto' in the model pill x 93.0-121.3 (28.3), cap 10.0: 14px regular
--k-t-speak600 14.5px/18px var(--k-font)07 'Speak' 42.3 wide (328.7-371.0) on the black pill, S 11.0 with overshoot; 15px semibold sets 43.7, 14.5px 42.3, the same width the 430pt capture gave
--k-t-sheet-h600 18.2px/22px var(--k-font)14 'Introducing Grok Bot' 174.3 wide (28.7-203.0), I cap 13.0 (679.67-692.67), 17.3 to the g foot; 18px sets 172.7 x 17.0 on the board, 18.2px 174.3
--k-t-sheet-copy400 15.25px/20px var(--k-font)14 sheet body cap tops 708.3 / 728.3 / 748.3 (20 pitch), line 1 'AI teammates you can give real work to. Bots can' 338.7 x 14.0 (x 28.0-366.7); 15px sets 333.7 x 13.3 on the board, 15.25px 339.2
+ + diff --git a/mockups/canvases/grok-ios/00h-evidence.html b/mockups/canvases/grok-ios/00h-evidence.html new file mode 100644 index 00000000..e1c4af59 --- /dev/null +++ b/mockups/canvases/grok-ios/00h-evidence.html @@ -0,0 +1,253 @@ + + + + +Grok iOS - Evidence 7/9 + + + +

Evidence 7/9

One row per token. A token with no evidence is a guess.

--k-t-card500 36.5px/44px var(--k-font)14 'Grok Bot' on the card, 136.7 wide (155.3-292.0), cap 26.4 (547.3-573.7): 36px medium sets 135.0 on the board, 36.5px 136.9
--k-t-store-h700 21px/26px var(--k-font)15 'Also Included In' 154.7 x 15.7 (x 20.7-175.3), 'What's New', 'Preview': 21px bold sets 155.0; 20.5px sets 151.3
--k-t-store-title600 21px/26px var(--k-font)15 'Grok Bot' beside the icon, 82.0 x 15.7 (x 155-237, G top to the k foot): the same height as the section heads but 21px bold sets 84.3, 2.7% wide, and 21px semibold 82.2
--k-t-store-sub400 14px/19px var(--k-font)15 'AI agents that do real work' 171.3 wide (154.7-326.0); 14px sets 171.5
--k-t-store-label600 11px/13px var(--k-font)15 '3.3K RATINGS' 76.0 wide (30.3-106.3), 'AGE RATING' 66.3, 'CHART' 38.0, cap 8.0 (295.0-303.0): 11px semibold caps at 7.9
--k-t-store-val700 21px/25px var(--k-font)15 '4.9' 31.3 wide (52-83.3), '18+' 35.0, '#19' 32.3, digit tops 318.7: 21px bold sets 31.5 / 35.2 / 32.0
--k-t-store-small400 11.5px/14px var(--k-font)15 'Years' 29.7 wide (161.7-191.3), 'Productivity' 66.3 (249-315.3): 11.5px sets 29.5 / 66.0; 'News' under the bundle the same size
--k-t-store-bundle400 16px/19px var(--k-font)15 'Apps by SpaceXAI: AI,' cap tops 432.0 and 451.0 (19 pitch), A cap 11.3: 16px has 11.5
--k-t-store-body400 14px/19px var(--k-font)15 'Version 1.8.0' cap 569.3, the three release-note lines at 598.3 / 617.3 / 636.3 (19 pitch), V cap 10.0: 14px
--k-t-store-btn600 13px/16px var(--k-font)15 'Purchased' 66.7 wide (302.3-369.0), P cap 9.3: 13px semibold sets 66.4 with a 9.3 cap
--k-t-illo-label500 11.5px/14px var(--k-font)02 'Grok' beside the app icon: ink 25.9 x 8.9; the stack sets 600 12px to 27.3 x 9.3 and 11.5px to 26.2 x 8.9. Weight and size swept over the word's box: 500 11.5px 7.9, 600 11.5px 13.4, 400 11.5px 10.1
--k-t-illo-title600 21.25px/26px var(--k-font)02 sheet title 'Grok': ink 44.6 x 16.1; 700 21px sets 46.3 x 15.7, 22px 48.7 x 16.3, 600 22px 47.3 x 16.3. Swept over the word's box: 600 21.25px 7.9, 600 21px 8.7, 500 21.5px 9.1, 700 21px 11.2, 700 22px 16.7
--k-t-illo-sub400 11.25px/15px var(--k-font)02 'Quickly start a new chat with Grok.': ink 184.7 x 10.7; 400 11.5px sets 188.7 x 10.7, 12px 195.7 x 11.3. Swept over the line's box in .05 steps: 11.25px 11.3, 11.2px 11.8, 11.3px 13.4, 11.5px 19.8
--k-t-illo-pill600 15.5px/20px var(--k-font)02 'Grok' in the widget pill, unprojected into the card's plane: ink 35.0 x 12.2; 600 16px sets 35.3 x 12.3, and projected back reads 34.8 x 13.8 against the capture's 34.3 x 15.2, a taller face. Swept over the word's box: 15.5px 27.9, 15px 28.3, 16px 34.7, 16.5px 40.1. Set in the card's flat coordinates, before its matrix3d
--k-w393pxiPhone 14 Pro/15/16 logical width
--k-h852pxiPhone 14 Pro/15/16 logical height
--k-status54pxiOS status bar, Dynamic Island devices
--k-gutter16px02 card x 16.1-376.8; 04 buttons x 16.3 and 333.2-377
--k-gutter-w20px05 card x 20.5-372.3, plan group and CTA the same
--k-tap44px02 back disc 44.1 x 43.7; 04 X and grid buttons 43-43.7
--k-sheet-top59px02/03 sheet ground starts at 58.9
--k-sheet-top-v403.6px04 sheet edge, col x100
--k-widget162.4px01 widget 24.1-186.5 both axes
--k-disc40px05 icon discs 40 x 39.8, left edge 40.3
--k-w-pro402pxiPhone 16 Pro logical width: cp6, cp7 and cp13-cp15 are 1206 x 2622 at 3 px/pt
--k-h-pro874pxiPhone 16 Pro logical height
+ + diff --git a/mockups/canvases/grok-ios/00i-evidence.html b/mockups/canvases/grok-ios/00i-evidence.html new file mode 100644 index 00000000..0a906228 --- /dev/null +++ b/mockups/canvases/grok-ios/00i-evidence.html @@ -0,0 +1,253 @@ + + + + +Grok iOS - Evidence 8/9 + + + +

Evidence 8/9

One row per token. A token with no evidence is a guess.

--k-sheet-v-blur4px04 sigma of the blur read off the voice pill's edge, the one sharp edge the capture holds under the sheet: across x 270-300 at y 776/784/792 the ramp from the ground (40) to the pill (74) is 10pt for 10-90%, down x 310/334/358 over y 755-775 it is 8pt, 3.1-3.9 sigma; blur(4px). A sweep cannot read it: it walks to 44px+ because blurring the generated scene away hides the scene's own error (sheet band 13.3 at 44px against 16.3 at 4px)
--k-illo-stroke10px03 the drawn frame's stroke: 10.0pt at the sides (x 45.8-55.8), 9.6 at the top (y 205.9-215.5); one border
--k-status-pro59pxiOS status bar on the 402pt device: 07 clock and cluster ink y 25.7-39.3, x 44.7-366.7, no island on a screenshot; the band the template bar covers on 06-07 and 13-15, and where their scoring starts
--k-monoui-monospace,"SF Mono",Menlo,monospace12 the version line: every glyph of 'VERSION 1.3.42 (BUILD 2776)' sets on one pitch, 6.95pt per character over 27 characters (187.4 wide); a monospaced face, the platform's
--k-voice-sheet#EDEDEE08/09 the voice card's interior, col x196 405-700 and row y520 outside the orb: flat #EDEDEE once the export's cast is taken out (README, colour normalisation). Its 1pt edge reads #FCFAFC, card white
--k-nav-well#C8C8C908/09 the tints under the nav: the menu disc 17.8-60.7 x 63.1-106.9, the Ask pill from 130.3 x 69.4-99.8, the compose disc from 335.4 x 64.0-106.9, all flat #C8C8C9, three levels under dim
--k-avatar#F0F0F010 the profile disc 32.1-91.9 x 180.2-240.4, flat #F0F0F0 around the glyph
--k-toggle-off#C5C4C711 'Open App in Voice Mode' track 300.3-362.7 x 283.0-310.7, flat #C5C4C7 beside its white knob 302.0-339.1 x 285.3-308.9
--k-card-line#EAEAEA10 the rule between rows, x 64.3-360.7 at y 373.9-374.8 and every 52 below: two capture pixels (0.9pt) of #EAEAEA between white rows, no solve needed; drawn 0.9pt tall so the same two pixels carry it
--k-voice-shadowrgba(0,0,0,.11)08/09 the ground beside the card reads 7-11 levels under dim, 3 above it. Swept as 0 4px 16px over the bands beside the card: .10 leaves them +0.6/+0.4, .11 +0.2/-0.0, .12 -0.5/-0.8, .14 -1.6/-2.1; 0 2px 10px and 0 6px 24px score worse at every alpha
--k-voice-sub#5E5E5E08/09 'Upbeat Female', 'Soothing Female' and 'Swipe to explore more voices' ink core #5E5E5E
--k-dot-off#A6A3A708/09 the three inactive page dots, mode #A6A3A7 across y 707.1-713.4; the active one is ink
--k-voice-btn#09070909 the Continue pill 46.5-347.2 x 746.1-796.5, 99.4% flat #090709: the capture's black, 9 levels above btn, which the same export reads on 07
--k-section-ink#78787810/11/12 'General', 'Voice', 'Data & Information', 'Subscription' ink core #787878, three screens
--k-sec-ink#7C7C7C10 'English' core #7C7C7C, the email line #7B7B7B: one secondary ink. 07's placeholder reads #7D7D7D off a 3 px/pt capture, kept apart because that is another device's export
--k-danger#BE484C12 'Sign Out', the label: its 20 most-covered pixels average #BE484C (darkest 2% by luminance #AE4E52). The glyph beside it cores at #E83B43, a brighter red no ink this dark could give, and is its own crop
--k-version-ink#C2C2C212 'VERSION 1.3.42 (BUILD 2776)' ink core #C3C1C3, the lightest type on the set
+ + diff --git a/mockups/canvases/grok-ios/00j-evidence.html b/mockups/canvases/grok-ios/00j-evidence.html new file mode 100644 index 00000000..e376a1c8 --- /dev/null +++ b/mockups/canvases/grok-ios/00j-evidence.html @@ -0,0 +1,253 @@ + + + + +Grok iOS - Evidence 9/9 + + + +

Evidence 9/9

One row per token. A token with no evidence is a guess.

--k-r-voice37.5px08/09 the voice card's top corners: circle fit to its edge 37.5 (err 4.2). Its bottom corners, fit 50.5 with a poor residual, arrive as pixels in the band crop
--k-r-modal39.5px10/11/12 the sheet's top corners, circle fit on the dim/sheet edge 39.5
--k-r-group25.5px10 the settings cards, fit 25.5 at x 16.1 / y 323.1 on the sheet
--k-t-nav500 16px/22px var(--k-font)08/09 'Ask' 26.3 x 12.0, 'Imagine' 56.7 wide: 500 17px sets 28.5 / 59.8, 16px 26.8 / 56.3
--k-t-voice600 16.25px/21px var(--k-font)08/09 'Voice Selection' 115.5 wide, 'Ara' 24.5, 'Eve' 25.0, 09 'Continue' 67.4: 600 17px (t-h) sets 120.4 / 25.9 / 26.3 / 70.5, 16.25px 115.1 / 24.8 / 25.1 / 67.4
--k-t-mail400 15.9px/20px var(--k-font)10 'alexsmith.mobbin+1@gmail.-' 207.4 wide, 'com' 29.4: 400 15px sets 195.8 / 27.7, 15.9px 207.5 / 29.4. 'Alex Smith' above it is t-h: 83.0 against 17px semibold's 82.8
--k-t-section600 15px/20px var(--k-font)10/11/12 'General' 53.1 x 11.2 cap, 'Voice' 37.9, 'Data & Information' 132.0, 'Subscription' 88.8: 600 15.5px sets 55.3 / 39.3 / 136.1 / 91.9, 15px 53.5 / 38.0 / 131.7 / 88.9
--k-t-voice-sub400 16px/21px var(--k-font)08/09 'Upbeat Female' 108.4 x 14.7 (cap to descender), 'Soothing Female' 120.4: 400 16px sets 108.6 / 120.2
--k-t-hint400 14.25px/18px var(--k-font)08 'Swipe to explore more voices' 190.5 x 12.9: 400 14px sets 186.9, 14.25px 190.2
--k-t-version400 11.65px/16px var(--k-mono)12 'VERSION 1.3.42 (BUILD 2776)' 186.9 x 11.6, parentheses to their full height: 12px sets 192.3 x 10.7, 11.65px 186.7; the face's parens are shorter than the capture's, so the width is what this fits
--k-row-s52px10/11 settings rows: cap tops 343.0/394.3/446.5/498.3/550.9 (pitch 51.3-52.6), a three-row card 156.1 tall, rules every 52.0
--k-sheet-blur19px14 the glass sheet's backdrop blur, swept with glass-sheet over the Got it pill seen through the sheet (x 40-360 y 764-784): at .5 white, 14px sits -6.63, 16px -3.76, 18px -0.92, 19px +0.17, 20px +1.57, 28px +11.9; the same band at .52/14px -2.47 and .55/14px +3.12
--k-sheet-top-s58.7px10/11/12 the sheet's edge, col x100: dim to 58.7, the header band from there
+ + diff --git a/mockups/canvases/grok-ios/01-widget.html b/mockups/canvases/grok-ios/01-widget.html new file mode 100644 index 00000000..2d9f3571 --- /dev/null +++ b/mockups/canvases/grok-ios/01-widget.html @@ -0,0 +1,230 @@ + + + + +Grok iOS - Home Screen widget + + + +
9:41
Grok
+ + diff --git a/mockups/canvases/grok-ios/02-widget-guide-add.html b/mockups/canvases/grok-ios/02-widget-guide-add.html new file mode 100644 index 00000000..546ce590 --- /dev/null +++ b/mockups/canvases/grok-ios/02-widget-guide-add.html @@ -0,0 +1,230 @@ + + + + +Grok iOS - Widget guide, step 4 + + + +
9:41
Widget
Home Screen Widget
Grok
Grok
Quickly start a new chat with Grok.
Grok
Find Grok in the list, choose a widget size,
then tap Add Widget.
+ + diff --git a/mockups/canvases/grok-ios/03-widget-guide-jiggle.html b/mockups/canvases/grok-ios/03-widget-guide-jiggle.html new file mode 100644 index 00000000..e4284e6a --- /dev/null +++ b/mockups/canvases/grok-ios/03-widget-guide-jiggle.html @@ -0,0 +1,230 @@ + + + + +Grok iOS - Widget guide, step 1 + + + +
9:41
Widget
Home Screen Widget
From the Home Screen, touch and hold an
empty area until the apps jiggle.
+ + diff --git a/mockups/canvases/grok-ios/04-voice-settings.html b/mockups/canvases/grok-ios/04-voice-settings.html new file mode 100644 index 00000000..5d0d2acd --- /dev/null +++ b/mockups/canvases/grok-ios/04-voice-settings.html @@ -0,0 +1,230 @@ + + + + +Grok iOS - Voice settings + + + +
9:41
Voice Settings
Select Audio Device
Microphone Selection
+ + diff --git a/mockups/canvases/grok-ios/05-supergrok.html b/mockups/canvases/grok-ios/05-supergrok.html new file mode 100644 index 00000000..17e75a95 --- /dev/null +++ b/mockups/canvases/grok-ios/05-supergrok.html @@ -0,0 +1,230 @@ + + + + +Grok iOS - SuperGrok paywall + + + +
9:41
Skip
SuperGrok
Unlock the full power of Grok
Longer conversations in Chat
With Grok 4.1 - Fast & Expert mode
Make more images & videos
With Imagine 1.0 - longer, 720p videos
Longer Voice Mode &
Companion chats
Priority access during
peak times
Early access to new features
Monthly
$30 /month
FREE
Yearly
$300 /year
$25 /month
Upgrade to SuperGrok
Terms of Service · Privacy Policy · Restore Purchases
+ + diff --git a/mockups/canvases/grok-ios/06-terms-update.html b/mockups/canvases/grok-ios/06-terms-update.html new file mode 100644 index 00000000..5c8c1108 --- /dev/null +++ b/mockups/canvases/grok-ios/06-terms-update.html @@ -0,0 +1,230 @@ + + + + +Grok iOS - Terms update + + + +
9:41
Updates to our Terms of Service
and Acceptable Use Policy
We’re updating our Terms of Service and
Acceptable Use Policy. Now’s a great chance to
review them.
Got it
Sign out
+ + diff --git a/mockups/canvases/grok-ios/07-home.html b/mockups/canvases/grok-ios/07-home.html new file mode 100644 index 00000000..f0a94c4a --- /dev/null +++ b/mockups/canvases/grok-ios/07-home.html @@ -0,0 +1,230 @@ + + + + +Grok iOS - SuperGrok home + + + +
9:41
SuperGrok
Build a Bot
Try Finance
Try C
Ask Anything
Auto
Speak
+ + diff --git a/mockups/canvases/grok-ios/08-voice-select-ara.html b/mockups/canvases/grok-ios/08-voice-select-ara.html new file mode 100644 index 00000000..8e928ce0 --- /dev/null +++ b/mockups/canvases/grok-ios/08-voice-select-ara.html @@ -0,0 +1,230 @@ + + + + +Grok iOS - Voice selection, Ara + + + +
9:41
Ask
Imagine
Voice Selection
Ara
Upbeat Female
Swipe to explore more voices
+ + diff --git a/mockups/canvases/grok-ios/09-voice-select-eve.html b/mockups/canvases/grok-ios/09-voice-select-eve.html new file mode 100644 index 00000000..db5a309a --- /dev/null +++ b/mockups/canvases/grok-ios/09-voice-select-eve.html @@ -0,0 +1,230 @@ + + + + +Grok iOS - Voice selection, Eve + + + +
9:41
Ask
Imagine
Voice Selection
Eve
Soothing Female
Continue
+ + diff --git a/mockups/canvases/grok-ios/10-settings.html b/mockups/canvases/grok-ios/10-settings.html new file mode 100644 index 00000000..fab5eb2d --- /dev/null +++ b/mockups/canvases/grok-ios/10-settings.html @@ -0,0 +1,230 @@ + + + + +Grok iOS - Settings + + + +
9:41
Alex Smith
alexsmith.mobbin+1@gmail.-
com
General
Appearance
Customize Grok
Haptics
Widget
App Language
English
Kids Mode
NSFW Preferences
Voice
Companions
Dictation
Settings
+ + diff --git a/mockups/canvases/grok-ios/11-settings-voice.html b/mockups/canvases/grok-ios/11-settings-voice.html new file mode 100644 index 00000000..adf05fa0 --- /dev/null +++ b/mockups/canvases/grok-ios/11-settings-voice.html @@ -0,0 +1,230 @@ + + + + +Grok iOS - Settings, Voice + + + +
9:41
Companions
Dictation
Open App in Voice Mode
Data & Information
Shared Conversations
Data Controls
Recently Deleted
Terms of Use
Privacy Policy
Report a Problem
Subscription
SuperGrok
Settings
Voice
+ + diff --git a/mockups/canvases/grok-ios/12-settings-bottom.html b/mockups/canvases/grok-ios/12-settings-bottom.html new file mode 100644 index 00000000..99ed9780 --- /dev/null +++ b/mockups/canvases/grok-ios/12-settings-bottom.html @@ -0,0 +1,230 @@ + + + + +Grok iOS - Settings, bottom + + + +
9:41
Data Controls
Recently Deleted
Terms of Use
Privacy Policy
Report a Problem
Subscription
SuperGrok
Sign Out
VERSION 1.3.42 (BUILD 2776)
Settings
+ + diff --git a/mockups/canvases/grok-ios/13-terms-loading.html b/mockups/canvases/grok-ios/13-terms-loading.html new file mode 100644 index 00000000..00679d2b --- /dev/null +++ b/mockups/canvases/grok-ios/13-terms-loading.html @@ -0,0 +1,230 @@ + + + + +Grok iOS - Terms update, signing out + + + +
9:41
Updates to our Terms of Service
and Acceptable Use Policy
We’re updating our Terms of Service and
Acceptable Use Policy. Now’s a great chance to
review them.
Sign out
+ + diff --git a/mockups/canvases/grok-ios/14-grok-bot-sheet.html b/mockups/canvases/grok-ios/14-grok-bot-sheet.html new file mode 100644 index 00000000..a845091f --- /dev/null +++ b/mockups/canvases/grok-ios/14-grok-bot-sheet.html @@ -0,0 +1,230 @@ + + + + +Grok iOS - Introducing Grok Bot + + + +
Updates to our Terms of Service
and Acceptable Use Policy
We’re updating our Terms of Service and
Acceptable Use Policy. Now’s a great chance to
review them.
Got it
Sign out
9:41
Grok Bot
Introducing Grok Bot
AI teammates you can give real work to. Bots can
sign in to your tools, use them just like you do,
and come back with finished work.
Upgrade to Access
+ + diff --git a/mockups/canvases/grok-ios/15-app-store.html b/mockups/canvases/grok-ios/15-app-store.html new file mode 100644 index 00000000..da01e81b --- /dev/null +++ b/mockups/canvases/grok-ios/15-app-store.html @@ -0,0 +1,230 @@ + + + + +Grok iOS - App Store, Grok Bot + + + +
9:41
Grok Bot
AI agents that do real work
3.3K RATINGS
AGE RATING
CHART
DEVELOPER
4.9
18+
#19
Years
Productivity
X Corp
Also Included In
Apps by SpaceXAI: AI,
news, videos, social me…
News
Purchased
What’s New
Version 1.8.0
1d ago
- Added select-and-copy on message text
- Added a confirm step when sharing a bot as a
template
more
Preview
+ + diff --git a/mockups/canvases/grok-ios/README.md b/mockups/canvases/grok-ios/README.md new file mode 100644 index 00000000..31ceeb8c --- /dev/null +++ b/mockups/canvases/grok-ios/README.md @@ -0,0 +1,537 @@ +# Grok, iOS + +Fifteen screens of the Grok iOS app: the Home Screen widget on the system +widget gallery ground, two pages of the in-app widget guide (the first and +the last step), the Voice Settings sheet over the 3D companion scene, the +SuperGrok paywall, the Terms update interstitial with its Got it pill and +again with a spinner in the pill, the Introducing Grok Bot sheet over the +Terms page, the App Store sheet for Grok Bot, the SuperGrok home with its +composer, the voice picker on two of its voices, and the Settings sheet at +three scroll positions. 01–05 and 08–12 are Mobbin captures of a 393pt +phone; 06, 07 and 13–15 are native captures of a 402pt one. Twenty-six +boards in three rows, plus fifteen more that park each capture under its +replica. The rows run in flow order, so 13–15 sit between 06 and 07: the +spinner and the two Grok Bot sheets follow the Terms update they come from. +A board's number is the capture it was built from and does not move. + +| # | Board | What it shows | +| --- | --- | --- | +| 00 | `design-tokens` | The 167 tokens, as one `:root` block | +| 00a | `type-tokens` | The type ladder, one row per size | +| 00b–00j | `evidence` | One row per token, with the measurement behind it | +| 01 | `widget` | The medium Home Screen widget on the gallery's grey | +| 02 | `widget-guide-add` | "Find Grok in the list, choose a widget size, then tap Add Widget.", dot 4 | +| 03 | `widget-guide-jiggle` | "From the Home Screen, touch and hold an empty area until the apps jiggle.", dot 1 | +| 04 | `voice-settings` | The Voice Settings sheet over the companion scene, recording | +| 05 | `supergrok` | The SuperGrok paywall: five features, two plans, the CTA | +| 06 | `terms-update` | "Updates to our Terms of Service and Acceptable Use Policy", Got it, Sign out | +| 07 | `home` | SuperGrok home: the header, three suggestion chips, the composer with Auto and Speak | +| 08 | `voice-select-ara` | The voice picker on Ara, "Upbeat Female", dot 1, "Swipe to explore more voices" | +| 09 | `voice-select-eve` | The voice picker on Eve, "Soothing Female", dot 2, the Continue pill | +| 10 | `settings` | The Settings sheet: profile card, General, the top of Voice | +| 11 | `settings-voice` | Settings scrolled to Voice, Data & Information, Terms, Report, Subscription | +| 12 | `settings-bottom` | The bottom of Settings: Sign Out, the xAI mark, the version line | +| 13 | `terms-loading` | The Terms update with a spinner in the Got it pill | +| 14 | `grok-bot-sheet` | "Introducing Grok Bot" over the dimmed Terms page: the card, three lines, Upgrade to Access | +| 15 | `app-store` | The App Store sheet for Grok Bot: ratings, the bundle, What's New, previews | + +## How close it lands + +Mean absolute delta against the captures, in levels of 255, over the window +described below: + +| Screen | Δ | +| --- | --- | +| 01 Widget | 0.27 | +| 02 Widget guide, step 4 | 1.41 | +| 03 Widget guide, step 1 | 1.04 | +| 04 Voice settings | 9.53 | +| 05 SuperGrok | 5.77 | +| 06 Terms update | 0.95 | +| 07 Home | 0.80 | +| 08 Voice selection, Ara | 0.75 | +| 09 Voice selection, Eve | 0.74 | +| 10 Settings | 1.50 | +| 11 Settings, Voice | 1.66 | +| 12 Settings, bottom | 1.06 | +| 13 Terms update, loading | 0.92 | +| 14 Introducing Grok Bot | 3.83 | +| 15 App Store, Grok Bot | 2.12 | + +The spread is what the pixels are. On 01 most of the frame is a crop of the +capture or a flat ground the census read to the level, and the type on it is +one nav title and two lines of body. 04 is the one screen whose ground is +generated (the section below): its 9.53 is nearly all the companion's body +under the sheet, where the gpt-image-2 body is narrower than the blurred one +the capture shows (the worst 40pt blocks, 38 at x 140–160 y 559, are the +hoodie's edges), while the sheet's type, rows and discs on top of it sit at +the same numbers as before; as a crop of the capture the screen read 1.00. +02 and 03 carry the guide illustration, and it is drawn, not cropped (the +section below): as crops the two read 0.90 and 0.89, drawn they read 1.42 +and 1.04, and on 02 the illustration's own box reads 2.28, nearly all of it +inside the perspective card, whose pill label is set in a face the capture's +is taller than. 05 is the only screen where most of what the window sees is +type set by the platform face over an inpainted hero: eighteen lines of it, +white on black, where any sub-pixel disagreement in a glyph edge costs +60–100 levels on that pixel. Split into glyph and ground, the title band +reads 66 on its glyph pixels and 3.8 on the rest; the ground under every +line of 05 is within 3–6 of the capture. 06, 07 and 13–15 are scored on +their own pixel grid, 3 px per pt, where a glyph edge a third of a point off +costs less than it does through a 2.2417 downscale. 06, 07 and 13 are white +pages with a few lines of type, and the worst 40pt block on each is type +within a point of its measured box: 'Sign out' at 17.5 on 06 and 20.3 on 13, +06's title at 17.4, 07's header at 19.7. 14 is 13's page under a scrim and a +glass sheet, and its worst blocks are that same title under the scrim at +14.7–16.2; the Grok Bot card, fitted below, reads 2.55 over its box and is no +longer among them. 15's worst blocks are lines of +type at 20–22, the release notes among them, over crops of the icon, the +stars, the bundle and the previews. 08–12 go back through the downscale. The +two voice screens are a flat dimmed ground, a flat card, and one crop each +for the orb and the band under it, so what is left is glyph fringing on +'Imagine' and on the card title, 13 and 12 in their 40pt blocks with the +offset probe at 0. The three settings screens are white cards of 17px type +on a grey sheet; their worst blocks are the profile card's name and email at +18 (offset probe at 0 again) and dense row labels at 10–11, and none is a +placement a blend can see. + +`refkit batch probes.json --against scratch/cap --pt 2.2417` replays the 138 +Phase-1 probes against the renders (the probes on 06, 07 and 13–15 carry +their own `"pt": 3`): 70 colour probes at a mean Δ of 2.6, 53 box probes at +a mean |dw| of 0.35pt and |dh| of 0.22pt, and 15 edge scans. The worst +colour probe is 12's 'Sign Out' at 20: the token is the label's own +most-covered pixels, #BE484C, and the render's core comes back more +saturated (#B93A3F against the capture's #AE4E52) through the same +resampling that darkens every grey ink below. Next is 04's hoodie through +the sheet at 11, the generated body against the capture's; the pill under +the same sheet lands within 2. The seven scans through real edges land on +the capture's own edge to the pixel, the settings sheet's edge at 58.7, 14's +sheet outline and 15's rule among them, and so do the two through 02's drawn +card edge and pill cap; the two through 02's fitted shadows land 3 and 9pt +off, because a scan reports the largest step and inside a smooth ramp that +step moves with one level of noise, so the value behind those two tokens is +the sweep in their evidence rows, not the scan. 07's composer line lands 2pt +high, 736 against 738, for the same reason: with the line at #F9F9F9 the +largest step in the render is the halo's. The five grey-ink probes on 01–05 +read Δ 7–11, the four on 08–12 (the voice sub-line, the section, secondary +and version inks) 6–11, and the two inks inside 02's drawn sheet read Δ 15 +the other way (`illo-label` #333333 replays as #242424), and that is the +scoring, not the ink: the render is downscaled with LANCZOS, whose ringing +puts the brightest 8% of a grey glyph 7 levels *above* the CSS colour +(`mute` #A9A9A9 replays as #B0B0B0), while the capture's blur keeps its +brightest 8% a few levels *below* the true ink. At 3% and 15% the pattern is +the same. The tokens are the capture's own core values and were left alone. +The same replay on the five native screens, where nothing is downscaled, +reads every ink probe at Δ 0 and every fill within 3, the largest 14's scrim +(#CFCFCF against #CCCCCC) and the pill through the glass (#929292 against +#959595). The grey copy on 06 is cored on a grey-only window, because a +window that takes in the black 'Terms of Service' span reads the span's +pixels, not the grey. + +## The diff window + +The captures are 881 × 1910 for a 393 × 852 frame: **2.2417 px per design +pt**, checked on both axes. Renders come out at 3× with `--crop-phone` and +are downscaled to 881 × 1910 with Pillow LANCZOS, the masked corners +composited onto the capture's own pixels, before diffing +(`scratch/run.sh` is the whole chain and also prints the worst 40pt blocks). + +Excluded, all three properties of Mobbin's export: the top 58pt, where +Mobbin composites the Dynamic Island out and the board draws it; the 52pt +corners; the bottom below 838pt, where the export has no home indicator. On +04 the capture does keep the island's contents, an orange recording dot at +x 215–221, and the board draws that dot (`rec`) inside its own island. + +06, 07 and 13–15 come from a 402 × 874 phone at exactly **3 px per pt** +(1206 × 2622, both axes), so their renders need no downscale: +`refkit shoot --scale 3` on the whole board, the phone cut at its offset +inside the bezel ring (147, 72 px, asserted on the ring's colour) to 1206 × +2622, the 52pt corners masked and composited onto the capture +(`scratch/run13.sh`). The phone on these boards is 402 × 874 with no home +indicator, because the captures show none, and it sits on the 478 × 980 +board with 38pt to spare on each side. Excluded: the top 59pt. These +captures do carry a real status bar and Dynamic Island, and the boards do +not replicate them: the ask was to use the template's status bar (9:41, the +template island and glyphs) rather than clone the capture's clock, bell and +right cluster, so nothing above 59pt is compared. 06 and 07 were first built +from 1290 × 2796 captures of a 430pt phone; on request they were rebuilt +from 402pt ones, and every number on them here is the 402pt one. + +08–12 are Mobbin exports again, 881 or 882 × 2000 with a 90px Mobbin footer, +cropped to 881 × 1910 (the 882-wide ones lose their last column), scored +through the same 2.2417 downscale as 01–05. Three of them, cp8, cp9 and +cp12, carry a colour cast the other seven captures do not: at every grey +the red and blue channels sit 3 above the green, so the voice screens' +dimmed ground read #CDCACE where 02's identical ground reads #CBCBCB, and +12's sheet read #F8F6F9 where 11's reads #F6F6F6. A per-channel monotone +lookup, fitted on the elements 12 shares with 11 (the sheet, the cards, the +rule, the row ink, the section ink, the chevron), is applied to those three +captures before anything is sampled or cut, and that is what +`assets/refs/cp8.png`, `cp9.png` and `cp12.png` hold; the originals are in +`scratch/orig/` and the table in `scratch/lut12.npy`. After it the voice +ground reads #CBCBCB, `dim`, and 12 matches 11 within a level everywhere +the two overlap. + +## What is a crop, what is drawn, what is fitted + +**Every icon but seven is a crop of the capture**, not a drawing: 64 of +them, each cut at its measured ink box grown by 1pt and placed back at the +same numbers (the `-ic-` ids in `crops.json`), and that includes the three +inside 02's drawn illustration, the app icon, the close disc and the Grok +mark in the widget's pill. That was asked for explicitly, that the icons +match the source exactly, and a crop is the only asset that scores 0 by +construction. It is also the only honest one: most of these glyphs are SF +Symbols, whose outlines may not be redistributed, so a hand-drawn SVG would +have been a near-copy of a licensed shape that was still measurably wrong. +The cost is that the canvas's inspector names them by image content from +`assets/art/`, not as vector assets. The seven exceptions are the three side +glyphs on 04 and the four marks on 07's chips (the section below). Three of the crops are keyed: the close, +AirPlay and microphone glyphs on 04's voice sheet were cut with the sheet's +blurred ground in their 1pt margin, and now that the sheet is drawn rather +than cropped, `cut()` keeps each one's coverage (the largest channel's (p − +g) / (255 − g) against the median of its margin) as white on alpha, so the +glyph is still the capture's and the ground under it is the board's. + +`scratch/icons.py` is the check that they are: it finds every placed crop +and inline SVG in the boards (107 placements, the chevron counted each time +it is set) and scores each one's window against the capture, with a shift +search of ±4 capture pixels. Every placement lands within one capture pixel +of the capture's own glyph. A crop's shape is the capture's by construction; +the seven vectors' are measured, in the section below. +`art()` places each crop on the pixels `cut()` took rather than at the pt +box: a box like 291.5pt on a 3px/pt capture is not a pixel edge, and a crop +set there was resampled by half a pixel on the way back. On 06, 07 and +13–15, where the render shares the capture's grid, that snap makes every +icon an exact copy, Δ 0.0 over its ink at offset 0 (on the first, 430pt 07 +the mic, the Auto rocket and the bank glyph read 14–26 before it). On the +Mobbin screens the render is shot at 3px/pt and downscaled to 2.2417, two +grids that share no edge, so a crop's ink reads Δ 5–25 through that chain at +whatever sub-pixel phase it lands on; the montages in `scratch/icons/` show +the three columns, capture, render and difference, and the difference is a +one-pixel ring on every edge and nothing inside it. + +### Seven vector icons + +The focus, hanger and trash glyphs in 04's side discs were asked for as +vectors, so each is an SVG in `assets/icons/04-.svg` whose `viewBox` +is its measured ink box in pt (`345.2 129.3 19.8 19.8`, `343.8 180.6 22.1 +18.9`, `347 233.6 16.7 18.5`), inlined by `icon()` at the same numbers so +the drawing is 1:1 with the measurement and the inspector names it as a +vector asset. They were traced against the capture's coverage, not by eye: +each box's local ground is a 15px median (a stroke is 3-4px), coverage is +(p − g) / (205 − g), and the row and column sums of that map, the ink area, +a ±4px offset probe and a polar profile for the focus ring were compared +between the render and the capture on every pass. What that settled: + +- The ink is a flat `#CDCECF` (`--x-side-ink`), not white at an alpha: the + top 3% of each box reads 203-208 over grounds of 163, 180 and 194, and + white would need .16-.49 to fit the three. +- The strokes differ per glyph. Focus is 1.7 with a 3.05 dot and four L + brackets whose corner radius is 2.6, the L and not an arc because both + polar profiles dip at the diagonal; the ring's centreline is at r 9.0 in + both. Trash is 1.6 with a 1.4 lid. The hanger is 1.3 with a 2.3 bar, read + through the blue channel because its ground is a cloud within 10 levels of + the ink in luminance; its tail is the left leg, and the right leg stops + short of the stem. +- Ink area, in pt², after the last pass: focus 85.8 capture against 90.6, + trash 100.9 against 102.4, hanger 87.6 against 96.2; the offset probe is at + 0 on all three. The 20pt boxes read 6.5, 4.0 and 6.0 mean Δ, nearly all of + it the generated scene under the glass discs, so the crops' 0 there is + not a number a vector can reach and 04's whole-frame Δ moves from 9.51 to + 9.52. + +The four marks on 07's chips are vectors for the opposite reason: they were +asked for as the original icons, so nothing in them is traced. +`assets/icons/07-{gmail,github,notion,bot}.svg` each carry the publisher's own +artwork, the original's children untouched under one `translate ... scale`, +inside a viewBox that is the box the artwork was fitted to. They replace two +crops, `07-ic-bot` and `07-ic-trio`, now gone from `crops.json` and +`assets/art/`. + +The boxes were fitted, not chosen (`scratch/fit_icons.py`): each source is +rendered with the engine the boards are shot with, and a search over uniform +scale and integer-pixel offset about its own ink box takes the lowest coverage +delta against the capture's pixels. The winners, in pt: + +| mark | box | mean Δ | source | +| --- | --- | --- | --- | +| Grok Bot | 28.333 691.667 18.667 × 18.667 | 10.80 | asvg.app, the logomark | +| Gmail | 317.333 696.333 13 × 9.667 | 5.03 | Wikimedia Commons, Gmail icon (2020) | +| GitHub | 333 695 12.667 × 12.333 | 18.92 | Iconify `logos/github-icon` | +| Notion | 348.333 694.667 12.333 × 13 | 11.95 | Iconify `logos/notion-icon` | + +- The Δ is the board against the capture's own crop of that box grown by 1pt, + and `scratch/marks.py` runs the same ±4 capture-pixel search the crops get: + all four land at offset 0, and a ±12% sweep of the size finds the fitted box + is the best one. A crop scores 0 by construction and published artwork + cannot: GitHub's 18.92 is the largest because the app's invertocat is a + little heavier than the published one at 12.7pt, where every edge is two or + three capture pixels of antialiasing. Two sources were rejected on the same + measurement: Iconify's `logos/google-gmail` draws the 2020 M as a gradient + where the capture has it flat, and `simple-icons:notion` draws the N solid + where the capture has it outlined. +- The three connector marks sit in white avatar circles, d 21.667pt at a + 15.5pt pitch, centres x 324.5 / 340 / 355.5 and y 701, painted right to left + so each circle cuts the mark behind it, the way the capture shows them. A fit + that does not model those circles reads the clipping as shape error, which is + what `scratch/fit_trio.py` is for; the whole 134 × 43 px window of the old + crop now reads 11.33. +- A viewBox is an ink box, so the ink has to land on it. `scratch/make_icons.py` + takes each source's ink box off a 400px raster, and that put three of the + four up to one capture pixel off the box they were fitted to. The correction + is carried in the `translate`, never the viewBox (`scratch/tune.py` sweeps it + in the board itself, in sixths of a point, against the capture): with it the + rendered ink box is the viewBox on all four, and 07's two windows move from + 17.92 and 25.72 to 10.80 and 11.33. +- The marks keep their publishers' colours; only the Grok ball follows + `--x-ink`, through the `currentColor` its logomark already uses. That ball is + also wider than the crop it replaces -- 18.667pt against the 18.04 `07-ic-bot` + was cut at -- so the vector puts back a sliver the crop had lost. + +The pictures under the type are crops too: the smoke hero of 05 (`05-bg`), +the band that carries the voice card's bottom corners and shadow on 08 and +09 (`08-band`, `09-band`, y 700–852) and the header band of the settings +sheet on 10, 11 and 12 (`10-hdr`, `11-hdr`, `12-hdr`, y 54–150). All are +**inpainted crops**, and a reader should not take their pixels as the +capture's where the type was: the generator patches every box of type and +chrome out of the frame before cutting it (a Coons fill from each box's own +four edges, edge profiles smoothed over 9px) so that the CSS type lands on +clean ground. `INPAINT` in `gen.py` lists the boxes; on 04 (whose patched +frame is the top of the generated scene below) that is the nav, the four +side buttons, the grabber, the title, the close disc and both row labels +with their glyphs; on 05 the title, the subtitle, the plan group, the CTA +and the footer. 05's feature card is handled differently: its 6.7% white +material is un-applied inside the card box, its edge, corner arcs, five +discs and nine lines of type are patched, and the CSS card re-applies the +material, so the card's pixels under the type are solved rather than +sampled. On 08 and 09 the patched boxes are the four page dots and the swipe +hint (08) or the Continue pill (09), all drawn again; on 10–12 the +'Settings' title, and on 11 the 'Voice' label that the header's fade runs +through, set again over the crop. What is not patched stays as pixels: the +header material, the close disc and the fade under it on all three settings +screens, 11's ghost of 'NSFW Preferences' scrolling out under that fade, and +12's 'Shared Conversations' row, which sits under the same fade with an ink +of #1C1B1C and would be a flat CSS grey over a gradient the CSS does not +have. Nothing on 13–15 is inpainted: 13's spinner, 14's badge and 15's app +icon, stars, bundle artwork and two preview screenshots are crops cut as +they stand. + +**The companion scene on 04 is generated, and the sheet over it is drawn.** +The capture holds the scene only above the sheet's edge at 403.6; below it +every pixel is the scene blurred and dimmed under the Voice Settings sheet, +and a crop of that (`04-bg` and `04-sheet`, the first version, 1.00) is a +screenshot of the sheet rather than a replica of it. On request the ground +was regenerated and the sheet rebuilt in code. `assets/art/04-scene.png` is +the patched capture above the sheet's edge (i4, so the head, the sky and +the buttons' ground are the capture's pixels) and a gpt-image-2 edit below +it, composed by `scratch/scene4.py` with a 6px blend at the seam. The edit +was made with `POST /v1/images/edits`, the frame as the image and its +sheet box as the mask, the prompt carrying the body's proportions read off +the capture through the blur (down x 130–210: red hoodie y 450–615, dark +shorts 630–670, orange legs 690–730, ground from 750). Nine candidates were +scored through the drawn sheet at the fitted material (mean |Δ| over the +sheet's box, x 8.5–393 y 404–838): three unmasked edits recomposed the +shot and moved the head (13.3–19.6, a seam step of 26 levels), two masked +edits without the proportions kept the head but ended the body at 635 +(15.6 and 14.7, seam steps of 16 and 20), the two with the proportions +scored 16.3 and 14.7 with seam steps of 6 and 20, and two more asking for a +wider hoodie recomposed the body (19.7 and 21.0). The 16.3 with the 6-level +seam is the one shipped; the sub-bands are the band under the sheet's edge +at 8.8, the rows at 19.3, the body at 12.5 and the ground at 12.4 (+11.5 +signed: the generated grass is lighter than the real one). Quality is +`medium`: every `high` request was cut at 60 s by the connection, four +times, sandboxed and not. The three faint voice-mode controls the capture +shows at the bottom left under the sheet (x 33, 89, 145, y 786, 3.6 levels +above the ground) are not drawn; the voice pill at the right is, a +`#767676` pill under the blur at its measured box (288.5–379.6 × +767.4–801.3), so that it reads the capture's `#474747` through the tint. + +The sheet is a `backdrop-filter: blur(4px)` over a `.40` black tint, a +grabber, a title, a close disc and two row cards that are a 1pt white line +at `.10` and no fill (radius 13, solved from where the line reaches full +coverage). Neither the blur nor the tint has a pixel to sample, and the +usual sweep cannot find them here either: with the scene generated, a sweep +walks to 44px and beyond because blurring the scene away hides the scene's +own error (13.3 over the sheet at 44px against 16.3 at 4px), and the pill +edge in the render, the one sharp edge the capture holds under the sheet, +says the blur is 3–4pt of sigma. So the blur is read off that edge, the +tint is the alpha at which the two bands the scene fits best (under the +sheet's edge and over the body) balance in sign at that blur, .40, and the +evidence rows carry both. + +**The guide illustration on 02 and 03 is drawn**, the one picture that is +not a crop or a generation. It was cut from the capture at first (0.90 and 0.89), and it +was redrawn on request so that the boards hold it as code rather than as a +screenshot. 03's is a phone: a 301.6 × 330 frame with a 10pt stroke and a +53.5 corner, a 87 × 25 island, ten 52.2pt tiles on a 65 pitch at a 14.3 +radius, four side buttons, all fading out through a mask whose stops are +the frame column's own fade profile (opacity 1 to .04 over 44pt, read at +8px steps). Frame, screen and tile greys are flat-fill censuses on 100%, +100% and 99.5% of their flats. 02 puts the add-widget sheet over the same +phone: a 12% scrim on the screen (the screen's #FAFAFA reads #DBDBDB and +#DDDDDD under it, the island still reads #A9A9A9, so the scrim lies under +the island), a white sheet at a 26.8 corner with a fitted halo, a 25.4 × 3.6 +grabber, the label, title and sub-line at swept sizes, two blurred grey +blobs where the capture has the next widgets' ghosts, and the widget card +itself, a flat 130 × 90.9 rectangle seen in perspective. Its four edges were +fitted as lines to the capture (top `y = .1355x + 436.67`, bottom +`y = .0908x + 641.72`, left `x = -.0402y + 212.67`, right +`x = .0364y + 459.80` in the crop's own pixels), the corners they meet at +fix a homography, and the card ships as one CSS `matrix3d` with the pill +and its label as flat children the browser projects. The flat aspect of the +card is the one number the capture does not settle: the pill's caps +unproject to circles at any aspect from 1.1 to 1.4, so the aspect was +chosen to make the pill's 'Grok' set at SF Pro's own width-to-ink-height +ratio of 2.86, and the pill and ink boxes are the capture's edges +unprojected through that same matrix. The two shadows are fitted, not +read: the card's `0 4px 28px rgba(0,0,0,.24)` swept over dy 0–8 / blur +14–44 / alpha .12–.30 (minimum .85 over the 25pt above the card; 0 28px .18 +costs .1, 4px 20px .18 costs 2.6), and the sheet's `0 0 24px rgba(0,0,0,.12)` +swept over blur 12–56 / alpha .05–.20 (minimum 1.51 over the 46pt above its +edge; 40px .08 costs .2). The remaining gap on 02 is the pill's 'Grok': the +capture's face sets it 34.3 × 15.2pt in projection where SF Pro at the same +width sets 13.4 tall, a taller face, and no size of SF Pro holds both the +width and the height. + +Two strings on 07 are not fully knowable from the capture. The third +suggestion chip runs off the screen with only 'Try C' visible; its icon +trio is Gmail, GitHub and Notion, which makes the chip Connectors, and the +board sets exactly the visible 'Try C' with the chip clipped at the frame +rather than inventing the rest. One string on 10 is: the Dictation row's +label is cut by the frame, and the board sets it whole and lets the phone +clip it (the Source section). + +Values no pixel holds, fitted rather than read: + +- `material` .067, `disc` .17, `scrim-btn` .32, `glass` .09 and `grabber` + .35 are alphas solved as (capture − patched frame) / (255 − patched frame) + over rings that avoid the glyphs; the evidence rows carry each ring and the + per-row spread. +- The Yearly card is a diagonal ramp, not a fill: its four corners census + 45/52/40/45 mean level, so it ships as `linear-gradient(to top right, + plan-lo, plan-hi)` between the bottom-left and top-right censuses. +- 07's composer edge is a .67pt `#F9F9F9` line under one `box-shadow`, + `0 4px 14px rgba(0,0,0,.07)`. The capture's edge is two capture px wide and + darkest at the sides (#A9A9A9 at x 10.67), but drawn at .67pt any grey is + too dark: swept from #A9A9A9 to #FFFFFF over the band y 728–862, the line + reads 5.25 at #A9A9A9, 4.59 at #E4E4E4, 4.39 at #F9F9F9 and 4.41 at white, + so the halo carries the edge. With the line there, the halo at blur 6 and + 14px by alpha .05–.09 lands 4.39–4.63, 14px at .07 the lowest. +- The voice card's shadow on 08 and 09 is `0 4px 16px rgba(0,0,0,.11)` + over a 1pt white inset edge: the ground beside the card reads 7–11 levels + under `dim` and 3 above it. Three geometries and five alphas were swept + against the 7.5pt bands beside the card and the 23pt above it; .11 leaves + them +0.2 / −0.0 / +0.5 signed, .10 is +0.6 / +0.4, .14 costs 1.6–2.1, + and the other two geometries score worse at every alpha. +- 14's scrim is black at .19 and the sheet over it white at .5 through a + `backdrop-filter: blur(19px)`. The page's white reads #CCCCCC under the + scrim, (255 − 204)/255 = .20, and the Got it pill under the glass reads + #8E8E8E at .19 and #8B8B8B at .20, so .19. The sheet's flats read white at + .51 and the black pill through it .56 with its edges blurred in, so the + blur was swept at .5 over the pill's band (x 40–360 y 764–784): 14px −6.63 + signed, 18px −0.92, 19px +0.17, 20px +1.57, 28px +11.9. At 19px the flats + read −0.48 at .48 and +0.74 at .5. +- 14's sheet starts at 445.3: its outline reads 444.67–445.0 at x 200 and its + first white row 445.67, and the corner's insets give `r-sheet-pro` 37. It + carries a 1pt white inset line at top and bottom and a 4px white glow under + the top edge; over the band y 436–470 the glow is worth .46 and the bottom + line .02 over the screen. +- 14's body copy is iOS's plus-darker vibrancy, not a flat grey: each ink + pixel is the ground under it plus `sheet-copy` minus white, so line 1 reads + #5B5B5B over the sheet's white and line 3 near black over the blurred Got it + pill. Chromium has no plus-darker, so each line is filled through + `background-clip: text` with a vertical ramp of that sum, the ground taken + from the capture every 2pt of y 704–766 at its 97th percentile over x + 60–330. The grey sweep is in the evidence row; blurs of 15 and 23px or glass + at .44 and .56 score the copy worse than 19px at .5 does. +- 14's card is `card-blue` lightening to #6EB5FC over its top 110px, with a + pale ellipse (`card-pale`) in its top-left and a thin ring of #0A84FF at .18 + outside it. The capture's pale shape holds 243 across its left and fades out + over some 60pt to the right, but falls off within 12pt along its bottom, and + its darker ring runs 20–30pt outside that edge rather than on it. So the + ellipse fades along its own width (full to 221.7px, clear by 301.5px) under + `blur(6.3px)`, and the ring is the same ellipse grown by 33.4 with a 12.7px + border under `blur(2.7px)`, both rotated 17.9°. All of it is one + least-squares fit of that construction to the card at 1pt, outside the bot + glyph, its title and the badge: mean |d| 3.13 at the start, 1.87 fitted. The + bottom-left glow fell to .03 in the fit and was dropped. In the browser the + card reads 2.55 against 4.26 before, and ring alphas .10 and .26 read 2.60 + and 2.57. +- `icon.png` is the App Store artwork under the system superellipse mask, the + one asset that is not a crop of a screen. + +## The typeface + +`refkit font` puts SF Pro on top of every title measured, each a weak call, +and the boards ship the platform stack with no width correction. Sizes were +then fitted to measured widths in the real board rather than assumed from +the iOS ladder, and several are not on it: + +- `t-feat` 17.5px and `t-row` 16.5px: the regular-weight strings on 05 and + 04 set 3% wider and 2% narrower than 17px does. +- `t-h1` is **500 at 40.5px with .6px of tracking**, not 400 at 42px. Both + set 'SuperGrok' 194.0 wide; the regular is 37.5 tall with 9116 ink px + against the capture's 36.1 and 10332, the medium is 36.1 and 10053, and + swapping it halved the title band's delta (16.5 → 10.9). +- `t-price` 20px: the digits' cap height reads as 21px, the run width as + 20px, and the run wins (52.2 → 49.5 for '$300', the capture's 49.5). +- `t-sub` 13.25px: the two long feature subtitles want 13.3, the footer + 13.16 and '$25 /month' 13.0, so the token splits them and each lands within + 1.3pt. +- `t-unit` 15.4px for the '/month' and '/year' runs, 2.5% wider than 15px. +- On the 3px/pt screens the fits are finer because the captures are, each a + width on the board against a width on the capture: `t-hdr` is 22px + semibold **with .12px of tracking**, because 'SuperGrok' measures 107.7 + wide where the untracked face sets 106.7 and its S, G and k are a point + wider than medium's; `t-link` 16.75px ('Sign out' 61.7, 17px sets 63.0), + `t-btn` 15.5px semibold ('Got it' 39.7 and 'Upgrade to Access' 138.7 at + one size), `t-ask` 16px, `t-speak` 14.5px, `t-sheet-h` 18.2px, + `t-sheet-copy` 15.25px, `t-card` 36.5px medium ('Grok Bot' 136.7 on the + card, 36px sets 135.0) and, on 15, `t-store-title` 21px semibold where the + section heads are 21px bold ('Grok Bot' 82.0, bold sets 84.3). A left + bearing of 0.7pt is applied to every string on those screens, measured on + the 06 title and body and confirmed on 07's header and chips; the 430pt + boards also dropped every cap top 0.5pt, and on the 402pt captures ten + strings landed 0.3–0.7pt low with it, so the drop is 0. +- On 08–12 the fits are by width again, each on a string the render was + measured against: `t-voice` 16.25px semibold for the voice title, the two + names and 'Continue' (17px sets all four 4% wide), `t-nav` 16px medium for + 'Ask' and 'Imagine', `t-mail` 15.9px for the email, `t-section` 15px + semibold for the group labels, `t-hint` 14.25px for the swipe hint and + `t-version` 11.65px of the platform's monospace face, whose parentheses + are shorter than the capture's (10.3 against 11.6 tall at the matched + width). 'Alex Smith' is `t-h` and every row label `t-body`, both on the + ladder, and every string above lands within 0.9pt of its measured width. + +## What the source itself gets wrong + +- 05's row titles wrap where the app wraps them, mid-phrase: "Longer Voice + Mode &" / "Companion chats" and "Priority access during" / "peak times". + Those are the app's line breaks, transcribed. +- 04's island carries the recording indicator because the capture was taken + mid-session; the widget and guide captures have theirs composited out. + 04 draws no home indicator: down x 196 the capture is grass at y 838–843. +- The '$' on 05's prices is shorter than SF Pro's at any size that matches + the digits: the price probe lands the width to 0.0 and the height 1.3 tall. +- 06, 07 and 13–15 are captures of a 402pt phone, not Mobbin exports, so + they have square corners and a real status bar; the corners are masked and + the bar is the template's by request. +- 10's email is 'alexsmith.mobbin+1@gmail.-' over 'com': the app hyphenates + it inside the domain, and the board sets both lines where they are. +- 10's last row, Dictation, is cut by the frame at 852 with 2.6pt of its cap + and the top of its glyph showing; the board draws the row at its full 52 + and lets the phone clip it rather than moving it. +- Three of the five Mobbin exports of the second batch carry a colour cast + the first batch does not (the diff window section); it was taken out + before sampling, and the tokens are the corrected values. + +## Regenerating + +`python3 gen.py` rewrites the twenty-six boards from `TOKENS`, `crops.json` +and `assets/art/`. With `assets/refs/` present it also re-cuts the art, +which needs Pillow and numpy; without it (a fresh clone, since the captures +are gitignored) it uses the committed crops and needs nothing. Re-cutting +from fresh captures also needs the colour pass described under the diff +window on cp8, cp9 and cp12. Fourteen of the fifteen `ref-*` boards are +gitignored too. `ref-14-grok-bot-sheet` is committed, a native screenshot +under board 14 so the hosted canvas can compare the two, so a fresh clone +has twenty-seven. \ No newline at end of file diff --git a/mockups/canvases/grok-ios/assets/art/01-ic-compose.png b/mockups/canvases/grok-ios/assets/art/01-ic-compose.png new file mode 100644 index 00000000..9ea930e0 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/01-ic-compose.png differ diff --git a/mockups/canvases/grok-ios/assets/art/01-ic-mark.png b/mockups/canvases/grok-ios/assets/art/01-ic-mark.png new file mode 100644 index 00000000..b8db688f Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/01-ic-mark.png differ diff --git a/mockups/canvases/grok-ios/assets/art/01-ic-wave.png b/mockups/canvases/grok-ios/assets/art/01-ic-wave.png new file mode 100644 index 00000000..b7b6e089 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/01-ic-wave.png differ diff --git a/mockups/canvases/grok-ios/assets/art/02-ic-app.png b/mockups/canvases/grok-ios/assets/art/02-ic-app.png new file mode 100644 index 00000000..adee1c8a Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/02-ic-app.png differ diff --git a/mockups/canvases/grok-ios/assets/art/02-ic-back.png b/mockups/canvases/grok-ios/assets/art/02-ic-back.png new file mode 100644 index 00000000..fdee845c Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/02-ic-back.png differ diff --git a/mockups/canvases/grok-ios/assets/art/02-ic-close.png b/mockups/canvases/grok-ios/assets/art/02-ic-close.png new file mode 100644 index 00000000..14d43f05 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/02-ic-close.png differ diff --git a/mockups/canvases/grok-ios/assets/art/02-ic-mark.png b/mockups/canvases/grok-ios/assets/art/02-ic-mark.png new file mode 100644 index 00000000..7d7d398b Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/02-ic-mark.png differ diff --git a/mockups/canvases/grok-ios/assets/art/02-ic-sparkle.png b/mockups/canvases/grok-ios/assets/art/02-ic-sparkle.png new file mode 100644 index 00000000..b46a2592 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/02-ic-sparkle.png differ diff --git a/mockups/canvases/grok-ios/assets/art/03-ic-sparkle.png b/mockups/canvases/grok-ios/assets/art/03-ic-sparkle.png new file mode 100644 index 00000000..0d62bc96 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/03-ic-sparkle.png differ diff --git a/mockups/canvases/grok-ios/assets/art/04-ic-airplay.png b/mockups/canvases/grok-ios/assets/art/04-ic-airplay.png new file mode 100644 index 00000000..ee986137 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/04-ic-airplay.png differ diff --git a/mockups/canvases/grok-ios/assets/art/04-ic-chevron.png b/mockups/canvases/grok-ios/assets/art/04-ic-chevron.png new file mode 100644 index 00000000..790c8786 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/04-ic-chevron.png differ diff --git a/mockups/canvases/grok-ios/assets/art/04-ic-close.png b/mockups/canvases/grok-ios/assets/art/04-ic-close.png new file mode 100644 index 00000000..40a0a99d Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/04-ic-close.png differ diff --git a/mockups/canvases/grok-ios/assets/art/04-ic-grid.png b/mockups/canvases/grok-ios/assets/art/04-ic-grid.png new file mode 100644 index 00000000..d7b2b555 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/04-ic-grid.png differ diff --git a/mockups/canvases/grok-ios/assets/art/04-ic-person.png b/mockups/canvases/grok-ios/assets/art/04-ic-person.png new file mode 100644 index 00000000..abeedf4d Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/04-ic-person.png differ diff --git a/mockups/canvases/grok-ios/assets/art/04-ic-x.png b/mockups/canvases/grok-ios/assets/art/04-ic-x.png new file mode 100644 index 00000000..5aa16d20 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/04-ic-x.png differ diff --git a/mockups/canvases/grok-ios/assets/art/04-scene.png b/mockups/canvases/grok-ios/assets/art/04-scene.png new file mode 100644 index 00000000..cddfbbae Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/04-scene.png differ diff --git a/mockups/canvases/grok-ios/assets/art/05-bg.png b/mockups/canvases/grok-ios/assets/art/05-bg.png new file mode 100644 index 00000000..eb49ba00 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/05-bg.png differ diff --git a/mockups/canvases/grok-ios/assets/art/05-ic-cube.png b/mockups/canvases/grok-ios/assets/art/05-ic-cube.png new file mode 100644 index 00000000..fbd76976 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/05-ic-cube.png differ diff --git a/mockups/canvases/grok-ios/assets/art/05-ic-imagine.png b/mockups/canvases/grok-ios/assets/art/05-ic-imagine.png new file mode 100644 index 00000000..0d710d3a Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/05-ic-imagine.png differ diff --git a/mockups/canvases/grok-ios/assets/art/05-ic-rocket.png b/mockups/canvases/grok-ios/assets/art/05-ic-rocket.png new file mode 100644 index 00000000..3459f471 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/05-ic-rocket.png differ diff --git a/mockups/canvases/grok-ios/assets/art/05-ic-star.png b/mockups/canvases/grok-ios/assets/art/05-ic-star.png new file mode 100644 index 00000000..7cfaef5d Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/05-ic-star.png differ diff --git a/mockups/canvases/grok-ios/assets/art/05-ic-wave5s.png b/mockups/canvases/grok-ios/assets/art/05-ic-wave5s.png new file mode 100644 index 00000000..a825007d Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/05-ic-wave5s.png differ diff --git a/mockups/canvases/grok-ios/assets/art/06-ic-mark.png b/mockups/canvases/grok-ios/assets/art/06-ic-mark.png new file mode 100644 index 00000000..4dae09df Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/06-ic-mark.png differ diff --git a/mockups/canvases/grok-ios/assets/art/07-ic-auto.png b/mockups/canvases/grok-ios/assets/art/07-ic-auto.png new file mode 100644 index 00000000..cbfdcf0e Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/07-ic-auto.png differ diff --git a/mockups/canvases/grok-ios/assets/art/07-ic-bank.png b/mockups/canvases/grok-ios/assets/art/07-ic-bank.png new file mode 100644 index 00000000..451259cb Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/07-ic-bank.png differ diff --git a/mockups/canvases/grok-ios/assets/art/07-ic-close.png b/mockups/canvases/grok-ios/assets/art/07-ic-close.png new file mode 100644 index 00000000..4b597a05 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/07-ic-close.png differ diff --git a/mockups/canvases/grok-ios/assets/art/07-ic-mark.png b/mockups/canvases/grok-ios/assets/art/07-ic-mark.png new file mode 100644 index 00000000..d795d4a6 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/07-ic-mark.png differ diff --git a/mockups/canvases/grok-ios/assets/art/07-ic-mic.png b/mockups/canvases/grok-ios/assets/art/07-ic-mic.png new file mode 100644 index 00000000..9f04b0d8 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/07-ic-mic.png differ diff --git a/mockups/canvases/grok-ios/assets/art/07-ic-plus.png b/mockups/canvases/grok-ios/assets/art/07-ic-plus.png new file mode 100644 index 00000000..69735fc1 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/07-ic-plus.png differ diff --git a/mockups/canvases/grok-ios/assets/art/07-ic-watermark.png b/mockups/canvases/grok-ios/assets/art/07-ic-watermark.png new file mode 100644 index 00000000..d98c05e6 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/07-ic-watermark.png differ diff --git a/mockups/canvases/grok-ios/assets/art/07-ic-wave.png b/mockups/canvases/grok-ios/assets/art/07-ic-wave.png new file mode 100644 index 00000000..5e3891cf Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/07-ic-wave.png differ diff --git a/mockups/canvases/grok-ios/assets/art/08-band.png b/mockups/canvases/grok-ios/assets/art/08-band.png new file mode 100644 index 00000000..716b25d8 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/08-band.png differ diff --git a/mockups/canvases/grok-ios/assets/art/08-ghost.png b/mockups/canvases/grok-ios/assets/art/08-ghost.png new file mode 100644 index 00000000..67b56d3e Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/08-ghost.png differ diff --git a/mockups/canvases/grok-ios/assets/art/08-ic-compose.png b/mockups/canvases/grok-ios/assets/art/08-ic-compose.png new file mode 100644 index 00000000..d8c795a1 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/08-ic-compose.png differ diff --git a/mockups/canvases/grok-ios/assets/art/08-ic-menu.png b/mockups/canvases/grok-ios/assets/art/08-ic-menu.png new file mode 100644 index 00000000..e3df5e08 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/08-ic-menu.png differ diff --git a/mockups/canvases/grok-ios/assets/art/08-orb.png b/mockups/canvases/grok-ios/assets/art/08-orb.png new file mode 100644 index 00000000..30d697b0 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/08-orb.png differ diff --git a/mockups/canvases/grok-ios/assets/art/09-band.png b/mockups/canvases/grok-ios/assets/art/09-band.png new file mode 100644 index 00000000..858d7efd Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/09-band.png differ diff --git a/mockups/canvases/grok-ios/assets/art/09-ghost.png b/mockups/canvases/grok-ios/assets/art/09-ghost.png new file mode 100644 index 00000000..62c5eefa Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/09-ghost.png differ diff --git a/mockups/canvases/grok-ios/assets/art/09-orb.png b/mockups/canvases/grok-ios/assets/art/09-orb.png new file mode 100644 index 00000000..68a203ed Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/09-orb.png differ diff --git a/mockups/canvases/grok-ios/assets/art/10-hdr.png b/mockups/canvases/grok-ios/assets/art/10-hdr.png new file mode 100644 index 00000000..eacf0349 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/10-hdr.png differ diff --git a/mockups/canvases/grok-ios/assets/art/10-ic-appearance.png b/mockups/canvases/grok-ios/assets/art/10-ic-appearance.png new file mode 100644 index 00000000..784bcb9b Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/10-ic-appearance.png differ diff --git a/mockups/canvases/grok-ios/assets/art/10-ic-chevron.png b/mockups/canvases/grok-ios/assets/art/10-ic-chevron.png new file mode 100644 index 00000000..27c980b8 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/10-ic-chevron.png differ diff --git a/mockups/canvases/grok-ios/assets/art/10-ic-companions.png b/mockups/canvases/grok-ios/assets/art/10-ic-companions.png new file mode 100644 index 00000000..e9f8cb5b Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/10-ic-companions.png differ diff --git a/mockups/canvases/grok-ios/assets/art/10-ic-customize.png b/mockups/canvases/grok-ios/assets/art/10-ic-customize.png new file mode 100644 index 00000000..8e93c684 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/10-ic-customize.png differ diff --git a/mockups/canvases/grok-ios/assets/art/10-ic-dictation.png b/mockups/canvases/grok-ios/assets/art/10-ic-dictation.png new file mode 100644 index 00000000..d81054ad Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/10-ic-dictation.png differ diff --git a/mockups/canvases/grok-ios/assets/art/10-ic-haptics.png b/mockups/canvases/grok-ios/assets/art/10-ic-haptics.png new file mode 100644 index 00000000..f1bbb340 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/10-ic-haptics.png differ diff --git a/mockups/canvases/grok-ios/assets/art/10-ic-kids.png b/mockups/canvases/grok-ios/assets/art/10-ic-kids.png new file mode 100644 index 00000000..f005c9c5 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/10-ic-kids.png differ diff --git a/mockups/canvases/grok-ios/assets/art/10-ic-language.png b/mockups/canvases/grok-ios/assets/art/10-ic-language.png new file mode 100644 index 00000000..acfc6a7a Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/10-ic-language.png differ diff --git a/mockups/canvases/grok-ios/assets/art/10-ic-nsfw.png b/mockups/canvases/grok-ios/assets/art/10-ic-nsfw.png new file mode 100644 index 00000000..e2bc293f Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/10-ic-nsfw.png differ diff --git a/mockups/canvases/grok-ios/assets/art/10-ic-person.png b/mockups/canvases/grok-ios/assets/art/10-ic-person.png new file mode 100644 index 00000000..4132ad8d Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/10-ic-person.png differ diff --git a/mockups/canvases/grok-ios/assets/art/10-ic-widget.png b/mockups/canvases/grok-ios/assets/art/10-ic-widget.png new file mode 100644 index 00000000..808f73b4 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/10-ic-widget.png differ diff --git a/mockups/canvases/grok-ios/assets/art/11-hdr.png b/mockups/canvases/grok-ios/assets/art/11-hdr.png new file mode 100644 index 00000000..778fa380 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/11-hdr.png differ diff --git a/mockups/canvases/grok-ios/assets/art/11-ic-companions.png b/mockups/canvases/grok-ios/assets/art/11-ic-companions.png new file mode 100644 index 00000000..1d78e587 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/11-ic-companions.png differ diff --git a/mockups/canvases/grok-ios/assets/art/11-ic-data.png b/mockups/canvases/grok-ios/assets/art/11-ic-data.png new file mode 100644 index 00000000..3ef182e6 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/11-ic-data.png differ diff --git a/mockups/canvases/grok-ios/assets/art/11-ic-deleted.png b/mockups/canvases/grok-ios/assets/art/11-ic-deleted.png new file mode 100644 index 00000000..82814d6b Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/11-ic-deleted.png differ diff --git a/mockups/canvases/grok-ios/assets/art/11-ic-dictation.png b/mockups/canvases/grok-ios/assets/art/11-ic-dictation.png new file mode 100644 index 00000000..2da37175 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/11-ic-dictation.png differ diff --git a/mockups/canvases/grok-ios/assets/art/11-ic-privacy.png b/mockups/canvases/grok-ios/assets/art/11-ic-privacy.png new file mode 100644 index 00000000..19f64196 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/11-ic-privacy.png differ diff --git a/mockups/canvases/grok-ios/assets/art/11-ic-report.png b/mockups/canvases/grok-ios/assets/art/11-ic-report.png new file mode 100644 index 00000000..a8f42b55 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/11-ic-report.png differ diff --git a/mockups/canvases/grok-ios/assets/art/11-ic-shared.png b/mockups/canvases/grok-ios/assets/art/11-ic-shared.png new file mode 100644 index 00000000..0da54696 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/11-ic-shared.png differ diff --git a/mockups/canvases/grok-ios/assets/art/11-ic-supergrok.png b/mockups/canvases/grok-ios/assets/art/11-ic-supergrok.png new file mode 100644 index 00000000..9430fe8e Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/11-ic-supergrok.png differ diff --git a/mockups/canvases/grok-ios/assets/art/11-ic-terms.png b/mockups/canvases/grok-ios/assets/art/11-ic-terms.png new file mode 100644 index 00000000..55625e67 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/11-ic-terms.png differ diff --git a/mockups/canvases/grok-ios/assets/art/11-ic-voicemode.png b/mockups/canvases/grok-ios/assets/art/11-ic-voicemode.png new file mode 100644 index 00000000..f14f344f Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/11-ic-voicemode.png differ diff --git a/mockups/canvases/grok-ios/assets/art/12-hdr.png b/mockups/canvases/grok-ios/assets/art/12-hdr.png new file mode 100644 index 00000000..dc1054fb Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/12-hdr.png differ diff --git a/mockups/canvases/grok-ios/assets/art/12-ic-data.png b/mockups/canvases/grok-ios/assets/art/12-ic-data.png new file mode 100644 index 00000000..9d8802c2 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/12-ic-data.png differ diff --git a/mockups/canvases/grok-ios/assets/art/12-ic-deleted.png b/mockups/canvases/grok-ios/assets/art/12-ic-deleted.png new file mode 100644 index 00000000..6251c371 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/12-ic-deleted.png differ diff --git a/mockups/canvases/grok-ios/assets/art/12-ic-privacy.png b/mockups/canvases/grok-ios/assets/art/12-ic-privacy.png new file mode 100644 index 00000000..fbc9001b Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/12-ic-privacy.png differ diff --git a/mockups/canvases/grok-ios/assets/art/12-ic-report.png b/mockups/canvases/grok-ios/assets/art/12-ic-report.png new file mode 100644 index 00000000..b2bfd6e0 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/12-ic-report.png differ diff --git a/mockups/canvases/grok-ios/assets/art/12-ic-signout.png b/mockups/canvases/grok-ios/assets/art/12-ic-signout.png new file mode 100644 index 00000000..77b1c109 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/12-ic-signout.png differ diff --git a/mockups/canvases/grok-ios/assets/art/12-ic-supergrok.png b/mockups/canvases/grok-ios/assets/art/12-ic-supergrok.png new file mode 100644 index 00000000..c5aa16cd Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/12-ic-supergrok.png differ diff --git a/mockups/canvases/grok-ios/assets/art/12-ic-terms.png b/mockups/canvases/grok-ios/assets/art/12-ic-terms.png new file mode 100644 index 00000000..4851205e Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/12-ic-terms.png differ diff --git a/mockups/canvases/grok-ios/assets/art/12-xai.png b/mockups/canvases/grok-ios/assets/art/12-xai.png new file mode 100644 index 00000000..b0a35f85 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/12-xai.png differ diff --git a/mockups/canvases/grok-ios/assets/art/13-spinner.png b/mockups/canvases/grok-ios/assets/art/13-spinner.png new file mode 100644 index 00000000..b192133a Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/13-spinner.png differ diff --git a/mockups/canvases/grok-ios/assets/art/14-badge.png b/mockups/canvases/grok-ios/assets/art/14-badge.png new file mode 100644 index 00000000..28b6ffca Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/14-badge.png differ diff --git a/mockups/canvases/grok-ios/assets/art/14-ic-bot.png b/mockups/canvases/grok-ios/assets/art/14-ic-bot.png new file mode 100644 index 00000000..6373f25e Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/14-ic-bot.png differ diff --git a/mockups/canvases/grok-ios/assets/art/15-bundle.png b/mockups/canvases/grok-ios/assets/art/15-bundle.png new file mode 100644 index 00000000..c9da8d1e Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/15-bundle.png differ diff --git a/mockups/canvases/grok-ios/assets/art/15-ic-chevron.png b/mockups/canvases/grok-ios/assets/art/15-ic-chevron.png new file mode 100644 index 00000000..70689469 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/15-ic-chevron.png differ diff --git a/mockups/canvases/grok-ios/assets/art/15-ic-close.png b/mockups/canvases/grok-ios/assets/art/15-ic-close.png new file mode 100644 index 00000000..763f2d82 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/15-ic-close.png differ diff --git a/mockups/canvases/grok-ios/assets/art/15-ic-cloud.png b/mockups/canvases/grok-ios/assets/art/15-ic-cloud.png new file mode 100644 index 00000000..41f9fe3d Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/15-ic-cloud.png differ diff --git a/mockups/canvases/grok-ios/assets/art/15-ic-dev.png b/mockups/canvases/grok-ios/assets/art/15-ic-dev.png new file mode 100644 index 00000000..b5883340 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/15-ic-dev.png differ diff --git a/mockups/canvases/grok-ios/assets/art/15-ic-share.png b/mockups/canvases/grok-ios/assets/art/15-ic-share.png new file mode 100644 index 00000000..e33546e2 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/15-ic-share.png differ diff --git a/mockups/canvases/grok-ios/assets/art/15-icon.png b/mockups/canvases/grok-ios/assets/art/15-icon.png new file mode 100644 index 00000000..2938b3eb Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/15-icon.png differ diff --git a/mockups/canvases/grok-ios/assets/art/15-preview-1.png b/mockups/canvases/grok-ios/assets/art/15-preview-1.png new file mode 100644 index 00000000..b0350e28 Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/15-preview-1.png differ diff --git a/mockups/canvases/grok-ios/assets/art/15-preview-2.png b/mockups/canvases/grok-ios/assets/art/15-preview-2.png new file mode 100644 index 00000000..c73f948e Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/15-preview-2.png differ diff --git a/mockups/canvases/grok-ios/assets/art/15-stars.png b/mockups/canvases/grok-ios/assets/art/15-stars.png new file mode 100644 index 00000000..4911a55f Binary files /dev/null and b/mockups/canvases/grok-ios/assets/art/15-stars.png differ diff --git a/mockups/canvases/grok-ios/assets/icons/04-focus.svg b/mockups/canvases/grok-ios/assets/icons/04-focus.svg new file mode 100644 index 00000000..c8b76f12 --- /dev/null +++ b/mockups/canvases/grok-ios/assets/icons/04-focus.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/mockups/canvases/grok-ios/assets/icons/04-hanger.svg b/mockups/canvases/grok-ios/assets/icons/04-hanger.svg new file mode 100644 index 00000000..a9802f4d --- /dev/null +++ b/mockups/canvases/grok-ios/assets/icons/04-hanger.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/mockups/canvases/grok-ios/assets/icons/04-trash.svg b/mockups/canvases/grok-ios/assets/icons/04-trash.svg new file mode 100644 index 00000000..75ed3ed9 --- /dev/null +++ b/mockups/canvases/grok-ios/assets/icons/04-trash.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/mockups/canvases/grok-ios/assets/icons/07-bot.svg b/mockups/canvases/grok-ios/assets/icons/07-bot.svg new file mode 100644 index 00000000..313d8da5 --- /dev/null +++ b/mockups/canvases/grok-ios/assets/icons/07-bot.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/mockups/canvases/grok-ios/assets/icons/07-github.svg b/mockups/canvases/grok-ios/assets/icons/07-github.svg new file mode 100644 index 00000000..2c973b0a --- /dev/null +++ b/mockups/canvases/grok-ios/assets/icons/07-github.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/mockups/canvases/grok-ios/assets/icons/07-gmail.svg b/mockups/canvases/grok-ios/assets/icons/07-gmail.svg new file mode 100644 index 00000000..27d5f37a --- /dev/null +++ b/mockups/canvases/grok-ios/assets/icons/07-gmail.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/mockups/canvases/grok-ios/assets/icons/07-notion.svg b/mockups/canvases/grok-ios/assets/icons/07-notion.svg new file mode 100644 index 00000000..6e3e9303 --- /dev/null +++ b/mockups/canvases/grok-ios/assets/icons/07-notion.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/mockups/canvases/grok-ios/crops.json b/mockups/canvases/grok-ios/crops.json new file mode 100644 index 00000000..558f6f14 --- /dev/null +++ b/mockups/canvases/grok-ios/crops.json @@ -0,0 +1,585 @@ +{ + "_": "Art cut from assets/refs/.png at measured pt boxes (2.2417 px/pt for cp1-cp5, 3.0 for the 402 x 874 captures cp6, cp7 and cp13-cp15; cp8-cp12 are 2.2417 again), and placed back at the same numbers by art(). Illustrations at their card boxes; every icon (-ic-) at its ink box plus 1pt of ground, so it is the capture's own glyph. i8-i12 are cp8-cp12 with the type and the page dots patched out of the one band each screen crops (08/09: the card's bottom corners and shadow, y 700-852; 10-12: the header band, y 54-150), so the type is set again in CSS over the capture's own material. i5 is cp5 with every piece of chrome and type patched out first (the boxes are INPAINT in gen.py), so the photograph and the sheet material survive and the chrome is drawn again in CSS. g4 is not a capture: 04-scene is the companion scene with the voice sheet removed, the patched cp4 (i4) above the sheet's edge and a gpt-image-2 edit of it below, composed by scratch/scene4.py and committed as assets/art/04-scene.png; cut() leaves it alone. 04-ic-close, 04-ic-airplay and 04-ic-person are keyed by cut() (KEYED in gen.py): white ink at the glyph's own coverage, the sheet ground in their margin dropped, because the board draws that sheet now.", + "_rule": "Crop what the capture already contains; draw only what it does not.", + "04-scene": [ + "g4", + 0.0, + 0.0, + 393.0, + 852.0 + ], + "05-bg": [ + "i5", + 0.0, + 0.0, + 393.0, + 852.0 + ], + "01-ic-mark": [ + "cp1", + 69.0, + 112.3, + 96.0, + 137.9 + ], + "01-ic-compose": [ + "cp1", + 56.5, + 184.1, + 81.7, + 209.3 + ], + "01-ic-wave": [ + "cp1", + 128.8, + 183.2, + 153.6, + 208.9 + ], + "02-ic-back": [ + "cp2", + 30.2, + 86.9, + 42.9, + 107.6 + ], + "02-ic-app": [ + "cp2", + 71.3, + 315.3, + 92.8, + 336.4 + ], + "02-ic-close": [ + "cp2", + 304.2, + 318.9, + 317.2, + 331.9 + ], + "02-ic-mark": [ + "cp2", + 166.3, + 444.3, + 187.9, + 464.0 + ], + "02-ic-sparkle": [ + "cp2", + 213.6, + 634.7, + 227.6, + 648.3 + ], + "03-ic-sparkle": [ + "cp3", + 165.8, + 634.7, + 179.4, + 648.3 + ], + "04-ic-x": [ + "cp4", + 30.7, + 77.5, + 45.2, + 92.4 + ], + "04-ic-grid": [ + "cp4", + 344.7, + 74.8, + 365.5, + 95.1 + ], + "04-ic-chevron": [ + "cp4", + 345.6, + 289.9, + 364.6, + 301.7 + ], + "04-ic-close": [ + "cp4", + 338.9, + 430.8, + 357.4, + 449.3 + ], + "04-ic-airplay": [ + "cp4", + 334.0, + 500.4, + 357.4, + 522.9 + ], + "04-ic-person": [ + "cp4", + 332.7, + 562.9, + 358.3, + 586.3 + ], + "05-ic-rocket": [ + "cp5", + 49.4, + 228.3, + 70.6, + 249.9 + ], + "05-ic-imagine": [ + "cp5", + 49.0, + 288.1, + 70.6, + 310.1 + ], + "05-ic-wave5s": [ + "cp5", + 49.0, + 349.2, + 71.0, + 371.3 + ], + "05-ic-star": [ + "cp5", + 49.4, + 412.5, + 70.1, + 432.4 + ], + "05-ic-cube": [ + "cp5", + 49.9, + 473.2, + 69.7, + 494.8 + ], + "06-ic-mark": [ + "cp6", + 172.33, + 299.03, + 229.37, + 353.97 + ], + "07-ic-mark": [ + "cp7", + 15.63, + 69.63, + 49.67, + 102.37 + ], + "07-ic-watermark": [ + "cp7", + 160.63, + 360.63, + 240.37, + 437.37 + ], + "07-ic-bank": [ + "cp7", + 169.33, + 692.33, + 185.67, + 708.97 + ], + "07-ic-plus": [ + "cp7", + 30.63, + 799.33, + 43.67, + 812.37 + ], + "07-ic-auto": [ + "cp7", + 70.33, + 797.63, + 86.67, + 813.97 + ], + "07-ic-mic": [ + "cp7", + 264.63, + 798.03, + 278.67, + 813.97 + ], + "07-ic-wave": [ + "cp7", + 305.03, + 798.33, + 319.67, + 812.97 + ], + "13-spinner": [ + "cp13", + 191.03, + 747.63, + 211.37, + 767.97 + ], + "14-ic-bot": [ + "cp14", + 110.37, + 543.37, + 144.63, + 578.03 + ], + "14-badge": [ + "cp14", + 30.67, + 630.97, + 83.03, + 652.03 + ], + "15-ic-close": [ + "cp15", + 28.33, + 91.33, + 46.67, + 109.67 + ], + "15-ic-share": [ + "cp15", + 354.33, + 87.63, + 373.67, + 111.67 + ], + "15-icon": [ + "cp15", + 19.33, + 141.03, + 138.67, + 260.37 + ], + "15-ic-cloud": [ + "cp15", + 156.33, + 231.03, + 183.67, + 256.37 + ], + "15-ic-dev": [ + "cp15", + 374.63, + 310.63, + 400.37, + 336.67 + ], + "15-stars": [ + "cp15", + 32.33, + 342.33, + 102.97, + 355.37 + ], + "15-bundle": [ + "cp15", + 19.33, + 424.33, + 82.67, + 487.67 + ], + "15-ic-chevron": [ + "cp15", + 144.33, + 532.63, + 154.67, + 548.97 + ], + "15-preview-1": [ + "cp15", + 19.33, + 726.03, + 255.37, + 874.0 + ], + "15-preview-2": [ + "cp15", + 264.03, + 726.03, + 402.0, + 874.0 + ], + "08-ic-menu": [ + "cp8", + 27.5, + 78.9, + 49.2, + 91.6 + ], + "08-ic-compose": [ + "cp8", + 344.7, + 74.4, + 366.8, + 96.0 + ], + "08-orb": [ + "cp8", + 137.7, + 501.7, + 256.2, + 574.7 + ], + "09-orb": [ + "cp9", + 137.7, + 501.7, + 256.6, + 574.7 + ], + "08-ghost": [ + "cp8", + 141.8, + 645.0, + 237.9, + 665.3 + ], + "09-ghost": [ + "cp9", + 141.8, + 645.0, + 237.9, + 665.3 + ], + "08-band": [ + "i8", + 0.0, + 700.0, + 393.0, + 852.0 + ], + "09-band": [ + "i9", + 0.0, + 700.0, + 393.0, + 852.0 + ], + "10-hdr": [ + "i10", + 0.0, + 54.0, + 393.0, + 150.0 + ], + "11-hdr": [ + "i11", + 0.0, + 54.0, + 393.0, + 150.0 + ], + "12-hdr": [ + "i12", + 0.0, + 54.0, + 393.0, + 150.0 + ], + "10-ic-person": [ + "cp10", + 48.5, + 196.2, + 75.5, + 224.9 + ], + "10-ic-chevron": [ + "cp10", + 350.5, + 342.0, + 359.2, + 355.6 + ], + "10-ic-appearance": [ + "cp10", + 31.6, + 338.0, + 52.7, + 359.2 + ], + "10-ic-customize": [ + "cp10", + 32.5, + 391.6, + 51.4, + 410.5 + ], + "10-ic-haptics": [ + "cp10", + 33.3, + 442.0, + 52.7, + 463.1 + ], + "10-ic-widget": [ + "cp10", + 32.0, + 494.6, + 51.9, + 514.9 + ], + "10-ic-language": [ + "cp10", + 31.6, + 546.4, + 52.7, + 567.1 + ], + "10-ic-kids": [ + "cp10", + 30.7, + 632.4, + 53.6, + 655.0 + ], + "10-ic-nsfw": [ + "cp10", + 32.0, + 686.0, + 51.9, + 705.8 + ], + "10-ic-companions": [ + "cp10", + 30.2, + 794.8, + 54.1, + 812.9 + ], + "10-ic-dictation": [ + "cp10", + 30.2, + 845.7, + 54.1, + 852.0 + ], + "11-ic-companions": [ + "cp11", + 30.2, + 183.7, + 54.1, + 202.2 + ], + "11-ic-dictation": [ + "cp11", + 31.6, + 235.0, + 52.7, + 254.4 + ], + "11-ic-voicemode": [ + "cp11", + 32.5, + 287.2, + 51.9, + 306.1 + ], + "11-ic-shared": [ + "cp11", + 31.6, + 393.8, + 52.3, + 414.5 + ], + "11-ic-data": [ + "cp11", + 32.9, + 445.5, + 51.0, + 466.7 + ], + "11-ic-deleted": [ + "cp11", + 32.5, + 497.7, + 51.9, + 518.5 + ], + "11-ic-terms": [ + "cp11", + 33.3, + 584.3, + 51.0, + 605.5 + ], + "11-ic-privacy": [ + "cp11", + 32.5, + 636.5, + 51.9, + 657.6 + ], + "11-ic-report": [ + "cp11", + 31.6, + 723.5, + 52.7, + 744.6 + ], + "11-ic-supergrok": [ + "cp11", + 34.2, + 833.2, + 51.4, + 850.4 + ], + "12-ic-data": [ + "cp12", + 32.9, + 175.2, + 51.0, + 195.9 + ], + "12-ic-deleted": [ + "cp12", + 32.9, + 227.0, + 51.4, + 248.1 + ], + "12-ic-terms": [ + "cp12", + 33.8, + 313.9, + 51.0, + 335.1 + ], + "12-ic-privacy": [ + "cp12", + 32.5, + 366.1, + 51.4, + 386.9 + ], + "12-ic-report": [ + "cp12", + 31.6, + 453.1, + 52.7, + 473.9 + ], + "12-ic-supergrok": [ + "cp12", + 34.2, + 563.3, + 50.5, + 580.0 + ], + "12-ic-signout": [ + "cp12", + 32.5, + 649.0, + 51.4, + 667.9 + ], + "12-xai": [ + "cp12", + 186.8, + 733.7, + 206.6, + 755.8 + ] +} \ No newline at end of file diff --git a/mockups/canvases/grok-ios/gen.py b/mockups/canvases/grok-ios/gen.py new file mode 100644 index 00000000..bbde95e3 --- /dev/null +++ b/mockups/canvases/grok-ios/gen.py @@ -0,0 +1,1664 @@ +"""Grok for iOS -- seven screens, the tokens behind them, and the captures. + +Regenerates the whole folder in place, byte-identically, from anywhere: + + python3 mockups/canvases/grok-ios/gen.py + refkit tokens mockups/canvases/grok-ios + +Every colour and every metric in here was read off five Mobbin captures at +2.2417 capture px per design pt (881 px across a 393 pt screen, 1910 down an +852 pt one) and two native captures at exactly 3 px per pt (1290 x 2796, a +430 x 932 pt Pro Max screen), and every one of them is stated with its +evidence on the 00b-00f boards. Nothing was eyeballed. The artboards are output: never hand-edit an +.html, edit this file and re-run. + +Four decisions the captures force. + +TWO DEVICES. 01-05 are 393 x 852 boards like every other folder here; 06-07 +were captured on a 430 x 932 device and are drawn at that size, which fills +the 478 x 980 artboard exactly with the 24px padding (the bezel rings fit, the +drop shadow is clipped). Their status bar and Dynamic Island are this repo's +template frame, not the captures' (the captures show 20:52, a muted bell and a +live-activity glyph in the island; none of that is the app), and they carry no +home indicator because the captures show none. + +THE FACE IS SF PRO, AND IT IS THE PLATFORM'S. `refkit font` returns a weak +call for SF Pro on every title measured, so the boards set in the platform +stack with no stand-in corrections: FACE_DROP and XOFF are both 0 here, and +the line-box model below is the platform face's own. + +TWO SCREENS ARE MOSTLY PHOTOGRAPH. 04 is a voice-settings sheet over a 3D +companion scene, and the sheet is a dark blur of that scene rather than a +fill; 05's paywall sits on a smoke-and-particles hero that reaches faintly +down the whole screen and shows through its translucent feature card. 05's +ground is cut from the capture (crops.json) after every piece of chrome and +type on it is patched out (INPAINT below, a Coons fill from each box's own +four edges), so the pixels are the capture's and the chrome on top is CSS; +its card is not patched: its 6.7% white material is un-applied inside the +card box and re-applied by the CSS card, which is exact by construction. +04's scene is the one asset the capture does not hold: above the sheet's +edge it is the patched capture (i4), below it a gpt-image-2 edit of that +frame (assets/art/04-scene.png, composed by scratch/scene4.py), and the +sheet itself is drawn, with its blur and tint fitted (see s04). + +ICONS ARE CROPS, NOT DRAWINGS, WITH TWO SETS OF EXCEPTIONS. Thirty-one glyphs on +these screens are SF Symbols, the Grok mark or its app icon, and a hand-drawn +approximation of an SF Symbol is visibly not the symbol at any zoom. Each one +is cut from its capture at its measured ink box plus a point of ground +(crops.json, the `-ic-` ids) and put back at the same numbers, so it is the +capture's own pixels and scores zero by construction. + +The exceptions are vectors in assets/icons/, each with a viewBox that is its +measured ink box in pt, inlined by icon() so the canvas's inspector hands it +back as a vector asset. The three side glyphs on 04 (focus, hanger, trash) are +traced stroke by stroke against the capture's coverage, by request. The four +marks on 07's chips are not traced at all: they are the published artwork of +Gmail, GitHub, Notion and Grok Bot, each placed on the box that fits the +capture's pixels, also by request (README, "Seven vector icons"). + +Three defects belong to the source, not to the replica: Mobbin composites the +Dynamic Island out (except on 04, where the app's own recording dot keeps it), +drops the home indicator, and exports with square corners. All three are drawn +here. The diff window is trimmed accordingly -- see README.md. +""" +import base64, json, re +from pathlib import Path + +OUT = Path(__file__).resolve().parent +REFS_DIR = OUT / "assets" / "refs" +ART_DIR = OUT / "assets" / "art" +CROPS = {k: v for k, v in json.loads((OUT / "crops.json").read_text()).items() + if not k.startswith("_")} +SCALE = 2.2417 # capture px per design pt +BIG = {"cp6", "cp7", "cp13", "cp14", "cp15"} # the 402 x 874 captures + + +def scale_of(ref): + return 3.0 if ref in BIG else SCALE + +NAME = "Grok iOS" +PAGE_NAME = "(example) " + NAME +P = "k" # token prefix: --k-sheet, --k-ink, --k-t-body + +# ---------------------------------------------------------------- tokens ---- +# (group, name, value, evidence). The :root block and the evidence table are +# both generated from this list, so a value cannot drift from the evidence +# behind it, and a token cannot ship without one. +TOKENS = [ + ("Font", "font", '-apple-system,BlinkMacSystemFont,"SF Pro Text",' + '"SF Pro Display","Helvetica Neue",Helvetica,Arial,sans-serif', + "refkit font on 02 'Widget', 05 'SuperGrok' and 'Unlock the full power of " + "Grok': SF Pro top on all three, weak call each time. The platform face"), + + ("Surface", "ground", "#D5D5D5", + "01 flat census left of the widget (x 0-20, y 100-240): #D5D5D5 100%"), + ("Surface", "card", "#FFFFFF", + "01 widget body, col x68 y 80.7-94.5; 02 card interior, row y300 x 60-340; " + "02 the drawn sheet x 221-311 y 339-352 #FFFFFF on 100% of the flats"), + ("Surface", "well", "#E5E5E5", + "01 pill and both circles: row y125 x 39-172 and row y196 x 39-100 flat " + "#E5E5E5; 02 the drawn widget's pill x 150-163 y 437-472 #E5E5E5 100%"), + ("Surface", "dim", "#CBCBCB", + "02/03 the band above the sheet, y 0-58.9 flat #CBCBCB: the dimmed parent"), + ("Surface", "sheet", "#F6F6F6", + "02/03 col x100 from 59.0 down and row y700 outside the card: #F6F6F6"), + ("Surface", "illo-frame", "#AAAAAA", + "02/03 the guide illustration's phone: frame col x 49.7 y 316-428 and " + "island x 163-230 y 232-247 flat #AAAAAA on 100% of the flats"), + ("Surface", "illo-screen", "#FAFAFA", + "03 inside the drawn frame, x 132-257 y 258-272: #FAFAFA, five under the " + "card, on 100% of the flats"), + ("Surface", "illo-tile", "#DDDDDD", + "03 tile core x 83-119 y 290-330: #DDDDDD on 99.5% of the flats"), + ("Surface", "illo-scrim", "rgba(0,0,0,.12)", + "02 the drawn screen under its sheet: #FAFAFA reads #DBDBDB at col x87 y " + "218-278 and #DDDDDD at col x200 y 252-274, (250-219..221)/250 = .116-.124; " + "the island still reads #A9A9A9, so the scrim lies under it"), + ("Surface", "illo-grabber", "#CCCCCC", + "02 sheet grabber x 183.8-209.2 y 302.4-306.0: mode #CCCCCC, flat #CDCDCD"), + ("Surface", "night", "#010101", + "05 flat census x 20-372 at y 718-728 and y 822-838, above the CTA and " + "below the footer: #010101 on 73% and 100% of the flats. The band between " + "the feature card and the plan group is not flat (#171717-#1D1D1D, the " + "smoke's tail) and stays in the crop"), + ("Surface", "skip", "#121212", + "05 row y83 across the Skip pill 316.1-371.8 reads #111111, col x344 " + "68-98.4 reads #141414; the mean"), + ("Surface", "material", "rgba(255,255,255,.067)", + "05 feature card censuses #131313 at y 203-213, 264-276 and 500-518 and " + "#111111 at y 384-396, over a ground of #000000-#030303 outside it: " + "(19-2)/253 = .067 white. At its top edge it reads #333033 with the smoke " + "behind it, so a fill would be wrong and a material is right"), + ("Surface", "disc", "rgba(255,255,255,.17)", + "05 icon discs solved against the patched frame i5 over a ring r 11-18.5 " + "around each glyph: alpha .185/.183/.167/.165/.182 on the five rows"), + ("Surface", "price", "#131313", + "05 census x 30-190 y 695-715, the blank of the Monthly side of the plan " + "group: #131313 on 99.8% of the flats"), + ("Surface", "plan-lo", "#282828", + "05 Yearly card, bottom-left blank x 212-228 y 700-712: #282828 on 99.8% " + "of the flats. The card is a diagonal ramp, not a fill: its four corners " + "census 45/52/40/45 mean level (TL/TR/BL/BR)"), + ("Surface", "plan-hi", "#333536", + "05 Yearly card, top-right blank x 340-358 y 626-636: #333536 on 72% of " + "the flats; the light end of the ramp, laid to top right in the builder"), + ("Surface", "free-bg", "#341A0E", + "05 FREE badge interior, rows 643-648 x 134-140: #321B10 #371B10 #33170C"), + ("Surface", "scrim-btn", "rgba(0,0,0,.32)", + "04 X and grid buttons solved against the patched frame i4 over a ring r " + "9-20: black at .325 (sd .02) and .320; the close disc on the sheet .28"), + ("Surface", "glass", "rgba(255,255,255,.09)", + "04 side-stack discs solved against the patched frame i4 over a ring r " + "10-14.5: white at .089 and .090 over sky, .037 over the cloud where the " + "ground is too bright to resolve"), + ("Surface", "grabber", "rgba(255,255,255,.35)", + "04 grabber #8B7467 over the patched sheet #412A1C at y 410-412: white at " + ".39/.35/.33 per channel"), + ("Surface", "sheet-v", "rgba(0,0,0,.40)", + "04 fitted through the drawn sheet at the 4px blur: at .40 the band under " + "the sheet's edge (y 406-428) reads -0.2 signed and the body band (y " + "606-740) +0.6; .35 leaves both +4, .45 both -5 (README)"), + ("Surface", "side-ink", "#CDCECF", + "04 ink of the three vector side glyphs: top 3% of each box 203-208 over grounds 163/180/194, so flat, not white at an alpha (.16-.49 would fit)"), + ("Surface", "voice-pill", "#767676", + "04 the voice pill reads #474747 flat through the sheet (x 300-370, y " + "772-797, std 3.6): 71/.60 = 118 under the .40 tint"), + ("Surface", "rec", "#F09540", + "04 the recording dot inside the island, x 215.0-220.8 y 26.8-32.6: " + "#F09540 #F29442 #F09444"), + ("Surface", "page", "#FFFFFF", + "06 flat census x 40-360 y 520-700, 07 x 100-300 y 200-300: #FFFFFF on " + "100% of the flats"), + ("Surface", "chip", "#F5F5F5", + "07 suggestion chips y 675-727, census x 20-60 y 680-690 above the bot " + "glyph: #F5F5F5 on 100% of the flats"), + ("Surface", "composer", "#FEFEFE", + "07 composer interior census x 140-300 y 765-785, right of the placeholder " + "and above the controls: #FEFDFE on 84% of the flats; the 2pt inside its " + "edge reads #F9F9F9, the inset the line token carries"), + ("Surface", "ctl", "#F4F3F4", + "07 the Auto pill x 59.3-134 y 789.3-822, census y 792-797 above its " + "glyph: #F4F3F4 on 98% of the flats; the + and mic discs the same"), + ("Surface", "btn", "#000000", + "06 Got it pill 20-382 x 730.7-784.7, census x 40-150 y 740-775: #000000 " + "on 100% of the flats; 07 Speak pill, 14 CTA the same"), + ("Surface", "scrim-sheet", "rgba(0,0,0,.19)", + "14 the Terms page under the sheet: its white reads #CCCCCC on 100% of the " + "flats (x 20-380 y 150-250) and the title's ink stays #000000; (255-204)/" + "255 = .20, the pill under the glass reads #8E8E8E at .19 and #8B8B8B at " + ".20, so .19"), + ("Surface", "glass-sheet", "rgba(255,255,255,.5)", + "14 the sheet over the scrimmed page: #E6E6E6 over #CCCCCC on 95% of " + "the flats (x 60-340 y 840-855) is white at .51; over the black Got it " + "pill it reads #8E8E8E, white at .56 with the pill's edges blurred in. " + "At the 19px blur the flats read .48 -0.48, .5 +0.74, .52 +1.74, .55 " + "+2.79 signed, and .5 is the alpha the blur was swept at over the pill"), + ("Surface", "grabber-pro", "#A4A4A6", + "14 grabber 172.3-229.7 x 451.3-455.0: #A4A4A6 on 78% of its flats"), + ("Surface", "store-dim", "#BDBFBC", + "15 the App Store page above the sheet, census x 100-300 y 20-50: #BDBFBC, " + "green one and two levels over red and blue in the capture itself"), + ("Surface", "store-disc", "#FAFAFA", + "15 the close and share discs (d 45.4 at 15.3 and 341.3, y 77.3-122.7): " + "interior mode #FAFAFA left of the X glyph (x 20-32 y 100-112), rim two " + "capture px of #D7D7D7 at the sides, #EEEEEE at the top"), + ("Surface", "store-pill", "#EEEEEF", + "15 the Purchased pill 289-382 x 440-472, census x 300-382 y 440-448: " + "#EEEEEF on 94% of the flats"), + ("Surface", "card-blue", "#80BEFD", + "14 the Grok Bot card 23.3-378.7 x 460.7-660.7: #80BEFD on a 20pt grid " + "over its right half and lower two thirds (x 66-366 y 583-643), every " + "cell within a level"), + ("Surface", "card-pale", "#E8F3FE", + "14 the pale shape in the card's top-left, cells x 46-106 y 463-513: " + "#E8F3FE, #E8F2FE. Along row 481 it holds 243 to x 108 and falls to 189 " + "by x 208, along column 88 it falls from 240 to 190 over y 521-537, and a " + "darker ring runs 20-30pt outside it (162-167 at x 208 y 505, x 168 y " + "541). Its ellipse, fade and ring are one fit to the card at 1pt, mean " + "|d| 3.13 to 1.87 over the card outside its crops and title (README)"), + + ("Line", "material-line", "rgba(255,255,255,.16)", + "05 card edge peaks #3B3B3B over one 0.9pt band at y 522.8-523.6 and " + "#5C5A5D at 198.9-199.8 with smoke behind; .16 over #131313 is #393939"), + ("Line", "price-line", "#252525", + "05 col x100 618.4-619.3 #252525 and 713.8-714.7 #222222: the plan group's " + "1pt edge"), + ("Line", "plan-line", "rgba(255,255,255,.17)", + "05 Yearly card edge peaks #505052 (row 623.5), #565658 (625), #535557 " + "(row 660 right); .17 over the ramp's #333536 top is #565758"), + ("Line", "composer-shadow", "rgba(0,0,0,.07)", + "07 the halo under the composer: the page reads #F5F5F5 at y 833, a pt " + "under the card's bottom edge (832.3), and climbs to #FDFDFD by y 848; " + "beside the card (x 392-395, row 780) #FAFAFA-#FCFCFC. Swept with the " + "line at #F9F9F9 over the composer band y 728-862: blur 6px reads 4.63, " + "4.59, 4.63 at alpha .05, .07, .09 and blur 14px 4.45, 4.39, 4.51"), + ("Line", "composer-line", "#F9F9F9", + "07 the card's edge, row y 780: x 10.33 #DEDEDE, 10.67 #A9A9A9, 11.0 " + "#DFDFDF, 11.33 #E0E0E0, 11.67 #EFEFEF, then the #F9F9F9 inset; the " + "right edge x 390.3-391.3 #E0E0E0 #E0E0E0 #BABABA #C5C5C5, the top at " + "737.33-737.67 #EFEFEF #E5E5E5 and the bottom at 832.0-832.3 #DBDBDB " + "#E6E6E6: a line 2 capture px wide, darkest at the sides. Drawn at " + ".67pt any grey is too dark, because the halo carries the edge: swept " + "#A9A9A9 to #FFFFFF over the band y 728-862, #A9A9A9 5.25, #E4E4E4 " + "4.59, #EEEEEE 4.48, #F6F6F6 4.40, #F9F9F9 4.39, #FFFFFF 4.41"), + ("Line", "sheet-line", "rgba(0,0,0,.45)", + "14 the sheet's outline, row y 600: x 7.33 #9A9A9A and 7.67 #696969 over " + "a scrim of #C0C0C0 beside it, x 394.0 #696969 and 394.33 #9A9A9A on the " + "right; two capture px of black at .45 mean over #C0C0C0 (.25 and .59), " + "and the scrim beside it is #C0C0C0-#C4C4C4 against #CCCCCC away from " + "it, the sheet's own soft shadow"), + ("Line", "store-rule", "#E7E7E8", + "15 the rules at y 278.67 and 366.67 x 20-402 and the three column " + "separators at x 124.67, 229.67, 334.67 y 305.7-339.7: one capture px, " + "#E7E7E8 on 100% of the pixels, no solve needed at 3 px/pt"), + ("Line", "illo-card-shadow", "rgba(0,0,0,.24)", + "02 the drawn widget card's halo: col x 176.8 climbs #FCFBFC to #E9E9E9 " + "over the 21pt above its top edge, row y 455 #F9F9F9 to #E5E5E5 over the " + "20.5pt left of it, row y 473 #E2E2E2 to #FEFEFE over 20pt to the right: " + "22-29 levels at the edge. One box-shadow swept dy 0-8 / blur 14-44 / " + "alpha .12-.30 over the 25pt above the card: minimum .85 at 4px 28px " + ".24, 0 28px .18 costs .1, 4px 20px .18 costs 2.6"), + ("Line", "row-line", "rgba(255,255,255,.10)", + "04 the row cards are a 1pt line and no fill: coverage solve over x 230-300 " + "of both rows' top and bottom edges (486.8, 537.7, 549.3, 600.3), white at " + ".087-.114, and .06-.14 on their sides, mean .10; inside a row reads " + "#42401C against #423F19 outside"), + ("Line", "illo-sheet-shadow", "rgba(0,0,0,.12)", + "02 above the drawn sheet's top edge 299.1, col x200: #DDDDDD to 274.6, " + "#DADADA to 285.3, #D7D7D7 to 292.4, #D4D4D4 to 298.7, nine levels over " + "46pt on top of the scrim. One box-shadow swept blur 12-56 / alpha " + ".05-.20 over that band: minimum 1.51 at 24px / .12, 40px / .08 costs .2"), + + ("Ink", "ink", "#000000", + "01 'Grok' and icon core; 02/03 body ink core #010101; 05 CTA label"), + ("Ink", "ink-inv", "#FFFFFF", + "05 title and feature titles ink core #FFFFFF; 04 title reads #FDF8F4 " + "through the warm blur"), + ("Ink", "mute", "#A9A9A9", + "05 feature subtitles #ACA9AB and #A5A4A5, 'Monthly' #A6A6A7, '/year' and " + "'$25 /month' #ACACAC: one grey, four readings, the mean"), + ("Ink", "skip-ink", "#BBBBBB", + "05 'Skip' ink core #B8B8B8-#BBBBBB"), + ("Ink", "foot", "#838383", + "05 footer line ink core, x 34.8-358.2 y 805-817"), + ("Ink", "free-ink", "#E07D54", + "05 FREE ink core (brightest 2%) inside x 135-180 y 645-662"), + ("Ink", "dots", "#C5C5C5", + "02/03 page dots, mode of each 6.2pt disc: #C4C4C4-#C5C5C5"), + ("Ink", "copy-mute", "#7F7F7F", + "06 body ink core on a grey-only window, 'review them.' x 200-245 y " + "482-493: #7F7F7F; a window that takes in the black 'Terms of Service' " + "span reads the span's pixels, not the grey"), + ("Ink", "placeholder", "#7E7E7E", + "07 'Ask Anything' ink core x 27-121 y 755-770"), + ("Ink", "sheet-copy", "#818181", + "14 the three body lines under 'Introducing Grok Bot', a plus-darker " + "grey: each ink pixel is the ground under it plus this minus white, " + "against the capture's ground at its 97th percentile over x 60-330 every " + "2pt of y 704-766 (228 at 704, 146 at 752). Line 1's core over 227 reads " + "#5B5B5B and line 3's over 146 #0E0E0E. Swept over the copy (x 20-390 y " + "700-770): #727272 9.30, #7C7C7C 8.52, #818181 8.32, #868686 8.37, " + "#8C8C8C 8.50"), + ("Ink", "store-mute", "#8A8A8D", + "15 'AI agents that do real work' (x 155-326 y 173-187), 'News', 'Version " + "1.8.0', '1d ago' and the chevron: ink core #8A8A8D on each"), + ("Ink", "store-val", "#8E8E92", + "15 '4.9' x 52-84 y 318-334 ink core #8E8E92; '18+', '#19', 'Years', " + "'Productivity', 'X Corp' and the stars the same to a level"), + ("Ink", "store-label", "#B1B1B4", + "15 '3.3K RATINGS' x 30-107 y 295-303: ink core #B1B1B4"), + ("Ink", "store-link", "#0088FF", + "15 'more' x 350-382 y 638-647 and the cloud glyph x 157-183 y 231-256: " + "ink core #0088FF on both"), + ("Ink", "store-pill-ink", "#CFCFD1", + "15 'Purchased' x 302-369 y 451-461 on the #EEEEEF pill: ink core #CFCFD1"), + ("Ink", "illo-label", "#333333", + "02 'Grok' beside the drawn app icon, x 98-124 y 321-330: ink core #333333"), + ("Ink", "illo-sub", "#5A5A5A", + "02 'Quickly start a new chat with Grok.' x 104-289 y 388-398: ink core " + "#5A5A5A; the title above it (x 174-219 y 361-377) and the pill's 'Grok' " + "(x 192-227 y 450-465) core #000000 and #080808, the ink token"), + + ("Radius", "r-phone", "52px", "iPhone 14 Pro/15/16 display corner, this repo's stand-in"), + ("Radius", "r-widget", "27px", + "01 widget corner insets 21.3/12.4/8.4/2.1 at 0.7/3.7/6.7/15.7 down: r 27"), + ("Radius", "r-card", "26px", + "02 card corner insets 16.2/12.2/8.6/5.1/2.4 at 2/4/7/11/16 down: r 26"), + ("Radius", "r-sheet", "30px", + "02 sheet corner insets 20.5/13.8/8.5/4.5 at 2.1/5.1/9.1/14.1 down: r 30"), + ("Radius", "r-illo", "53.5px", + "03 frame outer arc, leftmost frame pixel 28.5/13.8/5.4pt in at 8/21.4/" + "39.3pt down from 205.9: a 53.5pt circle; the inner arc (32.6/22.8/14.7 at " + "7.4/16.3/34.1 down from 215.5) is 42.4, the stroke less"), + ("Radius", "r-illo-tile", "14.3px", + "03 tile corner insets 10.7/6.2/3.6/0.9pt at 0.2/2/4.7/9.1 down from " + "278.4: r 14.3"), + ("Radius", "r-illo-sheet", "26.8px", + "02 drawn sheet corner: row y300, 1pt under the top edge at 299.1, white " + "begins at 76.9 against a sheet edge of 55.9: the inset of a 26.8 radius"), + ("Radius", "r-illo-card", "22px", + "02 the widget card's left edge leaves its fitted line 23pt below the " + "top-left corner and the top edge 25pt right of it, at a local scale of " + ".80 down and 1.09 across: 22 in the card's own plane"), + ("Radius", "r-sheet-v", "35px", + "04 sheet corner insets 20.9/15.1/10.2/6.2/2.7 at 3.4/6.4/10.4/15.4/21.4 " + "down from 403.6, left edge 8.5: r 35"), + ("Radius", "r-row", "13px", + "04 row card corner: the top edge's 1pt line reaches full coverage 8.1pt " + "in from the left edge (x 28.5 against 20.4), and r - sqrt(2r - 1) = 8.1 " + "at r 13 (12 gives 7.2, 14 gives 8.8)"), + ("Radius", "r-feat", "32px", + "05 feature card insets 14.9/10.5/6.9/3.8/1.7 at 5/8/12/17/23 down: r 32"), + ("Radius", "r-price", "18px", + "05 plan group insets 10.9/7.3/4.2/1.7 at 1.6/3.6/6.6/10.6 down: r 18"), + ("Radius", "r-plan", "15px", + "05 Yearly card insets 7.3/4.5/2.2/0.8 at 2.4/4.4/7.4/11.4 down: r 15"), + ("Radius", "r-chip", "22px", + "07 chip corner: the first chip's left edge (x 11) reaches full coverage " + "at y 697 and the top edge (675) at x 33, on a 52 tall chip whose ends are " + "not full semicircles; circle fit on the arc r 22"), + ("Radius", "r-composer", "28px", + "07 composer corner insets 21.3/15.0/10.3/6.3/3.0/1.0 at 1/3/6/10/15/21 " + "down from 737.3, left edge 10.3: r 28"), + ("Radius", "r-sheet-pro", "37px", + "14 the sheet's top-left corner, where its glass clears the scrim by 25 " + "levels: insets 18.67/9.0/3.33 at 4.7/12.7/21.7 down from its top edge " + "(outline 444.67-445.0, first white row 445.67) against a left edge of " + "8.0. r 37 gives 18.95/9.1/3.3, 36 gives 18.2/8.6/3.0, 38 19.7/9.6/3.7"), + ("Radius", "r-store", "38px", + "15 the App Store sheet's corner (top 62, left edge 0): insets 17.7/10.7/" + "6.0/3.3/1.7/0.7 at 5.7/11.3/17/22.7/28.3/34 down; r 38 gives 17.3/10.4/" + "6.4/3.5/1.6/0.5"), + ("Radius", "r-card", "18px", + "14 the Grok Bot card's bottom-left corner (left edge 23.3, bottom 660.7): " + "insets 7.3/3.7/2.0/0.7 at 3.3/6.7/10/13.3 up; r 18 gives 7.0/3.6/1.9/0.7"), + ("Radius", "r-tip", "14px", + "07 tooltip corner insets 9.7/7.7/6.0/4.0/1.7 at 1/2/3/5/8 down from 773, " + "left edge 215.3: r 14"), + ("Radius", "r-pill", "999px", + "01 pill 61.6 tall, 05 Skip 31.4, FREE 27.7 and CTA 56: all fully round " + "(CTA inset 19.5 at 1.5 down fits r 28)"), + + ("Type", "t-time", "600 15px/20px var(--x-font)", "iOS status bar clock"), + ("Type", "t-widget", "600 19.5px/24px var(--x-font)", + "01 'Grok' 42.4 wide, G 14.3 tall with overshoot; 20px sets 43.3 x 15.0 and " + "19.5px 42.2 x 14.6"), + ("Type", "t-h", "600 17px/22px var(--x-font)", + "02 'Widget' 55.8 wide, 'Home Screen Widget' 166.4 wide, both 16.1 cap-to-" + "descender: 17px; 05 CTA 'Upgrade to SuperGrok' 177.1 wide at the same"), + ("Type", "t-body", "400 17px/22px var(--x-font)", + "02/03 body pitch 21.9, F cap to g descender 15.6, line 1 315.8 wide on " + "both boards; 17px sets it 315.8"), + ("Type", "t-feat", "400 17.5px/22px var(--x-font)", + "05 'Longer conversations in Chat' 224.8 wide and 'Skip' 32.6: 17px sets " + "219.3 and 31.3, 17.5px 225.3 and 32.3. Same cap as t-body, wider set"), + ("Type", "t-row", "400 16.5px/21px var(--x-font)", + "04 'Select Audio Device' 147.7 x 12.9, 'Microphone Selection' 161.0 x " + "15.2: 17px sets 150.3/163.3, 16px 143.3/155.7, 16.5px 147.0/159.0"), + ("Type", "t-sheet", "600 16px/21px var(--x-font)", + "04 'Voice Settings' V cap 11.6 and 108.4 wide: one size under the nav"), + ("Type", "t-h1", "500 40.5px/50px var(--x-font)", + "05 'SuperGrok' 194.0 x 36.1 from S top to p foot with 10332 ink px; " + "swept in the board: 42px regular with .5px tracking hits the width but " + "sets 37.5 tall with 9116 ink px, 40.5px medium with .6px tracking sets " + "194.0 x 36.1 with 10053 and halves the title band's delta (16.5 to 10.9)"), + ("Type", "t-h2", "600 20px/25px var(--x-font)", + "05 'Unlock the full power of Grok' U cap 14.3, 263.2 wide"), + ("Type", "t-sub", "400 13.25px/18px var(--x-font)", + "05 feature subtitles W cap 9.4, pitch 21.8 under the title; footer T cap " + "9.4. Widths disagree on the size: 13px sets the two long subtitles 2.1% " + "narrow (211.0 for 215.5, 230.2 for 235.5) and the footer 1.2% narrow, " + "while '$25 /month' 67.8 x 12.5 is what 13px sets. 13.25px splits it"), + ("Type", "t-plan", "600 15px/20px var(--x-font)", + "05 'Monthly' M cap 10.3, 'Yearly' Y cap 10.7"), + ("Type", "t-unit", "400 15.4px/20px var(--x-font)", + "05 '/month' 11.2 tall (slash to h ascender), '/year' 13.8 (to y " + "descender); '/month' runs 85.0-133.6 (48.6) and '/year' 270.7-305.0 " + "(34.3), which 15px sets 47.3 and 33.5, 2.5% narrow"), + ("Type", "t-price", "700 20px/26px var(--x-font)", + "05 '300' digits 14.7 tall, '30' 15.2, which reads as 21px bold, but " + "'$300' runs 215.8-265.3 (49.5) and '$30' 42.1-80.9 (38.8), which 21px " + "sets 52.2 and 40.6, 5% wide, and the whole string 17.0 tall against " + "21px's 18.7. 20px carries the width"), + ("Type", "t-free", "700 12.5px/14px var(--x-font)", + "05 FREE 29.4 x 8.9; 12px bold sets 28.7 x 8.3, 12.5px 29.7 x 8.7, 13px " + "30.7 x 9.0"), + ("Type", "t-title", "600 21px/26px var(--x-font)", + "06 'Updates to our Terms of Service and' 304.0 wide (x 49.3-353.3), its " + "U cap 15.0 (y 379.0-394.0), cap tops 379.0 and 405.0: a 26 pitch; 21px " + "semibold has a 15.05 cap"), + ("Type", "t-copy", "400 14px/19px var(--x-font)", + "06 body: W cap 10.0, cap tops 444.7 / 463.7 / 482.7 (19 pitch), line 2 " + "305.3 wide (48.0-353.3); 14px has a 10.03 cap"), + ("Type", "t-link", "400 16.75px/22px var(--x-font)", + "06 'Sign out' 61.7 wide (170.0-231.7), S 12.0 tall with overshoot; 17px " + "sets 63.0, 16.5px 61.1, 16.75px 62.1. The underline is one pt of ink " + "1.7 under the baseline (y 817.67-818.67)"), + ("Type", "t-btn", "600 15.5px/20px var(--x-font)", + "06 'Got it' 39.7 wide (181.3-221.0), G 11.7 tall with overshoot, the " + "'o' 8.3 wide; 14 'Upgrade to Access' 138.7 wide (132.0-270.7), U 11.0 " + "flat top to overshoot; 16px semibold sets 40.8 and 143.2, 15.5px 39.6 " + "and 138.8"), + ("Type", "t-hdr", "600 22px/28px var(--x-font)", + "07 'SuperGrok' 107.7 wide (x 53.3-161.0), 20.0 from S top to p foot, " + "and its glyphs wider than medium's at the same height: S 12.7 against " + "11.7, G 15.3 against 14.0, k 11.0 against 10.0 on the board at 500; " + "semibold sets 106.7, with .12px tracking 107.7"), + ("Type", "t-chip", "500 14px/20px var(--x-font)", + "07 'Build a Bot' 69.0 wide (58.0-127.0), 'Try Finance' 75.0 (198.0-273.0), " + "caps 10.0-10.3; 14px medium sets 69.3 and 74.7"), + ("Type", "t-ask", "400 16px/21px var(--x-font)", + "07 'Ask Anything' 93.0 x 14.3, A top to y foot (x 27.3-120.3); 17px " + "(t-body) sets 98.3 x 15.7 on the board, 16px 92.5 x 14.8"), + ("Type", "t-ctl", "400 14px/18px var(--x-font)", + "07 'Auto' in the model pill x 93.0-121.3 (28.3), cap 10.0: 14px regular"), + ("Type", "t-speak", "600 14.5px/18px var(--x-font)", + "07 'Speak' 42.3 wide (328.7-371.0) on the black pill, S 11.0 with " + "overshoot; 15px semibold sets 43.7, 14.5px 42.3, the same width the " + "430pt capture gave"), + ("Type", "t-sheet-h", "600 18.2px/22px var(--x-font)", + "14 'Introducing Grok Bot' 174.3 wide (28.7-203.0), I cap 13.0 " + "(679.67-692.67), 17.3 to the g foot; 18px sets 172.7 x 17.0 on the " + "board, 18.2px 174.3"), + ("Type", "t-sheet-copy", "400 15.25px/20px var(--x-font)", + "14 sheet body cap tops 708.3 / 728.3 / 748.3 (20 pitch), line 1 'AI " + "teammates you can give real work to. Bots can' 338.7 x 14.0 (x " + "28.0-366.7); 15px sets 333.7 x 13.3 on the board, 15.25px 339.2"), + ("Type", "t-card", "500 36.5px/44px var(--x-font)", + "14 'Grok Bot' on the card, 136.7 wide (155.3-292.0), cap 26.4 " + "(547.3-573.7): 36px medium sets 135.0 on the board, 36.5px 136.9"), + ("Type", "t-store-h", "700 21px/26px var(--x-font)", + "15 'Also Included In' 154.7 x 15.7 (x 20.7-175.3), 'What's New', " + "'Preview': 21px bold sets 155.0; 20.5px sets 151.3"), + ("Type", "t-store-title", "600 21px/26px var(--x-font)", + "15 'Grok Bot' beside the icon, 82.0 x 15.7 (x 155-237, G top to the k " + "foot): the same height as the section heads but 21px bold sets 84.3, " + "2.7% wide, and 21px semibold 82.2"), + ("Type", "t-store-sub", "400 14px/19px var(--x-font)", + "15 'AI agents that do real work' 171.3 wide (154.7-326.0); 14px sets " + "171.5"), + ("Type", "t-store-label", "600 11px/13px var(--x-font)", + "15 '3.3K RATINGS' 76.0 wide (30.3-106.3), 'AGE RATING' 66.3, 'CHART' " + "38.0, cap 8.0 (295.0-303.0): 11px semibold caps at 7.9"), + ("Type", "t-store-val", "700 21px/25px var(--x-font)", + "15 '4.9' 31.3 wide (52-83.3), '18+' 35.0, '#19' 32.3, digit tops 318.7: " + "21px bold sets 31.5 / 35.2 / 32.0"), + ("Type", "t-store-small", "400 11.5px/14px var(--x-font)", + "15 'Years' 29.7 wide (161.7-191.3), 'Productivity' 66.3 (249-315.3): " + "11.5px sets 29.5 / 66.0; 'News' under the bundle the same size"), + ("Type", "t-store-bundle", "400 16px/19px var(--x-font)", + "15 'Apps by SpaceXAI: AI,' cap tops 432.0 and 451.0 (19 pitch), A cap " + "11.3: 16px has 11.5"), + ("Type", "t-store-body", "400 14px/19px var(--x-font)", + "15 'Version 1.8.0' cap 569.3, the three release-note lines at 598.3 / " + "617.3 / 636.3 (19 pitch), V cap 10.0: 14px"), + ("Type", "t-store-btn", "600 13px/16px var(--x-font)", + "15 'Purchased' 66.7 wide (302.3-369.0), P cap 9.3: 13px semibold sets " + "66.4 with a 9.3 cap"), + ("Type", "t-illo-label", "500 11.5px/14px var(--x-font)", + "02 'Grok' beside the app icon: ink 25.9 x 8.9; the stack sets 600 12px " + "to 27.3 x 9.3 and 11.5px to 26.2 x 8.9. Weight and size swept over the " + "word's box: 500 11.5px 7.9, 600 11.5px 13.4, 400 11.5px 10.1"), + ("Type", "t-illo-title", "600 21.25px/26px var(--x-font)", + "02 sheet title 'Grok': ink 44.6 x 16.1; 700 21px sets 46.3 x 15.7, 22px " + "48.7 x 16.3, 600 22px 47.3 x 16.3. Swept over the word's box: 600 " + "21.25px 7.9, 600 21px 8.7, 500 21.5px 9.1, 700 21px 11.2, 700 22px 16.7"), + ("Type", "t-illo-sub", "400 11.25px/15px var(--x-font)", + "02 'Quickly start a new chat with Grok.': ink 184.7 x 10.7; 400 11.5px " + "sets 188.7 x 10.7, 12px 195.7 x 11.3. Swept over the line's box in .05 " + "steps: 11.25px 11.3, 11.2px 11.8, 11.3px 13.4, 11.5px 19.8"), + ("Type", "t-illo-pill", "600 15.5px/20px var(--x-font)", + "02 'Grok' in the widget pill, unprojected into the card's plane: ink " + "35.0 x 12.2; 600 16px sets 35.3 x 12.3, and projected back reads 34.8 " + "x 13.8 against the capture's 34.3 x 15.2, a taller face. Swept over " + "the word's box: 15.5px 27.9, 15px 28.3, 16px 34.7, 16.5px 40.1. Set in " + "the card's flat coordinates, before its matrix3d"), + + ("Metrics", "w", "393px", "iPhone 14 Pro/15/16 logical width"), + ("Metrics", "h", "852px", "iPhone 14 Pro/15/16 logical height"), + ("Metrics", "status", "54px", "iOS status bar, Dynamic Island devices"), + ("Metrics", "gutter", "16px", + "02 card x 16.1-376.8; 04 buttons x 16.3 and 333.2-377"), + ("Metrics", "gutter-w", "20px", + "05 card x 20.5-372.3, plan group and CTA the same"), + ("Metrics", "tap", "44px", + "02 back disc 44.1 x 43.7; 04 X and grid buttons 43-43.7"), + ("Metrics", "sheet-top", "59px", "02/03 sheet ground starts at 58.9"), + ("Metrics", "sheet-top-v", "403.6px", "04 sheet edge, col x100"), + ("Metrics", "widget", "162.4px", "01 widget 24.1-186.5 both axes"), + ("Metrics", "disc", "40px", "05 icon discs 40 x 39.8, left edge 40.3"), + ("Metrics", "w-pro", "402px", + "iPhone 16 Pro logical width: cp6, cp7 and cp13-cp15 are 1206 x 2622 at 3 px/pt"), + ("Metrics", "h-pro", "874px", "iPhone 16 Pro logical height"), + ("Metrics", "sheet-v-blur", "4px", + "04 sigma of the blur read off the voice pill's edge, the one sharp edge the capture holds under the sheet: across x 270-300 at y 776/784/792 the ramp from the ground (40) to the pill (74) is 10pt for 10-90%, down x 310/334/358 over y 755-775 it is 8pt, 3.1-3.9 sigma; blur(4px). A sweep cannot read it: it walks to 44px+ because blurring the generated scene away hides the scene's own error (sheet band 13.3 at 44px against 16.3 at 4px)"), + ("Metrics", "illo-stroke", "10px", + "03 the drawn frame's stroke: 10.0pt at the sides (x 45.8-55.8), 9.6 at " + "the top (y 205.9-215.5); one border"), + ("Metrics", "status-pro", "59px", + "iOS status bar on the 402pt device: 07 clock and cluster ink y 25.7-39.3, " + "x 44.7-366.7, no island on a screenshot; the band the template bar " + "covers on 06-07 and 13-15, and where their scoring starts"), + # ---- 08-12: the voice picker and the settings sheet ---- + ("Font", "mono", 'ui-monospace,"SF Mono",Menlo,monospace', + "12 the version line: every glyph of 'VERSION 1.3.42 (BUILD 2776)' sets on " + "one pitch, 6.95pt per character over 27 characters (187.4 wide); a " + "monospaced face, the platform's"), + ("Surface", "voice-sheet", "#EDEDEE", + "08/09 the voice card's interior, col x196 405-700 and row y520 outside the " + "orb: flat #EDEDEE once the export's cast is taken out (README, colour " + "normalisation). Its 1pt edge reads #FCFAFC, card white"), + ("Surface", "nav-well", "#C8C8C9", + "08/09 the tints under the nav: the menu disc 17.8-60.7 x 63.1-106.9, the " + "Ask pill from 130.3 x 69.4-99.8, the compose disc from 335.4 x 64.0-106.9, " + "all flat #C8C8C9, three levels under dim"), + ("Surface", "avatar", "#F0F0F0", + "10 the profile disc 32.1-91.9 x 180.2-240.4, flat #F0F0F0 around the glyph"), + ("Surface", "toggle-off", "#C5C4C7", + "11 'Open App in Voice Mode' track 300.3-362.7 x 283.0-310.7, flat #C5C4C7 " + "beside its white knob 302.0-339.1 x 285.3-308.9"), + ("Line", "card-line", "#EAEAEA", + "10 the rule between rows, x 64.3-360.7 at y 373.9-374.8 and every 52 " + "below: two capture pixels (0.9pt) of #EAEAEA between white rows, no " + "solve needed; drawn 0.9pt tall so the same two pixels carry it"), + ("Line", "voice-shadow", "rgba(0,0,0,.11)", + "08/09 the ground beside the card reads 7-11 levels under dim, 3 above " + "it. Swept as 0 4px 16px over the bands beside the card: .10 leaves them " + "+0.6/+0.4, .11 +0.2/-0.0, .12 -0.5/-0.8, .14 -1.6/-2.1; 0 2px 10px and " + "0 6px 24px score worse at every alpha"), + ("Ink", "voice-sub", "#5E5E5E", + "08/09 'Upbeat Female', 'Soothing Female' and 'Swipe to explore more " + "voices' ink core #5E5E5E"), + ("Ink", "dot-off", "#A6A3A7", + "08/09 the three inactive page dots, mode #A6A3A7 across y 707.1-713.4; the " + "active one is ink"), + ("Ink", "voice-btn", "#090709", + "09 the Continue pill 46.5-347.2 x 746.1-796.5, 99.4% flat #090709: the " + "capture's black, 9 levels above btn, which the same export reads on 07"), + ("Ink", "section-ink", "#787878", + "10/11/12 'General', 'Voice', 'Data & Information', 'Subscription' ink " + "core #787878, three screens"), + ("Ink", "sec-ink", "#7C7C7C", + "10 'English' core #7C7C7C, the email line #7B7B7B: one secondary ink. " + "07's placeholder reads #7D7D7D off a 3 px/pt capture, kept apart because " + "that is another device's export"), + ("Ink", "danger", "#BE484C", + "12 'Sign Out', the label: its 20 most-covered pixels average #BE484C " + "(darkest 2% by luminance #AE4E52). The glyph beside it cores at #E83B43, " + "a brighter red no ink this dark could give, and is its own crop"), + ("Ink", "version-ink", "#C2C2C2", + "12 'VERSION 1.3.42 (BUILD 2776)' ink core #C3C1C3, the lightest type on " + "the set"), + ("Radius", "r-voice", "37.5px", + "08/09 the voice card's top corners: circle fit to its edge 37.5 (err " + "4.2). Its bottom corners, fit 50.5 with a poor residual, arrive as pixels " + "in the band crop"), + ("Radius", "r-modal", "39.5px", + "10/11/12 the sheet's top corners, circle fit on the dim/sheet edge 39.5"), + ("Radius", "r-group", "25.5px", + "10 the settings cards, fit 25.5 at x 16.1 / y 323.1 on the sheet"), + ("Type", "t-nav", "500 16px/22px var(--x-font)", + "08/09 'Ask' 26.3 x 12.0, 'Imagine' 56.7 wide: 500 17px sets 28.5 / 59.8, " + "16px 26.8 / 56.3"), + ("Type", "t-voice", "600 16.25px/21px var(--x-font)", + "08/09 'Voice Selection' 115.5 wide, 'Ara' 24.5, 'Eve' 25.0, 09 'Continue' " + "67.4: 600 17px (t-h) sets 120.4 / 25.9 / 26.3 / 70.5, 16.25px 115.1 / 24.8 " + "/ 25.1 / 67.4"), + ("Type", "t-mail", "400 15.9px/20px var(--x-font)", + "10 'alexsmith.mobbin+1@gmail.-' 207.4 wide, 'com' 29.4: 400 15px sets " + "195.8 / 27.7, 15.9px 207.5 / 29.4. 'Alex Smith' above it is t-h: 83.0 " + "against 17px semibold's 82.8"), + ("Type", "t-section", "600 15px/20px var(--x-font)", + "10/11/12 'General' 53.1 x 11.2 cap, 'Voice' 37.9, 'Data & Information' " + "132.0, 'Subscription' 88.8: 600 15.5px sets 55.3 / 39.3 / 136.1 / 91.9, " + "15px 53.5 / 38.0 / 131.7 / 88.9"), + ("Type", "t-voice-sub", "400 16px/21px var(--x-font)", + "08/09 'Upbeat Female' 108.4 x 14.7 (cap to descender), 'Soothing Female' " + "120.4: 400 16px sets 108.6 / 120.2"), + ("Type", "t-hint", "400 14.25px/18px var(--x-font)", + "08 'Swipe to explore more voices' 190.5 x 12.9: 400 14px sets 186.9, " + "14.25px 190.2"), + ("Type", "t-version", "400 11.65px/16px var(--x-mono)", + "12 'VERSION 1.3.42 (BUILD 2776)' 186.9 x 11.6, parentheses to their " + "full height: 12px sets 192.3 x 10.7, 11.65px 186.7; the face's parens " + "are shorter than the capture's, so the width is what this fits"), + ("Metrics", "row-s", "52px", + "10/11 settings rows: cap tops 343.0/394.3/446.5/498.3/550.9 (pitch " + "51.3-52.6), a three-row card 156.1 tall, rules every 52.0"), + ("Metrics", "sheet-blur", "19px", + "14 the glass sheet's backdrop blur, swept with glass-sheet over the Got " + "it pill seen through the sheet (x 40-360 y 764-784): at .5 white, 14px " + "sits -6.63, 16px -3.76, 18px -0.92, 19px +0.17, 20px +1.57, 28px +11.9; " + "the same band at .52/14px -2.47 and .55/14px +3.12"), + ("Metrics", "sheet-top-s", "58.7px", + "10/11/12 the sheet's edge, col x100: dim to 58.7, the header band from there"), +] + + +def _root(): + """One :root block, byte-identical in every board. No `}` inside it: + refkit tokens reads it with a non-greedy regex.""" + out, seen = [":root{"], None + for group, name, value, _ in TOKENS: + if group != seen: + out.append("" if seen else None) + out.append(" /* %s */" % group) + seen = group + out.append(" --x-%s:%s;" % (name, value)) + return "\n".join(x for x in out if x is not None) + "\n}" + + +TOKENS_CSS = _root() + +# ------------------------------------------------------------------ art ---- +# Boxes (pt) patched out of a capture before it is cropped: everything on the +# photo and the sheet that the boards draw again in CSS. Each box is filled +# with a Coons patch from its own four edges, which is exact on the smooth +# grounds these sit on and continuous at the boundary by construction. +INPAINT = { + "i4": ("cp4", [ + (40, 16, 105, 42), (278, 18, 366, 40), # status bar clock and glyphs + (130, 8, 263, 52), # Dynamic Island + (14, 61, 62, 110), (331, 61, 380, 110), # X and grid buttons + (337, 121, 376, 158), (337, 174, 376, 213), (337, 227, 376, 265), + (343, 288, 367, 304), # side stack and its chevron + (176, 406, 217, 416), # grabber + (138, 430, 255, 453), (325, 417, 372, 464), # title, close disc + (32, 502, 187, 522), (331, 498, 360, 526), # row 1 label and icon + (32, 565, 201, 588), (330, 560, 361, 590), # row 2 label and icon + ]), + "i5": ("cp5", [ + (40, 16, 105, 42), (278, 18, 366, 40), # status bar clock and glyphs + (312, 64, 376, 102), # Skip + (95, 103, 298, 147), (61, 151, 334, 178), # title, subtitle + (19, 617, 374, 716), (19, 729, 374, 788), # plan group, CTA + (30, 802, 364, 820), # footer + ]), + # 08/09: the band that carries the voice card's bottom corners and its + # shadow, with the page dots and the hint / pill patched out; 10-12: the + # header band (material, close disc, the fade below it) with its title out. + "i8": ("cp8", [(172.0, 705.5, 222.0, 715.0), (100.0, 764.0, 294.0, 780.5)]), + "i9": ("cp9", [(172.0, 705.5, 222.0, 715.0), (45.0, 744.5, 349.0, 798.0)]), + "i10": ("cp10", [(162.5, 88.5, 230.5, 108.0)]), + "i11": ("cp11", [(162.5, 88.5, 230.5, 108.0), (31.5, 140.5, 72.0, 154.5)]), + "i12": ("cp12", [(162.5, 88.5, 230.5, 108.0)]), +} +# 05's feature card: un-apply the material inside it, then patch its 1pt +# edge, its four corner arcs, the icon discs and the nine lines of type. +CARD = (20.5, 199.0, 372.3, 523.8) +CARD_PATCH = ([(19.0, 197.5, 374.0, 201.0), (19.0, 522.0, 374.0, 525.5), + (19.0, 197.5, 22.5, 525.5), (370.5, 197.5, 374.0, 525.5), + (19.0, 197.5, 53.0, 233.0), (340.0, 197.5, 374.0, 233.0), + (19.0, 490.0, 53.0, 525.5), (340.0, 490.0, 374.0, 525.5)] + + [(39, cy - 21.5, 82, cy + 21.5) + for cy in (239.1, 299.1, 360.25, 422.45, 483.8)] + + [(93, y0, 350, y1) for y0, y1 in + ((221, 242), (243, 260), (281, 302), (303, 320), (340, 361), + (362, 383), (402, 423), (424, 445), (475, 496))]) + + +def _coons(a, box, s=SCALE): + import numpy as np # noqa: local dep + x0, y0, x1, y1 = [round(v * s) for v in box] + h, w, band = y1 - y0, x1 - x0, 2 + + def edge(v, k=9): # a smoothed profile: texture along an + v = np.pad(v, ((k // 2, k // 2), (0, 0)), mode="edge") # edge would + return np.stack([np.convolve(v[:, c], np.ones(k) / k, "valid") # streak + for c in range(3)], 1) # across + top, bot = edge(a[y0 - band:y0, x0:x1].mean(0)), edge(a[y1:y1 + band, x0:x1].mean(0)) + lef, rig = edge(a[y0:y1, x0 - band:x0].mean(1)), edge(a[y0:y1, x1:x1 + band].mean(1)) + U, V = np.meshgrid((np.arange(w) + .5) / w, (np.arange(h) + .5) / h) + U, V = U[..., None], V[..., None] + a[y0:y1, x0:x1] = ((1 - V) * top + V * bot + (1 - U) * lef[:, None] + + U * rig[:, None] + - ((1 - U) * (1 - V) * top[0] + U * (1 - V) * top[-1] + + (1 - U) * V * bot[0] + U * V * bot[-1])) + + +def _source(ref, cache): + """A capture as an RGB image, patched first if crops.json asks for i4/i5/i8-i12.""" + from PIL import Image # noqa: local dep + import numpy as np + if ref in cache: + return cache[ref] + if ref not in INPAINT: + cache[ref] = Image.open(REFS_DIR / (ref + ".png")).convert("RGB") + return cache[ref] + src, boxes = INPAINT[ref] + a = np.asarray(Image.open(REFS_DIR / (src + ".png")).convert("RGB")).astype(float) + for box in boxes: + _coons(a, box, scale_of(src)) + if ref == "i5": + x0, y0, x1, y1 = [round(v * SCALE) for v in CARD] + a[y0:y1, x0:x1] = np.clip((a[y0:y1, x0:x1] - 255 * .067) / (1 - .067), 0, 255) + for box in CARD_PATCH: + _coons(a, box) + cache[ref] = Image.fromarray(np.clip(a + .5, 0, 255).astype("uint8")) + return cache[ref] + + +# The three glyphs on 04's voice sheet: white ink the capture shows over the +# sheet's own blurred ground, which is not on the board any more (see s04). +KEYED = {"04-ic-close", "04-ic-airplay", "04-ic-person"} + + +def cut(): + """Refresh assets/art/ from assets/refs/ at the boxes in crops.json.""" + if not REFS_DIR.exists(): + return + ART_DIR.mkdir(parents=True, exist_ok=True) + cache, n = {}, 0 + for cid, (ref, x0, y0, x1, y1) in CROPS.items(): + if not (REFS_DIR / (INPAINT.get(ref, (ref,))[0] + ".png")).exists(): + continue + box = tuple(round(v * scale_of(ref)) for v in (x0, y0, x1, y1)) + im = _source(ref, cache).crop(box) + if cid in KEYED: + # A white glyph the capture shows through the voice sheet: its + # ground is the sheet, which the board now draws, so the crop + # keeps the glyph's coverage and drops the ground. Ground is the + # median of the 1pt margin the box carries; coverage per pixel is + # the largest channel's (p - g) / (255 - g), the ink white. + import numpy as np + from PIL import Image + a = np.asarray(im.convert("RGB")).astype(float) + m = np.concatenate([a[:2].reshape(-1, 3), a[-2:].reshape(-1, 3), + a[:, :2].reshape(-1, 3), a[:, -2:].reshape(-1, 3)]) + g = np.median(m, axis=0) + cov = np.clip(((a - g) / (255 - g)).max(axis=2), 0, 1) + out = np.empty(a.shape[:2] + (4,), dtype="uint8") + out[..., :3] = 255 + out[..., 3] = np.round(cov * 255) + im = Image.fromarray(out, "RGBA") + im.save(ART_DIR / (cid + ".png"), optimize=True) + n += 1 + print("%-24s %6d crops" % ("assets/art/", n)) + + +def _uri(cid): + f = ART_DIR / (cid + ".png") + return ("data:image/png;base64," + base64.b64encode(f.read_bytes()).decode() + if f.exists() else "") + + +def art(cid, style="", z=None, top=None): + """One , at the box it was measured from, snapped to the pixels + cut() took: a crop placed at its pt box lands up to half a capture + pixel from where it was cut, which reads as a one-pixel shift on every + glyph. top moves a crop placed more than once (the chevron).""" + ref, x0, y0, x1, y1 = CROPS[cid] + s = scale_of(ref) + w, h = round(x1 * s) - round(x0 * s), round(y1 * s) - round(y0 * s) + x, y = round(x0 * s), round((top if top is not None else y0) * s) + return ('' + % (_uri(cid), x / s, y / s, w / s, h / s, + ";z-index:%d" % z if z else "", ";" + style if style else "")) + + +ICON_DIR = OUT / "assets" / "icons" + + +def icon(name, colour): + """One inline from assets/icons/.svg, at the ink box its + viewBox holds (pt), so the drawing is 1:1 with the measurement and the + canvas's inspector names it as a vector asset.""" + svg = (ICON_DIR / (name + ".svg")).read_text().strip() + x, y, w, h = (float(v) for v in re.search(r'viewBox="([^"]+)"', svg).group(1).split()) + return svg.replace('' + '' + '' + '' + '' + '' + '' + '' + '' + '') + + +def statusbar(colour="var(--x-ink)", time="9:41", rec=False, dx=0): + """The template bar. dx shifts the right cluster (and widens the clock's + centring box by the same) for the 402pt boards.""" + return ('
%s' + '
%s
%s
' + % (colour, '
' if rec else "", + ' style="width:%.1fpx"' % (142.4 + dx) if dx else "", time, dx, SB_ICONS)) + + +def home(colour="var(--x-ink)"): + return '
' % colour + + +# ----------------------------------------------------------------- emit ---- +def page(title, body, extra_css=""): + html = ('\n\n\n\n' + '%s\n\n\n\n%s\n\n\n' + % (title, TOKENS_CSS, BASE, PHONE, extra_css, body)) + return html.replace("--x-", "--%s-" % P) + + +def write(name, html): + (OUT / (name + ".html")).write_text(html) + print(name, len(html)) + + +# ------------------------------------------------------- the line box ---- +# Every string on these boards is placed by the top of its ink, because that +# is what refkit measures. Chrome puts the cap top of a line at +# lh/2 - 0.3455*size +# below the box top -- half-leading (lh - 1.162*size)/2 plus the gap between +# the ascent (0.952em) and the cap height (0.7165em) of the platform face. +TY = {"t-time": (15, 20), "t-widget": (19.5, 24), "t-h": (17, 22), "t-body": (17, 22), + "t-feat": (17.5, 22), "t-row": (16.5, 21), "t-sheet": (16, 21), "t-h1": (40.5, 50), + "t-h2": (20, 25), "t-sub": (13.25, 18), "t-plan": (15, 20), "t-unit": (15.4, 20), + "t-price": (20, 26), "t-free": (12.5, 14), "t-title": (21, 26), "t-copy": (14, 19), + "t-link": (16.75, 22), "t-hdr": (22, 28), "t-chip": (14, 20), "t-ctl": (14, 18), + "t-btn": (15.5, 20), "t-sheet-h": (18.2, 22), "t-sheet-copy": (15.25, 20), "t-card": (36.5, 44), + "t-store-h": (21, 26), "t-store-title": (21, 26), "t-store-sub": (14, 19), "t-store-label": (11, 13), + "t-store-val": (21, 25), "t-store-small": (11.5, 14), "t-store-bundle": (16, 19), + "t-store-body": (14, 19), "t-store-btn": (13, 16), "t-ask": (16, 21), + "t-speak": (14.5, 18), "t-nav": (16, 22), "t-voice": (16.25, 21), "t-mail": (15.9, 20), + "t-section": (15, 20), "t-voice-sub": (16, 21), "t-hint": (14.25, 18), + "t-version": (11.65, 16), "t-illo-label": (11.5, 14), + "t-illo-title": (21.25, 26), "t-illo-sub": (11.25, 15), "t-illo-pill": (15.5, 20)} + + +def boxtop(ink_top, tk): + size, lh = TY[tk] + return ink_top - (lh / 2 - 0.3455 * size) + + +def tx(x, ink_top, s, tk="t-body", col=None, w=None, extra="", attrs=""): + """One run of type, positioned by the top of its ink.""" + return ('
%s
' + % (attrs, x, boxtop(ink_top, tk), tk, + ";color:%s" % col if col else "", + ";width:%.1fpx" % w if w else "", extra, s)) + + +def txc(ink_top, s, tk="t-body", col=None, x=0.0, w=393.0, extra="", attrs=""): + """Centred type. The width is the box it centres in, not the ink.""" + return tx(x, ink_top, s, tk, col, w, ";text-align:center" + extra, attrs) + + +def box(x, y, w, h, style="", cls="b", inner="", attrs=""): + return ('
%s
' % (cls, attrs, x, y, w, h, style, inner)) + + +def circle(x, y, d, style=""): + return box(x, y, d, d, "border-radius:50%;" + style) + + +# --------------------------------------------------------------- screens ---- +SCREEN_CSS = """.t,.b,.a,.ic{position:absolute} +.a,.ic{display:block} +.ic{overflow:visible} +.t{white-space:nowrap} +.u{font:var(--x-t-unit)} +.k{color:var(--x-ink)} +s{text-decoration:line-through}""" + +# The one thing here that is decoration rather than measurement: the halo +# under 02's back disc reads #F2F2F2 four levels under the #F6F6F6 sheet just +# above it and #EFEFEF eleven levels under it 8-19pt below, which is what +# this shadow puts back. +SH = "box-shadow:0 5px 16px rgba(0,0,0,.07)" +# 07's chips: col x30 reads #F5F5F5 to 780.7 and #F2F2F2 from there to 782.3, +# with no halo at the sides (row 752 goes straight from the chip to #FFFFFF). +CHIP_SH = "box-shadow:0 1.6px 0 #F2F2F2" +COMPOSER_SH = "0 4px 14px var(--x-composer-shadow)" + + +def screen(title, inner, sb="var(--x-ink)", hm="var(--x-ink)", bg=None, rec=False, big=False, + under=""): + """One phone artboard. No board background: the phone floats on the canvas. + big: the 402 x 874 device, template status bar over the content, no home + indicator (the captures show none); hm None hides it on a 393pt screen. + under: content the status bar sits on top of (14's dimmed page).""" + style = ("width:var(--x-w-pro);height:var(--x-h-pro);" if big else "") + \ + ("background:%s" % bg if bg else "") + return page(NAME + " - " + title, + '
%s%s%s%s
' + % (' style="%s"' % style if style else "", under, + statusbar(sb, rec=rec, dx=9 if big else 0), inner, + "" if big or hm is None else home(hm)), + SCREEN_CSS) + + +# -------------------------------------------------------------------- 01 ---- +# The small widget on the gallery's grey. Widget 24.1-186.5 both axes; the +# pill 37.5-173.0 x 94.5-156.1; two 62.5 x 63.8 wells at 164.6 down. +def s01(): + return screen("Home Screen widget", + box(24.1, 80.3, 162.4, 162.4, "border-radius:var(--x-r-widget);background:var(--x-card)") + + box(37.5, 94.5, 135.5, 61.6, "border-radius:var(--x-r-pill);background:var(--x-well)") + + art("01-ic-mark") + tx(99.0, 118.6, "Grok", "t-widget") + + box(37.5, 164.6, 62.5, 63.8, "border-radius:var(--x-r-pill);background:var(--x-well)") + + box(110.5, 164.6, 62.5, 63.8, "border-radius:var(--x-r-pill);background:var(--x-well)") + + art("01-ic-compose") + art("01-ic-wave"), + bg="var(--x-ground)") + + +# ----------------------------------------------------------------- 02-03 ---- +# The widget guide: a sheet from 58.9 with a 30pt corner, a white card at +# 16.1-376.8 x 137.0-665.4, the phone illustration cropped, two body lines on +# a 21.9 pitch at 548.6 and 570.5, and four page dots on a 16 pitch centred at +# y 641.45 with the active one a 12pt sparkle cut from the capture. +# The guide illustration is a drawing of a phone, and it is drawn: a frame +# with one border, a pill, ten rounded squares, four side buttons, all +# fading out through a mask whose stops are the capture's own fade profile +# (the frame column reads 170/172/176/182/186/194/205/217/226/235/245/249/251 +# at 8px steps from y 470.9, i.e. opacity 1 -> .04 over 44pt). Origin 43,205. +ILLO_MASK = ("-webkit-mask-image:linear-gradient(#000 265.9px,rgba(0,0,0,.93) 273px," + "rgba(0,0,0,.81) 280.1px,rgba(0,0,0,.59) 287.3px,rgba(0,0,0,.34) 294.4px," + "rgba(0,0,0,.12) 301.6px,rgba(0,0,0,.05) 308.7px,rgba(0,0,0,.04) 310px)") +ILLO_TILES = [(x, y) for y in (73.4, 139.0, 204.5) for x in (30.1, 95.0, 159.9, 225.1)][:10] + + +def illo_phone(inner="", scrim=False): + fr = "background:var(--x-illo-frame)" + body = (box(2.8, 0.9, 301.6, 330.0, + "box-sizing:border-box;border:var(--x-illo-stroke) solid var(--x-illo-frame);" + "border-radius:var(--x-r-illo);background:var(--x-illo-screen)") + + "".join(box(x, y, 52.2, 52.2, "border-radius:var(--x-r-illo-tile);" + "background:var(--x-illo-tile)") for x, y in ILLO_TILES) + + (box(12.8, 10.9, 281.6, 320.0, "border-radius:43.5px 43.5px 0 0;" + "background:var(--x-illo-scrim)") if scrim else "") + + box(110.0, 21.6, 87.0, 25.0, "border-radius:12.5px;" + fr) + + box(1.0, 130.9, 1.8, 28.3, fr) + box(1.0, 180.9, 1.8, 46.6, fr) + + box(1.0, 239.8, 1.8, 45.3, fr) + box(304.4, 197.6, 1.9, 73.2, fr) + + inner) + return box(43.0, 205.0, 307.0, 310.0, "overflow:hidden;" + ILLO_MASK, inner=body, + attrs=" data-clip-ok") + + +# 02's widget card is a flat 130 x 90.9 rectangle seen in perspective. Its +# four edges were fitted to the capture (top y = .1355x + 436.67, bottom +# y = .0908x + 641.72, left x = -.0402y + 212.67, right x = .0364y + 459.80 +# in capture px of the illustration crop) and the corners they meet at, +# (86.6,206.5) (213.3,223.7) (216.3,305.9) (83.1,293.8) in pt from the +# illustration's origin, fix the homography below. The flat aspect is the +# one that makes the pill's 'Grok' set at the platform face's own aspect +# (2.86 wide per ink height); the pill's caps unproject to circles at any +# aspect from 1.1 to 1.4, so they cannot decide it. The pill and its label +# are the capture's edges unprojected through the same matrix: pill u +# .0707-.9388, v .1124-.7353; ink u .480-.749, v .358-.492. +ILLO_CARD = ("transform-origin:0 0;transform:matrix3d(1.08765,0.250679,0,0.000530578," + "-0.084579,0.797395,0,-0.000553983,0,0,1,0,86.5763,206.522,0,1)") + + +def illo_sheet(): + """02: the add-widget sheet drawn over the phone, origin 43,205.""" + sheet = "border-radius:var(--x-r-illo-sheet) var(--x-r-illo-sheet) 0 0;" + ghost = "background:var(--x-well);filter:blur(1.5px)" + pill = box(9.19, 10.22, 112.85, 56.63, "border-radius:var(--x-r-pill);" + "background:var(--x-well)", + inner=tx(53.21, 22.35, "Grok", "t-illo-pill", col="var(--x-ink)")) + return (box(12.8, 10.9, 281.6, 319.1, "overflow:hidden;border-radius:43.5px 43.5px 0 0", + inner=box(0, 83.2, 281.6, 236.0, sheet + "box-shadow:0 0 24px var(--x-illo-sheet-shadow)")) + + box(12.8, 94.1, 281.6, 236.0, sheet + "background:var(--x-card)") + + box(140.8, 97.4, 25.4, 3.6, "border-radius:1.8px;background:var(--x-illo-grabber)") + + tx(55.1, 116.2, "Grok", "t-illo-label", col="var(--x-illo-label)") + + txc(155.9, "Grok", "t-illo-title", col="var(--x-ink)", x=12.8, w=281.6) + + txc(182.7, "Quickly start a new chat with Grok.", "t-illo-sub", + col="var(--x-illo-sub)", x=12.8, w=281.6) + + circle(100.6, 283.5, 42.0, ghost) + circle(165.3, 287.5, 31.3, ghost) + + box(0, 0, 130.0, 90.91, ILLO_CARD + ";border-radius:var(--x-r-illo-card);" + "background:var(--x-card);box-shadow:0 4px 28px var(--x-illo-card-shadow)", + inner=pill)) + + +def guide(n, title, l1, l2, active, illo): + dots = "" + for i in range(4): + cx = 172.5 + 16 * i + dots += (art("%02d-ic-sparkle" % n) if i == active + else circle(cx - 3.1, 638.35, 6.2, "background:var(--x-dots)")) + return screen(title, + box(0, 58.9, 393, 793.1, "border-radius:var(--x-r-sheet) var(--x-r-sheet) 0 0;" + "background:var(--x-sheet)") + + circle(16.1, 75.2, 44, "background:var(--x-card);" + SH) + art("02-ic-back") + + txc(91.5, "Widget", "t-h") + + box(16.1, 137.0, 360.7, 528.4, "border-radius:var(--x-r-card);background:var(--x-card)") + + txc(161.5, "Home Screen Widget", "t-h", x=16.1, w=360.7) + + illo + + txc(548.6, l1, "t-body", x=16.1, w=360.7) + + txc(570.5, l2, "t-body", x=16.1, w=360.7) + + dots, + bg="var(--x-dim)") + + +def s02(): + return guide(2, "Widget guide, step 4", + "Find Grok in the list, choose a widget size,", + "then tap Add Widget.", 3, + illo_phone(illo_sheet(), scrim=True) + art("02-ic-app") + + art("02-ic-close") + art("02-ic-mark")) + + +def s03(): + return guide(3, "Widget guide, step 1", + "From the Home Screen, touch and hold an", + "empty area until the apps jiggle.", 0, illo_phone()) + + +# -------------------------------------------------------------------- 04 ---- +# Voice settings over the companion scene. The scene (04-scene) is the one +# picture here the capture does not contain: under the sheet it is blurred +# and dimmed, so the asset is the capture above the sheet's edge (the patched +# frame i4) and, below it, a gpt-image-2 edit of that frame with the sheet's +# box masked out and the body's measured proportions in the prompt +# (scratch/scene4.py composes it; README.md has the candidates and scores). +# The sheet is drawn over it: a 4px backdrop blur read off the voice pill's +# edge, a .40 black tint fitted through it, two row cards that are a 1pt line +# and no fill, and under the blur the voice pill where the capture shows it. +# The capture shows no home indicator on this screen (x 196, y 842 is grass). +def s04(): + inv = "var(--x-ink-inv)" + side = "" + for cy, name in ((139.9, "focus"), (192.9, "hanger"), (245.9, "trash")): + side += circle(340.0, cy - 16, 32, "background:var(--x-glass)") + icon("04-" + name, "var(--x-side-ink)") + row = "border-radius:var(--x-r-row);border:1px solid var(--x-row-line)" + return screen("Voice settings", + art("04-scene") + + box(288.5, 767.4, 91.1, 33.9, "border-radius:var(--x-r-pill);background:var(--x-voice-pill)") + + circle(16.3, 63.4, 44, "background:var(--x-scrim-btn)") + art("04-ic-x") + + circle(333.2, 63.4, 44, "background:var(--x-scrim-btn)") + art("04-ic-grid") + + side + art("04-ic-chevron") + + box(8.5, 403.6, 384.5, 448.4, "border-radius:var(--x-r-sheet-v) var(--x-r-sheet-v) 0 0;" + "backdrop-filter:blur(var(--x-sheet-v-blur));background:var(--x-sheet-v)") + + box(20.4, 486.8, 352.8, 50.9, row) + box(20.4, 549.3, 352.8, 51.0, row) + + box(179.3, 408.6, 34.3, 4.9, "border-radius:var(--x-r-pill);background:var(--x-grabber)") + + txc(434.9, "Voice Settings", "t-sheet", inv) + + circle(327.5, 419.4, 42, "background:var(--x-scrim-btn)") + art("04-ic-close") + + tx(34.8, 506.2, "Select Audio Device", "t-row", inv) + art("04-ic-airplay") + + tx(34.7, 568.3, "Microphone Selection", "t-row", inv) + art("04-ic-person"), + sb=inv, hm=None, bg="#000", rec=True) + + +# -------------------------------------------------------------------- 05 ---- +# The SuperGrok paywall. The smoke hero is the capture (05-bg) with the type +# and the cards patched out; the feature card is a 6.7% white material with a +# .16 edge, its five rows placed by ink top, the icons in 40pt discs centred +# on each row's text block. The regular-weight strings on this screen set 3% +# wider than 17px does (t-feat); the semibold ones sit on the nominal sizes. +FEATURES = [ + ("rocket", 223.5, "Longer conversations in Chat", 245.3, "With Grok 4.1 - Fast & Expert mode"), + ("imagine", 284.1, "Make more images & videos", 305.1, "With Imagine 1.0 - longer, 720p videos"), + ("wave5s", 343.0, "Longer Voice Mode &", 364.5, "Companion chats"), + ("star", 405.4, "Priority access during", 426.9, "peak times"), + ("cube", 477.7, "Early access to new features", None, None), +] +DISC_Y = (239.1, 299.1, 360.25, 422.45, 483.8) + + +def s05(): + inv, mute = "var(--x-ink-inv)", "var(--x-mute)" + rows = "" + for (name, t1, s1, t2, s2), cy in zip(FEATURES, DISC_Y): + rows += (circle(40.3, cy - 20, 40, "background:var(--x-disc)") + art("05-ic-" + name) + + tx(95.1, t1, s1, "t-feat", inv)) + if t2: + rows += tx(95.1, t2, s2, "t-feat" if s2 in ("Companion chats", "peak times") else "t-sub", + inv if s2 in ("Companion chats", "peak times") else mute) + return screen("SuperGrok paywall", + art("05-bg") + + box(315.6, 67.6, 56.7, 31.4, "border-radius:var(--x-r-pill);background:var(--x-skip)") + + txc(77.0, "Skip", "t-feat", "var(--x-skip-ink)", 315.6, 56.7) + + txc(107.0, "SuperGrok", "t-h1", inv, extra=";letter-spacing:.6px") + + txc(156.1, "Unlock the full power of Grok", "t-h2", inv) + + box(20.5, 199.0, 351.8, 324.8, "border-radius:var(--x-r-feat);background:var(--x-material);" + "border:1px solid var(--x-material-line)") + + rows + + box(20.5, 618.4, 352.3, 96.6, "border-radius:var(--x-r-price);background:var(--x-price);" + "border:1px solid var(--x-price-line)") + + tx(42.0, 647.3, "Monthly", "t-plan", mute) + + tx(41.9, 672.7, '$30 /month', "t-price", mute) + + box(129.8, 640.1, 55.3, 27.7, "border-radius:var(--x-r-pill);background:var(--x-free-bg)") + + txc(647.7, "FREE", "t-free", "var(--x-free-ink)", 129.8, 55.3) + + box(197.0, 622.6, 172.0, 88.3, "border-radius:var(--x-r-plan);background:linear-gradient(to top right,var(--x-plan-lo),var(--x-plan-hi));" + "border:1px solid var(--x-plan-line)") + + tx(215.1, 638.4, "Yearly", "t-plan", inv) + + tx(214.6, 661.1, '$300 /year', "t-price", inv) + + tx(214.6, 684.7, "$25 /month", "t-sub", mute) + + box(20.0, 730.5, 353.0, 56.0, "border-radius:var(--x-r-pill);background:var(--x-card)") + + txc(753.0, "Upgrade to SuperGrok", "t-h", "var(--x-ink)", 20.0, 353.0) + + txc(805.6, "Terms of Service · Privacy Policy · Restore Purchases", + "t-sub", "var(--x-foot)"), + sb=inv, hm=inv, bg="var(--x-night)") + + +# At 3 px/pt Chrome sets a left-anchored string 0.7pt right of its box (the +# face's left bearing: .6-1.0 on every string measured against the capture, +# 1.3 for a leading F), so the 402pt boards place through it. The line-box +# model above holds to the tenth on this device: ten strings on 06, 07, 14 +# and 15 landed 0.3-0.7 low with a 0.5 drop, so there is none. +BEAR, DROP = 0.7, 0.0 + + +def txb(x, ink_top, s, tk="t-body", col=None, w=None, extra="", attrs=""): + return tx(x - BEAR, ink_top + DROP, s, tk, col, w, extra, attrs) + + +def txcb(ink_top, s, tk="t-body", col=None, x=0.0, w=402.0, extra="", attrs=""): + return txc(ink_top + DROP, s, tk, col, x, w, extra, attrs) + + +# -------------------------------------------------------------- 06, 13 ---- +# The terms notice: a white page, the mark cut from the capture, two title +# lines on a 26 pitch, three body lines on 19 with the two policy names in +# black, a 54pt black pill and an underlined link. 13 is the same page a +# beat after 'Sign out' was tapped: the pill's label is its spinner. +def terms(label): + mute = "var(--x-copy-mute)" + return (art("06-ic-mark") + + txcb(379.0, "Updates to our Terms of Service", "t-title") + + txcb(405.0, "and Acceptable Use Policy", "t-title") + + txcb(444.7, 'We’re updating our Terms of Service and', + "t-copy", mute) + + txcb(463.7, 'Acceptable Use Policy. Now’s a great chance to', + "t-copy", mute) + + txcb(482.7, "review them.", "t-copy", mute) + + box(20.0, 730.7, 362.0, 54.0, "border-radius:var(--x-r-pill);background:var(--x-btn)") + + label + + txcb(804.2, "Sign out", "t-link", + extra=";text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:1.7px")) + + +GOT_IT = txcb(751.8, "Got it", "t-btn", "var(--x-ink-inv)", 20.0, 362.0) + + +def s06(): + return screen("Terms update", terms(GOT_IT), bg="var(--x-page)", big=True) + + +def s13(): + return screen("Terms update, signing out", terms(art("13-spinner")), + bg="var(--x-page)", big=True) + + +# -------------------------------------------------------------------- 07 ---- +# The SuperGrok home: header mark and wordmark, the grey watermark mark, three +# suggestion chips (the third runs off the screen; only 'Try C' is visible, +# and Gmail, GitHub and Notion in its icon trio make it Connectors), and the +# composer card with a thin grey edge over a soft halo. +def s07(): + inv = "var(--x-ink-inv)" + chip = "border-radius:var(--x-r-chip);background:var(--x-chip);" + CHIP_SH + ctl = "background:var(--x-ctl)" + return screen("SuperGrok home", + art("07-ic-mark") + txb(53.3, 78.3, "SuperGrok", "t-hdr", extra=";letter-spacing:.12px") + + art("07-ic-watermark") + + box(11.0, 675.0, 132.7, 52.0, chip) + icon("07-bot", "var(--x-ink)") + + txb(58.0, 696.0, "Build a Bot", "t-chip") + + box(151.3, 675.0, 138.0, 52.0, chip) + art("07-ic-bank") + txb(198.0, 696.0, "Try Finance", "t-chip") + + box(297.0, 675.0, 105.0, 52.0, chip + ";border-radius:var(--x-r-chip) 0 0 var(--x-r-chip)") + # the three connector avatars, painted right to left so each white + # circle cuts the mark behind it, the way the capture shows them + + "".join(circle(cx - 10.83, 690.17, 21.67, "background:var(--x-card)") + + icon("07-" + n, "var(--x-ink)") + for cx, n in ((355.5, "notion"), (340.0, "github"), (324.5, "gmail"))) + + txb(374.3, 696.0, "Try C", "t-chip") + + box(10.3, 737.3, 381.3, 95.3, "border-radius:var(--x-r-composer);background:var(--x-composer);" + "box-shadow:0 0 0 .67px var(--x-composer-line)," + COMPOSER_SH) + + txb(27.0, 754.7, "Ask Anything", "t-ask", "var(--x-placeholder)") + + circle(21.0, 789.3, 32.7, ctl) + art("07-ic-plus") + + box(59.3, 789.3, 74.7, 32.7, "border-radius:var(--x-r-pill);" + ctl) + + art("07-ic-auto") + txb(93.0, 800.7, "Auto", "t-ctl") + + circle(255.3, 789.3, 32.7, ctl) + art("07-ic-mic") + + box(293.7, 789.5, 87.6, 32.3, "border-radius:var(--x-r-pill);background:var(--x-btn)") + + art("07-ic-wave") + txb(328.7, 800.2, "Speak", "t-speak", inv), + bg="var(--x-page)", big=True) + + +# -------------------------------------------------------------------- 14 ---- +# 'Introducing Grok Bot': the terms page under a scrim, a glass sheet with a +# dark outline, the blue card (blue lightening toward its top, a pale tilted +# ellipse in its top-left that fades out along its own width, and a thin +# darker ring 33pt outside it; the bot glyph and the NEW badge are crops), a +# heading, three body lines and the CTA pill. +CARD_CSS = ("border-radius:var(--x-r-card);background:linear-gradient(#6EB5FC,var(--x-card-blue) 110px);" + "overflow:hidden;transform:translateZ(0)") +# Both ellipses are one least-squares fit of this exact construction to the +# card at 1pt (README): the pale one, then the ring as the same ellipse grown +# by 33.4 with a 12.7px border, both rotated about their shared centre. +WASH = ('
' + '
') + + +def s14(): + inv = "var(--x-ink-inv)" + sheet = ("border-radius:var(--x-r-sheet-pro);background:var(--x-glass-sheet);" + "backdrop-filter:blur(var(--x-sheet-blur));-webkit-backdrop-filter:blur(var(--x-sheet-blur));" + "box-shadow:0 0 0 .67px var(--x-sheet-line),0 0 24px rgba(0,0,0,.15)," + "inset 0 1px 0 #FFF,inset 0 -1px 0 #FFF,inset 0 4px 4px -2px rgba(255,255,255,.5)") + # The body copy is iOS's plus-darker grey: each ink pixel is the ground under it + # plus the grey minus white, so the lines over the blurred Got it pill go near + # black. The ground is the capture's, every 2pt from y 704 (README); CSS has no + # plus-darker outside WebKit, so each line is filled with that ramp instead. + ground = (228, 227, 227, 226, 225, 223, 222, 220, 217, 214, 208, 202, 195, 186, 179, 174, + 169, 164, 160, 157, 154, 152, 150, 148, 146, 146, 146, 146, 147, 147, 148, 151) + grey = int(next(v for _, n, v, _ in TOKENS if n == "sheet-copy")[1:3], 16) + copy = "" + for top, line in ((708.3, "AI teammates you can give real work to. Bots can"), + (728.3, "sign in to your tools, use them just like you do,"), + (748.3, "and come back with finished work.")): + b = boxtop(top, "t-sheet-copy") + ramp = ",".join("#%02X%02X%02X %.2fpx" % ((max(0, g + grey - 255),) * 3 + (704 + 2 * i - b,)) + for i, g in enumerate(ground)) + copy += txb(27.7, top, line, "t-sheet-copy", + extra=";background:linear-gradient(%s);-webkit-background-clip:text;" + "background-clip:text;-webkit-text-fill-color:transparent" % ramp) + return screen("Introducing Grok Bot", + box(8.0, 445.3, 386.0, 420.7, sheet) + + box(172.3, 451.3, 57.3, 3.7, "border-radius:2px;background:var(--x-grabber-pro)") + + box(23.3, 460.7, 355.3, 200.0, CARD_CSS, inner=WASH, attrs=" data-clip-ok") + + art("14-ic-bot") + art("14-badge") + + txb(155.3, 547.3, "Grok Bot", "t-card", inv) + + txb(27.7, 679.7, "Introducing Grok Bot", "t-sheet-h") + + copy + + box(27.3, 786.0, 347.3, 47.3, "border-radius:var(--x-r-pill);background:var(--x-btn)") + + txcb(804.0, "Upgrade to Access", "t-btn", inv, 27.3, 347.3), + bg="var(--x-page)", big=True, + under=terms(GOT_IT) + box(0, 0, 402, 874, "background:var(--x-scrim-sheet)")) + + +# -------------------------------------------------------------------- 15 ---- +# The App Store product sheet for Grok Bot over the dimmed store: two glyph +# discs, the app icon (a crop), title, subtitle, the cloud, the four-column +# facts strip between two rules, the bundle row with its Purchased pill, +# What's New with the version line and three release notes, and the two +# preview cards (crops) running off the bottom. +def s15(): + mute, val = "var(--x-store-mute)", "var(--x-store-val)" + disc = "background:var(--x-store-disc);box-shadow:inset 0 0 0 .67px #D7D7D7" + rule = "background:var(--x-store-rule)" + clip = ' data-clip-ok' + cols = (68.3, 177.2, 282.2, 387.2) + return screen("App Store, Grok Bot", + box(0, 62.0, 402, 812, "border-radius:var(--x-r-store) var(--x-r-store) 0 0;" + "background:var(--x-card);box-shadow:0 -2px 16px rgba(0,0,0,.12)") + + circle(15.3, 77.3, 45.4, disc) + art("15-ic-close") + + circle(341.3, 77.3, 45.4, disc) + art("15-ic-share") + + art("15-icon") + + txb(155.0, 146.7, "Grok Bot", "t-store-title") + + txb(154.7, 173.7, "AI agents that do real work", "t-store-sub", mute) + + art("15-ic-cloud") + + box(20, 278.67, 382, 1, rule) + box(20, 366.67, 382, 1, rule) + + "".join(box(x, 305.7, 1, 34, rule) for x in (124.67, 229.67, 334.67)) + + "".join(txcb(295.0, t, "t-store-label", "var(--x-store-label)", cx - 70, 140, + extra=";letter-spacing:.1px", **({"attrs": clip} if cx > 350 else {})) + for cx, t in zip(cols, ("3.3K RATINGS", "AGE RATING", "CHART", "DEVELOPER"))) + + "".join(txcb(318.7, t, "t-store-val", val, cx - 40, 80) + for cx, t in zip(cols, ("4.9", "18+", "#19"))) + + art("15-ic-dev") + art("15-stars") + + txcb(344.7, "Years", "t-store-small", val, cols[1] - 40, 80) + + txcb(344.7, "Productivity", "t-store-small", val, cols[2] - 40, 80) + + txb(366.7, 344.7, "X Corp", "t-store-small", val, attrs=clip) + + txb(20.7, 392.3, "Also Included In", "t-store-h") + + art("15-bundle") + + txb(92.3, 432.0, "Apps by SpaceXAI: AI,", "t-store-bundle") + + txb(92.3, 451.0, "news, videos, social me…", "t-store-bundle") + + txb(92.3, 471.7, "News", "t-store-small", mute) + + box(289.0, 440.0, 93.0, 32.0, "border-radius:var(--x-r-pill);background:var(--x-store-pill)") + + txb(302.3, 451.7, "Purchased", "t-store-btn", "var(--x-store-pill-ink)") + + txb(20.7, 533.3, "What’s New", "t-store-h") + art("15-ic-chevron") + + txb(20.7, 569.3, "Version 1.8.0", "t-store-body", mute) + + txb(281.3, 569.3, "1d ago", "t-store-body", mute, w=100, extra=";text-align:right") + + txb(21.0, 598.3, "- Added select-and-copy on message text", "t-store-body") + + txb(21.0, 617.3, "- Added a confirm step when sharing a bot as a", "t-store-body") + + txb(21.0, 636.3, "template", "t-store-body") + + txb(281.3, 636.3, "more", "t-store-body", "var(--x-store-link)", w=100, extra=";text-align:right") + + txb(21.3, 694.0, "Preview", "t-store-h") + + art("15-preview-1") + art("15-preview-2"), + bg="var(--x-store-dim)", big=True) + + +# -------------------------------------------------------------- 08, 09 ---- +# The voice picker: a card on the dimmed home, its bottom corners and shadow +# cropped (08-band / 09-band, the dots and the hint or pill patched out and +# drawn again), everything above y700 CSS around the orb and the ghost line. +def voice(stem, orb, ghost, band, name, sub, foot): + return screen("Voice selection, " + name, + circle(17.8, 63.1, 43.5, "background:var(--x-nav-well)") + + box(130.3, 69.4, 50.7, 30.4, "border-radius:var(--x-r-pill);background:var(--x-nav-well)") + + circle(335.4, 64.0, 43.0, "background:var(--x-nav-well)") + + art("08-ic-menu") + art("08-ic-compose") + + tx(142.0, 78.9, "Ask", "t-nav") + tx(194.0, 78.9, "Imagine", "t-nav") + + box(8.0, 403.6, 377.4, 440.9, + "border-radius:var(--x-r-voice);background:var(--x-voice-sheet);" + "box-shadow:inset 0 0 0 1px var(--x-card),0 4px 16px var(--x-voice-shadow)") + + txc(434.8, "Voice Selection", "t-voice") + + art(orb) + txc(607.5, name, "t-voice") + txc(631.3, sub, "t-voice-sub", "var(--x-voice-sub)") + + art(ghost) + art(band) + + "".join(circle(cx - 3.15, 707.1, 6.3, "background:var(--x-%s)" + % ("ink" if k == (0 if stem == "08" else 1) else "dot-off")) + for k, cx in enumerate((176.7, 190.1, 203.65, 217.05))) + + foot, + bg="var(--x-dim)") + + +def s08(): + return voice("08", "08-orb", "08-ghost", "08-band", "Ara", "Upbeat Female", + txc(766.3, "Swipe to explore more voices", "t-hint", "var(--x-voice-sub)")) + + +def s09(): + return voice("09", "09-orb", "09-ghost", "09-band", "Eve", "Soothing Female", + box(46.5, 746.1, 300.7, 50.4, "border-radius:var(--x-r-pill);background:var(--x-voice-btn)") + + txc(765.1, "Continue", "t-voice", "var(--x-ink-inv)", x=46.5, w=300.7)) + + +# ---------------------------------------------------------- 10, 11, 12 ---- +# The settings sheet, three scroll states of one list. Cards are CSS at +# their measured tops; rows are 52 (row-s); every glyph is a crop at its own +# box; the header band (material, close disc, the fade under it) is a crop +# with its title patched out. A row's label None means the crop above +# carries that row (12's first row sits under the header). +def group(top, items, label=None, label_top=None): + n = len(items) + out = box(16.1, top, 361.3, 52.0 * n, "border-radius:var(--x-r-group);background:var(--x-card)") + if label: + out += tx(32.5, label_top if label_top else top - 24.85, label, "t-section", "var(--x-section-ink)") + for k, (text, ic, trail, col) in enumerate(items): + y = top + 52.0 * k + if k: + out += box(64.3, y - 1.1, 296.4, 0.9, "background:var(--x-card-line)") + if text is None: + continue + out += tx(64.3, y + 19.9, text, "t-body", col) + art(ic) + if trail == "chev": + out += art("10-ic-chevron", top=y + 18.9) + elif trail == "toggle": + out += box(300.3, y + 12.0, 62.4, 27.7, "border-radius:var(--x-r-pill);background:var(--x-toggle-off)") \ + + box(302.0, y + 14.3, 37.1, 23.6, "border-radius:var(--x-r-pill);background:var(--x-card)") + elif trail: + out += tx(200.0, y + 19.9, trail, "t-body", "var(--x-sec-ink)", w=138.9, extra=";text-align:right") \ + + art("10-ic-chevron", top=y + 18.9) + return out + + +def settings(title, inner, hdr, after=""): + """after: what sits over the header crop, a label it patched out.""" + return screen(title, + box(0, 58.7, 393, 852 - 58.7, "border-radius:var(--x-r-modal) var(--x-r-modal) 0 0;background:var(--x-sheet)") + + inner + art(hdr) + txc(91.5, "Settings", "t-h") + after, + bg="var(--x-dim)") + + +def s10(): + sec = "var(--x-sec-ink)" + return settings("Settings", + box(16.1, 164.3, 361.3, 92.3, "border-radius:var(--x-r-group);background:var(--x-card)") + + circle(32.1, 180.2, 60.0, "background:var(--x-avatar)") + art("10-ic-person") + + tx(104.5, 183.0, "Alex Smith", "t-h") + + tx(104.5, 204.8, "alexsmith.mobbin+1@gmail.-", "t-mail", sec) + + tx(104.5, 226.2, "com", "t-mail", sec) + + art("10-ic-chevron", top=203.3) + + group(323.1, [("Appearance", "10-ic-appearance", "chev", None), + ("Customize Grok", "10-ic-customize", "chev", None), + ("Haptics", "10-ic-haptics", "chev", None), + ("Widget", "10-ic-widget", "chev", None), + ("App Language", "10-ic-language", "English", None)], "General") + + group(618.0, [("Kids Mode", "10-ic-kids", "chev", None), + ("NSFW Preferences", "10-ic-nsfw", "chev", None)]) + + group(777.7, [("Companions", "10-ic-companions", "chev", None), + ("Dictation", "10-ic-dictation", "chev", None)], "Voice"), + "10-hdr") + + +def s11(): + return settings("Settings, Voice", + group(167.0, [("Companions", "11-ic-companions", "chev", None), + ("Dictation", "11-ic-dictation", "chev", None), + ("Open App in Voice Mode", "11-ic-voicemode", "toggle", None)]) + + group(378.4, [("Shared Conversations", "11-ic-shared", "chev", None), + ("Data Controls", "11-ic-data", "chev", None), + ("Recently Deleted", "11-ic-deleted", "chev", None)], "Data & Information") + + group(569.3, [("Terms of Use", "11-ic-terms", "chev", None), + ("Privacy Policy", "11-ic-privacy", "chev", None)]) + + group(708.1, [("Report a Problem", "11-ic-report", "chev", None)]) + + group(816.0, [("SuperGrok", "11-ic-supergrok", "chev", None)], "Subscription"), + "11-hdr", tx(32.5, 142.4, "Voice", "t-section", "var(--x-section-ink)")) + + +def s12(): + return settings("Settings, bottom", + group(107.8, [(None, None, None, None), + ("Data Controls", "12-ic-data", "chev", None), + ("Recently Deleted", "12-ic-deleted", "chev", None)]) + + group(299.0, [("Terms of Use", "12-ic-terms", "chev", None), + ("Privacy Policy", "12-ic-privacy", "chev", None)]) + + group(437.7, [("Report a Problem", "12-ic-report", "chev", None)]) + + group(545.7, [("SuperGrok", "12-ic-supergrok", "chev", None)], "Subscription") + + group(632.2, [("Sign Out", "12-ic-signout", None, "var(--x-danger)")]) + + art("12-xai") + + txc(772.5, "VERSION 1.3.42 (BUILD 2776)", "t-version", "var(--x-version-ink)"), + "12-hdr") + + +SCREENS = [ + ("01-widget", "Home Screen widget", s01), + ("02-widget-guide-add", "Widget guide, step 4", s02), + ("03-widget-guide-jiggle", "Widget guide, step 1", s03), + ("04-voice-settings", "Voice settings", s04), + ("05-supergrok", "SuperGrok paywall", s05), + ("06-terms-update", "Terms update", s06), + ("13-terms-loading", "Terms update, signing out", s13), + ("14-grok-bot-sheet", "Introducing Grok Bot", s14), + ("15-app-store", "App Store, Grok Bot", s15), + ("07-home", "SuperGrok home", s07), + ("08-voice-select-ara", "Voice selection, Ara", s08), + ("09-voice-select-eve", "Voice selection, Eve", s09), + ("10-settings", "Settings", s10), + ("11-settings-voice", "Settings, scrolled to Voice", s11), + ("12-settings-bottom", "Settings, bottom", s12), +] + + +# ------------------------------------------------------ tokens + evidence ---- +SHEET = """body{padding:0;background:#FFF;color:var(--x-ink)} +.sheet{width:478px;height:980px;padding:14px 20px 8px;overflow:hidden} +h1{font:600 17px/22px var(--x-font);margin-bottom:2px} +header p{font:400 10.5px/13.5px var(--x-font);color:var(--x-foot);margin-bottom:4px} +h2{font:600 9px/12px var(--x-font);letter-spacing:.8px;text-transform:uppercase; + color:var(--x-foot);margin:5px 0 3px} +.grid{column-count:2;column-gap:12px} +.sw{display:flex;align-items:center;gap:5px;height:10.2px;break-inside:avoid;white-space:nowrap} +.sw .chip{width:16px;height:9px;flex:none;border-radius:3px;border:1px solid var(--x-well);background-color:#888} +.sw b{font:600 7.5px/10.5px ui-monospace,Menlo,monospace} +.sw i{font:400 7.5px/10.5px ui-monospace,Menlo,monospace;color:var(--x-foot);font-style:normal} +.foot{display:flex;gap:28px;align-items:flex-start;margin-top:4px} +.foot h2{margin-top:0} +.rad{display:flex;gap:6px;flex-wrap:wrap;width:250px} +.rb{width:36px;height:22px;background:var(--x-sheet);border:1px solid var(--x-well)} +.rad em{display:block;margin-top:2px;font:400 8.5px/11px var(--x-font); + color:var(--x-foot);font-style:normal;text-align:center} +.ty{column-count:3;column-gap:12px} +.tr{break-inside:avoid;border-bottom:1px solid var(--x-well)} +.tr span{display:block;white-space:nowrap;overflow:hidden;line-height:1} +.tr em{display:block;font:400 7px/9px ui-monospace,Menlo,monospace; + color:var(--x-foot);font-style:normal;white-space:nowrap} +.met{font:400 8px/9.5px ui-monospace,Menlo,monospace;color:var(--x-ink);white-space:nowrap} +table.ev{width:100%;border-collapse:collapse} +table.ev td{vertical-align:top;padding:2.5px 6px 2.5px 0; + border-bottom:1px solid var(--x-well);font:400 8.5px/11px var(--x-font)} +td.t,td.v{font-family:ui-monospace,Menlo,monospace;white-space:nowrap} +td.t{color:#0A60FF} +td.v{color:var(--x-ink);max-width:150px;overflow:hidden;text-overflow:ellipsis} +td.e{color:var(--x-foot)}""" + + +def _of(group): + return [x for x in TOKENS if x[0] == group] + + +def token_board(): + swatches = "".join( + '
' + '--x-%s%s
' % (n, n, v) + for g in ("Surface", "Line", "Ink") for _, n, v, _ in _of(g)) + radii = "".join( + '
%s
' % (v, v) + for _, n, v, _ in _of("Radius") if n != "r-phone") + met = "
".join("--x-%s: %s" % (n, v) for _, n, v, _ in _of("Metrics")) + return page(NAME + " - Design Tokens", + '

%s

' + '

Ten Mobbin captures at 2.2417 px per pt, five native 1206 × ' + '2622 captures at 3 px per pt. One face (SF Pro), one type ladder, ' + 'surfaces from white and light grey to black and a blurred photograph. ' + 'Translucent surfaces are materials, not fills: the ground under them ' + 'is not flat.

' + '
' + '

Colour

%s
' + '

Radius

' + '
%s
' + '

Metrics

%s
' + % (NAME, swatches, radii, met), SHEET) + + +def type_board(): + # the type ladder outgrew the token board at 46 rows, so it has its own + rows = "".join( + '
Grok' + '--x-%s · %s
' % (n, n, v.split(" var")[0]) + for _, n, v, _ in _of("Type")) + return page(NAME + " - Type Tokens", + '

%s type

' + '

Every size is fitted to a measured width on the board, so several ' + 'are off the iOS ladder. The evidence rows carry the widths.

' + '
%s
' % (NAME, rows), SHEET) + + +EV_LINES = 56 # a page of 60 estimated lines fits the board, 62 does not + + +def evidence_boards(): + # a row wraps its evidence at about 62 characters, so a page breaks by + # lines rather than by rows: 22 rows ran from 52 lines to 73 + pages, page_, lines = [], [], 0 + for row in TOKENS: + n = -(-len(row[3]) // 62) + if page_ and lines + n > EV_LINES: + pages.append(page_) + page_, lines = [], 0 + page_.append(row) + lines += n + pages.append(page_) + for i, chunk in enumerate(pages): + rows = "".join( + '--x-%s%s%s' + % (n, v, e) for _, n, v, e in chunk) + of = " %d/%d" % (i + 1, len(pages)) if len(pages) > 1 else "" + yield ("00%s-evidence" % "bcdefghijk"[i], + page(NAME + " - Evidence" + of, + '

Evidence%s

' + '

One row per token. A token with no evidence is a guess.

' + '
%s
' % (of, rows), SHEET)) + + +# ----------------------------------------------------------- references ---- +REF_CSS = """body{padding:24px} +.phone img{position:absolute;left:0;top:0;width:100%;height:100%;display:block}""" + + +def ref_boards(): + for stem, label, _ in SCREENS: + ref = "cp%d" % int(stem[:2]) # the capture of this board, not of its place in the row + f = REFS_DIR / (ref + ".png") + if not f.exists(): + continue + uri = "data:image/png;base64," + base64.b64encode(f.read_bytes()).decode() + big = ' style="width:var(--x-w-pro);height:var(--x-h-pro)"' if ref in BIG else "" + yield ("ref-" + stem, + page(NAME + " - reference: " + label, + '
%s
' % (big, uri, label), + REF_CSS)) + + +# ----------------------------------------------------------------- main ---- +def layout(names): + rows = [{"title": "Foundations", + "files": [{"file": "00-design-tokens", "label": "Design tokens"}, + {"file": "00a-type-tokens", "label": "Type tokens"}] + + [{"file": n, "label": "Evidence"} + for n, _ in evidence_boards()]}, + {"title": "Screens", "numbered": True, + "files": [{"file": s, "label": l} for s, l, _ in SCREENS]}] + refs = [{"file": "ref-" + s, "label": l} + for s, l, _ in SCREENS if "ref-" + s in names] + if refs: + rows.append({"title": "Source of truth: the captures", + "numbered": True, "files": refs}) + return {"name": PAGE_NAME, "cover": "05-supergrok", "rows": rows} + + +def main(): + cut() + files = dict([("00-design-tokens", token_board()), ("00a-type-tokens", type_board())] + + list(evidence_boards()) + + [(s, fn()) for s, _, fn in SCREENS] + + list(ref_boards())) + for name in sorted(files): + write(name, files[name]) + (OUT / "layout.json").write_text(json.dumps(layout(files), indent=2) + "\n") + print("%-24s %6d rows" % ("layout.json", len(layout(files)["rows"]))) + + +if __name__ == "__main__": + main() diff --git a/mockups/canvases/grok-ios/icon.png b/mockups/canvases/grok-ios/icon.png new file mode 100644 index 00000000..9d3556a4 Binary files /dev/null and b/mockups/canvases/grok-ios/icon.png differ diff --git a/mockups/canvases/grok-ios/layout.json b/mockups/canvases/grok-ios/layout.json new file mode 100644 index 00000000..fffadf47 --- /dev/null +++ b/mockups/canvases/grok-ios/layout.json @@ -0,0 +1,187 @@ +{ + "name": "(example) Grok iOS", + "cover": "05-supergrok", + "rows": [ + { + "title": "Foundations", + "files": [ + { + "file": "00-design-tokens", + "label": "Design tokens" + }, + { + "file": "00a-type-tokens", + "label": "Type tokens" + }, + { + "file": "00b-evidence", + "label": "Evidence" + }, + { + "file": "00c-evidence", + "label": "Evidence" + }, + { + "file": "00d-evidence", + "label": "Evidence" + }, + { + "file": "00e-evidence", + "label": "Evidence" + }, + { + "file": "00f-evidence", + "label": "Evidence" + }, + { + "file": "00g-evidence", + "label": "Evidence" + }, + { + "file": "00h-evidence", + "label": "Evidence" + }, + { + "file": "00i-evidence", + "label": "Evidence" + }, + { + "file": "00j-evidence", + "label": "Evidence" + } + ] + }, + { + "title": "Screens", + "numbered": true, + "files": [ + { + "file": "01-widget", + "label": "Home Screen widget" + }, + { + "file": "02-widget-guide-add", + "label": "Widget guide, step 4" + }, + { + "file": "03-widget-guide-jiggle", + "label": "Widget guide, step 1" + }, + { + "file": "04-voice-settings", + "label": "Voice settings" + }, + { + "file": "05-supergrok", + "label": "SuperGrok paywall" + }, + { + "file": "06-terms-update", + "label": "Terms update" + }, + { + "file": "13-terms-loading", + "label": "Terms update, signing out" + }, + { + "file": "14-grok-bot-sheet", + "label": "Introducing Grok Bot" + }, + { + "file": "15-app-store", + "label": "App Store, Grok Bot" + }, + { + "file": "07-home", + "label": "SuperGrok home" + }, + { + "file": "08-voice-select-ara", + "label": "Voice selection, Ara" + }, + { + "file": "09-voice-select-eve", + "label": "Voice selection, Eve" + }, + { + "file": "10-settings", + "label": "Settings" + }, + { + "file": "11-settings-voice", + "label": "Settings, scrolled to Voice" + }, + { + "file": "12-settings-bottom", + "label": "Settings, bottom" + } + ] + }, + { + "title": "Source of truth: the captures", + "numbered": true, + "files": [ + { + "file": "ref-01-widget", + "label": "Home Screen widget" + }, + { + "file": "ref-02-widget-guide-add", + "label": "Widget guide, step 4" + }, + { + "file": "ref-03-widget-guide-jiggle", + "label": "Widget guide, step 1" + }, + { + "file": "ref-04-voice-settings", + "label": "Voice settings" + }, + { + "file": "ref-05-supergrok", + "label": "SuperGrok paywall" + }, + { + "file": "ref-06-terms-update", + "label": "Terms update" + }, + { + "file": "ref-13-terms-loading", + "label": "Terms update, signing out" + }, + { + "file": "ref-14-grok-bot-sheet", + "label": "Introducing Grok Bot" + }, + { + "file": "ref-15-app-store", + "label": "App Store, Grok Bot" + }, + { + "file": "ref-07-home", + "label": "SuperGrok home" + }, + { + "file": "ref-08-voice-select-ara", + "label": "Voice selection, Ara" + }, + { + "file": "ref-09-voice-select-eve", + "label": "Voice selection, Eve" + }, + { + "file": "ref-10-settings", + "label": "Settings" + }, + { + "file": "ref-11-settings-voice", + "label": "Settings, scrolled to Voice" + }, + { + "file": "ref-12-settings-bottom", + "label": "Settings, bottom" + } + ] + } + ] +} diff --git a/mockups/canvases/grok-ios/probes.json b/mockups/canvases/grok-ios/probes.json new file mode 100644 index 00000000..a0807c96 --- /dev/null +++ b/mockups/canvases/grok-ios/probes.json @@ -0,0 +1,1966 @@ +[ + { + "id": "ground", + "img": "assets/refs/cp1.png", + "cmd": "sample", + "box": [ + 0, + 100, + 20, + 240 + ], + "only": "flat", + "mine": "01-widget.png", + "_": "01 left of the widget (x 0-20, y 100-240): page ground, nothing else; the widget starts at 24.8", + "_head": "Phase 1's measurements, replayable. Boxes are design pt at capture scale 2.2417 (881x1910 for 393x852); run with --pt 2.2417. --against wants a directory of renders resized to 881x1910 with the masked corners composited onto the capture, which is what scratch/run.sh writes to scratch/cap/; every probe names its own file there. 'bright' on a sample means the ink is lighter than its ground; on a bbox it is the luminance above which a pixel is ink. 06, 07 and 13-15 are native captures at 3 px/pt (1206x2622 for 402x874); their probes carry \"pt\": 3, which overrides the command line, and scratch/run13.sh writes their composites to the same scratch/cap/. The status bar on those five is the template's, not the capture's, so no probe sits above y 59. 08-12 are 2.2417 again (881x1910 after the Mobbin footer is dropped); cp8, cp9 and cp12 are read after the per-channel cast correction the README describes, which is what assets/refs holds." + }, + { + "id": "card", + "img": "assets/refs/cp2.png", + "cmd": "sample", + "box": [ + 60, + 295, + 340, + 305 + ], + "only": "flat", + "mine": "02-widget-guide-add.png", + "_": "02 illustration card interior, row band y 295-305 x 60-340: white between the fake home screen's rows, no icon ink" + }, + { + "id": "well", + "img": "assets/refs/cp1.png", + "cmd": "sample", + "box": [ + 45, + 122, + 165, + 128 + ], + "only": "flat", + "mine": "01-widget.png", + "_": "01 the widget's pill (61.6 tall, y 96-158): the band x 45-165 y 122-128 is its upper blank, above the compose and wave glyphs which sit at y 183-209" + }, + { + "id": "dim", + "img": "assets/refs/cp2.png", + "cmd": "sample", + "box": [ + 30, + 5, + 110, + 50 + ], + "only": "flat", + "mine": "02-widget-guide-add.png", + "_": "02 the dimmed parent above the sheet, y 5-50 x 30-110: left of the island (134-259) and below nothing" + }, + { + "id": "sheet", + "img": "assets/refs/cp2.png", + "cmd": "sample", + "box": [ + 60, + 700, + 340, + 720 + ], + "only": "flat", + "mine": "02-widget-guide-add.png", + "_": "02 sheet ground below the card (card ends 515) and above the body ink (548): y 700-720 x 60-340 is under the dots too, blank" + }, + { + "id": "night", + "img": "assets/refs/cp5.png", + "cmd": "sample", + "box": [ + 20, + 822, + 372, + 838 + ], + "only": "flat", + "mine": "05-supergrok.png", + "_": "05 below the footer (ends 817) and above the diff window's floor (838), x 20-372: the flat page ground. The band between the feature card and the plan group is smoke tail, not ground" + }, + { + "id": "skip", + "img": "assets/refs/cp5.png", + "cmd": "sample", + "box": [ + 320, + 72, + 368, + 94 + ], + "only": "flat", + "mine": "05-supergrok.png", + "_": "05 Skip pill 315.6-372.3 x 67.6-99: the band x 320-368 y 72-94 holds the label ink too, so only the flats count" + }, + { + "id": "material", + "img": "assets/refs/cp5.png", + "cmd": "sample", + "box": [ + 200, + 384, + 330, + 396 + ], + "only": "flat", + "mine": "05-supergrok.png", + "_": "05 feature card blank x 200-330 y 384-396, between row 3's second line (ends 380.5) and row 4's title (405): the material over black" + }, + { + "id": "price", + "img": "assets/refs/cp5.png", + "cmd": "sample", + "box": [ + 30, + 695, + 190, + 715 + ], + "only": "flat", + "mine": "05-supergrok.png", + "_": "05 Monthly side of the plan group, x 30-190 y 695-715: below '$30 /month' (ends 688.3), above the group's edge (714.7)" + }, + { + "id": "plan-lo", + "img": "assets/refs/cp5.png", + "cmd": "sample", + "box": [ + 212, + 700, + 228, + 712 + ], + "only": "flat", + "mine": "05-supergrok.png", + "_": "05 Yearly card bottom-left x 212-228 y 700-712: below '$25 /month' (ends 697.2), inside the card's 15pt corner" + }, + { + "id": "plan-hi", + "img": "assets/refs/cp5.png", + "cmd": "sample", + "box": [ + 340, + 626, + 358, + 636 + ], + "only": "flat", + "mine": "05-supergrok.png", + "_": "05 Yearly card top-right x 340-358 y 626-636: right of 'Yearly' (ends 258.3), the light end of the ramp" + }, + { + "id": "free-bg", + "img": "assets/refs/cp5.png", + "cmd": "sample", + "box": [ + 134, + 643, + 140, + 648 + ], + "only": "flat", + "mine": "05-supergrok.png", + "_": "05 FREE badge 129.8-185.1 x 640.1-667.8, the blank x 134-140 y 643-648 left of the F (starts 141)" + }, + { + "id": "rec", + "img": "assets/refs/cp4.png", + "cmd": "sample", + "box": [ + 215, + 26.8, + 220.8, + 32.6 + ], + "only": "all", + "mine": "04-voice-settings.png", + "_": "04 the orange recording dot inside the island, x 215-220.8 y 26.8-32.6: a 6pt disc, so the mode of all pixels" + }, + { + "id": "ink", + "img": "assets/refs/cp2.png", + "cmd": "sample", + "box": [ + 16, + 545, + 377, + 567 + ], + "only": "ink", + "ink": "8", + "mine": "02-widget-guide-add.png", + "_": "02 body line 1 x 16-377 y 545-567: 'Find Grok in the list, choose a widget size,' on sheet ground; darkest 8%" + }, + { + "id": "ink-inv", + "img": "assets/refs/cp5.png", + "cmd": "sample", + "box": [ + 99, + 107, + 294, + 144 + ], + "only": "ink", + "ink": "8", + "bright": true, + "mine": "05-supergrok.png", + "_": "05 'SuperGrok' x 99-294 y 107-144: the largest white ink on the set; brightest 8%" + }, + { + "id": "mute", + "img": "assets/refs/cp5.png", + "cmd": "sample", + "box": [ + 95, + 244, + 312, + 258 + ], + "only": "ink", + "ink": "8", + "bright": true, + "mine": "05-supergrok.png", + "_": "05 row 1 subtitle 'With Grok 4.1 - Fast & Expert mode' x 95-312 y 244-258; brightest 8% is the grey" + }, + { + "id": "skip-ink", + "img": "assets/refs/cp5.png", + "cmd": "sample", + "box": [ + 325, + 76, + 362, + 92 + ], + "only": "ink", + "ink": "8", + "bright": true, + "mine": "05-supergrok.png", + "_": "05 'Skip' x 325-362 y 76-92 inside its pill; brightest 8%" + }, + { + "id": "foot", + "img": "assets/refs/cp5.png", + "cmd": "sample", + "box": [ + 35, + 805, + 358, + 817 + ], + "only": "ink", + "ink": "8", + "bright": true, + "mine": "05-supergrok.png", + "_": "05 footer x 35-358 y 805-817, one 13px line on night ground; brightest 8%" + }, + { + "id": "free-ink", + "img": "assets/refs/cp5.png", + "cmd": "sample", + "box": [ + 141, + 645, + 176, + 662 + ], + "only": "ink", + "ink": "8", + "bright": true, + "mine": "05-supergrok.png", + "_": "05 'FREE' x 141-176 y 645-662 inside the badge; brightest 8% is the orange" + }, + { + "id": "h1-05", + "img": "assets/refs/cp5.png", + "cmd": "bbox", + "box": [ + 80, + 90, + 315, + 150 + ], + "bright": 128, + "mine": "05-supergrok.png", + "_": "05 'SuperGrok' alone: x 80-315 y 90-150. The Skip pill starts at x 315.6 and its label at 326, so the window's right edge keeps both out; the subtitle starts at y 156" + }, + { + "id": "h-02", + "img": "assets/refs/cp2.png", + "cmd": "bbox", + "box": [ + 140, + 85, + 255, + 112 + ], + "mine": "02-widget-guide-add.png", + "_": "02 nav title 'Widget' x 140-255 y 85-112: centred at 196.5, the back disc ends at 62, nothing else on the row" + }, + { + "id": "body-02", + "img": "assets/refs/cp2.png", + "cmd": "bbox", + "box": [ + 16, + 545, + 377, + 567 + ], + "mine": "02-widget-guide-add.png", + "_": "02 body line 1 only, y 545-567; line 2 starts at 570" + }, + { + "id": "widget-01", + "img": "assets/refs/cp1.png", + "cmd": "bbox", + "box": [ + 97, + 115, + 145, + 140 + ], + "mine": "01-widget.png", + "_": "01 'Grok' in the widget header, x 96-145 y 115-140; the mark ends at 96" + }, + { + "id": "sheet-04", + "img": "assets/refs/cp4.png", + "cmd": "bbox", + "box": [ + 130, + 428, + 265, + 455 + ], + "bright": 128, + "mine": "04-voice-settings.png", + "_": "04 'Voice Settings' x 130-265 y 428-455, centred; the close disc starts at 338" + }, + { + "id": "row-04", + "img": "assets/refs/cp4.png", + "cmd": "bbox", + "box": [ + 30, + 500, + 200, + 525 + ], + "bright": 128, + "mine": "04-voice-settings.png", + "_": "04 'Select Audio Device' x 30-200 y 500-525; the airplay glyph starts at 334" + }, + { + "id": "feat-05", + "img": "assets/refs/cp5.png", + "cmd": "bbox", + "box": [ + 90, + 218, + 340, + 240 + ], + "bright": 128, + "mine": "05-supergrok.png", + "_": "05 row 1 title 'Longer conversations in Chat' x 90-340 y 218-240; the subtitle starts at 244.9" + }, + { + "id": "price-05", + "img": "assets/refs/cp5.png", + "cmd": "bbox", + "box": [ + 210, + 656, + 312, + 680 + ], + "bright": 128, + "mine": "05-supergrok.png", + "_": "05 '$300 /year' x 210-312 y 656-680; 'Yearly' ends 651.7, '$25 /month' starts 684.7" + }, + { + "id": "cta-05", + "img": "assets/refs/cp5.png", + "cmd": "bbox", + "box": [ + 100, + 745, + 300, + 770 + ], + "mine": "05-supergrok.png", + "_": "05 'Upgrade to SuperGrok' on the white CTA, x 100-300 y 745-770: dark ink on white" + }, + { + "id": "sheet-edge", + "img": "assets/refs/cp2.png", + "cmd": "scan", + "axis": "col", + "at": 100, + "range": [ + 40, + 80 + ], + "mine": "02-widget-guide-add.png", + "_": "02 down x 100 from the dimmed parent into the sheet: the edge is the token's y" + }, + { + "id": "card-edge-05", + "img": "assets/refs/cp5.png", + "cmd": "scan", + "axis": "col", + "at": 200, + "range": [ + 190, + 210 + ], + "mine": "05-supergrok.png", + "_": "05 down x 200 across the feature card's top edge (199): smoke, the .16 line, then the material" + }, + { + "id": "plan-edge", + "img": "assets/refs/cp5.png", + "cmd": "scan", + "axis": "col", + "at": 100, + "range": [ + 610, + 625 + ], + "mine": "05-supergrok.png", + "_": "05 down x 100 across the plan group's top edge (618.4): night, the 1pt #252525 line, the price fill" + }, + { + "id": "sheet-v-edge", + "img": "assets/refs/cp4.png", + "cmd": "scan", + "axis": "col", + "at": 100, + "range": [ + 395, + 415 + ], + "mine": "04-voice-settings.png", + "_": "04 down x 100 across the voice sheet's top edge (403.6), left of the grabber (176.7-217): the scene, then the blurred sheet" + }, + { + "id": "voice-pill", + "img": "assets/refs/cp4.png", + "cmd": "sample", + "box": [ + 300, + 772, + 370, + 797 + ], + "only": "flat", + "mine": "04-voice-settings.png", + "_": "04 the voice pill under the sheet, its core only (x 300-370 y 772-797 inside the blurred 288.5-379.6 x 767.4-801.3): #474747 through the tint; the render's #767676 pill under the .40 tint should read the same" + }, + { + "id": "sheet-v-blur", + "img": "assets/refs/cp4.png", + "cmd": "scan", + "axis": "row", + "at": 784, + "range": [ + 270, + 300 + ], + "mine": "04-voice-settings.png", + "_": "04 across the voice pill's left edge at y 784, ground (x 270) to pill core (x 300): the ramp's width is the sheet's blur, 10pt for 10-90%" + }, + { + "id": "row-line", + "img": "assets/refs/cp4.png", + "cmd": "scan", + "axis": "col", + "at": 265, + "range": [ + 483, + 491 + ], + "mine": "04-voice-settings.png", + "_": "04 down x 265 across the first row card's top edge (486.8), between the label and the airplay glyph: the 1pt line is the single lighter run, no fill on either side" + }, + { + "id": "sheet-v", + "img": "assets/refs/cp4.png", + "cmd": "sample", + "box": [ + 120, + 495, + 160, + 505 + ], + "only": "flat", + "mine": "04-voice-settings.png", + "_": "04 the hoodie through the sheet (x 120-160 y 495-505, between the row labels): #682525 in the capture; the render's is the generated hoodie under the same tint, so this probe scores the scene and the tint together" + }, + { + "id": "home-04", + "img": "assets/refs/cp4.png", + "cmd": "scan", + "axis": "col", + "at": 196, + "range": [ + 836, + 848 + ], + "mine": "04-voice-settings.png", + "_": "04 down x 196 where a home indicator would be (y 838-843): grass all the way in the capture, so the render draws none" + }, + { + "id": "illo-scrim-02", + "img": "assets/refs/cp2.png", + "cmd": "sample", + "box": [ + 58, + 220, + 71, + 276 + ], + "only": "flat", + "mine": "02-widget-guide-add.png", + "_": "02 the drawn phone's screen between the frame's inner edge (55.9) and the first tile (73.1), y 220-276: the dimmed screen only, above the sheet's halo" + }, + { + "id": "illo-sheet-02", + "img": "assets/refs/cp2.png", + "cmd": "sample", + "box": [ + 221, + 339, + 311, + 352 + ], + "only": "flat", + "mine": "02-widget-guide-add.png", + "_": "02 the drawn sheet between the header row (ends y 336) and the title (starts 361): white ground only" + }, + { + "id": "illo-grabber-02", + "img": "assets/refs/cp2.png", + "cmd": "sample", + "box": [ + 186, + 303, + 207, + 305 + ], + "only": "all", + "mine": "02-widget-guide-add.png", + "_": "02 the sheet grabber's core, inside its 183.8-209.2 x 302.4-306.0 box" + }, + { + "id": "illo-pill-02", + "img": "assets/refs/cp2.png", + "cmd": "sample", + "box": [ + 150, + 437, + 163, + 472 + ], + "only": "flat", + "mine": "02-widget-guide-add.png", + "_": "02 the widget pill's left end, x 150-163 y 437-472: pill fill, left of the mark (starts 166.8) and inside the cap" + }, + { + "id": "illo-label-02", + "img": "assets/refs/cp2.png", + "cmd": "sample", + "box": [ + 95, + 316, + 128, + 335 + ], + "only": "ink", + "mine": "02-widget-guide-add.png", + "_": "02 'Grok' beside the app icon, x 98-124 y 321-330, with 3pt of sheet around it: the label's ink only" + }, + { + "id": "illo-sub-02", + "img": "assets/refs/cp2.png", + "cmd": "sample", + "box": [ + 101, + 383, + 293, + 402 + ], + "only": "ink", + "mine": "02-widget-guide-add.png", + "_": "02 the subtitle line x 104-289 y 388-398 with 3pt around it: its ink only" + }, + { + "id": "illo-title-02", + "img": "assets/refs/cp2.png", + "cmd": "sample", + "box": [ + 167, + 356, + 226, + 382 + ], + "only": "ink", + "mine": "02-widget-guide-add.png", + "_": "02 the sheet title 'Grok' x 174-219 y 361-377 with sheet around it: the black ink" + }, + { + "id": "illo-pill-ink-02", + "img": "assets/refs/cp2.png", + "cmd": "sample", + "box": [ + 190, + 445, + 231, + 469 + ], + "only": "ink", + "mine": "02-widget-guide-add.png", + "_": "02 'Grok' in the widget pill x 192-227 y 450-465, right of the mark (ends 187.4): its ink only" + }, + { + "id": "illo-sheet-shadow-02", + "img": "assets/refs/cp2.png", + "cmd": "scan", + "box": null, + "axis": "col", + "at": 200, + "range": [ + 254, + 298 + ], + "mine": "02-widget-guide-add.png", + "_": "02 down x 200 between the island's foot (251.4) and the sheet's top edge (299.1), both excluded: the scrim, then the sheet's halo darkening into the edge; the largest step is the halo's last run" + }, + { + "id": "illo-card-halo-02", + "img": "assets/refs/cp2.png", + "cmd": "scan", + "box": null, + "axis": "col", + "at": 176.8, + "range": [ + 400, + 416 + ], + "mine": "02-widget-guide-add.png", + "_": "02 down x 176.8 from the subtitle's foot (398.4) to the widget card's top edge (417 at that column): the card's halo only" + }, + { + "id": "t-illo-label-02", + "img": "assets/refs/cp2.png", + "cmd": "bbox", + "box": [ + 95, + 316, + 128, + 335 + ], + "dark": 128, + "mine": "02-widget-guide-add.png", + "_": "02 'Grok' beside the app icon: the window holds the word and 3pt of sheet, the icon ends at 92.3" + }, + { + "id": "t-illo-title-02", + "img": "assets/refs/cp2.png", + "cmd": "bbox", + "box": [ + 167, + 356, + 226, + 382 + ], + "dark": 128, + "mine": "02-widget-guide-add.png", + "_": "02 the sheet title: the word and sheet around it, the subtitle starts at 387.7" + }, + { + "id": "t-illo-sub-02", + "img": "assets/refs/cp2.png", + "cmd": "bbox", + "box": [ + 101, + 383, + 293, + 402 + ], + "dark": 160, + "mine": "02-widget-guide-add.png", + "_": "02 the subtitle line: the whole line and sheet around it, the title ends at 376.9 and the card's halo starts below 405" + }, + { + "id": "t-illo-pill-02", + "img": "assets/refs/cp2.png", + "cmd": "bbox", + "box": [ + 190, + 445, + 231, + 469 + ], + "dark": 128, + "mine": "02-widget-guide-add.png", + "_": "02 'Grok' in the pill, right of the mark (ends 187.4) and inside the pill (right cap starts about 240)" + }, + { + "id": "illo-grabber-box-02", + "img": "assets/refs/cp2.png", + "cmd": "bbox", + "box": [ + 178, + 300, + 215, + 309 + ], + "dark": 235, + "mine": "02-widget-guide-add.png", + "_": "02 the grabber: window inside the sheet (top 299.1), clear of the app icon (starts 315.8)" + }, + { + "id": "illo-app-02", + "img": "assets/refs/cp2.png", + "cmd": "bbox", + "box": [ + 70, + 313, + 95, + 338 + ], + "dark": 128, + "mine": "02-widget-guide-add.png", + "_": "02 the app icon crop: the black rounded square and 2pt of sheet, the label starts at 98.1" + }, + { + "id": "illo-close-02", + "img": "assets/refs/cp2.png", + "cmd": "bbox", + "box": [ + 302, + 317, + 320, + 334 + ], + "dark": 128, + "mine": "02-widget-guide-add.png", + "_": "02 the close X crop: the glyph and 2pt of sheet, the sheet's right edge is 294.4+43" + }, + { + "id": "illo-mark-02", + "img": "assets/refs/cp2.png", + "cmd": "bbox", + "box": [ + 163, + 441, + 191, + 466 + ], + "dark": 128, + "mine": "02-widget-guide-add.png", + "_": "02 the mark crop inside the pill: the glyph and pill fill, the pill's 'Grok' starts at 192.3" + }, + { + "id": "illo-card-02", + "img": "assets/refs/cp2.png", + "cmd": "scan", + "box": null, + "axis": "row", + "at": 460, + "range": [ + 100, + 136 + ], + "mine": "02-widget-guide-add.png", + "_": "02 across y 460 from the sheet's left edge to short of the pill (its cap starts 140.3 at this row): the card's halo and the card's left edge at 127.6, nothing else" + }, + { + "id": "illo-pill-cap-02", + "img": "assets/refs/cp2.png", + "cmd": "scan", + "box": null, + "axis": "row", + "at": 460, + "range": [ + 132, + 150 + ], + "mine": "02-widget-guide-add.png", + "_": "02 across y 460 from inside the card (its left edge is 127.6) into the pill: the pill's left cap at 140.3 is the only edge" + }, + { + "id": "page-06", + "img": "assets/refs/cp6.png", + "cmd": "sample", + "box": [ + 20, + 520, + 380, + 700 + ], + "only": "flat", + "pt": 3, + "mine": "06-terms-update.png", + "_": "06 the empty band between the body copy (ends y 496) and the Got it pill (starts 730.7): page ground, nothing else" + }, + { + "id": "chip-07", + "img": "assets/refs/cp7.png", + "cmd": "sample", + "box": [ + 15, + 678, + 55, + 688 + ], + "only": "flat", + "pt": 3, + "mine": "07-home.png", + "_": "07 top of the first suggestion chip (y 675-727, x 11-143.7), above the bot glyph which starts at y 691.7: chip fill only" + }, + { + "id": "composer-07", + "img": "assets/refs/cp7.png", + "cmd": "sample", + "box": [ + 140, + 765, + 300, + 785 + ], + "only": "flat", + "pt": 3, + "mine": "07-home.png", + "_": "07 composer interior right of 'Ask Anything' (ends x 120.3) and above the control row (starts 789.3): the card fill" + }, + { + "id": "ctl-07", + "img": "assets/refs/cp7.png", + "cmd": "sample", + "box": [ + 90, + 792, + 132, + 797 + ], + "only": "flat", + "pt": 3, + "mine": "07-home.png", + "_": "07 the Auto pill (x 59.3-134, y 789.3-822) above its glyph (y 798.3-813.3) and label (ink top 800.7): pill fill" + }, + { + "id": "btn-06", + "img": "assets/refs/cp6.png", + "cmd": "sample", + "box": [ + 40, + 740, + 150, + 775 + ], + "only": "flat", + "pt": 3, + "mine": "06-terms-update.png", + "_": "06 the Got it pill (y 730.7-784.7) left of its label (x 181-221): black fill" + }, + { + "id": "composer-line-07", + "img": "assets/refs/cp7.png", + "cmd": "scan", + "box": null, + "axis": "col", + "at": 200, + "range": [ + 731, + 745 + ], + "pt": 3, + "mine": "07-home.png", + "_": "07 down x 200 across the composer's top edge: the halo, the line at 737.3-737.7, then the #FEFEFE interior; the largest step is the line" + }, + { + "id": "composer-shadow-07", + "img": "assets/refs/cp7.png", + "cmd": "sample", + "box": [ + 8, + 770, + 10, + 820 + ], + "only": "all", + "pt": 3, + "mine": "07-home.png", + "_": "07 a 2pt strip just outside the composer's left edge (x 10.3), mid-height: the halo at its darkest, nothing else" + }, + { + "id": "composer-below-07", + "img": "assets/refs/cp7.png", + "cmd": "sample", + "box": [ + 100, + 838, + 300, + 843 + ], + "only": "all", + "pt": 3, + "mine": "07-home.png", + "_": "07 5-10pt under the composer's bottom (832.7), above the home indicator's band: the halo's tail" + }, + { + "id": "copy-mute-06", + "img": "assets/refs/cp6.png", + "cmd": "sample", + "box": [ + 200, + 482, + 245, + 493 + ], + "only": "ink", + "pt": 3, + "mine": "06-terms-update.png", + "_": "06 'review them.' on body line 3, the only grey-only window: the copy ink, no black span" + }, + { + "id": "placeholder-07", + "img": "assets/refs/cp7.png", + "cmd": "sample", + "box": [ + 27, + 755, + 121, + 770 + ], + "only": "ink", + "pt": 3, + "mine": "07-home.png", + "_": "07 'Ask Anything' in the composer, x 27.3-120.3, above the control row: placeholder ink" + }, + { + "id": "title-06", + "img": "assets/refs/cp6.png", + "cmd": "bbox", + "box": [ + 15, + 374, + 390, + 401 + ], + "pt": 3, + "mine": "06-terms-update.png", + "_": "06 title line 1 'Updates to our Terms of Service' (ink 379.0-394.0 plus descenders); line 2 starts at 405.0" + }, + { + "id": "copy-06", + "img": "assets/refs/cp6.png", + "cmd": "bbox", + "box": [ + 15, + 441, + 390, + 461 + ], + "pt": 3, + "mine": "06-terms-update.png", + "_": "06 body line 1 (ink top 444.7, 10.0 cap); line 2 starts 463.7" + }, + { + "id": "link-06", + "img": "assets/refs/cp6.png", + "cmd": "bbox", + "box": [ + 150, + 798, + 250, + 822 + ], + "pt": 3, + "mine": "06-terms-update.png", + "_": "06 'Sign out' with its underline (ink 804.2-818.7), centred, nothing beside it" + }, + { + "id": "hdr-07", + "img": "assets/refs/cp7.png", + "cmd": "bbox", + "box": [ + 50, + 70, + 175, + 102 + ], + "pt": 3, + "mine": "07-home.png", + "_": "07 'SuperGrok' right of the mark (mark ends x 49), ink 78-98" + }, + { + "id": "chip-lbl-07", + "img": "assets/refs/cp7.png", + "cmd": "bbox", + "box": [ + 50, + 690, + 143, + 712 + ], + "pt": 3, + "mine": "07-home.png", + "_": "07 'Build a Bot' in the first chip, right of the bot glyph (ends x 45); the chip fill is above threshold" + }, + { + "id": "ctl-lbl-07", + "img": "assets/refs/cp7.png", + "cmd": "bbox", + "box": [ + 90, + 795, + 132, + 816 + ], + "pt": 3, + "mine": "07-home.png", + "_": "07 'Auto' in the model pill, right of its glyph (ends x 86)" + }, + { + "id": "speak-07", + "img": "assets/refs/cp7.png", + "cmd": "bbox", + "box": [ + 322, + 796, + 376, + 816 + ], + "bright": 160, + "pt": 3, + "mine": "07-home.png", + "_": "07 'Speak' on the black pill, right of the wave glyph (ends x 319) and short of the pill's rounded right end (x 378.3 at y 796)" + }, + { + "id": "page-13", + "img": "assets/refs/cp13.png", + "cmd": "sample", + "box": [ + 20, + 520, + 380, + 700 + ], + "only": "flat", + "pt": 3, + "mine": "13-terms-loading.png", + "_": "13 the same band as page-06 under the spinner pill: page ground, nothing else" + }, + { + "id": "title-13", + "img": "assets/refs/cp13.png", + "cmd": "bbox", + "box": [ + 15, + 374, + 390, + 401 + ], + "pt": 3, + "mine": "13-terms-loading.png", + "_": "13 title line 1, the same box as title-06; the spinner pill is 330pt below" + }, + { + "id": "link-13", + "img": "assets/refs/cp13.png", + "cmd": "bbox", + "box": [ + 150, + 798, + 250, + 822 + ], + "pt": 3, + "mine": "13-terms-loading.png", + "_": "13 'Sign out' with its underline, the same box as link-06" + }, + { + "id": "scrim-14", + "img": "assets/refs/cp14.png", + "cmd": "sample", + "box": [ + 20, + 150, + 380, + 250 + ], + "only": "flat", + "pt": 3, + "mine": "14-grok-bot-sheet.png", + "_": "14 the dimmed Terms page above the sheet (sheet top 442.5), between the status bar and the mark (starts 299.7): the scrim over white, nothing else" + }, + { + "id": "glass-14", + "img": "assets/refs/cp14.png", + "cmd": "sample", + "box": [ + 60, + 840, + 340, + 855 + ], + "only": "flat", + "pt": 3, + "mine": "14-grok-bot-sheet.png", + "_": "14 the sheet's flats under the CTA (ends 833.3) and above the home indicator: glass over the scrimmed page, no type" + }, + { + "id": "glass-pill-14", + "img": "assets/refs/cp14.png", + "cmd": "sample", + "box": [ + 60, + 764, + 340, + 784 + ], + "only": "all", + "pt": 3, + "mine": "14-grok-bot-sheet.png", + "_": "14 the band between sheet body line 3 (ink ends 762) and the CTA (starts 786), where the black Got it pill (730.7-784.7) shows through the glass" + }, + { + "id": "grabber-14", + "img": "assets/refs/cp14.png", + "cmd": "sample", + "box": [ + 175, + 452, + 227, + 454 + ], + "only": "all", + "pt": 3, + "mine": "14-grok-bot-sheet.png", + "_": "14 the grabber's core (172.3-229.7 x 451.3-455.0), inside its rounded ends" + }, + { + "id": "card-blue-14", + "img": "assets/refs/cp14.png", + "cmd": "sample", + "box": [ + 66, + 583, + 366, + 643 + ], + "only": "flat", + "pt": 3, + "mine": "14-grok-bot-sheet.png", + "_": "14 the card's lower two thirds right of the NEW badge (ends x 82.7 at y 631-652 - the window starts at 66 above it, y 583-631 clear) and under the title (ends 573.7): flat blue" + }, + { + "id": "card-pale-14", + "img": "assets/refs/cp14.png", + "cmd": "sample", + "box": [ + 46, + 463, + 106, + 513 + ], + "only": "flat", + "pt": 3, + "mine": "14-grok-bot-sheet.png", + "_": "14 the card's top-left corner inside the pale shape (its edge runs from (26,505) to (246,463)): the pale fill only" + }, + { + "id": "sheet-line-14", + "img": "assets/refs/cp14.png", + "cmd": "scan", + "box": null, + "axis": "row", + "at": 600, + "range": [ + 3, + 13 + ], + "pt": 3, + "mine": "14-grok-bot-sheet.png", + "_": "14 along row y 600 across the sheet's left edge (7.33-7.67): scrim, the two-px outline, then the glass" + }, + { + "id": "sheet-copy-ink-14", + "img": "assets/refs/cp14.png", + "cmd": "sample", + "box": [ + 40, + 708, + 360, + 721 + ], + "only": "ink", + "pt": 3, + "mine": "14-grok-bot-sheet.png", + "_": "14 sheet body line 1 'AI teammates you can give real work to. Bots can' (ink 708.3-722): the copy ink" + }, + { + "id": "sheet-h-14", + "img": "assets/refs/cp14.png", + "cmd": "bbox", + "box": [ + 20, + 676, + 220, + 699 + ], + "pt": 3, + "mine": "14-grok-bot-sheet.png", + "_": "14 'Introducing Grok Bot' (ink 679.7-697), above body line 1 (starts 708.3)" + }, + { + "id": "sheet-copy-14", + "img": "assets/refs/cp14.png", + "cmd": "bbox", + "box": [ + 20, + 705, + 380, + 724 + ], + "pt": 3, + "mine": "14-grok-bot-sheet.png", + "_": "14 sheet body line 1 (ink top 708.3); line 2 starts 728.3" + }, + { + "id": "card-title-14", + "img": "assets/refs/cp14.png", + "cmd": "bbox", + "box": [ + 150, + 543, + 300, + 578 + ], + "bright": 200, + "pt": 3, + "mine": "14-grok-bot-sheet.png", + "_": "14 'Grok Bot' on the card, white on #80BEFD (luminance 181), right of the bot glyph (ends 144.3) and clear of the pale shape" + }, + { + "id": "store-dim-15", + "img": "assets/refs/cp15.png", + "cmd": "sample", + "box": [ + 20, + 22, + 130, + 52 + ], + "only": "flat", + "pt": 3, + "mine": "15-app-store.png", + "_": "15 the App Store page above the sheet (sheet top 62), under the template's clock, whose glyphs the flat census ignores: the dimmed ground" + }, + { + "id": "store-disc-15", + "img": "assets/refs/cp15.png", + "cmd": "sample", + "box": [ + 20, + 100, + 32, + 112 + ], + "only": "all", + "pt": 3, + "mine": "15-app-store.png", + "_": "15 the close disc's interior (d 45.4 at 15.3, 77.3) left of the X glyph (starts x 29)" + }, + { + "id": "store-pill-15", + "img": "assets/refs/cp15.png", + "cmd": "sample", + "box": [ + 300, + 440, + 382, + 448 + ], + "only": "flat", + "pt": 3, + "mine": "15-app-store.png", + "_": "15 the Purchased pill (289-382 x 440-472) above its label (ink top 451.7): pill fill" + }, + { + "id": "store-rule-15", + "img": "assets/refs/cp15.png", + "cmd": "scan", + "box": null, + "axis": "col", + "at": 200, + "range": [ + 274, + 284 + ], + "pt": 3, + "mine": "15-app-store.png", + "_": "15 down x 200 across the first rule (278.67): sheet, one px of rule, sheet" + }, + { + "id": "store-mute-15", + "img": "assets/refs/cp15.png", + "cmd": "sample", + "box": [ + 155, + 173, + 326, + 187 + ], + "only": "ink", + "pt": 3, + "mine": "15-app-store.png", + "_": "15 'AI agents that do real work' under the title (ends 162.4): the subtitle ink" + }, + { + "id": "store-val-15", + "img": "assets/refs/cp15.png", + "cmd": "sample", + "box": [ + 52, + 318, + 84, + 334 + ], + "only": "ink", + "pt": 3, + "mine": "15-app-store.png", + "_": "15 '4.9' in the ratings column (ink top 318.7), above the stars (start 343)" + }, + { + "id": "store-label-15", + "img": "assets/refs/cp15.png", + "cmd": "sample", + "box": [ + 30, + 295, + 107, + 303 + ], + "only": "ink", + "pt": 3, + "mine": "15-app-store.png", + "_": "15 '3.3K RATINGS' (ink 295-303), between the rule at 278.67 and the value at 318.7" + }, + { + "id": "store-link-15", + "img": "assets/refs/cp15.png", + "cmd": "sample", + "box": [ + 350, + 638, + 382, + 647 + ], + "only": "ink", + "pt": 3, + "mine": "15-app-store.png", + "_": "15 'more' at the end of the release notes (ink 638-647), right of 'template' (ends x 90)" + }, + { + "id": "store-pill-ink-15", + "img": "assets/refs/cp15.png", + "cmd": "sample", + "box": [ + 302, + 451, + 369, + 461 + ], + "only": "ink", + "pt": 3, + "mine": "15-app-store.png", + "_": "15 'Purchased' on its pill (ink 451.7-461): the label ink over #EEEEEF" + }, + { + "id": "store-title-15", + "img": "assets/refs/cp15.png", + "cmd": "bbox", + "box": [ + 150, + 143, + 245, + 168 + ], + "pt": 3, + "mine": "15-app-store.png", + "_": "15 'Grok Bot' beside the icon (icon ends x 138), ink 146.7-162.4; the subtitle starts 173.7" + }, + { + "id": "store-sub-15", + "img": "assets/refs/cp15.png", + "cmd": "bbox", + "box": [ + 150, + 170, + 330, + 190 + ], + "pt": 3, + "mine": "15-app-store.png", + "_": "15 'AI agents that do real work' (ink 173.7-187), above the cloud button (starts 231.7)" + }, + { + "id": "store-h-15", + "img": "assets/refs/cp15.png", + "cmd": "bbox", + "box": [ + 15, + 389, + 180, + 411 + ], + "pt": 3, + "mine": "15-app-store.png", + "_": "15 'Also Included In' (ink 392.3-408), under the second rule (366.67) and above the bundle art (starts 425)" + }, + { + "id": "store-bundle-15", + "img": "assets/refs/cp15.png", + "cmd": "bbox", + "box": [ + 88, + 428, + 285, + 448 + ], + "pt": 3, + "mine": "15-app-store.png", + "_": "15 'Apps by SpaceXAI: AI,' right of the bundle art (ends x 82) and left of the Purchased pill (starts 289), ink 432-447" + }, + { + "id": "store-body-15", + "img": "assets/refs/cp15.png", + "cmd": "bbox", + "box": [ + 15, + 595, + 300, + 613 + ], + "pt": 3, + "mine": "15-app-store.png", + "_": "15 the first release-note line (ink top 598.3); line 2 starts 617.3" + }, + { + "id": "side-ink", + "img": "assets/refs/cp4.png", + "cmd": "sample", + "box": [ + 347.0, + 233.6, + 363.7, + 252.1 + ], + "only": "ink", + "bright": true, + "mine": "04-voice-settings.png", + "_": "04 the trash glyph's box (x 347-363.7, y 233.6-252.1): flat #CDCECF ink over the glass disc, the disc's ground at 163 there; the focus box reads the same ink over 180 and the hanger over 194, which is why it is a grey and not an alpha", + "ink": "3" + }, + { + "id": "ic-focus-04", + "img": "assets/refs/cp4.png", + "cmd": "bbox", + "box": [ + 344, + 128, + 366, + 150 + ], + "bright": 200, + "mine": "04-voice-settings.png", + "_": "04 the focus ring alone, 1pt of disc ground on each side: the disc is 180 under it and the ring's 205 ink is the only thing over 200; expect 345.2-365.0 x 129.3-149.1, the SVG's viewBox" + }, + { + "id": "ic-trash-04", + "img": "assets/refs/cp4.png", + "cmd": "bbox", + "box": [ + 345, + 231, + 366, + 254 + ], + "bright": 200, + "mine": "04-voice-settings.png", + "_": "04 the trash glyph alone, 2pt of disc ground around it (163 there); expect 347.0-363.7 x 233.6-252.1, the SVG's viewBox. The hanger gets no bbox: its cloud ground is within 10 levels of the ink" + }, + { + "id": "dim-08", + "img": "assets/refs/cp8.png", + "cmd": "sample", + "box": [ + 0, + 150, + 393, + 380 + ], + "only": "flat", + "mine": "08-voice-select-ara.png", + "_": "08 the dimmed home between the nav and the card, y 150-380: flat ground, no chrome (the card starts at 403.6)" + }, + { + "id": "nav-well", + "img": "assets/refs/cp8.png", + "cmd": "sample", + "box": [ + 19, + 65, + 59, + 105 + ], + "only": "flat", + "mine": "08-voice-select-ara.png", + "_": "08 the menu disc 17.8-60.7 x 63.1-106.9; the hamburger 28.5-48.2 x 79.9-90.6 is inside it, too thin to win a flat census" + }, + { + "id": "t-nav-ask", + "img": "assets/refs/cp8.png", + "cmd": "bbox", + "box": [ + 135, + 72, + 175, + 96 + ], + "dark": 100, + "mine": "08-voice-select-ara.png", + "_": "08 'Ask' alone: the pill ground around it is 3 levels under dim, under any ink threshold; expect 142.3-168.6 x 78.5-90.6" + }, + { + "id": "t-nav-imagine", + "img": "assets/refs/cp8.png", + "cmd": "bbox", + "box": [ + 188, + 72, + 258, + 98 + ], + "dark": 100, + "mine": "08-voice-select-ara.png", + "_": "08 'Imagine' alone between the pill and the compose disc; expect 194.9-251.6 x 78.5-93.2" + }, + { + "id": "voice-sheet", + "img": "assets/refs/cp8.png", + "cmd": "sample", + "box": [ + 40, + 420, + 120, + 700 + ], + "only": "flat", + "mine": "08-voice-select-ara.png", + "_": "08 the card interior left of the orb (138.7-255.2) and the title (from 138.7): flat card, no type" + }, + { + "id": "t-voice-title", + "img": "assets/refs/cp8.png", + "cmd": "bbox", + "box": [ + 120, + 428, + 275, + 452 + ], + "dark": 100, + "mine": "08-voice-select-ara.png", + "_": "08 'Voice Selection' alone on the card, the orb starts at 502; expect 138.7-254.3 x 434.0-446.5" + }, + { + "id": "t-voice-name", + "img": "assets/refs/cp8.png", + "cmd": "bbox", + "box": [ + 170, + 600, + 225, + 625 + ], + "dark": 100, + "mine": "08-voice-select-ara.png", + "_": "08 'Ara' between the orb (to 573.7) and 'Upbeat Female' (from 630.8); expect 184.2-208.8 x 608.0-619.6" + }, + { + "id": "voice-sub", + "img": "assets/refs/cp8.png", + "cmd": "sample", + "box": [ + 142, + 630, + 252, + 646 + ], + "only": "ink", + "mine": "08-voice-select-ara.png", + "_": "08 'Upbeat Female' 142.7-251.1 x 630.8-645.5, the ghost line starts at 646" + }, + { + "id": "t-voice-sub", + "img": "assets/refs/cp8.png", + "cmd": "bbox", + "box": [ + 130, + 626, + 265, + 650 + ], + "dark": 140, + "mine": "08-voice-select-ara.png", + "_": "08 'Upbeat Female' alone; the ghost line below 646 is lighter than 140; expect 142.7-251.1 x 630.8-645.5" + }, + { + "id": "dot-off", + "img": "assets/refs/cp8.png", + "cmd": "sample", + "box": [ + 187, + 707, + 193.5, + 713.5 + ], + "only": "all", + "mine": "08-voice-select-ara.png", + "_": "08 the second page dot, inactive on this screen (the first is ink), 187.0-193.2 x 707.1-713.4: mode of a 6.3pt disc" + }, + { + "id": "t-hint", + "img": "assets/refs/cp8.png", + "cmd": "bbox", + "box": [ + 90, + 760, + 300, + 784 + ], + "dark": 140, + "mine": "08-voice-select-ara.png", + "_": "08 'Swipe to explore more voices' alone under the dots (to 713.4); expect 101.7-292.2 x 765.9-778.9" + }, + { + "id": "voice-btn", + "img": "assets/refs/cp9.png", + "cmd": "sample", + "box": [ + 60, + 750, + 150, + 792 + ], + "only": "flat", + "mine": "09-voice-select-eve.png", + "_": "09 the Continue pill 46.5-347.2 x 746.1-796.5 left of its label (from 163.3)" + }, + { + "id": "t-voice-btn", + "img": "assets/refs/cp9.png", + "cmd": "bbox", + "box": [ + 150, + 758, + 245, + 782 + ], + "bright": 200, + "mine": "09-voice-select-eve.png", + "_": "09 'Continue' white on the pill; expect 163.3-230.6 x 764.6-777.1" + }, + { + "id": "t-voice-name-09", + "img": "assets/refs/cp9.png", + "cmd": "bbox", + "box": [ + 170, + 600, + 225, + 625 + ], + "dark": 100, + "mine": "09-voice-select-eve.png", + "_": "09 'Eve' alone; expect 184.7-209.7 x 608.0-619.6" + }, + { + "id": "sheet-top-s", + "img": "assets/refs/cp10.png", + "cmd": "scan", + "axis": "col", + "at": 100, + "range": [ + 40, + 80 + ], + "mine": "10-settings.png", + "_": "10 col x100 across the sheet's edge, clear of the template island (130-263): dim to 58.7, the sheet from there; the title starts at 90.6" + }, + { + "id": "sheet-10", + "img": "assets/refs/cp10.png", + "cmd": "sample", + "box": [ + 100, + 262, + 300, + 292 + ], + "only": "flat", + "mine": "10-settings.png", + "_": "10 the sheet between the profile card (to 256.6) and 'General' (from 298.0): flat sheet, nothing on it" + }, + { + "id": "card-10", + "img": "assets/refs/cp10.png", + "cmd": "sample", + "box": [ + 200, + 326, + 340, + 368 + ], + "only": "flat", + "mine": "10-settings.png", + "_": "10 the first card's interior right of 'Appearance' (to 155.2) and left of the chevron (351.5): white" + }, + { + "id": "avatar", + "img": "assets/refs/cp10.png", + "cmd": "sample", + "box": [ + 34, + 183, + 90, + 238 + ], + "only": "flat", + "mine": "10-settings.png", + "_": "10 the profile disc 32.1-91.9 x 180.2-240.4; the person glyph 49.5-74.5 x 197.2-223.9 is a minority of it" + }, + { + "id": "t-h-name", + "img": "assets/refs/cp10.png", + "cmd": "bbox", + "box": [ + 98, + 176, + 200, + 200 + ], + "dark": 100, + "mine": "10-settings.png", + "_": "10 'Alex Smith' alone above the email (from 204.8); expect 104.8-187.8 x 182.5-195.8" + }, + { + "id": "t-mail", + "img": "assets/refs/cp10.png", + "cmd": "bbox", + "box": [ + 98, + 200, + 320, + 224 + ], + "dark": 160, + "mine": "10-settings.png", + "_": "10 the email's first line alone, between the name (to 195.8) and 'com' (from 229.3); the chevron sits at 351.5; expect 104.8-312.3 x 204.8-219.5" + }, + { + "id": "sec-ink", + "img": "assets/refs/cp10.png", + "cmd": "sample", + "box": [ + 285, + 550, + 338, + 566 + ], + "only": "ink", + "mine": "10-settings.png", + "_": "10 'English' 285.5-337.7 x 550.5-566.1, the chevron is 14pt to its right" + }, + { + "id": "section-ink", + "img": "assets/refs/cp10.png", + "cmd": "sample", + "box": [ + 33, + 298, + 86, + 309 + ], + "only": "ink", + "mine": "10-settings.png", + "_": "10 'General' 33.0-86.1 x 298.0-309.1 on the sheet" + }, + { + "id": "t-section", + "img": "assets/refs/cp10.png", + "cmd": "bbox", + "box": [ + 25, + 292, + 100, + 314 + ], + "dark": 160, + "mine": "10-settings.png", + "_": "10 'General' alone between the profile card (to 256.6) and the first card (from 323.1); expect 33.0-86.1 x 298.0-309.1" + }, + { + "id": "card-line", + "img": "assets/refs/cp10.png", + "cmd": "sample", + "box": [ + 100, + 373.9, + 300, + 374.8 + ], + "only": "ink", + "mine": "10-settings.png", + "_": "10 the rule under 'Appearance', x 64.3-360.7 at y 373.9-374.8: the darkest 2% of a band holding only the rule and white is the rule" + }, + { + "id": "t-body-row", + "img": "assets/refs/cp10.png", + "cmd": "bbox", + "box": [ + 60, + 337, + 180, + 360 + ], + "dark": 100, + "mine": "10-settings.png", + "_": "10 'Appearance' alone: the icon ends at 51.7, the chevron starts at 351.5; expect 64.7-155.2 x 343.0-358.2" + }, + { + "id": "row-s", + "img": "assets/refs/cp10.png", + "cmd": "bbox", + "box": [ + 60, + 631, + 160, + 655 + ], + "dark": 100, + "mine": "10-settings.png", + "_": "10 'Kids Mode', the first row of the second card at 618.0: expect 65.6-144.1 x 637.5-650.4, cap top card + 19.5" + }, + { + "id": "toggle-off", + "img": "assets/refs/cp11.png", + "cmd": "sample", + "box": [ + 342, + 284, + 362, + 310 + ], + "only": "flat", + "mine": "11-settings-voice.png", + "_": "11 the track right of its knob (knob to 339.1), 300.3-362.7 x 283.0-310.7" + }, + { + "id": "t-section-11", + "img": "assets/refs/cp11.png", + "cmd": "bbox", + "box": [ + 25, + 347, + 180, + 370 + ], + "dark": 160, + "mine": "11-settings-voice.png", + "_": "11 'Data & Information' alone on the sheet between two cards (323.1 and 378.4); expect 33.5-165.5 x 353.3-364.5" + }, + { + "id": "t-body-row-11", + "img": "assets/refs/cp11.png", + "cmd": "bbox", + "box": [ + 60, + 284, + 260, + 308 + ], + "dark": 100, + "mine": "11-settings-voice.png", + "_": "11 'Open App in Voice Mode' alone, the toggle starts at 300.3; expect 65.1-251.6 x 290.4-306.0" + }, + { + "id": "danger", + "img": "assets/refs/cp12.png", + "cmd": "sample", + "box": [ + 65, + 652, + 130, + 668 + ], + "only": "ink", + "mine": "12-settings-bottom.png", + "_": "12 'Sign Out' 65.1-129.4 x 652.2-667.8 on the white card: ink core of thin red strokes" + }, + { + "id": "t-danger", + "img": "assets/refs/cp12.png", + "cmd": "bbox", + "box": [ + 60, + 646, + 140, + 672 + ], + "dark": 200, + "mine": "12-settings-bottom.png", + "_": "12 'Sign Out' alone: the icon ends at 50.4; expect 65.1-129.4 x 652.2-667.8" + }, + { + "id": "version-ink", + "img": "assets/refs/cp12.png", + "cmd": "sample", + "box": [ + 103, + 770, + 290, + 783 + ], + "only": "ink", + "mine": "12-settings-bottom.png", + "_": "12 'VERSION 1.3.42 (BUILD 2776)' 103.0-290.0 x 770.8-782.4 on the sheet" + }, + { + "id": "t-version", + "img": "assets/refs/cp12.png", + "cmd": "bbox", + "box": [ + 95, + 765, + 300, + 788 + ], + "dark": 225, + "mine": "12-settings-bottom.png", + "_": "12 the version line alone under the xAI mark (to 754.8); expect 103.0-290.0 x 770.8-782.4" + } +] diff --git a/mockups/canvases/grok-ios/ref-14-grok-bot-sheet.html b/mockups/canvases/grok-ios/ref-14-grok-bot-sheet.html new file mode 100644 index 00000000..9ce18f52 --- /dev/null +++ b/mockups/canvases/grok-ios/ref-14-grok-bot-sheet.html @@ -0,0 +1,225 @@ + + + + +Grok iOS - reference: Introducing Grok Bot + + + +
Introducing Grok Bot
+ +