/*
 * The stylesheet for every page the Worker renders. It uses only the tokens in tokens.css, which
 * each page links first. See "Design" in plans/haystack-v1-implementation-plan.md.
 */

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* The ground is the root's background, which always fills the whole canvas. The message bar's
   height, which message-bar.js keeps up to date, is the scroll padding, so a control that Tab
   moves to is scrolled into view below the bar, never under it (WCAG 2.4.11). */
html {
  background-color: var(--color-ground);
  scroll-padding-block-start: var(--message-bar-height, 0);
}

body {
  --gutter: clamp(var(--space-m), 5vi, var(--space-l));
  --page-width: var(--width-narrow);

  color: var(--color-ink);
  font-family: var(--font-sans);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  margin: 0;
  overflow-wrap: break-word;
}

/* The saved links page and /held are wider, so their grids have room for several columns. */
.layout-wide {
  --page-width: var(--width-wide);
}

h1,
h2,
h3,
p,
ul,
ol {
  margin: 0;
}

h1 {
  font-size: var(--text-h1);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: var(--leading-h1);
}

h2,
h3 {
  line-height: var(--leading-heading);
}

a {
  color: var(--color-accent);
  text-underline-offset: 0.15em;
}

a:hover {
  color: var(--color-accent-hover);
}

:focus-visible {
  outline: var(--focus-width) solid var(--color-focus);
  outline-offset: var(--focus-offset);
}

/* Layout. The header and the main content share one width, so they line up. */

.site-header-inner,
main {
  inline-size: min(100% - 2 * var(--gutter), var(--page-width));
  margin-inline: auto;
}

.site-header-inner {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-s);
  justify-content: space-between;
  padding-block: 1.25rem;
}

main {
  padding-block: var(--space-2xl) var(--space-3xl);
}

/* Block margins, not a flex gap, so an empty element such as the list's status region takes no
   space: its margins collapse with the next element's. */
main > * + * {
  margin-block-start: var(--space-l);
}

/* Text directly in the page keeps a readable line length on the wide page too. */
main > :where(p, ul, div) {
  max-inline-size: var(--width-narrow);
}

/* The header. */

.wordmark {
  align-items: center;
  color: var(--color-ink);
  display: inline-flex;
  font-size: var(--text-wordmark);
  font-weight: 700;
  gap: 0.625rem;
  letter-spacing: -0.02em;
  min-block-size: var(--target-small);
  text-decoration: none;
}

.wordmark:hover {
  color: var(--color-ink);
}

/* Forced colors drop the dot's background color, so it disappears there. It is decorative, so the
   wordmark loses nothing a reader needs. */
.wordmark-dot {
  background-color: var(--color-primary);
  block-size: 0.75rem;
  border-radius: 50%;
  inline-size: 0.75rem;
}

.site-actions {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}

/* The navigation links and Sign out are plain underlined text, so the three weigh the same next
   to the wordmark. Sign out is a button, so the browser's own button fill and border are reset,
   and it takes the links' underline offset and color transition, which are set for `a`. */
