/* =============================================================================================
   Vanilla Sky components.

   Every rule here comes from section 4-7 of the Foundation sheet. Where the design expressed a
   value inline on a prototype element, it appears here once as a class, so a button's hover state
   is defined in one place rather than on each of the forty buttons in the product.

   Ordering: layout, buttons, forms, badges, cards, feedback, dialog, tables.
   ============================================================================================= */

/* ---------------------------------------------------------------------------------------------
   Layout
   --------------------------------------------------------------------------------------------- */

.vs-page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.vs-main {
  flex: 1;
}

.vs-container {
  width: 100%;
  max-width: var(--content-wide);
  margin: 0 auto;
  padding-inline: var(--space-6);
}

.vs-container--narrow {
  max-width: var(--content-narrow);
}

.vs-stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.vs-stack--tight { gap: var(--space-2); }
.vs-stack--loose { gap: var(--space-6); }
.vs-stack--section { gap: var(--space-8); }

.vs-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.vs-row--between {
  justify-content: space-between;
}

.vs-section {
  padding-block: var(--space-12);
}

/* ---------------------------------------------------------------------------------------------
   Site header and footer
   --------------------------------------------------------------------------------------------- */

.vs-header {
  background: var(--color-bg-surface);
  border-bottom: 1px solid var(--color-border);
}

.vs-header__inner {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  min-height: 72px;
}

.vs-header__logo img {
  display: block;
  height: 44px;
  width: auto;
}

/* The brief is explicit that the main menu has exactly four entries and that language, account and
   accessibility controls are utility navigation. Two separate <nav> elements keep that structural
   rather than a matter of styling discipline. */
.vs-nav {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-inline-start: auto;
}

.vs-nav__link {
  display: inline-flex;
  align-items: center;
  min-height: var(--touch-target);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-button);
  font-size: var(--text-ui-14);
  font-weight: 500;
  color: var(--color-text-primary);
  text-decoration: none;
}

.vs-nav__link:hover {
  background: var(--color-bg-sand-deep);
  color: var(--color-action-primary);
}

.vs-nav__link[aria-current='page'] {
  color: var(--color-action-primary);
  font-weight: 600;
  box-shadow: inset 0 -2px 0 var(--color-action-primary);
}

.vs-utility {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

/* A link group, not flags: a flag is a country, not a language, and Georgian, English and Russian
   are not selected by nationality. */
.vs-lang {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-button);
  overflow: hidden;
}

.vs-lang__option {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--touch-target);
  min-height: var(--touch-target);
  padding-inline: var(--space-2);
  font-size: var(--text-caption-12);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-secondary);
  text-decoration: none;
  background: var(--color-bg-surface);
}

.vs-lang__option + .vs-lang__option {
  border-inline-start: 1px solid var(--color-border);
}

.vs-lang__option[aria-current='true'] {
  background: var(--color-action-primary);
  color: #FFF;
}

.vs-footer {
  background: var(--color-bg-sand);
  border-top: 1px solid var(--color-border);
  padding-block: var(--space-8);
  font-size: var(--text-ui-14);
  color: var(--color-text-secondary);
}

/* ---------------------------------------------------------------------------------------------
   Buttons

   Sizing is shared; only colour and border differ per variant. Every variant clears 44px.
   --------------------------------------------------------------------------------------------- */

.vs-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-family: inherit;
  font-size: var(--text-body-15);
  font-weight: 600;
  line-height: 1.2;
  padding: var(--space-3) var(--space-6);
  min-height: var(--touch-target);
  border: none;
  border-radius: var(--radius-button);
  cursor: pointer;
  text-decoration: none;
}

.vs-btn--primary {
  background: var(--color-action-primary);
  color: #FFF;
}

.vs-btn--primary:hover:not(:disabled) {
  background: var(--color-action-primary-hover);
  color: #FFF;
}

.vs-btn--secondary {
  background: var(--color-bg-surface);
  color: var(--color-action-primary);
  border: 1.5px solid var(--color-action-primary);
}

.vs-btn--secondary:hover:not(:disabled) {
  background: var(--color-action-primary-wash);
}

