@hjmds/react 1.34.0 → 1.35.1

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.
Files changed (141) hide show
  1. package/dist/actions.d.ts +23 -2
  2. package/dist/actions.d.ts.map +1 -1
  3. package/dist/actions.js +61 -6
  4. package/dist/actions.js.map +1 -1
  5. package/dist/advanced-display.d.ts +35 -2
  6. package/dist/advanced-display.d.ts.map +1 -1
  7. package/dist/advanced-display.js +28 -9
  8. package/dist/advanced-display.js.map +1 -1
  9. package/dist/anchor.d.ts +3 -1
  10. package/dist/anchor.d.ts.map +1 -1
  11. package/dist/anchor.js +5 -5
  12. package/dist/anchor.js.map +1 -1
  13. package/dist/auth-screen.d.ts.map +1 -1
  14. package/dist/auth-screen.js +5 -2
  15. package/dist/auth-screen.js.map +1 -1
  16. package/dist/avatar-blobatar-motion.d.ts.map +1 -1
  17. package/dist/avatar-blobatar-motion.js +2 -1
  18. package/dist/avatar-blobatar-motion.js.map +1 -1
  19. package/dist/avatar-blobatar.d.ts.map +1 -1
  20. package/dist/avatar-blobatar.js +2 -1
  21. package/dist/avatar-blobatar.js.map +1 -1
  22. package/dist/bottom-cta.d.ts +8 -1
  23. package/dist/bottom-cta.d.ts.map +1 -1
  24. package/dist/bottom-cta.js +6 -2
  25. package/dist/bottom-cta.js.map +1 -1
  26. package/dist/carousel-motion.d.ts.map +1 -1
  27. package/dist/carousel-motion.js +11 -2
  28. package/dist/carousel-motion.js.map +1 -1
  29. package/dist/carousel.d.ts +10 -0
  30. package/dist/carousel.d.ts.map +1 -1
  31. package/dist/carousel.js +23 -7
  32. package/dist/carousel.js.map +1 -1
  33. package/dist/collapsible.d.ts +6 -0
  34. package/dist/collapsible.d.ts.map +1 -1
  35. package/dist/collapsible.js +22 -20
  36. package/dist/collapsible.js.map +1 -1
  37. package/dist/collection-editing.d.ts +3 -1
  38. package/dist/collection-editing.d.ts.map +1 -1
  39. package/dist/collection-editing.js +5 -5
  40. package/dist/collection-editing.js.map +1 -1
  41. package/dist/collection-rail.d.ts +4 -4
  42. package/dist/collection-rail.d.ts.map +1 -1
  43. package/dist/collection-rail.js.map +1 -1
  44. package/dist/conversation-row.d.ts.map +1 -1
  45. package/dist/conversation-row.js +4 -1
  46. package/dist/conversation-row.js.map +1 -1
  47. package/dist/data-table.d.ts +2 -0
  48. package/dist/data-table.d.ts.map +1 -1
  49. package/dist/data-table.js +2 -2
  50. package/dist/data-table.js.map +1 -1
  51. package/dist/display.d.ts +60 -5
  52. package/dist/display.d.ts.map +1 -1
  53. package/dist/display.js +32 -9
  54. package/dist/display.js.map +1 -1
  55. package/dist/evidence.d.ts +1 -1
  56. package/dist/evidence.d.ts.map +1 -1
  57. package/dist/evidence.js +2 -1
  58. package/dist/evidence.js.map +1 -1
  59. package/dist/feedback.d.ts +5 -0
  60. package/dist/feedback.d.ts.map +1 -1
  61. package/dist/feedback.js +7 -5
  62. package/dist/feedback.js.map +1 -1
  63. package/dist/floating-action-button.js +1 -1
  64. package/dist/floating-action-button.js.map +1 -1
  65. package/dist/forms.d.ts.map +1 -1
  66. package/dist/forms.js +4 -4
  67. package/dist/forms.js.map +1 -1
  68. package/dist/image-choice.js +3 -3
  69. package/dist/image-choice.js.map +1 -1
  70. package/dist/index.d.ts +5 -4
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +5 -4
  73. package/dist/index.js.map +1 -1
  74. package/dist/internal/initial-focus.d.ts +6 -0
  75. package/dist/internal/initial-focus.d.ts.map +1 -1
  76. package/dist/internal/initial-focus.js +6 -0
  77. package/dist/internal/initial-focus.js.map +1 -1
  78. package/dist/internal/pending-content.d.ts +19 -0
  79. package/dist/internal/pending-content.d.ts.map +1 -0
  80. package/dist/internal/pending-content.js +34 -0
  81. package/dist/internal/pending-content.js.map +1 -0
  82. package/dist/internal/screen-footer.d.ts +4 -2
  83. package/dist/internal/screen-footer.d.ts.map +1 -1
  84. package/dist/internal/screen-footer.js +2 -2
  85. package/dist/internal/screen-footer.js.map +1 -1
  86. package/dist/internal.d.ts +9 -1
  87. package/dist/internal.d.ts.map +1 -1
  88. package/dist/internal.js +4 -0
  89. package/dist/internal.js.map +1 -1
  90. package/dist/navigation.d.ts.map +1 -1
  91. package/dist/navigation.js +58 -4
  92. package/dist/navigation.js.map +1 -1
  93. package/dist/number-field.d.ts.map +1 -1
  94. package/dist/number-field.js +4 -3
  95. package/dist/number-field.js.map +1 -1
  96. package/dist/overlays.d.ts +4 -0
  97. package/dist/overlays.d.ts.map +1 -1
  98. package/dist/overlays.js +46 -18
  99. package/dist/overlays.js.map +1 -1
  100. package/dist/public-exports.generated.d.ts +6 -0
  101. package/dist/public-exports.generated.d.ts.map +1 -1
  102. package/dist/public-exports.generated.js +18 -0
  103. package/dist/public-exports.generated.js.map +1 -1
  104. package/dist/screen-flows.d.ts +13 -5
  105. package/dist/screen-flows.d.ts.map +1 -1
  106. package/dist/screen-flows.js +25 -14
  107. package/dist/screen-flows.js.map +1 -1
  108. package/dist/screens.d.ts +18 -5
  109. package/dist/screens.d.ts.map +1 -1
  110. package/dist/screens.js +22 -11
  111. package/dist/screens.js.map +1 -1
  112. package/dist/selection.d.ts +22 -0
  113. package/dist/selection.d.ts.map +1 -1
  114. package/dist/selection.js +32 -9
  115. package/dist/selection.js.map +1 -1
  116. package/dist/shortcut-rail.d.ts +27 -0
  117. package/dist/shortcut-rail.d.ts.map +1 -0
  118. package/dist/shortcut-rail.js +37 -0
  119. package/dist/shortcut-rail.js.map +1 -0
  120. package/dist/steps.d.ts +5 -2
  121. package/dist/steps.d.ts.map +1 -1
  122. package/dist/steps.js +3 -3
  123. package/dist/steps.js.map +1 -1
  124. package/dist/styles.css +223 -48
  125. package/dist/styles.layered.css +223 -48
  126. package/dist/task-list.d.ts +3 -1
  127. package/dist/task-list.d.ts.map +1 -1
  128. package/dist/task-list.js +2 -2
  129. package/dist/task-list.js.map +1 -1
  130. package/dist/theme.d.ts.map +1 -1
  131. package/dist/theme.js +1 -0
  132. package/dist/theme.js.map +1 -1
  133. package/dist/time-picker.d.ts +9 -0
  134. package/dist/time-picker.d.ts.map +1 -0
  135. package/dist/time-picker.js +74 -0
  136. package/dist/time-picker.js.map +1 -0
  137. package/dist/top-bar.d.ts +4 -0
  138. package/dist/top-bar.d.ts.map +1 -1
  139. package/dist/top-bar.js +2 -2
  140. package/dist/top-bar.js.map +1 -1
  141. package/package.json +26 -15