.nav-link {
  align-items: center;
  background-color: transparent;
  border: 0;
  color: var(--color-ink);
  cursor: pointer;
  display: inline-flex;
  font: inherit;
  font-size: 1rem;
  min-block-size: var(--target-small);
  padding-inline: var(--space-xs);
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

.nav-link:hover {
  color: var(--color-accent);
}

/* The current page is told apart by more than color: it is bold, has no underline, and has a
   straw bar along its bottom edge, the primary button's edge, which is ochre in the light scheme.
   The bar is a border, which forced colors, such as Windows' contrast themes, keep in a system
   color. The padding at the top matches it, so the text stays in line with the other items. */
.nav-link[aria-current="page"] {
  border-block-end: 3px solid var(--color-primary-border);
  font-weight: 700;
  padding-block-start: 3px;
  text-decoration: none;
}

/* Buttons. Every `.button` is a pill. The plain one is secondary. */

.button {
  align-items: center;
  background-color: var(--color-raised);
  border: 1px solid var(--color-control-border);
  border-radius: var(--radius-pill);
  color: var(--color-ink);
  cursor: pointer;
  display: inline-flex;
  font: inherit;
  justify-content: center;
  min-block-size: var(--target-control);
  padding-block: var(--space-xs);
  padding-inline: var(--space-l);
}

.button:hover {
  background-color: var(--color-border);
}

.button-primary {
  background-color: var(--color-primary);
  border-color: var(--color-primary-border);
  color: var(--color-on-primary);
  font-weight: 700;
  min-block-size: var(--target-primary);
  padding-inline: var(--space-xl);
}

.button-primary:hover {
  background-color: var(--color-primary-hover);
}

.button-danger,
.button-danger:hover {
  background-color: var(--color-danger);
  border-color: var(--color-danger);
  color: var(--color-on-danger);
  font-weight: 700;
}

.button-danger-outline {
  background-color: transparent;
  border-color: var(--color-danger-border);
  color: var(--color-danger);
}

.button-danger-outline:hover {
  background-color: var(--color-danger);
  border-color: var(--color-danger);
  color: var(--color-on-danger);
}

.button-small {
  font-size: var(--text-small);
  min-block-size: var(--target-small);
  padding-inline: var(--space-m);
}

/* The dialog's buttons while a delete runs (delete-dialog.js). They stay focusable. The fill
   and the border go quiet, and the text stays at 6:1 on the raised fill in both schemes. */
.button[aria-disabled="true"],
.button[aria-disabled="true"]:hover {
  background-color: var(--color-raised);
  border-color: var(--color-border);
  border-style: dashed;
  color: var(--color-ink-muted);
  cursor: progress;
}

@media (prefers-reduced-motion: no-preference) {
  a,
  .button {
    transition:
      background-color 120ms ease,
      color 120ms ease;
  }

  /* The header's items change only their color. Sign out is a button, which the browser first
     draws with its own fill, so a transition of its background would fade that fill out over
     each page load, with the text on it below 4.5:1 until it ends. */
  .nav-link {
    transition: color 120ms ease;
  }
}

/* Forms. */

.panel {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-panel);
  display: flex;
  flex-direction: column;
  gap: var(--space-l);
  padding: clamp(var(--space-m), 5vi, var(--space-xl));
}

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.field label {
  font-weight: 600;
}

.field input,
.field textarea {
  background-color: var(--color-field);
  border: 1px solid var(--color-control-border);
  border-radius: var(--radius-field);
  color: var(--color-ink);
  font: inherit;
  inline-size: 100%;
  min-block-size: var(--target-primary);
  padding-block: var(--space-s);
  padding-inline: 0.875rem;
}

.field textarea {
  /* A field the reader resizes still fits the form. */
  max-inline-size: 100%;
}

/* An inset shadow doubles the border without moving the text. */
.field [aria-invalid="true"],
.address-input[aria-invalid="true"] {
  border-color: var(--color-danger);
  box-shadow: inset 0 0 0 1px var(--color-danger);
}

/* "Address:" above the address, which the form shows as read-only text. */
.address-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.address-field strong {
  color: var(--color-ink-muted);
  font-size: var(--text-xsmall);
  font-weight: 500;
}

/* A saved address can be one long word, so it breaks anywhere rather than scroll (#33). */
.address {
  color: var(--color-accent);
  font-family: var(--font-mono);
  font-size: var(--text-small);
  overflow-wrap: anywhere;
}

/* The address form (#97) and the search form (#206). The field and the button share a row that
   fills the panel, and the button moves under the field when the row has no room for both. On
   the search form, the voice button (#216) can sit between them (`.voice-button` below). */
.address-form,
.search-form {
  gap: var(--space-s);
}

/* The saved links' and the search results' list headings (#245) look like the address form's
   heading, the other h2 on the saved links page, so the page's h2s match. */
.address-form-title,
.cards-heading {
  font-size: var(--text-form-title);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: var(--leading-heading);
}

.hint {
  color: var(--color-ink-muted);
  font-size: var(--text-small);
}