.vs-btn--tertiary {
  background: transparent;
  color: var(--color-action-primary);
  padding-inline: var(--space-4);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.vs-btn--tertiary:hover:not(:disabled) {
  background: var(--color-bg-sand-deep);
}

/* Outlined at rest. The solid fill below is reserved for the final confirm button inside a
   dialog -- so a destructive action can never be triggered by one stray click on a page. */
.vs-btn--destructive {
  background: var(--color-bg-surface);
  color: var(--color-status-error);
  border: 1.5px solid var(--color-status-error);
}

.vs-btn--destructive:hover:not(:disabled) {
  background: var(--color-status-error-bg);
}

.vs-btn--destructive-confirm {
  background: var(--color-status-error);
  color: #FFF;
  border: 1.5px solid var(--color-status-error);
}

.vs-btn--destructive-confirm:hover:not(:disabled) {
  background: #8E1D17;
  color: #FFF;
}

.vs-btn:disabled {
  cursor: not-allowed;
  background: var(--color-border-disabled);
  color: var(--color-text-disabled);
  border-color: var(--color-border-disabled);
}

.vs-btn--secondary:disabled,
.vs-btn--destructive:disabled {
  background: var(--color-bg-surface);
  color: var(--color-text-faint);
}

.vs-btn--tertiary:disabled {
  background: transparent;
  color: var(--color-text-faint);
}

.vs-btn--block {
  width: 100%;
}

.vs-btn--compact {
  font-size: var(--text-ui-14);
  padding: var(--space-2) var(--space-4);
}

/* ---------------------------------------------------------------------------------------------
   Forms

   Labels are always present and always above the field. A placeholder is an example, never a
   label: it disappears exactly when the user needs it.
   --------------------------------------------------------------------------------------------- */

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

.vs-field__label {
  font-size: 13px;
  font-weight: 600;
  color: var(--color-text-primary);
}

.vs-field--invalid .vs-field__label {
  color: var(--color-status-error);
}

.vs-field__label--disabled {
  color: var(--color-text-disabled);
}

.vs-field__hint {
  font-size: var(--text-caption-12);
  color: var(--color-text-secondary);
}

.vs-field__required {
  color: var(--color-status-error);
  margin-inline-start: 2px;
}

.vs-input,
.vs-select,
.vs-textarea {
  font-family: inherit;
  font-size: var(--text-body-15);
  color: var(--color-text-primary);
  padding: 11px var(--space-4);
  min-height: var(--touch-target);
  border: 1.5px solid var(--color-border-input);
  border-radius: var(--radius-input);
  background: var(--color-bg-surface);
  width: 100%;
}

.vs-textarea {
  min-height: 120px;
  line-height: var(--leading-body);
  resize: vertical;
}

.vs-input:focus,
.vs-select:focus,
.vs-textarea:focus {
  border-color: var(--color-action-primary);
  border-width: 2px;
  padding: 10px 15px;   /* keeps the text from shifting when the border thickens */
}

.vs-input:disabled,
.vs-select:disabled,
.vs-textarea:disabled {
  background: var(--color-bg-sand-deep);
  border-color: var(--color-border-disabled);
  color: var(--color-text-disabled);
  cursor: not-allowed;
}

.vs-field--invalid .vs-input,
.vs-field--invalid .vs-select,
.vs-field--invalid .vs-textarea {
  border: 2px solid var(--color-status-error);
  padding: 10px 15px;
}

/* Error text carries an icon as well as colour, and is referenced by aria-describedby so a screen
   reader hears it as part of the field rather than as loose text after it. */
.vs-field__error {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  font-size: 13px;
  font-weight: 600;
  color: var(--color-status-error);
}

.vs-check {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  font-size: var(--text-ui-14);
  line-height: 1.5;
  cursor: pointer;
  min-height: var(--touch-target);
  padding-block: var(--space-2);
}

.vs-check input {
  width: 20px;
  height: 20px;
  margin: 2px 0 0;
  accent-color: var(--color-action-primary);
  flex-shrink: 0;
}

/* Two columns where there is room, one where there is not. Fields keep their own width rather
   than stretching to fill a row, so a two-letter country code is not rendered as a 600px box. */
.vs-field-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--space-4);
}

.vs-counter {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.vs-counter__button {
  width: var(--touch-target);
  height: var(--touch-target);
  border-radius: var(--radius-button);
  border: 1.5px solid var(--color-action-primary);
  background: var(--color-bg-surface);
  color: var(--color-action-primary);
  font-size: 20px;
  font-family: inherit;
  cursor: pointer;
}

.vs-counter__button:disabled {
  border-color: var(--color-border-disabled);
  color: var(--color-text-faint);
  cursor: not-allowed;
}

.vs-counter__value {
  min-width: 36px;
  text-align: center;
  font-size: 16px;
  font-weight: 700;
}

/* The password input and its reveal toggle share one border, so they read as one control rather
   than as a field with a button parked next to it. */
.vs-password {
  display: flex;
  align-items: center;
  border: 1.5px solid var(--color-border-input);
  border-radius: var(--radius-input);
  background: var(--color-bg-surface);
}

.vs-password:focus-within {
  border-color: var(--color-action-primary);
  border-width: 2px;
}

.vs-password__input {
  border: none;
  flex: 1;
  min-width: 0;
  background: transparent;
}

.vs-password__input:focus {
  border: none;
  padding: 11px var(--space-4);
  outline: none;   /* The ring is on the wrapper, which is what the eye reads as the field. */
}

.vs-password__toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: var(--touch-target);
  min-height: var(--touch-target);
  padding: 0 var(--space-3);
  background: none;
  border: none;
  color: var(--color-text-secondary);
  cursor: pointer;
}

.vs-password__toggle:hover {
  color: var(--color-action-primary);
}

/* A one-time code is read back digit by digit, so it gets the monospace face and enough letter
   spacing to be checked against an email at a glance. */
.vs-code-input {
  font-family: var(--font-mono);
  font-size: 22px;
  font-weight: 600;
  letter-spacing: 0.35em;
  max-width: 260px;
}

/* The validation summary at the top of a form. role="alert" on the element itself, links straight
   to each offending field, and focus moves here on a failed submit. */
.vs-error-summary {
  background: var(--color-status-error-bg);
  border: 1.5px solid var(--color-status-error);
  border-radius: var(--radius-card);
  padding: var(--space-4) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.vs-error-summary__title {
  font-size: var(--text-title-17);
  font-weight: 700;
  color: var(--color-status-error);
}

.vs-error-summary ul {
  margin: 0;
  padding-inline-start: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: var(--text-ui-14);
}

.vs-error-summary a {
  color: var(--color-status-error);
}

/* ---------------------------------------------------------------------------------------------
   The error panel: a sentence, a reference, and a collapsed technical block.

   The details region carries no `display: none` of its own. It is hidden by the `hidden`
   attribute, which /js/disclosure.js sets once it runs -- so with no script the block renders open
   rather than becoming unreachable. That is why nothing behind the toggle may be sensitive.
   --------------------------------------------------------------------------------------------- */

.vs-error-notice__body {
  min-width: 0;
}

.vs-error-notice__list {
  margin: 0;
  padding-inline-start: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: var(--text-ui-14);
}

.vs-error-notice__reference code {
  font-weight: 600;
  letter-spacing: 0.04em;
}

.vs-error-notice__disclosure {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
}

.vs-error-notice__details {
  margin: 0;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-1) var(--space-3);
  font-size: var(--text-ui-14);
  width: 100%;
}