package/dist/steps.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"steps.js","sourceRoot":"","sources":["../src/steps.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n resolveStepsDescriptor,\n stepsRecipe,\n type ComposeStepsAccessibleName,\n type StepStatus,\n type StepsDescriptor,\n type StepsStatusLabels,\n} from \"@hjmds/design-contracts/components/steps\";\nimport { forwardRef, useId, type HTMLAttributes, type ReactNode } from \"react\";\n\nimport { classNames } from \"./internal.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\nexport type StepsProps<Id extends string = string> = Omit<\n HTMLAttributes<HTMLOListElement>,\n \"children\"\n> & Readonly<{\n descriptor: StepsDescriptor<Id>;\n statusLabels: StepsStatusLabels;\n composeAccessibleName: ComposeStepsAccessibleName;\n renderMark?: (status: StepStatus, position: number) => ReactNode;\n /**\n * Return to a step before the cursor (2026-10-18, spint compose). Only those steps become buttons; the cursor and\n * later steps stay static so the flow never skips forward past validation. Omit it while the flow is locked.\n */\n onStepPress?: (id: Id) => void;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\n/** Linear progress steps with one canonical cursor; steps before it can be pressed to go back. */\nexport const Steps = forwardRef<HTMLOListElement, StepsProps>(function Steps(\n { descriptor, statusLabels, composeAccessibleName, renderMark, onStepPress, className, layoutStyle, ...props },\n ref,\n) {\n const steps = resolveStepsDescriptor(descriptor, { statusLabels, composeAccessibleName });\n const statusId = useId();\n return (\n <ol {...props} style={{ [\"--hjm-steps-press-target\" as string]: `${stepsRecipe.press.minTouchTarget}px`, ...props.style, ...layoutStyle }} ref={ref} className={classNames(\"hjm-steps\", className)}>\n {steps.map((step, index) => {\n const content = <>\n <div className=\"hjm-steps__rail\" aria-hidden=\"true\">\n <span className=\"hjm-steps__indicator\">\n {renderMark?.(step.status, step.position) ?? (\n step.status === \"complete\" ? \"✓\" : step.status === \"error\" ? \"!\" : step.position\n )}\n </span>\n {index === steps.length - 1 ? null : <span className=\"hjm-steps__connector\" />}\n </div>\n <div className=\"hjm-steps__copy\">\n <span className=\"hjm-steps__label\">{step.label}</span>\n {step.description === undefined ? null : (\n <span className=\"hjm-steps__description\">{step.description}</span>\n )}\n <span className=\"hjm-visually-hidden\" id={`${statusId}-${index}`}>{step.statusLabel}</span>\n </div>\n </>;\n // A pressable step is one named button; its status stays a description so the name keeps order + label.\n return step.revisitable && onStepPress ? (\n <li className=\"hjm-steps__step\" data-status={step.status} key={step.id}>\n <button type=\"button\" className=\"hjm-steps__press\" aria-label={step.accessibleName} aria-describedby={`${statusId}-${index}`}\n onClick={() => onStepPress(step.id)}>{content}</button>\n </li>\n ) : (\n <li\n aria-label={step.accessibleName}\n aria-current={step.status === \"current\" || step.status === \"error\" ? \"step\" : undefined}\n className=\"hjm-steps__step\"\n data-status={step.status}\n key={step.id}\n >{content}</li>\n );\n })}\n </ol>\n );\n});\n"]}
1
+ {"version":3,"file":"steps.js","sourceRoot":"","sources":["../src/steps.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n resolveStepsDescriptor,\n stepsRecipe,\n type ComposeStepsAccessibleName,\n type StepStatus,\n type StepsDescriptor,\n type StepsStatusLabels,\n} from \"@hjmds/design-contracts/components/steps\";\nimport { forwardRef, useId, type HTMLAttributes, type ReactNode } from \"react\";\n\nimport { classNames } from \"./internal.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\nexport type StepsProps<Id extends string = string> = Omit<\n HTMLAttributes<HTMLOListElement>,\n \"children\"\n> & Readonly<{\n descriptor: StepsDescriptor<Id>;\n statusLabels: StepsStatusLabels;\n composeAccessibleName: ComposeStepsAccessibleName;\n renderMark?: (status: StepStatus, position: number) => ReactNode;\n /**\n * Return to a step before the cursor (2026-10-18, spint compose). Only those steps become buttons; the cursor and\n * later steps stay static in default linear mode. Free reading mode makes every step selectable.\n * Omit the handler while the flow is locked.\n */\n onStepPress?: (id: Id) => void;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\n/** Linear progress steps with one canonical cursor; steps before it can be pressed to go back. */\nexport const Steps = forwardRef<HTMLOListElement, StepsProps>(function Steps(\n { descriptor, statusLabels, composeAccessibleName, renderMark, onStepPress, className, layoutStyle, ...props },\n ref,\n) {\n const steps = resolveStepsDescriptor(descriptor, { statusLabels, composeAccessibleName });\n const statusId = useId();\n return (\n <ol {...props} // The terminal step has no outgoing connector: reserve only its content width.\n style={{ [\"--hjm-steps-count\" as string]: steps.length, [\"--hjm-steps-connector-count\" as string]: steps.length - 1, [\"--hjm-steps-press-target\" as string]: `${stepsRecipe.press.minTouchTarget}px`, ...props.style, ...layoutStyle }} ref={ref} className={classNames(\"hjm-steps\", className)}>\n {steps.map((step, index) => {\n const content = <>\n <div className=\"hjm-steps__rail\" aria-hidden=\"true\">\n {index === steps.length - 1 ? <span className=\"hjm-steps__connector\" data-reached={steps[index - 1]?.status === \"complete\" || undefined} /> : null}\n <span className=\"hjm-steps__indicator\">\n {renderMark?.(step.status, step.position) ?? (\n step.status === \"complete\" ? \"✓\" : step.status === \"error\" ? \"!\" : step.position\n )}\n </span>\n {index === steps.length - 1 ? null : <span className=\"hjm-steps__connector\" />}\n </div>\n <div className=\"hjm-steps__copy\">\n <span className=\"hjm-steps__label\">{step.label}</span>\n {step.description === undefined ? null : (\n <span className=\"hjm-steps__description\">{step.description}</span>\n )}\n <span className=\"hjm-visually-hidden\" id={`${statusId}-${index}`}>{step.statusLabel}</span>\n </div>\n </>;\n // A pressable step is one named button; its status stays a description so the name keeps order + label.\n return (descriptor.navigationMode === \"free\" || step.revisitable) && onStepPress ? (\n <li className=\"hjm-steps__step\" data-status={step.status} key={step.id}>\n <button type=\"button\" className=\"hjm-steps__press\" aria-label={step.accessibleName} aria-describedby={`${statusId}-${index}`}\n aria-current={step.status === \"current\" || step.status === \"error\" ? \"step\" : undefined}\n onClick={() => onStepPress(step.id)}>{content}</button>\n </li>\n ) : (\n <li\n aria-label={step.accessibleName}\n aria-current={step.status === \"current\" || step.status === \"error\" ? \"step\" : undefined}\n className=\"hjm-steps__step\"\n data-status={step.status}\n key={step.id}\n >{content}</li>\n );\n })}\n </ol>\n );\n});\n"]}
package/dist/styles.css CHANGED
@@ -228,6 +228,7 @@
228
228
  cursor: pointer;
229
229
  }