/* The gap under the field, when the button wraps, is twice the gap beside it (design review).
   A focused control's ring reaches 6 px out, its 3 px offset and 3 px width, so in a 12 px gap it
   filled half the space between the two on a phone. */
.address-row,
.search-row {
  display: flex;
  flex-wrap: wrap;
  gap: calc(2 * var(--space-s)) var(--space-s);
}

/* The field and the button both grow, so the row is always full. On one row, the field's far
   larger share of the growth gives it nearly all the room the button doesn't need. When the button
   wraps, it is alone on its line, so it grows to the line's width, which is the field's. The
   button doesn't shrink below its label, so when its label becomes "Processing…", the field gives
   it the room. */
.address-row > .button,
.search-row > .button {
  flex: 1 0 auto;
}

/* A field's automatic minimum width grows with the text size, so `min-inline-size: 0` lets it
   shrink to the row at any text size instead of overflowing. */
.address-input,
.search-input {
  background-color: var(--color-field);
  border: 1px solid var(--color-control-border);
  border-radius: var(--radius-pill);
  color: var(--color-ink);
  flex: 1000 1 18rem;
  font: inherit;
  min-block-size: var(--target-primary);
  min-inline-size: 0;
  padding-block: var(--space-s);
  padding-inline: 1.125rem;
}

/* An address is set in the monospace font, as everywhere else. A query is words, so it keeps the
   body's font and size. */
.address-input {
  font-family: var(--font-mono);
  font-size: var(--text-small);
}

/* The search page (#206). Browsers that predate the element would draw it inline. */
search {
  display: block;
}

/* The voice button (#216), which the page renders after the search field, hidden, and which
   voice-input.js shows only when the browser has speech recognition. It is a secondary button,
   round and as tall as the field and Search, 48 px, so it never shrinks or grows. The row wraps by width, so it has three layouts, as
   measured in Chromium: from about 600 px wide, one line of the field, the button and Search;
   at about 480 to 540 px, the field and the button on the first line, and Search alone, full
   width, under them; and at about 320 to 430 px, the field alone, then the button and Search,
   which takes the rest of that line. The row's own rule makes its buttons grow, so `flex` is
   set at the row's specificity. */
.voice-button {
  block-size: var(--target-primary);
  inline-size: var(--target-primary);
  padding: 0;
}

.search-row > .voice-button {
  flex: none;
}

/* The button's `display` would win over the `hidden` attribute, which the browser's own
   stylesheet draws as `display: none`, so a browser without speech recognition would show it. */
.voice-button[hidden] {
  display: none;
}

.voice-icon {
  block-size: 1.5rem;
  inline-size: 1.5rem;
}

/* The icon is a microphone, and a stop square while the browser listens, so the state is a
   change of shape as well as of color. */
.voice-icon-stop,
.voice-button[aria-pressed="true"] .voice-icon-microphone {
  display: none;
}

.voice-button[aria-pressed="true"] .voice-icon-stop {
  display: inline;
}

/* While it listens, the button has the primary button's straw fill and edge, which is ochre in
   the light scheme, because straw alone is under 3:1 on white. */
.voice-button[aria-pressed="true"],
.voice-button[aria-pressed="true"]:hover {
  background-color: var(--color-primary);
  border-color: var(--color-primary-border);
  color: var(--color-on-primary);
}

/* Forced colors drop the straw fill, so there the listening button's edge is 3 px, three times
   its usual width, as well as holding the stop square. Both are shapes, which forced colors
   keep. `forced-color-adjust`, which could keep a fill, isn't newly available Baseline, which
   the style linter flags. */
@media (forced-colors: active) {
  .voice-button[aria-pressed="true"] {
    border-width: 3px;
  }
}

/* The voice input's live region, under the field's row, which the button's first press shows. Its
   first message comes after that, and while it is empty it is taken out of the panel's flow, so
   the panel's gap doesn't leave a space for it. It is still drawn, which keeps it a live region that a screen reader follows. Its messages
   are the page's: the raised status box (`.status > p`), and the alert's box for an error. */