/* Any `display` in an author sheet beats the user agent's `[hidden] { display: none }`, so the rule
   above would leave the block on screen with the attribute set and the button claiming it is
   collapsed. Restated here rather than by switching the toggle to a class, because `hidden` is what
   assistive technology reads. */
.vs-error-notice__details[hidden] {
  display: none;
}

.vs-error-notice__details dt {
  font-weight: 600;
}

.vs-error-notice__details dd {
  margin: 0;
  min-width: 0;
}

/* Wraps rather than scrolls sideways: an exception message on a phone must not push the page. */
.vs-error-notice__raw {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-size: 13px;
}

@media (max-width: 400px) {
  .vs-error-notice__details {
    grid-template-columns: 1fr;
  }
}

/* ---------------------------------------------------------------------------------------------
   Badges. Colour is never the only carrier: each badge has an icon or shape and a text label.
   --------------------------------------------------------------------------------------------- */

.vs-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: 13px;
  font-weight: 600;
  padding: 6px var(--space-3);
  border-radius: var(--radius-pill);
  white-space: nowrap;
}

.vs-badge--success {
  background: var(--color-status-success-bg);
  color: var(--color-status-success);
}

.vs-badge--warning {
  background: var(--color-status-warning-bg);
  color: var(--color-status-warning-text);
}

.vs-badge--error {
  background: var(--color-status-error-bg);
  color: var(--color-status-error);
}

.vs-badge--info {
  background: var(--color-status-info-bg);
  color: var(--color-status-info);
}

.vs-badge--neutral {
  background: var(--color-neutral-chip-bg);
  color: var(--color-neutral-chip-text);
}

/* A cancelled ticket is struck through as well as greyed, so the state survives greyscale. */
.vs-badge--cancelled {
  background: var(--color-neutral-chip-bg);
  color: var(--color-neutral-chip-text);
  border-radius: var(--radius-input);
  text-decoration: line-through;
}

.vs-badge__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

.vs-badge__dot--held {
  border-radius: 0;
  transform: rotate(45deg);
}

.vs-badge--visible {
  border-radius: var(--radius-input);
  border: 1.5px solid var(--color-status-info);
  color: var(--color-status-info);
  background: var(--color-bg-surface);
}

/* Dashed, not merely a different colour: hidden inventory reads as hidden even in monochrome. */
.vs-badge--hidden {
  border-radius: var(--radius-input);
  border: 1.5px dashed var(--color-text-secondary);
  color: var(--color-neutral-chip-text);
  background: var(--color-bg-surface);
}

/* ---------------------------------------------------------------------------------------------
   Cards and surfaces
   --------------------------------------------------------------------------------------------- */

.vs-card {
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  padding: var(--space-5) var(--space-6);
}

.vs-card--flush {
  padding: 0;
  overflow: hidden;
}

.vs-card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-6);
  border-bottom: 1px solid var(--color-border-hairline);
}

.vs-card__title {
  font-size: var(--text-title-17);
  font-weight: 600;
}

.vs-eyebrow {
  font-size: var(--text-caption-12);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-accent-gold-text);
}

.vs-display {
  font-family: var(--font-display);
  font-size: var(--text-display-40);
  font-weight: 600;
  line-height: var(--leading-display);
}

.vs-heading-28 { font-size: var(--text-heading-28); font-weight: 700; }
.vs-heading-22 { font-size: var(--text-heading-22); font-weight: 700; }
.vs-title-17 { font-size: var(--text-title-17); font-weight: 600; }
.vs-body { font-size: var(--text-body-15); }
.vs-ui-14 { font-size: var(--text-ui-14); font-weight: 500; }
.vs-caption { font-size: var(--text-caption-12); color: var(--color-text-secondary); }
.vs-muted { color: var(--color-text-secondary); }
.vs-mono { font-family: var(--font-mono); }

/* ---------------------------------------------------------------------------------------------
   Feedback: inline alerts, toasts, skeletons, empty states
   --------------------------------------------------------------------------------------------- */

.vs-alert {
  display: flex;
  gap: var(--space-2);
  border-radius: var(--radius-button);
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-ui-14);
  line-height: 1.5;
}

.vs-alert__icon,
.vs-alternatives__icon,
.vs-hold__icon {
  flex-shrink: 0;
  margin-top: 2px;
  display: inline-flex;
  align-items: center;
}

/* Icons take their colour from the text beside them, which is what keeps a status icon and its
   label from ever disagreeing about which state they are showing. */
.vs-status-icon {
  flex-shrink: 0;
  color: currentColor;
}

/* The sign-out control is a POST, because signing somebody out on a GET means any page that can
   embed an image can sign them out. It still has to look like the link next to it. */
.vs-utility__form {
  display: inline;
  margin: 0;
}

.vs-alert--success {
  background: var(--color-status-success-bg);
  border: 1px solid #9DC3AD;
  color: var(--color-status-success-text);
}

.vs-alert--warning {
  background: var(--color-status-warning-bg);
  border: 1px solid var(--color-status-warning-border);
  color: var(--color-status-warning-text);
}

.vs-alert--error {
  background: var(--color-status-error-bg);
  border: 1px solid var(--color-status-error-border);
  color: var(--color-status-error);
}

.vs-alert--info {
  background: var(--color-status-info-bg);
  border: 1px solid var(--color-status-info-border);
  color: var(--color-status-info);
}

/* ---------------------------------------------------------------------------------------------
   The staff simulation banner

   Solid rather than tinted like .vs-alert--warning, and that is the point of it existing as its
   own class instead of reusing one. This is not a message about the page; it is a statement about
   the account, and it has to survive being seen for the twentieth time that afternoon. Sticky, so
   scrolling cannot leave it behind, and there is no dismiss control to style because there is no
   dismiss control.

   White on --color-status-warning rather than the softer --color-status-warning-text, for contrast
   against a filled bar.
   --------------------------------------------------------------------------------------------- */