230
230
  .hjm-button {
231
+ text-decoration: none;
231
232
  position: relative;
232
233
  min-block-size: var(--hjm-control-button-medium);
233
234
  padding: var(--hjm-space-xs) var(--hjm-space-md);
@@ -276,10 +277,23 @@
276
277
  버튼인지 잃고, 무제한 줄바꿈은 하단 CTA 행 같은 남의 레이아웃을 밀어낸다. */
277
278
  .hjm-button__label { min-inline-size: 0; overflow-wrap: anywhere; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: var(--hjm-button-label-lines, 2); overflow: hidden; }
278
279
  /* Keep the original content in layout for stable width; the sole visible busy cue sits at the frame center. */
279
- .hjm-button[data-state="loading"] > :not(.hjm-button__loading-indicator) { opacity: 0; }
280
+ .hjm-button[data-state="loading"] > :not(.hjm-button__loading-indicator):not(.hjm-button__face),
281
+ .hjm-button[data-state="loading"] > .hjm-button__face > :not(.hjm-button__loading-indicator) { opacity: 0; }
280
282
  .hjm-button__loading-indicator { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }
281
283
  /* 큰 글자 설정에서는 상한을 푼다 — 사용자가 키운 글자를 잘라 내용을 숨기면 WCAG 1.4.4다. */
282
284
  [data-large-text="true"] .hjm-button__label { display: block; overflow: visible; }
285
+ /* The root stays still as the face sinks, preserving the original pointer/focus target. */
286
+ .hjm-button[data-full-width="true"] { inline-size: 100%; }
287
+ .hjm-button[data-tone="primary"] { --hjm-button-face-fill: var(--hjm-color-primary); }
288
+ .hjm-button[data-tone="secondary"] { --hjm-button-face-fill: var(--hjm-color-bg); --hjm-button-face-border: var(--hjm-color-border-control); }
289
+ .hjm-button[data-tone="danger"] { --hjm-button-face-fill: var(--hjm-color-danger-fill); }
290
+ .hjm-button[data-selected="true"] { --hjm-button-face-fill: var(--hjm-color-bg); --hjm-button-face-border: transparent; }
291
+ .hjm-button[data-raised="true"] { padding: 0 0 var(--hjm-button-depth); border: 0; gap: 0; flex-direction: column; background: color-mix(in srgb, var(--hjm-button-side), #000 var(--hjm-button-side-shade)); }
292
+ .hjm-button__face { position: relative; display: flex; box-sizing: border-box; inline-size: 100%; min-block-size: inherit; flex: 1; align-items: center; justify-content: inherit; gap: var(--hjm-space-xs); padding: var(--hjm-space-xs) var(--hjm-button-face-padding); border: 1px solid var(--hjm-button-face-border, transparent); border-radius: inherit; background: var(--hjm-button-face-fill); transition: transform var(--hjm-button-settle) ease-out; }
293
+ .hjm-button[data-raised="true"]:active:not(:disabled):not([aria-disabled="true"]) { opacity: 1; }
294
+ .hjm-button[data-raised="true"]:active:not(:disabled):not([aria-disabled="true"]) > .hjm-button__face { transform: translateY(var(--hjm-button-depth)); }
295
+ @media (prefers-reduced-motion: reduce) { .hjm-button__face { transition: none; } }
296
+ [data-reduced-motion="true"] .hjm-button__face { transition: none; }
283
297
  .hjm-button__spinner,
284
298
  .hjm-spinner__glyph {
285
299
  display: inline-block;
@@ -349,11 +363,12 @@
349
363
  font-family: var(--hjm-font-family-ui, inherit); display: grid; gap: var(--hjm-space-xs); min-inline-size: 0; }
350
364
  .hjm-field__label { color: var(--hjm-color-text-body); font-weight: var(--hjm-text-emphasis-medium); }
351
365
  .hjm-field__control {
366
+ --hjm-field-resolved-border-width: var(--hjm-field-border-width);
352
367
  display: flex;
353
368
  align-items: center;
354
369
  min-block-size: var(--hjm-control-field-height);
355
370
  padding-inline: var(--hjm-space-md);
356
- border: var(--hjm-field-border-width) solid var(--hjm-color-border-control);
371
+ border: var(--hjm-field-resolved-border-width) solid var(--hjm-color-border-control);
357
372
  border-radius: var(--hjm-radius-md);
358
373
  background: var(--hjm-color-bg);
359
374
  }
@@ -365,7 +380,9 @@
365
380
  reads as hue only. The wider ring makes it a shape change like every other control.
366
381
  See issue #19. */
367
382
  .hjm-field[data-state="focused"] .hjm-field__control { border-color: var(--hjm-color-content-brand); box-shadow: 0 0 0 var(--hjm-field-focus-ring-width) var(--hjm-color-content-brand); }
368
- .hjm-field[data-state="invalid"] .hjm-field__control { border-color: var(--hjm-color-danger); }
383
+ /* Validation remains visible when availability is disabled; support text and aria-invalid keep their existing contracts. */
384
+ .hjm-field[data-state="invalid"] .hjm-field__control,
385
+ .hjm-field[data-invalid="true"] .hjm-field__control { border-color: var(--hjm-color-danger); --hjm-field-resolved-border-width: var(--hjm-field-invalid-border-width); }
369
386
  /* fieldRecipe.disabledScope (2026-10-06): disabled fades the label and the control, not
370
387
  the hint or the error, which explain why the field is locked or what to fix. Fading the
371
388
  whole frame (the rule before) took their contrast down with it. Every direct child except
@@ -373,10 +390,11 @@
373
390
  recipe value (Select, NumberField, OtpField, SearchField, PasswordField) arrives as an
374
391
  inline --hjm-field-disabled-opacity on the root. */
375
392
  .hjm-field[data-state="disabled"] > :not(.hjm-field__description):not(.hjm-field__error):not([data-hjm-field-error]) { opacity: var(--hjm-field-disabled-opacity); }
393
+ /* The editable minimum excludes both resolved borders, keeping the field footprint stable in invalid state. */
376
394
  .hjm-field__input {
377
395
  inline-size: 100%;
378
396
  min-inline-size: 0;
379
- min-block-size: calc(var(--hjm-control-field-height) - 2px);
397
+ min-block-size: calc(var(--hjm-control-field-height) - 2 * var(--hjm-field-resolved-border-width));
380
398
  padding-block: var(--hjm-space-xs);
381
399
  border: 0;
382
400
  outline: 0;
@@ -393,7 +411,7 @@
393
411
  .hjm-field__control--multiline { min-block-size: var(--hjm-field-multiline-min-height); align-items: stretch; }
394
412
  .hjm-field__control--multiline textarea {
395
413
  min-block-size: max(
396
- calc(var(--hjm-field-multiline-min-height) - 2px),
414
+ calc(var(--hjm-field-multiline-min-height) - 2 * var(--hjm-field-resolved-border-width)),
397
415
  calc(var(--hjm-field-min-visible-lines, 0) * var(--hjm-type-body-line-height) + var(--hjm-field-padding-block) * 2)
398
416
  );
399
417
  max-block-size: calc(
@@ -411,7 +429,7 @@
411
429
  so clearing has one localized name, onClear callback and focus-restoration path. */
412
430
  .hjm-search-field input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; display: none; }
413
431
  .hjm-search-field:has(.hjm-field__input[data-size="large"]) .hjm-field__control { min-block-size: var(--hjm-control-button-large); padding-inline: var(--hjm-search-field-padding-large, var(--hjm-space-md)); gap: var(--hjm-search-field-gap-large, var(--hjm-space-sm)); }
414
- .hjm-search-field .hjm-field__input[data-size="large"] { min-block-size: calc(var(--hjm-control-button-large) - 2px); font-size: var(--hjm-type-body-large-size); line-height: var(--hjm-type-body-large-line-height); }
432
+ .hjm-search-field .hjm-field__input[data-size="large"] { min-block-size: calc(var(--hjm-control-button-large) - 2 * var(--hjm-field-resolved-border-width)); font-size: var(--hjm-type-body-large-size); line-height: var(--hjm-type-body-large-line-height); }
415
433
  /* The visible circle is the recipe diameter; ::after extends the hit area by clearHitSlop so the target stays 44. */
416
434
  .hjm-search-field__clear { --hjm-search-clear-slop: var(--hjm-search-field-clear-slop-medium, 4px); position: relative; flex: 0 0 auto; inline-size: var(--hjm-search-field-clear-medium, 36px); block-size: var(--hjm-search-field-clear-medium, 36px); display: inline-grid; place-items: center; border: 0; border-radius: 50%; color: inherit; background: transparent; font: inherit; cursor: pointer; }
417
435
  .hjm-search-field__clear::after { content: ""; position: absolute; inset: calc(-1 * var(--hjm-search-clear-slop)); border-radius: 50%; }
@@ -419,7 +437,7 @@
419
437
  .hjm-search-field__spinner { inline-size: 32px; block-size: 32px; display: inline-grid; place-items: center; color: var(--hjm-color-content-brand); }
420
438
  .hjm-search-field__spinner:empty::before { content: ""; inline-size: 1em; block-size: 1em; border: 2px solid currentColor; border-inline-end-color: transparent; border-radius: 50%; animation: hjm-spin 800ms linear infinite; }
421
439
  .hjm-password-field--large .hjm-field__control { min-block-size: var(--hjm-control-button-large); padding-inline: var(--hjm-space-lg); }
422
- .hjm-password-field--large .hjm-field__input { min-block-size: calc(var(--hjm-control-button-large) - 2px); font-size: var(--hjm-type-body-large-size); line-height: var(--hjm-type-body-large-line-height); }
440
+ .hjm-password-field--large .hjm-field__input { min-block-size: calc(var(--hjm-control-button-large) - 2 * var(--hjm-field-resolved-border-width)); font-size: var(--hjm-type-body-large-size); line-height: var(--hjm-type-body-large-line-height); }
423
441
  .hjm-password-field__toggle {
424
442
  position: relative;
425
443
  flex: 0 0 var(--hjm-control-min-touch-target);
@@ -643,7 +661,7 @@
643
661
  font-variant-numeric: tabular-nums;
644
662
  }
645
663
  .hjm-number-field[data-size="large"] .hjm-number-field__input {
646
- min-block-size: calc(var(--hjm-control-button-large) - 2px);
664
+ min-block-size: calc(var(--hjm-control-button-large) - 2 * var(--hjm-field-resolved-border-width));
647
665
  padding-inline: var(--hjm-space-xs);
648
666
  font-size: var(--hjm-type-body-large-size);
649
667
  line-height: var(--hjm-type-body-large-line-height);
@@ -814,16 +832,24 @@
814
832
  .hjm-choice__copy { display: grid; gap: var(--hjm-space-xxs); padding-block: 2px; }
815
833
  .hjm-choice[data-state="checked"] .hjm-choice__copy > :first-child,
816
834
  .hjm-choice[data-state="mixed"] .hjm-choice__copy > :first-child { font-weight: var(--hjm-font-weight-semibold); }
817
- .hjm-radio-group { min-inline-size: 0; padding: 0; border: 0; }
818
- .hjm-radio-group legend { margin-block-end: var(--hjm-space-xs); font-weight: var(--hjm-text-emphasis-medium); }
835
+ /* Native groups have no outer inset; remove the browser fieldset margin so sibling content shares one edge. */
836
+ .hjm-radio-group { margin: 0; min-inline-size: 0; padding: 0; border: 0; }
837
+ .hjm-radio-group legend { padding: 0; margin-block-end: var(--hjm-space-xs); font-weight: var(--hjm-text-emphasis-medium); }
819
838
  .hjm-radio-group__items { display: flex; flex-direction: column; gap: var(--hjm-space-xs); }
820
839
  .hjm-radio-group[data-presentation="plain"] .hjm-radio-group__items { gap: var(--hjm-space-xxs); }
821
840
  .hjm-radio-group[data-presentation="grouped"] .hjm-radio-group__items { gap: 0; overflow: hidden; border: 1px solid var(--hjm-color-border); border-radius: var(--hjm-radius-lg); background: var(--hjm-color-bg); }
822
841
  .hjm-radio-group[data-orientation="horizontal"] .hjm-radio-group__items { flex-direction: row; flex-wrap: wrap; gap: var(--hjm-space-md); }
823
842
  .hjm-radio-group[data-orientation="horizontal"][data-presentation="plain"] .hjm-radio-group__items { gap: var(--hjm-space-sm); }
824
843
  .hjm-radio-group[data-orientation="horizontal"][data-presentation="grouped"] .hjm-radio-group__items { gap: 0; }
844
+ /* Radio option actions are siblings of the label, never nested interactive controls. */
845
+ .hjm-choice.hjm-choice--with-action { padding: 0; gap: 0; }
846
+ .hjm-choice__target { display: flex; align-items: center; align-self: stretch; flex: 1; min-inline-size: 0; min-block-size: inherit; gap: var(--hjm-space-sm); padding: var(--hjm-space-sm) var(--hjm-space-md); cursor: inherit; }
847
+ .hjm-choice[data-size="small"] > .hjm-choice__target { gap: var(--hjm-space-xs); padding: var(--hjm-space-xs) var(--hjm-space-sm); }
848
+ .hjm-choice[data-presentation="plain"] > .hjm-choice__target { padding: 0; }
849
+ .hjm-choice__action { flex: 0 0 auto; padding-inline-end: var(--hjm-space-xs); }
850
+ .hjm-choice__target .hjm-choice__copy { min-inline-size: 0; overflow-wrap: anywhere; }
825
851
  .hjm-checkbox-group { min-inline-size: 0; margin: 0; padding: 0; border: 0; }
826
- .hjm-checkbox-group legend { margin-block-end: var(--hjm-space-xs); font-weight: var(--hjm-text-emphasis-medium); }
852
+ .hjm-checkbox-group legend { padding: 0; margin-block-end: var(--hjm-space-xs); font-weight: var(--hjm-text-emphasis-medium); }
827
853
  .hjm-checkbox-group__items { display: flex; flex-direction: column; gap: var(--hjm-space-xs); }
828
854
  .hjm-checkbox-group[data-presentation="plain"] .hjm-checkbox-group__items { gap: var(--hjm-space-xxs); }
829
855
  .hjm-checkbox-group[data-presentation="grouped"] .hjm-checkbox-group__items { gap: 0; overflow: hidden; border: 1px solid var(--hjm-color-border); border-radius: var(--hjm-radius-lg); background: var(--hjm-color-bg); }
@@ -845,6 +871,18 @@
845
871
  .hjm-switch__copy { display: flex; flex-direction: column; gap: var(--hjm-space-xxs); min-inline-size: 0; text-align: start; overflow-wrap: anywhere; }
846
872
  .hjm-switch__description { color: var(--hjm-color-text-muted); font-size: var(--hjm-type-caption-size); line-height: var(--hjm-type-caption-line-height); }
847
873
  .hjm-switch[data-presentation="row"] { display: flex; inline-size: 100%; justify-content: space-between; }
874
+ /* Chip collections retain their native radio/checkbox inputs, including nullable and multi-select values. */
875
+ :is(.hjm-radio-group, .hjm-checkbox-group)[data-presentation="chips"] > :is(.hjm-radio-group__items, .hjm-checkbox-group__items) { flex-direction: row; flex-wrap: wrap; gap: var(--hjm-space-xs); }
876
+ .hjm-choice[data-presentation="chips"] { position: relative; flex: 0 1 auto; min-block-size: var(--hjm-control-min-touch-target); padding: 0 var(--hjm-space-md); border-radius: var(--hjm-radius-full); color: var(--hjm-color-text-muted); font-weight: var(--hjm-text-emphasis-medium); }
877
+ .hjm-choice[data-presentation="chips"][data-size="small"] { min-block-size: 36px; padding-inline: var(--hjm-space-sm); }
878
+ .hjm-choice[data-presentation="chips"][data-size="small"]::after { content: ""; position: absolute; inset: -4px 0; }
879
+ .hjm-choice[data-presentation="chips"].hjm-choice--with-action { padding: 0; }
880
+ .hjm-choice[data-presentation="chips"] > .hjm-choice__target { padding-block: 0; }
881
+ .hjm-choice[data-presentation="chips"] .hjm-choice__indicator { display: none; }
882
+ .hjm-choice[data-presentation="chips"] .hjm-choice__leading { color: inherit; }
883
+ .hjm-choice[data-presentation="chips"] .hjm-choice__copy { min-inline-size: 0; overflow-wrap: anywhere; padding-block: 0; }
884
+ .hjm-choice[data-presentation="chips"][data-state="checked"], .hjm-choice[data-presentation="chips"][data-state="mixed"] { color: var(--hjm-color-content-brand); border-color: var(--hjm-color-content-brand); }
885
+ .hjm-choice[data-presentation="chips"]:has(.hjm-choice__input:focus-visible) { outline: var(--hjm-focus-width) solid var(--hjm-color-focus); outline-offset: var(--hjm-focus-offset); }
848
886
  /* A described switch: copy + switchRecipe.rowPaddingVertical 8 on both sides, min rowTwoLineMinHeight 56, same as Native.
849
887
  Stacked switch rows carry this spacing themselves; containers add no gap between them (2026-10-17). */
850
888
  .hjm-switch[data-two-line="true"] { min-block-size: var(--hjm-switch-row-two-line-min-height); padding-block: var(--hjm-switch-row-padding-vertical); }
@@ -924,10 +962,10 @@
924
962
 
925
963
  .hjm-badge, .hjm-tag { display: inline-flex; align-items: center; gap: var(--hjm-space-xxs); max-inline-size: 100%; overflow-wrap: anywhere; }
926
964
  /* Solid status plates mirror badgeRecipe; Tag keeps its independent tint treatment. */
927
- .hjm-badge { min-block-size: 24px; padding: 2px var(--hjm-space-xs); border: 0; border-radius: var(--hjm-radius-sm); color: var(--hjm-color-on-primary); background: var(--hjm-color-neutral-fill); font-size: var(--hjm-type-caption-size); line-height: var(--hjm-type-caption-line-height); font-weight: var(--hjm-font-weight-bold); }
965
+ .hjm-badge { min-block-size: 24px; padding: 2px var(--hjm-space-xs); border: 0; border-radius: var(--hjm-radius-sm); color: var(--hjm-color-on-status-fill); background: var(--hjm-color-neutral-fill); font-size: var(--hjm-type-caption-size); line-height: var(--hjm-type-caption-line-height); font-weight: var(--hjm-font-weight-bold); }
928
966
  .hjm-badge[data-size="small"] { min-block-size: 20px; }
929
967
  .hjm-badge[data-tone="strong"] { background: var(--hjm-color-strong-fill); }
930
- .hjm-badge[data-tone="brand"] { background: var(--hjm-color-primary); }
968
+ .hjm-badge[data-tone="brand"] { color: var(--hjm-color-on-primary); background: var(--hjm-color-primary); }
931
969
  .hjm-badge[data-tone="danger"] { color: var(--hjm-color-on-danger); background: var(--hjm-color-danger-fill); }
932
970
  .hjm-badge__icon { display: inline-flex; align-items: center; flex: 0 0 auto; }
933
971
  .hjm-badge[data-variant="outline"] { background: transparent; border: 1px solid var(--hjm-color-border); color: var(--hjm-color-text-muted); }
@@ -967,13 +1005,16 @@
967
1005
  .hjm-counter-badge[data-tone="danger"] { color: var(--hjm-color-on-danger); background: var(--hjm-color-danger-fill); }
968
1006
  .hjm-counter-badge[data-variant="floating"] { border: 2px solid var(--hjm-color-bg); }
969
1007
 
970
- .hjm-card { overflow: hidden; }
1008
+ .hjm-card { display: flex; flex-direction: column; overflow: hidden; }
971
1009
  .hjm-card__media > * { display: block; inline-size: 100%; }
972
- /* The implicit auto column grew to the min-content of slotted children (e.g. a SegmentedControl with max-content items),
973
- pushing content past the card padding at narrow widths (2026-10-17 STEA schedule card at 402). minmax(0, 1fr) keeps every
974
- slot inside the padded body so scroll/wrap rules of the child apply. */
975
- .hjm-card__body { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--hjm-space-xs); padding: var(--hjm-space-md); }
976
- .hjm-card__header { display: flex; align-items: flex-start; gap: var(--hjm-space-sm); min-inline-size: 0; }
1010
+ /* Zero inline minima preserve narrow-slot wrapping; body/content relay allocated height to slotted layouts
1011
+ without growing headers or footer commands (Diairy journey overview, 2026-10-20). */
1012
+ .hjm-card__body { display: flex; flex-direction: column; flex: 1; min-inline-size: 0; min-block-size: 0; gap: var(--hjm-space-xs); padding: var(--hjm-space-md); }
1013
+ .hjm-card__body > * { min-inline-size: 0; }
1014
+ .hjm-card__content { display: flex; flex-direction: column; flex: 1; min-block-size: 0; }
1015
+ .hjm-card__media, .hjm-card__actions { flex-shrink: 0; }
1016
+ .hjm-card__header { display: flex; align-items: center; gap: var(--hjm-space-sm); min-inline-size: 0; }
1017
+ .hjm-card__header-actions { position: relative; z-index: 1; display: flex; flex: 0 0 auto; align-items: center; gap: var(--hjm-space-xs); }
977
1018
  .hjm-card__leading { flex: 0 0 auto; display: inline-grid; place-items: center; line-height: 1; }
978
1019
  .hjm-card__copy { flex: 1 1 auto; min-inline-size: 0; display: grid; gap: var(--hjm-space-xs); }
979
1020
  /* cardRecipe.title.emphasis "strong": without a weight the h2–h6 element fell back to the UA bold (700). */
@@ -1071,13 +1112,15 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
1071
1112
  .hjm-list { min-inline-size: 0; }
1072
1113
  .hjm-list[data-appearance="grouped"] { overflow: hidden; padding-inline: var(--hjm-list-grouped-padding-inline); border-radius: var(--hjm-radius-lg); background: var(--hjm-color-bg); }
1073
1114
  .hjm-list__item { min-inline-size: 0; }
1115
+ .hjm-list-separator { border-block-start: 1px solid var(--hjm-color-border); flex-shrink: 0; pointer-events: none; }
1074
1116
  /* Indent only the divider: moving the row shifted every title after the first
1075
1117
  and narrowed its text column in the notification-settings composition. Insets are measured from the list content
1076
1118
  edge (where the row text sits) and come from listRecipe.separators: full spans the row surface; indented follows
1077
1119
  the text column of the row above (the separator belongs to that row, as Native draws it after the row) — 52 after a
1078
1120
  row with leading (ListRow root `data-leading`), 0 after one without, ending on the content edge (2026-10-17). */
1079
- .hjm-list:is([data-separator="full"], [data-separator="indented"]) > .hjm-list__item + .hjm-list__item { position: relative; }
1080
- .hjm-list:is([data-separator="full"], [data-separator="indented"]) > .hjm-list__item + .hjm-list__item::before { content: ""; position: absolute; inset-block-start: 0; border-block-start: 1px solid var(--hjm-color-border); pointer-events: none; }
1121
+ .hjm-list:is([data-separator="full"], [data-separator="indented"], [data-separator="content"]) > .hjm-list__item + .hjm-list__item { position: relative; }
1122
+ .hjm-list:is([data-separator="full"], [data-separator="indented"], [data-separator="content"]) > .hjm-list__item + .hjm-list__item::before { content: ""; position: absolute; inset-block-start: 0; border-block-start: 1px solid var(--hjm-color-border); pointer-events: none; }
1123
+ .hjm-list[data-separator="content"] > .hjm-list__item + .hjm-list__item::before { inset-inline: var(--hjm-list-separator-content-start) var(--hjm-list-separator-content-end); }
1081
1124
  .hjm-list[data-separator="full"] > .hjm-list__item + .hjm-list__item::before { inset-inline: var(--hjm-list-separator-full-start) var(--hjm-list-separator-full-end); }
1082
1125
  .hjm-list[data-separator="indented"] > .hjm-list__item + .hjm-list__item::before { inset-inline: var(--hjm-list-separator-indented-start) var(--hjm-list-separator-indented-end); }
1083
1126
  .hjm-list[data-separator="indented"] > .hjm-list__item:has(> [data-leading]) + .hjm-list__item::before { inset-inline-start: var(--hjm-list-separator-indented-leading-start); }
@@ -1095,7 +1138,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
1095
1138
  .hjm-statistic__label { color: var(--hjm-color-text-muted); font-size: var(--hjm-type-label-size); line-height: var(--hjm-type-label-line-height); font-weight: var(--hjm-text-emphasis-medium); overflow-wrap: anywhere; }
1096
1139
  .hjm-statistic[data-density="compact"] .hjm-statistic__label { font-size: var(--hjm-type-caption-size); line-height: var(--hjm-type-caption-line-height); }
1097
1140
  .hjm-statistic__value-row { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--hjm-space-xxs); min-inline-size: 0; }
1098
- .hjm-statistic__value { color: var(--hjm-color-text); font-size: var(--hjm-type-heading-size); line-height: var(--hjm-type-heading-line-height); font-weight: var(--hjm-font-weight-semibold); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
1141
+ .hjm-statistic__value { color: var(--hjm-statistic-value-color, var(--hjm-color-text)); font-size: var(--hjm-type-heading-size); line-height: var(--hjm-type-heading-line-height); font-weight: var(--hjm-font-weight-semibold); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
1099
1142
  .hjm-statistic[data-density="compact"] .hjm-statistic__value { font-size: var(--hjm-type-title-size); line-height: var(--hjm-type-title-line-height); }
1100
1143
  .hjm-statistic__affix { color: var(--hjm-color-text-body); font-size: var(--hjm-type-body-size); line-height: var(--hjm-type-body-line-height); font-weight: var(--hjm-text-emphasis-medium); }
1101
1144
  .hjm-statistic__hint { color: var(--hjm-color-text-muted); font-size: var(--hjm-type-caption-size); line-height: var(--hjm-type-caption-line-height); }
@@ -1108,7 +1151,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
1108
1151
  .hjm-statistic-group { grid-template-columns: minmax(0, 1fr); }
1109
1152
  }
1110
1153
 
1111
- .hjm-notice { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--hjm-space-sm); padding: var(--hjm-space-md); border: 1px solid; border-radius: var(--hjm-radius-md); color: var(--hjm-color-text-body); background: var(--hjm-color-bg); border-color: var(--hjm-color-border); }
1154
+ .hjm-notice { display: flex; flex-wrap: wrap; align-items: center; gap: var(--hjm-space-sm); padding: var(--hjm-space-md); border: 1px solid; border-radius: var(--hjm-radius-md); color: var(--hjm-color-text-body); background: var(--hjm-color-bg); border-color: var(--hjm-color-border); }
1112
1155
  .hjm-notice[data-tone="info"] { border-color: var(--hjm-accent-info); }
1113
1156
  .hjm-notice[data-tone="success"] { border-color: var(--hjm-accent-success); background: color-mix(in srgb, var(--hjm-accent-success) 10%, var(--hjm-color-bg)); }
1114
1157
  .hjm-notice[data-tone="warning"] { border-color: var(--hjm-accent-warning); background: color-mix(in srgb, var(--hjm-accent-warning) 10%, var(--hjm-color-bg)); }
@@ -1116,14 +1159,9 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
1116
1159
  .hjm-notice[data-tone="danger"] { border-color: var(--hjm-color-danger); background: color-mix(in srgb, var(--hjm-color-danger) 10%, var(--hjm-color-bg)); }
1117
1160
  /* Reserve readable copy; wrap the action instead of crushing its label. */
1118
1161
  .hjm-notice__content { flex: 1 1 60%; min-inline-size: 0; display: grid; gap: var(--hjm-space-xxs); }
1119
- /* First-line anchor (2026-10-17 measured audit): the inline action (contract: Button size="small") centered 8px
1120
- below the title's first line and the icon box had no rule at all. Icon, first line and action now share one
1121
- anchor — the line box (1lh) alone, or the small-button height when an action sits on the row. Extra lines
1122
- grow downward; Native keeps the action under the copy (docs/usage/components/notice.md). */
1123
- .hjm-notice { --hjm-notice-anchor: 1lh; }
1124
- .hjm-notice:has(> .hjm-notice__action) { --hjm-notice-anchor: var(--hjm-control-button-small); }
1125
- .hjm-notice__icon { flex: 0 0 auto; display: flex; align-items: center; justify-content: center; min-inline-size: 1.25rem; block-size: var(--hjm-notice-anchor); }
1126
- .hjm-notice__content > :first-child { margin-block-start: calc((var(--hjm-notice-anchor) - 1lh) / 2); }
1162
+ /* Center the complete copy and action within the row; a first-line offset drifts
1163
+ when the copy wraps or the button's actual height differs from its token. */
1164
+ .hjm-notice__icon { flex: 0 0 auto; display: flex; align-items: center; justify-content: center; min-inline-size: 1.25rem; block-size: 1lh; }
1127
1165
  .hjm-notice__action { flex: 0 0 auto; max-inline-size: 100%; }
1128
1166
  .hjm-notice__title, .hjm-notice__description { overflow-wrap: anywhere; }
1129
1167
  /* noticeRecipe/emptyStateRecipe title weight; the <strong> otherwise draws the UA bold (700). */
@@ -1171,7 +1209,12 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
1171
1209
  /* Copy row above the ring at the start edge, like the linear bar and Native (2026-10-06 follow-up). The ring used to sit
1172
1210
  beside the copy (grid auto 1fr), so the same Progress laid out differently per platform. */
1173
1211
  .hjm-progress[data-shape="circular"] { justify-items: start; }
1174
- .hjm-progress[data-shape="circular"] .hjm-progress__native { display: none; }
1212
+ /* Keep one semantic progress target even when decorative segments or the ring paint it. */
1213
+ .hjm-progress[data-shape="circular"] .hjm-progress__native,
1214
+ .hjm-progress[data-segmented] .hjm-progress__native { position: absolute; inline-size: 1px; block-size: 1px; clip-path: inset(50%); overflow: hidden; }
1215
+ .hjm-progress__segments { display: flex; inline-size: 100%; }
1216
+ .hjm-progress__segments > span { flex: 1; min-inline-size: 0; overflow: hidden; border-radius: var(--hjm-radius-full); background: var(--hjm-progress-track); }
1217
+ .hjm-progress__segments > span > i { display: block; block-size: 100%; background: var(--hjm-progress-fill); }
1175
1218
  .hjm-progress__ring {
1176
1219
  position: relative;
1177
1220
  display: grid;
@@ -2453,7 +2496,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2453
2496
  display: grid;
2454
2497
  place-items: center;
2455
2498
  min-inline-size: var(--hjm-control-min-touch-target);
2456
- min-block-size: var(--hjm-space-lg);
2499
+ min-block-size: var(--hjm-control-min-touch-target);
2457
2500
  padding: 0;
2458
2501
  border: 0;
2459
2502
  background: transparent;
@@ -2706,8 +2749,9 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2706
2749
 
2707
2750
  /* Advanced display ------------------------------------------------------- */
2708
2751
  /* timelineRecipe label/description are `body`; binding it here lets the rail and timestamp derive from the same line box. */
2709
- .hjm-timeline { display: grid; gap: var(--hjm-space-md); margin: 0; padding: 0; list-style: none; font-size: var(--hjm-type-body-size); line-height: var(--hjm-type-body-line-height); }
2710
- .hjm-timeline__item { min-inline-size: 0; display: grid; grid-template-columns: 1rem minmax(0, 1fr); gap: var(--hjm-space-sm); }
2752
+ .hjm-timeline { display: grid; gap: var(--hjm-space-lg); margin: 0; padding: 0; list-style: none; font-size: var(--hjm-type-body-size); line-height: var(--hjm-type-body-line-height); }
2753
+ .hjm-timeline__item { padding: var(--hjm-space-sm); border-radius: var(--hjm-radius-md); min-inline-size: 0; display: grid; grid-template-columns: 1rem minmax(0, 1fr); gap: var(--hjm-space-sm); }
2754
+ .hjm-timeline__item[data-emphasized="true"] { background: color-mix(in srgb, var(--hjm-accent-info) 10%, transparent); }
2711
2755
  .hjm-timeline__rail { position: relative; display: flex; justify-content: center; }
2712
2756
  /* Dot, label first line and timestamp share the label's first line box (2026-10-17 measured audit: centers 396/397/398.5).
2713
2757
  The rail inherits the label's line height, so 1lh is that line box. */
@@ -2715,12 +2759,12 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2715
2759
  .hjm-timeline__item[data-tone="info"] .hjm-timeline__dot { border-color: var(--hjm-accent-info); background: var(--hjm-accent-info); }
2716
2760
  .hjm-timeline__item[data-tone="success"] .hjm-timeline__dot { border-color: var(--hjm-accent-success); background: var(--hjm-accent-success); }
2717
2761
  .hjm-timeline__item[data-tone="attention"] .hjm-timeline__dot { border-color: var(--hjm-accent-attention); background: var(--hjm-accent-attention); }
2718
- .hjm-timeline__connector { position: absolute; inset-block: calc((1lh + 0.625rem) / 2) calc(-1 * var(--hjm-space-md)); inline-size: 1px; background: var(--hjm-color-border); }
2762
+ .hjm-timeline__connector { position: absolute; inset-block: calc((1lh + 0.625rem) / 2) calc(-1 * (var(--hjm-space-lg) + 2 * var(--hjm-space-sm)) - .5lh); inline-size: 1px; background: var(--hjm-color-border); }
2719
2763
  .hjm-timeline__content { min-inline-size: 0; display: grid; gap: var(--hjm-space-xxs); padding-block-end: var(--hjm-space-xxs); }
2720
- .hjm-timeline__heading { min-inline-size: 0; display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: var(--hjm-space-xxs) var(--hjm-space-sm); }
2764
+ .hjm-timeline__heading { min-inline-size: 0; display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--hjm-space-xxs) var(--hjm-space-sm); }
2721
2765
  .hjm-timeline__label { color: var(--hjm-color-text); font-weight: var(--hjm-text-emphasis-medium); overflow-wrap: anywhere; }
2722
2766
  /* Baseline sharing put the smaller caption 1.5px under the label's center; center it on the label's first line instead. */
2723
- .hjm-timeline__timestamp { margin-block-start: calc((var(--hjm-type-body-line-height) - var(--hjm-type-caption-line-height)) / 2); color: var(--hjm-color-text-muted); font-size: var(--hjm-type-caption-size); line-height: var(--hjm-type-caption-line-height); }
2767
+ .hjm-timeline__timestamp { color: var(--hjm-color-text-muted); font-size: var(--hjm-type-caption-size); line-height: var(--hjm-type-caption-line-height); }
2724
2768
  .hjm-timeline__description { color: var(--hjm-color-text-body); white-space: pre-wrap; overflow-wrap: anywhere; }
2725
2769
  .hjm-accordion { border-block-start: 1px solid var(--hjm-color-border); }
2726
2770
  .hjm-accordion__item { border-block-end: 1px solid var(--hjm-color-border); }
@@ -2773,7 +2817,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2773
2817
  .hjm-description-list { display: grid; grid-template-columns: repeat(var(--hjm-description-columns), minmax(0, 1fr)); gap: var(--hjm-space-sm); margin: 0; }
2774
2818
  .hjm-description-list__item { min-inline-size: 0; display: grid; gap: var(--hjm-space-xxs); }
2775
2819
  .hjm-description-list__label { color: var(--hjm-color-text-muted); font-size: var(--hjm-type-label-size); font-weight: var(--hjm-text-emphasis-medium); }
2776
- .hjm-description-list__value { margin: 0; color: var(--hjm-color-text); overflow-wrap: anywhere; }
2820
+ .hjm-description-list__value { margin: 0; color: var(--hjm-color-text); white-space: pre-wrap; overflow-wrap: anywhere; }
2777
2821
  .hjm-table-scroll { max-inline-size: 100%; overflow: auto; outline-offset: 2px; }
2778
2822
  .hjm-table { inline-size: 100%; border-collapse: collapse; color: var(--hjm-color-text-body); }
2779
2823
  .hjm-table__caption { padding: var(--hjm-space-sm); color: var(--hjm-color-text); font-weight: var(--hjm-type-title-weight); text-align: start; }
@@ -2823,7 +2867,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2823
2867
  .hjm-load-more__spinner { inline-size: 1em; block-size: 1em; border: 2px solid var(--hjm-color-content-brand); border-inline-end-color: transparent; border-radius: 50%; animation: hjm-spin 800ms linear infinite; }
2824
2868
 
2825
2869
  /* Expansion renderers --------------------------------------------------- */
2826
- .hjm-steps { display: grid; grid-template-columns: repeat(var(--hjm-steps-count, auto-fit), minmax(0, 1fr)); gap: var(--hjm-space-xs); margin: 0; padding: 0; list-style: none; }
2870
+ .hjm-steps { display: grid; grid-template-columns: repeat(var(--hjm-steps-connector-count), minmax(0, 1fr)) fit-content(calc(100% / var(--hjm-steps-count))); gap: 0; margin: 0; padding: 0; list-style: none; }
2827
2871
  .hjm-steps__step { min-inline-size: 0; display: grid; align-content: start; gap: var(--hjm-space-xs); }
2828
2872
  .hjm-steps__rail { display: flex; align-items: center; min-inline-size: 0; }
2829
2873
  .hjm-steps__indicator { flex: 0 0 auto; inline-size: 1.5rem; block-size: 1.5rem; display: grid; place-items: center; border: 1px solid var(--hjm-color-border); border-radius: 50%; color: var(--hjm-color-text-muted); background: var(--hjm-color-bg); font-size: var(--hjm-type-label-size); font-weight: var(--hjm-text-emphasis-medium); }
@@ -2831,11 +2875,16 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2831
2875
  .hjm-steps__step[data-status="current"] .hjm-steps__indicator { border: 2px solid var(--hjm-color-content-brand); color: var(--hjm-color-content-brand); }
2832
2876
  .hjm-steps__step[data-status="complete"] .hjm-steps__indicator { border-color: var(--hjm-accent-success); color: var(--hjm-accent-success); background: var(--hjm-color-bg); }
2833
2877
  .hjm-steps__step[data-status="complete"] .hjm-steps__connector { background: var(--hjm-color-content-brand); }
2878
+ /* The terminal incoming segment continues the previous rail across its copy width. */
2879
+ .hjm-steps__connector[data-reached="true"] { background: var(--hjm-color-content-brand); }
2834
2880
  .hjm-steps__step[data-status="error"] .hjm-steps__indicator { border: 2px solid var(--hjm-color-danger); color: var(--hjm-color-danger); background: var(--hjm-color-danger-fill); }
2835
2881
  .hjm-steps__copy { min-inline-size: 0; display: grid; gap: var(--hjm-space-xxs); padding-inline-end: var(--hjm-space-sm); }
2836
2882
  .hjm-steps__label { color: var(--hjm-color-text); font-size: var(--hjm-type-label-size); line-height: var(--hjm-type-label-line-height); font-weight: var(--hjm-text-emphasis-medium); overflow-wrap: anywhere; }
2837
2883
  .hjm-steps__step[data-status="pending"] .hjm-steps__label { color: var(--hjm-color-text-muted); }
2838
2884
  .hjm-steps__step[data-status="error"] .hjm-steps__label { color: var(--hjm-color-danger); }
2885
+ /* Keep the terminal marker at the inline edge instead of an empty trailing step cell. */
2886
+ .hjm-steps__step:last-child .hjm-steps__rail { justify-content: flex-end; }
2887
+ .hjm-steps__step:last-child .hjm-steps__copy { padding-inline-end: 0; text-align: end; }
2839
2888
  .hjm-steps__description { color: var(--hjm-color-text-muted); font-size: var(--hjm-type-caption-size); overflow-wrap: anywhere; }
2840
2889
  /* A step before the cursor is one button over marker and label (Steps onStepPress); the cell keeps its static layout. */
2841
2890
  .hjm-steps__press { display: grid; align-content: start; gap: var(--hjm-space-xs); min-inline-size: 0; min-block-size: var(--hjm-steps-press-target); margin: 0; padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: start; cursor: pointer; }
@@ -2991,6 +3040,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2991
3040
  /* Intrinsic action columns keep short labels readable at 320px; the title wraps
2992
3041
  in the remaining space instead of squeezing actions to equal-width tracks. */
2993
3042
  .hjm-top-bar { display: grid; grid-template-columns: minmax(var(--hjm-control-min-touch-target), auto) minmax(0, 1fr) minmax(var(--hjm-control-min-touch-target), auto); align-items: center; min-block-size: var(--hjm-top-bar-min-height); gap: var(--hjm-top-bar-gap); padding-inline: var(--hjm-top-bar-padding); padding-block-start: max(env(safe-area-inset-top, 0px), var(--hjm-top-bar-safe-area)); background: var(--hjm-color-bg); }
3043
+ .hjm-top-bar[data-surface="transparent"] { background: transparent; }
2994
3044
  .hjm-top-bar__leading, .hjm-top-bar__trailing { display: flex; flex-wrap: wrap; align-items: center; min-inline-size: 0; gap: var(--hjm-top-bar-gap); }
2995
3045
  .hjm-top-bar__trailing { justify-content: flex-end; }
2996
3046
  .hjm-top-bar__title { min-inline-size: 0; text-align: center; overflow-wrap: anywhere; }
@@ -3004,11 +3054,11 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
3004
3054
  .hjm-top-bar[data-large-text="true"] .hjm-top-bar__trailing { grid-column: 2; grid-row: 1; }
3005
3055
  .hjm-bottom-cta { display: grid; gap: var(--hjm-bottom-cta-gap); min-block-size: var(--hjm-bottom-cta-min-height); padding: var(--hjm-bottom-cta-padding-top) var(--hjm-bottom-cta-padding-inline) max(var(--hjm-bottom-cta-padding-bottom), env(safe-area-inset-bottom, 0px), var(--hjm-bottom-cta-safe-area)); border-block-start: 1px solid var(--hjm-color-border); background: var(--hjm-color-bg); box-shadow: var(--hjm-bottom-cta-shadow, none); }
3006
3056
  .hjm-bottom-cta[data-position="sticky"] { position: sticky; inset-block-end: 0; z-index: var(--hjm-layer-sticky); }
3007
- /* Inside ScreenLayout's footer the footer owns border, padding, surface and safe area; BottomCTA keeps only its copy,
3057
+ /* Inside a padded ScreenLayout or Sheet footer the parent owns padding, surface and safe area; BottomCTA keeps only its copy,
3008
3058
  actions and an explicit safeAreaBottom (2026-10-17: the doubled bar inset the buttons twice). */
3009
- /* The screen footer already pads max(screen padding, env(safe-area-inset-bottom)); an explicit safeAreaBottom adds only
3059
+ /* Each footer passes its actual bottom padding (ScreenLayout max, Sheet additive); an explicit safeAreaBottom adds only
3010
3060
  the remainder so the gap is max(footer, inset), not their sum (2026-10-17 "버튼 아래 여백이 많아"). */
3011
- .hjm-bottom-cta[data-placement="screen-footer"] { position: static; min-block-size: 0; padding: 0 0 max(0px, calc(var(--hjm-bottom-cta-safe-area) - max(var(--hjm-screen-padding), env(safe-area-inset-bottom, 0px)))); border: 0; background: none; box-shadow: none; }
3061
+ .hjm-bottom-cta[data-placement="screen-footer"] { position: static; box-sizing: border-box; inline-size: 100%; min-inline-size: 0; min-block-size: 0; padding: 0 0 max(0px, calc(var(--hjm-bottom-cta-safe-area) - var(--hjm-bottom-cta-parent-padding))); border: 0; background: none; box-shadow: none; }
3012
3062
  .hjm-bottom-cta__description { margin: 0; font-size: var(--hjm-type-caption-size); line-height: var(--hjm-type-caption-line-height); color: var(--hjm-color-text-muted); overflow-wrap: anywhere; }
3013
3063
  .hjm-bottom-cta__actions { display: flex; flex-wrap: wrap; gap: var(--hjm-bottom-cta-gap); }
3014
3064
  /* bottomCtaRecipe.contentMaxWidth: the surface spans the viewport, its copy and actions stop at the reading width. */
@@ -3075,7 +3125,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
3075
3125
 
3076
3126
  .hjm-anchor { min-inline-size: 0; }
3077
3127
  .hjm-anchor__list { display: flex; flex-direction: column; gap: var(--hjm-space-xxs); list-style: none; margin: 0; padding: 0; }
3078
- .hjm-anchor__link { display: block; padding: var(--hjm-space-xs); border-inline-start: 2px solid transparent; color: var(--hjm-color-text-muted); text-decoration: none; overflow-wrap: anywhere; }
3128
+ .hjm-anchor__link { display: flex; align-items: center; gap: var(--hjm-space-xs); min-block-size: var(--hjm-control-min-touch-target); min-inline-size: var(--hjm-control-min-touch-target); box-sizing: border-box; padding: var(--hjm-space-xs); border-inline-start: 2px solid transparent; color: var(--hjm-color-text-muted); text-decoration: none; overflow-wrap: anywhere; }
3079
3129
  .hjm-anchor__link:hover { text-decoration: underline; text-underline-offset: 0.18em; }
3080
3130
  .hjm-anchor__link[aria-current="location"] { color: var(--hjm-color-content-brand); border-color: var(--hjm-color-focus); font-weight: var(--hjm-text-emphasis-strong); }
3081
3131
  .hjm-anchor__link:focus-visible { outline: 2px solid var(--hjm-color-focus); outline-offset: 2px; }
@@ -3098,6 +3148,12 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
3098
3148
  /* Disclosure, context menu, menubar --------------------------------------- */
3099
3149
  .hjm-collapsible { display: grid; gap: var(--hjm-collapsible-gap); min-inline-size: 0; }
3100
3150
  .hjm-collapsible__trigger { inline-size: 100%; min-block-size: var(--hjm-control-min-touch-target); display: flex; align-items: center; justify-content: space-between; gap: var(--hjm-space-sm); padding: var(--hjm-space-xs) 0; border: 0; background: transparent; color: var(--hjm-color-text-body); font: inherit; text-align: start; cursor: pointer; }
3151
+ .hjm-collapsible__header { display: flex; align-items: center; gap: var(--hjm-space-xs); min-block-size: var(--hjm-control-min-touch-target); min-inline-size: 0; }
3152
+ .hjm-collapsible__title { flex: 1; min-inline-size: 0; overflow-wrap: anywhere; }
3153
+ .hjm-collapsible__header[data-titled] > .hjm-collapsible__trigger { inline-size: auto; min-inline-size: var(--hjm-control-min-touch-target); flex: 0 0 auto; }
3154
+ .hjm-collapsible__pending { display: inline-flex; align-items: center; justify-content: center; min-inline-size: var(--hjm-control-min-touch-target); min-block-size: var(--hjm-control-min-touch-target); }
3155
+ .hjm-collapsible__header:not([data-titled]) > .hjm-collapsible__pending { flex: 1; }
3156
+ .hjm-collapsible__header[hidden] { display: none; }
3101
3157
  .hjm-collapsible__trigger:disabled { opacity: 0.5; cursor: not-allowed; }
3102
3158
  .hjm-collapsible__trigger:focus-visible { outline: 2px solid var(--hjm-color-focus); outline-offset: 2px; }
3103
3159
  /* The marker is decoration: aria-expanded carries the state, so it only needs
@@ -3324,6 +3380,8 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
3324
3380
  .hjm-message-composer { display: flex; flex-direction: column; gap: var(--hjm-message-composer-gap, var(--hjm-space-sm)); }
3325
3381
  .hjm-message-composer__row { display: flex; gap: var(--hjm-message-composer-gap, var(--hjm-space-sm)); align-items: flex-end; }
3326
3382
  .hjm-message-composer__row > .hjm-field { flex: 1; min-inline-size: 0; }
3383
+ /* 2026-10-20: numeric composer hints belong at the end; errors keep the field default. */
3384
+ .hjm-message-composer[data-description-align="end"] > .hjm-message-composer__reply-card > .hjm-message-composer__row > .hjm-field > .hjm-field__description { text-align: end; }
3327
3385
  .hjm-message-composer__row > .hjm-button { flex-shrink: 0; }
3328
3386
  /* 2026-10-16 timeline standard (measured KakaoTalk iOS chat room, chatMessageRecipe): filled borderless
3329
3387
  bubbles, one avatar/author/tip per run, time beside the run's last bubble. */
@@ -3393,7 +3451,7 @@ button.hjm-chat-message__media-item:focus-visible { outline: 2px solid var(--hjm
3393
3451
 
3394
3452
  .hjm-image-choice { display: flex; flex-direction: column; gap: var(--hjm-space-xs); }
3395
3453
  .hjm-image-choice__label { font-weight: var(--hjm-text-emphasis-medium); }
3396
- .hjm-image-choice__tiles { display: flex; flex-wrap: wrap; gap: var(--hjm-image-choice-gap); }
3454
+ .hjm-image-choice__tiles { display: grid; grid-template-columns: repeat(auto-fit, calc(var(--hjm-image-choice-size) + (var(--hjm-image-choice-ring) + var(--hjm-image-choice-offset)) * 2)); justify-content: space-between; gap: var(--hjm-image-choice-gap); }
3397
3455
  /* The button is a column (ring frame, optional item label) so the label shares the tap target; the ring is drawn on
3398
3456
  the inner frame (2026-10-18 showItemLabels). */
3399
3457
  .hjm-image-choice__tile { display: flex; flex-direction: column; gap: var(--hjm-image-choice-item-label-gap); inline-size: calc(var(--hjm-image-choice-size) + (var(--hjm-image-choice-ring) + var(--hjm-image-choice-offset)) * 2); padding: 0; border: 0; border-radius: calc(var(--hjm-image-choice-radius) + var(--hjm-image-choice-ring) + var(--hjm-image-choice-offset)); background: none; color: inherit; cursor: pointer; }
@@ -3411,7 +3469,7 @@ button.hjm-chat-message__media-item:focus-visible { outline: 2px solid var(--hjm
3411
3469
  .hjm-image-choice__row { position: absolute; inset-inline: 0; display: flex; gap: var(--hjm-image-choice-gap); }
3412
3470
  .hjm-image-choice__tile:focus-visible { outline: 2px solid var(--hjm-color-focus, currentColor); outline-offset: 2px; }
3413
3471
  .hjm-image-choice__tile:disabled { opacity: 0.5; cursor: default; }
3414
- .hjm-image-choice__image { display: block; inline-size: 100%; block-size: 100%; overflow: hidden; border-radius: var(--hjm-image-choice-radius); background: var(--hjm-color-surface); }
3472
+ .hjm-image-choice__image { display: flex; align-items: center; justify-content: center; inline-size: 100%; block-size: 100%; overflow: hidden; border-radius: var(--hjm-image-choice-radius); background: var(--hjm-color-surface); }
3415
3473
  .hjm-image-choice__image > img { inline-size: 100%; block-size: 100%; object-fit: cover; display: block; }
3416
3474
  .hjm-image-choice__check { position: absolute; inset-block-start: 0; inset-inline-end: 0; inline-size: var(--hjm-image-choice-check); block-size: var(--hjm-image-choice-check); border-radius: 50%; background: var(--hjm-color-content-brand); color: var(--hjm-color-on-primary); font-size: 12px; line-height: var(--hjm-image-choice-check); text-align: center; }
3417
3475
  .hjm-message-composer__leading { flex: 0 0 auto; align-self: center; display: inline-flex; }
@@ -3533,8 +3591,9 @@ button.hjm-chat-message__media-item:focus-visible { outline: 2px solid var(--hjm
3533
3591
  .hjm-segmented[data-presentation="pills"] { background:transparent; border:0; padding:0; }
3534
3592
  /* Keep the inset pill behind the whole line at large text (40px text / 28px fill was observed). Native already includes this inset as vertical padding. */
3535
3593
  .hjm-segmented[data-presentation="pills"] .hjm-segmented__items { flex-wrap:wrap; gap:var(--hjm-space-xs); overflow:visible; padding:0; border:0; border-radius:0; background:transparent; }
3536
- .hjm-segmented[data-presentation="pills"] .hjm-segmented__item { padding-block:var(--hjm-space-xs); position:relative; flex:0 1 auto; min-inline-size:0; min-block-size:var(--hjm-control-min-touch-target); border:0; border-radius:var(--hjm-radius-full); background:transparent; box-shadow:none; padding-inline:var(--hjm-space-md); color:var(--hjm-color-text-muted); }
3537
- .hjm-segmented[data-presentation="pills"] .hjm-segmented__item::before { content:""; position:absolute; inset:var(--hjm-space-xs) 0; border-radius:var(--hjm-radius-full); background:var(--hjm-color-surface-alt); }
3594
+ .hjm-segmented[data-presentation="pills"] .hjm-segmented__item { padding-block:var(--hjm-space-xxs); position:relative; flex:0 1 auto; min-inline-size:0; min-block-size:max(var(--hjm-control-min-touch-target), calc(var(--hjm-segmented-height) + 2 * var(--hjm-space-xxs))); border:0; border-radius:var(--hjm-radius-full); background:transparent; box-shadow:none; padding-inline:var(--hjm-space-md); color:var(--hjm-color-text-muted); }
3595
+ .hjm-segmented[data-presentation="pills"] .hjm-segmented__item::before { content:""; position:absolute; inset:var(--hjm-space-xxs) 0; border-radius:var(--hjm-radius-full); background:var(--hjm-color-surface-alt); }
3596
+ .hjm-segmented[data-presentation="pills"][data-size="small"] .hjm-segmented__item { padding-inline:var(--hjm-space-sm); }
3538
3597
  .hjm-segmented[data-presentation="pills"] .hjm-segmented__item > span { position:relative; overflow-wrap:anywhere; }
3539
3598
  .hjm-segmented[data-presentation="pills"] .hjm-segmented__item[data-state="checked"] { color:var(--hjm-color-bg); font-weight:var(--hjm-font-weight-semibold); }
3540
3599
  .hjm-segmented[data-presentation="pills"] .hjm-segmented__item[data-state="checked"]::before { background:var(--hjm-color-text-body); }
@@ -3607,3 +3666,119 @@ button.hjm-chat-message__media-item:focus-visible { outline: 2px solid var(--hjm
3607
3666
  .hjm-description-list[data-layout="inline"] { gap: 0; }
3608
3667
  .hjm-description-list[data-layout="inline"] .hjm-description-list__item { grid-template-columns: 24% minmax(0, 1fr); gap: var(--hjm-space-sm); padding-block: var(--hjm-space-sm); }
3609
3668
  .hjm-description-list[data-layout="inline"] .hjm-description-list__item + .hjm-description-list__item { border-block-start: 1px solid var(--hjm-color-border); }
3669
+
3670
+ /* A cover action stays separate from creator/metadata/footer controls in a Card. */
3671
+ .hjm-card__media-action { display: block; position: relative; inline-size: 100%; padding: 0; border: 0; background: transparent; color: inherit; cursor: pointer; text-align: inherit; }
3672
+ .hjm-card__media-action:active { opacity: var(--hjm-card-pressed-opacity); }
3673
+ .hjm-card__media-action:focus-visible { outline: var(--hjm-focus-width) solid var(--hjm-color-primary); outline-offset: calc(-1 * var(--hjm-focus-width)); }
3674
+ .hjm-card__media-action:disabled { cursor: default; }
3675
+ .hjm-card__media-icon { position: absolute; display: flex; align-items: center; justify-content: center; border: 1px solid var(--hjm-color-border); border-radius: var(--hjm-radius-full); background: var(--hjm-color-bg); color: var(--hjm-color-text); pointer-events: none; }
3676
+
3677
+ /* Background artwork keeps Card anatomy and independent actions; it is never a second activation target. */
3678
+ .hjm-card[data-background-media="true"] { position: relative; display: flex; flex-direction: column; }
3679
+ .hjm-card__background { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
3680
+ .hjm-card__background > :first-child { width: 100%; height: 100%; }
3681
+ /* A product gesture host stays behind the common copy/actions; corner badges remain readable. */
3682
+ .hjm-card__background-interaction { position: absolute; inset: 0; }
3683
+ .hjm-card__background-interaction > :first-child { width: 100%; height: 100%; }
3684
+ .hjm-card__media-badges { position: absolute; inset-block-start: var(--hjm-space-sm); inset-inline-end: var(--hjm-space-sm); display: flex; flex-wrap: wrap; gap: var(--hjm-space-xs); z-index: 1; }
3685
+ .hjm-card__scrim { position: absolute; inset: 0; background: var(--hjm-card-background-scrim); }
3686
+ .hjm-card__badges { display: flex; flex-wrap: wrap; gap: var(--hjm-space-xs); }
3687
+ .hjm-card[data-background-media="true"] > .hjm-card__body { position: relative; flex: 0 1 auto; margin-block-start: auto; }
3688
+ .hjm-card[data-background-media="true"] > .hjm-card__actions { position: relative; }
3689
+ .hjm-card[data-background-media="true"] .hjm-card__title,
3690
+ .hjm-card[data-background-media="true"] .hjm-card__description { color: var(--hjm-card-background-foreground); }
3691
+
3692
+ @media (forced-colors: active) {
3693
+ .hjm-card__background { display: none; }
3694
+ .hjm-card[data-background-media="true"] :is(.hjm-card__title, .hjm-card__description) { color: CanvasText; }
3695
+ }
3696
+
3697
+ .hjm-statistic__leading { display: inline-flex; align-items: center; color: var(--hjm-statistic-value-color, var(--hjm-color-text)); }
3698
+ .hjm-statistic-group[data-arrangement="bar"] { grid-template-columns: repeat(var(--hjm-statistic-columns), minmax(0, 1fr)); gap: 0; }
3699
+ .hjm-statistic-group[data-arrangement="bar"] > * { min-inline-size: 0; padding-inline: var(--hjm-space-xs); }
3700
+ .hjm-statistic-group[data-arrangement="bar"] > * + * { border-inline-start: 1px solid var(--hjm-color-border); }
3701
+ .hjm-statistic[data-arrangement="bar"] { align-items: center; text-align: center; gap: var(--hjm-space-xxs); }
3702
+ .hjm-statistic[data-arrangement="bar"] .hjm-statistic__label { order: 1; }
3703
+ .hjm-statistic[data-arrangement="bar"] .hjm-statistic__value-row { justify-content: center; align-items: center; }
3704
+ .hjm-statistic[data-arrangement="bar"] :is(.hjm-statistic__trend, .hjm-statistic__hint) { order: 2; }
3705
+
3706
+ .hjm-quote-card__mark { display: inline-flex; align-items: center; color: var(--hjm-color-content-brand); font-size: var(--hjm-type-heading-size); line-height: var(--hjm-type-heading-line-height); }
3707
+ .hjm-quote-card__body { display: grid; gap: var(--hjm-space-xs); margin: 0; min-inline-size: 0; }
3708
+
3709
+ /* NotificationRow's optional command owns focus and feedback; its passive preview owns all geometry. */
3710
+ .hjm-notification-row-action { appearance: none; display: block; inline-size: 100%; border: 0; padding: 0; margin: 0; background: transparent; color: inherit; font: inherit; text-align: start; cursor: pointer; }
3711
+ .hjm-notification-row-action:disabled { opacity: var(--hjm-notification-disabled-opacity); cursor: not-allowed; }
3712
+ .hjm-notification-row-action:enabled:active { opacity: var(--hjm-notification-pressed-opacity); }
3713
+ .hjm-notification-row-action:focus-visible { outline: var(--hjm-focus-width) solid var(--hjm-color-focus); outline-offset: calc(-1 * var(--hjm-focus-width)); }
3714
+
3715
+ .hjm-search-screen--embedded { display: flex; flex-direction: column; flex: 1; min-block-size: 0; }
3716
+ .hjm-search-screen--embedded > .hjm-stack { flex: 1; min-block-size: 0; }
3717
+
3718
+ /* Independent shortcut/remove targets share a Chip-shaped surface; neither button contains the other. */
3719
+ .hjm-shortcut-rail { display: flex; overflow-x: auto; list-style: none; margin: 0; padding: 4px 0; min-inline-size: 0; }
3720
+ .hjm-shortcut-rail[data-empty] { padding: 0; }
3721
+ .hjm-shortcut-rail__item { position: relative; display: inline-flex; align-items: stretch; flex: 0 0 auto; color: var(--hjm-color-text-body); }
3722
+ .hjm-shortcut-rail__item::before { content: ""; pointer-events: none; position: absolute; inset: 4px 0; border: 1px solid var(--hjm-color-border); border-radius: 999px; background: var(--hjm-color-bg); }
3723
+ .hjm-shortcut-rail[data-size="medium"] .hjm-shortcut-rail__item::before { inset-block: 0; }
3724
+ .hjm-shortcut-rail__action, .hjm-shortcut-rail__remove { position: relative; display: inline-flex; align-items: center; justify-content: center; min-block-size: var(--hjm-control-min-touch-target); min-inline-size: var(--hjm-control-min-touch-target); background: transparent; color: inherit; font: inherit; font-weight: var(--hjm-text-emphasis-medium); border: 0; border-radius: 999px; cursor: pointer; }
3725
+ .hjm-shortcut-rail__action { gap: var(--hjm-space-xxs); padding-inline: var(--hjm-space-sm); white-space: nowrap; }
3726
+ .hjm-shortcut-rail[data-size="medium"] .hjm-shortcut-rail__action { gap: var(--hjm-space-xs); padding-inline: var(--hjm-space-md); }
3727
+ .hjm-shortcut-rail__remove { inline-size: var(--hjm-control-min-touch-target); padding: 0; }
3728
+ .hjm-shortcut-rail__remove > span { font-size: 14px; line-height: 1; }
3729
+ .hjm-shortcut-rail__item[data-disabled] { opacity: 0.5; }
3730
+ .hjm-shortcut-rail button:disabled { cursor: not-allowed; }
3731
+ .hjm-shortcut-rail button:active:not(:disabled) { opacity: 0.7; }
3732
+ .hjm-shortcut-rail:focus-visible, .hjm-shortcut-rail button:focus-visible { outline: var(--hjm-focus-width) solid var(--hjm-color-focus); outline-offset: var(--hjm-focus-offset); }
3733
+
3734
+ /* A filter rail scrolls independently of its trailing action (Spint spot adoption). */
3735
+ .hjm-segmented-rail { display:flex; align-items:center; gap:var(--hjm-space-xs); min-inline-size:0; }
3736
+ .hjm-segmented-rail > :last-child { flex-shrink:0; }
3737
+ .hjm-segmented[data-overflow="scroll"] .hjm-segmented__items { flex-direction:row; flex-wrap:nowrap; inline-size:max-content; min-inline-size:100%; }
3738
+ .hjm-segmented[data-overflow="scroll"] .hjm-segmented__item { flex-shrink:0; }
3739
+
3740
+ /* A destination card uses an anchor; disabled links omit href and share the card's disabled feedback. */
3741
+ .hjm-card__activator[aria-disabled="true"] { cursor:default; }
3742
+ .hjm-card[data-activation="overlay"]:has(> .hjm-card__activator[aria-disabled="true"]) > :is(.hjm-card__media,.hjm-card__body) { opacity:var(--hjm-card-disabled-opacity); }
3743
+
3744
+ .hjm-anchor__leading { display: inline-flex; flex: 0 0 auto; }
3745
+ .hjm-anchor__leading svg { inline-size: 100%; block-size: 100%; }
3746
+ .hjm-shortcut-rail[data-layout="wrap"] { flex-wrap: wrap; overflow-x: visible; }
3747
+ .hjm-shortcut-rail[data-layout="wrap"] .hjm-shortcut-rail__item { max-inline-size: 100%; min-inline-size: 0; }
3748
+ .hjm-shortcut-rail[data-layout="wrap"] .hjm-shortcut-rail__action { white-space: normal; overflow-wrap: anywhere; }
3749
+
3750
+ /* TimePicker: one two-column session; dimensions come from the shared recipe on its panel. */
3751
+ .hjm-time-picker { display: grid; gap: var(--hjm-space-xs); min-inline-size: 0; }
3752
+ .hjm-time-picker[data-disabled] { opacity: .5; }
3753
+ .hjm-time-picker__label { font-weight: 500; }
3754
+ .hjm-time-picker__trigger { display:flex; align-items:center; gap:var(--hjm-space-xs); inline-size:100%; min-block-size:44px; padding:var(--hjm-space-sm); border:1px solid var(--hjm-color-border-control); border-radius:var(--hjm-radius-md); background:var(--hjm-color-bg); color:var(--hjm-color-text); font:inherit; font-variant-numeric:tabular-nums; cursor:pointer; }
3755
+ .hjm-time-picker__trigger[aria-invalid=true] { border-color:var(--hjm-color-danger); }
3756
+ .hjm-time-picker__trigger:disabled { cursor:default; }
3757
+ .hjm-time-picker__panel { display:grid; gap:var(--hjm-space-md); inline-size:100%; min-inline-size:0; }
3758
+ .hjm-time-picker__panel > .hjm-button { inline-size:100%; }
3759
+ .hjm-time-picker__readout { text-align:center; font-size:var(--hjm-time-summary); line-height:var(--hjm-time-summary-line-height); font-weight:500; font-variant-numeric:tabular-nums; direction:ltr; }
3760
+ .hjm-time-picker__readout span { color:var(--hjm-color-text-muted); padding-inline:var(--hjm-space-xs); }
3761
+ .hjm-time-picker__columns { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--hjm-space-sm); }
3762
+ .hjm-time-picker__caption { text-align:center; color:var(--hjm-color-text-muted); margin-block-end:var(--hjm-space-xs); }
3763
+ .hjm-time-picker__list { position:relative; block-size:var(--hjm-time-height); overflow-y:auto; overscroll-behavior:contain; scrollbar-width:thin; }
3764
+ .hjm-time-picker__list button { display:block; inline-size:100%; min-block-size:var(--hjm-time-row); border:0; border-radius:var(--hjm-radius-md); background:transparent; color:var(--hjm-color-text); font:inherit; font-variant-numeric:tabular-nums; cursor:pointer; }
3765
+ .hjm-time-picker__list button[aria-selected=true] { background:var(--hjm-color-surface-accent); color:var(--hjm-color-content-brand); font-weight:500; }
3766
+ .hjm-time-picker__list button:disabled { opacity:.4; cursor:default; }
3767
+ .hjm-time-picker__list button:focus-visible,.hjm-time-picker__trigger:focus-visible { outline:2px solid var(--hjm-color-content-brand); outline-offset:-2px; }
3768
+ .hjm-time-picker__description { color:var(--hjm-color-text-muted); }
3769
+ .hjm-time-picker__error { color:var(--hjm-color-danger); }
3770
+
3771
+ /* IconTile's own target keeps the full artwork width; Button's face padding would squeeze narrow grid cells. */
3772
+ .hjm-icon-tile-action { display: block; box-sizing: border-box; width: 100%; margin: 0; padding: 0; border: 0; border-radius: var(--hjm-radius-md); background: transparent; color: inherit; font: inherit; cursor: pointer; }
3773
+ .hjm-icon-tile-action:focus-visible { outline: 2px solid var(--hjm-color-primary); outline-offset: 2px; }
3774
+ .hjm-icon-tile-action:active:not(:disabled) { opacity: var(--hjm-icon-tile-pressed-opacity); }
3775
+ .hjm-icon-tile-action:disabled { opacity: var(--hjm-icon-tile-disabled-opacity); cursor: default; }
3776
+
3777
+ /* Position-only pager indicators have no small interactive targets; adjacent pager controls own navigation. */
3778
+ .hjm-page-indicator__marker, .hjm-page-indicator__marker > span { display: block; inline-size: var(--hjm-space-xs); block-size: var(--hjm-space-xs); border-radius: var(--hjm-radius-full); }
3779
+ .hjm-page-indicator__marker > span { background: var(--hjm-color-text-weak); }
3780
+ .hjm-page-indicator__marker[data-current="true"] > span { background: var(--hjm-color-content-brand); }
3781
+
3782
+ /* Commands remain independent of the passive record and rail. */
3783
+ .hjm-timeline__item:has(> .hjm-timeline__actions) { grid-template-columns: 1rem minmax(0, 1fr) auto; }
3784
+ .hjm-timeline__actions { align-self: center; display: flex; align-items: center; gap: var(--hjm-space-xs); }