@nok-integration/storefront-react 0.17.2 → 0.18.0

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.
@@ -41,14 +41,32 @@
41
41
  --type-heading-sm-line: 1.38;
42
42
  --type-paragraph-size: 16px;
43
43
  --type-paragraph-line: 1.55;
44
+ /*
45
+ * The `trimmed` family is `text-box-trim: trim-both` with a cap-alphabetic edge, which
46
+ * is how nearly every small text layer in this design is drawn. Figma's box therefore
47
+ * stops at the CAP height and a CSS line box does not, so these carry the cap in pixels
48
+ * rather than a ratio: 16px DAZN Oscine caps at 11, 14px at 10, 12px at 9. Rounded by
49
+ * the designer, which is why they are not one ratio.
50
+ *
51
+ * They were all `1` — the right idea, approximated, and 5px out on every 16px label. On
52
+ * the PDP that was the "Color: White" header and the "Size" header, and it compounded:
53
+ * measured at 375, the colour block came out 142 against the frame's 128.
54
+ *
55
+ * Glyphs deliberately overflow a box this short, exactly as they do in Figma. Anything
56
+ * that CLIPS (`overflow: hidden`, for an ellipsis or a line clamp) must add the
57
+ * padding/negative-margin pair — see `CartLineItem.title` and `ProductTile.title` — or
58
+ * it beheads the descenders. `text-box-trim` itself would let us write the design's
59
+ * numbers directly; it is Chrome 133+ and this package still supports the WebView
60
+ * DAZN's React 16 build ships with.
61
+ */
44
62
  --type-trimmed-md-size: 16px;
45
- --type-trimmed-md-line: 1;
63
+ --type-trimmed-md-line: 11px;
46
64
  --type-trimmed-sm-size: 14px;
47
- --type-trimmed-sm-line: 1;
65
+ --type-trimmed-sm-line: 10px;
48
66
  --type-caption-sm-size: 14px;
49
67
  --type-caption-sm-line: 1.5;
50
68
  --type-trimmed-xs-size: 12px;
51
- --type-trimmed-xs-line: 1;
69
+ --type-trimmed-xs-line: 9px;
52
70
 
53
71
  /* ── Colour ───────────────────────────────────────────────────────────── */
54
72
  --color-text-default: #0c161c;
@@ -65,6 +83,9 @@
65
83
  control and the close disc on a sheet header. `full-color`, so it is the same
66
84
  value in both palettes and is not remapped below. */
67
85
  --color-surface-neutral: #ced0d2;
86
+ /* semantic/base/surface/bold — the sheet handle, and the ground of a disabled
87
+ `mobile/button`. Static, like the neutral above it. */
88
+ --color-surface-bold: #6d7377;
68
89
  --color-border-default: #dddedf;
69
90
  --color-border-subtle: #ced0d2;
70
91
  /* semantic/base/border/transparent/soft. Alpha rather than a flat grey on purpose: it
@@ -222,7 +243,7 @@
222
243
  background: var(--color-surface-max);
223
244
  color: var(--color-text-strong);
224
245
  }
225
- ._button_tdhm8_1 {
246
+ ._button_1u2uh_1 {
226
247
  display: inline-flex;
227
248
  align-items: center;
228
249
  justify-content: center;
@@ -246,33 +267,54 @@
246
267
  -webkit-tap-highlight-color: transparent;
247
268
  }
248
269
 
249
- ._fullWidth_tdhm8_25 {
270
+ ._fullWidth_1u2uh_25 {
250
271
  width: 100%;
251
272
  }
252
273
 
253
- ._primary_tdhm8_29 {
274
+ ._primary_1u2uh_29 {
254
275
  background: var(--color-surface-max);
255
276
  color: var(--color-text-strong);
256
277
  }
257
278
 
258
- ._secondary_tdhm8_34 {
279
+ ._secondary_1u2uh_34 {
259
280
  background: transparent;
260
281
  color: var(--color-text-default);
261
282
  border-color: var(--color-border-default);
262
283
  }
263
284
 
264
- ._ghost_tdhm8_40 {
285
+ ._ghost_1u2uh_40 {
265
286
  background: transparent;
266
287
  color: var(--color-text-default);
267
288
  border-color: transparent;
268
289
  }
269
290
 
270
- ._button_tdhm8_1:disabled {
291
+ ._button_1u2uh_1:disabled {
271
292
  cursor: not-allowed;
293
+ }
294
+
295
+ /*
296
+ * Figma `mobile/button` state=disabled: a solid `surface/bold` ground with `text/disabled`
297
+ * on it — NOT the filled button at half strength, which is what this used to be.
298
+ *
299
+ * The difference is visible wherever a form gates its own CTA, and the new cancel and
300
+ * return sheets both open in that state, so it is the first thing drawn on either screen.
301
+ * Half-opacity black over white renders a washed grey that changes with whatever is behind
302
+ * it; the design's is one colour that does not.
303
+ *
304
+ * Only the filled variant. `secondary` and `ghost` are outlines rather than grounds, and
305
+ * the DS does not draw a filled disabled state for either — they keep the dimming.
306
+ */
307
+ ._primary_1u2uh_29:disabled {
308
+ background: var(--color-surface-bold);
309
+ color: var(--color-text-disabled);
310
+ }
311
+
312
+ ._secondary_1u2uh_34:disabled,
313
+ ._ghost_1u2uh_40:disabled {
272
314
  opacity: 0.5;
273
315
  }
274
316
 