.vs-simulation-banner {
  align-items: center;
  background: var(--color-status-warning);
  color: #FFFFFF;
  display: flex;
  font-size: var(--text-ui-14);
  font-weight: 600;
  gap: var(--space-2);
  justify-content: center;
  line-height: 1.4;
  margin-bottom: var(--space-4);
  padding: var(--space-3) var(--space-4);
  position: sticky;
  text-align: center;
  top: 0;
  width: 100%;

  /* Below the mobile tab bar (40) and the skip link (100), above ordinary page furniture. It
     announces a state rather than blocking one, so it must never cover a control.

     30 is enough against every sticky element that actually renders. The two this bar shares a
     page with -- `.vs-admin__side` and `.vs-checkout__aside` -- are both `position: sticky` with
     no z-index of their own, so they sit in the auto tier and this paints above them without a
     tie to break. Nothing live occupies 30 alongside it. */
  z-index: 30;
}

.vs-empty {
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  padding: var(--space-8) var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  align-items: center;
  text-align: center;
}

.vs-skeleton {
  height: 14px;
  border-radius: var(--radius-input);
  background: linear-gradient(90deg, #EFE8DC, #F7F2E9, #EFE8DC);
}

/* ---------------------------------------------------------------------------------------------
   Dialog

   The <dialog> element gives focus trapping, Escape-to-close and inertness of the page behind it
   from the platform. Reimplementing those in script is how they end up half-working.
   --------------------------------------------------------------------------------------------- */

.vs-dialog {
  border: none;
  border-radius: var(--radius-card);
  padding: 0;
  max-width: 560px;
  width: calc(100vw - var(--space-8));
  box-shadow: var(--shadow-2);
  background: var(--color-bg-surface);
  color: var(--color-text-primary);
}

.vs-dialog::backdrop {
  background: rgba(43, 39, 36, 0.55);
}

.vs-dialog__body {
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.vs-dialog__title {
  font-size: var(--text-heading-22);
  font-weight: 700;
}

/* The dialog is rendered conditionally rather than shown with the <dialog> element's own API,
   because opening a native dialog needs a JS interop call and this flow has to work on a server
   render. The host below reproduces what <dialog> gives for free: a scrim, centring, and the page
   behind held still. Focus is moved to the title on open and Escape is handled by the page. */
.vs-dialog-host {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  background: rgba(43, 39, 36, 0.55);
  overflow-y: auto;
}

.vs-dialog__points {
  margin: 0;
  padding-inline-start: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  font-size: var(--text-ui-14);
  line-height: 1.5;
}

.vs-dialog__actions {
  display: flex;
  gap: var(--space-3);
  justify-content: flex-end;
  flex-wrap: wrap;
  padding: var(--space-4) var(--space-6);
  border-top: 1px solid var(--color-border-hairline);
  background: var(--color-bg-page);
}

/* ---------------------------------------------------------------------------------------------
   Tables

   Admin tables scroll inside their own container. A page that scrolls horizontally loses its
   header and its navigation; a table that scrolls keeps them.
   --------------------------------------------------------------------------------------------- */

.vs-table-scroll {
  overflow-x: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  background: var(--color-bg-surface);
}

.vs-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-ui-14);
}

.vs-table th {
  text-align: start;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-secondary);
  background: var(--color-bg-page);
  padding: var(--space-3) var(--space-4);
  white-space: nowrap;
}

.vs-table td {
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--color-border-hairline);
  vertical-align: middle;
}

.vs-table tbody tr:hover {
  background: var(--color-bg-page);
}

.vs-table__numeric {
  text-align: end;
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------------------------
   Portal: status timeline and detail lists
   --------------------------------------------------------------------------------------------- */

.vs-timeline {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.vs-timeline__step {
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: var(--space-3);
  align-items: start;
  position: relative;
}

/* The connecting line is drawn from each step except the last, so the sequence reads as one
   thread rather than three unrelated rows. */
.vs-timeline__step:not(:last-child)::after {
  content: '';
  position: absolute;
  left: 13px;
  top: 26px;
  bottom: calc(var(--space-4) * -1);
  width: 2px;
  background: var(--color-border);
}

.vs-timeline__mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid var(--color-border);
  background: var(--color-bg-surface);
  z-index: 1;
}

.vs-timeline__step--done .vs-timeline__mark {
  border-color: var(--color-status-success);
  color: var(--color-status-success);
  background: var(--color-status-success-bg);
}

.vs-timeline__step--current .vs-timeline__mark {
  border-color: var(--color-status-warning);
  color: var(--color-status-warning);
  background: var(--color-status-warning-bg);
}

.vs-timeline__step--todo {
  color: var(--color-text-secondary);
}

.vs-detail-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-4);
  margin: 0;
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  padding: var(--space-5) var(--space-6);
}

.vs-detail-list dt {
  font-size: var(--text-caption-12);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-secondary);
  margin-bottom: var(--space-1);
}

.vs-detail-list dd {
  margin: 0;
  font-size: var(--text-body-15);
  font-weight: 600;
}

/* One entry in a repeated history — a cancellation attempt, and there can be several. Separated by
   a rule rather than by a card, so a list of three does not read as three unrelated things. */
.vs-detail-block + .vs-detail-block {
  border-top: 1px solid var(--color-border-hairline);
  padding-top: var(--space-5);
}

/* ---------------------------------------------------------------------------------------------
   Responsive
   --------------------------------------------------------------------------------------------- */