.voice-status:empty {
  position: absolute;
}

/* Notices and messages. */

/* The message bar (design review): every message on the page, in one region after the page's
   heading (`messageBar` in notices.ts). It spans the viewport, and its messages line up with the
   page's content and keep a readable line length. Only a bar with something to show is drawn:
   a status region is empty until a message arrives, and an empty one takes no space. While the
   address form looks a page up (#105, address-form.js), and when a lookup fails, its status is
   here too. Continue keeps its usual style: only its label changes, because it is never
   disabled. */
.message-bar {
  max-inline-size: none;
}

/* The box stays as wide as the content, and its fill and borders are drawn out to the viewport's
   edges: the fill as a shadow, and the borders as a border image set out past the box. Neither
   counts as overflow, so the bar never makes the page scroll sideways, as `vw` would with a
   classic scrollbar, and the clip keeps the shadow off the content above and below the bar. A
   size container on the body would give the viewport's width as `cqi` instead, but Chromium then
   sometimes runs every button's and link's transition from the browser's own style on load. */
.message-bar:has(> :not(:empty, [hidden])) {
  background-color: var(--color-surface);
  border-block: 1px solid var(--color-border);
  border-image: linear-gradient(var(--color-border) 0 0) 1 / 1px 0 / 0 100vmax;
  box-shadow: 0 0 0 100vmax var(--color-surface);
  clip-path: inset(0 -100vmax);
  padding-block: var(--space-m);
}

/* Forced colors keep the gradient's own color, which would draw the borders in the palette's
   faint border color, so the box's own borders, which they replace with a system color, draw
   them instead. The shadow is dropped there too, and the canvas is one color, so nothing is
   lost by the bar no longer reaching the viewport's edges. */
@media (forced-colors: active) {
  .message-bar:has(> :not(:empty, [hidden])) {
    border-image: none;
  }
}

.message-bar > * {
  max-inline-size: var(--width-narrow);
}

/* Only between messages that show something, so an empty status region adds no gap. */
.message-bar > :not(:empty, [hidden]) ~ :not(:empty, [hidden]) {
  margin-block-start: var(--space-s);
}

/* A message's own `display`, such as the alert's flex or the button's inline-flex, would win over
   the `hidden` attribute, which the browser's own stylesheet draws as `display: none`. Close
   hides messages, and itself when there is nothing to close. */
.message-bar > [hidden] {
  display: none;
}

/* With message-bar.js, which can close it, the bar sticks to the top of the viewport, above the
   content it scrolls over, while it is at most a third of the viewport's height. */
.message-bar[data-stuck] {
  inset-block-start: 0;
  position: sticky;
  z-index: 1;
}

.notice {
  color: var(--color-ink-muted);
  font-size: var(--text-small);
}

/* The alert's icon is drawn here, not in the markup. */
.alert {
  align-items: flex-start;
  background-color: var(--color-alert);
  border: 1px solid var(--color-alert-border);
  border-radius: var(--radius-card);
  color: var(--color-alert-ink);
  display: flex;
  font-weight: 600;
  gap: var(--space-s);
  padding-block: var(--space-m);
  padding-inline: 1.25rem;
}

/* The "!" is text with an empty alternative, so a screen reader skips it, and forced colors keep
   it and the circle, which they would not do for a drawn background. */
.alert::before {
  block-size: 1.375rem;
  border: 2px solid var(--color-danger);
  border-radius: 50%;
  color: var(--color-danger);
  content: "!" / "";
  display: grid;
  flex: none;
  font-size: var(--text-xsmall);
  font-weight: 700;
  inline-size: 1.375rem;
  line-height: 1;
  place-items: center;
}

/* The live region stays in the page when it is empty, so only its message is drawn. */
.status > p {
  background-color: var(--color-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-field);
  padding-block: var(--space-s);
  padding-inline: var(--space-m);
}

/* Search results that may be incomplete, because some links could not be searched (#207). The
   count and the notice share the status box, with the straw edge of the save form's warning, so
   it reads as something to note, and its words say what. The edge is the primary button's, which
   is ochre in the light scheme, because straw on the light raised box barely shows. */