275
- ._button_tdhm8_1:focus-visible {
317
+ ._button_1u2uh_1:focus-visible {
276
318
  outline: 2px solid var(--color-surface-max);
277
319
  outline-offset: 2px;
278
320
  }
@@ -283,17 +325,17 @@
283
325
  * cta-bar's own note said "annotate in build" — so it was drawn at 16px and the label
284
326
  * was dimmed to carry the busy signal. It has one now, and the spinner carries it alone.
285
327
  */
286
- ._spinner_tdhm8_62 {
328
+ ._spinner_1u2uh_83 {
287
329
  width: 20px;
288
330
  height: 20px;
289
331
  margin: 2px;
290
332
  border-radius: var(--radius-full);
291
333
  border: 2px solid currentColor;
292
334
  border-top-color: transparent;
293
- animation: _spin_tdhm8_62 700ms linear infinite;
335
+ animation: _spin_1u2uh_83 700ms linear infinite;
294
336
  }
295
337
 
296
- @keyframes _spin_tdhm8_62 {
338
+ @keyframes _spin_1u2uh_83 {
297
339
  to {
298
340
  transform: rotate(360deg);
299
341
  }
@@ -819,7 +861,7 @@
819
861
  display: block;
820
862
  flex-shrink: 0;
821
863
  }
822
- ._root_n3nm5_1 {
864
+ ._root_rvfx9_1 {
823
865
  display: inline-flex;
824
866
  align-items: baseline;
825
867
  gap: var(--space-8);
@@ -828,33 +870,54 @@
828
870
 
829
871
  /* Alignment variants. Cards align on the price baseline row with a tight 4px gap; the
830
872
  PDP price row centres the price against its sale badge (6px). */
831
- ._center_n3nm5_10 {
873
+ ._center_rvfx9_10 {
832
874
  align-items: center;
833
875
  gap: var(--space-6);
834
876
  }
835
- ._end_n3nm5_14 {
877
+ ._end_rvfx9_14 {
836
878
  align-items: flex-end;
837
879
  gap: var(--space-4);
838
880
  }
839
881
 
840
- /* Size sets the row's font-size so the price and its struck was-price match (per the
841
- product-card, where both are 16px). */
842
- ._sm_n3nm5_21 {
882
+ /*
883
+ * Size sets the row's font-size so the price and its struck was-price match (per the
884
+ * product-card, where both are 16px), and its cap-trimmed leading.
885
+ *
886
+ * The leading was missing, and on the PDP that made the price row 25 tall against the
887
+ * frame's 20 — which is the whole of the 6px the product-info block was over. Figma sets
888
+ * every amount `text-box-trim: trim-both`, cap-alphabetic, so the row's height comes from
889
+ * the sale badge beside it rather than from the leading of a 16px font.
890
+ */
891
+ ._sm_rvfx9_28 {
843
892
  font-size: var(--type-trimmed-sm-size);
893
+ line-height: var(--type-trimmed-sm-line);
844
894
  }
845
- ._md_n3nm5_24 {
895
+ ._md_rvfx9_32 {
846
896
  font-size: var(--type-trimmed-md-size);
897
+ line-height: var(--type-trimmed-md-line);
847
898
  }
848
- ._lg_n3nm5_27 {
899
+ ._lg_rvfx9_36 {
849
900
  font-size: var(--type-heading-md-size);
901
+ /* 14 of cap on 20px, the same trim one size up. No token: `heading/md` is a display
902
+ size and this is its only trimmed use. */
903
+ line-height: 14px;
904
+ }
905
+
906
+ /*
907
+ * `mobile/pdp/price` is `min-h-[20px]`, and 20 is the sale badge's own height — so the row
908
+ * keeps that height whether or not a discount put a badge in it. Without this a
909
+ * full-price PDP would sit 9px tighter than a discounted one.
910
+ */
911
+ ._badge_rvfx9_48 {
912
+ min-height: 20px;
850
913
  }
851
914
 
852
- ._price_n3nm5_31 {
915
+ ._price_rvfx9_52 {
853
916
  font-weight: var(--font-weight-bold);
854
917
  color: var(--color-text-default);
855
918
  }
856
919
 
857
- ._compareAt_n3nm5_36 {
920
+ ._compareAt_rvfx9_57 {
858
921
  color: var(--color-text-disabled);
859
922
  text-decoration: line-through;
860
923
  font-weight: var(--font-weight-regular);
@@ -862,7 +925,7 @@
862
925
 
863
926
  /* On a product card the struck price carries the same weight as the live one (Figma
864
927
  `mobile/product-card`). Scoped to the card variant so the PDP's row is untouched. */
865
- ._strikethrough_n3nm5_44 ._compareAt_n3nm5_36 {
928
+ ._strikethrough_rvfx9_65 ._compareAt_rvfx9_57 {
866
929
  font-weight: var(--font-weight-bold);
867
930
  }
868
931
  /*
@@ -1261,6 +1324,235 @@
1261
1324
  ._summaryCard_7mr8w_136 > :last-child {
1262
1325
  padding: 0 var(--space-16);
1263
1326
  }
1327
+ /*
1328
+ * Figma `.sheet-header` (404:5379) — 48 tall, three slots.
1329
+ *
1330
+ * Extracted from the size guide when the cancel and return sheets turned out to instance
1331
+ * the same component. One copy, so the handle cannot end up 4px off on one screen.
1332
+ */
1333
+ ._header_1f3nh_7 {
1334
+ display: flex;
1335
+ align-items: flex-start;
1336
+ justify-content: space-between;
1337
+ }
1338
+
1339
+ /* The empty left slot. It exists to balance the close control so the handle is centred on
1340
+ the sheet rather than on what is left of it. */
1341
+ ._slot_1f3nh_15 {
1342
+ flex-shrink: 0;
1343
+ width: 48px;
1344
+ height: 48px;
1345
+ }
1346
+
1347
+ /* `self-stretch` with 12 of padding: the handle sits 12 from the top of the 48, not
1348
+ centred in it. */
1349
+ ._handleSlot_1f3nh_23 {
1350
+ align-self: stretch;
1351
+ padding: var(--space-12);
1352
+ }
1353
+
1354
+ ._handle_1f3nh_23 {
1355
+ width: 44px;
1356
+ height: 4px;
1357
+ border-radius: var(--radius-full);
1358
+ background: var(--color-surface-bold);
1359
+ }
1360
+
1361
+ ._closeSlot_1f3nh_35 {
1362
+ display: inline-flex;
1363
+ align-items: center;
1364
+ justify-content: center;
1365
+ flex-shrink: 0;
1366
+ width: 48px;
1367
+ height: 48px;
1368
+ padding: var(--space-12);
1369
+ border: 0;
1370
+ background: none;
1371
+ color: var(--color-text-default);
1372
+ cursor: pointer;
1373
+ }
1374
+
1375
+ ._closeSlot_1f3nh_35:focus-visible {
1376
+ outline: none;
1377
+ box-shadow: var(--focus-ring);
1378
+ border-radius: var(--radius-4);
1379
+ }
1380
+
1381
+ /* `across-platform/icon-button`, fill: a 24 disc around the 16px cross box. */
1382
+ ._close_1f3nh_35 {
1383
+ display: inline-flex;
1384
+ align-items: center;
1385
+ justify-content: center;
1386
+ width: 24px;
1387
+ height: 24px;
1388
+ border-radius: var(--radius-full);
1389
+ background: var(--color-surface-neutral);
1390
+ }
1391
+ /*
1392
+ * Figma `Reason for cancelling` (4632:17129) and `Reason for return`.
1393
+ *
1394
+ * A 48 header, a body of 24-gap blocks inset 16, and the sheet footer. Radius 12 at the
1395
+ * top — NOT the size guide's 16. The two sheets are drawn with different corners in the
1396
+ * file and each follows its own.
1397
+ */
1398
+ ._scrim_7on4q_8 {
1399
+ position: fixed;
1400
+ inset: 0;
1401
+ z-index: 60;
1402
+ display: flex;
1403
+ align-items: flex-end;
1404
+ justify-content: center;
1405
+ /* `semantic/base/surface/backdrop`. */
1406
+ background: rgba(12, 22, 28, 0.32);
1407
+ animation: _fade_7on4q_1 160ms ease-out;
1408
+ }
1409
+
1410
+ ._sheet_7on4q_20 {
1411
+ display: flex;
1412
+ flex-direction: column;
1413
+ width: 100%;
1414
+ max-width: 480px;
1415
+ max-height: 90dvh;
1416
+ overflow: hidden;
1417
+ border-radius: var(--radius-12) var(--radius-12) 0 0;
1418
+ background: var(--color-surface-default);
1419
+ animation: _rise_7on4q_1 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
1420
+ }
1421
+
1422
+ ._body_7on4q_32 {
1423
+ flex: 1 1 auto;
1424
+ overflow-y: auto;
1425
+ display: flex;
1426
+ flex-direction: column;
1427
+ gap: var(--space-16);
1428
+ padding: 0 var(--space-16);
1429
+ }
1430
+
1431
+ ._body_7on4q_32 > * {
1432
+ flex-shrink: 0;
1433
+ }
1434
+
1435
+ /* `heading/md` at the library's 1.32, not our 1.25 base. */
1436
+ ._title_7on4q_46 {
1437
+ margin: 0;
1438
+ font-size: var(--type-heading-md-size);
1439
+ line-height: 1.32;
1440
+ font-weight: var(--font-weight-bold);
1441
+ color: var(--color-text-default);
1442
+ }
1443
+
1444
+ ._options_7on4q_54 {
1445
+ display: flex;
1446
+ flex-direction: column;
1447
+ gap: var(--space-6);
1448
+ }
1449
+
1450
+ /*
1451
+ * Each reason is a filled card, not a bare radio: 12 of padding on a `soft` ground at
1452
+ * radius 12, which makes the whole row the target rather than the 20px circle.
1453
+ */
1454
+ ._option_7on4q_54 {
1455
+ display: flex;
1456
+ align-items: center;
1457
+ gap: var(--space-8);
1458
+ width: 100%;
1459
+ padding: var(--space-12);
1460
+ border: 0;
1461
+ border-radius: var(--radius-12);
1462
+ background: var(--color-surface-soft);
1463
+ color: var(--color-text-subtle);
1464
+ font-family: inherit;
1465
+ text-align: left;
1466
+ cursor: pointer;
1467
+ }
1468
+
1469
+ ._option_7on4q_54:focus-visible {
1470
+ outline: none;
1471
+ box-shadow: var(--focus-ring);
1472
+ }
1473
+
1474
+ /*
1475
+ * The frame's `Checkbox`: a 24 box holding a 20 circle, so the ring sits 2 in from each
1476
+ * edge and the row's 8 gap measures from the box rather than the circle.
1477
+ */
1478
+ ._radio_7on4q_88 {
1479
+ position: relative;
1480
+ display: inline-flex;
1481
+ align-items: center;
1482
+ justify-content: center;
1483
+ flex-shrink: 0;
1484
+ width: 24px;
1485
+ height: 24px;
1486
+ color: var(--color-surface-max);
1487
+ }
1488
+
1489
+ /* Unselected is an empty ring; the filled disc and tick are drawn only when chosen. */
1490
+ ._radio_7on4q_88::before {
1491
+ content: '';
1492
+ position: absolute;
1493
+ width: 20px;
1494
+ height: 20px;
1495
+ border: 1px solid var(--color-border-default);
1496
+ border-radius: var(--radius-full);
1497
+ }
1498
+
1499
+ ._option_7on4q_54[aria-checked='true'] ._radio_7on4q_88::before {
1500
+ border-color: transparent;
1501
+ }
1502
+
1503
+ ._radio_7on4q_88 svg {
1504
+ position: relative;
1505
+ }
1506
+
1507
+ /* 16px, cap-trimmed to 11 — `trimmed/md`, the same face the size chips use. */
1508
+ ._label_7on4q_118 {
1509
+ font-size: var(--type-trimmed-md-size);
1510
+ line-height: 11px;
1511
+ font-weight: var(--font-weight-regular);
1512
+ padding: 5px 0;
1513
+ margin: -5px 0;
1514
+ }
1515
+
1516
+ /* `.bottomsheet-footer`: no top padding, 24 below, inset 16. */
1517
+ ._footer_7on4q_127 {
1518
+ flex-shrink: 0;
1519
+ display: flex;
1520
+ flex-direction: column;
1521
+ gap: var(--space-12);
1522
+ padding: var(--space-16) var(--space-16) calc(var(--space-24) + var(--safe-area-bottom));
1523
+ }
1524
+
1525
+ ._error_7on4q_135 {
1526
+ margin: 0;
1527
+ font-size: var(--type-trimmed-sm-size);
1528
+ line-height: 1.4;
1529
+ color: var(--color-state-text-critical);
1530
+ }
1531
+
1532
+ @keyframes _fade_7on4q_1 {
1533
+ from {
1534
+ opacity: 0;
1535
+ }
1536
+ to {
1537
+ opacity: 1;
1538
+ }
1539
+ }
1540
+
1541
+ @keyframes _rise_7on4q_1 {
1542
+ from {
1543
+ transform: translateY(12%);
1544
+ }
1545
+ to {
1546
+ transform: translateY(0);
1547
+ }
1548
+ }
1549
+
1550
+ @media (prefers-reduced-motion: reduce) {
1551
+ ._scrim_7on4q_8,
1552
+ ._sheet_7on4q_20 {
1553
+ animation: none;
1554
+ }
1555
+ }
1264
1556
  /*
1265
1557
  * Figma `order stats` (5479:132209), whose three states differ only inside the widget.
1266
1558
  *
@@ -1268,7 +1560,7 @@
1268
1560
  * everything below it is 32 apart: widget, rule, rows, address, summary. Same rhythm and
1269
1561
  * same padding as the confirmation, which is the same page from the fold down.
1270
1562
  */
1271
- ._page_1vg5x_8 {
1563
+ ._page_opefg_8 {
1272
1564
  display: flex;
1273
1565
  flex-direction: column;
1274
1566
  gap: var(--space-32);
@@ -1278,7 +1570,7 @@
1278
1570
  /* ── Order number + timeline ───────────────────────────────────────────────── */
1279
1571
 
1280
1572
  /* `mobile/order/delivery-widget`: the title row, then the steps, 32 apart. */
1281
- ._widget_1vg5x_18 {
1573
+ ._widget_opefg_18 {
1282
1574
  display: flex;
1283
1575
  flex-direction: column;
1284
1576
  gap: var(--space-32);
@@ -1286,7 +1578,7 @@
1286
1578
 
1287
1579
  /* The number on the left, the carrier link hard right — and nothing between them, so a
1288
1580
  long reference runs into the space the link is not using rather than under it. */
1289
- ._titleRow_1vg5x_26 {
1581
+ ._titleRow_opefg_26 {
1290
1582
  display: flex;
1291
1583
  align-items: center;
1292
1584
  justify-content: space-between;
@@ -1302,119 +1594,687 @@
1302
1594
  *
1303
1595
  * Nothing clips it, so the cap-height box needs no descender protection.
1304
1596
  */
1305
- ._headline_1vg5x_42 {
1597
+ ._headline_opefg_42 {
1598
+ margin: 0;
1599
+ min-width: 0;
1600
+ font-size: var(--type-heading-md-size);
1601
+ line-height: 14px;
1602
+ font-weight: var(--font-weight-bold);
1603
+ overflow: hidden;
1604
+ text-overflow: ellipsis;
1605
+ white-space: nowrap;
1606
+ }
1607
+
1608
+ /*
1609
+ * The carrier link: a text link with the design's `redirect-link` mark, not the 48px
1610
+ * button this used to be. The frame puts it on the title's own line, right-aligned, at the
1611
+ * same 16px as a timeline label.
1612
+ *
1613
+ * An anchor rather than a button because the destination is a real page on somebody else's
1614
+ * site, and it has to behave like one: middle-click, long-press, open in a new tab.
1615
+ */
1616
+ ._track_opefg_61 {
1617
+ display: inline-flex;
1618
+ align-items: center;
1619
+ gap: var(--space-6);
1620
+ flex-shrink: 0;
1621
+ font-size: var(--type-trimmed-md-size);
1622
+ line-height: 14px;
1623
+ font-weight: var(--font-weight-bold);
1624
+ color: var(--color-text-default);
1625
+ text-decoration: none;
1626
+ }
1627
+
1628
+ ._track_opefg_61:focus-visible {
1629
+ outline: none;
1630
+ box-shadow: var(--focus-ring);
1631
+ border-radius: var(--radius-4);
1632
+ }
1633
+
1634
+ /*
1635
+ * The frame's `Line 11`, between the widget and the receipt.
1636
+ *
1637
+ * A Figma line has no height — 32 above it and 32 below it means 64 between the blocks it
1638
+ * separates, with the hairline drawn on that boundary. The negative margin takes the
1639
+ * pixel back out of the layout so the two gaps stay 32 rather than becoming 32 and 33.
1640
+ */
1641
+ ._rule_opefg_86 {
1642
+ height: 1px;
1643
+ margin: 0 0 -1px;
1644
+ border: 0;
1645
+ background: var(--color-border-default);
1646
+ }
1647
+
1648
+ /* ── Need help? ────────────────────────────────────────────────────────────── */
1649
+
1650
+ /* `mobile/explore`: the heading, then the rows, 6 apart. */
1651
+ ._help_opefg_96 {
1652
+ display: flex;
1653
+ flex-direction: column;
1654
+ gap: var(--space-6);
1655
+ }
1656
+
1657
+ ._helpTitle_opefg_102 {
1658
+ margin: 0;
1659
+ font-size: var(--type-heading-md-size);
1660
+ line-height: 1.32;
1661
+ font-weight: var(--font-weight-bold);
1662
+ }
1663
+
1664
+ ._helpRows_opefg_109 {
1665
+ display: flex;
1666
+ flex-direction: column;
1667
+ }
1668
+
1669
+ /*
1670
+ * 48 tall: 16 of padding either side of a 16px chevron, which is what sets the height. The
1671
+ * label is cap-trimmed to 10 and is shorter than the mark beside it.
1672
+ */
1673
+ ._helpRow_opefg_109 {
1674
+ display: flex;
1675
+ align-items: center;
1676
+ justify-content: space-between;
1677
+ gap: var(--space-12);
1678
+ width: 100%;
1679
+ padding: var(--space-16) 0;
1680
+ border: 0;
1681
+ border-radius: var(--radius-8);
1682
+ background: none;
1683
+ color: var(--color-text-default);
1684
+ font-family: inherit;
1685
+ font-size: var(--type-trimmed-sm-size);
1686
+ line-height: 10px;
1687
+ font-weight: var(--font-weight-bold);
1688
+ text-align: left;
1689
+ cursor: pointer;
1690
+ }
1691
+
1692
+ /*
1693
+ * `border/full-color/subtle`, one step darker than the hairline the cards are drawn with,
1694
+ * and between the rows only — a rule under the last one would leave the block underlined.
1695
+ *
1696
+ * After `.helpRow` and not before it: that rule sets `border: 0` and its own padding, and
1697
+ * at equal specificity the later one wins. Written first, this drew no line at all.
1698
+ *
1699
+ * Nothing gives the pixel back, because nothing takes it: the row's height comes from its
1700
+ * padding and its 16px chevron rather than from a `height`, so the hairline adds to the
1701
+ * row instead of eating into it. 48, the line, then 48 — the frame's own 97 for the pair.
1702
+ */
1703
+ ._helpRow_opefg_109 + ._helpRow_opefg_109 {
1704
+ border-top: 1px solid var(--color-border-subtle);
1705
+ }
1706
+
1707
+ ._helpRow_opefg_109:focus-visible {
1708
+ outline: none;
1709
+ box-shadow: var(--focus-ring);
1710
+ }
1711
+
1712
+ /* ── Cancel, and the cancelled order ───────────────────────────────────────── */
1713
+
1714
+ /*
1715
+ * Figma `Cancel flow` (4551:32251) screen 1: a destructive action on a pale critical
1716
+ * ground, at the foot of the screen below the summary.
1717
+ *
1718
+ * Not a `Button` variant. The design system has no destructive button and inventing one
1719
+ * would put a fourth variant in the primitive for a single use — this is the one control
1720
+ * in the package drawn this way, so it is drawn here.
1721
+ */
1722
+ ._cancel_opefg_167 {
1723
+ display: inline-flex;
1724
+ align-items: center;
1725
+ justify-content: center;
1726
+ width: 100%;
1727
+ min-height: var(--control-height);
1728
+ padding: 0 var(--space-20);
1729
+ border: 0;
1730
+ border-radius: var(--radius-8);
1731
+ background: var(--color-state-surface-critical-soft);
1732
+ color: var(--color-state-text-critical);
1733
+ font-family: inherit;
1734
+ font-size: var(--type-trimmed-md-size);
1735
+ line-height: 11px;
1736
+ font-weight: var(--font-weight-bold);
1737
+ cursor: pointer;
1738
+ }
1739
+
1740
+ ._cancel_opefg_167:focus-visible {
1741
+ outline: none;
1742
+ box-shadow: var(--focus-ring);
1743
+ }
1744
+
1745
+ /* Screen 3. The head is a title and one meta line, 8 apart. */
1746
+ ._cancelledHead_opefg_191 {
1747
+ display: flex;
1748
+ flex-direction: column;
1749
+ gap: var(--space-8);
1750
+ }
1751
+
1752
+ ._cancelledTitle_opefg_197 {
1753
+ margin: 0;
1754
+ font-size: var(--type-heading-md-size);
1755
+ line-height: 1.32;
1756
+ font-weight: var(--font-weight-bold);
1757
+ color: var(--color-text-default);
1758
+ }
1759
+
1760
+ /* The reference and the date it was placed, cap-trimmed to 10 on 14. */
1761
+ ._cancelledMeta_opefg_206 {
1762
+ font-size: var(--type-trimmed-sm-size);
1763
+ line-height: 10px;
1764
+ padding: 5px 0;
1765
+ margin: -5px 0;
1766
+ color: var(--color-text-subtle);
1767
+ }
1768
+ /*
1769
+ * Figma `Return flow` (4551:32294), the item-selection screen (4632:17780).
1770
+ *
1771
+ * 20 of padding top and bottom, 16 either side, and 24 between the title block, the list
1772
+ * and the button. The cards are 12 apart inside the list.
1773
+ */
1774
+ ._page_1c7ro_7 {
1775
+ display: flex;
1776
+ flex-direction: column;
1777
+ gap: var(--space-24);
1778
+ padding: var(--space-20) var(--space-16);
1779
+ background: var(--color-surface-default);
1780
+ }
1781
+
1782
+ ._titles_1c7ro_15 {
1783
+ display: flex;
1784
+ flex-direction: column;
1785
+ gap: var(--space-8);
1786
+ }
1787
+
1788
+ ._title_1c7ro_15 {
1789
+ margin: 0;
1790
+ font-size: var(--type-heading-md-size);
1791
+ line-height: 1.32;
1792
+ font-weight: var(--font-weight-bold);
1793
+ color: var(--color-text-default);
1794
+ }
1795
+
1796
+ /* 14 cap-trimmed to 10, like every small label in this package. */
1797
+ ._subtitle_1c7ro_30 {
1798
+ font-size: var(--type-trimmed-sm-size);
1799
+ line-height: 10px;
1800
+ padding: 5px 0;
1801
+ margin: -5px 0;
1802
+ color: var(--color-text-subtle);
1803
+ }
1804
+
1805
+ ._list_1c7ro_38 {
1806
+ display: flex;
1807
+ flex-direction: column;
1808
+ gap: var(--space-12);
1809
+ }
1810
+
1811
+ /*
1812
+ * A filled card at radius 18 — the largest corner in the scale, and the one the frame
1813
+ * uses for a block a fan acts on rather than merely reads.
1814
+ */
1815
+ ._card_1c7ro_48 {
1816
+ display: flex;
1817
+ align-items: flex-start;
1818
+ gap: var(--space-12);
1819
+ padding: var(--space-20) var(--space-16);
1820
+ border-radius: var(--radius-18);
1821
+ background: var(--color-surface-soft);
1822
+ }
1823
+
1824
+ /*
1825
+ * The checkbox sits 12 down from the top of the card rather than centred on the row: the
1826
+ * card grows when a reason is chosen, and a centred control would drift down with it.
1827
+ */
1828
+ ._checkSlot_1c7ro_61 {
1829
+ display: inline-flex;
1830
+ align-items: flex-start;
1831
+ flex-shrink: 0;
1832
+ padding: var(--space-12) 0 0;
1833
+ border: 0;
1834
+ background: none;
1835
+ color: var(--color-surface-max);
1836
+ cursor: pointer;
1837
+ }
1838
+
1839
+ ._checkSlot_1c7ro_61:focus-visible {
1840
+ outline: none;
1841
+ box-shadow: var(--focus-ring);
1842
+ border-radius: var(--radius-4);
1843
+ }
1844
+
1845
+ /* A 24 box holding a 20 mark, so the row's 12 gap measures from the box. */
1846
+ ._check_1c7ro_61 {
1847
+ position: relative;
1848
+ display: inline-flex;
1849
+ align-items: center;
1850
+ justify-content: center;
1851
+ width: 24px;
1852
+ height: 24px;
1853
+ }
1854
+
1855
+ ._check_1c7ro_61::before {
1856
+ content: '';
1857
+ position: absolute;
1858
+ width: 20px;
1859
+ height: 20px;
1860
+ border: 1px solid var(--color-border-default);
1861
+ border-radius: var(--radius-full);
1862
+ }
1863
+
1864
+ ._checkSlot_1c7ro_61[aria-checked='true'] ._check_1c7ro_61::before {
1865
+ border-color: transparent;
1866
+ }
1867
+
1868
+ ._check_1c7ro_61 svg {
1869
+ position: relative;
1870
+ }
1871
+
1872
+ ._row_1c7ro_105 {
1873
+ display: flex;
1874
+ flex-direction: column;
1875
+ gap: var(--space-12);
1876
+ flex: 1 1 0;
1877
+ min-width: 0;
1878
+ }
1879
+
1880
+ ._line_1c7ro_113 {
1881
+ display: flex;
1882
+ align-items: center;
1883
+ gap: var(--space-12);
1884
+ }
1885
+
1886
+ ._thumb_1c7ro_119 {
1887
+ position: relative;
1888
+ flex-shrink: 0;
1889
+ width: 48px;
1890
+ height: 48px;
1891
+ border-radius: var(--radius-6);
1892
+ overflow: hidden;
1893
+ background: var(--color-surface-subtle);
1894
+ }
1895
+
1896
+ ._img_1c7ro_129 {
1897
+ object-fit: cover;
1898
+ }
1899
+
1900
+ ._placeholder_1c7ro_133 {
1901
+ width: 100%;
1902
+ height: 100%;
1903
+ }
1904
+
1905
+ ._meta_1c7ro_138 {
1906
+ display: flex;
1907
+ flex-direction: column;
1908
+ gap: var(--space-12);
1909
+ flex: 1 1 0;
1910
+ min-width: 0;
1911
+ }
1912
+
1913
+ /* 14 bold, cap-trimmed to 10 and clipped to one line. */
1914
+ ._name_1c7ro_147 {
1915
+ font-size: var(--type-trimmed-sm-size);
1916
+ line-height: 10px;
1917
+ padding: 5px 0;
1918
+ margin: -5px 0;
1919
+ font-weight: var(--font-weight-bold);
1920
+ color: var(--color-text-default);
1921
+ overflow: hidden;
1922
+ text-overflow: ellipsis;
1923
+ white-space: nowrap;
1924
+ }
1925
+
1926
+ ._attrs_1c7ro_159 {
1927
+ font-size: var(--type-trimmed-sm-size);
1928
+ line-height: 10px;
1929
+ padding: 5px 0;
1930
+ margin: -5px 0;
1931
+ color: var(--color-text-subtle);
1932
+ }
1933
+
1934
+ ._price_1c7ro_167 {
1935
+ display: flex;
1936
+ flex-direction: column;
1937
+ align-items: flex-end;
1938
+ gap: var(--space-6);
1939
+ flex-shrink: 0;
1940
+ text-align: right;
1941
+ }
1942
+
1943
+ ._paid_1c7ro_176 {
1944
+ font-size: var(--type-trimmed-md-size);
1945
+ line-height: 11px;
1946
+ font-weight: var(--font-weight-bold);
1947
+ color: var(--color-text-default);
1948
+ font-variant-numeric: tabular-nums;
1949
+ }
1950
+
1951
+ ._was_1c7ro_184 {
1952
+ font-size: var(--type-trimmed-sm-size);
1953
+ line-height: 10px;
1954
+ color: var(--color-text-disabled);
1955
+ text-decoration: line-through;
1956
+ font-variant-numeric: tabular-nums;
1957
+ }
1958
+
1959
+ /*
1960
+ * The frame's `drop-menu`: a fixed 154 x 32 outlined control, padded 12 on the left and 8
1961
+ * on the right so the chevron sits closer to the edge than the label does.
1962
+ *
1963
+ * Disabled-coloured while it still says "Select reason" — the label is a prompt at that
1964
+ * point, not a value, and the design greys it to say so. It is a live control either way.
1965
+ */
1966
+ ._reason_1c7ro_199 {
1967
+ display: inline-flex;
1968
+ align-items: center;
1969
+ justify-content: space-between;
1970
+ width: 154px;
1971
+ height: 32px;
1972
+ padding: var(--space-4) var(--space-8) var(--space-4) var(--space-12);
1973
+ border: 1px solid var(--color-border-default);
1974
+ border-radius: var(--radius-6);
1975
+ background: none;
1976
+ color: var(--color-text-disabled);
1977
+ font-family: inherit;
1978
+ font-size: var(--type-trimmed-sm-size);
1979
+ line-height: 10px;
1980
+ font-weight: var(--font-weight-bold);
1981
+ cursor: pointer;
1982
+ }
1983
+
1984
+ ._reasonSet_1c7ro_217 {
1985
+ color: var(--color-text-default);
1986
+ }
1987
+
1988
+ ._reason_1c7ro_199:focus-visible {
1989
+ outline: none;
1990
+ box-shadow: var(--focus-ring);
1991
+ }
1992
+ /*
1993
+ * Figma `Return flow` (4551:32294), screen 5 — the label and its instructions.
1994
+ *
1995
+ * The intro block, then a bordered card holding two numbered steps, then "Done". The card
1996
+ * is padded 16 with 24 between its steps; the steps themselves are 16 and 8 internally.
1997
+ */
1998
+ ._page_1r0ea_7 {
1999
+ display: flex;
2000
+ flex-direction: column;
2001
+ gap: var(--space-24);
2002
+ padding: var(--space-20) var(--space-16);
2003
+ background: var(--color-surface-default);
2004
+ }
2005
+
2006
+ ._intro_1r0ea_15 {
2007
+ display: flex;
2008
+ flex-direction: column;
2009
+ gap: var(--space-8);
2010
+ }
2011
+
2012
+ /* `trimmed/md` bold, cap-trimmed to 11 — the frame's heading here is 16, not 20. */
2013
+ ._title_1r0ea_22 {
2014
+ font-size: var(--type-trimmed-md-size);
2015
+ line-height: 11px;
2016
+ padding: 5px 0;
2017
+ margin: -5px 0;
2018
+ font-weight: var(--font-weight-bold);
2019
+ color: var(--color-text-default);
2020
+ }
2021
+
2022
+ ._subtitle_1r0ea_31 {
2023
+ margin: 0;
2024
+ font-size: var(--type-caption-sm-size);
2025
+ line-height: var(--type-caption-sm-line);
2026
+ color: var(--color-text-subtle);
2027
+ }
2028
+
2029
+ /* radius-xxl in the DS — 18 here, the same corner the return cards take. */
2030
+ ._card_1r0ea_39 {
2031
+ display: flex;
2032
+ flex-direction: column;
2033
+ gap: var(--space-24);
2034
+ padding: var(--space-16);
2035
+ border: 1px solid var(--color-border-default);
2036
+ border-radius: var(--radius-18);
2037
+ }
2038
+
2039
+ /* Step one carries a button and a note, so its parts are 16 apart. */
2040
+ ._step_1r0ea_49 {
2041
+ display: flex;
2042
+ flex-direction: column;
2043
+ gap: var(--space-16);
2044
+ }
2045
+
2046
+ /* Step two is a heading and a paragraph, at 8. */
2047
+ ._step2_1r0ea_56 {
2048
+ display: flex;
2049
+ flex-direction: column;
2050
+ gap: var(--space-8);
2051
+ }
2052
+
2053
+ ._stepHead_1r0ea_62 {
2054
+ display: flex;
2055
+ align-items: center;
2056
+ gap: var(--space-8);
2057
+ }
2058
+
2059
+ /* A 24 square at radius 6 on the soft ground — a marker, not a circle. */
2060
+ ._number_1r0ea_69 {
2061
+ display: inline-flex;
2062
+ align-items: center;
2063
+ justify-content: center;
2064
+ flex-shrink: 0;
2065
+ width: 24px;
2066
+ height: 24px;
2067
+ border-radius: var(--radius-6);
2068
+ background: var(--color-surface-soft);
2069
+ font-size: var(--type-caption-sm-size);
2070
+ line-height: 1.5;
2071
+ font-weight: var(--font-weight-bold);
2072
+ color: var(--color-text-default);
2073
+ }
2074
+
2075
+ ._stepTitle_1r0ea_84 {
2076
+ flex: 1 1 0;
2077
+ min-width: 0;
2078
+ font-size: var(--type-trimmed-md-size);
2079
+ line-height: 11px;
2080
+ padding: 5px 0;
2081
+ margin: -5px 0;
2082
+ font-weight: var(--font-weight-bold);
2083
+ color: var(--color-text-default);
2084
+ }
2085
+
2086
+ ._body_1r0ea_95 {
2087
+ margin: 0;
2088
+ font-size: var(--type-caption-sm-size);
2089
+ line-height: var(--type-caption-sm-line);
2090
+ color: var(--color-text-default);
2091
+ }
2092
+
2093
+ /* The frame gives this paragraph 4 of spacing between its two lines. */
2094
+ ._body2_1r0ea_103 {
1306
2095
  margin: 0;
1307
- min-width: 0;
1308
- font-size: var(--type-heading-md-size);
1309
- line-height: 14px;
1310
- font-weight: var(--font-weight-bold);
1311
- overflow: hidden;
1312
- text-overflow: ellipsis;
1313
- white-space: nowrap;
2096
+ font-size: var(--type-caption-sm-size);
2097
+ line-height: var(--type-caption-sm-line);
2098
+ color: var(--color-text-default);
2099
+ }
2100
+
2101
+ ._body2_1r0ea_103 br {
2102
+ content: '';
2103
+ display: block;
2104
+ margin-bottom: var(--space-4);
1314
2105
  }
1315
2106
 
1316
2107
  /*
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.
1320
- *
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.
2108
+ * `mobile/button` at the small size: 40 rather than 48, outlined in the static dark
2109
+ * border, and 14 rather than 16. It is a secondary action inside a card, not the screen's
2110
+ * own call to action the frame keeps "Done" for that.
1323
2111
  */
1324
- ._track_1vg5x_61 {
2112
+ ._download_1r0ea_121 {
1325
2113
  display: inline-flex;
1326
2114
  align-items: center;
1327
- gap: var(--space-6);
1328
- flex-shrink: 0;
1329
- font-size: var(--type-trimmed-md-size);
1330
- line-height: 14px;
1331
- font-weight: var(--font-weight-bold);
2115
+ justify-content: center;
2116
+ gap: var(--space-8);
2117
+ min-height: 40px;
2118
+ padding: var(--space-6) var(--space-8);
2119
+ border: 1px solid var(--color-surface-max);
2120
+ border-radius: var(--radius-8);
1332
2121
  color: var(--color-text-default);
2122
+ font-size: var(--type-trimmed-sm-size);
2123
+ line-height: 10px;
2124
+ font-weight: var(--font-weight-bold);
1333
2125
  text-decoration: none;
1334
2126
  }
1335
2127
 
1336
- ._track_1vg5x_61:focus-visible {
2128
+ ._download_1r0ea_121:focus-visible {
1337
2129
  outline: none;
1338
2130
  box-shadow: var(--focus-ring);
1339
- border-radius: var(--radius-4);
1340
2131
  }
1341
2132
 
2133
+ /* 12 with the library's 1% tracking. */
2134
+ ._note_1r0ea_143 {
2135
+ margin: 0;
2136
+ font-size: var(--type-trimmed-xs-size);
2137
+ line-height: 1.5;
2138
+ letter-spacing: 0.12px;
2139
+ color: var(--color-text-default);
2140
+ }
1342
2141
  /*
1343
- * The frame's `Line 11`, between the widget and the receipt.
2142
+ * Figma `Return flow` (4551:32294), screens 6 to 8 "Return in progress".
1344
2143
  *
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.
2144
+ * The title block, the three-step timeline, then the lines coming back. Same 20/16
2145
+ * padding and same rhythm as the order tracking screen, because it is the same screen
2146
+ * with a different subject.
1348
2147
  */
1349
- ._rule_1vg5x_86 {
1350
- height: 1px;
1351
- margin: 0 0 -1px;
1352
- border: 0;
1353
- background: var(--color-border-default);
2148
+ ._page_o44fl_8 {
2149
+ display: flex;
2150
+ flex-direction: column;
2151
+ gap: var(--space-24);
2152
+ padding: var(--space-20) var(--space-16) var(--space-24);
1354
2153
  }
1355
2154
 
1356
- /* ── Need help? ────────────────────────────────────────────────────────────── */
1357
-
1358
- /* `mobile/explore`: the heading, then the rows, 6 apart. */
1359
- ._help_1vg5x_96 {
2155
+ ._titles_o44fl_15 {
1360
2156
  display: flex;
1361
2157
  flex-direction: column;
1362
- gap: var(--space-6);
2158
+ gap: var(--space-8);
1363
2159
  }
1364
2160
 
1365
- ._helpTitle_1vg5x_102 {
2161
+ ._title_o44fl_15 {
1366
2162
  margin: 0;
1367
2163
  font-size: var(--type-heading-md-size);
1368
2164
  line-height: 1.32;
1369
2165
  font-weight: var(--font-weight-bold);
2166
+ color: var(--color-text-default);
1370
2167
  }
1371
2168
 
1372
- ._helpRows_1vg5x_109 {
2169
+ /* 14 cap-trimmed to 10 — the reference and the reported date on one line. */
2170
+ ._subtitle_o44fl_30 {
2171
+ font-size: var(--type-trimmed-sm-size);
2172
+ line-height: 10px;
2173
+ padding: 5px 0;
2174
+ margin: -5px 0;
2175
+ color: var(--color-text-subtle);
2176
+ }
2177
+
2178
+ ._items_o44fl_38 {
2179
+ list-style: none;
2180
+ margin: 0;
2181
+ padding: 0;
1373
2182
  display: flex;
1374
2183
  flex-direction: column;
2184
+ gap: var(--space-16);
1375
2185
  }
1376
2186
 
1377
- /*
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.
1380
- */
1381
- ._helpRow_1vg5x_109 {
2187
+ ._item_o44fl_38 {
1382
2188
  display: flex;
1383
2189
  align-items: center;
1384
- justify-content: space-between;
1385
2190
  gap: var(--space-12);
2191
+ }
2192
+
2193
+ ._thumb_o44fl_53 {
2194
+ position: relative;
2195
+ flex-shrink: 0;
2196
+ width: 48px;
2197
+ height: 48px;
2198
+ border-radius: var(--radius-6);
2199
+ overflow: hidden;
2200
+ background: var(--color-surface-subtle);
2201
+ }
2202
+
2203
+ ._img_o44fl_63 {
2204
+ object-fit: cover;
2205
+ }
2206
+
2207
+ ._placeholder_o44fl_67 {
1386
2208
  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;
2209
+ height: 100%;
2210
+ }
2211
+
2212
+ ._meta_o44fl_72 {
2213
+ display: flex;
2214
+ flex-direction: column;
2215
+ gap: var(--space-12);
2216
+ flex: 1 1 0;
2217
+ min-width: 0;
2218
+ }
2219
+
2220
+ ._name_o44fl_80 {
1393
2221
  font-size: var(--type-trimmed-sm-size);
1394
2222
  line-height: 10px;
2223
+ padding: 5px 0;
2224
+ margin: -5px 0;
1395
2225
  font-weight: var(--font-weight-bold);
1396
- text-align: left;
1397
- cursor: pointer;
2226
+ color: var(--color-text-default);
2227
+ overflow: hidden;
2228
+ text-overflow: ellipsis;
2229
+ white-space: nowrap;
1398
2230
  }
1399
2231
 
1400
2232
  /*
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.
2233
+ * "Size: M" and the sale badge on one row, as the frame has them. `align-items: center`
2234
+ * rather than baseline: the badge is a 20px box and its text is 12px, so a baseline would
2235
+ * hang it below the size it sits beside.
1403
2236
  *
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.
2237
+ * The trim pair stays on the TEXT, not on the row the badge brings its own height, and
2238
+ * a negative margin on the flex container would eat into the gap above it.
1410
2239
  */
1411
- ._helpRow_1vg5x_109 + ._helpRow_1vg5x_109 {
1412
- border-top: 1px solid var(--color-border-subtle);
2240
+ ._attrs_o44fl_100 {
2241
+ margin: 0;
2242
+ display: flex;
2243
+ align-items: center;
2244
+ gap: var(--space-8);
2245
+ color: var(--color-text-subtle);
1413
2246
  }
1414
2247
 
1415
- ._helpRow_1vg5x_109:focus-visible {
1416
- outline: none;
1417
- box-shadow: var(--focus-ring);
2248
+ ._attrs_o44fl_100 > span {
2249
+ font-size: var(--type-trimmed-sm-size);
2250
+ line-height: 10px;
2251
+ padding: 5px 0;
2252
+ margin: -5px 0;
2253
+ }
2254
+
2255
+ ._price_o44fl_115 {
2256
+ display: flex;
2257
+ flex-direction: column;
2258
+ align-items: flex-end;
2259
+ gap: var(--space-6);
2260
+ flex-shrink: 0;
2261
+ text-align: right;
2262
+ }
2263
+
2264
+ ._paid_o44fl_124 {
2265
+ font-size: var(--type-trimmed-md-size);
2266
+ line-height: 11px;
2267
+ font-weight: var(--font-weight-bold);
2268
+ color: var(--color-text-default);
2269
+ font-variant-numeric: tabular-nums;
2270
+ }
2271
+
2272
+ ._was_o44fl_132 {
2273
+ font-size: var(--type-trimmed-sm-size);
2274
+ line-height: 10px;
2275
+ color: var(--color-text-disabled);
2276
+ text-decoration: line-through;
2277
+ font-variant-numeric: tabular-nums;
1418
2278
  }
1419
2279
  /*
1420
2280
  * Figma `5295:74053`. The page's own block starts at y=118 — under the 64px bar and the
@@ -1719,7 +2579,7 @@
1719
2579
  * and left the card 11px taller than the frame, because the compensation was in the gap
1720
2580
  * rather than in the box that was wrong. See `.title`.
1721
2581
  */
1722
- ._tile_1eiri_7 {
2582
+ ._tile_1io44_7 {
1723
2583
  display: flex;
1724
2584
  flex-direction: column;
1725
2585
  gap: var(--space-12);
@@ -1727,7 +2587,7 @@
1727
2587
  color: inherit;
1728
2588
  }
1729
2589
 
1730
- ._media_1eiri_15 {
2590
+ ._media_1io44_15 {
1731
2591
  position: relative;
1732
2592
  width: 100%;
1733
2593
  /* Product-card image is 165:220 (3:4), radius-6 (Figma), sharp not pill-round. */
@@ -1737,11 +2597,11 @@
1737
2597
  background: var(--color-surface-soft);
1738
2598
  }
1739
2599
 
1740
- ._image_1eiri_25 {
2600
+ ._image_1io44_25 {
1741
2601
  object-fit: cover;
1742
2602
  }
1743
2603
 
1744
- ._placeholder_1eiri_29 {
2604
+ ._placeholder_1io44_29 {
1745
2605
  width: 100%;
1746
2606
  height: 100%;
1747
2607
  background: var(--color-surface-soft);
@@ -1749,7 +2609,7 @@
1749
2609
 
1750
2610
  /* TOP PICK flag — top-left over the image, white surface, radius-2, uppercase. Fixed
1751
2611
  colours (not theme tokens): it always sits over a light product image. */
1752
- ._topBadge_1eiri_37 {
2612
+ ._topBadge_1io44_37 {
1753
2613
  position: absolute;
1754
2614
  top: var(--space-8);
1755
2615
  left: var(--space-8);
@@ -1760,7 +2620,13 @@
1760
2620
  max-width: calc(100% - var(--space-8) * 2);
1761
2621
  overflow: hidden;
1762
2622
  text-overflow: ellipsis;
1763
- padding: var(--space-4) var(--space-6);
2623
+ /* `mobile/badge/top-pick` fixes the box at 20 — it does not hug its leading. That was
2624
+ invisible while `--type-trimmed-xs-line` was `1`, because 4 + 12 + 4 happened to come
2625
+ to 20; with the token carrying the real cap (9) it would have shrunk to 17. */
2626
+ display: inline-flex;
2627
+ align-items: center;
2628
+ height: 20px;
2629
+ padding: 0 var(--space-6);
1764
2630
  border-radius: var(--radius-2);
1765
2631
  background: #f9fafa;
1766
2632
  color: #0c161c;
@@ -1772,14 +2638,27 @@
1772
2638
  white-space: nowrap;
1773
2639
  }
1774
2640
 
1775
- ._saleBadge_1eiri_60 {
2641
+ /*
2642
+ * `display: block` is not decoration. The wrapper is a `span`, so as an inline box it
2643
+ * reserves room for the font's descenders around the 20px badge inside it — measured 25,
2644
+ * which pushed the badge 2.5px off the 8px inset the frame draws it at.
2645
+ */
2646
+ /*
2647
+ * `display: flex`, and it is load-bearing. The wrapper is a `span`, so left inline — or
2648
+ * even as a `block` — it builds a LINE box around the 20px badge and reserves the font's
2649
+ * descender room under it: measured 25 against the badge's 20, which put the badge 13px
2650
+ * above the image's edge where the frame draws it 8. A flex container makes the badge a
2651
+ * flex item, and a flex item has no line box.
2652
+ */
2653
+ ._saleBadge_1io44_78 {
1776
2654
  position: absolute;
2655
+ display: flex;
1777
2656
  bottom: var(--space-8);
1778
2657
  left: var(--space-8);
1779
2658
  }
1780
2659
 
1781
2660
  /* Scrim over the whole image, not a corner flag (Figma out-of-stock state). */
1782
- ._oos_1eiri_67 {
2661
+ ._oos_1io44_86 {
1783
2662
  position: absolute;
1784
2663
  inset: 0;
1785
2664
  display: flex;
@@ -1806,13 +2685,13 @@
1806
2685
  * The trim now lives on the text, as it does on the order screens, so the gaps can be the
1807
2686
  * design's own numbers again.
1808
2687
  */
1809
- ._bottom_1eiri_94 {
2688
+ ._bottom_1io44_113 {
1810
2689
  display: flex;
1811
2690
  flex-direction: column;
1812
2691
  gap: var(--space-16);
1813
2692
  }
1814
2693
 
1815
- ._titlePrice_1eiri_81 {
2694
+ ._titlePrice_1io44_100 {
1816
2695
  display: flex;
1817
2696
  flex-direction: column;
1818
2697
  gap: var(--space-16);
@@ -1832,7 +2711,7 @@
1832
2711
  * `text-box-trim` would let us write the design's numbers directly; it is Chrome 133+ and
1833
2712
  * this package still supports the WebView that ships with React 16-era DAZN builds.
1834
2713
  */
1835
- ._title_1eiri_5 {
2714
+ ._title_1io44_5 {
1836
2715
  font-size: var(--type-paragraph-size);
1837
2716
  line-height: 21px;
1838
2717
  padding: 5px 0;
@@ -1866,13 +2745,13 @@
1866
2745
  * Scoped here rather than set on `PriceBlock` itself, which the PDP also renders — its
1867
2746
  * row is measured against a different frame and must not move with this one.
1868
2747
  */
1869
- ._titlePrice_1eiri_81 > :last-child {
2748
+ ._titlePrice_1io44_100 > :last-child {
1870
2749
  line-height: 11px;
1871
2750
  }
1872
2751
 
1873
2752
  /* Colour swatches (Figma product-card): 0.5px-bordered boxes with a 14px colour square;
1874
2753
  the first reads as selected (dark border). */
1875
- ._swatches_1eiri_160 {
2754
+ ._swatches_1io44_179 {
1876
2755
  display: flex;
1877
2756
  gap: var(--space-4);
1878
2757
  align-items: center;
@@ -1882,18 +2761,18 @@
1882
2761
  * 18 on the nose: 14 of colour with 2 either side, and the outline drawn INSIDE that,
1883
2762
  * which is where Figma draws a stroke. As a `border` it sat outside and made the box 19.
1884
2763
  */
1885
- ._swatch_1eiri_160 {
2764
+ ._swatch_1io44_179 {
1886
2765
  display: inline-flex;
1887
2766
  padding: 2px;
1888
2767
  box-shadow: inset 0 0 0 0.5px var(--color-border-subtle);
1889
2768
  border-radius: var(--radius-2);
1890
2769
  }
1891
2770
 
1892
- ._swatchActive_1eiri_177 {
2771
+ ._swatchActive_1io44_196 {
1893
2772
  box-shadow: inset 0 0 0 0.5px var(--color-surface-max);
1894
2773
  }
1895
2774
 
1896
- ._swatchDot_1eiri_181 {
2775
+ ._swatchDot_1io44_200 {
1897
2776
  display: block;
1898
2777
  width: 14px;
1899
2778
  height: 14px;
@@ -1904,11 +2783,11 @@
1904
2783
  * Spotlight card (Figma `size=large`, 3668:12485). Full-bleed with its own 16px gutter —
1905
2784
  * the block that places it adds none — a taller 343:457 image and an 18px title.
1906
2785
  */
1907
- ._large_1eiri_192 {
2786
+ ._large_1io44_211 {
1908
2787
  padding: 0 var(--space-16);
1909
2788
  }
1910
2789
 
1911
- ._large_1eiri_192 ._media_1eiri_15 {
2790
+ ._large_1io44_211 ._media_1io44_15 {
1912
2791
  aspect-ratio: 343 / 457;
1913
2792
  }
1914
2793
 
@@ -1921,7 +2800,7 @@
1921
2800
  * 23 = the cap of 18px text (13) plus the same 10 of leading, so the margins above leave a
1922
2801
  * one-line name 13 tall — the frame's number for this variant.
1923
2802
  */
1924
- ._large_1eiri_192 ._title_1eiri_5 {
2803
+ ._large_1io44_211 ._title_1io44_5 {
1925
2804
  font-size: 18px;
1926
2805
  line-height: 23px;
1927
2806
  min-height: 0;
@@ -1935,14 +2814,14 @@
1935
2814
  * spotlight shows two swatches under its price. Drawn on a 165px card it also cost 34 of
1936
2815
  * the 291 the card is given, which is why the rail ran 55 long before this.
1937
2816
  */
1938
- ._tile_1eiri_7:not(._large_1eiri_192) ._swatches_1eiri_160 {
2817
+ ._tile_1io44_7:not(._large_1io44_211) ._swatches_1io44_179 {
1939
2818
  display: none;
1940
2819
  }
1941
2820
  /*
1942
2821
  * Figma `mobile/limited edition` (5304:77067), 360 tall at 375:
1943
2822
  * 24 above the heading, 28 of heading, 12, a 220 row, 12, a 40 caption, 24 below.
1944
2823
  */
1945
- ._section_1fdjh_5 {
2824
+ ._section_1n5an_5 {
1946
2825
  display: flex;
1947
2826
  flex-direction: column;
1948
2827
  gap: var(--space-12);
@@ -1954,7 +2833,7 @@
1954
2833
  * same 206x28 `header` frame, so they have to measure the same. (`ExploreList`'s heading
1955
2834
  * is the same 20px face in a 26 box; the frames differ, and each follows its own.)
1956
2835
  */
1957
- ._title_1fdjh_17 {
2836
+ ._title_1n5an_17 {
1958
2837
  margin: 0;
1959
2838
  padding: 0 var(--space-16);
1960
2839
  font-size: var(--type-heading-md-size);
@@ -1963,7 +2842,7 @@
1963
2842
  color: var(--color-text-default);
1964
2843
  }
1965
2844
 
1966
- ._link_1fdjh_26 {
2845
+ ._link_1n5an_26 {
1967
2846
  display: flex;
1968
2847
  flex-direction: column;
1969
2848
  gap: var(--space-12);
@@ -1975,7 +2854,7 @@
1975
2854
  * The row scrolls, and the third picture peeks past the fold exactly as the frame draws
1976
2855
  * it: two 165s and a 12 gutter fill the 343 content width, and the next one starts at 354.
1977
2856
  */
1978
- ._track_1fdjh_38 {
2857
+ ._track_1n5an_38 {
1979
2858
  display: flex;
1980
2859
  gap: var(--space-12);
1981
2860
  list-style: none;
@@ -1991,11 +2870,11 @@
1991
2870
  scrollbar-width: none;
1992
2871
  }
1993
2872
 
1994
- ._track_1fdjh_38::-webkit-scrollbar {
2873
+ ._track_1n5an_38::-webkit-scrollbar {
1995
2874
  display: none;
1996
2875
  }
1997
2876
 
1998
- ._frame_1fdjh_58 {
2877
+ ._frame_1n5an_58 {
1999
2878
  position: relative;
2000
2879
  flex: 0 0 auto;
2001
2880
  width: 165px;
@@ -2006,23 +2885,31 @@
2006
2885
  scroll-snap-align: start;
2007
2886
  }
2008
2887
 
2009
- ._image_1fdjh_69 {
2888
+ ._image_1n5an_69 {
2010
2889
  object-fit: cover;
2011
2890
  }
2012
2891
 
2013
- ._placeholder_1fdjh_73 {
2892
+ ._placeholder_1n5an_73 {
2014
2893
  width: 100%;
2015
2894
  height: 100%;
2016
2895
  }
2017
2896
 
2018
- ._saleBadge_1fdjh_78 {
2897
+ /*
2898
+ * `display: flex`, and it is load-bearing. The wrapper is a `span`, so left inline — or
2899
+ * even as a `block` — it builds a LINE box around the 20px badge and reserves the font's
2900
+ * descender room under it: measured 25 against the badge's 20, which put the badge 13px
2901
+ * above the image's edge where the frame draws it 8. A flex container makes the badge a
2902
+ * flex item, and a flex item has no line box.
2903
+ */
2904
+ ._saleBadge_1n5an_85 {
2019
2905
  position: absolute;
2906
+ display: flex;
2020
2907
  bottom: var(--space-8);
2021
2908
  left: var(--space-8);
2022
2909
  }
2023
2910
 
2024
2911
  /* The whole picture dims, as it does on a product card — not a corner flag. */
2025
- ._oos_1fdjh_85 {
2912
+ ._oos_1n5an_93 {
2026
2913
  position: absolute;
2027
2914
  inset: 0;
2028
2915
  display: flex;
@@ -2038,7 +2925,7 @@
2038
2925
  * One caption for the row: the frame's `bottom` is 40 — a 13px name, 16, an 11px price —
2039
2926
  * because the pictures above it are all the same garment.
2040
2927
  */
2041
- ._caption_1fdjh_101 {
2928
+ ._caption_1n5an_109 {
2042
2929
  display: flex;
2043
2930
  flex-direction: column;
2044
2931
  gap: var(--space-16);
@@ -2051,7 +2938,7 @@
2051
2938
  * margin takes back both that padding and the half-leading the trim removes. The frame's
2052
2939
  * name box is 13.
2053
2940
  */
2054
- ._name_1fdjh_114 {
2941
+ ._name_1n5an_122 {
2055
2942
  font-size: 18px;
2056
2943
  line-height: 23px;
2057
2944
  padding: 5px 0;
@@ -2064,7 +2951,7 @@
2064
2951
  }
2065
2952
 
2066
2953
  /* 11 on 16px, the same cap the product card's price row takes. */
2067
- ._price_1fdjh_127 {
2954
+ ._price_1n5an_135 {
2068
2955
  display: flex;
2069
2956
  align-items: baseline;
2070
2957
  gap: var(--space-4);
@@ -2073,13 +2960,13 @@
2073
2960
  font-variant-numeric: tabular-nums;
2074
2961
  }
2075
2962
 
2076
- ._paid_1fdjh_136 {
2963
+ ._paid_1n5an_144 {
2077
2964
  font-weight: var(--font-weight-bold);
2078
2965
  color: var(--color-text-default);
2079
2966
  }
2080
2967
 
2081
2968
  /* Struck, and at the same weight as the live price — `mobile/product-card` again. */
2082
- ._was_1fdjh_142 {
2969
+ ._was_1n5an_150 {
2083
2970
  font-weight: var(--font-weight-bold);
2084
2971
  color: var(--color-text-disabled);
2085
2972
  text-decoration: line-through;
@@ -2381,17 +3268,55 @@
2381
3268
  color: var(--color-text-default);
2382
3269
  font-variant-numeric: tabular-nums;
2383
3270
  }
2384
- ._row_1xbbn_1 {
3271
+ /*
3272
+ * The line is a COLUMN now: the media/detail row, and under it the `Labels` row Figma's
3273
+ * low-stock state adds (4693:67094). `spacer/spacer-xxs` between them, which is what
3274
+ * takes the line from 100 to 130 in the frame.
3275
+ */
3276
+ ._line_1s2s6_6 {
3277
+ display: flex;
3278
+ flex-direction: column;
3279
+ gap: var(--space-6);
3280
+ }
3281
+
3282
+ ._row_1s2s6_12 {
2385
3283
  display: flex;
2386
3284
  gap: var(--space-16);
2387
3285
  align-items: center;
2388
3286
  }
2389
3287
 
2390
- ._pending_1xbbn_7 {
3288
+ ._pending_1s2s6_18 {
2391
3289
  opacity: 0.6;
2392
3290
  }
2393
3291
 
2394
- ._media_1xbbn_11 {
3292
+ /* Full width and its own row, so the label sits under the thumbnail as well as the
3293
+ detail column — not tucked inside the stepper's column, where it used to be. */
3294
+ ._labels_1s2s6_24 {
3295
+ display: flex;
3296
+ align-items: center;
3297
+ gap: var(--space-4);
3298
+ }
3299
+
3300
+ /*
3301
+ * "Only 2 left", in the warning tone. 24px tall: `py-7` around a cap-trimmed 14px line,
3302
+ * which is 7 + 10 + 7. The cap height is stated as the line-height for the same reason it
3303
+ * is everywhere else in this package — Figma's box stops at the cap and a CSS line box
3304
+ * does not.
3305
+ *
3306
+ * Warning, not subtle grey. Scarcity is the one thing on a cart line the fan is meant to
3307
+ * notice before they leave the screen, and it was previously set to be ignored.
3308
+ */
3309
+ ._lowStock_1s2s6_39 {
3310
+ display: inline-flex;
3311
+ align-items: center;
3312
+ padding: 7px 0;
3313
+ font-size: var(--type-trimmed-sm-size);
3314
+ font-weight: var(--font-weight-bold);
3315
+ line-height: 10px;
3316
+ color: var(--color-state-text-warning);
3317
+ }
3318
+
3319
+ ._media_1s2s6_49 {
2395
3320
  position: relative;
2396
3321
  flex-shrink: 0;
2397
3322
  width: 100px;
@@ -2401,18 +3326,26 @@
2401
3326
  background: var(--color-surface-soft);
2402
3327
  }
2403
3328
 
2404
- ._image_1xbbn_21 {
3329
+ ._image_1s2s6_59 {
2405
3330
  object-fit: cover;
2406
3331
  }
2407
3332
 
2408
- ._placeholder_1xbbn_25 {
3333
+ ._placeholder_1s2s6_63 {
2409
3334
  width: 100%;
2410
3335
  height: 100%;
2411
3336
  }
2412
3337
 
2413
3338
  /* Bottom-left over the thumbnail, per the design. */
2414
- ._saleBadge_1xbbn_31 {
3339
+ /*
3340
+ * `display: flex`, and it is load-bearing. The wrapper is a `span`, so left inline — or
3341
+ * even as a `block` — it builds a LINE box around the 20px badge and reserves the font's
3342
+ * descender room under it: measured 25 against the badge's 20, which put the badge 13px
3343
+ * above the image's edge where the frame draws it 6. A flex container makes the badge a
3344
+ * flex item, and a flex item has no line box.
3345
+ */
3346
+ ._saleBadge_1s2s6_76 {
2415
3347
  position: absolute;
3348
+ display: flex;
2416
3349
  left: var(--space-6);
2417
3350
  bottom: var(--space-6);
2418
3351
  }
@@ -2425,7 +3358,7 @@
2425
3358
  *
2426
3359
  * Radius matches the 8px thumbnail rather than the card's 6.
2427
3360
  */
2428
- ._oos_1xbbn_45 {
3361
+ ._oos_1s2s6_91 {
2429
3362
  position: absolute;
2430
3363
  inset: 0;
2431
3364
  display: flex;
@@ -2438,7 +3371,7 @@
2438
3371
  font-weight: var(--font-weight-bold);
2439
3372
  }
2440
3373
 
2441
- ._info_1xbbn_58 {
3374
+ ._info_1s2s6_104 {
2442
3375
  display: flex;
2443
3376
  flex-direction: column;
2444
3377
  gap: var(--space-16);
@@ -2446,47 +3379,66 @@
2446
3379
  min-width: 0;
2447
3380
  }
2448
3381
 
2449
- ._head_1xbbn_66 {
3382
+ ._head_1s2s6_112 {
2450
3383
  display: flex;
2451
3384
  align-items: flex-start;
2452
3385
  justify-content: space-between;
2453
3386
  gap: var(--space-8);
2454
3387
  }
2455
3388
 
2456
- ._meta_1xbbn_73 {
3389
+ ._meta_1s2s6_119 {
2457
3390
  display: flex;
2458
3391
  flex-direction: column;
2459
3392
  gap: var(--space-12);
2460
3393
  min-width: 0;
2461
3394
  }
2462
3395
 
2463
- ._title_1xbbn_80 {
3396
+ /*
3397
+ * ONE line, ellipsised, and trimmed to the cap.
3398
+ *
3399
+ * Figma's `Product info` sets `whitespace-nowrap` and the title `text-ellipsis`, so a long
3400
+ * catalogue name is cut rather than wrapped. Ours clamped to two lines, and the second
3401
+ * line is what made every cart line 6.5px taller than the frame draws it — the detail
3402
+ * column overflowed the 100px thumbnail that is supposed to set the row's height.
3403
+ *
3404
+ * The cap-trim pair is the idiom this package uses everywhere (see `ProductTile.title`):
3405
+ * `line-height` is the design's box — 11 of cap on 16px text — and the padding gives the
3406
+ * descenders room inside the clip box that `text-overflow` needs, while the negative
3407
+ * margin takes that room back out of the layout. Measured in a browser at 375: title box
3408
+ * 24.8 -> 11, and the line 106.5 -> 100.
3409
+ */
3410
+ ._title_1s2s6_134 {
2464
3411
  font-size: var(--type-trimmed-md-size);
2465
3412
  font-weight: var(--font-weight-bold);
2466
- /* Product titles are catalogue copy and can run long; unbounded, the title pushes the
2467
- price out of alignment down the list. */
2468
- display: -webkit-box;
2469
- -webkit-line-clamp: 2;
2470
- -webkit-box-orient: vertical;
3413
+ line-height: 11px;
3414
+ padding: 7px 0;
3415
+ margin: -7px 0;
2471
3416
  overflow: hidden;
3417
+ text-overflow: ellipsis;
3418
+ white-space: nowrap;
2472
3419
  }
2473
3420
 
2474
3421
  /* "Color: White Size: M" */
2475
- ._details_1xbbn_92 {
3422
+ ._details_1s2s6_152 {
2476
3423
  display: flex;
2477
3424
  flex-wrap: wrap;
2478
3425
  gap: var(--space-6);
2479
3426
  min-width: 0;
2480
3427
  }
2481
3428
 
2482
- ._detail_1xbbn_92 {
3429
+ /* 10 of cap on 14px, same trim. Nothing clips these, so the descenders simply hang out
3430
+ of the box and are drawn — exactly as they are in the frame. */
3431
+ ._detail_1s2s6_152 {
2483
3432
  font-size: var(--type-trimmed-sm-size);
2484
3433
  font-weight: var(--font-weight-regular);
3434
+ line-height: 10px;
3435
+ padding: 6px 0;
3436
+ margin: -6px 0;
2485
3437
  color: var(--color-text-subtle);
2486
3438
  white-space: nowrap;
2487
3439
  }
2488
3440
 
2489
- ._price_1xbbn_106 {
3441
+ ._price_1s2s6_171 {
2490
3442
  display: flex;
2491
3443
  flex-direction: column;
2492
3444
  align-items: flex-end;
@@ -2494,15 +3446,21 @@
2494
3446
  flex-shrink: 0;
2495
3447
  }
2496
3448
 
2497
- ._amount_1xbbn_114 {
3449
+ ._amount_1s2s6_179 {
2498
3450
  font-size: var(--type-trimmed-md-size);
2499
3451
  font-weight: var(--font-weight-bold);
3452
+ line-height: 11px;
3453
+ padding: 7px 0;
3454
+ margin: -7px 0;
2500
3455
  white-space: nowrap;
2501
3456
  }
2502
3457
 
2503
- ._was_1xbbn_120 {
3458
+ ._was_1s2s6_188 {
2504
3459
  font-size: var(--type-trimmed-sm-size);
2505
3460
  font-weight: var(--font-weight-regular);
3461
+ line-height: 10px;
3462
+ padding: 6px 0;
3463
+ margin: -6px 0;
2506
3464
  color: var(--color-text-disabled);
2507
3465
  text-decoration: line-through;
2508
3466
  white-space: nowrap;
@@ -2676,49 +3634,56 @@
2676
3634
  gap: var(--space-20);
2677
3635
  }
2678
3636
 
2679
- ._gallery_1e69n_1 {
3637
+ ._gallery_10mch_1 {
2680
3638
  position: relative;
2681
3639
  display: flex;
2682
3640
  flex-direction: column;
2683
3641
  gap: var(--space-12);
2684
3642
  }
2685
3643
 
2686
- ._track_1e69n_8 {
3644
+ ._track_10mch_8 {
2687
3645
  display: flex;
2688
3646
  overflow-x: auto;
2689
3647
  scroll-snap-type: x mandatory;
2690
3648
  -webkit-overflow-scrolling: touch;
2691
- /* Hero media is 375×485 (portrait) and fully sharp (no rounded corners) — it sits
2692
- edge-to-edge and flush under the header. */
2693
- aspect-ratio: 375 / 485;
3649
+ /*
3650
+ * Hero media is 375x475 (portrait) and fully sharp (no rounded corners) — it sits
3651
+ * edge-to-edge and flush under the header.
3652
+ *
3653
+ * 475, not the 485 this had. That number came from `pdp` (3601:2479), which ADR-0022
3654
+ * superseded: every frame in the design of record puts the `img` at 375x475 — `full
3655
+ * PDP`, all three `States > PDP` frames, and the scrolled one. Ten pixels, on the
3656
+ * tallest element of the tallest screen, and everything below it moved with it.
3657
+ */
3658
+ aspect-ratio: 375 / 475;
2694
3659
  background: var(--color-surface-soft);
2695
3660
  /* Same as the review carousel: the dots below are the indicator. */
2696
3661
  scrollbar-width: none;
2697
3662
  }
2698
3663
 
2699
- ._track_1e69n_8::-webkit-scrollbar {
3664
+ ._track_10mch_8::-webkit-scrollbar {
2700
3665
  display: none;
2701
3666
  }
2702
3667
 
2703
- ._slide_1e69n_25 {
3668
+ ._slide_10mch_32 {
2704
3669
  position: relative;
2705
3670
  flex: 0 0 100%;
2706
3671
  scroll-snap-align: center;
2707
- aspect-ratio: 375 / 485;
3672
+ aspect-ratio: 375 / 475;
2708
3673
  }
2709
3674
 
2710
- ._image_1e69n_32 {
3675
+ ._image_10mch_39 {
2711
3676
  object-fit: cover;
2712
3677
  }
2713
3678
 
2714
- ._placeholder_1e69n_36 {
3679
+ ._placeholder_10mch_43 {
2715
3680
  width: 100%;
2716
- aspect-ratio: 375 / 485;
3681
+ aspect-ratio: 375 / 475;
2717
3682
  background: var(--color-surface-soft);
2718
3683
  }
2719
3684
 
2720
3685
  /* Share button — top-right chrome over the image (mobile/button: 32px, soft, radius-8). */
2721
- ._share_1e69n_43 {
3686
+ ._share_10mch_50 {
2722
3687
  position: absolute;
2723
3688
  top: var(--space-16);
2724
3689
  right: var(--space-16);
@@ -2735,13 +3700,13 @@
2735
3700
  cursor: pointer;
2736
3701
  }
2737
3702
 
2738
- ._dots_1e69n_60 {
3703
+ ._dots_10mch_67 {
2739
3704
  display: flex;
2740
3705
  justify-content: center;
2741
3706
  gap: var(--space-6);
2742
3707
  }
2743
3708
 
2744
- ._dot_1e69n_60 {
3709
+ ._dot_10mch_67 {
2745
3710
  width: 8px;
2746
3711
  height: 8px;
2747
3712
  padding: 0;
@@ -2753,13 +3718,13 @@
2753
3718
  position: relative;
2754
3719
  }
2755
3720
 
2756
- ._dot_1e69n_60::after {
3721
+ ._dot_10mch_67::after {
2757
3722
  content: '';
2758
3723
  position: absolute;
2759
3724
  inset: -18px;
2760
3725
  }
2761
3726
 
2762
- ._dotActive_1e69n_84 {
3727
+ ._dotActive_10mch_91 {
2763
3728
  background: var(--color-surface-max);
2764
3729
  }
2765
3730
  /*
@@ -2769,7 +3734,7 @@
2769
3734
  * The body's blocks are all 20 apart: title, unit control, table, note, "How to measure",
2770
3735
  * fabric. Everything below is that rhythm and the geometry inside each block.
2771
3736
  */
2772
- ._scrim_v44fk_8 {
3737
+ ._scrim_ddqa4_8 {
2773
3738
  position: fixed;
2774
3739
  inset: 0;
2775
3740
  z-index: 60;
@@ -2780,10 +3745,10 @@
2780
3745
  cart and menu sheets are drawn over. Theirs are literals of the same intent written
2781
3746
  before the variable was published; this one follows the variable. */
2782
3747
  background: rgba(12, 22, 28, 0.32);
2783
- animation: _fade_v44fk_1 160ms ease-out;
3748
+ animation: _fade_ddqa4_1 160ms ease-out;
2784
3749
  }
2785
3750
 
2786
- ._sheet_v44fk_2 {
3751
+ ._sheet_ddqa4_2 {
2787
3752
  display: flex;
2788
3753
  flex-direction: column;
2789
3754
  width: 100%;
@@ -2796,68 +3761,12 @@
2796
3761
  and `xs`, and this corner is neither. */
2797
3762
  border-radius: 16px 16px 0 0;
2798
3763
  background: #ffffff;
2799
- animation: _rise_v44fk_1 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
2800
- }
2801
-
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;
2827
- height: 4px;
2828
- border-radius: var(--radius-full);
2829
- /* `semantic/base/surface/bold`. */
2830
- background: #6d7377;
2831
- }
2832
-
2833
- ._closeSlot_v44fk_69 {
2834
- display: inline-flex;
2835
- align-items: center;
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);
3764
+ animation: _rise_ddqa4_1 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
2856
3765
  }
2857
3766
 
2858
3767
  /* ── Body ──────────────────────────────────────────────────────────────────── */
2859
3768
 
2860
- ._body_v44fk_96 {
3769
+ ._body_ddqa4_40 {
2861
3770
  flex: 1 1 auto;
2862
3771
  overflow-y: auto;
2863
3772
  display: flex;
@@ -2873,11 +3782,11 @@
2873
3782
  * excess and the chart came out 14 short of the 256 the design draws. The body scrolls;
2874
3783
  * its blocks keep their size.
2875
3784
  */
2876
- ._body_v44fk_96 > * {
3785
+ ._body_ddqa4_40 > * {
2877
3786
  flex-shrink: 0;
2878
3787
  }
2879
3788
 
2880
- ._titles_v44fk_116 {
3789
+ ._titles_ddqa4_60 {
2881
3790
  display: flex;
2882
3791
  flex-direction: column;
2883
3792
  gap: var(--space-2);
@@ -2885,7 +3794,7 @@
2885
3794
 
2886
3795
  /* `heading/md` at 1.32 — the library's 1.32, not our `--type-heading-md-line`, which is
2887
3796
  1.25 and is the base h2 default the whole package inherits. */
2888
- ._title_v44fk_116 {
3797
+ ._title_ddqa4_60 {
2889
3798
  margin: 0;
2890
3799
  font-size: var(--type-heading-md-size);
2891
3800
  line-height: 1.32;
@@ -2893,7 +3802,7 @@
2893
3802
  color: var(--color-text-default);
2894
3803
  }
2895
3804
 
2896
- ._subtitle_v44fk_132 {
3805
+ ._subtitle_ddqa4_76 {
2897
3806
  margin: 0;
2898
3807
  font-size: var(--type-caption-sm-size);
2899
3808
  line-height: var(--type-caption-sm-line);
@@ -2906,7 +3815,7 @@
2906
3815
  * `Segmented Control` (4882:56556): 190 x 40, a 9 radius the scale does not carry, and 4
2907
3816
  * of horizontal padding around two halves.
2908
3817
  */
2909
- ._units_v44fk_145 {
3818
+ ._units_ddqa4_89 {
2910
3819
  display: flex;
2911
3820
  align-items: center;
2912
3821
  width: 190px;
@@ -2921,7 +3830,7 @@
2921
3830
  * and its content centred, so the trim is what decides whether the CAP box or the line box
2922
3831
  * is the thing being centred — and the design centres the cap.
2923
3832
  */
2924
- ._unit_v44fk_145 {
3833
+ ._unit_ddqa4_89 {
2925
3834
  flex: 1 1 0;
2926
3835
  display: inline-flex;
2927
3836
  align-items: center;
@@ -2940,7 +3849,7 @@
2940
3849
 
2941
3850
  /* Four shorter than its neighbour, and that is the component rather than a slip: the
2942
3851
  selected half carries its own 2 of vertical padding inside the track's 36. */
2943
- ._unitOn_v44fk_179 {
3852
+ ._unitOn_ddqa4_123 {
2944
3853
  height: 32px;
2945
3854
  background: var(--color-surface-neutral);
2946
3855
  font-weight: var(--font-weight-bold);
@@ -2948,7 +3857,7 @@
2948
3857
 
2949
3858
  /* A half-pixel hairline drawn INSIDE the pill, as every Figma stroke is — hence `inset`
2950
3859
  rather than a border, which CSS would draw around it and make the pill 37 tall. */
2951
- ._unitOff_v44fk_187 {
3860
+ ._unitOff_ddqa4_131 {
2952
3861
  box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, 0.04);
2953
3862
  font-weight: var(--font-weight-regular);
2954
3863
  }
@@ -2957,11 +3866,11 @@
2957
3866
 
2958
3867
  /* Wider than the sheet on a narrow phone or a long chart, so it scrolls inside its own
2959
3868
  container rather than making the sheet scroll sideways. */
2960
- ._tableWrap_v44fk_196 {
3869
+ ._tableWrap_ddqa4_140 {
2961
3870
  overflow-x: auto;
2962
3871
  }
2963
3872
 
2964
- ._table_v44fk_196 {
3873
+ ._table_ddqa4_140 {
2965
3874
  width: 100%;
2966
3875
  /* `separate` with no spacing, not `collapse`: collapsed borders cannot carry the
2967
3876
  header's rounded top corners. */
@@ -2982,11 +3891,11 @@
2982
3891
  * 93%, and Chrome scaled all five back up to an equal fifth. Same trap `ShopSurface`
2983
3892
  * documents on its base headings.
2984
3893
  */
2985
- ._col_v44fk_221 {
3894
+ ._col_ddqa4_165 {
2986
3895
  width: 18.6006%;
2987
3896
  }
2988
3897
 
2989
- ._colEdge_v44fk_225 {
3898
+ ._colEdge_ddqa4_169 {
2990
3899
  width: 22.0991%;
2991
3900
  }
2992
3901
 
@@ -2996,7 +3905,7 @@
2996
3905
  * variable behind either, and `border/soft` and `text/subtle` are visibly different
2997
3906
  * greys.
2998
3907
  */
2999
- ._table_v44fk_196 thead th {
3908
+ ._table_ddqa4_140 thead th {
3000
3909
  height: 36px;
3001
3910
  padding: 0;
3002
3911
  background: #f5f5f5;
@@ -3008,21 +3917,21 @@
3008
3917
  text-align: center;
3009
3918
  }
3010
3919
 
3011
- ._table_v44fk_196 thead th:first-child {
3920
+ ._table_ddqa4_140 thead th:first-child {
3012
3921
  padding-left: var(--space-12);
3013
3922
  border-top-left-radius: var(--radius-8);
3014
3923
  text-align: left;
3015
3924
  }
3016
3925
 
3017
- ._table_v44fk_196 thead th:last-child {
3926
+ ._table_ddqa4_140 thead th:last-child {
3018
3927
  padding-right: var(--space-12);
3019
3928
  border-top-right-radius: var(--radius-8);
3020
3929
  }
3021
3930
 
3022
3931
  /* 13px, which is not on the type scale — the design uses a detached style here rather
3023
3932
  than a token, and 12 or 14 both miss the row. */
3024
- ._table_v44fk_196 tbody th,
3025
- ._table_v44fk_196 tbody td {
3933
+ ._table_ddqa4_140 tbody th,
3934
+ ._table_ddqa4_140 tbody td {
3026
3935
  height: 44px;
3027
3936
  padding: 0;
3028
3937
  border-bottom: 1px solid var(--color-surface-soft);
@@ -3033,20 +3942,20 @@
3033
3942
  text-align: center;
3034
3943
  }
3035
3944
 
3036
- ._table_v44fk_196 tbody th {
3945
+ ._table_ddqa4_140 tbody th {
3037
3946
  padding-left: var(--space-12);
3038
3947
  font-weight: var(--font-weight-bold);
3039
3948
  text-align: left;
3040
3949
  }
3041
3950
 
3042
- ._table_v44fk_196 tbody td:last-child {
3951
+ ._table_ddqa4_140 tbody td:last-child {
3043
3952
  padding-right: var(--space-12);
3044
3953
  }
3045
3954
 
3046
3955
  /* No rule under the last row: the table would otherwise be underlined, and the note that
3047
3956
  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 {
3957
+ ._table_ddqa4_140 tbody tr:last-child th,
3958
+ ._table_ddqa4_140 tbody tr:last-child td {
3050
3959
  border-bottom: 0;
3051
3960
  }
3052
3961
 
@@ -3054,7 +3963,7 @@
3054
3963
 
3055
3964
  /* `caption/xs` — the same 12px face as `trimmed/xs` on a 1.52 leading rather than a
3056
3965
  trimmed box, which is why the line-height is written out. */
3057
- ._note_v44fk_293 {
3966
+ ._note_ddqa4_237 {
3058
3967
  margin: 0;
3059
3968
  padding: var(--space-8) var(--space-12);
3060
3969
  border-radius: var(--radius-8);
@@ -3066,13 +3975,13 @@
3066
3975
 
3067
3976
  /* ── How to measure ────────────────────────────────────────────────────────── */
3068
3977
 
3069
- ._how_v44fk_305 {
3978
+ ._how_ddqa4_249 {
3070
3979
  display: flex;
3071
3980
  flex-direction: column;
3072
3981
  gap: var(--space-16);
3073
3982
  }
3074
3983
 
3075
- ._howTitle_v44fk_311 {
3984
+ ._howTitle_ddqa4_255 {
3076
3985
  margin: 0;
3077
3986
  font-size: var(--type-heading-sm-size);
3078
3987
  line-height: var(--type-heading-sm-line);
@@ -3080,14 +3989,14 @@
3080
3989
  color: #0d0d0d;
3081
3990
  }
3082
3991
 
3083
- ._howList_v44fk_319 {
3992
+ ._howList_ddqa4_263 {
3084
3993
  margin: 0;
3085
3994
  display: flex;
3086
3995
  flex-direction: column;
3087
3996
  gap: var(--space-8);
3088
3997
  }
3089
3998
 
3090
- ._howItem_v44fk_326 {
3999
+ ._howItem_ddqa4_270 {
3091
4000
  display: flex;
3092
4001
  flex-direction: column;
3093
4002
  gap: var(--space-8);
@@ -3100,7 +4009,7 @@
3100
4009
  * separates with the hairline drawn on that boundary — the negative margin takes the pixel
3101
4010
  * back out of the layout so the pair stays 16 rather than becoming 17.
3102
4011
  */
3103
- ._howItem_v44fk_326 + ._howItem_v44fk_326 {
4012
+ ._howItem_ddqa4_270 + ._howItem_ddqa4_270 {
3104
4013
  margin-top: -1px;
3105
4014
  padding-top: var(--space-8);
3106
4015
  border-top: 1px solid var(--color-surface-soft);
@@ -3112,7 +4021,7 @@
3112
4021
  * length" clear of anything that clips, and the margin takes that padding back out of the
3113
4022
  * layout so the box measures the 9 the frame gives it.
3114
4023
  */
3115
- ._howLabel_v44fk_351 {
4024
+ ._howLabel_ddqa4_295 {
3116
4025
  padding: 5px 0;
3117
4026
  margin: -5px 0;
3118
4027
  font-size: var(--type-trimmed-xs-size);
@@ -3122,7 +4031,7 @@
3122
4031
  color: #0d0d0d;
3123
4032
  }
3124
4033
 
3125
- ._howText_v44fk_361 {
4034
+ ._howText_ddqa4_305 {
3126
4035
  margin: 0;
3127
4036
  font-size: var(--type-trimmed-xs-size);
3128
4037
  line-height: 1.52;
@@ -3131,7 +4040,7 @@
3131
4040
 
3132
4041
  /* ── Fabric ────────────────────────────────────────────────────────────────── */
3133
4042
 
3134
- ._fabric_v44fk_370 {
4043
+ ._fabric_ddqa4_314 {
3135
4044
  display: flex;
3136
4045
  flex-direction: column;
3137
4046
  gap: var(--space-2);
@@ -3139,7 +4048,7 @@
3139
4048
 
3140
4049
  /* `caption/xs-bold`, not the trimmed style the "How to measure" labels use: the frame's
3141
4050
  box is 18, which is the full 1.52 line rather than a cap. */
3142
- ._fabricLabel_v44fk_378 {
4051
+ ._fabricLabel_ddqa4_322 {
3143
4052
  margin: 0;
3144
4053
  font-size: var(--type-trimmed-xs-size);
3145
4054
  line-height: 1.52;
@@ -3147,7 +4056,7 @@
3147
4056
  color: #0d0d0d;
3148
4057
  }
3149
4058
 
3150
- ._fabricText_v44fk_386 {
4059
+ ._fabricText_ddqa4_330 {
3151
4060
  margin: 0;
3152
4061
  font-size: var(--type-trimmed-xs-size);
3153
4062
  line-height: 1.52;
@@ -3158,7 +4067,7 @@
3158
4067
 
3159
4068
  /* Not in the frame. Guides carried these before there was a chart to carry instead, and a
3160
4069
  payload that still has them is still worth drawing. */
3161
- ._notes_v44fk_397 {
4070
+ ._notes_ddqa4_341 {
3162
4071
  margin: 0;
3163
4072
  padding-left: var(--space-16);
3164
4073
  display: flex;
@@ -3169,7 +4078,7 @@
3169
4078
  color: var(--color-text-subtle);
3170
4079
  }
3171
4080
 
3172
- @keyframes _fade_v44fk_1 {
4081
+ @keyframes _fade_ddqa4_1 {
3173
4082
  from {
3174
4083
  opacity: 0;
3175
4084
  }
@@ -3178,7 +4087,7 @@
3178
4087
  }
3179
4088
  }
3180
4089
 
3181
- @keyframes _rise_v44fk_1 {
4090
+ @keyframes _rise_ddqa4_1 {
3182
4091
  from {
3183
4092
  transform: translateY(12%);
3184
4093
  }
@@ -3188,8 +4097,8 @@
3188
4097
  }
3189
4098
 
3190
4099
  @media (prefers-reduced-motion: reduce) {
3191
- ._scrim_v44fk_8,
3192
- ._sheet_v44fk_2 {
4100
+ ._scrim_ddqa4_8,
4101
+ ._sheet_ddqa4_2 {
3193
4102
  animation: none;
3194
4103
  }
3195
4104
  }
@@ -3280,30 +4189,34 @@
3280
4189
  ._chevron_9zj90_85 {
3281
4190
  display: block;
3282
4191
  }
3283
- ._root_1j4n8_1 {
4192
+ ._root_1h4ny_1 {
3284
4193
  display: flex;
3285
4194
  flex-direction: column;
3286
4195
  gap: var(--space-12);
3287
4196
  }
3288
4197
 
3289
- ._header_1j4n8_7 {
4198
+ /* "Color: White" — cap-trimmed like every label in this column, so the block measures the
4199
+ frame's 128 rather than 142. */
4200
+ ._header_1h4ny_9 {
3290
4201
  margin: 0;
3291
4202
  display: flex;
4203
+ align-items: center;
3292
4204
  gap: var(--space-4);
3293
4205
  font-size: var(--type-trimmed-md-size);
4206
+ line-height: var(--type-trimmed-md-line);
3294
4207
  }
3295
4208
 
3296
- ._title_1j4n8_14 {
4209
+ ._title_1h4ny_18 {
3297
4210
  font-weight: var(--font-weight-bold);
3298
4211
  color: var(--color-text-default);
3299
4212
  }
3300
4213
 
3301
- ._value_1j4n8_19 {
4214
+ ._value_1h4ny_23 {
3302
4215
  font-weight: var(--font-weight-regular);
3303
4216
  color: var(--color-text-subtle);
3304
4217
  }
3305
4218
 
3306
- ._tiles_1j4n8_24 {
4219
+ ._tiles_1h4ny_28 {
3307
4220
  display: flex;
3308
4221
  flex-wrap: wrap;
3309
4222
  gap: var(--space-8);
@@ -3314,7 +4227,7 @@
3314
4227
  * overhanging the top edge, so clipping here would shave it in half. `.media` is the
3315
4228
  * clipped box instead, which keeps the image inside the radius.
3316
4229
  */
3317
- ._tile_1j4n8_24 {
4230
+ ._tile_1h4ny_28 {
3318
4231
  position: relative;
3319
4232
  width: 79px;
3320
4233
  height: 105px;
@@ -3327,11 +4240,11 @@
3327
4240
  cursor: pointer;
3328
4241
  }
3329
4242
 
3330
- ._selected_1j4n8_48 {
4243
+ ._selected_1h4ny_52 {
3331
4244
  border-color: var(--color-surface-max);
3332
4245
  }
3333
4246
 
3334
- ._media_1j4n8_32 {
4247
+ ._media_1h4ny_36 {
3335
4248
  position: absolute;
3336
4249
  inset: 0;
3337
4250
  border-radius: var(--radius-8);
@@ -3339,11 +4252,11 @@
3339
4252
  background: var(--color-surface-soft);
3340
4253
  }
3341
4254
 
3342
- ._image_1j4n8_60 {
4255
+ ._image_1h4ny_64 {
3343
4256
  object-fit: cover;
3344
4257
  }
3345
4258
 
3346
- ._placeholder_1j4n8_64 {
4259
+ ._placeholder_1h4ny_68 {
3347
4260
  position: absolute;
3348
4261
  inset: 0;
3349
4262
  background: var(--color-surface-soft);
@@ -3351,7 +4264,7 @@
3351
4264
 
3352
4265
  /* Sold-out: full dark scrim with white label (Figma color/tile state=sold-out). The tile
3353
4266
  stays tappable — see the component docblock. */
3354
- ._scrim_1j4n8_72 {
4267
+ ._scrim_1h4ny_76 {
3355
4268
  position: absolute;
3356
4269
  inset: 0;
3357
4270
  display: flex;
@@ -3370,7 +4283,7 @@
3370
4283
  * proud of the top edge — so it reads as a tag pinned to the tile rather than a label
3371
4284
  * inside it. `pointer-events: none` keeps it from swallowing taps meant for the tile.
3372
4285
  */
3373
- ._stockBadge_1j4n8_91 {
4286
+ ._stockBadge_1h4ny_95 {
3374
4287
  position: absolute;
3375
4288
  top: -10px;
3376
4289
  left: 50px;