@media (max-width: 768px) {
  .vs-container {
    padding-inline: var(--space-4);
  }

  .vs-header__inner {
    flex-wrap: wrap;
    padding-block: var(--space-3);
  }

  .vs-nav {
    order: 3;
    width: 100%;
    margin-inline-start: 0;
    overflow-x: auto;
  }

  /* The utility group is a language chooser plus three links, and in Georgian those words are
     long enough to total well over a phone's width. Without this it cannot wrap and pushes the
     whole document sideways, which costs the header and the main menu off the right edge. */
  .vs-utility {
    flex-wrap: wrap;
    justify-content: flex-end;
    row-gap: var(--space-2);
  }

  .vs-display {
    font-size: 30px;
  }

  .vs-heading-28 {
    font-size: 24px;
  }

  .vs-section {
    padding-block: var(--space-8);
  }
}

/* =================================================================================================
   Circuit status
   -------------------------------------------------------------------------------------------------
   Styling for the two elements blazor.web.js drives by id. The framework owns when they appear and
   which state class is on them; this sheet owns only what they look like.

   Both are hidden by default. The modal is revealed by the framework adding one of its state
   classes; blazor-error-ui is revealed by the framework setting display:block inline, which beats
   the rule below on specificity, so it must not be given a display value in a class here.
   ================================================================================================= */

#components-reconnect-modal,
#blazor-error-ui {
  display: none;
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 1000;
  padding: var(--space-4);
}

#components-reconnect-modal.components-reconnect-show,
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-rejected {
  display: block;
}

.vs-circuit__panel {
  margin: 0 auto;
  max-width: 560px;
  padding: var(--space-4) var(--space-5);
  background: var(--color-status-error-bg);
  border: 1px solid var(--color-status-error-border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-2);
}

.vs-circuit__title {
  margin: 0;
  font-weight: 600;
  color: var(--color-status-error);
}

.vs-circuit__detail {
  margin: var(--space-1) 0 0;
  color: var(--color-text-secondary);
}

.vs-circuit__state .vs-btn {
  margin-top: var(--space-3);
}

/* Retrying is the resting state of the modal; the terminal message replaces it once the framework
   has given up, so the two are never on screen together. */
.vs-circuit__state--lost {
  display: none;
}

#components-reconnect-modal.components-reconnect-failed .vs-circuit__state--retrying,
#components-reconnect-modal.components-reconnect-rejected .vs-circuit__state--retrying {
  display: none;
}

#components-reconnect-modal.components-reconnect-failed .vs-circuit__state--lost,
#components-reconnect-modal.components-reconnect-rejected .vs-circuit__state--lost {
  display: block;
}
/* ================================================================================================
   Editor-managed prose, the news list, and the pager.

   These carry the four public content routes — About us, News, Contact us and Terms — which the
   main menu linked to before any of them had a page behind it.
   ================================================================================================ */

/* Rich text an editor wrote and HtmlSanitizer approved.

   Scoped to this one wrapper rather than applied to bare elements, because the sanitiser's allow
   list is wider than any single screen: styling `h2` globally to suit an article would restyle
   every heading in the back office too. Element selectors are safe *inside* here. */
.vs-prose {
  color: var(--color-text-primary);
  font-size: var(--text-body-15);
  line-height: var(--leading-body);
}

.vs-prose > * + * {
  margin-top: var(--space-4);
}

.vs-prose h2 {
  font-family: var(--font-display);
  font-size: var(--text-heading-22);
  line-height: var(--leading-heading);
  margin-top: var(--space-8);
}

.vs-prose h3 {
  font-size: var(--text-title-17);
  line-height: var(--leading-heading);
  margin-top: var(--space-6);
}

.vs-prose ul,
.vs-prose ol {
  padding-inline-start: var(--space-6);
}

.vs-prose li + li {
  margin-top: var(--space-2);
}

.vs-prose a {
  color: var(--color-action-primary);
  text-underline-offset: 2px;
}

.vs-prose blockquote {
  border-inline-start: 3px solid var(--color-accent-gold-deco);
  color: var(--color-text-secondary);
  padding-inline-start: var(--space-4);
}

/* An editor can paste a table or a wide image. Neither may push the page sideways at 360px, so the
   overflow is taken here rather than by the document. */
.vs-prose img {
  border-radius: var(--radius-card);
  height: auto;
  max-width: 100%;
}

.vs-prose table {
  border-collapse: collapse;
  display: block;
  overflow-x: auto;
  width: 100%;
}

.vs-prose th,
.vs-prose td {
  border: 1px solid var(--color-border);
  padding: var(--space-2) var(--space-3);
  text-align: start;
}

/* News list ------------------------------------------------------------------------------------ */

/* auto-fit rather than a media query: the grid becomes one column when one column is what fits,
   which is the rule the handoff states for every card surface. */
.vs-news-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  list-style: none;
  margin: 0;
  padding: 0;
}

.vs-news-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* The whole card is the target, not just the words in the heading — 48px of reachable area on a
   phone instead of a two-line link. The heading keeps the real anchor so the accessibility tree
   still reads a link with the article's name. */
.vs-news-card {
  position: relative;
}

.vs-news-card__link {
  color: inherit;
  text-decoration: none;
}

.vs-news-card__link::after {
  content: '';
  inset: 0;
  position: absolute;
}

.vs-news-card__link:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
}

.vs-news-card__link:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

.vs-badge--accent {
  background: var(--color-status-warning-bg);
  border: 1px solid var(--color-status-warning-border);
  color: var(--color-status-warning-text);
}

/* Pager ---------------------------------------------------------------------------------------- */

.vs-pager {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  justify-content: center;
}

/* Forms ---------------------------------------------------------------------------------------- */

/* "(optional)" beside a label. Quieter than the label and still announced with it, so a screen
   reader reaches the same conclusion a sighted reader does. */
