@nok-integration/storefront-react 0.17.1 → 0.17.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/styles.css CHANGED
@@ -32,8 +32,13 @@
32
32
  --type-heading-lg-size: 24px;
33
33
  --type-heading-lg-line: 1.2;
34
34
  --type-heading-md-size: 20px;
35
- --type-heading-sm-size: 20px;
36
35
  --type-heading-md-line: 1.25;
36
+ /* `size/heading/sm` + `heading/sm-bold`. This used to read 20px, which is the
37
+ library's heading/md — the two components that want it (the PDP's "Why us" tiles
38
+ and the size guide's "How to measure") both wrote 18 out by hand to work around
39
+ it, and nothing else consumes it. */
40
+ --type-heading-sm-size: 18px;
41
+ --type-heading-sm-line: 1.38;
37
42
  --type-paragraph-size: 16px;
38
43
  --type-paragraph-line: 1.55;
39
44
  --type-trimmed-md-size: 16px;
@@ -56,6 +61,10 @@
56
61
  --color-border-default, but a separate token in DAZN's library; keep them separate. */
57
62
  --color-surface-subtle: #dddedf;
58
63
  --color-surface-max: #080e12;
64
+ /* semantic/base/surface/full-color/neutral — the selected half of a segmented
65
+ control and the close disc on a sheet header. `full-color`, so it is the same
66
+ value in both palettes and is not remapped below. */
67
+ --color-surface-neutral: #ced0d2;
59
68
  --color-border-default: #dddedf;
60
69
  --color-border-subtle: #ced0d2;
61
70
  /* semantic/base/border/transparent/soft. Alpha rather than a flat grey on purpose: it
@@ -491,40 +500,55 @@
491
500
  ._action_ney0g_57 {
492
501
  margin: var(--space-8) var(--space-16) 0;
493
502
  }
494
- ._root_1u83t_1 {
503
+ /*
504
+ * The design's shared empty state, instanced by the cart (Figma 4451:48190) and the orders
505
+ * list (4551:32238). Both frames draw the same block: a 24px heading, a paragraph 6px
506
+ * under it, and the action 24 below the pair.
507
+ */
508
+ ._root_ryf3q_6 {
495
509
  display: flex;
496
510
  flex-direction: column;
497
511
  align-items: center;
498
512
  text-align: center;
499
- gap: var(--space-8);
513
+ gap: var(--space-24);
500
514
  padding: var(--space-32) var(--space-24);
501
515
  }
502
516
 
