/* Component classes. Load after base.css; the brand file decides the colours. */
/* The components measure themselves border-box. The min-height on a button and the
     100% width on a field are the outer size, not the size before padding and border are
     added, and every size token is written on that basis. This lives here rather than in
     the page that happens to load it, because a page that forgets it gets controls that
     are quietly taller and wider than the tokens say. */
  *, *::before, *::after { box-sizing: border-box; }

  /* Large is the default size; medium is what you opt into. */
  .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sg-action-large-gap);
    border: 1px solid transparent;
    border-radius: var(--sg-action-radius);
    min-height: var(--sg-action-large-min-height);
    padding: var(--sg-action-large-padding-block) var(--sg-action-large-padding-inline);
    font-family: inherit;
    font-size: var(--sg-action-large-font-size);
    line-height: var(--sg-action-large-line-height);
    font-weight: var(--sg-font-weight-500);
    cursor: pointer;
  }
  .btn[data-size='medium'] {
    gap: var(--sg-action-medium-gap);
    min-height: var(--sg-action-medium-min-height);
    padding: var(--sg-action-medium-padding-block) var(--sg-action-medium-padding-inline);
    font-size: var(--sg-action-medium-font-size);
    line-height: var(--sg-action-medium-line-height);
  }
  /* Icons take the button's own text colour, so they never disagree with the label. */
  .btn svg {
    flex: 0 0 auto;
    width: var(--sg-action-large-icon-size);
    height: var(--sg-action-large-icon-size);
  }
  .btn[data-size='medium'] svg {
    width: var(--sg-action-medium-icon-size);
    height: var(--sg-action-medium-icon-size);
  }
  /* An icon-only button is square: the height sets the floor for the width too. */
  .btn[data-icon-only] {
    min-width: var(--sg-action-large-min-height);
    padding-inline: var(--sg-action-large-padding-block);
  }
  .btn[data-icon-only][data-size='medium'] {
    min-width: var(--sg-action-medium-min-height);
    padding-inline: var(--sg-action-medium-padding-block);
  }
  /* Each state is written twice on purpose: the real selector is what a consumer gets, and
     the data-state twin is how the demo shows a state next to its resting form without a
     cursor on it. The demo attribute alone shipped for a while, and buttons reached three
     applications with no hover, no focus ring and a disabled that still looked pressable. */
  .btn[data-variant='primary'] {
    background: var(--sg-action-primary-background);
    color: var(--sg-action-primary-text);
  }
  .btn[data-variant='primary']:hover:not(:disabled),
  .btn[data-variant='primary'][data-state='hover'] { background: var(--sg-action-primary-background-hover); }
  .btn[data-variant='secondary'] {
    background: var(--sg-action-secondary-background);
    border-color: var(--sg-action-secondary-border);
    color: var(--sg-action-secondary-text);
  }
  .btn[data-variant='secondary']:hover:not(:disabled),
  .btn[data-variant='secondary'][data-state='hover'] { background: var(--sg-action-secondary-background-hover); }
  .btn[data-variant='tertiary'] {
    background: transparent;
    color: var(--sg-action-tertiary-text);
  }
  .btn[data-variant='tertiary']:hover:not(:disabled),
  .btn[data-variant='tertiary'][data-state='hover'] { background: var(--sg-action-tertiary-background-hover); }
  .btn:focus-visible,
  .btn[data-state='focus'] { outline: 2px solid var(--sg-action-focus-ring); outline-offset: 2px; }
  /* :not([data-state]) rather than naming the states to exclude. A button that is working
     or reporting a result is still disabled so a second press cannot land, but it is not
     off, and it keeps the colour that says so. Naming them one by one also raises the
     specificity above the state rules, which is how success and error went grey. */
  .btn:disabled:not([data-state]),
  .btn[data-state='disabled'] {
    background: var(--sg-action-disabled-background);
    border-color: transparent;
    color: var(--sg-action-disabled-text);
    cursor: default;
  }
  .btn[data-state='loading'] { cursor: progress; }
  .btn[data-state='success'] {
    background: var(--sg-action-success-background);
    border-color: transparent;
    color: var(--sg-action-success-text);
  }
  .btn[data-state='error'] {
    background: var(--sg-action-error-background);
    border-color: transparent;
    color: var(--sg-action-error-text);
  }

  /* Takes the button's own text colour, so it works on every variant. */
  .spinner {
    flex: 0 0 auto;
    width: var(--sg-action-large-icon-size);
    height: var(--sg-action-large-icon-size);
    border: 2px solid currentColor;
    border-block-start-color: transparent;
    border-radius: var(--sg-radius-full);
    animation: spin var(--sg-motion-loop-duration) var(--sg-motion-loop-easing) infinite;
  }
  .btn[data-size='medium'] .spinner {
    width: var(--sg-action-medium-icon-size);
    height: var(--sg-action-medium-icon-size);
  }
  /* The spinner sits on top of the label rather than beside it, so a button is the same
     width working as it is at rest. Beside it, the button grows by an icon and a gap and
     the whole row shifts under the pointer that just pressed it. The label stays in the
     element — only its ink is hidden — so a screen reader still has something to name the
     control, and aria-busy says what is going on. */
  .btn[data-state='loading'] {
    position: relative;
    color: transparent;
  }
  .btn[data-state='loading'] .spinner {
    position: absolute;
    inset-block-start: 50%;
    inset-inline-start: 50%;
    translate: -50% -50%;
  }
  /* Named per variant because a transparent label takes currentColor with it. Each one
     borrows the colour its own text would have had. */
  .btn[data-variant='primary'][data-state='loading'] .spinner { border-color: var(--sg-action-primary-text); border-block-start-color: transparent; }
  .btn[data-variant='secondary'][data-state='loading'] .spinner { border-color: var(--sg-action-secondary-text); border-block-start-color: transparent; }
  .btn[data-variant='tertiary'][data-state='loading'] .spinner { border-color: var(--sg-action-tertiary-text); border-block-start-color: transparent; }
  @keyframes spin { to { transform: rotate(360deg); } }

  /* Anything that changes colour under the pointer settles rather than snapping. Listed
     in one place so a new component cannot forget it, and so the preference below only
     has to be honoured once. */
  .btn,
  .chip,
  .list-row,
  .option,
  .picker-button,
  .datepicker-day,
  .datepicker-nav,
  .segmented-item,
  .dropdown-item,
  .accordion summary,
  .token-reset,
  :is(a, button).card,
  .tree-row,
  .table tbody td {
    transition:
      background-color var(--sg-motion-state-duration) var(--sg-motion-state-easing),
      border-color var(--sg-motion-state-duration) var(--sg-motion-state-easing),
      color var(--sg-motion-state-duration) var(--sg-motion-state-easing);
  }

  /* Motion is a preference, not a decoration. Transitions are cut everywhere at once;
     the spinner is slowed instead of stopped, since a frozen one reads as a hang. */
  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { transition-duration: 1ms !important; }
    .spinner { animation-duration: 2.4s; }
  }

  .field-group { display: flex; flex-direction: column; gap: var(--sg-field-gap); }
  .field-label { color: var(--sg-field-label); font-size: var(--sg-field-label-font-size); line-height: var(--sg-field-label-line-height); font-weight: var(--sg-font-weight-500); }
  .field-hint { color: var(--sg-field-hint); font-size: var(--sg-field-hint-font-size); line-height: var(--sg-field-hint-line-height); font-weight: var(--sg-font-weight-400); }
  .field {
    min-width: 12rem;
    background: var(--sg-field-background);
    color: var(--sg-field-text);
    border: 1px solid var(--sg-field-border);
    border-radius: var(--sg-field-radius);
    font-family: inherit;
    min-height: var(--sg-field-large-min-height);
    padding: var(--sg-field-large-padding-block) var(--sg-field-large-padding-inline);
    font-size: var(--sg-field-large-font-size);
    line-height: var(--sg-field-large-line-height);
    font-weight: var(--sg-font-weight-400);
  }
  .field[data-size='medium'] {
    min-height: var(--sg-field-medium-min-height);
    padding: var(--sg-field-medium-padding-block) var(--sg-field-medium-padding-inline);
    font-size: var(--sg-field-medium-font-size);
    line-height: var(--sg-field-medium-line-height);
  }
  .field::placeholder { color: var(--sg-field-placeholder); }
  .field:hover { border-color: var(--sg-field-border-hover); }
  .field:focus-visible,
  .field[data-state='focus'] {
    border-color: var(--sg-field-border-focus);
    box-shadow: 0 0 0 2px var(--sg-field-border-focus);
    /* The ring is a shadow, and shadows are dropped in forced-colours mode. A transparent
       outline is invisible here and becomes the focus ring there. */
    outline: 2px solid transparent;
    outline-offset: 2px;
  }
  .field[data-state='error'] { border-color: var(--sg-field-border-error); }
  .field:disabled {
    background: var(--sg-field-background-disabled);
    color: var(--sg-field-text-disabled);
  }
  textarea.field { resize: vertical; min-height: 4rem; }

  /* One answer in several parts is one bordered box. Two fields side by side would be two
     outlines for one answer, and a focus ring that fits neither.

     The box carries the border, the hover, the focus, the error and the sizes; the parts
     inside carry nothing. This was written out once per composed field until there were
     three of them, and the copies had already drifted: a disabled stepper stayed white
     while a disabled phone greyed. Anything made of parts sits on this now. */
  .field-box {
    display: flex;
    align-items: stretch;
    background: var(--sg-field-background);
    border: 1px solid var(--sg-field-border);
    border-radius: var(--sg-field-radius);
    min-height: var(--sg-field-large-min-height);
    font-size: var(--sg-field-large-font-size);
    line-height: var(--sg-field-large-line-height);
    font-weight: var(--sg-font-weight-400);
  }
  .field-box[data-size='medium'] {
    min-height: var(--sg-field-medium-min-height);
    font-size: var(--sg-field-medium-font-size);
    line-height: var(--sg-field-medium-line-height);
  }
  .field-box:hover { border-color: var(--sg-field-border-hover); }
  .field-box:has(:focus-visible),
  .field-box[data-state='focus'] {
    border-color: var(--sg-field-border-focus);
    box-shadow: 0 0 0 2px var(--sg-field-border-focus);
    /* The ring is a shadow, and shadows are dropped in forced-colours mode. A transparent
       outline is invisible here and becomes the focus ring there. */
    outline: 2px solid transparent;
    outline-offset: 2px;
  }
  .field-box[data-state='error'] { border-color: var(--sg-field-border-error); }
  /* Reached through the part that holds the value, not through any disabled descendant: a
     stepper at its minimum disables one button and is still very much on. */
  .field-box:has(.field-box-input:disabled) { background: var(--sg-field-background-disabled); }
  /* Every part gives up its own chrome. The border and the ring belong to the box, so a
     part that drew either would put a second outline inside the first. */
  .field-box > * {
    font: inherit;
    background: none;
    border: 0;
    color: var(--sg-field-text);
    min-inline-size: 0;
  }
  .field-box > :focus-visible { outline: none; }
  .field-box > :disabled { color: var(--sg-field-text-disabled); }
  .field-box-input {
    flex: 1 1 auto;
    padding: var(--sg-field-large-padding-block) var(--sg-field-large-padding-inline);
  }
  .field-box[data-size='medium'] .field-box-input {
    padding: var(--sg-field-medium-padding-block) var(--sg-field-medium-padding-inline);
  }
  .field-box-input::placeholder { color: var(--sg-field-placeholder); }
  /* Decoration, not a control: it says what the field is for and is never tabbed to. */
  .field-box-icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    padding-inline-start: var(--sg-field-large-padding-inline);
    color: var(--sg-icon-muted);
  }
  .field-box[data-size='medium'] .field-box-icon {
    padding-inline-start: var(--sg-field-medium-padding-inline);
  }
  .field-box-icon svg {
    inline-size: var(--sg-icon-size-medium);
    block-size: var(--sg-icon-size-medium);
  }
  /* Square, so it matches the height it sits in rather than inventing a size of its own. */
  .field-box-action {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: var(--sg-field-large-min-height);
    cursor: pointer;
  }
  .field-box[data-size='medium'] .field-box-action { inline-size: var(--sg-field-medium-min-height); }
  .field-box-action:hover:not(:disabled) { background: var(--sg-field-box-action-background-hover); }
  .field-box-action:disabled { cursor: default; }
  .field-box-action svg {
    inline-size: var(--sg-icon-size-medium);
    block-size: var(--sg-icon-size-medium);
  }
  /* A unit or a currency: part of the answer, but not part of what is typed. */
  .field-box-text {
    display: inline-flex;
    align-items: center;
    padding-inline-end: var(--sg-padding-sm);
    color: var(--sg-field-hint);
    white-space: nowrap;
  }

  /* A phone number is one value in two parts. Everything that makes it a box comes from
     .field-box; what is left here is the divider between the country and the number. */
  .phone { min-inline-size: 12rem; }
  .phone-code {
    flex: 0 0 auto;
    padding: var(--sg-field-large-padding-block) var(--sg-field-large-padding-inline);
    border-inline-end: 1px solid var(--sg-phone-divider);
  }
  .field-box[data-size='medium'] .phone-code {
    padding: var(--sg-field-medium-padding-block) var(--sg-field-medium-padding-inline);
  }

  /* One value with two ways to change it. The number is a text input with a numeric
     keyboard rather than type=number: the native spinners would be a second pair of
     buttons doing what these two already do, and a scroll wheel over the field would
     change an order quantity by accident. */
  .stepper {
    display: inline-flex;
    /* A quantity is not a column-width thing. Without this it stretches to whatever it is
       dropped into, and an order line gets a 900px box around the number 55. */
    inline-size: fit-content;
  }
  /* Sized in ch, which is the advance of a zero, because the requirement is a number of
     digits and not a number of pixels — it then holds across a brand that ships a wider
     font. Five ch, not four: ch measures a zero, and the wider digits in a proportional
     font need the slack. Four digits fit, so three is never in doubt.

     The inline padding is its own because the one inherited from .field-box-input is meant
     for text starting at the left edge. On a centred number it was 16px of gutter on each
     side of a 48px box, leaving 14px for digits that need 26. */
  .stepper-value {
    flex: 0 0 auto;
    inline-size: calc(5ch + 2 * var(--sg-padding-xs));
    padding-inline: var(--sg-padding-xs);
    text-align: center;
    border-inline: 1px solid var(--sg-stepper-divider);
  }
  /* A search field is the same box again: something that says what it is for, something to
     type in, and a way back to the full list. */
  .search { min-inline-size: 12rem; }
  /* Nothing to clear yet, so nothing to press. Hidden rather than disabled: a control that
     spends most of its life greyed out is furniture, not an affordance. */
  .search-clear[hidden] { display: none; }
  /* A date field is a field. Only the browser's own spin and clear affordances are given
     room, so the native calendar button lands inside the border instead of on top of it. */
  input.field[type='date'] { padding-inline-end: var(--sg-field-large-padding-inline); }
  input.field[type='date'][data-size='medium'] { padding-inline-end: var(--sg-field-medium-padding-inline); }
  input.field[type='date']::-webkit-calendar-picker-indicator { cursor: pointer; }

  /* A text field that guarantees its own order, for when the native input's locale is not
     something you are willing to leave to the reader's browser. */
  .datepicker-field { position: relative; display: flex; align-items: center; }
  .datepicker-field .field { inline-size: 100%; padding-inline-end: calc(var(--sg-datepicker-day-size) + var(--sg-spacing-4)); }
  .datepicker-trigger {
    position: absolute;
    inset-inline-end: var(--sg-spacing-4);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: var(--sg-datepicker-day-size);
    block-size: var(--sg-datepicker-day-size);
    padding: 0;
    border: none;
    border-radius: var(--sg-datepicker-day-radius);
    background: none;
    color: var(--sg-datepicker-icon);
    cursor: pointer;
  }
  .datepicker-trigger:hover { background: var(--sg-datepicker-day-background-hover); }
  .datepicker-trigger:focus-visible { outline: 2px solid var(--sg-action-focus-ring); outline-offset: -2px; }
  .datepicker-trigger svg { inline-size: var(--sg-datepicker-icon-size); block-size: var(--sg-datepicker-icon-size); }
  /* The calendar hangs off the field rather than pushing the form down when it opens. */
  .datepicker-anchor { position: relative; }
  .datepicker-anchor .datepicker { position: absolute; inset-block-start: calc(100% + 0.25rem); inset-inline-start: 0; z-index: 20; }

  /* The calendar. Only for dates native cannot express — an unavailable Sunday, a lead
     time — since min and max are all the input itself understands. */
  .datepicker {
    display: inline-flex;
    flex-direction: column;
    gap: var(--sg-datepicker-padding);
    padding: var(--sg-datepicker-padding);
    background: var(--sg-datepicker-background);
    border: 1px solid var(--sg-datepicker-border);
    border-radius: var(--sg-datepicker-radius);
    box-shadow: var(--sg-elevation-overlay);
  }
  .datepicker-header { display: flex; align-items: center; justify-content: space-between; gap: var(--sg-datepicker-padding); }
  .datepicker-month {
    color: var(--sg-datepicker-header-text);
    font-size: var(--sg-datepicker-header-font-size);
    line-height: var(--sg-datepicker-header-line-height);
    font-weight: var(--sg-font-weight-600);
  }
  .datepicker-nav {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: var(--sg-datepicker-day-size);
    block-size: var(--sg-datepicker-day-size);
    padding: 0;
    border: none;
    border-radius: var(--sg-datepicker-day-radius);
    background: none;
    color: var(--sg-datepicker-icon);
    cursor: pointer;
  }
  .datepicker-nav:hover { background: var(--sg-datepicker-day-background-hover); }
  .datepicker-nav:focus-visible { outline: 2px solid var(--sg-action-focus-ring); outline-offset: -2px; }
  .datepicker-nav svg { inline-size: var(--sg-datepicker-icon-size); block-size: var(--sg-datepicker-icon-size); }
  .datepicker-nav[data-direction='previous'] svg { rotate: 180deg; }
  .datepicker-grid { border-collapse: separate; border-spacing: var(--sg-datepicker-gap); }
  .datepicker-grid th {
    inline-size: var(--sg-datepicker-day-size);
    padding: 0;
    color: var(--sg-datepicker-weekday-text);
    font-size: var(--sg-datepicker-day-font-size);
    line-height: var(--sg-datepicker-day-line-height);
    font-weight: var(--sg-font-weight-500);
  }
  .datepicker-grid th abbr { text-decoration: none; }
  .datepicker-grid td { padding: 0; }
  .datepicker-day {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: var(--sg-datepicker-day-size);
    block-size: var(--sg-datepicker-day-size);
    padding: 0;
    border: none;
    border-radius: var(--sg-datepicker-day-radius);
    background: none;
    color: var(--sg-datepicker-day-text);
    font-family: inherit;
    font-size: var(--sg-datepicker-day-font-size);
    line-height: var(--sg-datepicker-day-line-height);
    /* Not the 500 the other controls carry: forty-two numbers at that weight reads as a
       grid shouting. The fill marks the selection, so the weight does not have to. */
    font-weight: var(--sg-font-weight-400);
    font-variant-numeric: tabular-nums;
    cursor: pointer;
  }
  .datepicker-day[data-outside] { color: var(--sg-datepicker-day-text-outside); }
  .datepicker-day:hover { background: var(--sg-datepicker-day-background-hover); }
  .datepicker-day:focus-visible { outline: 2px solid var(--sg-action-focus-ring); outline-offset: -2px; }
  /* Today is a dot, not a fill: it has to stay legible under the selected fill, since the
     day you are on and the day you picked are often the same day. */
  .datepicker-day[data-today]::after {
    content: '';
    position: absolute;
    inset-block-end: 0.3rem;
    inline-size: 0.25rem;
    block-size: 0.25rem;
    border-radius: var(--sg-radius-full);
    background: var(--sg-datepicker-today-marker);
  }
  .datepicker-day[aria-pressed='true'] {
    background: var(--sg-datepicker-day-background-selected);
    color: var(--sg-datepicker-day-text-selected);
  }
  .datepicker-day[aria-pressed='true'][data-today]::after { background: var(--sg-datepicker-day-text-selected); }
  .datepicker-day:disabled {
    color: var(--sg-datepicker-day-text-disabled);
    background: none;
    cursor: default;
  }
  /* An unavailable day is struck through as well as dimmed, since dimmed alone is the same
     signal as "belongs to another month" and the two mean very different things. */
  .datepicker-day:disabled { text-decoration: line-through; }

  .check { display: inline-flex; align-items: center; gap: var(--sg-control-gap); font-size: var(--sg-body-small-font-size); line-height: var(--sg-body-small-line-height); font-weight: var(--sg-font-weight-400); cursor: pointer; }
  /* The wrapper is whatever element is acting as the label: the control on its own, or
     a whole list row. The state always hangs off the input's next sibling either way. */
  :is(.check, .switch, .list-row, .segmented-item, .option, .tree-label) input { position: absolute; opacity: 0; pointer-events: none; }
  .check-box {
    display: grid;
    place-items: center;
    width: var(--sg-control-size);
    height: var(--sg-control-size);
    background: var(--sg-control-background);
    border: 1px solid var(--sg-control-border);
    border-radius: var(--sg-control-radius);
  }
  .check-round .check-box { border-radius: var(--sg-radius-full); }
  .check-box::after {
    content: '';
    width: 0.5rem;
    height: 0.5rem;
    border-radius: inherit;
    background: var(--sg-control-mark);
    transform: scale(0);
  }
  :is(.check, .list-row, .tree-label) input:checked + .check-box {
    background: var(--sg-control-background-selected);
    border-color: var(--sg-control-border-selected);
  }
  :is(.check, .list-row, .tree-label) input:checked + .check-box::after { transform: scale(1); }
  /* Partly selected is its own answer. Showing it as either ticked or empty misreports
     what submitting the form will do, so it gets a dash rather than the mark. */
  :is(.check, .list-row, .tree-label) input:indeterminate + .check-box {
    background: var(--sg-control-background-selected);
    border-color: var(--sg-control-border-selected);
  }
  :is(.check, .list-row, .tree-label) input:indeterminate + .check-box::after {
    transform: scale(1);
    height: 2px;
    border-radius: 1px;
  }
  :is(.check, .list-row, .tree-label) input:focus-visible + .check-box { outline: 2px solid var(--sg-action-focus-ring); outline-offset: 2px; }

  /* Large is the default size; medium is what you opt into. */
  .chips { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
  .chip {
    display: inline-flex;
    align-items: center;
    gap: var(--sg-chip-large-gap);
    min-height: var(--sg-chip-large-min-height);
    padding-inline: var(--sg-chip-large-padding-inline);
    background: var(--sg-chip-background);
    color: var(--sg-chip-text);
    border: 1px solid var(--sg-chip-border);
    border-radius: var(--sg-chip-radius);
    font-family: inherit;
    font-size: var(--sg-chip-large-font-size);
    line-height: var(--sg-chip-large-line-height);
    /* The weight buttons and segments use. A chip shares a row with both, and at the same
       size the lighter weight reads as text that happens to have a border round it. */
    font-weight: var(--sg-font-weight-500);
    cursor: pointer;
  }
  .chip[data-size='medium'] {
    gap: var(--sg-chip-medium-gap);
    min-height: var(--sg-chip-medium-min-height);
    padding-inline: var(--sg-chip-medium-padding-inline);
    font-size: var(--sg-chip-medium-font-size);
    line-height: var(--sg-chip-medium-line-height);
  }
  .chip[data-size='small'] {
    gap: var(--sg-chip-small-gap);
    min-height: var(--sg-chip-small-min-height);
    padding-inline: var(--sg-chip-small-padding-inline);
    font-size: var(--sg-chip-small-font-size);
    line-height: var(--sg-chip-small-line-height);
  }
  .chip:hover { background: var(--sg-chip-background-hover); }
  .chip[aria-pressed='true'] {
    background: var(--sg-chip-selected-background);
    border-color: var(--sg-chip-selected-border);
    color: var(--sg-chip-selected-text);
    font-weight: var(--sg-font-weight-500);
  }
  .chip:focus-visible { outline: 2px solid var(--sg-action-focus-ring); outline-offset: 2px; }
  .chip[data-static] { cursor: default; }
  .chip-remove {
    display: grid;
    place-items: center;
    width: 1rem;
    height: 1rem;
    margin-inline-end: -0.125rem;
    padding: 0;
    background: none;
    border: none;
    border-radius: var(--sg-radius-full);
    color: inherit;
    font: inherit;
    line-height: 1;
    cursor: pointer;
  }
  .chip-remove:hover { background: var(--sg-chip-selected-border); color: var(--sg-color-neutral-0); }
  .chip-remove:focus-visible { outline: 2px solid var(--sg-action-focus-ring); outline-offset: 1px; }

  /* Sized like a chip so the two line up in a row, but a badge is a label: no border,
     no hover, nothing to press. */
  .badges { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
  .badge {
    display: inline-flex;
    align-items: center;
    gap: var(--sg-badge-large-gap);
    min-height: var(--sg-badge-large-min-height);
    padding-inline: var(--sg-badge-large-padding-inline);
    background: var(--sg-badge-neutral-background);
    color: var(--sg-badge-neutral-text);
    border-radius: var(--sg-badge-radius);
    font-family: inherit;
    font-size: var(--sg-badge-large-font-size);
    line-height: var(--sg-badge-large-line-height);
    font-weight: var(--sg-font-weight-500);
    white-space: nowrap;
  }
  .badge[data-size='medium'] {
    gap: var(--sg-badge-medium-gap);
    min-height: var(--sg-badge-medium-min-height);
    padding-inline: var(--sg-badge-medium-padding-inline);
    font-size: var(--sg-badge-medium-font-size);
    line-height: var(--sg-badge-medium-line-height);
  }
  .badge[data-size='small'] {
    gap: var(--sg-badge-small-gap);
    min-height: var(--sg-badge-small-min-height);
    padding-inline: var(--sg-badge-small-padding-inline);
    font-size: var(--sg-badge-small-font-size);
    line-height: var(--sg-badge-small-line-height);
  }
  .badge[data-status='info'] {
    background: var(--sg-badge-info-background);
    color: var(--sg-badge-info-text);
  }
  .badge[data-status='success'] {
    background: var(--sg-badge-success-background);
    color: var(--sg-badge-success-text);
  }
  .badge[data-status='warning'] {
    background: var(--sg-badge-warning-background);
    color: var(--sg-badge-warning-text);
  }
  .badge[data-status='error'] {
    background: var(--sg-badge-error-background);
    color: var(--sg-badge-error-text);
  }

  /* Built on <details>, so open and closed, keyboard and screen reader support all come
     from the element rather than from script. */
  .accordion {
    display: flex;
    flex-direction: column;
    background: var(--sg-accordion-background);
    border: 1px solid var(--sg-accordion-border);
    border-radius: var(--sg-accordion-radius);
    overflow: hidden;
  }
  .accordion details + details { border-block-start: 1px solid var(--sg-accordion-border); }
  .accordion summary {
    display: flex;
    align-items: center;
    gap: var(--sg-accordion-gap);
    min-height: var(--sg-accordion-min-height);
    padding: var(--sg-accordion-padding-block) var(--sg-accordion-padding-inline);
    cursor: pointer;
    list-style: none;
  }
  .accordion summary::-webkit-details-marker { display: none; }
  /* The open section carries the tint on the whole box, so the panel is part of what was
     opened rather than something floating under a coloured header. */
  .accordion details[open] { background: var(--sg-accordion-background-open); }
  /* Only closed headers answer a hover. On an open one the hover step is lighter than the
     open step, so it would read as the section closing again under the pointer. */
  .accordion details:not([open]) summary:hover { background: var(--sg-accordion-background-hover); }
  .accordion summary:focus-visible { outline: 2px solid var(--sg-action-focus-ring); outline-offset: -2px; }
  .accordion-text { display: flex; flex-direction: column; gap: 0.125rem; flex: 1; }
  .accordion-title {
    color: var(--sg-accordion-title);
    font-size: var(--sg-accordion-title-font-size);
    line-height: var(--sg-accordion-title-line-height);
    font-weight: var(--sg-font-weight-600);
  }
  .accordion-supporting {
    color: var(--sg-accordion-supporting-text);
    font-size: var(--sg-accordion-supporting-font-size);
    line-height: var(--sg-accordion-supporting-line-height);
    font-weight: var(--sg-font-weight-400);
  }
  .accordion summary svg {
    flex: 0 0 auto;
    width: var(--sg-accordion-icon-size);
    height: var(--sg-accordion-icon-size);
    color: var(--sg-accordion-icon);
    transition: rotate var(--sg-motion-move-duration) var(--sg-motion-move-easing);
  }
  .accordion details[open] summary svg { rotate: 180deg; }
  .accordion-panel {
    padding: 0 var(--sg-accordion-padding-inline) var(--sg-accordion-padding-block);
    color: var(--sg-accordion-content-text);
    font-size: var(--sg-accordion-content-font-size);
    line-height: var(--sg-accordion-content-line-height);
    font-weight: var(--sg-font-weight-400);
  }

  /* Built on <hr>, so a divider that separates content is announced as a separator.
     The decorative ones in the demos are marked aria-hidden instead. */
  .divider {
    margin: 0;
    border: none;
    align-self: stretch;
    background: var(--sg-divider-color);
    block-size: var(--sg-divider-thickness);
  }
  .divider[data-weight='strong'] { background: var(--sg-divider-color-strong); }
  .divider[data-orientation='vertical'] {
    block-size: auto;
    inline-size: var(--sg-divider-thickness);
  }
  .divider-label {
    display: flex;
    align-items: center;
    gap: var(--sg-divider-label-gap);
    color: var(--sg-divider-label-text);
    font-size: var(--sg-divider-label-font-size);
    line-height: var(--sg-divider-label-line-height);
    font-weight: var(--sg-font-weight-400);
  }
  .divider-label .divider { flex: 1; }
  /* A stack showing the space a divider is meant to sit in. */
  .divider-stack { display: flex; flex-direction: column; gap: var(--sg-divider-space); max-width: 32rem; }
  .divider-bar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0.75rem;
    background: var(--sg-surface-raised);
    border: 1px solid var(--sg-border-subtle);
    border-radius: var(--sg-radius-6);
    align-self: flex-start;
  }

  /* Built on <details> so the demo opens and closes without script. A real menu button
     needs more than this; the guidance says what. */
  .dropdown { position: relative; display: inline-block; }
  .dropdown > summary { list-style: none; }
  .dropdown > summary::-webkit-details-marker { display: none; }
  .dropdown[open] > summary svg { rotate: 180deg; }
  .dropdown-panel {
    position: absolute;
    z-index: 3;
    inset-block-start: calc(100% + var(--sg-dropdown-gap));
    inset-inline-start: 0;
    min-inline-size: 15rem;
    padding-block: var(--sg-dropdown-padding-block);
    background: var(--sg-dropdown-background);
    border: 1px solid var(--sg-dropdown-border);
    border-radius: var(--sg-dropdown-radius);
    box-shadow: var(--sg-elevation-overlay);
  }
  .dropdown-item {
    display: flex;
    align-items: center;
    gap: var(--sg-dropdown-item-gap);
    inline-size: 100%;
    min-height: var(--sg-dropdown-item-min-height);
    padding-inline: var(--sg-dropdown-item-padding-inline);
    background: none;
    border: none;
    color: var(--sg-dropdown-item-text);
    font-family: inherit;
    font-size: var(--sg-dropdown-item-font-size);
    line-height: var(--sg-dropdown-item-line-height);
    text-align: start;
    cursor: pointer;
  }
  .dropdown-item:hover { background: var(--sg-dropdown-item-background-hover); }
  .dropdown-item:focus-visible { outline: 2px solid var(--sg-action-focus-ring); outline-offset: -2px; }
  .dropdown-item[aria-checked='true'] {
    background: var(--sg-dropdown-item-background-selected);
    color: var(--sg-dropdown-item-text-selected);
    font-weight: var(--sg-font-weight-500);
  }
  .dropdown-item[data-danger] { color: var(--sg-dropdown-item-text-danger); }
  .dropdown-item svg {
    flex: 0 0 auto;
    width: var(--sg-dropdown-icon-size);
    height: var(--sg-dropdown-icon-size);
    color: var(--sg-dropdown-icon);
  }
  /* A coloured item owns its icon too, or the two disagree about what the row means. */
  .dropdown-item[data-danger] svg,
  .dropdown-item[aria-checked='true'] svg { color: currentColor; }
  .dropdown-label {
    display: block;
    padding: var(--sg-dropdown-padding-block) var(--sg-dropdown-item-padding-inline);
    color: var(--sg-dropdown-section-label);
    font-size: var(--sg-dropdown-section-label-font-size);
    line-height: var(--sg-dropdown-section-label-line-height);
    font-weight: var(--sg-font-weight-600);
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }
  .dropdown-panel .divider { margin-block: var(--sg-dropdown-padding-block); }
  .dropdown-over { display: flex; flex-direction: column; gap: 0.75rem; max-width: 34rem; }

  /* The knob travels exactly the difference between the track's width and its height,
     which keeps the inset equal on both ends whatever the sizes are set to. */
  .switch { display: inline-flex; align-items: flex-start; gap: var(--sg-switch-gap); cursor: pointer; }
  .switch-track {
    position: relative;
    flex: 0 0 auto;
    inline-size: var(--sg-switch-track-width);
    block-size: var(--sg-switch-track-height);
    background: var(--sg-switch-track-background);
    border-radius: var(--sg-switch-radius);
    transition: background var(--sg-motion-state-duration) var(--sg-motion-state-easing);
  }
  .switch-knob {
    position: absolute;
    inset-block-start: calc((var(--sg-switch-track-height) - var(--sg-switch-knob-size)) / 2);
    inset-inline-start: calc((var(--sg-switch-track-height) - var(--sg-switch-knob-size)) / 2);
    inline-size: var(--sg-switch-knob-size);
    block-size: var(--sg-switch-knob-size);
    background: var(--sg-switch-knob);
    border-radius: var(--sg-radius-full);
    transition: translate var(--sg-motion-move-duration) var(--sg-motion-move-easing);
  }
  :is(.switch, .list-row) input:checked + .switch-track { background: var(--sg-switch-track-background-checked); }
  :is(.switch, .list-row) input:checked + .switch-track .switch-knob {
    translate: calc(var(--sg-switch-track-width) - var(--sg-switch-track-height)) 0;
  }
  :is(.switch, .list-row) input:focus-visible + .switch-track { outline: 2px solid var(--sg-action-focus-ring); outline-offset: 2px; }
  :is(.switch, .list-row) input:disabled + .switch-track { background: var(--sg-switch-track-background-disabled); }
  .switch-text { display: flex; flex-direction: column; gap: 0.125rem; color: var(--sg-switch-label); }
  .switch-label {
    font-size: var(--sg-switch-label-font-size);
    line-height: var(--sg-switch-label-line-height);
    font-weight: var(--sg-font-weight-400);
  }
  .switch-supporting { color: var(--sg-switch-supporting-text); font-size: var(--sg-switch-supporting-font-size); line-height: var(--sg-switch-supporting-line-height); font-weight: var(--sg-font-weight-400); }
  /* Disabled takes the whole block, supporting text included, or the two disagree. */
  .switch input:disabled ~ .switch-text { color: var(--sg-switch-label-disabled); }
  .switch input:disabled ~ .switch-text .switch-supporting { color: inherit; }
  /* Backgrounds are dropped in forced colours, so on and off would look identical. */
  @media (forced-colors: active) {
    .switch-track { border: 1px solid ButtonBorder; }
    .switch input:checked + .switch-track { background: Highlight; }
  }

  /* Built on <dialog>, so the top layer, the focus trap, Escape and the backdrop all
     come from the element. */
  .dialog {
    display: flex;
    flex-direction: column;
    padding: 0;
    border: none;
    border-radius: var(--sg-dialog-radius);
    background: var(--sg-dialog-background);
    color: var(--sg-dialog-text);
    box-shadow: var(--sg-elevation-dialog);
    /* A width, not just a cap. <dialog> is fit-content by default, so a cap alone lets
       the box collapse around whatever is in it — a list, whose items have no width of
       their own, ends up a column of a few hundred pixels. The min() is the cap.
       Not tokens: the size scale is control heights, and these are layout widths. */
    inline-size: min(32rem, calc(100vw - 2rem));
    max-block-size: min(40rem, calc(100dvh - 4rem));
    /* The body carries its own surface, so the corners have to be clipped or it squares
       off the bottom of a dialog with no footer. */
    overflow: hidden;
  }
  /* The form sits between the dialog and its three parts, so the column has to run
     through it for the middle to be the only thing that scrolls. */
  .dialog > form {
    display: flex;
    flex-direction: column;
    min-block-size: 0;
    flex: 1;
  }
  .dialog::backdrop { background: var(--sg-dialog-scrim); }
  /* For a dialog holding a list, a table or a form rather than a question. Wide enough
     that rows do not wrap, narrow enough that the eye still finds the next line. */
  .dialog[data-size='wide'] { inline-size: min(40rem, calc(100vw - 2rem)); }
  .dialog-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sg-dialog-gap);
    flex: 0 0 auto;
    padding: var(--sg-dialog-padding-block) var(--sg-dialog-padding-inline);
    border-block-end: 1px solid var(--sg-divider-color);
  }
  .dialog-title { color: var(--sg-dialog-title); }
  .dialog-body {
    flex: 1;
    min-block-size: 0;
    overflow-y: auto;
    padding: var(--sg-dialog-padding-block) var(--sg-dialog-padding-inline);
    background: var(--sg-dialog-body-background);
    color: var(--sg-dialog-text);
  }
  .dialog-body:focus-visible { outline: 2px solid var(--sg-action-focus-ring); outline-offset: -2px; }
  /* Secondary before primary, and pushed to the end: the last thing on the row is the
     one being confirmed. */
  .dialog-footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--sg-dialog-gap);
    flex: 0 0 auto;
    padding: var(--sg-dialog-padding-block) var(--sg-dialog-padding-inline);
    border-block-start: 1px solid var(--sg-divider-color);
  }

  /* A row is a label around a control or a link, so the whole row is the target either
     way. Nothing here assumes which. */
  /* No width here on purpose. How wide a list should be depends on what is in it — a
     settings list wants a readable measure, a list of orders with actions on the right
     wants the column it is given — and that is the page's decision, not the component's. */
  .list {
    list-style: none;
    margin: 0;
    padding: 0;
    background: var(--sg-list-background);
    border: 1px solid var(--sg-list-border);
    border-radius: var(--sg-list-radius);
    overflow: hidden;
  }
  /* Rows that can be pressed or ticked make the list a control, and a control has to read
     as one against the cards around it. The row element is what says so: a div row is
     content and keeps the quieter edge. Only the outline goes dark — carrying it into the
     rules between rows as well turns three choices into a table. */
  .list:has(:is(a, button, label).list-row) { border-color: var(--sg-list-border-interactive); }
  .list li + li { border-block-start: 1px solid var(--sg-list-border); }
  /* Separated rows, for a list long enough that the run of them stops being scannable and
     starts being a wall. Each row gets its own edge; the group loses the single outline
     that said the rows belong together, which is the price and the reason this is not the
     default. The gap replaces the rule between rows — a boundary drawn twice reads as
     neither. */
  .list[data-separated] {
    display: flex;
    flex-direction: column;
    gap: var(--sg-list-row-gap);
    background: none;
    border: none;
    border-radius: 0;
    overflow: visible;
  }
  .list[data-separated] li {
    background: var(--sg-list-background);
    border: 1px solid var(--sg-list-border);
    border-radius: var(--sg-list-radius);
    overflow: hidden;
  }
  .list[data-separated]:has(:is(a, button, label).list-row) li {
    border-color: var(--sg-list-border-interactive);
  }
  .list-row {
    display: flex;
    align-items: center;
    gap: var(--sg-list-gap);
    min-height: var(--sg-list-row-min-height);
    padding: var(--sg-list-padding-block) var(--sg-list-padding-inline);
    color: var(--sg-list-text);
    text-decoration: none;
  }
  /* The pointer and the hover belong to the element that actually does something. A row
     that is a plain div holds content and is not a target, and lighting it up under the
     cursor promises a click that never arrives. */
  :is(a, button, label).list-row { cursor: pointer; }
  :is(a, button, label).list-row:hover { background: var(--sg-list-background-hover); }
  /* After the hover, so a chosen row keeps its tint under the cursor rather than flickering
     back to the hover colour. A switch is left out: it is a setting rather than one of a
     set, its track already carries the state, and a list of settings would end up mostly
     tinted, which says nothing. */
  .list-row:has(input:checked:not([role='switch'])) { background: var(--sg-list-background-selected); }
  .list-row:focus-visible { outline: 2px solid var(--sg-action-focus-ring); outline-offset: -2px; }
  .list-text { display: flex; flex-direction: column; gap: 0.125rem; flex: 1; min-inline-size: 0; }
  .list-title {
    font-size: var(--sg-list-title-font-size);
    line-height: var(--sg-list-title-line-height);
    font-weight: var(--sg-font-weight-600);
  }
  .list-supporting {
    color: var(--sg-list-supporting-text);
    font-size: var(--sg-list-supporting-font-size);
    line-height: var(--sg-list-supporting-line-height);
    font-weight: var(--sg-font-weight-400);
  }
  .list-row > svg {
    flex: 0 0 auto;
    width: var(--sg-list-icon-size);
    height: var(--sg-list-icon-size);
    color: var(--sg-list-icon);
  }
  .list-legend {
    padding: 0 0 0.5rem;
    color: var(--sg-text-secondary);
    font-size: var(--sg-body-small-font-size);
    line-height: var(--sg-body-small-line-height);
    font-weight: var(--sg-font-weight-600);
  }
  .list-fieldset { margin: 0; padding: 0; border: none; }

  /* The one place two targets share a row. The disclosure opens the branch, the label
     ticks the box, and each has its own accessible name — which is why the row cannot
     be a single label the way a list row is. */
  .tree {
    list-style: none;
    margin: 0;
    padding: 0;
    background: var(--sg-tree-background);
    border: 1px solid var(--sg-divider-color);
    border-radius: var(--sg-tree-radius);
    overflow: hidden;
  }
  .tree ul { list-style: none; margin: 0; padding: 0; }
  .tree-row {
    display: flex;
    align-items: center;
    gap: var(--sg-tree-gap);
    min-height: var(--sg-tree-row-min-height);
    padding: var(--sg-tree-padding-block) var(--sg-tree-padding-inline);
    border-block-start: 1px solid var(--sg-divider-color);
    color: var(--sg-tree-text);
  }
  .tree > li:first-child > .tree-row { border-block-start: none; }
  .tree-row:hover { background: var(--sg-tree-background-hover); }
  /* Four levels written out rather than counted, because four is the depth the structure
     has. A fifth simply stops indenting, which shows as two rows at the same depth — a
     visible wrong answer rather than a layout that silently drifts. */
  .tree-group > li > .tree-row { padding-inline-start: calc(var(--sg-tree-padding-inline) + var(--sg-tree-indent)); }
  .tree-group .tree-group > li > .tree-row { padding-inline-start: calc(var(--sg-tree-padding-inline) + var(--sg-tree-indent) * 2); }
  .tree-group .tree-group .tree-group > li > .tree-row { padding-inline-start: calc(var(--sg-tree-padding-inline) + var(--sg-tree-indent) * 3); }
  .tree-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    inline-size: var(--sg-tree-icon-size);
    block-size: var(--sg-tree-icon-size);
    padding: 0;
    border: none;
    background: none;
    color: var(--sg-tree-icon);
    cursor: pointer;
  }
  .tree-toggle svg {
    inline-size: var(--sg-tree-icon-size);
    block-size: var(--sg-tree-icon-size);
    rotate: -90deg;
    transition: rotate var(--sg-motion-state-duration) var(--sg-motion-state-easing);
  }
  .tree-toggle[aria-expanded='true'] svg { rotate: 0deg; }
  .tree-toggle:focus-visible { outline: 2px solid var(--sg-action-focus-ring); outline-offset: 2px; }
  /* A leaf keeps the chevron's space so every checkbox in a branch lines up. Without it
     the ticks stagger by one icon width and the depth stops being readable. */
  .tree-leaf { flex: 0 0 auto; inline-size: var(--sg-tree-icon-size); }
  .tree-label {
    display: inline-flex;
    align-items: center;
    gap: var(--sg-control-gap);
    flex: 1;
    min-inline-size: 0;
    font-size: var(--sg-tree-title-font-size);
    line-height: var(--sg-tree-title-line-height);
    font-weight: var(--sg-font-weight-400);
    cursor: pointer;
  }

  /* Both kinds hang off a positioned host, so nothing has to measure anything. The host
     shrinks to its trigger, or centring would resolve against the whole row. */
  .tooltip-host { position: relative; display: inline-flex; align-self: start; }
  .tooltip {
    position: absolute;
    z-index: 4;
    inset-block-end: calc(100% + var(--sg-tooltip-offset));
    inset-inline-start: 50%;
    translate: -50% 0;
    inline-size: max-content;
    max-inline-size: 16rem;
    padding: var(--sg-tooltip-plain-padding-block) var(--sg-tooltip-plain-padding-inline);
    border-radius: var(--sg-tooltip-plain-radius);
    background: var(--sg-tooltip-plain-background);
    color: var(--sg-tooltip-plain-text);
    font-size: var(--sg-tooltip-plain-font-size);
    line-height: var(--sg-tooltip-plain-line-height);
    font-weight: var(--sg-font-weight-400);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--sg-motion-state-duration) var(--sg-motion-state-easing);
  }
  /* Shown on focus as well as hover, and the tooltip itself stays hoverable so the
     pointer can travel into it. */
  .tooltip-host:hover .tooltip,
  .tooltip-host:focus-within .tooltip,
  .tooltip:hover { opacity: 1; visibility: visible; }
  .tooltip-host[data-dismissed='true'] .tooltip { opacity: 0; visibility: hidden; }

  .tooltip-rich {
    inline-size: 18rem;
    max-inline-size: none;
    /* Below the trigger: it is persistent, so it should not cover what was just read. */
    inset-block-end: auto;
    inset-block-start: calc(100% + var(--sg-tooltip-offset));
    display: flex;
    flex-direction: column;
    gap: var(--sg-tooltip-rich-gap);
    padding: var(--sg-tooltip-rich-padding-block) var(--sg-tooltip-rich-padding-inline);
    border-radius: var(--sg-tooltip-rich-radius);
    background: var(--sg-tooltip-rich-background);
    color: var(--sg-tooltip-rich-text);
    font-size: var(--sg-tooltip-rich-font-size);
    line-height: var(--sg-tooltip-rich-line-height);
    font-weight: var(--sg-font-weight-400);
    box-shadow: var(--sg-elevation-overlay);
    text-align: start;
  }
  /* A rich tooltip is persistent, so it is opened rather than hovered into view. */
  .tooltip-host:hover .tooltip-rich,
  .tooltip-host:focus-within .tooltip-rich { opacity: 0; visibility: hidden; }
  .tooltip-host[data-open='true'] .tooltip-rich { opacity: 1; visibility: visible; }
  .tooltip-rich-title { color: var(--sg-tooltip-rich-title); font-weight: var(--sg-font-weight-600); }
  .tooltip-rich a { color: var(--sg-link-default); }

  /* One connected pill: a light border around the group, no rules between segments. The
     selected segment is a tinted fill with accent text. Segments size to their own label,
     so a short and a long option sit side by side without padding the short one out. */
  .segmented {
    display: inline-flex;
    align-self: start;
    border: 1px solid var(--sg-segmented-border);
    border-radius: var(--sg-segmented-radius);
    overflow: hidden;
  }
  .segmented-item {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sg-segmented-gap);
    min-height: var(--sg-segmented-min-height);
    padding-inline: var(--sg-segmented-padding-inline);
    background: var(--sg-segmented-background);
    color: var(--sg-segmented-text);
    font-size: var(--sg-segmented-font-size);
    line-height: var(--sg-segmented-line-height);
    /* Constant across states: a weight that changes on selection makes the row jump. */
    font-weight: var(--sg-font-weight-600);
    white-space: nowrap;
    cursor: pointer;
  }
  .segmented-item:hover { background: var(--sg-segmented-background-hover); }
  /* Selection is a tinted fill plus accent text, so it is not hue alone: the fill also
     changes lightness against the white segments. */
  .segmented-item:has(input:checked) {
    background: var(--sg-segmented-background-selected);
    color: var(--sg-segmented-text-selected);
  }
  .segmented-item:has(input:focus-visible) { outline: 2px solid var(--sg-action-focus-ring); outline-offset: -2px; }
  /* No tick: the fill carries the selection. */
  .segmented-item svg { display: none; }

  /* A large button that goes and fetches a choice rather than being one. Columns are set
     by how much room a button needs, not by a number, so the same markup gives two across
     on a desk and one on a phone without a breakpoint.
     No align-items: the default stretch is what keeps two buttons in a row the same height
     when one carries an icon and a supporting line and the other carries neither. */
  .picker-buttons {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: var(--sg-picker-button-group-gap);
  }
  .picker-button {
    display: flex;
    align-items: center;
    gap: var(--sg-picker-button-gap);
    min-height: var(--sg-picker-button-min-height);
    padding: var(--sg-picker-button-padding-block) var(--sg-picker-button-padding-inline);
    background: var(--sg-picker-button-background);
    border: 1px solid var(--sg-picker-button-border);
    border-radius: var(--sg-picker-button-radius);
    font-family: inherit;
    text-align: start;
    cursor: pointer;
  }
  .picker-button:hover {
    background: var(--sg-picker-button-background-hover);
    border-color: var(--sg-picker-button-border-hover);
  }
  .picker-button:focus-visible { outline: 2px solid var(--sg-action-focus-ring); outline-offset: 2px; }
  /* Disabled takes the whole button, chevron included, or it says it is unavailable while
     the arrow still says it opens. */
  .picker-button:disabled {
    background: var(--sg-picker-button-background-disabled);
    border-color: transparent;
    cursor: default;
  }
  .picker-button:disabled :is(.picker-button-title, .picker-button-supporting, .picker-button-icon, .picker-button-chevron) {
    color: var(--sg-picker-button-text-disabled);
  }
  .picker-button:disabled:hover { border-color: transparent; }
  .picker-button-icon {
    flex: 0 0 auto;
    inline-size: var(--sg-picker-button-icon-size);
    block-size: var(--sg-picker-button-icon-size);
    color: var(--sg-picker-button-icon);
  }
  .picker-button-text { display: flex; flex-direction: column; gap: var(--sg-picker-button-text-gap); flex: 1; min-inline-size: 0; }
  .picker-button-title {
    color: var(--sg-picker-button-title);
    font-size: var(--sg-picker-button-title-font-size);
    line-height: var(--sg-picker-button-title-line-height);
    font-weight: var(--sg-font-weight-600);
  }
  .picker-button-supporting {
    color: var(--sg-picker-button-supporting-text);
    font-size: var(--sg-picker-button-supporting-font-size);
    line-height: var(--sg-picker-button-supporting-line-height);
    font-weight: var(--sg-font-weight-400);
  }
  /* The chevron is the only thing separating this from a card that has been selected.
     Without it the press is a guess about whether something is about to open. */
  .picker-button-chevron {
    flex: 0 0 auto;
    inline-size: var(--sg-picker-button-chevron-size);
    block-size: var(--sg-picker-button-chevron-size);
    color: var(--sg-picker-button-chevron);
  }

  /* Cards in a row, each one a label around a radio or a checkbox. Equal width, so the
     group reads as one set of choices rather than a row of different things.
     No align-items here on purpose: the default stretch is what gives every card in a row
     the same height even when one has an icon and its neighbour does not. Setting it to
     start or center reads as tidier and breaks that. */
  .options { display: flex; flex-wrap: wrap; gap: var(--sg-option-group-gap); }
  .option {
    position: relative;
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--sg-option-gap);
    min-inline-size: 9rem;
    min-height: var(--sg-option-min-height);
    padding: var(--sg-option-padding-block) var(--sg-option-padding-inline);
    background: var(--sg-option-background);
    border: 1px solid var(--sg-option-border);
    border-radius: var(--sg-option-radius);
    text-align: center;
    cursor: pointer;
  }
  .option:hover { background: var(--sg-option-background-hover); }
  .option:has(input:checked) {
    background: var(--sg-option-background-selected);
    border-color: var(--sg-option-border-selected);
  }
  .option:has(input:focus-visible) { outline: 2px solid var(--sg-action-focus-ring); outline-offset: 2px; }
  .option-title {
    color: var(--sg-option-title);
    font-size: var(--sg-option-title-font-size);
    line-height: var(--sg-option-title-line-height);
    font-weight: var(--sg-font-weight-600);
  }
  .option-supporting {
    color: var(--sg-option-supporting-text);
    font-size: var(--sg-option-supporting-font-size);
    line-height: var(--sg-option-supporting-line-height);
    font-weight: var(--sg-font-weight-400);
  }
  .option svg {
    flex: 0 0 auto;
    width: var(--sg-option-icon-size);
    height: var(--sg-option-icon-size);
    color: var(--sg-option-icon);
  }
  .option:has(input:checked) .option-title { color: var(--sg-option-title-selected); }
  .option:has(input:checked) .option-supporting { color: var(--sg-option-supporting-text-selected); }
  .option:has(input:checked) svg { color: var(--sg-option-icon-selected); }

  /* Four statuses, one text colour. The icon is what says which status it is. */
  /* A card is a surface, not a layout. It gives a group of content an edge and a
     consistent inset; what goes inside, and how wide it is, stays the page's decision. */
  .card {
    display: flex;
    flex-direction: column;
    gap: var(--sg-card-gap);
    padding: var(--sg-card-large-padding);
    background: var(--sg-card-background);
    border: 1px solid var(--sg-card-border);
    border-radius: var(--sg-card-radius);
    color: var(--sg-card-content-text);
  }
  .card[data-size='medium'] { padding: var(--sg-card-medium-padding); }
  .card-header { display: flex; align-items: flex-start; gap: var(--sg-card-gap); }
  .card-heading { display: flex; flex-direction: column; gap: 0.125rem; flex: 1; min-inline-size: 0; }
  /* Colour only. The size comes from a text-heading class on the element, so a card never
     ends up owning a second heading scale beside the one typography already sets. */
  .card-title { margin: 0; color: var(--sg-card-title); }
  .card-supporting {
    color: var(--sg-card-supporting-text);
    font-size: var(--sg-card-supporting-font-size);
    line-height: var(--sg-card-supporting-line-height);
    font-weight: var(--sg-font-weight-400);
  }
  .card-body { display: flex; flex-direction: column; gap: var(--sg-card-gap); }
  .card-footer { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sg-card-footer-gap); }
  /* A card that is one target has to be the element that already behaves like one. Nothing
     else in it can be interactive: two targets in the same box means neither is reachable
     by keyboard in the order the eye reads them. */
  :is(a, button).card {
    inline-size: 100%;
    font: inherit;
    text-align: start;
    text-decoration: none;
    cursor: pointer;
  }
  :is(a, button).card:hover { background: var(--sg-card-background-hover); }
  :is(a, button).card:focus-visible { outline: 2px solid var(--sg-action-focus-ring); outline-offset: 2px; }

  .alerts { display: flex; flex-direction: column; gap: 0.75rem; max-inline-size: 40rem; }
  .alert {
    display: flex;
    align-items: center;
    gap: var(--sg-alert-gap);
    min-height: var(--sg-alert-min-height);
    padding: var(--sg-alert-padding-block) var(--sg-alert-padding-inline);
    border-radius: var(--sg-alert-radius);
    color: var(--sg-alert-text);
    font-size: var(--sg-alert-font-size);
    line-height: var(--sg-alert-line-height);
    font-weight: var(--sg-font-weight-400);
  }
  .alert-text { flex: 1; min-inline-size: 0; }
  .alert-title { display: block; font-weight: var(--sg-font-weight-600); }
  .alert > svg {
    flex: 0 0 auto;
    width: var(--sg-alert-icon-size);
    height: var(--sg-alert-icon-size);
  }
  .alert[data-status='error'] { background: var(--sg-alert-error-background); }
  .alert[data-status='error'] > svg { color: var(--sg-alert-error-icon); }
  .alert[data-status='warning'] { background: var(--sg-alert-warning-background); }
  .alert[data-status='warning'] > svg { color: var(--sg-alert-warning-icon); }
  .alert[data-status='success'] { background: var(--sg-alert-success-background); }
  .alert[data-status='success'] > svg { color: var(--sg-alert-success-icon); }
  .alert[data-status='info'] { background: var(--sg-alert-info-background); }
  .alert[data-status='info'] > svg { color: var(--sg-alert-info-icon); }
  /* An icon inside a component takes that component's text colour, so the close control
     agrees with the message rather than with the button roles. */
  .alert .btn { color: var(--sg-alert-text); }
  .alert .btn:hover { background: rgb(0 0 0 / 0.06); }

  /* min-inline-size so the scroller survives being a flex or grid item: without it the
     automatic minimum is the table's width, the parent grows to match, and the page
     scrolls sideways instead of the table. */
  .table-scroll { overflow-x: auto; min-inline-size: 0; }  .table {
    width: 100%;
    /* Sticky cells need separate borders: collapsed ones do not travel with the cell. */
    border-collapse: separate;
    border-spacing: 0;
    background: var(--sg-table-background);
    color: var(--sg-table-text);
    border: 1px solid var(--sg-table-border);
    border-radius: var(--sg-table-radius);
    font-size: var(--sg-table-large-font-size);
    line-height: var(--sg-table-large-line-height);
  }
  .table th,
  .table td {
    position: relative;
    padding: var(--sg-table-large-padding-block) var(--sg-table-large-padding-inline);
    text-align: left;
    white-space: nowrap;
    background: var(--sg-table-background);
    border-block-end: 1px solid var(--sg-table-border);
  }
  .table[data-size='medium'] {
    font-size: var(--sg-table-medium-font-size);
    line-height: var(--sg-table-medium-line-height);
  }
  .table[data-size='medium'] th,
  .table[data-size='medium'] td {
    padding: var(--sg-table-medium-padding-block) var(--sg-table-medium-padding-inline);
  }
  /* Cells are their own containing block. A visually hidden label in a header — the usual
     way to name a column of buttons — is absolutely positioned, and without this it is
     laid out against the page instead of the cell, escapes the horizontal scroller and
     drags the whole document wider. */
  .table thead th {
    position: relative;
    background: var(--sg-table-header-background);
    color: var(--sg-table-header-text);
    font-weight: var(--sg-font-weight-600);
  }
  .table tbody tr:last-child td { border-block-end: none; }
  .table tbody tr:hover td { background: var(--sg-table-row-hover); }
  .table .numeric { text-align: right; font-variant-numeric: tabular-nums; }
  .table .muted { color: var(--sg-table-muted-text); }

  /* A pinned column keeps its own background, or the rest would scroll under it. */
  .table[data-sticky~='first'] :is(th, td):first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    border-inline-end: 1px solid var(--sg-table-sticky-border);
  }
  .table[data-sticky~='last'] :is(th, td):last-child {
    position: sticky;
    right: 0;
    z-index: 1;
    border-inline-start: 1px solid var(--sg-table-sticky-border);
  }
  .table[data-sticky] thead :is(th):first-child,
  .table[data-sticky] thead :is(th):last-child { z-index: 2; }
  /* A pinned column is only lifted while it is actually stuck: sticky is a position the
     column falls into, not a state it is always in. The wrapper reports which edge is
     stuck, and each edge takes the shadow that falls towards the content. */
  .table-scroll[data-stuck~='first'] .table[data-sticky~='first'] :is(th, td):first-child {
    box-shadow: var(--sg-elevation-sticky-start);
  }
  .table-scroll[data-stuck~='last'] .table[data-sticky~='last'] :is(th, td):last-child {
    box-shadow: var(--sg-elevation-sticky-end);
  }
  :is(.check, .list-row, .tree-label) input:disabled + .check-box { background: var(--sg-control-background-disabled); }
  .check input:disabled ~ span { color: var(--sg-text-disabled); }

  /* The page's own copy confirmation is a snackbar, so it runs on the snackbar roles
     rather than a second set of values that would drift from them. */
  .snackbar {
    display: inline-flex;
    align-items: center;
    align-self: start;
    gap: var(--sg-snackbar-gap);
    padding: var(--sg-snackbar-padding-block) var(--sg-snackbar-padding-inline);
    border-radius: var(--sg-snackbar-radius);
    background: var(--sg-snackbar-background);
    color: var(--sg-snackbar-text);
    font-size: var(--sg-snackbar-font-size);
    line-height: var(--sg-snackbar-line-height);
    font-weight: var(--sg-font-weight-400);
    box-shadow: var(--sg-elevation-overlay);
  }
  .snackbar svg {
    flex: 0 0 auto;
    width: var(--sg-snackbar-icon-size);
    height: var(--sg-snackbar-icon-size);
    color: var(--sg-snackbar-icon);
  }
  .snackbar-action {
    padding: 0;
    background: none;
    border: none;
    color: var(--sg-snackbar-action-text);
    font: inherit;
    font-weight: var(--sg-font-weight-500);
    text-decoration: underline;
    cursor: pointer;
  }
  .snackbar-action:focus-visible { outline: 2px solid var(--sg-snackbar-action-text); outline-offset: 2px; }
  /* The live region is fixed and always in the DOM, since one inserted along with the
     message is not announced. */
  .snackbar-live {
    position: fixed;
    inset-block-end: 1.5rem;
    inset-inline-start: 50%;
    translate: -50% 0;
    opacity: 0;
    transition: opacity var(--sg-motion-enter-duration) var(--sg-motion-enter-easing);
    pointer-events: none;
  }
  .snackbar-live[data-visible='true'] { opacity: 1; }