.vs-field__optional {
  color: var(--color-text-secondary);
  font-size: var(--text-caption-12);
  font-weight: 400;
}

/* ================================================================================================
   The responsive layer.

   Breakpoints 360 / 768 / 1024 / 1440, per the handoff. Most of the reflow is not here: the grids
   above use `repeat(auto-fit, minmax(...))` and flex-wrap, so they become one column when one
   column is what fits, at whatever width that happens to be. Media queries appear only where the
   *pattern itself* changes -- the navigation swap, the sticky bars, the date strip's day count --
   which is what the handoff asks for and what keeps this section short enough to reason about.

   The rule everything below serves: no horizontal page scroll at 360px. Wide things (tables, the
   date strip, an editor's pasted table) scroll inside their own container, never the document.
   ================================================================================================ */

/* Deliberately NOT `html, body { overflow-x: hidden }`.

   That is the usual reflex and it is a lie: it stops the page scrolling sideways without stopping
   anything from being too wide, so the overflowing element is still there and now simply clipped —
   and, worse, the browser-suite assertion that no page overflows becomes vacuously true, because
   scrollWidth can no longer exceed clientWidth. The overflow is fixed where it happens instead:
   tables and the date strip scroll inside their own containers, and images and prose are bounded.
   MobileLayoutBrowserTests measures the document at 360px and would fail if any of that stopped
   being true. */

/* Fluid gutters rather than a fixed pair. min() keeps the 40px the design specifies on a wide
   screen and gives a phone its 5% back instead of eating a quarter of a 360px viewport. */
.vs-container {
  padding-inline: min(40px, 5vw);
}

/* ---- The mobile tab bar -------------------------------------------------------------------- */

/* Hidden by default and shown below the navigation breakpoint. The other way round would leave it
   visible for the moment before the media query applies on a slow first paint. */
.vs-tabbar {
  display: none;
}

.vs-tabbar__item {
  align-items: center;
  color: var(--color-text-secondary);
  display: flex;
  flex: 1;
  flex-direction: column;
  font-weight: 600;
  gap: 2px;
  justify-content: center;

  /* The handoff's 48px, before the safe-area padding below is added to the bar itself. */
  min-height: 48px;
  padding: var(--space-2) var(--space-1);
  text-decoration: none;
}

.vs-tabbar__icon {
  height: 20px;
  width: 20px;
}

.vs-tabbar__label {
  font-size: 10.5px;
  line-height: 1.2;
  text-align: center;
}

/* Weight as well as colour, so the active tab is distinguishable without relying on hue. */
.vs-tabbar__item--active {
  color: var(--color-action-primary);
  font-weight: 700;
}

.vs-tabbar__item:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: -2px;
}

/* ---- Sticky checkout bars ------------------------------------------------------------------ */

/* The running total and the primary action, pinned so the total never scrolls out of view. Shown
   only on small screens; the desktop journey keeps its fare-summary sidebar. */
.vs-action-bar {
  display: none;
}

.vs-action-bar__total {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}

.vs-action-bar__label {
  color: var(--color-text-secondary);
  font-size: 11.5px;
}

.vs-action-bar__value {
  font-size: 19px;
  font-weight: 700;
}

.vs-action-bar .vs-btn {
  flex: 1;
  min-height: 50px;
}

/* ---- The menu page ------------------------------------------------------------------------- */

.vs-menu-list {
  display: flex;
  flex-direction: column;
}

.vs-menu-list__item {
  border-bottom: 1px solid var(--color-border-hairline);
  color: var(--color-text-primary);
  display: block;
  font-size: var(--text-title-17);

  /* A whole-row target. On a phone this is the primary navigation and a text-height link is a
     miss waiting to happen. */
  min-height: 48px;
  padding: var(--space-4) 0;
  text-decoration: none;
}

.vs-menu-list__item:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: 2px;
}

.vs-menu-list__form {
  padding-top: var(--space-4);
}

/* ---- Bottom sheet -----------------------------------------------------------------------------

   Base state: not a sheet. The <dialog> contributes no box of its own, so its content sits in the
   page exactly where the markup puts it, and the trigger and the sheet's own chrome are absent.
   This is what a tablet, a desktop, and a phone whose circuit has not arrived all get.

   `display: contents` on the dialog is deliberate and is the reason the component sets role="none"
   while it is closed — a box-less element is still in the accessibility tree, and a dialog role
   around a set of ordinary form fields would be a lie.

   Author rules beat the user-agent sheet regardless of specificity, which is what lets a closed
   dialog be visible at all; `dialog:not([open]) { display: none }` is a UA rule.
   ----------------------------------------------------------------------------------------------- */

.vs-sheet {
  background: transparent;
  border: 0;
  color: inherit;
  display: contents;
  margin: 0;
  max-height: none;
  max-width: none;
  padding: 0;
}

.vs-sheet__panel {
  display: contents;
}

.vs-sheet__trigger,
.vs-sheet__chrome {
  display: none;
}

/* ================================================================================================
   1024px and below — the tablet step. Admin loses its sidebar; the public site keeps its header.
   ================================================================================================ */

@media (max-width: 1024px) {
  /* The back office sidebar becomes a full-width nav list above the content, per MOBILE.md. */
  .vs-admin {
    display: block;
  }

  .vs-admin__sidebar {
    border-inline-end: 0;
    border-block-end: 1px solid var(--color-border);
    height: auto;
    position: static;
    width: 100%;
  }

  .vs-admin__nav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
  }

  .vs-admin__link {
    min-height: 44px;
  }
}

/* ================================================================================================
   768px and below — the navigation swap. This is where the pattern genuinely changes.
   ================================================================================================ */