503
- ._icon_1u83t_10 {
517
+ ._icon_ryf3q_15 {
504
518
  font-size: 32px;
505
519
  line-height: 1;
506
520
  }
507
521
 
508
- ._title_1u83t_15 {
509
- font-size: var(--type-heading-md-size);
510
- line-height: var(--type-heading-md-line);
522
+ /* The heading and the paragraph, 6px apart — `spacer/spacer-xxs`. */
523
+ ._text_ryf3q_21 {
524
+ display: flex;
525
+ flex-direction: column;
526
+ gap: var(--space-6);
527
+ }
528
+
529
+ /*
530
+ * `heading/lg`, 24px, and the 1.32 the design system gives it rather than
531
+ * `--type-heading-lg-line`. That token is 1.2, which is a divergence of its own on every
532
+ * screen that reads it; correcting it there moves the PDP title, the lifestyle copy and
533
+ * the review carousel, so it is written out here and left for a measured pass of its own.
534
+ *
535
+ * Both frames make this line 32px tall, which is 24 x 1.32.
536
+ */
537
+ ._title_ryf3q_35 {
538
+ font-size: var(--type-heading-lg-size);
539
+ line-height: 1.32;
511
540
  }
512
541
 
513
- ._body_1u83t_20 {
542
+ ._body_ryf3q_40 {
514
543
  margin: 0;
515
544
  color: var(--color-text-subtle);
516
545
  font-size: var(--type-paragraph-size);
546
+ line-height: var(--type-paragraph-line);
517
547
  max-width: 34ch;
518
548
  }
519
549
 
520
- /*
521
- * The one place the empty state is drawn is the cart (Figma 4451:48190), and it separates
522
- * the action from the copy far more than it separates the two lines of copy: 24 against 6.
523
- * With the `gap` above, this lands the button 28px below the last line where the frame has
524
- * 28 — it was 20, close enough to the paragraph above to read as part of it.
525
- */
526
- ._action_1u83t_33 {
527
- margin-top: var(--space-16);
550
+ ._action_ryf3q_48 {
551
+ display: flex;
528
552
  }
529
553
  ._root_1lbpx_1 {
530
554
  display: flex;
@@ -1057,158 +1081,40 @@
1057
1081
  ._row_1hsxt_16._discount_1hsxt_69 dd {
1058
1082
  color: var(--color-state-text-success);
1059
1083
  }
1060
- ._page_1eqkm_1 {
1061
- display: flex;
1062
- flex-direction: column;
1063
- gap: var(--space-24);
1064
- padding: var(--space-24) var(--space-16);
1065
- }
1066
-
1067
- /* ── Status + timeline ─────────────────────────────────────────────────────── */
1068
-
1069
- ._status_1eqkm_10 {
1070
- display: flex;
1071
- flex-direction: column;
1072
- gap: var(--space-24);
1073
- }
1074
-
1075
- /* The timeline and its button are one block in the design — 16px apart, 24px from the
1076
- heading above them. */
1077
- ._widget_1eqkm_18 {
1078
- display: flex;
1079
- flex-direction: column;
1080
- gap: var(--space-16);
1081
- }
1082
-
1083
- ._title_1eqkm_24 {
1084
- display: flex;
1085
- flex-direction: column;
1086
- gap: var(--space-12);
1087
- }
1088
-
1089
- ._headline_1eqkm_30 {
1090
- margin: 0;
1091
- font-size: var(--type-heading-md-size);
1092
- line-height: 1.32;
1093
- font-weight: var(--font-weight-bold);
1094
- }
1095
-
1096
- ._subtitle_1eqkm_37 {
1097
- margin: 0;
1098
- display: flex;
1099
- align-items: center;
1100
- gap: var(--space-8);
1101
- flex-wrap: wrap;
1102
- font-size: var(--type-paragraph-size);
1103
- font-weight: var(--font-weight-regular);
1104
- color: var(--color-text-subtle);
1105
- }
1106
-
1107
- ._dot_1eqkm_48 {
1108
- width: 4px;
1109
- height: 4px;
1110
- border-radius: var(--radius-full);
1111
- background: currentColor;
1112
- flex-shrink: 0;
1113
- }
1114
-
1115
- /* Figma `mobile/button`, as an anchor: the destination is the carrier's own site, so this
1116
- is a link and has to behave like one — middle-click, long-press, open in new tab. */
1117
- ._trackButton_1eqkm_58 {
1118
- display: flex;
1119
- align-items: center;
1120
- justify-content: center;
1121
- min-height: 48px;
1122
- padding: var(--space-12);
1123
- border-radius: var(--radius-8);
1124
- background: var(--color-surface-max);
1125
- color: var(--color-text-strong);
1126
- font-size: var(--type-trimmed-md-size);
1127
- font-weight: var(--font-weight-bold);
1128
- text-align: center;
1129
- text-decoration: none;
1130
- }
1131
-
1132
- ._trackButton_1eqkm_58:focus-visible {
1133
- outline: none;
1134
- box-shadow: var(--focus-ring);
1135
- }
1136
-
1137
- ._srOnly_1eqkm_78 {
1138
- position: absolute;
1139
- width: 1px;
1140
- height: 1px;
1141
- padding: 0;
1142
- margin: -1px;
1143
- overflow: hidden;
1144
- clip: rect(0, 0, 0, 0);
1145
- white-space: nowrap;
1146
- border: 0;
1147
- }
1148
-
1149
- /* ── Items card ────────────────────────────────────────────────────────────── */
1150
-
1151
- ._itemsCard_1eqkm_92 {
1152
- display: flex;
1153
- flex-direction: column;
1154
- border: 1px solid var(--color-border-transparent-soft);
1155
- border-radius: var(--radius-18);
1156
- overflow: hidden;
1157
- }
1158
-
1159
- ._cardHeader_1eqkm_100 {
1160
- display: flex;
1161
- align-items: center;
1162
- gap: var(--space-12);
1163
- min-height: 60px;
1164
- padding: 0 var(--space-16);
1165
- }
1166
-
1167
- ._cardTitle_1eqkm_108 {
1168
- margin: 0;
1169
- font-size: var(--type-heading-md-size);
1170
- line-height: 1.38;
1171
- font-weight: var(--font-weight-bold);
1172
- }
1084
+ /*
1085
+ * The blocks the confirmation (Figma 5295:74053) and the tracking screen (5479:132209)
1086
+ * both draw: the item rows, then the two cards. Written once because the frames instance
1087
+ * one set of components, and measured against both.
1088
+ */
1173
1089
 
1174
- ._count_1eqkm_115 {
1175
- display: inline-flex;
1176
- align-items: center;
1177
- justify-content: center;
1178
- min-width: 16px;
1179
- height: 16px;
1180
- padding: 0 var(--space-4);
1181
- border-radius: var(--radius-full);
1182
- background: var(--color-surface-subtle);
1183
- font-size: var(--type-trimmed-xs-size);
1184
- font-weight: var(--font-weight-bold);
1185
- letter-spacing: 0.12px;
1186
- font-variant-numeric: tabular-nums;
1187
- }
1090
+ /* ── Lines ─────────────────────────────────────────────────────────────────── */
1188
1091
 
1189
- ._lines_1eqkm_130 {
1092
+ /*
1093
+ * `mobile/checkout/cart-row`, and deliberately NOT inside a card.
1094
+ *
1095
+ * Both frames lay the rows straight on the page between the widget and the address. The
1096
+ * tracking screen used to draw a bordered "Items" card with a count instead, off a frame
1097
+ * that has since been redrawn; nothing draws that card now.
1098
+ *
1099
+ * `CartLineItem` is left alone: its copy of this component carries a quantity stepper and
1100
+ * a remove control that a receipt must not have.
1101
+ */
1102
+ ._lines_7mr8w_19 {
1190
1103
  list-style: none;
1191
1104
  margin: 0;
1192
1105
  padding: 0;
1193
1106
  display: flex;
1194
1107
  flex-direction: column;
1195
- border-top: 1px solid var(--color-border-default);
1108
+ gap: var(--space-16);
1196
1109
  }
1197
1110
 
1198
- ._line_1eqkm_130 {
1111
+ ._line_7mr8w_19 {
1199
1112
  display: flex;
1200
1113
  align-items: center;
1201
1114
  gap: var(--space-12);
1202
- padding: var(--space-12) var(--space-16);
1203
- }
1204
-
1205
- /* Between lines only — a rule under the last one would float above the card's edge. The
1206
- 12px either side of it comes from the rows' own padding. */
1207
- ._line_1eqkm_130 + ._line_1eqkm_130 {
1208
- border-top: 1px solid var(--color-border-default);
1209
1115
  }
1210
1116
 
1211
- ._thumb_1eqkm_152 {
1117
+ ._thumb_7mr8w_34 {
1212
1118
  position: relative;
1213
1119
  flex-shrink: 0;
1214
1120
  width: 48px;
@@ -1218,388 +1124,372 @@
1218
1124
  background: var(--color-surface-soft);
1219
1125
  }
1220
1126
 
1221
- ._image_1eqkm_162 {
1127
+ ._image_7mr8w_44 {
1222
1128
  object-fit: cover;
1223
1129
  }
1224
1130
 
1225
- ._placeholder_1eqkm_166 {
1131
+ ._placeholder_7mr8w_48 {
1226
1132
  width: 100%;
1227
1133
  height: 100%;
1228
1134
  }
1229
1135
 
1230
- /* Title and price share a top edge; the thumbnail centres against the pair. */
1231
- ._lineBody_1eqkm_172 {
1136
+ ._lineBody_7mr8w_53 {
1232
1137
  display: flex;
1233
1138
  align-items: flex-start;
1234
1139
  justify-content: space-between;
1140
+ gap: var(--space-16);
1235
1141
  flex: 1 1 0;
1236
1142
  min-width: 0;
1237
1143
  }
1238
1144
 
1239
- ._lineText_1eqkm_180 {
1145
+ ._lineText_7mr8w_62 {
1240
1146
  display: flex;
1241
1147
  flex-direction: column;
1242
1148
  gap: var(--space-12);
1243
1149
  flex: 1 1 0;
1244
1150
  min-width: 0;
1245
- padding-right: var(--space-16);
1246
1151
  }
1247
1152
 
1248
- ._lineTitle_1eqkm_189 {
1153
+ /* Cap-trimmed to the frame's 11, with the same descender protection as the subtitle —
1154
+ this one is ellipsised too, and a `p` or a `g` in a product name is not unusual. */
1155
+ ._lineTitle_7mr8w_72 {
1156
+ margin: -6px 0;
1157
+ padding: 6px 0;
1249
1158
  font-size: var(--type-trimmed-sm-size);
1159
+ line-height: 11px;
1250
1160
  font-weight: var(--font-weight-bold);
1251
1161
  white-space: nowrap;
1252
1162
  overflow: hidden;
1253
1163
  text-overflow: ellipsis;
1254
1164
  }
1255
1165
 
1256
- ._lineDetails_1eqkm_197 {
1166
+ /*
1167
+ * The variant, then the sale badge beside it — 12px apart, vertically centred on it.
1168
+ *
1169
+ * Cap-trimmed like the title above, which is what leaves the badge as the tallest thing in
1170
+ * the row and holds it to the 20px the frame gives it. Untrimmed the text alone was 22, so
1171
+ * the row stood 55 against the frame's 48 and the thumbnail stopped being what sets the
1172
+ * row's height.
1173
+ */
1174
+ ._lineMeta_7mr8w_91 {
1257
1175
  display: flex;
1176
+ align-items: center;
1258
1177
  gap: var(--space-12);
1178
+ min-width: 0;
1259
1179
  font-size: var(--type-trimmed-sm-size);
1180
+ line-height: 11px;
1260
1181
  color: var(--color-text-subtle);
1261
- min-width: 0;
1262
1182
  }
1263
1183
 
1264
- ._linePrice_1eqkm_205 {
1184
+ /*
1185
+ * Stacked, not in a row: the frame puts what was paid above what it would have cost, at
1186
+ * two different sizes. That is why this is written here rather than with `PriceBlock`,
1187
+ * which lays the pair out inline at one size for the product card and the PDP.
1188
+ */
1189
+ ._linePrice_7mr8w_106 {
1190
+ display: flex;
1191
+ flex-direction: column;
1192
+ align-items: flex-end;
1193
+ gap: var(--space-6);
1265
1194
  flex-shrink: 0;
1266
- font-size: var(--type-trimmed-md-size);
1267
- font-weight: var(--font-weight-bold);
1268
1195
  white-space: nowrap;
1269
1196
  font-variant-numeric: tabular-nums;
1270
1197
  }
1271
1198
 
1272
- /* ── Address + payment ─────────────────────────────────────────────────────── */
1273
-
1274
- ._details_1eqkm_215 {
1275
- display: flex;
1276
- flex-direction: column;
1277
- gap: var(--space-16);
1278
- padding: var(--space-16);
1279
- background: var(--color-surface-soft);
1280
- border: 1px solid var(--color-border-default);
1281
- border-radius: var(--radius-18);
1282
- /* The design nests this card inside a second, one-step-darker ring. Drawn as a shadow
1283
- rather than a wrapper element: the two borders are coincident, so it renders the same. */
1284
- box-shadow: 0 0 0 1px var(--color-border-subtle);
1285
- }
1286
-
1287
- ._detailBlock_1eqkm_228 {
1288
- display: flex;
1289
- flex-direction: column;
1290
- gap: var(--space-8);
1291
- }
1292
-
1293
- /* The payment block sits a step looser than the address one. */
1294
- ._detailBlock_1eqkm_228._payment_1eqkm_235 {
1295
- gap: var(--space-12);
1296
- }
1297
-
1298
- ._detailLabel_1eqkm_239 {
1299
- margin: 0;
1300
- font-size: var(--type-trimmed-sm-size);
1199
+ /* Cap-trimmed like everything else in this row: 11 on 16px, 10 on 14px. Untrimmed the
1200
+ pair stood 52 tall and became what set the row's height, against a 48px thumbnail. */
1201
+ ._paid_7mr8w_118 {
1202
+ font-size: var(--type-trimmed-md-size);
1203
+ line-height: 11px;
1301
1204
  font-weight: var(--font-weight-bold);
1302
1205
  }
1303
1206
 
1304
- ._detailValue_1eqkm_245 {
1305
- margin: 0;
1306
- display: flex;
1307
- align-items: center;
1308
- gap: var(--space-8);
1207
+ ._was_7mr8w_124 {
1309
1208
  font-size: var(--type-trimmed-sm-size);
1310
- line-height: var(--type-caption-sm-line);
1311
- color: var(--color-text-subtle);
1312
- }
1313
-
1314
- /* The masked digits carry the same weight as the brand beside them. */
1315
- ._last4_1eqkm_256 {
1316
- font-weight: var(--font-weight-bold);
1317
- }
1318
-
1319
- /* The brand as DAZN send it — lowercase on the wire, capitalised for display rather than
1320
- matched against a list, so an unfamiliar one still renders properly. */
1321
- ._brand_1eqkm_262 {
1322
- text-transform: capitalize;
1323
- font-weight: var(--font-weight-bold);
1324
- color: var(--color-text-default);
1325
- }
1326
-
1327
- ._divider_1eqkm_268 {
1328
- height: 1px;
1329
- background: var(--color-border-default);
1209
+ line-height: 10px;
1210
+ font-weight: var(--font-weight-regular);
1211
+ color: var(--color-text-disabled);
1212
+ text-decoration: line-through;
1330
1213
  }
1331
1214
 
1332
- /* ── Order summary ─────────────────────────────────────────────────────────── */
1215
+ /* ── Cards ─────────────────────────────────────────────────────────────────── */
1333
1216
 
1334
- ._summaryCard_1eqkm_275 {
1217
+ /*
1218
+ * The address and summary cards are one shape: a 60px titled header, a hairline, and a
1219
+ * body. They differ only in ground, which is what `.summaryCard` below changes.
1220
+ *
1221
+ * The ring is an inset shadow rather than a border, and that is a measurement rather than
1222
+ * a preference. Figma draws a frame's stroke INSIDE its box, so the address card is 113
1223
+ * tall with its outline in that 113 — 60 of header and 53 of body. A CSS border sits
1224
+ * outside the content and makes the same card 115. An inset shadow paints the same
1225
+ * hairline and occupies no layout, so the card lands on the design's own number.
1226
+ */
1227
+ ._card_7mr8w_144 {
1335
1228
  display: flex;
1336
1229
  flex-direction: column;
1337
- background: var(--color-surface-soft);
1338
- border: 1px solid var(--color-border-default);
1230
+ box-shadow: inset 0 0 0 1px var(--color-border-default);
1339
1231
  border-radius: var(--radius-18);
1340
1232
  overflow: hidden;
1341
1233
  }
1342
1234
 
1343
- ._summaryCard_1eqkm_275 ._cardTitle_1eqkm_108 {
1235
+ ._cardTitle_7mr8w_152 {
1344
1236
  display: flex;
1345
1237
  align-items: center;
1238
+ margin: 0;
1346
1239
  min-height: 60px;
1347
1240
  padding: 0 var(--space-16);
1241
+ border-bottom: 1px solid var(--color-border-default);
1242
+ font-size: var(--type-heading-md-size);
1243
+ line-height: 1.38;
1244
+ font-weight: var(--font-weight-bold);
1245
+ }
1246
+
1247
+ ._cardBody_7mr8w_164 {
1248
+ margin: 0;
1249
+ padding: var(--space-16);
1250
+ font-size: var(--type-trimmed-sm-size);
1251
+ line-height: 1.5;
1252
+ }
1253
+
1254
+ /* `surface/full-color/soft` — the summary is the one card the design fills. */
1255
+ ._summaryCard_7mr8w_136 {
1256
+ background: var(--color-surface-soft);
1348
1257
  }
1349
1258
 
1350
- /* The shared summary rows are drawn edge-to-edge in the cart; inside this card they need
1351
- the card's own gutter. */
1352
- ._summaryCard_1eqkm_275 > :last-child {
1259
+ /* The shared summary rows are drawn edge-to-edge in the cart; here they take the card's
1260
+ own gutter, as they do on the tracking screen. */
1261
+ ._summaryCard_7mr8w_136 > :last-child {
1353
1262
  padding: 0 var(--space-16);
1354
1263
  }
1355
1264
  /*
1356
- * Figma `5295:74053`. The page's own block starts at y=118 under the 64px bar and the
1357
- * 54px status bar the device draws above it — with 20px above the first heading, 24px
1358
- * below the last control, and 32px between the five blocks.
1265
+ * Figma `order stats` (5479:132209), whose three states differ only inside the widget.
1266
+ *
1267
+ * The page's own block starts at y=138 — 20 under the 118 of status bar and header — and
1268
+ * everything below it is 32 apart: widget, rule, rows, address, summary. Same rhythm and
1269
+ * same padding as the confirmation, which is the same page from the fold down.
1359
1270
  */
1360
- ._page_8yxu9_6 {
1271
+ ._page_1vg5x_8 {
1361
1272
  display: flex;
1362
1273
  flex-direction: column;
1363
1274
  gap: var(--space-32);
1364
1275
  padding: var(--space-20) var(--space-16) var(--space-24);
1365
1276
  }
1366
1277
 
1367
- /* ── Confirmation + timeline ───────────────────────────────────────────────── */
1278
+ /* ── Order number + timeline ───────────────────────────────────────────────── */
1368
1279
 
1369
- /* `mobile/order/delivery-widget`: the heading pair, then the timeline, 24px apart. */
1370
- ._confirmed_8yxu9_16 {
1280
+ /* `mobile/order/delivery-widget`: the title row, then the steps, 32 apart. */
1281
+ ._widget_1vg5x_18 {
1371
1282
  display: flex;
1372
1283
  flex-direction: column;
1373
- gap: var(--space-24);
1284
+ gap: var(--space-32);
1374
1285
  }
1375
1286
 
1376
- ._title_8yxu9_22 {
1287
+ /* The number on the left, the carrier link hard right — and nothing between them, so a
1288
+ long reference runs into the space the link is not using rather than under it. */
1289
+ ._titleRow_1vg5x_26 {
1377
1290
  display: flex;
1378
- flex-direction: column;
1291
+ align-items: center;
1292
+ justify-content: space-between;
1379
1293
  gap: var(--space-12);
1380
1294
  }
1381
1295
 
1382
1296
  /*
1383
- * Green, and the only green heading in the storefront: `semantic/state/text/success`
1384
- * rather than `text/default`, which is the design saying this line is a result and not a
1385
- * label. It is the same token the discount row and the "Free" shipping figure take, so
1386
- * the screen has one success tone rather than three.
1387
- *
1388
- * `line-height: 14px` on 20px text, and that is the frame's own number rather than a
1389
- * squeeze: every text layer here is `text-box-trim: trim-both` with a cap-alphabetic
1390
- * edge, so Figma's boxes stop at the cap height and its 14 is 14 of visible letter. A CSS
1391
- * line box carries the font's leading above and below, which renders the same heading as
1392
- * 26 and pushes all four blocks below it down by the difference.
1393
- *
1394
- * `text-box-trim` would let us write the design's own number and is Chrome 133+ only; this
1395
- * package still supports the WebView in React 16-era DAZN builds. `OrderTimeline` and
1396
- * `ProductTile` carry the same approximation for the same reason.
1297
+ * `line-height: 14px` on 20px text, which is the frame's own number rather than a squeeze:
1298
+ * every text layer here is `text-box-trim: trim-both` with a cap-alphabetic edge, so
1299
+ * Figma's box stops at the cap height and its 14 is 14 of visible letter. A CSS line box
1300
+ * carries the font's leading above and below, which renders the same heading as 26 and
1301
+ * pushes everything below it down by the difference.
1397
1302
  *
1398
- * Nothing clips it, so the cap-height box needs no descender protection — unlike the
1399
- * subtitle below, which the design truncates.
1303
+ * Nothing clips it, so the cap-height box needs no descender protection.
1400
1304
  */
1401
- ._headline_8yxu9_47 {
1305
+ ._headline_1vg5x_42 {
1402
1306
  margin: 0;
1307
+ min-width: 0;
1403
1308
  font-size: var(--type-heading-md-size);
1404
1309
  line-height: 14px;
1405
1310
  font-weight: var(--font-weight-bold);
1406
- color: var(--color-state-text-success);
1407
- }
1408
-
1409
- /*
1410
- * 11px on 16px text, the same cap-height trim as the heading, and one line: the design's
1411
- * own text layer is `overflow-hidden` with `text-ellipsis`, which is how it holds an
1412
- * address of unknown length to a single row.
1413
- *
1414
- * The padding is what the trim costs. Clipping cuts in both directions, and an 11px box
1415
- * beheads every descender — including the `g` in the `@gmail.com` the frame itself shows.
1416
- * The padding gives the glyphs somewhere to go and the equal negative margin takes it back
1417
- * out of the layout, leaving the box 11px and the letters whole.
1418
- */
1419
- ._subtitle_8yxu9_65 {
1420
- margin: -6px 0;
1421
- padding: 6px 0;
1422
- font-size: var(--type-paragraph-size);
1423
- line-height: 11px;
1424
- font-weight: var(--font-weight-regular);
1425
- color: var(--color-text-subtle);
1426
1311
  overflow: hidden;
1427
1312
  text-overflow: ellipsis;
1428
1313
  white-space: nowrap;
1429
1314
  }
1430
1315
 
1431
- /* ── Lines ─────────────────────────────────────────────────────────────────── */
1432
-
1433
1316
  /*
1434
- * `mobile/checkout/cart-row`, and deliberately NOT inside a card.
1317
+ * The carrier link: a text link with the design's `redirect-link` mark, not the 48px
1318
+ * button this used to be. The frame puts it on the title's own line, right-aligned, at the
1319
+ * same 16px as a timeline label.
1435
1320
  *
1436
- * The tracking screen puts its items in a bordered "Items" card with a count; this frame
1437
- * lays them straight on the page between the timeline and the address. The same data, and
1438
- * two designs — so the row is written here rather than either screen being bent to fit the
1439
- * other, and `CartLineItem` is left alone because its copy of this component carries a
1440
- * quantity stepper and a remove control that a receipt must not have.
1321
+ * An anchor rather than a button because the destination is a real page on somebody else's
1322
+ * site, and it has to behave like one: middle-click, long-press, open in a new tab.
1441
1323
  */
1442
- ._lines_8yxu9_88 {
1443
- list-style: none;
1444
- margin: 0;
1445
- padding: 0;
1446
- display: flex;
1447
- flex-direction: column;
1448
- gap: var(--space-16);
1449
- }
1450
-
1451
- ._line_8yxu9_88 {
1452
- display: flex;
1324
+ ._track_1vg5x_61 {
1325
+ display: inline-flex;
1453
1326
  align-items: center;
1454
- gap: var(--space-12);
1455
- }
1456
-
1457
- ._thumb_8yxu9_103 {
1458
- position: relative;
1327
+ gap: var(--space-6);
1459
1328
  flex-shrink: 0;
1460
- width: 48px;
1461
- height: 48px;
1462
- border-radius: var(--radius-8);
1463
- overflow: hidden;
1464
- background: var(--color-surface-soft);
1329
+ font-size: var(--type-trimmed-md-size);
1330
+ line-height: 14px;
1331
+ font-weight: var(--font-weight-bold);
1332
+ color: var(--color-text-default);
1333
+ text-decoration: none;
1465
1334
  }
1466
1335
 
1467
- ._image_8yxu9_113 {
1468
- object-fit: cover;
1336
+ ._track_1vg5x_61:focus-visible {
1337
+ outline: none;
1338
+ box-shadow: var(--focus-ring);
1339
+ border-radius: var(--radius-4);
1469
1340
  }
1470
1341
 
1471
- ._placeholder_8yxu9_117 {
1472
- width: 100%;
1473
- height: 100%;
1342
+ /*
1343
+ * The frame's `Line 11`, between the widget and the receipt.
1344
+ *
1345
+ * A Figma line has no height — 32 above it and 32 below it means 64 between the blocks it
1346
+ * separates, with the hairline drawn on that boundary. The negative margin takes the
1347
+ * pixel back out of the layout so the two gaps stay 32 rather than becoming 32 and 33.
1348
+ */
1349
+ ._rule_1vg5x_86 {
1350
+ height: 1px;
1351
+ margin: 0 0 -1px;
1352
+ border: 0;
1353
+ background: var(--color-border-default);
1474
1354
  }
1475
1355
 
1476
- ._lineBody_8yxu9_122 {
1477
- display: flex;
1478
- align-items: flex-start;
1479
- justify-content: space-between;
1480
- gap: var(--space-16);
1481
- flex: 1 1 0;
1482
- min-width: 0;
1483
- }
1356
+ /* ── Need help? ────────────────────────────────────────────────────────────── */
1484
1357
 
1485
- ._lineText_8yxu9_131 {
1358
+ /* `mobile/explore`: the heading, then the rows, 6 apart. */
1359
+ ._help_1vg5x_96 {
1486
1360
  display: flex;
1487
1361
  flex-direction: column;
1488
- gap: var(--space-12);
1489
- flex: 1 1 0;
1490
- min-width: 0;
1362
+ gap: var(--space-6);
1491
1363
  }
1492
1364
 
1493
- /* Cap-trimmed to the frame's 11, with the same descender protection as the subtitle —
1494
- this one is ellipsised too, and a `p` or a `g` in a product name is not unusual. */
1495
- ._lineTitle_8yxu9_141 {
1496
- margin: -6px 0;
1497
- padding: 6px 0;
1498
- font-size: var(--type-trimmed-sm-size);
1499
- line-height: 11px;
1365
+ ._helpTitle_1vg5x_102 {
1366
+ margin: 0;
1367
+ font-size: var(--type-heading-md-size);
1368
+ line-height: 1.32;
1500
1369
  font-weight: var(--font-weight-bold);
1501
- white-space: nowrap;
1502
- overflow: hidden;
1503
- text-overflow: ellipsis;
1370
+ }
1371
+
1372
+ ._helpRows_1vg5x_109 {
1373
+ display: flex;
1374
+ flex-direction: column;
1504
1375
  }
1505
1376
 
1506
1377
  /*
1507
- * The variant, then the sale badge beside it 12px apart, vertically centred on it.
1508
- *
1509
- * Cap-trimmed like the title above, which is what leaves the badge as the tallest thing in
1510
- * the row and holds it to the 20px the frame gives it. Untrimmed the text alone was 22, so
1511
- * the row stood 55 against the frame's 48 and the thumbnail stopped being what sets the
1512
- * row's height.
1378
+ * 48 tall: 16 of padding either side of a 16px chevron, which is what sets the height. The
1379
+ * label is cap-trimmed to 10 and is shorter than the mark beside it.
1513
1380
  */
1514
- ._lineMeta_8yxu9_160 {
1381
+ ._helpRow_1vg5x_109 {
1515
1382
  display: flex;
1516
1383
  align-items: center;
1384
+ justify-content: space-between;
1517
1385
  gap: var(--space-12);
1518
- min-width: 0;
1386
+ width: 100%;
1387
+ padding: var(--space-16) 0;
1388
+ border: 0;
1389
+ border-radius: var(--radius-8);
1390
+ background: none;
1391
+ color: var(--color-text-default);
1392
+ font-family: inherit;
1519
1393
  font-size: var(--type-trimmed-sm-size);
1520
- line-height: 11px;
1521
- color: var(--color-text-subtle);
1394
+ line-height: 10px;
1395
+ font-weight: var(--font-weight-bold);
1396
+ text-align: left;
1397
+ cursor: pointer;
1522
1398
  }
1523
1399
 
1524
1400
  /*
1525
- * Stacked, not in a row: the frame puts what was paid above what it would have cost, at
1526
- * two different sizes. That is why this is written here rather than with `PriceBlock`,
1527
- * which lays the pair out inline at one size for the product card and the PDP.
1401
+ * `border/full-color/subtle`, one step darker than the hairline the cards are drawn with,
1402
+ * and between the rows only a rule under the last one would leave the block underlined.
1403
+ *
1404
+ * After `.helpRow` and not before it: that rule sets `border: 0` and its own padding, and
1405
+ * at equal specificity the later one wins. Written first, this drew no line at all.
1406
+ *
1407
+ * Nothing gives the pixel back, because nothing takes it: the row's height comes from its
1408
+ * padding and its 16px chevron rather than from a `height`, so the hairline adds to the
1409
+ * row instead of eating into it. 48, the line, then 48 — the frame's own 97 for the pair.
1528
1410
  */
1529
- ._linePrice_8yxu9_175 {
1530
- display: flex;
1531
- flex-direction: column;
1532
- align-items: flex-end;
1533
- gap: var(--space-6);
1534
- flex-shrink: 0;
1535
- white-space: nowrap;
1536
- font-variant-numeric: tabular-nums;
1537
- }
1538
-
1539
- /* Cap-trimmed like everything else in this row: 11 on 16px, 10 on 14px. Untrimmed the
1540
- pair stood 52 tall and became what set the row's height, against a 48px thumbnail. */
1541
- ._paid_8yxu9_187 {
1542
- font-size: var(--type-trimmed-md-size);
1543
- line-height: 11px;
1544
- font-weight: var(--font-weight-bold);
1411
+ ._helpRow_1vg5x_109 + ._helpRow_1vg5x_109 {
1412
+ border-top: 1px solid var(--color-border-subtle);
1545
1413
  }
1546
1414
 
1547
- ._was_8yxu9_193 {
1548
- font-size: var(--type-trimmed-sm-size);
1549
- line-height: 10px;
1550
- font-weight: var(--font-weight-regular);
1551
- color: var(--color-text-disabled);
1552
- text-decoration: line-through;
1415
+ ._helpRow_1vg5x_109:focus-visible {
1416
+ outline: none;
1417
+ box-shadow: var(--focus-ring);
1553
1418
  }
1554
-
1555
- /* ── Cards ─────────────────────────────────────────────────────────────────── */
1556
-
1557
1419
  /*
1558
- * The address and summary cards are one shape: a 60px titled header, a hairline, and a
1559
- * body. They differ only in ground, which is what `.summaryCard` below changes.
1560
- *
1561
- * The ring is an inset shadow rather than a border, and that is a measurement rather than
1562
- * a preference. Figma draws a frame's stroke INSIDE its box, so the address card is 113
1563
- * tall with its outline in that 113 — 60 of header and 53 of body. A CSS border sits
1564
- * outside the content and makes the same card 115. An inset shadow paints the same
1565
- * hairline and occupies no layout, so the card lands on the design's own number.
1420
+ * Figma `5295:74053`. The page's own block starts at y=118 under the 64px bar and the
1421
+ * 54px status bar the device draws above it with 20px above the first heading, 24px
1422
+ * below the last control, and 32px between the five blocks.
1566
1423
  */
1567
- ._card_8yxu9_213 {
1424
+ ._page_1s8l9_6 {
1568
1425
  display: flex;
1569
1426
  flex-direction: column;
1570
- box-shadow: inset 0 0 0 1px var(--color-border-default);
1571
- border-radius: var(--radius-18);
1572
- overflow: hidden;
1427
+ gap: var(--space-32);
1428
+ padding: var(--space-20) var(--space-16) var(--space-24);
1573
1429
  }
1574
1430
 
1575
- ._cardTitle_8yxu9_221 {
1431
+ /* ── Confirmation + timeline ───────────────────────────────────────────────── */
1432
+
1433
+ /* `mobile/order/delivery-widget`: the heading pair, then the timeline, 24px apart. */
1434
+ ._confirmed_1s8l9_16 {
1576
1435
  display: flex;
1577
- align-items: center;
1578
- margin: 0;
1579
- min-height: 60px;
1580
- padding: 0 var(--space-16);
1581
- border-bottom: 1px solid var(--color-border-default);
1582
- font-size: var(--type-heading-md-size);
1583
- line-height: 1.38;
1584
- font-weight: var(--font-weight-bold);
1436
+ flex-direction: column;
1437
+ gap: var(--space-24);
1585
1438
  }
1586
1439
 
1587
- ._cardBody_8yxu9_233 {
1588
- margin: 0;
1589
- padding: var(--space-16);
1590
- font-size: var(--type-trimmed-sm-size);
1591
- line-height: 1.5;
1440
+ ._title_1s8l9_22 {
1441
+ display: flex;
1442
+ flex-direction: column;
1443
+ gap: var(--space-12);
1592
1444
  }
1593
1445
 
1594
- /* `surface/full-color/soft` — the summary is the one card the design fills. */
1595
- ._summaryCard_8yxu9_205 {
1596
- background: var(--color-surface-soft);
1446
+ /*
1447
+ * Green, and the only green heading in the storefront: `semantic/state/text/success`
1448
+ * rather than `text/default`, which is the design saying this line is a result and not a
1449
+ * label. It is the same token the discount row and the "Free" shipping figure take, so
1450
+ * the screen has one success tone rather than three.
1451
+ *
1452
+ * `line-height: 14px` on 20px text, and that is the frame's own number rather than a
1453
+ * squeeze: every text layer here is `text-box-trim: trim-both` with a cap-alphabetic
1454
+ * edge, so Figma's boxes stop at the cap height and its 14 is 14 of visible letter. A CSS
1455
+ * line box carries the font's leading above and below, which renders the same heading as
1456
+ * 26 and pushes all four blocks below it down by the difference.
1457
+ *
1458
+ * `text-box-trim` would let us write the design's own number and is Chrome 133+ only; this
1459
+ * package still supports the WebView in React 16-era DAZN builds. `OrderTimeline` and
1460
+ * `ProductTile` carry the same approximation for the same reason.
1461
+ *
1462
+ * Nothing clips it, so the cap-height box needs no descender protection — unlike the
1463
+ * subtitle below, which the design truncates.
1464
+ */
1465
+ ._headline_1s8l9_47 {
1466
+ margin: 0;
1467
+ font-size: var(--type-heading-md-size);
1468
+ line-height: 14px;
1469
+ font-weight: var(--font-weight-bold);
1470
+ color: var(--color-state-text-success);
1597
1471
  }
1598
1472
 
1599
- /* The shared summary rows are drawn edge-to-edge in the cart; here they take the card's
1600
- own gutter, as they do on the tracking screen. */
1601
- ._summaryCard_8yxu9_205 > :last-child {
1602
- padding: 0 var(--space-16);
1473
+ /*
1474
+ * 11px on 16px text, the same cap-height trim as the heading, and one line: the design's
1475
+ * own text layer is `overflow-hidden` with `text-ellipsis`, which is how it holds an
1476
+ * address of unknown length to a single row.
1477
+ *
1478
+ * The padding is what the trim costs. Clipping cuts in both directions, and an 11px box
1479
+ * beheads every descender — including the `g` in the `@gmail.com` the frame itself shows.
1480
+ * The padding gives the glyphs somewhere to go and the equal negative margin takes it back
1481
+ * out of the layout, leaving the box 11px and the letters whole.
1482
+ */
1483
+ ._subtitle_1s8l9_65 {
1484
+ margin: -6px 0;
1485
+ padding: 6px 0;
1486
+ font-size: var(--type-paragraph-size);
1487
+ line-height: 11px;
1488
+ font-weight: var(--font-weight-regular);
1489
+ color: var(--color-text-subtle);
1490
+ overflow: hidden;
1491
+ text-overflow: ellipsis;
1492
+ white-space: nowrap;
1603
1493
  }
1604
1494
 
1605
1495
  /* ── Done ──────────────────────────────────────────────────────────────────── */
@@ -1612,7 +1502,7 @@
1612
1502
  * which is what "max" means, and taking it from that token keeps the two in step if the
1613
1503
  * palette ever moves.
1614
1504
  */
1615
- ._done_8yxu9_261 {
1505
+ ._done_1s8l9_87 {
1616
1506
  border-color: var(--color-surface-max);
1617
1507
  }
1618
1508
  /*
@@ -1650,8 +1540,8 @@
1650
1540
  background: var(--color-state-surface-critical-soft);
1651
1541
  color: var(--color-state-text-critical);
1652
1542
  }
1653
- /* Figma `mobile/order/list` (4024:58594). */
1654
- ._page_y686q_2 {
1543
+ /* Figma `mobile/order/list` (4551:32241, in the `my orders` section 4551:32237). */
1544
+ ._page_6xodo_2 {
1655
1545
  list-style: none;
1656
1546
  margin: 0;
1657
1547
  display: flex;
@@ -1660,18 +1550,28 @@
1660
1550
  padding: var(--space-16) var(--space-16) var(--space-24);
1661
1551
  }
1662
1552
 
1663
- ._empty_y686q_11 {
1553
+ /*
1554
+ * The design centres the empty state in the whole screen below the header, not at the top
1555
+ * of an otherwise blank page: the block runs from the bar's bottom edge to 32px above the
1556
+ * foot of the display, with its contents centred inside that.
1557
+ *
1558
+ * The frame's own numbers are 96 to 780 of 812, and 96 is where the bar ended when this
1559
+ * screen was drawn — the cart's empty frame (4451:48190) has the same block at the same
1560
+ * two numbers under a 96px header. The bar is 118 with the status bar now, so following
1561
+ * the frame's literal 96 would tuck the heading under it. Measuring from the bar instead
1562
+ * keeps the intent and lands the block 11px lower than the export.
1563
+ */
1564
+ ._empty_6xodo_22 {
1664
1565
  display: flex;
1665
1566
  align-items: center;
1666
1567
  justify-content: center;
1667
- /* The design centres the empty state in the whole screen below the header, not at the
1668
- top of an otherwise blank page. */
1669
- min-height: 60dvh;
1568
+ min-height: calc(100dvh - var(--header-height) - var(--space-32));
1569
+ padding-bottom: var(--space-32);
1670
1570
  }
1671
1571
 
1672
1572
  /* `mobile/button`, the design's own dark CTA. Not the shared `Button` primary, whose
1673
1573
  shape is the cart's; this one is content-width with a 48px floor. */
1674
- ._cta_y686q_22 {
1574
+ ._cta_6xodo_32 {
1675
1575
  display: inline-flex;
1676
1576
  align-items: center;
1677
1577
  justify-content: center;
@@ -1689,12 +1589,12 @@
1689
1589
  cursor: pointer;
1690
1590
  }
1691
1591
 
1692
- ._cta_y686q_22:focus-visible {
1592
+ ._cta_6xodo_32:focus-visible {
1693
1593
  outline: none;
1694
1594
  box-shadow: var(--focus-ring);
1695
1595
  }
1696
1596
 
1697
- ._card_y686q_45 {
1597
+ ._card_6xodo_55 {
1698
1598
  display: flex;
1699
1599
  flex-direction: column;
1700
1600
  gap: var(--space-24);
@@ -1709,16 +1609,16 @@
1709
1609
  overflow: hidden;
1710
1610
  }
1711
1611
 
1712
- ._tappable_y686q_60 {
1612
+ ._tappable_6xodo_70 {
1713
1613
  cursor: pointer;
1714
1614
  }
1715
1615
 
1716
- ._tappable_y686q_60:focus-visible {
1616
+ ._tappable_6xodo_70:focus-visible {
1717
1617
  outline: none;
1718
1618
  box-shadow: var(--focus-ring);
1719
1619
  }
1720
1620
 
1721
- ._head_y686q_69 {
1621
+ ._head_6xodo_79 {
1722
1622
  display: flex;
1723
1623
  align-items: flex-start;
1724
1624
  justify-content: space-between;
@@ -1726,7 +1626,7 @@
1726
1626
  width: 100%;
1727
1627
  }
1728
1628
 
1729
- ._heading_y686q_77 {
1629
+ ._heading_6xodo_87 {
1730
1630
  display: flex;
1731
1631
  flex: 1 1 auto;
1732
1632
  flex-direction: column;
@@ -1735,7 +1635,7 @@
1735
1635
  color: var(--color-text-default);
1736
1636
  }
1737
1637
 
1738
- ._title_y686q_86 {
1638
+ ._title_6xodo_96 {
1739
1639
  font-size: var(--type-heading-md-size);
1740
1640
  font-weight: var(--font-weight-bold);
1741
1641
  /* The frame's own 1.32, not the token's 1.25 — that value was set from a different
@@ -1746,12 +1646,20 @@
1746
1646
  white-space: nowrap;
1747
1647
  }
1748
1648
 
1749
- ._date_y686q_97 {
1649
+ /*
1650
+ * 10px on 14px text: the date is `text-box-trim: trim-both` with a cap-alphabetic edge, so
1651
+ * Figma's box stops at the cap height. The row's own height depends on it — untrimmed the
1652
+ * card stood 160 against the frame's 156, and every card below it inherited the drift.
1653
+ *
1654
+ * Nothing clips this one, so it needs no descender protection: the comma and a Spanish
1655
+ * "sept" hang below the box and are drawn, as they are in the frame.
1656
+ */
1657
+ ._date_6xodo_115 {
1750
1658
  font-size: var(--type-trimmed-sm-size);
1751
- line-height: 1;
1659
+ line-height: 10px;
1752
1660
  }
1753
1661
 
1754
- ._bottom_y686q_102 {
1662
+ ._bottom_6xodo_120 {
1755
1663
  display: flex;
1756
1664
  align-items: center;
1757
1665
  justify-content: space-between;
@@ -1759,12 +1667,12 @@
1759
1667
  width: 100%;
1760
1668
  }
1761
1669
 
1762
- ._strip_y686q_110 {
1670
+ ._strip_6xodo_128 {
1763
1671
  display: flex;
1764
1672
  gap: var(--space-6);
1765
1673
  }
1766
1674
 
1767
- ._tile_y686q_115 {
1675
+ ._tile_6xodo_133 {
1768
1676
  position: relative;
1769
1677
  flex: 0 0 56px;
1770
1678
  width: 56px;
@@ -1774,18 +1682,18 @@
1774
1682
  background: var(--color-surface-subtle);
1775
1683
  }
1776
1684
 
1777
- ._image_y686q_125 {
1685
+ ._image_6xodo_143 {
1778
1686
  object-fit: cover;
1779
1687
  }
1780
1688
 
1781
- ._placeholder_y686q_129 {
1689
+ ._placeholder_6xodo_147 {
1782
1690
  /* No picture resolved for any line. A flat tile keeps the row's rhythm rather than
1783
1691
  collapsing the strip and shifting the chevron. */
1784
1692
  background: var(--color-surface-subtle);
1785
1693
  }
1786
1694
 
1787
1695
  /* The "+N" tile: the last thumbnail, dimmed, with the count over it. */
1788
- ._more_y686q_136 {
1696
+ ._more_6xodo_154 {
1789
1697
  position: absolute;
1790
1698
  inset: 0;
1791
1699
  display: flex;
@@ -1798,24 +1706,28 @@
1798
1706
  line-height: 1;
1799
1707
  }
1800
1708
 
1801
- ._chevron_y686q_149 {
1709
+ ._chevron_6xodo_167 {
1802
1710
  display: inline-flex;
1803
1711
  flex: 0 0 24px;
1804
1712
  width: 24px;
1805
1713
  height: 24px;
1806
1714
  color: var(--color-text-default);
1807
1715
  }
1808
- /* 8 where Figma declares 12, for the reason set out on `.titlePrice` below: the gap sits
1809
- against a text layer whose CSS line box carries leading that Figma's does not. */
1810
- ._tile_1u9l8_3 {
1716
+ /*
1717
+ * The frame's own 12, now that the text below it is trimmed to its cap height like the
1718
+ * frame's. This was 8 — half the declared number — which put the glyphs in the right place
1719
+ * and left the card 11px taller than the frame, because the compensation was in the gap
1720
+ * rather than in the box that was wrong. See `.title`.
1721
+ */
1722
+ ._tile_1eiri_7 {
1811
1723
  display: flex;
1812
1724
  flex-direction: column;
1813
- gap: var(--space-8);
1725
+ gap: var(--space-12);
1814
1726
  text-decoration: none;
1815
1727
  color: inherit;
1816
1728
  }
1817
1729
 
1818
- ._media_1u9l8_11 {
1730
+ ._media_1eiri_15 {
1819
1731
  position: relative;
1820
1732
  width: 100%;
1821
1733
  /* Product-card image is 165:220 (3:4), radius-6 (Figma), sharp not pill-round. */
@@ -1825,11 +1737,11 @@
1825
1737
  background: var(--color-surface-soft);
1826
1738
  }
1827
1739
 
1828
- ._image_1u9l8_21 {
1740
+ ._image_1eiri_25 {
1829
1741
  object-fit: cover;
1830
1742
  }
1831
1743
 
1832
- ._placeholder_1u9l8_25 {
1744
+ ._placeholder_1eiri_29 {
1833
1745
  width: 100%;
1834
1746
  height: 100%;
1835
1747
  background: var(--color-surface-soft);
@@ -1837,7 +1749,7 @@
1837
1749
 
1838
1750
  /* TOP PICK flag — top-left over the image, white surface, radius-2, uppercase. Fixed
1839
1751
  colours (not theme tokens): it always sits over a light product image. */
1840
- ._topBadge_1u9l8_33 {
1752
+ ._topBadge_1eiri_37 {
1841
1753
  position: absolute;
1842
1754
  top: var(--space-8);
1843
1755
  left: var(--space-8);
@@ -1860,14 +1772,14 @@
1860
1772
  white-space: nowrap;
1861
1773
  }
1862
1774
 
1863
- ._saleBadge_1u9l8_56 {
1775
+ ._saleBadge_1eiri_60 {
1864
1776
  position: absolute;
1865
1777
  bottom: var(--space-8);
1866
1778
  left: var(--space-8);
1867
1779
  }
1868
1780
 
1869
1781
  /* Scrim over the whole image, not a corner flag (Figma out-of-stock state). */
1870
- ._oos_1u9l8_63 {
1782
+ ._oos_1eiri_67 {
1871
1783
  position: absolute;
1872
1784
  inset: 0;
1873
1785
  display: flex;
@@ -1881,32 +1793,57 @@
1881
1793
  }
1882
1794
 
1883
1795
  /*
1884
- * 8, where Figma declares 16 — and this is not a drift, so please do not "correct" it.
1796
+ * Figma's own 16, both here and on `.titlePrice`.
1885
1797
  *
1886
- * Every text layer in this card is `text-box-trim: trim-both` with a cap-alphabetic edge:
1887
- * Figma's boxes stop at the cap height and the baseline, so its 16 is 16 of visible white.
1888
- * A CSS line box carries the font's leading above and below the glyphs, so the same 16
1889
- * renders as 23 measured off both, title glyph bottom to price glyph top: Figma 15, ours
1890
- * 23. Halving the declared gap puts ours at 15.
1798
+ * These were 8 half the declared number and the halving was right about the cause and
1799
+ * wrong about the cure. Every text layer in this card is `text-box-trim: trim-both` with a
1800
+ * cap-alphabetic edge, so Figma's boxes stop at the cap height and its 16 is 16 of visible
1801
+ * white, where a CSS line box carries the font's leading and renders the same 16 as 23.
1802
+ * Halving the gap put the glyphs in the right place and left the BOX 11px too tall, which
1803
+ * is invisible on one card and is the whole page by the bottom of the PCP: measured at
1804
+ * 375, ours ran 3776 against the frame's 3384.
1891
1805
  *
1892
- * `text-box-trim` would let us write the design's own number, and it is Chrome 133+ only.
1893
- * This package still supports the WebView that ships with React 16-era DAZN builds.
1806
+ * The trim now lives on the text, as it does on the order screens, so the gaps can be the
1807
+ * design's own numbers again.
1894
1808
  */
1895
- ._bottom_1u9l8_88 {
1809
+ ._bottom_1eiri_94 {
1896
1810
  display: flex;
1897
1811
  flex-direction: column;
1898
- gap: var(--space-8);
1812
+ gap: var(--space-16);
1899
1813
  }
1900
1814
 
1901
- ._titlePrice_1u9l8_1 {
1815
+ ._titlePrice_1eiri_81 {
1902
1816
  display: flex;
1903
1817
  flex-direction: column;
1904
- gap: var(--space-8);
1818
+ gap: var(--space-16);
1905
1819
  }
1906
1820
 
1907
- ._title_1u9l8_1 {
1821
+ /*
1822
+ * Trimmed to the cap height, in the only way that also keeps the leading BETWEEN two
1823
+ * lines: `line-height` carries the design's line-to-line distance (11 of cap + 10 of
1824
+ * leading = 21), and the padding/negative-margin pair takes the outer half-leading back
1825
+ * out of the layout. The frame's two-line name box is 32 — 11 + 10 + 11 — and so is this.
1826
+ *
1827
+ * The padding is not decoration: `-webkit-line-clamp` needs `overflow: hidden`, which
1828
+ * clips in both directions, and an 11px box beheads every descender — the `p` in
1829
+ * "Zip-Up", the `y` in "Everyday". The padding gives them room inside the clip box and
1830
+ * the margin removes it from the layout.
1831
+ *
1832
+ * `text-box-trim` would let us write the design's numbers directly; it is Chrome 133+ and
1833
+ * this package still supports the WebView that ships with React 16-era DAZN builds.
1834
+ */
1835
+ ._title_1eiri_5 {
1908
1836
  font-size: var(--type-paragraph-size);
1909
- line-height: 1.3;
1837
+ line-height: 21px;
1838
+ padding: 5px 0;
1839
+ /*
1840
+ * Ten, not five: the margin has two jobs. Five cancels the padding above, which exists
1841
+ * only to keep the clip box off the descenders; the other five is the half-leading the
1842
+ * trim removes — (21 - 11) / 2 — above the first line and below the last. A single
1843
+ * two-line name is then 32 in the layout and 52 on screen, which is where the padding
1844
+ * went.
1845
+ */
1846
+ margin: -10px 0;
1910
1847
  font-weight: var(--font-weight-regular);
1911
1848
  color: var(--color-text-default);
1912
1849
  display: -webkit-box;
@@ -1917,30 +1854,46 @@
1917
1854
  /* Reserve both lines rather than only capping at two. The clamp stops a long title
1918
1855
  overflowing but lets a short one collapse to one line, and in a two-column grid that
1919
1856
  pulls its price up level with the neighbour's title — a ragged price baseline across
1920
- the row, which reads as broken alignment rather than as varying title lengths. */
1921
- min-height: calc(2 * 1.3em);
1857
+ the row, which reads as broken alignment rather than as varying title lengths.
1858
+ Two line boxes, which the margins above bring back to the frame's 32. */
1859
+ min-height: calc(2 * 21px + 10px);
1860
+ }
1861
+
1862
+ /*
1863
+ * The price row, trimmed to its own cap: 11 on 16px, which is what makes the card's text
1864
+ * block 32 + 16 + 11 = 59, as the frame draws it.
1865
+ *
1866
+ * Scoped here rather than set on `PriceBlock` itself, which the PDP also renders — its
1867
+ * row is measured against a different frame and must not move with this one.
1868
+ */
1869
+ ._titlePrice_1eiri_81 > :last-child {
1870
+ line-height: 11px;
1922
1871
  }
1923
1872
 
1924
1873
  /* Colour swatches (Figma product-card): 0.5px-bordered boxes with a 14px colour square;
1925
1874
  the first reads as selected (dark border). */
1926
- ._swatches_1u9l8_119 {
1875
+ ._swatches_1eiri_160 {
1927
1876
  display: flex;
1928
1877
  gap: var(--space-4);
1929
1878
  align-items: center;
1930
1879
  }
1931
1880
 
1932
- ._swatch_1u9l8_119 {
1881
+ /*
1882
+ * 18 on the nose: 14 of colour with 2 either side, and the outline drawn INSIDE that,
1883
+ * which is where Figma draws a stroke. As a `border` it sat outside and made the box 19.
1884
+ */
1885
+ ._swatch_1eiri_160 {
1933
1886
  display: inline-flex;
1934
1887
  padding: 2px;
1935
- border: 0.5px solid var(--color-border-subtle);
1888
+ box-shadow: inset 0 0 0 0.5px var(--color-border-subtle);
1936
1889
  border-radius: var(--radius-2);
1937
1890
  }
1938
1891
 
1939
- ._swatchActive_1u9l8_132 {
1940
- border-color: var(--color-surface-max);
1892
+ ._swatchActive_1eiri_177 {
1893
+ box-shadow: inset 0 0 0 0.5px var(--color-surface-max);
1941
1894
  }
1942
1895
 
1943
- ._swatchDot_1u9l8_136 {
1896
+ ._swatchDot_1eiri_181 {
1944
1897
  display: block;
1945
1898
  width: 14px;
1946
1899
  height: 14px;
@@ -1951,23 +1904,185 @@
1951
1904
  * Spotlight card (Figma `size=large`, 3668:12485). Full-bleed with its own 16px gutter —
1952
1905
  * the block that places it adds none — a taller 343:457 image and an 18px title.
1953
1906
  */
1954
- ._large_1u9l8_147 {
1907
+ ._large_1eiri_192 {
1955
1908
  padding: 0 var(--space-16);
1956
1909
  }
1957
1910
 
1958
- ._large_1u9l8_147 ._media_1u9l8_11 {
1959
- aspect-ratio: 343 / 457;
1911
+ ._large_1eiri_192 ._media_1eiri_15 {
1912
+ aspect-ratio: 343 / 457;
1913
+ }
1914
+
1915
+ /*
1916
+ * No two-line reservation here. It exists so that neighbouring cards in a grid or rail
1917
+ * keep their prices on one baseline, and the spotlight card is alone on its row — there is
1918
+ * nothing to line up with, so all it reserves is empty space under a one-line title.
1919
+ * Figma's note on this variant is "height hugs".
1920
+ *
1921
+ * 23 = the cap of 18px text (13) plus the same 10 of leading, so the margins above leave a
1922
+ * one-line name 13 tall — the frame's number for this variant.
1923
+ */
1924
+ ._large_1eiri_192 ._title_1eiri_5 {
1925
+ font-size: 18px;
1926
+ line-height: 23px;
1927
+ min-height: 0;
1928
+ }
1929
+
1930
+ /*
1931
+ * The colours row is the spotlight card's alone.
1932
+ *
1933
+ * `mobile/product-card` carries one in every variant and **hides it on the small card**:
1934
+ * the rail's instances and the grid's all draw the frame `hidden`, and only the 375-wide
1935
+ * spotlight shows two swatches under its price. Drawn on a 165px card it also cost 34 of
1936
+ * the 291 the card is given, which is why the rail ran 55 long before this.
1937
+ */
1938
+ ._tile_1eiri_7:not(._large_1eiri_192) ._swatches_1eiri_160 {
1939
+ display: none;
1940
+ }
1941
+ /*
1942
+ * Figma `mobile/limited edition` (5304:77067), 360 tall at 375:
1943
+ * 24 above the heading, 28 of heading, 12, a 220 row, 12, a 40 caption, 24 below.
1944
+ */
1945
+ ._section_1fdjh_5 {
1946
+ display: flex;
1947
+ flex-direction: column;
1948
+ gap: var(--space-12);
1949
+ padding: var(--space-24) 0;
1950
+ }
1951
+
1952
+ /*
1953
+ * `heading/md` at 1.38, which is the rail's own heading rule — the two blocks instance the
1954
+ * same 206x28 `header` frame, so they have to measure the same. (`ExploreList`'s heading
1955
+ * is the same 20px face in a 26 box; the frames differ, and each follows its own.)
1956
+ */
1957
+ ._title_1fdjh_17 {
1958
+ margin: 0;
1959
+ padding: 0 var(--space-16);
1960
+ font-size: var(--type-heading-md-size);
1961
+ line-height: 1.38;
1962
+ font-weight: var(--font-weight-bold);
1963
+ color: var(--color-text-default);
1964
+ }
1965
+
1966
+ ._link_1fdjh_26 {
1967
+ display: flex;
1968
+ flex-direction: column;
1969
+ gap: var(--space-12);
1970
+ text-decoration: none;
1971
+ color: inherit;
1972
+ }
1973
+
1974
+ /*
1975
+ * The row scrolls, and the third picture peeks past the fold exactly as the frame draws
1976
+ * it: two 165s and a 12 gutter fill the 343 content width, and the next one starts at 354.
1977
+ */
1978
+ ._track_1fdjh_38 {
1979
+ display: flex;
1980
+ gap: var(--space-12);
1981
+ list-style: none;
1982
+ margin: 0;
1983
+ padding: 0 var(--space-16);
1984
+ overflow-x: auto;
1985
+ scroll-snap-type: x mandatory;
1986
+ /* Keeps the 16px inset under mandatory snap: without it the first frame snaps to x=0
1987
+ and the padding is scrolled away, so the row stops lining up with its heading. */
1988
+ scroll-padding-inline: var(--space-16);
1989
+ -webkit-overflow-scrolling: touch;
1990
+ /* The row is its own indicator — a native scrollbar under it is not in the frame. */
1991
+ scrollbar-width: none;
1992
+ }
1993
+
1994
+ ._track_1fdjh_38::-webkit-scrollbar {
1995
+ display: none;
1996
+ }
1997
+
1998
+ ._frame_1fdjh_58 {
1999
+ position: relative;
2000
+ flex: 0 0 auto;
2001
+ width: 165px;
2002
+ height: 220px;
2003
+ border-radius: var(--radius-6);
2004
+ overflow: hidden;
2005
+ background: var(--color-surface-soft);
2006
+ scroll-snap-align: start;
2007
+ }
2008
+
2009
+ ._image_1fdjh_69 {
2010
+ object-fit: cover;
2011
+ }
2012
+
2013
+ ._placeholder_1fdjh_73 {
2014
+ width: 100%;
2015
+ height: 100%;
2016
+ }
2017
+
2018
+ ._saleBadge_1fdjh_78 {
2019
+ position: absolute;
2020
+ bottom: var(--space-8);
2021
+ left: var(--space-8);
2022
+ }
2023
+
2024
+ /* The whole picture dims, as it does on a product card — not a corner flag. */
2025
+ ._oos_1fdjh_85 {
2026
+ position: absolute;
2027
+ inset: 0;
2028
+ display: flex;
2029
+ align-items: center;
2030
+ justify-content: center;
2031
+ background: rgba(0, 0, 0, 0.45);
2032
+ color: #ffffff;
2033
+ font-size: var(--type-trimmed-sm-size);
2034
+ font-weight: var(--font-weight-bold);
2035
+ }
2036
+
2037
+ /*
2038
+ * One caption for the row: the frame's `bottom` is 40 — a 13px name, 16, an 11px price —
2039
+ * because the pictures above it are all the same garment.
2040
+ */
2041
+ ._caption_1fdjh_101 {
2042
+ display: flex;
2043
+ flex-direction: column;
2044
+ gap: var(--space-16);
2045
+ padding: 0 var(--space-16);
2046
+ }
2047
+
2048
+ /*
2049
+ * Trimmed to the cap, as every text layer in this block is: 23 carries the design's
2050
+ * leading over an 18px face, the padding keeps the ellipsis off the descenders, and the
2051
+ * margin takes back both that padding and the half-leading the trim removes. The frame's
2052
+ * name box is 13.
2053
+ */
2054
+ ._name_1fdjh_114 {
2055
+ font-size: 18px;
2056
+ line-height: 23px;
2057
+ padding: 5px 0;
2058
+ margin: -10px 0;
2059
+ font-weight: var(--font-weight-regular);
2060
+ color: var(--color-text-default);
2061
+ overflow: hidden;
2062
+ text-overflow: ellipsis;
2063
+ white-space: nowrap;
2064
+ }
2065
+
2066
+ /* 11 on 16px, the same cap the product card's price row takes. */
2067
+ ._price_1fdjh_127 {
2068
+ display: flex;
2069
+ align-items: baseline;
2070
+ gap: var(--space-4);
2071
+ font-size: var(--type-trimmed-md-size);
2072
+ line-height: 11px;
2073
+ font-variant-numeric: tabular-nums;
2074
+ }
2075
+
2076
+ ._paid_1fdjh_136 {
2077
+ font-weight: var(--font-weight-bold);
2078
+ color: var(--color-text-default);
1960
2079
  }
1961
2080
 
1962
- /*
1963
- * No two-line reservation here. It exists so that neighbouring cards in a grid or rail
1964
- * keep their prices on one baseline, and the spotlight card is alone on its row — there is
1965
- * nothing to line up with, so all it reserves is empty space under a one-line title.
1966
- * Figma's note on this variant is "height hugs".
1967
- */
1968
- ._large_1u9l8_147 ._title_1u9l8_1 {
1969
- font-size: 18px;
1970
- min-height: 0;
2081
+ /* Struck, and at the same weight as the live price — `mobile/product-card` again. */
2082
+ ._was_1fdjh_142 {
2083
+ font-weight: var(--font-weight-bold);
2084
+ color: var(--color-text-disabled);
2085
+ text-decoration: line-through;
1971
2086
  }
1972
2087
  ._bar_fn0g9_1 {
1973
2088
  display: flex;
@@ -2030,33 +2145,38 @@
2030
2145
  gap: var(--space-16);
2031
2146
  }
2032
2147
  /* The block owns its vertical rhythm (Figma padding 24/16) — the page stacks blocks flush. */
2033
- ._rail_5z5e9_2 {
2148
+ /*
2149
+ * 24 above and 16 below, where the frame says 24 and 24 — because the track below carries
2150
+ * 8 of its own so a focused card's ring is not clipped by its scroller. 24 + 28 + 12 +
2151
+ * 291 + 8 + 16 is the frame's 379; leaving both at 24 made the block 387.
2152
+ */
2153
+ ._rail_11l7h_7 {
2034
2154
  display: flex;
2035
2155
  flex-direction: column;
2036
2156
  gap: var(--space-12);
2037
- padding: var(--space-24) 0;
2157
+ padding: var(--space-24) 0 var(--space-16);
2038
2158
  }
2039
2159
 
2040
- ._header_5z5e9_9 {
2160
+ ._header_11l7h_14 {
2041
2161
  display: flex;
2042
2162
  align-items: baseline;
2043
2163
  justify-content: space-between;
2044
2164
  padding: 0 var(--space-16);
2045
2165
  }
2046
2166
 
2047
- ._title_5z5e9_16 {
2167
+ ._title_11l7h_21 {
2048
2168
  font-size: var(--type-heading-md-size);
2049
2169
  /* Figma rail header: 20px, line-height 1.38. */
2050
2170
  line-height: 1.38;
2051
2171
  }
2052
2172
 
2053
- ._seeAll_5z5e9_22 {
2173
+ ._seeAll_11l7h_27 {
2054
2174
  font-size: var(--type-trimmed-sm-size);
2055
2175
  color: var(--color-text-subtle);
2056
2176
  text-decoration: none;
2057
2177
  }
2058
2178
 
2059
- ._track_5z5e9_28 {
2179
+ ._track_11l7h_33 {
2060
2180
  display: flex;
2061
2181
  gap: var(--space-12);
2062
2182
  list-style: none;
@@ -2073,7 +2193,7 @@
2073
2193
 
2074
2194
  /* Fixed 165px, as the card is drawn. At 375 two fit the 343 content width and the third
2075
2195
  peeks, which is the signal the design asks for. */
2076
- ._item_5z5e9_45 {
2196
+ ._item_11l7h_50 {
2077
2197
  flex: 0 0 auto;
2078
2198
  width: 165px;
2079
2199
  scroll-snap-align: start;
@@ -2085,11 +2205,11 @@
2085
2205
  * parent supplies the 16px inset, so the header/track add none of their own, and tiles
2086
2206
  * size to show exactly two across the content width (per the PDP design: rail x16 w343).
2087
2207
  */
2088
- ._inset_5z5e9_57 ._header_5z5e9_9 {
2208
+ ._inset_11l7h_62 ._header_11l7h_14 {
2089
2209
  padding: 0;
2090
2210
  }
2091
2211
 
2092
- ._inset_5z5e9_57 ._track_5z5e9_28 {
2212
+ ._inset_11l7h_62 ._track_11l7h_33 {
2093
2213
  padding-left: 0;
2094
2214
  padding-right: 0;
2095
2215
  scroll-padding-inline: 0;
@@ -2100,11 +2220,11 @@
2100
2220
  * can sit between flush blocks on the home screen; the PDP content column already spaces
2101
2221
  * its blocks 32px apart, so keeping it here made the gap above the rail 56px.
2102
2222
  */
2103
- ._inset_5z5e9_57 {
2223
+ ._inset_11l7h_62 {
2104
2224
  padding: 0;
2105
2225
  }
2106
2226
 
2107
- ._inset_5z5e9_57 ._item_5z5e9_45 {
2227
+ ._inset_11l7h_62 ._item_11l7h_50 {
2108
2228
  /* Fixed 165px cards (Figma product-card size=default). At 375 two fit the 343 content
2109
2229
  width exactly; more scroll horizontally. */
2110
2230
  width: 165px;
@@ -2643,121 +2763,433 @@
2643
2763
  background: var(--color-surface-max);
2644
2764
  }
2645
2765
  /*
2646
- * Size-guide bottom sheet. Uses the same scrim + rounded-top surface as the other PDP
2647
- * overlays so it reads as one system. Fixed light surface: the PDP is light in every
2648
- * theme, and an inverted sheet over a light page would be jarring.
2766
+ * Figma `size-guide` (4882:58365): a bottom sheet over the PDP a 48 `.sheet-header`,
2767
+ * then `mobile/size-guide`, which is 806 tall at 375 for the hoodie chart.
2768
+ *
2769
+ * The body's blocks are all 20 apart: title, unit control, table, note, "How to measure",
2770
+ * fabric. Everything below is that rhythm and the geometry inside each block.
2649
2771
  */
2650
- ._scrim_8wz6r_6 {
2772
+ ._scrim_v44fk_8 {
2651
2773
  position: fixed;
2652
2774
  inset: 0;
2653
2775
  z-index: 60;
2654
2776
  display: flex;
2655
2777
  align-items: flex-end;
2656
2778
  justify-content: center;
2657
- background: rgba(8, 14, 18, 0.5);
2658
- animation: _fade_8wz6r_1 160ms ease-out;
2779
+ /* `semantic/base/surface/backdrop` #0c161c at 32%, which is lighter than the 50% the
2780
+ cart and menu sheets are drawn over. Theirs are literals of the same intent written
2781
+ before the variable was published; this one follows the variable. */
2782
+ background: rgba(12, 22, 28, 0.32);
2783
+ animation: _fade_v44fk_1 160ms ease-out;
2659
2784
  }
2660
2785
 
2661
- ._sheet_8wz6r_17 {
2786
+ ._sheet_v44fk_2 {
2787
+ display: flex;
2788
+ flex-direction: column;
2662
2789
  width: 100%;
2663
2790
  max-width: 480px;
2664
- max-height: 80vh;
2665
- overflow-y: auto;
2666
- padding: var(--space-8) var(--space-16) var(--space-24);
2667
- border-radius: var(--radius-18) var(--radius-18) 0 0;
2791
+ max-height: 90dvh;
2792
+ /* Clips the body's scroll to the rounded corners, so a chart scrolled to the top does
2793
+ not square them off. */
2794
+ overflow: hidden;
2795
+ /* 16, and a literal because the design draws one: the library's radii here are `full`
2796
+ and `xs`, and this corner is neither. */
2797
+ border-radius: 16px 16px 0 0;
2668
2798
  background: #ffffff;
2669
- color: #16181a;
2670
- animation: _rise_8wz6r_1 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
2799
+ animation: _rise_v44fk_1 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
2671
2800
  }
2672
2801
 
2673
- ._grabber_8wz6r_29 {
2674
- width: 40px;
2802
+ /* ── .sheet-header ─────────────────────────────────────────────────────────── */
2803
+
2804
+ /* Three slots, so the handle is centred on the sheet rather than on what is left of it
2805
+ once the close control has taken its 48. */
2806
+ ._header_v44fk_42 {
2807
+ display: flex;
2808
+ align-items: flex-start;
2809
+ justify-content: space-between;
2810
+ }
2811
+
2812
+ ._slot_v44fk_48 {
2813
+ flex-shrink: 0;
2814
+ width: 48px;
2815
+ height: 48px;
2816
+ }
2817
+
2818
+ /* `self-stretch` with 12 of padding: the handle sits 12 from the top of the 48, not
2819
+ centred in it. */
2820
+ ._handleSlot_v44fk_56 {
2821
+ align-self: stretch;
2822
+ padding: var(--space-12);
2823
+ }
2824
+
2825
+ ._handle_v44fk_56 {
2826
+ width: 44px;
2675
2827
  height: 4px;
2676
- margin: 0 auto var(--space-12);
2677
- border-radius: 2px;
2678
- background: #d8dcde;
2828
+ border-radius: var(--radius-full);
2829
+ /* `semantic/base/surface/bold`. */
2830
+ background: #6d7377;
2679
2831
  }
2680
2832
 
2681
- ._header_8wz6r_37 {
2682
- display: flex;
2833
+ ._closeSlot_v44fk_69 {
2834
+ display: inline-flex;
2683
2835
  align-items: center;
2684
- justify-content: space-between;
2685
- gap: var(--space-12);
2686
- margin-bottom: var(--space-16);
2836
+ justify-content: center;
2837
+ flex-shrink: 0;
2838
+ width: 48px;
2839
+ height: 48px;
2840
+ padding: var(--space-12);
2841
+ border: 0;
2842
+ background: none;
2843
+ color: var(--color-text-default);
2844
+ cursor: pointer;
2845
+ }
2846
+
2847
+ /* `across-platform/icon-button`, fill: a 24 disc around the 16px cross box. */
2848
+ ._close_v44fk_69 {
2849
+ display: inline-flex;
2850
+ align-items: center;
2851
+ justify-content: center;
2852
+ width: 24px;
2853
+ height: 24px;
2854
+ border-radius: var(--radius-full);
2855
+ background: var(--color-surface-neutral);
2856
+ }
2857
+
2858
+ /* ── Body ──────────────────────────────────────────────────────────────────── */
2859
+
2860
+ ._body_v44fk_96 {
2861
+ flex: 1 1 auto;
2862
+ overflow-y: auto;
2863
+ display: flex;
2864
+ flex-direction: column;
2865
+ gap: var(--space-20);
2866
+ padding: 0 var(--space-16) calc(var(--space-24) + var(--safe-area-bottom));
2867
+ background: var(--color-surface-default);
2687
2868
  }
2688
2869
 
2689
- ._title_8wz6r_45 {
2870
+ /*
2871
+ * A long guide is taller than 90dvh and the body scrolls — but a column flex container
2872
+ * shrinks its items to fit before it will overflow, so every block lost a share of the
2873
+ * excess and the chart came out 14 short of the 256 the design draws. The body scrolls;
2874
+ * its blocks keep their size.
2875
+ */
2876
+ ._body_v44fk_96 > * {
2877
+ flex-shrink: 0;
2878
+ }
2879
+
2880
+ ._titles_v44fk_116 {
2881
+ display: flex;
2882
+ flex-direction: column;
2883
+ gap: var(--space-2);
2884
+ }
2885
+
2886
+ /* `heading/md` at 1.32 — the library's 1.32, not our `--type-heading-md-line`, which is
2887
+ 1.25 and is the base h2 default the whole package inherits. */
2888
+ ._title_v44fk_116 {
2690
2889
  margin: 0;
2691
- font-size: var(--type-heading-sm-size, 20px);
2890
+ font-size: var(--type-heading-md-size);
2891
+ line-height: 1.32;
2692
2892
  font-weight: var(--font-weight-bold);
2893
+ color: var(--color-text-default);
2894
+ }
2895
+
2896
+ ._subtitle_v44fk_132 {
2897
+ margin: 0;
2898
+ font-size: var(--type-caption-sm-size);
2899
+ line-height: var(--type-caption-sm-line);
2900
+ color: var(--color-text-subtle);
2901
+ }
2902
+
2903
+ /* ── cm / inches ───────────────────────────────────────────────────────────── */
2904
+
2905
+ /*
2906
+ * `Segmented Control` (4882:56556): 190 x 40, a 9 radius the scale does not carry, and 4
2907
+ * of horizontal padding around two halves.
2908
+ */
2909
+ ._units_v44fk_145 {
2910
+ display: flex;
2911
+ align-items: center;
2912
+ width: 190px;
2913
+ height: 40px;
2914
+ padding: var(--space-2) var(--space-4);
2915
+ border-radius: 9px;
2916
+ background: var(--color-surface-soft);
2693
2917
  }
2694
2918
 
2695
- ._close_8wz6r_51 {
2919
+ /*
2920
+ * 10 on 14px text: `text-box-trim: trim-both`, cap-alphabetic. The pill's height is fixed
2921
+ * and its content centred, so the trim is what decides whether the CAP box or the line box
2922
+ * is the thing being centred — and the design centres the cap.
2923
+ */
2924
+ ._unit_v44fk_145 {
2925
+ flex: 1 1 0;
2696
2926
  display: inline-flex;
2697
2927
  align-items: center;
2698
2928
  justify-content: center;
2699
- width: 32px;
2700
- height: 32px;
2701
- flex-shrink: 0;
2702
- border: none;
2703
- border-radius: 50%;
2704
- background: #f2f4f5;
2705
- color: #16181a;
2929
+ height: 36px;
2930
+ padding: 0 var(--space-8);
2931
+ border: 0;
2932
+ border-radius: var(--radius-6);
2933
+ background: none;
2934
+ color: var(--color-text-default);
2935
+ font-family: inherit;
2936
+ font-size: var(--type-trimmed-sm-size);
2937
+ line-height: 10px;
2706
2938
  cursor: pointer;
2707
2939
  }
2708
- ._close_8wz6r_51:focus-visible {
2709
- outline: 2px solid #16181a;
2710
- outline-offset: 2px;
2940
+
2941
+ /* Four shorter than its neighbour, and that is the component rather than a slip: the
2942
+ selected half carries its own 2 of vertical padding inside the track's 36. */
2943
+ ._unitOn_v44fk_179 {
2944
+ height: 32px;
2945
+ background: var(--color-surface-neutral);
2946
+ font-weight: var(--font-weight-bold);
2947
+ }
2948
+
2949
+ /* A half-pixel hairline drawn INSIDE the pill, as every Figma stroke is — hence `inset`
2950
+ rather than a border, which CSS would draw around it and make the pill 37 tall. */
2951
+ ._unitOff_v44fk_187 {
2952
+ box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, 0.04);
2953
+ font-weight: var(--font-weight-regular);
2711
2954
  }
2712
2955
 
2713
- /* The chart can be wider than the sheet, so it scrolls inside its own container
2714
- rather than making the sheet scroll sideways. */
2715
- ._tableWrap_8wz6r_71 {
2956
+ /* ── The chart ─────────────────────────────────────────────────────────────── */
2957
+
2958
+ /* Wider than the sheet on a narrow phone or a long chart, so it scrolls inside its own
2959
+ container rather than making the sheet scroll sideways. */
2960
+ ._tableWrap_v44fk_196 {
2716
2961
  overflow-x: auto;
2717
- margin-bottom: var(--space-16);
2718
2962
  }
2719
2963
 
2720
- ._table_8wz6r_71 {
2964
+ ._table_v44fk_196 {
2721
2965
  width: 100%;
2722
- border-collapse: collapse;
2723
- font-size: var(--type-trimmed-sm-size, 14px);
2966
+ /* `separate` with no spacing, not `collapse`: collapsed borders cannot carry the
2967
+ header's rounded top corners. */
2968
+ border-collapse: separate;
2969
+ border-spacing: 0;
2970
+ table-layout: fixed;
2724
2971
  }
2725
2972
 
2726
- ._table_8wz6r_71 th,
2727
- ._table_8wz6r_71 td {
2728
- padding: var(--space-8) var(--space-12);
2973
+ /*
2974
+ * The frame's five columns are equal at 63.8 across 343, and the table's 12 of inset lives
2975
+ * INSIDE the first and last of them (75.8 = 63.8 + 12). Declared on the columns rather
2976
+ * than as padding on every cell so that the centred headings land where the design puts
2977
+ * them: as cell padding, the last column's centre drifts 4 left.
2978
+ *
2979
+ * Two mutually exclusive classes rather than a `col` rule plus an override for the edges.
2980
+ * `.table col` is specificity (0,1,1) and a module class is (0,1,0), so the descendant
2981
+ * selector won wherever the two met and every column came out 18.6006% — which sums to
2982
+ * 93%, and Chrome scaled all five back up to an equal fifth. Same trap `ShopSurface`
2983
+ * documents on its base headings.
2984
+ */
2985
+ ._col_v44fk_221 {
2986
+ width: 18.6006%;
2987
+ }
2988
+
2989
+ ._colEdge_v44fk_225 {
2990
+ width: 22.0991%;
2991
+ }
2992
+
2993
+ /*
2994
+ * 12 bold with the library's 1% tracking, cap-trimmed to 9 in a 36 row. `#f5f5f5` and
2995
+ * `#6b6b6b` are literals because the designer drew them as literals — there is no library
2996
+ * variable behind either, and `border/soft` and `text/subtle` are visibly different
2997
+ * greys.
2998
+ */
2999
+ ._table_v44fk_196 thead th {
3000
+ height: 36px;
3001
+ padding: 0;
3002
+ background: #f5f5f5;
3003
+ color: #6b6b6b;
3004
+ font-size: var(--type-trimmed-xs-size);
3005
+ line-height: 9px;
3006
+ font-weight: var(--font-weight-bold);
3007
+ letter-spacing: 0.12px;
3008
+ text-align: center;
3009
+ }
3010
+
3011
+ ._table_v44fk_196 thead th:first-child {
3012
+ padding-left: var(--space-12);
3013
+ border-top-left-radius: var(--radius-8);
2729
3014
  text-align: left;
2730
- border-bottom: 1px solid #e2e6e8;
2731
- white-space: nowrap;
2732
3015
  }
2733
3016
 
2734
- ._table_8wz6r_71 thead th {
3017
+ ._table_v44fk_196 thead th:last-child {
3018
+ padding-right: var(--space-12);
3019
+ border-top-right-radius: var(--radius-8);
3020
+ }
3021
+
3022
+ /* 13px, which is not on the type scale — the design uses a detached style here rather
3023
+ than a token, and 12 or 14 both miss the row. */
3024
+ ._table_v44fk_196 tbody th,
3025
+ ._table_v44fk_196 tbody td {
3026
+ height: 44px;
3027
+ padding: 0;
3028
+ border-bottom: 1px solid var(--color-surface-soft);
3029
+ color: #0d0d0d;
3030
+ font-size: 13px;
3031
+ line-height: 17px;
3032
+ font-weight: var(--font-weight-regular);
3033
+ text-align: center;
3034
+ }
3035
+
3036
+ ._table_v44fk_196 tbody th {
3037
+ padding-left: var(--space-12);
3038
+ font-weight: var(--font-weight-bold);
3039
+ text-align: left;
3040
+ }
3041
+
3042
+ ._table_v44fk_196 tbody td:last-child {
3043
+ padding-right: var(--space-12);
3044
+ }
3045
+
3046
+ /* No rule under the last row: the table would otherwise be underlined, and the note that
3047
+ follows is a separate block with its own ground. */
3048
+ ._table_v44fk_196 tbody tr:last-child th,
3049
+ ._table_v44fk_196 tbody tr:last-child td {
3050
+ border-bottom: 0;
3051
+ }
3052
+
3053
+ /* ── The note under the chart ──────────────────────────────────────────────── */
3054
+
3055
+ /* `caption/xs` — the same 12px face as `trimmed/xs` on a 1.52 leading rather than a
3056
+ trimmed box, which is why the line-height is written out. */
3057
+ ._note_v44fk_293 {
3058
+ margin: 0;
3059
+ padding: var(--space-8) var(--space-12);
3060
+ border-radius: var(--radius-8);
3061
+ background: var(--color-surface-soft);
3062
+ color: var(--color-text-subtle);
3063
+ font-size: var(--type-trimmed-xs-size);
3064
+ line-height: 1.52;
3065
+ }
3066
+
3067
+ /* ── How to measure ────────────────────────────────────────────────────────── */
3068
+
3069
+ ._how_v44fk_305 {
3070
+ display: flex;
3071
+ flex-direction: column;
3072
+ gap: var(--space-16);
3073
+ }
3074
+
3075
+ ._howTitle_v44fk_311 {
3076
+ margin: 0;
3077
+ font-size: var(--type-heading-sm-size);
3078
+ line-height: var(--type-heading-sm-line);
3079
+ font-weight: var(--font-weight-bold);
3080
+ color: #0d0d0d;
3081
+ }
3082
+
3083
+ ._howList_v44fk_319 {
3084
+ margin: 0;
3085
+ display: flex;
3086
+ flex-direction: column;
3087
+ gap: var(--space-8);
3088
+ }
3089
+
3090
+ ._howItem_v44fk_326 {
3091
+ display: flex;
3092
+ flex-direction: column;
3093
+ gap: var(--space-8);
3094
+ }
3095
+
3096
+ /*
3097
+ * The frame's `Line 9`, between rows and never under the last one.
3098
+ *
3099
+ * A Figma line has no height, so 8 above it and 8 below it means 16 between the rows it
3100
+ * separates with the hairline drawn on that boundary — the negative margin takes the pixel
3101
+ * back out of the layout so the pair stays 16 rather than becoming 17.
3102
+ */
3103
+ ._howItem_v44fk_326 + ._howItem_v44fk_326 {
3104
+ margin-top: -1px;
3105
+ padding-top: var(--space-8);
3106
+ border-top: 1px solid var(--color-surface-soft);
3107
+ }
3108
+
3109
+ /*
3110
+ * Cap-trimmed to 9 on a 12px face. Unlike the table header this box is content-sized, so
3111
+ * the trim has to come off the text itself: the padding keeps the descenders of "Body
3112
+ * length" clear of anything that clips, and the margin takes that padding back out of the
3113
+ * layout so the box measures the 9 the frame gives it.
3114
+ */
3115
+ ._howLabel_v44fk_351 {
3116
+ padding: 5px 0;
3117
+ margin: -5px 0;
3118
+ font-size: var(--type-trimmed-xs-size);
3119
+ line-height: 9px;
3120
+ font-weight: var(--font-weight-bold);
3121
+ letter-spacing: 0.12px;
3122
+ color: #0d0d0d;
3123
+ }
3124
+
3125
+ ._howText_v44fk_361 {
3126
+ margin: 0;
3127
+ font-size: var(--type-trimmed-xs-size);
3128
+ line-height: 1.52;
3129
+ color: #6b6b6b;
3130
+ }
3131
+
3132
+ /* ── Fabric ────────────────────────────────────────────────────────────────── */
3133
+
3134
+ ._fabric_v44fk_370 {
3135
+ display: flex;
3136
+ flex-direction: column;
3137
+ gap: var(--space-2);
3138
+ }
3139
+
3140
+ /* `caption/xs-bold`, not the trimmed style the "How to measure" labels use: the frame's
3141
+ box is 18, which is the full 1.52 line rather than a cap. */
3142
+ ._fabricLabel_v44fk_378 {
3143
+ margin: 0;
3144
+ font-size: var(--type-trimmed-xs-size);
3145
+ line-height: 1.52;
2735
3146
  font-weight: var(--font-weight-bold);
2736
- background: #f7f8f9;
3147
+ color: #0d0d0d;
3148
+ }
3149
+
3150
+ ._fabricText_v44fk_386 {
3151
+ margin: 0;
3152
+ font-size: var(--type-trimmed-xs-size);
3153
+ line-height: 1.52;
3154
+ color: #6b6b6b;
2737
3155
  }
2738
3156
 
2739
- ._notes_8wz6r_95 {
3157
+ /* ── Fit notes ─────────────────────────────────────────────────────────────── */
3158
+
3159
+ /* Not in the frame. Guides carried these before there was a chart to carry instead, and a
3160
+ payload that still has them is still worth drawing. */
3161
+ ._notes_v44fk_397 {
2740
3162
  margin: 0;
2741
3163
  padding-left: var(--space-16);
2742
3164
  display: flex;
2743
3165
  flex-direction: column;
2744
3166
  gap: var(--space-6);
2745
- font-size: var(--type-trimmed-sm-size, 14px);
2746
- color: #4a5257;
3167
+ font-size: var(--type-caption-sm-size);
3168
+ line-height: var(--type-caption-sm-line);
3169
+ color: var(--color-text-subtle);
2747
3170
  }
2748
3171
 
2749
- @keyframes _fade_8wz6r_1 {
2750
- from { opacity: 0; }
2751
- to { opacity: 1; }
3172
+ @keyframes _fade_v44fk_1 {
3173
+ from {
3174
+ opacity: 0;
3175
+ }
3176
+ to {
3177
+ opacity: 1;
3178
+ }
2752
3179
  }
2753
- @keyframes _rise_8wz6r_1 {
2754
- from { transform: translateY(12%); }
2755
- to { transform: translateY(0); }
3180
+
3181
+ @keyframes _rise_v44fk_1 {
3182
+ from {
3183
+ transform: translateY(12%);
3184
+ }
3185
+ to {
3186
+ transform: translateY(0);
3187
+ }
2756
3188
  }
2757
3189
 
2758
3190
  @media (prefers-reduced-motion: reduce) {
2759
- ._scrim_8wz6r_6,
2760
- ._sheet_8wz6r_17 {
3191
+ ._scrim_v44fk_8,
3192
+ ._sheet_v44fk_2 {
2761
3193
  animation: none;
2762
3194
  }
2763
3195
  }
@@ -3407,14 +3839,14 @@
3407
3839
  ._dotActive_9mquf_63 {
3408
3840
  background: #f9fafa;
3409
3841
  }
3410
- ._section_n8xka_1 {
3842
+ ._section_kdf3c_1 {
3411
3843
  display: flex;
3412
3844
  flex-direction: column;
3413
3845
  gap: var(--space-12);
3414
3846
  padding: var(--space-24) 0 var(--space-16);
3415
3847
  }
3416
3848
 
3417
- ._track_n8xka_8 {
3849
+ ._track_kdf3c_8 {
3418
3850
  display: flex;
3419
3851
  gap: var(--space-12);
3420
3852
  list-style: none;
@@ -3429,7 +3861,7 @@
3429
3861
  scrollbar-width: none;
3430
3862
  }
3431
3863
 
3432
- ._track_n8xka_8::-webkit-scrollbar {
3864
+ ._track_kdf3c_8::-webkit-scrollbar {
3433
3865
  display: none;
3434
3866
  }
3435
3867
 
@@ -3444,7 +3876,7 @@
3444
3876
  * is raised with DAZN's designers, and the card flips the moment they retune the token.
3445
3877
  * Everything else on this block follows Figma exactly.
3446
3878
  */
3447
- ._card_n8xka_38 {
3879
+ ._card_kdf3c_38 {
3448
3880
  flex: 0 0 323px;
3449
3881
  max-width: calc(100% - var(--space-20));
3450
3882
  scroll-snap-align: start;
@@ -3456,7 +3888,7 @@
3456
3888
  background: #f9fafa;
3457
3889
  }
3458
3890
 
3459
- ._quote_n8xka_50 {
3891
+ ._quote_kdf3c_50 {
3460
3892
  margin: 0;
3461
3893
  font-size: var(--type-heading-lg-size);
3462
3894
  line-height: 1.2;
@@ -3464,38 +3896,46 @@
3464
3896
  color: #0c161c;
3465
3897
  }
3466
3898
 
3467
- ._author_n8xka_58 {
3899
+ ._author_kdf3c_58 {
3468
3900
  margin: 0;
3469
3901
  font-size: var(--type-trimmed-sm-size);
3470
3902
  color: #3d4549;
3471
3903
  }
3472
3904
 
3473
- ._dots_n8xka_64 {
3905
+ /*
3906
+ * `.slide-dots` is a 32-tall band in the frame, sitting straight under the quotes with no
3907
+ * gap of its own — the dots are centred inside it. Ours was an 8px row 12 below the track,
3908
+ * which put it 12 too close to the quote and 12 too far from the bottom of the block.
3909
+ */
3910
+ ._dots_kdf3c_69 {
3474
3911
  display: flex;
3912
+ align-items: center;
3475
3913
  justify-content: center;
3914
+ height: 32px;
3915
+ margin-top: calc(-1 * var(--space-12));
3476
3916
  gap: var(--space-8);
3477
3917
  }
3478
3918
 
3479
- ._dot_n8xka_64 {
3919
+ ._dot_kdf3c_69 {
3480
3920
  width: 8px;
3481
3921
  height: 8px;
3482
3922
  border-radius: var(--radius-full);
3483
3923
  background: #9ea2a4;
3484
3924
  }
3485
3925
 
3486
- ._dotActive_n8xka_77 {
3926
+ ._dotActive_kdf3c_85 {
3487
3927
  background: #f9fafa;
3488
3928
  }
3489
3929
 
3490
3930
  /* Quiet, but present. Not in the Figma frame — the component's own note makes it
3491
3931
  mandatory, and staff quotes shown as reviews without one is the failure it guards. */
3492
- ._disclaimer_n8xka_83 {
3932
+ ._disclaimer_kdf3c_91 {
3493
3933
  margin: 0;
3494
3934
  padding: 0 var(--space-16);
3495
3935
  font-size: var(--type-trimmed-xs-size);
3496
3936
  color: var(--color-text-subtle);
3497
3937
  }
3498
- ._section_145t0_1 {
3938
+ ._section_1tevp_1 {
3499
3939
  display: flex;
3500
3940
  flex-direction: column;
3501
3941
  gap: var(--space-12);
@@ -3503,7 +3943,7 @@
3503
3943
  }
3504
3944
 
3505
3945
  /* Each benefit is a filled tile, not a bare row (Figma `mobile/why-us`). */
3506
- ._row_145t0_9 {
3946
+ ._row_1tevp_9 {
3507
3947
  display: flex;
3508
3948
  flex-direction: column;
3509
3949
  gap: var(--space-8);
@@ -3512,48 +3952,64 @@
3512
3952
  background: var(--color-surface-soft);
3513
3953
  }
3514
3954
 
3515
- /* Figma `size/heading/sm`. Written out rather than taken from
3516
- `--type-heading-sm-size`, which is 20px here and 18px in the library — the token is
3517
- wrong and correcting it would move the PDP's size guide, which has its own design. */
3518
- ._title_145t0_21 {
3955
+ /* Figma `size/heading/sm`. This used to be written out because the token read 20px, the
3956
+ library's heading/md; it is 18 now, and the size guide — the only other consumer, and
3957
+ the reason the token was left wrong asks for the same 18. */
3958
+ ._title_1tevp_21 {
3519
3959
  margin: 0;
3520
- font-size: 18px;
3521
- line-height: 1.38;
3960
+ font-size: var(--type-heading-sm-size);
3961
+ line-height: var(--type-heading-sm-line);
3522
3962
  font-weight: var(--font-weight-bold);
3523
3963
  color: var(--color-text-default);
3524
3964
  }
3525
3965
 
3526
- ._body_145t0_29 {
3966
+ /*
3967
+ * 10 on 14px text: `text-box-trim: trim-both`, cap-alphabetic, as every small text layer
3968
+ * in this file is. The frame's tile is 83 — 20 of padding, a 25px title, 8, this line, 20
3969
+ * — and at a natural line box it was 21 rather than 10, which made every tile 11 too tall
3970
+ * and the block 226 → 249.
3971
+ *
3972
+ * Nothing clips this one, so the descenders hang out of the box and are drawn, exactly as
3973
+ * they are in the frame.
3974
+ */
3975
+ ._body_1tevp_38 {
3527
3976
  margin: 0;
3528
3977
  font-size: var(--type-trimmed-sm-size);
3978
+ line-height: 10px;
3529
3979
  color: var(--color-text-subtle);
3530
3980
  }
3531
- ._section_opjfc_1 {
3981
+ ._section_snuuj_1 {
3532
3982
  display: flex;
3533
3983
  flex-direction: column;
3534
3984
  gap: var(--space-16);
3535
3985
  padding: var(--space-16) var(--space-16) var(--space-24);
3536
3986
  }
3537
3987
 
3538
- ._title_opjfc_8 {
3988
+ /* 1.32, the design system's own figure for `heading/md`, which makes this line the
3989
+ frame's 26 rather than the 25 the token's 1.25 gives. */
3990
+ ._title_snuuj_10 {
3539
3991
  font-size: var(--type-heading-md-size);
3540
- line-height: var(--type-heading-md-line);
3992
+ line-height: 1.32;
3541
3993
  font-weight: var(--font-weight-bold);
3542
3994
  color: var(--color-text-default);
3543
3995
  }
3544
3996
 
3545
- ._list_opjfc_15 {
3997
+ ._list_snuuj_17 {
3546
3998
  list-style: none;
3547
3999
  margin: 0;
3548
4000
  padding: 0;
3549
4001
  }
3550
4002
 
3551
4003
  /*
3552
- * 16px above and below a 14px label clears the 44px tap target on its own, so there is no
3553
- * explicit floor here. That holds because of the type size a smaller label would need
3554
- * the min-height back.
4004
+ * 48 tall, which the 16px chevron sets rather than the label: 16 of padding, the mark, 16.
4005
+ * That only holds with the label trimmed to its cap (10 on 14px, as the frame draws it) —
4006
+ * at a natural line box the text was the taller of the two and made the row 54.
4007
+ *
4008
+ * 16 above and below still clears the 44px tap target on its own, so there is no explicit
4009
+ * floor here. That holds because of the type size and the mark beside it; a smaller label
4010
+ * with no chevron would need the min-height back.
3555
4011
  */
3556
- ._row_opjfc_26 {
4012
+ ._row_snuuj_32 {
3557
4013
  display: flex;
3558
4014
  align-items: center;
3559
4015
  justify-content: space-between;
@@ -3561,15 +4017,16 @@
3561
4017
  text-decoration: none;
3562
4018
  color: var(--color-text-default);
3563
4019
  font-size: var(--type-trimmed-sm-size);
4020
+ line-height: 10px;
3564
4021
  font-weight: var(--font-weight-bold);
3565
4022
  }
3566
4023
 
3567
4024
  /* Between rows only — a rule under the last one reads as a cut-off list. */
3568
- ._list_opjfc_15 li + li ._row_opjfc_26 {
4025
+ ._list_snuuj_17 li + li ._row_snuuj_32 {
3569
4026
  border-top: 1px solid var(--color-border-transparent-soft);
3570
4027
  }
3571
4028
 
3572
- ._row_opjfc_26 svg {
4029
+ ._row_snuuj_32 svg {
3573
4030
  flex-shrink: 0;
3574
4031
  color: var(--color-text-default);
3575
4032
  }