.status > .search-incomplete {
  border-inline-start: 4px solid var(--color-primary-border);
}

/* A search that failed (#207): the alert's box in the status region, in place of the results,
   with Try again under the message. Try again has the danger style, the error's own theme
   (design review): its fill is 6.36:1 on the dark alert and 5.91:1 on the light one, over the 3:1
   a control's edge needs, and its text 8.06:1 and 6.57:1 on the fill. */
.search-failure-body {
  align-items: flex-start;
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
}

/* address-form.js moves focus to its message, so a screen reader reads it (#105). The ring is the
   site's focus ring, drawn whenever the message has focus, also after a click, because the page,
   not the user, put focus there. An outline survives forced colors, which give it a system color. */
.status > p:focus {
  outline: var(--focus-width) solid var(--color-focus);
  outline-offset: var(--focus-offset);
}

.empty-state {
  background-color: var(--color-surface);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-card);
  color: var(--color-ink-secondary);
  padding: var(--space-l);
}

/* /held's empty state has a second paragraph, the way back to the saved links. */
.empty-state > * + * {
  margin-block-start: var(--space-xs);
}

.empty-state strong {
  color: var(--color-ink);
}

/* The link to /held on the saved links page, shown only when something waits there. The straw
   edge marks it as something to act on, and the link's words say what. */
.callout {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-inline-start: 4px solid var(--color-primary);
  border-radius: var(--radius-field);
  padding-block: var(--space-s);
  padding-inline: var(--space-m);
}

.callout a {
  font-weight: 600;
}

/* The saved links grid. */

.cards {
  display: grid;
  gap: var(--space-m);
  grid-template-columns: repeat(auto-fill, minmax(min(18rem, 100%), 1fr));
  padding: 0;
}

/* The grid's `display` would win over the `hidden` attribute, which the browser's own stylesheet
   draws as `display: none`. The search page's results list is hidden until a search finds
   something. */
.cards[hidden] {
  display: none;
}

/* Each item's own `display: flex` replaces `list-item`, so it draws no marker, and the list
   needs no `list-style: none`. */
.cards > li {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  min-inline-size: 0;
  padding: 1.25rem;
}

.cards h3 {
  font-size: var(--text-card-title);
  font-weight: 600;
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
}

.cards h3 a {
  color: var(--color-ink);
}

.cards h3 a:hover {
  color: var(--color-accent);
}

.card-date {
  color: var(--color-ink-muted);
  font-size: var(--text-xsmall);
}

.cards .address {
  font-size: var(--text-address-small);
}

.card-description {
  color: var(--color-ink-secondary);
  font-size: var(--text-small);
  margin-block-start: var(--space-3xs);
}

/* Pinned to the bottom, so the buttons of a row line up. A card on the saved links page and a
   search result have one form, and a card on /held has a row of them. */
.cards > li > form,
.card-actions {
  margin-block-start: auto;
  padding-block-start: var(--space-s);
}

.card-actions {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}

/* On a Held card, the release form's checkbox takes a row of its own, and its Release button
   shares the row below with Delete. The form's own box is left out of the layout, which changes
   nothing about how it is sent, and a form without a name has no role to lose. */
.release-form {
  display: contents;
}

/* The review page at /held (#129). Each kind of item has a section, with a heading and a short
   explanation, and its cards are the saved links' cards. */
.review-section > * + * {
  margin-block-start: var(--space-xs);
}