@media (max-width: 768px) {
  /* The header keeps the logo and the language chooser; everything else moves to the tab bar and
     the menu page. Hiding the links rather than wrapping them is deliberate: a wrapped six-link
     header costs three rows of a 720px-tall viewport before any content appears. */
  .vs-nav,
  .vs-utility .vs-nav__link,
  .vs-utility .vs-utility__form {
    display: none;
  }

  .vs-tabbar {
    background: var(--color-bg-surface);
    border-top: 1px solid var(--color-border);
    bottom: 0;
    display: flex;
    inset-inline: 0;
    position: fixed;

    /* Above the page, below a dialog. */
    z-index: 40;

    /* The home indicator on a modern phone sits inside the viewport; without this the labels are
       under it. */
    padding-bottom: env(safe-area-inset-bottom, 0);
  }

  /* Room for the bar, so the last element on every page is reachable rather than sitting behind
     it. Calculated from the bar's own height plus the inset. */
  .vs-page {
    padding-bottom: calc(64px + env(safe-area-inset-bottom, 0));
  }

  /* Checkout swaps the tab bar for the action bar. Both fixed to the same edge, so exactly one is
     present at a time -- two would stack and bury the content behind 120px of chrome. */
  .vs-checkout .vs-tabbar {
    display: none;
  }

  .vs-checkout .vs-action-bar {
    align-items: center;
    background: var(--color-bg-surface);
    border-top: 1px solid var(--color-border);
    bottom: 0;
    box-shadow: var(--shadow-1);
    display: flex;
    gap: var(--space-4);
    inset-inline: 0;
    padding: var(--space-3) min(40px, 5vw);
    padding-bottom: calc(var(--space-3) + env(safe-area-inset-bottom, 0));
    position: fixed;
    z-index: 40;
  }

  /* On failure and confirmation the bar carries two full-width actions instead of a total and a
     button (M8/M9). */
  .vs-action-bar--stacked {
    flex-direction: column;
  }

  .vs-action-bar--stacked .vs-btn {
    width: 100%;
  }

  /* Single column below ~760px, for every grid that has not already collapsed on its own. */
  .vs-field-grid,
  .vs-journey__layout,
  .vs-summary__layout {
    grid-template-columns: 1fr;
  }

  /* The fare summary stops being a sidebar and becomes a card above the form. */
  .vs-journey__aside {
    order: -1;
  }

  /* Touch targets grow. 48px is the handoff's mobile floor; 44px is the desktop one. */
  .vs-btn,
  .vs-nav__link,
  .vs-input,
  .vs-select {
    min-height: 48px;
  }

  /* Calendar cells and steppers have their own sizes in the handoff. */
  .vs-calendar__day {
    min-height: 46px;
    min-width: 46px;
  }

  .vs-stepper__button {
    min-height: 36px;
    min-width: 36px;
    padding-inline: var(--space-3);
  }

  /* Five days rather than seven, scrolling horizontally with the selected day centred. The strip
     scrolls, the page does not. */
  .vs-date-strip {
    -webkit-overflow-scrolling: touch;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
  }

  .vs-date-strip__day {
    flex: 0 0 calc(20% - var(--space-2));
    scroll-snap-align: center;
  }

  /* MOBILE.md rule 1 -- "the hold timer moves into the sticky header so it survives scrolling" --
     is NOT implemented, and the rule that used to sit here did not implement it either. It selected
     `.vs-hold-timer`, a class HoldTimer has never emitted: ContainerClass produces `vs-hold`,
     `vs-hold--expired` or `vs-hold--ending` and nothing else, verified back to the component's
     introduction. The sticky timer has therefore never worked on any build that shipped.

     The dead selector is removed rather than corrected, and the two are different acts. Pointing it
     at `.vs-hold` would switch on a position:sticky element, at the top of the checkout page, on
     phones, that no one has ever seen render -- a visual change arrived at by accident while
     tidying CSS. That is somebody's decision to take deliberately. Leaving the rule in place was
     not the alternative: it read as working code and would have gone on doing so.

     Whoever takes that decision: the target is `.vs-checkout .vs-hold`, and expiry is decided on
     the server either way -- this element has never been what enforces it. */

  /* An enlarged QR for scanning at the aerodrome, where the light is bad and the phone is at
     arm's length. */
  .vs-eticket__qr {
    height: 112px;
    width: 112px;
  }

  /* ---- The bottom sheet, which only exists here ----------------------------------------------

     Every rule below is scoped to `--live`, the class the component adds once the circuit is up.
     Without it the trigger is not rendered, and collapsing the content anyway would leave the
     picker unreachable on a phone with no script — the exact failure the inline fallback exists
     to prevent. */

  .vs-sheet-host--live .vs-sheet__trigger {
    align-items: center;
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-input);
    color: var(--color-text-primary);
    display: flex;
    gap: var(--space-3);
    justify-content: space-between;

    /* The handoff's mobile floor, and this is a control a thumb reaches for. */
    min-height: 48px;
    padding: var(--space-3) var(--space-4);
    text-align: start;
    width: 100%;
  }

  .vs-sheet-host--live .vs-sheet__trigger:focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: 2px;
  }

  .vs-sheet__trigger-label {
    color: var(--color-text-secondary);
    font-size: var(--text-caption-12);
  }

  .vs-sheet__trigger-summary {
    font-weight: 600;
    text-align: end;
  }

  .vs-sheet-host--live .vs-sheet:not([open]) {
    display: none;
  }

  /* Pinned to the bottom edge rather than centred. A modal dialog's default is inset: 0 with auto
     margins, so all four sides have to be answered, not just the one being moved to. */
  .vs-sheet-host--live .vs-sheet[open] {
    background: var(--color-bg-surface);
    border-radius: var(--radius-card) var(--radius-card) 0 0;
    bottom: 0;
    box-shadow: var(--shadow-2);
    display: block;
    inset-inline: 0;
    margin: 0;

    /* Never the whole screen. A sheet that reaches the top edge reads as a page, and the customer
       loses the one cue that says the thing behind it is still there. */
    max-height: 85vh;
    overflow-y: auto;
    padding: var(--space-4) min(40px, 5vw);
    padding-bottom: calc(var(--space-4) + env(safe-area-inset-bottom, 0));
    position: fixed;
    top: auto;
    width: 100%;
  }

  .vs-sheet-host--live .vs-sheet[open] .vs-sheet__panel {
    display: block;
  }

  .vs-sheet-host--live .vs-sheet[open] .vs-sheet__chrome {
    align-items: center;
    display: flex;
    justify-content: space-between;
  }

  .vs-sheet__chrome--footer {
    padding-top: var(--space-4);
  }

  .vs-sheet__done {
    width: 100%;
  }

  .vs-sheet__close {
    align-items: center;
    background: transparent;
    border: 0;
    border-radius: var(--radius-button);
    color: var(--color-text-secondary);
    display: flex;
    justify-content: center;

    /* 44px rather than the 48 above: this one is a secondary escape sitting next to a heading, and
       "done" below is the target the design points a thumb at. */
    min-height: 44px;
    min-width: 44px;
  }

  .vs-sheet__close:focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: 2px;
  }

  /* Dimmed rather than opaque, so the page the customer was on is still visibly behind the sheet. */
  .vs-sheet::backdrop {
    background: rgb(0 0 0 / 45%);
  }
}

/* ================================================================================================
   360px — the narrowest supported viewport. Nothing new appears here; things stop competing.
   ================================================================================================ */

@media (max-width: 400px) {
  /* Approve and decline never sit side by side below 400px (MOBILE.md, admin reflow). Two 48px
     buttons plus a gap do not fit, and what happens instead is that both shrink until the wrong
     one is easy to press. */
  .vs-queue__actions {
    flex-direction: column;
  }

  .vs-queue__actions .vs-btn {
    width: 100%;
  }

  /* Bulk edit puts its field panel below the selection list rather than beside it. */
  .vs-bulk-edit {
    grid-template-columns: 1fr;
  }
}

/* ================================================================================================
   1440px and up — the widest step. The container stops growing.
   ================================================================================================ */

@media (min-width: 1440px) {
  /* Measure, not width. A line of body text 1400px wide is unreadable however much room there is. */
  .vs-container {
    margin-inline: auto;
    max-width: 1320px;
  }
}

/* ---------------------------------------------------------------------------------------------
   Notification navigation and feeds
   --------------------------------------------------------------------------------------------- */

.vs-notification-link {
  align-items: center;
  display: inline-flex;
  gap: var(--space-2);
  min-height: 44px;
}

.vs-notification-link__icon {
  display: inline-grid;
  flex: 0 0 auto;
  place-items: center;
  position: relative;
}

.vs-notification-link__badge {
  align-items: center;
  background: var(--color-status-error);
  border: 2px solid var(--color-bg-surface);
  border-radius: 999px;
  color: #FFFFFF;
  display: inline-flex;
  font-size: 10px;
  font-weight: 700;
  justify-content: center;
  line-height: 1;
  min-height: 18px;
  min-width: 18px;
  padding-inline: 4px;
  position: absolute;
  inset-block-start: -9px;
  inset-inline-end: -12px;
}

.vs-notification-heading {
  align-items: flex-start;
}

.vs-notification-filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.vs-filter-chip {
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  color: var(--color-text);
  cursor: pointer;
  font: inherit;
  min-height: 40px;
  padding: var(--space-2) var(--space-4);
}

.vs-filter-chip--active {
  background: var(--color-action-primary-wash);
  border-color: var(--color-action-primary);
  color: var(--color-action-primary);
  font-weight: 600;
}

.vs-filter-chip:focus-visible,
.vs-notification-link:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: 2px;
}

.vs-notification-list {
  display: grid;
  gap: var(--space-3);
}

.vs-notification-card {
  align-items: start;
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  display: grid;
  gap: var(--space-4);
  grid-template-columns: minmax(8rem, auto) minmax(0, 1fr) auto;
  padding: var(--space-4);
}

.vs-notification-card--unread {
  border-inline-start: 4px solid var(--color-action-primary);
}

.vs-notification-card--read,
.vs-notification-card--resolved {
  background: var(--color-action-primary-wash);
}

.vs-notification-card__status {
  align-items: center;
  display: inline-flex;
  font-size: var(--text-ui-14);
  font-weight: 600;
  gap: var(--space-1);
}

.vs-notification-card__status--action,
.vs-notification-card__status--warning {
  color: var(--color-status-warning-text);
}

.vs-notification-card__status--info {
  color: var(--color-status-info);
}

.vs-notification-card__content {
  min-width: 0;
  overflow-wrap: anywhere;
}

.vs-notification-card__content h2,
.vs-notification-card__content p {
  margin: 0 0 var(--space-2);
}

.vs-notification-card__actions {
  align-items: flex-end;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.vs-notification-target {
  outline: 3px solid var(--color-action-primary);
  outline-offset: 3px;
}

@media (max-width: 768px) {
  /* Unlike ordinary utility links, the notification indicator stays beside the language chooser. */
  .vs-utility .vs-notification-link {
    display: inline-flex;
  }

  .vs-utility .vs-notification-link__label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }

  .vs-notification-heading,
  .vs-notification-card {
    grid-template-columns: 1fr;
  }

  .vs-notification-heading {
    align-items: stretch;
    flex-direction: column;
  }

  .vs-notification-card__actions {
    align-items: stretch;
    flex-direction: row;
    flex-wrap: wrap;
  }
}