.review-section h2 {
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.review-intro {
  color: var(--color-ink-secondary);
  max-inline-size: var(--width-narrow);
}

.review-section > .cards {
  margin-block-start: var(--space-m);
}

/* The card's top edge repeats what its section's heading says in words: straw for a link held
   back, the danger color for one that wasn't described. */
.review-cards-held > li {
  border-block-start: 3px solid var(--color-primary);
}

.review-cards-failed > li {
  border-block-start: 3px solid var(--color-danger-border);
}

/* Release's checkbox, above the card's buttons (.release-form), and the save form's (#132,
   .sensitivity-check). The box is 24 px, WCAG 2.5.8's minimum target,
   and the label can be pressed too. It is drawn here, because the browser's own box takes the
   system's accent color. Its edge is a field's, at 3:1 or more, and a ticked box is the primary
   button's straw with its edge, so it keeps 3:1 on white too. The tick is a border, which forced
   colors keep. */
.checkbox {
  align-items: flex-start;
  color: var(--color-ink-secondary);
  display: flex;
  flex-basis: 100%;
  font-size: var(--text-small);
  gap: var(--space-xs);
  margin-block-end: var(--space-3xs);
}

.checkbox input {
  appearance: none;
  background-color: var(--color-field);
  block-size: 1.5rem;
  border: 1px solid var(--color-control-border);
  border-radius: 0.375rem;
  cursor: pointer;
  display: grid;
  flex: none;
  inline-size: 1.5rem;
  margin: 0;
  place-content: center;
}

.checkbox input::before {
  block-size: 0.75rem;
  border-color: var(--color-on-primary);
  border-style: solid;
  border-width: 0 3px 3px 0;
  content: "";
  inline-size: 0.4375rem;
  transform: translateY(-0.0625rem) rotate(45deg);
  visibility: hidden;
}

.checkbox input:checked {
  background-color: var(--color-primary);
  border-color: var(--color-primary-border);
}

.checkbox input:checked::before {
  visibility: visible;
}

.checkbox label {
  cursor: pointer;
  padding-block-start: 0.125rem;
}

/* A box the server rejected gets the danger edge of a rejected field (#132). */
.checkbox input[aria-invalid="true"] {
  border-color: var(--color-danger);
  box-shadow: inset 0 0 0 1px var(--color-danger);
}

/* The save form's warning that the link might be private, and its checkbox (#132). The warning
   is the notice's raised box with the straw edge that marks a link held back on /held and the
   link to /held, so it reads as something to act on, and its words say what. The edge is the
   primary button's, which is ochre in the light scheme, because straw on the light raised box
   barely shows, and the edge is what tells the warning from the notice above it. Its first
   sentence is in ink. In the form, the checkbox's label is a field's label, so it has a field
   label's size, weight and ink. */
.sensitivity-check {
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
}

.warning {
  background-color: var(--color-raised);
  border-inline-start: 4px solid var(--color-primary-border);
  border-radius: var(--radius-field);
  color: var(--color-ink-secondary);
  font-size: var(--text-small);
  padding-block: 0.875rem;
  padding-inline: var(--space-m);
}

.warning strong {
  color: var(--color-ink);
  font-weight: 600;
}

.sensitivity-check .checkbox {
  color: var(--color-ink);
  font-size: inherit;
  font-weight: 600;
  margin-block-end: 0;
}

/* A Failed card's last error, in plain words, in the raised box of the site's messages. */
.card-error {
  background-color: var(--color-raised);
  border-radius: var(--radius-field);
  color: var(--color-ink-secondary);
  font-size: var(--text-small);
  margin-block-start: var(--space-xs);
  padding-block: var(--space-xs);
  padding-inline: var(--space-s);
}

.card-error strong {
  color: var(--color-ink);
  font-weight: 600;
}

/* The delete dialog, which delete-dialog.js builds. */

/* The dialog is inside <main>, so `margin: auto` restores the centering that the margins between
   main's children would otherwise replace. */
.delete-dialog {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-panel);
  color: var(--color-ink);
  margin: auto;
  max-inline-size: min(30rem, 100% - 2 * var(--gutter));
  padding: var(--space-l);
}

.delete-dialog[open] {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-s);
}

.delete-dialog > :not(button) {
  flex-basis: 100%;
}

.delete-dialog h2 {
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.delete-dialog-name {
  font-weight: 600;
  overflow-wrap: anywhere;
}

.delete-dialog-notice {
  color: var(--color-ink-secondary);
  margin-block-end: var(--space-xs);
}

.delete-dialog::backdrop {
  background-color: var(--color-backdrop);
}
