/* Vivfy UI - cascade layer order. Declared once, first file of the bundle.
   Later layers win over earlier ones regardless of selector specificity.
   Unlayered CSS (Bootstrap, legacy style.php) beats every layer here, which is
   why pages on the v2 layout do not load it (see README.md). */
@layer vf.tokens, vf.base, vf.atoms, vf.molecules, vf.organisms, vf.layouts, vf.utilities;

/* Self-hosted Onest (variable, 400-600) and Poppins 600, served from
   /assets/fonts/ (the bundle is served from /assets/vivfy-ui/, hence ../fonts/).
   File names carry the upstream version, so they are cached as immutable; a
   new version is a new file name. Licence: assets/fonts/OFL.txt. latin covers
   all of Spanish; latin-ext is only downloaded when a character outside it
   shows up (proper names). */
@layer vf.tokens {
  @font-face {
    font-family: "Onest";
    font-style: normal;
    font-weight: 400 600;
    font-display: swap;
    src: url("../fonts/onest-v11-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
  }

  @font-face {
    font-family: "Onest";
    font-style: normal;
    font-weight: 400 600;
    font-display: swap;
    src: url("../fonts/onest-v11-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: "Poppins";
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url("../fonts/poppins-v24-600-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
  }

  @font-face {
    font-family: "Poppins";
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url("../fonts/poppins-v24-600-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }
}

/* Colour tokens. Names mirror vivfy-app src/design-system/tokens/colors.ts
   (camelCase there, kebab-case here, prefixed --vf-color-). */
@layer vf.tokens {
  :root {
    /* brand */
    --vf-color-brand: #2961C7;
    --vf-color-brand-pressed: #214E9F;
    --vf-color-brand-subtle: #E5ECF8;
    --vf-color-brand-subtle-pressed: #D4DFF4;
    --vf-color-brand-edge: #AFC2E8;
    --vf-color-on-brand: #FFFFFF;
    --vf-color-on-brand-muted: #E5ECF8;
    --vf-color-brand-motif-deep: #1F4FA6;
    --vf-color-brand-motif-light: #3A73D6;
    --vf-color-brand-motif-overlap: #183F8A;
    --vf-color-brand-mark-light: #6B9CE9;
    --vf-color-brand-mark-mid: #4675CB;
    --vf-color-brand-mark-overlap: #2961C7;

    /* surfaces */
    --vf-color-background: #EFF0F9;
    --vf-color-surface: #FFFFFF;
    --vf-color-surface-sunken: #E4E6F1;
    --vf-color-surface-pressed: #E9ECF6;
    --vf-color-surface-hover: #F6F7FC;
    --vf-color-surface-quiet: #FAFBFD; /* rows already seen (alert list) */
    --vf-color-surface-tag: #ECEEF5;
    --vf-color-scrim: rgba(27, 37, 64, 0.48);

    /* text */
    --vf-color-text-primary: #1B2540;
    --vf-color-text-secondary: #47506B;
    --vf-color-text-muted: #5C6580;
    --vf-color-text-inverse: #FFFFFF;
    --vf-color-text-link: #214E9F;

    /* borders */
    --vf-color-border-subtle: #E4E7F2;
    --vf-color-border-handle: #C9CEDD;
    --vf-color-border-default: #78809A; /* >= 3:1 on white: inputs, non-text */
    --vf-color-border-focus: #2961C7;
    --vf-color-border-danger: #C3362B;
    --vf-color-timeline-pending: #B9C4DE;

    /* status: text / surface / border / tint */
    --vf-color-success: #3A6B1C;
    --vf-color-success-surface: #EDF5E3;
    --vf-color-success-border: #C5E1A5;
    --vf-color-success-tint: #DCEBCB;
    --vf-color-warning: #8A5200;
    --vf-color-warning-surface: #FFF3E0;
    --vf-color-warning-border: #FFCC80;
    --vf-color-warning-tint: #FFE2BF;
    --vf-color-danger: #C3362B;
    --vf-color-danger-text: #AB2F26;
    --vf-color-danger-surface: #FEECEB;
    --vf-color-danger-border: #F8B4AE;
    --vf-color-danger-tint: #FBD3CF;
    --vf-color-info: #2961C7;
    --vf-color-info-text: #214E9F;
    --vf-color-info-surface: #E5ECF8;

    /* level: marker (>= 3:1 on white, never the only cue), band tint
       (backgrounds only), label ink (>= 4.5:1 on its band), band border */
    --vf-color-level-normal: #5E8F2E;
    --vf-color-level-attention: #9C8700;
    --vf-color-level-alert: #C76E00;
    --vf-color-level-critical: #C3362B;
    --vf-color-level-no-data: #6E6E6E;
    --vf-color-level-normal-band: #F1F8E9;
    --vf-color-level-attention-band: #FFFBD8;
    --vf-color-level-alert-band: #FFF3E0;
    --vf-color-level-critical-band: #FEECEB;
    --vf-color-level-no-data-band: #F4F4F6;
    --vf-color-level-normal-ink: #3A6B1C;
    --vf-color-level-attention-ink: #665E18;
    --vf-color-level-alert-ink: #8A5200;
    --vf-color-level-critical-ink: #AB2F26;
    --vf-color-level-no-data-ink: #555B6E;
    --vf-color-level-normal-border: #C5E1A5;
    --vf-color-level-attention-border: #E9DB7A;
    --vf-color-level-alert-border: #FFCC80;
    --vf-color-level-critical-border: #F8B4AE;
    --vf-color-level-no-data-border: #D6D8E0;
  }
}

/* Typography tokens (desktop scale). Body 0.875rem Onest, titles Poppins 600.
   Never below 0.75rem effective. Every font-family in the bundle reads one of
   the --vf-font-family-* tokens, so overriding them switches the whole page. */
@layer vf.tokens {
  :root {
    --vf-font-family-body: "Onest", system-ui, "Segoe UI", Roboto, sans-serif;
    --vf-font-family-display: "Poppins", "Onest", system-ui, sans-serif;
    --vf-font-family-mono: ui-monospace, "Cascadia Mono", Consolas, monospace;

    --vf-font-weight-regular: 400;
    --vf-font-weight-medium: 500;
    --vf-font-weight-semibold: 600;

    --vf-font-size-display: 1.75rem;
    --vf-line-height-display: 2.25rem;
    --vf-font-size-title: 1.5rem;
    --vf-line-height-title: 2rem;
    --vf-font-size-section: 1.125rem;
    --vf-line-height-section: 1.625rem;
    --vf-font-size-card: 1rem;
    --vf-line-height-card: 1.5rem;
    --vf-font-size-body: 0.875rem;
    --vf-line-height-body: 1.25rem;
    --vf-font-size-read: 1rem;
    --vf-line-height-read: 1.5rem;
    --vf-font-size-small: 0.8125rem;
    --vf-line-height-small: 1.125rem;
    --vf-font-size-caption: 0.75rem;
    --vf-line-height-caption: 1rem;
    --vf-font-size-metric: 1.75rem;
    --vf-line-height-metric: 2.25rem;

    --vf-measure-read: 72ch;
  }
}

/* Spacing (0.25rem base, names mirror vivfy-app space.ts) and sizing tokens. */
@layer vf.tokens {
  :root {
    --vf-space-none: 0;
    --vf-space-xxs: 0.125rem;
    --vf-space-xs: 0.25rem;
    --vf-space-sm: 0.5rem;
    --vf-space-md: 0.75rem;
    --vf-space-lg: 1rem;
    --vf-space-xl: 1.25rem;
    --vf-space-xxl: 1.5rem;
    --vf-space-xxxl: 2rem;
    --vf-space-section: 2.25rem;

    /* controls: 2 / 2.5 / 3rem, default 2.5rem; targets >= 1.5rem */
    --vf-size-control-sm: 2rem;
    --vf-size-control-md: 2.5rem;
    --vf-size-control-lg: 3rem;
    --vf-size-icon-button: 2rem;
    --vf-size-tab: 2.5rem;
    --vf-size-nav-item: 2.5rem;
    --vf-size-row: 3rem;
    --vf-size-row-two-line: 3.5rem;
    --vf-size-row-compact: 2.5rem;
    --vf-size-cell-padding: 0.5rem 0.75rem;

    --vf-size-icon-sm: 1rem;
    --vf-size-icon-md: 1.25rem;
    --vf-size-icon-lg: 1.5rem;

    /* layout */
    --vf-size-sidebar: 15rem;
    --vf-size-topbar: 3.5rem;
    --vf-size-content-max: 100rem;
    --vf-size-drawer: 40rem;
    --vf-size-drawer-wide: 55rem;
    --vf-size-dialog: 32rem;
  }
}

/* Radii. Scale mirrors vivfy-app radii.ts; semantic names on top. */
@layer vf.tokens {
  :root {
    --vf-radius-none: 0;
    --vf-radius-xs: 0.25rem;
    --vf-radius-sm: 0.5rem;
    --vf-radius-md: 0.75rem;
    --vf-radius-lg: 1rem;
    --vf-radius-panel: 1.25rem;
    --vf-radius-xl: 1.5rem;
    --vf-radius-pill: 999rem;

    --vf-radius-card: var(--vf-radius-md);
    --vf-radius-input: var(--vf-radius-sm);
    --vf-radius-tag: 0.375rem;
    --vf-radius-overlay: var(--vf-radius-lg);
  }
}

/* Elevation. Values mirror vivfy-app elevation.ts, converted to rem. */
@layer vf.tokens {
  :root {
    --vf-shadow-none: none;
    --vf-shadow-raised: 0 0.0625rem 0.125rem rgba(27, 37, 64, 0.12); /* a chosen segment on its track */
    --vf-shadow-rest: 0 0.0625rem 0.125rem rgba(27, 37, 64, 0.06), 0 0.5rem 1.5rem rgba(27, 37, 64, 0.08);
    --vf-shadow-float: 0 0.125rem 0.5rem rgba(27, 37, 64, 0.12), 0 0.0625rem 0.125rem rgba(27, 37, 64, 0.08);
    --vf-shadow-modal: 0 0.375rem 1rem rgba(27, 37, 64, 0.16), 0 0.125rem 0.25rem rgba(27, 37, 64, 0.08);
  }
}

/* Stacking order. Overlays sit above the shell; toasts above overlays so a
   confirmation raised from a drawer stays visible. */
@layer vf.tokens {
  :root {
    --vf-z-sticky: 10;
    --vf-z-shell: 20;
    --vf-z-popover: 25;
    --vf-z-overlay: 40;
    --vf-z-toast: 50;
    --vf-z-skip-link: 60;
  }
}

/* Motion. Durations and easings mirror vivfy-app motion.ts. Animate only on
   open; prefers-reduced-motion turns the durations to zero. */
@layer vf.tokens {
  :root {
    --vf-duration-instant: 0ms;
    --vf-duration-fast: 120ms;
    --vf-duration-base: 200ms;
    --vf-duration-slow: 280ms;
    --vf-duration-deliberate: 400ms;
    --vf-easing-standard: cubic-bezier(0.2, 0, 0, 1);
    --vf-easing-enter: cubic-bezier(0, 0, 0, 1);
    --vf-easing-exit: cubic-bezier(0.3, 0, 1, 1);
  }

  @media (prefers-reduced-motion: reduce) {
    :root {
      --vf-duration-fast: 0ms;
      --vf-duration-base: 0ms;
      --vf-duration-slow: 0ms;
      --vf-duration-deliberate: 0ms;
    }
  }
}

/* Reset, scoped under .vf-root so it never touches a legacy page that loads
   the bundle next to Bootstrap. The v2 layouts put .vf-root on <body>. */
@layer vf.base {
  .vf-root,
  .vf-root *,
  .vf-root *::before,
  .vf-root *::after {
    box-sizing: border-box;
  }

  .vf-root {
    margin: 0;
    min-height: 100vh;
    background: var(--vf-color-background);
    color: var(--vf-color-text-primary);
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
    -webkit-font-smoothing: antialiased;
  }

  .vf-root :where(h1, h2, h3, h4, h5, h6, p, ul, ol, li, figure, blockquote, dl, dd, dt, fieldset, legend) {
    margin: 0;
    padding: 0;
  }

  .vf-root :where(fieldset) {
    border: 0;
    min-width: 0;
  }

  .vf-root :where(ul, ol) {
    list-style: none;
  }

  .vf-root :where(button) {
    font: inherit;
    color: inherit;
    border: 0;
    background: none;
    cursor: pointer;
    padding: 0;
    text-align: inherit;
  }

  .vf-root :where(a) {
    color: inherit;
    text-decoration: none;
  }

  .vf-root :where(input, select, textarea) {
    font: inherit;
    color: inherit;
    margin: 0;
  }

  .vf-root :where(table) {
    border-collapse: collapse;
  }

  .vf-root :where(svg) {
    flex: none;
  }

  .vf-root :where(img) {
    max-width: 100%;
    display: block;
  }

  .vf-root [hidden] {
    display: none !important;
  }

  .vf-root.is-scroll-locked {
    overflow: hidden;
  }
}

/* Base type and text helpers. Type classes are part of the base layer so any
   component can override them. */
@layer vf.base {
  .vf-root {
    font-family: var(--vf-font-family-body);
    font-size: var(--vf-font-size-body);
    line-height: var(--vf-line-height-body);
    font-variant-numeric: lining-nums;
  }

  .vf-text-display,
  .vf-text-title,
  .vf-text-section,
  .vf-text-card,
  .vf-text-metric {
    font-family: var(--vf-font-family-display);
    font-weight: var(--vf-font-weight-semibold);
  }

  .vf-text-display { font-size: var(--vf-font-size-display); line-height: var(--vf-line-height-display); letter-spacing: -0.01em; }
  .vf-text-title { font-size: var(--vf-font-size-title); line-height: var(--vf-line-height-title); letter-spacing: -0.01em; }
  .vf-text-section { font-size: var(--vf-font-size-section); line-height: var(--vf-line-height-section); }
  .vf-text-card { font-size: var(--vf-font-size-card); line-height: var(--vf-line-height-card); }
  .vf-text-metric { font-size: var(--vf-font-size-metric); line-height: var(--vf-line-height-metric); font-variant-numeric: tabular-nums; }
  .vf-text-body { font-size: var(--vf-font-size-body); line-height: var(--vf-line-height-body); }
  .vf-text-read { font-size: var(--vf-font-size-read); line-height: var(--vf-line-height-read); max-width: var(--vf-measure-read); }
  .vf-text-small { font-size: var(--vf-font-size-small); line-height: var(--vf-line-height-small); }
  .vf-text-caption { font-size: var(--vf-font-size-caption); line-height: var(--vf-line-height-caption); }

  .vf-text-strong { font-weight: var(--vf-font-weight-semibold); }
  .vf-text-medium { font-weight: var(--vf-font-weight-medium); }
  .vf-text-secondary { color: var(--vf-color-text-secondary); }
  .vf-text-muted { color: var(--vf-color-text-muted); }
  .vf-text-danger { color: var(--vf-color-danger-text); }
  .vf-text-warning { color: var(--vf-color-warning); }
  .vf-text-success { color: var(--vf-color-success); }
  .vf-text-brand { color: var(--vf-color-brand-pressed); }
  .vf-text-num { font-variant-numeric: tabular-nums; }
  .vf-text-nowrap { white-space: nowrap; }
  .vf-text-pre-line { white-space: pre-line; overflow-wrap: anywhere; }

  .vf-link {
    color: var(--vf-color-text-link);
    font-weight: var(--vf-font-weight-medium);
    text-decoration: underline;
    text-underline-offset: 0.1875rem;
    text-decoration-thickness: 1px;
  }

  .vf-link:hover {
    text-decoration-thickness: 0.125rem;
  }

  /* a link that names its target with an icon ("Ver ficha >"): no underline
     until hover, the colour and weight say it is a link */
  .vf-link--quiet {
    display: inline-flex;
    align-items: center;
    gap: 0.125rem;
    font-size: var(--vf-font-size-body);
    text-decoration: none;
    white-space: nowrap;
  }

  .vf-link--quiet .vf-icon { width: 1rem; height: 1rem; }
  .vf-link--quiet:hover { text-decoration: underline; text-decoration-thickness: 1px; }

  .vf-root code,
  .vf-code {
    font-family: var(--vf-font-family-mono);
    font-size: var(--vf-font-size-small);
    background: var(--vf-color-surface-tag);
    border-radius: var(--vf-radius-xs);
    padding: 0 var(--vf-space-xs);
  }
}

/* Focus is always visible for keyboard users (:focus-visible), never for
   mouse clicks. On the blue sidebar the ring turns white (organisms/sidebar). */
@layer vf.base {
  .vf-root :focus {
    outline: none;
  }

  .vf-root :focus-visible {
    outline: 0.125rem solid var(--vf-color-border-focus);
    outline-offset: 0.125rem;
  }

  /* headings that receive focus programmatically (tabindex="-1") */
  .vf-root :where(h1, h2, h3)[tabindex="-1"]:focus {
    outline: none;
  }
}

/* Button. Pill, 2.5rem by default; --lg (3rem) only for the main CTA of a
   wizard step. Label is always verb + object. */
@layer vf.atoms {
  .vf-button {
    --vf-icon-tint: var(--vf-color-brand-subtle-pressed);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--vf-space-sm);
    min-height: var(--vf-size-control-md);
    padding: 0 var(--vf-space-lg);
    border: 0;
    border-radius: var(--vf-radius-pill);
    font-family: inherit;
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-body);
    line-height: 1.125rem;
    white-space: nowrap;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    flex: none;
    background: var(--vf-color-surface);
    color: var(--vf-color-brand-pressed);
    box-shadow: inset 0 0 0 1px var(--vf-color-brand-edge);
    transition: background-color var(--vf-duration-fast) var(--vf-easing-standard), box-shadow var(--vf-duration-fast) var(--vf-easing-standard);
  }

  .vf-button:hover { background: var(--vf-color-brand-subtle); }

  .vf-button--primary {
    --vf-icon-tint: rgba(255, 255, 255, 0.25);
    background: var(--vf-color-brand);
    color: var(--vf-color-on-brand);
    box-shadow: none;
  }
  .vf-button--primary:hover { background: var(--vf-color-brand-pressed); }

  .vf-button--secondary { font-weight: var(--vf-font-weight-medium); }

  .vf-button--tertiary {
    background: transparent;
    box-shadow: none;
    font-weight: var(--vf-font-weight-medium);
    padding: 0 var(--vf-space-md);
  }
  .vf-button--tertiary:hover { background: var(--vf-color-brand-subtle); }

  .vf-button--danger {
    --vf-icon-tint: rgba(255, 255, 255, 0.25);
    background: var(--vf-color-danger);
    color: var(--vf-color-on-brand);
    box-shadow: none;
  }
  .vf-button--danger:hover { background: var(--vf-color-danger-text); }

  .vf-button--danger-outline {
    --vf-icon-tint: var(--vf-color-danger-tint);
    background: var(--vf-color-surface);
    color: var(--vf-color-danger-text);
    box-shadow: inset 0 0 0 1px var(--vf-color-danger);
    font-weight: var(--vf-font-weight-medium);
  }
  .vf-button--danger-outline:hover { background: var(--vf-color-danger-surface); }

  .vf-button--sm {
    min-height: var(--vf-size-control-sm);
    padding: 0 var(--vf-space-md);
    font-size: var(--vf-font-size-small);
  }

  .vf-button--lg {
    min-height: var(--vf-size-control-lg);
    padding: 0 var(--vf-space-xxl);
    font-size: var(--vf-font-size-read);
  }

  .vf-button--block { width: 100%; }

  .vf-button[disabled],
  .vf-button[aria-disabled="true"] {
    background: var(--vf-color-surface-sunken);
    color: var(--vf-color-text-muted);
    box-shadow: none;
    cursor: not-allowed;
  }

  .vf-button--tertiary[disabled],
  .vf-button--tertiary[aria-disabled="true"] { background: transparent; }

  .vf-button__label { min-width: 0; }

  /* md and lg buttons carry a 1.125rem icon; sm keeps the 1rem one */
  .vf-button:not(.vf-button--sm) > .vf-icon { width: 1.125rem; height: 1.125rem; }

  .vf-button-row {
    display: flex;
    gap: var(--vf-space-sm);
    flex-wrap: wrap;
    align-items: center;
  }

  .vf-button-row--end { justify-content: flex-end; }
}

/* Icon-only button. Always carries an aria-label (the visible tooltip is the
   title attribute). 2rem by default, --md 2.5rem. */
@layer vf.atoms {
  .vf-icon-button {
    position: relative;
    display: inline-grid;
    place-items: center;
    width: var(--vf-size-icon-button);
    height: var(--vf-size-icon-button);
    border: 0;
    border-radius: var(--vf-radius-pill);
    background: transparent;
    color: var(--vf-color-text-secondary);
    cursor: pointer;
    flex: none;
  }

  .vf-icon-button:hover {
    background: var(--vf-color-surface-pressed);
    color: var(--vf-color-text-primary);
  }

  .vf-icon-button--md {
    width: var(--vf-size-control-md);
    height: var(--vf-size-control-md);
  }

  .vf-icon-button[disabled] {
    color: var(--vf-color-text-muted);
    background: transparent;
    opacity: 0.55;
    cursor: not-allowed;
  }

  .vf-icon-button__badge {
    position: absolute;
    top: -0.125rem;
    right: -0.25rem;
  }
}

/* Tag (status label) and count (numeric badge). A tag's tone is redundant with
   its text: colour never carries the meaning alone. */
@layer vf.atoms {
  .vf-tag {
    --vf-icon-tint: #D9DCE8;
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    min-height: 1.5rem;
    max-width: 100%;
    padding: 0 var(--vf-space-sm);
    border-radius: var(--vf-radius-tag);
    background: var(--vf-color-surface-tag);
    color: var(--vf-color-text-secondary);
    font-weight: var(--vf-font-weight-medium);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    white-space: nowrap;
  }

  .vf-tag--with-icon { padding-left: 0.375rem; }

  .vf-tag--ok { background: var(--vf-color-success-surface); color: var(--vf-color-success); --vf-icon-tint: var(--vf-color-success-tint); }
  .vf-tag--warn { background: var(--vf-color-warning-surface); color: var(--vf-color-warning); --vf-icon-tint: var(--vf-color-warning-tint); }
  .vf-tag--bad { background: var(--vf-color-danger-surface); color: var(--vf-color-danger-text); --vf-icon-tint: var(--vf-color-danger-tint); }
  .vf-tag--brand { background: var(--vf-color-brand-subtle); color: var(--vf-color-brand-pressed); --vf-icon-tint: var(--vf-color-brand-subtle-pressed); }
  .vf-tag--outline { background: var(--vf-color-surface); box-shadow: inset 0 0 0 1px var(--vf-color-border-handle); }
  .vf-tag--allergy {
    background: var(--vf-color-danger-surface);
    color: var(--vf-color-danger-text);
    box-shadow: inset 0 0 0 1px var(--vf-color-danger-border);
    font-weight: var(--vf-font-weight-semibold);
    --vf-icon-tint: var(--vf-color-danger-tint);
  }

  .vf-count {
    display: inline-grid;
    place-items: center;
    min-width: 1.25rem;
    height: 1.25rem;
    padding: 0 0.375rem;
    border-radius: var(--vf-radius-pill);
    background: var(--vf-color-danger);
    color: var(--vf-color-text-inverse);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-caption);
    line-height: var(--vf-line-height-caption);
    font-variant-numeric: tabular-nums;
    flex: none;
  }

  .vf-count--soft { background: var(--vf-color-surface-sunken); color: var(--vf-color-text-secondary); }
  .vf-count--brand { background: var(--vf-color-brand); }
}

/* Text input and textarea. Invalid state = border + inset bar + inline error
   text (molecules/field), never colour alone. */
@layer vf.atoms {
  .vf-input {
    display: block;
    width: 100%;
    min-width: 0;
    height: var(--vf-size-control-md);
    padding: 0 var(--vf-space-md);
    border: 1px solid var(--vf-color-border-default);
    border-radius: var(--vf-radius-input);
    background-color: var(--vf-color-surface);
    color: var(--vf-color-text-primary);
    font-family: inherit;
    font-size: var(--vf-font-size-body);
    line-height: var(--vf-line-height-body);
  }

  .vf-input::placeholder { color: var(--vf-color-text-muted); }
  .vf-input:hover { border-color: var(--vf-color-text-secondary); }

  .vf-input:focus,
  .vf-input:focus-visible {
    outline: 0.125rem solid var(--vf-color-border-focus);
    outline-offset: -0.0625rem;
    border-color: var(--vf-color-border-focus);
  }

  .vf-input[aria-invalid="true"] {
    border-color: var(--vf-color-border-danger);
    background-color: #FFFBFB;
    box-shadow: inset 0.1875rem 0 0 var(--vf-color-border-danger);
  }

  .vf-input[disabled],
  .vf-input[readonly] {
    background-color: var(--vf-color-background);
    color: var(--vf-color-text-secondary);
    cursor: not-allowed;
  }

  .vf-input[readonly] { cursor: default; }

  .vf-input--sm { height: var(--vf-size-control-sm); }
  .vf-input--lg { height: var(--vf-size-control-lg); font-size: var(--vf-font-size-read); }
  .vf-input--num { text-align: start; letter-spacing: normal; }

  textarea.vf-input {
    height: auto;
    min-height: 5rem;
    padding: var(--vf-space-sm) var(--vf-space-md);
    resize: vertical;
  }

  .vf-input-unit {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
  }

  .vf-input-unit__unit {
    color: var(--vf-color-text-secondary);
    white-space: nowrap;
  }
}

/* Native select styled like .vf-input. Uses background-color (never the
   background shorthand) so the arrow survives the invalid state. */
@layer vf.atoms {
  .vf-select {
    appearance: none;
    padding-right: 2.25rem;
    cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2347506B' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.625rem center;
    background-size: 1.125rem;
  }

  .vf-select[disabled] { cursor: not-allowed; }
}

/* Native checkbox / radio with its label. The whole line is the target. */
@layer vf.atoms {
  .vf-checkbox {
    display: inline-flex;
    align-items: flex-start;
    gap: var(--vf-space-sm);
    min-height: 1.5rem;
    cursor: pointer;
  }

  .vf-checkbox__input {
    width: 1.125rem;
    height: 1.125rem;
    margin: 0.0625rem 0 0;
    accent-color: var(--vf-color-brand);
    cursor: pointer;
    flex: none;
  }

  .vf-checkbox__label { min-width: 0; }

  .vf-checkbox--disabled {
    color: var(--vf-color-text-muted);
    cursor: not-allowed;
  }

  .vf-checkbox--disabled .vf-checkbox__input { cursor: not-allowed; }

  .vf-checkbox__error { margin-top: var(--vf-space-xs); }
}

/* Lucide "duo" icons from icons/sprite.svg: the closed shape is tinted with
   --vf-icon-tint, strokes use currentColor. Decorative unless labelled. */
@layer vf.atoms {
  .vf-icon {
    display: inline-block;
    width: var(--vf-size-icon-md);
    height: var(--vf-size-icon-md);
    flex: none;
    vertical-align: middle;
    color: var(--vf-icon-color, currentColor);
  }

  .vf-icon--xs { width: 0.875rem; height: 0.875rem; }
  .vf-icon--sm { width: var(--vf-size-icon-sm); height: var(--vf-size-icon-sm); }
  .vf-icon--lg { width: var(--vf-size-icon-lg); height: var(--vf-size-icon-lg); }
  .vf-icon--xl { width: 2rem; height: 2rem; }

  .vf-icon--brand { --vf-icon-color: var(--vf-color-brand); }
  .vf-icon--ok { --vf-icon-color: var(--vf-color-success); --vf-icon-tint: var(--vf-color-success-tint); }
  .vf-icon--warn { --vf-icon-color: var(--vf-color-warning); --vf-icon-tint: var(--vf-color-warning-tint); }
  .vf-icon--bad { --vf-icon-color: var(--vf-color-danger-text); --vf-icon-tint: var(--vf-color-danger-tint); }
  .vf-icon--muted { --vf-icon-color: var(--vf-color-text-muted); --vf-icon-tint: var(--vf-color-surface-sunken); }
}

/* Initials avatar. Decorative: the name is always written next to it. */
@layer vf.atoms {
  .vf-avatar {
    display: inline-grid;
    place-items: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--vf-radius-pill);
    background: var(--vf-color-brand-subtle);
    color: var(--vf-color-brand-pressed);
    font-family: var(--vf-font-family-display);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-body);
    flex: none;
  }

  .vf-avatar--sm { width: 2rem; height: 2rem; font-size: var(--vf-font-size-caption); }
  .vf-avatar--lg { width: 3.5rem; height: 3.5rem; font-size: var(--vf-font-size-section); }
}

/* Level badge, marker and legend: own shape + label + value for every
   level, never colour alone. Markers are >= 3:1 on white, label ink >= 4.5:1
   on its band. normal = circle with check, attention = diamond with !,
   alert = triangle with !, critical = octagon with !, no-data = dashed ring
   with a dash. */
@layer vf.atoms {
  .vf-level-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    min-height: 1.75rem;
    padding: 0 0.625rem 0 0.375rem;
    border: 1px solid transparent;
    border-radius: var(--vf-radius-tag);
    font-weight: var(--vf-font-weight-medium);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    white-space: nowrap;
  }

  .vf-level-badge--lg {
    min-height: 2.25rem;
    padding: 0 0.75rem 0 0.5rem;
    gap: 0.5rem;
    font-size: var(--vf-font-size-body);
    font-weight: var(--vf-font-weight-semibold);
  }

  .vf-level-badge__value {
    font-weight: var(--vf-font-weight-semibold);
    font-variant-numeric: tabular-nums;
  }

  .vf-level-badge__sep { opacity: 0.6; }

  .vf-level-badge--normal { background: var(--vf-color-level-normal-band); color: var(--vf-color-level-normal-ink); border-color: var(--vf-color-level-normal-border); }
  .vf-level-badge--attention { background: var(--vf-color-level-attention-band); color: var(--vf-color-level-attention-ink); border-color: var(--vf-color-level-attention-border); }
  .vf-level-badge--alert { background: var(--vf-color-level-alert-band); color: var(--vf-color-level-alert-ink); border-color: var(--vf-color-level-alert-border); }
  .vf-level-badge--critical { background: var(--vf-color-level-critical-band); color: var(--vf-color-level-critical-ink); border-color: var(--vf-color-level-critical-border); }
  .vf-level-badge--no-data { background: var(--vf-color-level-no-data-band); color: var(--vf-color-level-no-data-ink); border-color: var(--vf-color-level-no-data-border); }

  .vf-level-badge--plain {
    background: none;
    border-color: transparent;
    padding-left: 0;
  }

  /* the marker shape (inline SVG) */
  .vf-level-mark {
    display: inline-block;
    width: 1rem;
    height: 1rem;
    flex: none;
  }

  .vf-level-badge--lg .vf-level-mark { width: 1.25rem; height: 1.25rem; }
  .vf-level-mark--sm { width: 0.875rem; height: 0.875rem; }
  .vf-level-mark--lg { width: 1.25rem; height: 1.25rem; }
  .vf-level-mark--xl { width: 1.5rem; height: 1.5rem; }

  .vf-level-mark__shape { fill: var(--vf-level-color); }
  .vf-level-mark__glyph { stroke: var(--vf-color-text-inverse); stroke-width: 2.4; stroke-linecap: round; fill: none; }
  .vf-level-mark__dot { fill: var(--vf-color-text-inverse); }

  .vf-level-mark--normal { --vf-level-color: var(--vf-color-level-normal); }
  .vf-level-mark--attention { --vf-level-color: var(--vf-color-level-attention); }
  .vf-level-mark--alert { --vf-level-color: var(--vf-color-level-alert); }
  .vf-level-mark--critical { --vf-level-color: var(--vf-color-level-critical); }
  .vf-level-mark--no-data { --vf-level-color: var(--vf-color-level-no-data); }

  .vf-level-mark--no-data .vf-level-mark__shape {
    fill: var(--vf-color-text-inverse);
    stroke: var(--vf-level-color);
    stroke-width: 2.2;
    stroke-dasharray: 3.2 2.6;
  }

  .vf-level-mark--no-data .vf-level-mark__glyph { stroke: var(--vf-level-color); stroke-width: 2.2; }

  .vf-level-legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--vf-space-xs) var(--vf-space-lg);
    font-size: var(--vf-font-size-small);
    color: var(--vf-color-text-secondary);
  }

  .vf-level-legend__item {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
  }
}

/* Spinner. Wrap it in role="status" with a visually hidden label. With
   reduced motion it stops rotating and shows a static ring. */
@layer vf.atoms {
  .vf-spinner {
    display: inline-block;
    width: 1.25rem;
    height: 1.25rem;
    border-radius: var(--vf-radius-pill);
    border: 0.1875rem solid var(--vf-color-brand-subtle-pressed);
    border-top-color: var(--vf-color-brand);
    animation: vf-spin 0.8s linear infinite;
    flex: none;
  }

  .vf-spinner--sm { width: 1rem; height: 1rem; border-width: 0.125rem; }
  .vf-spinner--lg { width: 2rem; height: 2rem; border-width: 0.25rem; }

  @keyframes vf-spin {
    to { transform: rotate(360deg); }
  }

  @media (prefers-reduced-motion: reduce) {
    .vf-spinner { animation: none; border-top-color: var(--vf-color-brand-subtle-pressed); border-right-color: var(--vf-color-brand); }
  }
}

/* Loading placeholder. Hide it from assistive tech (aria-hidden) and announce
   the loading state once on the container (aria-busy). */
@layer vf.atoms {
  .vf-skeleton {
    display: block;
    height: 0.875rem;
    border-radius: 0.375rem;
    background: linear-gradient(90deg, var(--vf-color-surface-sunken) 0%, #EEF0F7 50%, var(--vf-color-surface-sunken) 100%);
    background-size: 200% 100%;
    animation: vf-skeleton 1.4s ease-in-out infinite;
  }

  .vf-skeleton--lg { height: 1.25rem; }
  .vf-skeleton--circle { width: 2rem; height: 2rem; border-radius: var(--vf-radius-pill); }

  @keyframes vf-skeleton {
    from { background-position: 100% 0; }
    to { background-position: -100% 0; }
  }

  @media (prefers-reduced-motion: reduce) {
    .vf-skeleton { animation: none; }
  }
}

/* Form field: label + control + help + inline error. The control points at
   help and error with aria-describedby (see the field component). */
@layer vf.molecules {
  .vf-field {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    min-width: 0;
  }

  .vf-field__label {
    font-weight: var(--vf-font-weight-medium);
    color: var(--vf-color-text-primary);
  }

  .vf-field__optional {
    font-weight: var(--vf-font-weight-regular);
    color: var(--vf-color-text-secondary);
  }

  .vf-field__help {
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    color: var(--vf-color-text-secondary);
  }

  .vf-field__error {
    --vf-icon-tint: var(--vf-color-danger-tint);
    display: flex;
    align-items: flex-start;
    gap: 0.375rem;
    color: var(--vf-color-danger-text);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    font-weight: var(--vf-font-weight-medium);
  }

  .vf-field__error:empty { display: none; }

  .vf-form-grid {
    display: grid;
    gap: var(--vf-space-lg);
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .vf-form-grid__full { grid-column: 1 / -1; }

  @media (max-width: 64rem) {
    .vf-form-grid { grid-template-columns: minmax(0, 1fr); }
  }
}

/* Form section: a titled group of fields inside a drawer, a dialog or a form
   column. Consecutive sections are split by a hairline; the gap above it
   belongs to the parent (a vf-stack around the sections).
   Without a title the section has no head, for a single-field section whose
   field label already names it. */
@layer vf.molecules {
  .vf-form-section {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-md);
    min-width: 0;
  }

  .vf-form-section + .vf-form-section {
    padding-top: var(--vf-space-xl);
    border-top: 1px solid var(--vf-color-border-subtle);
  }

  .vf-form-section__head {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxs);
  }

  .vf-form-section__title {
    font-family: var(--vf-font-family-display);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-card);
    line-height: var(--vf-line-height-card);
  }

  .vf-form-section__desc {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-form-section__body {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-lg);
    min-width: 0;
  }
}

/* Option cards: native radios/checkboxes inside a card-sized label. Selection
   is shown with :has(:checked), no JavaScript needed. */
@layer vf.molecules {
  .vf-option-cards {
    display: grid;
    gap: var(--vf-space-sm);
    min-width: 0;
  }

  .vf-option-cards:focus { outline: none; }

  .vf-option-cards__legend {
    font-weight: var(--vf-font-weight-medium);
    margin-bottom: var(--vf-space-sm);
  }

  .vf-option-cards__list {
    display: grid;
    gap: var(--vf-space-sm);
  }

  .vf-option-cards--cols-2 .vf-option-cards__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .vf-option-cards--cols-3 .vf-option-cards__list { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  .vf-option-card {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: var(--vf-space-md);
    min-width: 0;
    padding: var(--vf-space-md) var(--vf-space-lg);
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-surface);
    box-shadow: inset 0 0 0 1px var(--vf-color-border-default);
    cursor: pointer;
  }

  .vf-option-card:hover { box-shadow: inset 0 0 0 1px var(--vf-color-brand); }

  .vf-option-card__input {
    width: 1.125rem;
    height: 1.125rem;
    margin: 0.1875rem 0 0;
    accent-color: var(--vf-color-brand);
    flex: none;
    cursor: pointer;
  }

  .vf-option-card__input:focus-visible { outline: none; }

  .vf-option-card:has(.vf-option-card__input:checked) {
    background: var(--vf-option-band, var(--vf-color-brand-subtle));
    box-shadow: inset 0 0 0 0.125rem var(--vf-option-accent, var(--vf-color-brand));
  }

  .vf-option-card:has(.vf-option-card__input:focus-visible) {
    outline: 0.125rem solid var(--vf-color-border-focus);
    outline-offset: 0.125rem;
  }

  .vf-option-card:has(.vf-option-card__input:disabled) {
    opacity: 0.55;
    cursor: not-allowed;
  }

  .vf-option-card__text {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxs);
    min-width: 0;
    flex: 1;
  }

  .vf-option-card__title { font-weight: var(--vf-font-weight-semibold); }

  .vf-option-card__desc {
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    color: var(--vf-color-text-secondary);
  }

  /* Toned options (item tone): the title leads with the tone's mark (a
     semáforo level shape, or an ok/warn/bad/neutral icon) so the meaning
     never rests on colour alone; once checked, the card takes the tone's
     band and border instead of the brand ones. */
  .vf-option-card__title--marked {
    display: inline-flex;
    align-items: center;
    gap: var(--vf-space-sm);
  }

  .vf-option-card--normal { --vf-option-accent: var(--vf-color-level-normal); --vf-option-band: var(--vf-color-level-normal-band); }
  .vf-option-card--attention { --vf-option-accent: var(--vf-color-level-attention); --vf-option-band: var(--vf-color-level-attention-band); }
  .vf-option-card--alert { --vf-option-accent: var(--vf-color-level-alert); --vf-option-band: var(--vf-color-level-alert-band); }
  .vf-option-card--critical { --vf-option-accent: var(--vf-color-level-critical); --vf-option-band: var(--vf-color-level-critical-band); }
  .vf-option-card--ok { --vf-option-accent: var(--vf-color-success); --vf-option-band: var(--vf-color-success-surface); }
  .vf-option-card--warn { --vf-option-accent: var(--vf-color-warning); --vf-option-band: var(--vf-color-warning-surface); }
  .vf-option-card--bad { --vf-option-accent: var(--vf-color-danger); --vf-option-band: var(--vf-color-danger-surface); }
  .vf-option-card--neutral { --vf-option-accent: var(--vf-color-text-secondary); --vf-option-band: var(--vf-color-surface-hover); }

  .vf-option-cards--invalid .vf-option-card { box-shadow: inset 0 0 0 1px var(--vf-color-border-danger); }

  @media (max-width: 64rem) {
    .vf-option-cards--cols-3 .vf-option-cards__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }

  @media (max-width: 48rem) {
    .vf-option-cards--stack-mobile .vf-option-cards__list { grid-template-columns: minmax(0, 1fr); }
  }
}

/* Search box: a .vf-input with a leading search icon. */
@layer vf.molecules {
  .vf-search-box {
    position: relative;
    min-width: 0;
  }

  .vf-search-box__icon {
    position: absolute;
    left: 0.75rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--vf-color-text-secondary);
    pointer-events: none;
  }

  .vf-search-box .vf-input { padding-left: 2.375rem; }
}

/* Key-value list (<dl class="vf-kv">) made of rows (<div class="vf-kv-row">
   with <dt> + <dd>). --lines adds hairlines between rows. */
@layer vf.molecules {
  .vf-kv {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-sm);
  }

  .vf-kv-row {
    display: grid;
    grid-template-columns: minmax(6rem, 40%) minmax(0, 1fr);
    gap: var(--vf-space-lg);
    align-items: baseline;
  }

  .vf-kv-row__key { color: var(--vf-color-text-secondary); }
  .vf-kv-row__value { font-weight: var(--vf-font-weight-medium); min-width: 0; overflow-wrap: anywhere; }

  .vf-kv--lines { gap: 0; }
  .vf-kv--lines .vf-kv-row { padding: var(--vf-space-sm) 0; border-bottom: 1px solid var(--vf-color-border-subtle); }
  .vf-kv--lines .vf-kv-row:last-child { border-bottom: 0; }
}

/* Meter: the level bands of a variable with a marker at the current value
   and tick values under the track. The container carries role="img" and a
   full text label; the level badge next to it repeats level + value. */
@layer vf.molecules {
  .vf-meter {
    position: relative;
    padding-top: 1.75rem;
  }

  .vf-meter__track {
    display: flex;
    gap: var(--vf-space-xxs);
    height: 0.625rem;
  }

  .vf-meter__band { display: block; min-width: 0.25rem; }
  .vf-meter__band:first-child { border-radius: 0.3125rem 0 0 0.3125rem; }
  .vf-meter__band:last-child { border-radius: 0 0.3125rem 0.3125rem 0; }
  .vf-meter__band--normal { background: var(--vf-color-level-normal); }
  .vf-meter__band--attention { background: var(--vf-color-level-attention); }
  .vf-meter__band--alert { background: var(--vf-color-level-alert); }
  .vf-meter__band--critical { background: var(--vf-color-level-critical); }

  .vf-meter__mark {
    position: absolute;
    top: 0;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--vf-space-xxs);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-small);
    line-height: 1rem;
    white-space: nowrap;
  }

  .vf-meter__mark::after {
    content: "";
    border-left: 0.375rem solid transparent;
    border-right: 0.375rem solid transparent;
    border-top: 0.5rem solid var(--vf-color-text-primary);
  }

  .vf-meter__ticks {
    position: relative;
    height: 1.125rem;
    margin-top: var(--vf-space-xs);
    font-size: var(--vf-font-size-caption);
    line-height: 1.125rem;
    color: var(--vf-color-text-secondary);
  }

  .vf-meter__tick {
    position: absolute;
    transform: translateX(-50%);
    white-space: nowrap;
  }
}

/* Progress: how much of a known total is done ("4 de 5 hechas", "2 de 3
   subidos"). The track carries role="progressbar" with aria-valuetext; the
   visible text repeats it and is hidden from assistive technology. An optional
   visible label (show_label) goes above the bar. Tones: brand (default), ok
   and warn. The meter of the triage levels is a different component
   (meter.css). */
@layer vf.molecules {
  .vf-progress {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xs);
    min-width: 0;
  }

  .vf-progress__label {
    margin: 0;
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    font-weight: var(--vf-font-weight-medium);
  }

  .vf-progress__row {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
    min-width: 0;
  }

  .vf-progress__track {
    flex: 1 1 6rem;
    min-width: 4rem;
    height: 0.5rem;
    border-radius: var(--vf-radius-pill);
    background: var(--vf-color-brand-subtle);
    overflow: hidden;
  }

  .vf-progress__bar {
    display: block;
    height: 100%;
    border-radius: inherit;
    background: var(--vf-color-brand);
  }

  .vf-progress--ok .vf-progress__bar {
    background: var(--vf-color-success);
  }

  .vf-progress--warn .vf-progress__bar {
    background: var(--vf-color-warning);
  }

  .vf-progress__text {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
}

/* Tabs (ARIA tablist). js/tabs.js hides inactive panels and adds arrow-key
   navigation; without JavaScript every panel stays visible. */
@layer vf.molecules {
  .vf-tabs {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-lg);
    min-width: 0;
  }

  .vf-tabs__list {
    display: flex;
    gap: var(--vf-space-xs);
    border-bottom: 1px solid var(--vf-color-border-subtle);
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: thin;
  }

  .vf-tabs__tab {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: var(--vf-space-sm);
    min-height: var(--vf-size-tab);
    padding: 0 var(--vf-space-md);
    color: var(--vf-color-text-secondary);
    font-weight: var(--vf-font-weight-medium);
    white-space: nowrap;
    flex: none;
  }

  .vf-tabs__tab:hover { color: var(--vf-color-text-primary); }

  .vf-tabs__tab[aria-selected="true"] {
    color: var(--vf-color-brand-pressed);
    font-weight: var(--vf-font-weight-semibold);
  }

  .vf-tabs__tab[aria-selected="true"]::after {
    content: "";
    position: absolute;
    left: var(--vf-space-sm);
    right: var(--vf-space-sm);
    bottom: -1px;
    height: 0.1875rem;
    border-radius: 0.125rem;
    background: var(--vf-color-brand);
  }

  .vf-tabs__tab:focus-visible {
    outline-offset: -0.125rem;
    border-radius: 0.375rem;
  }

  .vf-tabs__panel { min-width: 0; }
  .vf-tabs__panel:focus-visible { outline-offset: 0.25rem; border-radius: var(--vf-radius-xs); }
}

/* In-page banner. Tone is repeated by the icon and the title text. */
@layer vf.molecules {
  .vf-banner {
    display: flex;
    gap: var(--vf-space-md);
    align-items: flex-start;
    padding: var(--vf-space-md) var(--vf-space-lg);
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-surface);
    box-shadow: inset 0 0 0 1px var(--vf-color-border-subtle);
    color: var(--vf-color-text-primary);
  }

  .vf-banner__body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xs);
  }

  .vf-banner__title { font-weight: var(--vf-font-weight-semibold); }
  .vf-banner__actions { display: flex; gap: var(--vf-space-sm); flex-wrap: wrap; margin-top: var(--vf-space-xs); }

  .vf-banner--ok { background: var(--vf-color-success-surface); box-shadow: inset 0 0 0 1px var(--vf-color-success-border); }
  .vf-banner--warn { background: var(--vf-color-warning-surface); box-shadow: inset 0 0 0 1px var(--vf-color-warning-border); }
  .vf-banner--bad { background: var(--vf-color-danger-surface); box-shadow: inset 0 0 0 1px var(--vf-color-danger-border); }
  .vf-banner--brand { background: var(--vf-color-brand-subtle); box-shadow: none; }

  .vf-banner--strong.vf-banner--bad { box-shadow: inset 0 0 0 1px var(--vf-color-danger-border), inset 0.25rem 0 0 var(--vf-color-danger); }
  .vf-banner--strong.vf-banner--warn { box-shadow: inset 0 0 0 1px var(--vf-color-warning-border), inset 0.25rem 0 0 var(--vf-color-level-alert); }

  /* Plain notice: the icon and text alone, no box, for a note inside a white
     panel (a form drawer or dialog) where a tinted box would read as a card. */
  .vf-banner.vf-banner--plain {
    padding: 0;
    background: none;
    box-shadow: none;
  }
}

/* Empty / error / no-permission state: icon + title + what to do next. */
@layer vf.molecules {
  .vf-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--vf-space-sm);
    padding: var(--vf-space-xxxl) var(--vf-space-lg);
    color: var(--vf-color-text-secondary);
  }

  .vf-empty-state__icon {
    display: grid;
    place-items: center;
    flex: none;
  }

  .vf-empty-state__icon .vf-icon { width: 2.5rem; height: 2.5rem; }
  .vf-empty-state--inline .vf-empty-state__icon .vf-icon { width: var(--vf-size-icon-lg); height: var(--vf-size-icon-lg); }

  .vf-empty-state__title {
    font-family: var(--vf-font-family-display);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-card);
    line-height: var(--vf-line-height-card);
    color: var(--vf-color-text-primary);
  }

  .vf-empty-state__body { max-width: 44ch; }
  .vf-empty-state__actions { display: flex; gap: var(--vf-space-sm); flex-wrap: wrap; justify-content: center; margin-top: var(--vf-space-sm); }

  .vf-empty-state--inline {
    flex-direction: row;
    align-items: flex-start;
    text-align: left;
    padding: var(--vf-space-lg);
    gap: var(--vf-space-md);
  }

  .vf-empty-state--inline .vf-empty-state__actions { justify-content: flex-start; }

  .vf-empty-state__text { display: flex; flex-direction: column; gap: var(--vf-space-xs); min-width: 0; }
}

/* Pagination: <nav aria-label> with links; the current page has
   aria-current="page". */
@layer vf.molecules {
  .vf-pagination {
    display: flex;
    align-items: center;
    gap: var(--vf-space-xs);
    flex-wrap: wrap;
  }

  .vf-pagination__page {
    display: inline-grid;
    place-items: center;
    min-width: 2rem;
    height: 2rem;
    padding: 0 0.375rem;
    border-radius: var(--vf-radius-pill);
    color: var(--vf-color-text-secondary);
    font-weight: var(--vf-font-weight-medium);
    font-variant-numeric: tabular-nums;
  }

  .vf-pagination__page:hover { background: var(--vf-color-surface-pressed); color: var(--vf-color-text-primary); }

  .vf-pagination__page[aria-current="page"] {
    background: var(--vf-color-brand);
    color: var(--vf-color-on-brand);
  }

  .vf-pagination__page[aria-disabled="true"] {
    opacity: 0.45;
    cursor: not-allowed;
    background: none;
  }

  .vf-pagination__page--gap,
  .vf-pagination__page--gap:hover { background: none; color: var(--vf-color-text-secondary); }

  .vf-pagination__info {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    margin-right: var(--vf-space-sm);
  }
}

/* Wizard steps (ordered list). The current step has aria-current="step". */
@layer vf.molecules {
  .vf-stepper {
    display: flex;
    gap: var(--vf-space-sm);
    align-items: center;
    flex-wrap: wrap;
  }

  .vf-stepper__step {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
    min-height: 2.5rem;
    color: var(--vf-color-text-secondary);
    font-weight: var(--vf-font-weight-medium);
  }

  .vf-stepper__step + .vf-stepper__step::before {
    content: "";
    width: 1.5rem;
    height: 0.125rem;
    margin-right: var(--vf-space-xs);
    border-radius: 0.0625rem;
    background: var(--vf-color-border-handle);
  }

  .vf-stepper__number {
    display: grid;
    place-items: center;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: var(--vf-radius-pill);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-caption);
    box-shadow: inset 0 0 0 0.125rem var(--vf-color-border-default);
    flex: none;
  }

  .vf-stepper__step[aria-current="step"] { color: var(--vf-color-brand-pressed); font-weight: var(--vf-font-weight-semibold); }
  .vf-stepper__step[aria-current="step"] .vf-stepper__number { background: var(--vf-color-brand); color: var(--vf-color-on-brand); box-shadow: none; }
  .vf-stepper__step.is-done .vf-stepper__number { background: var(--vf-color-brand-subtle); color: var(--vf-color-brand-pressed); box-shadow: none; }
}

/* Link tabs: tabs that are navigation, one URL each (aria-current="page").
   Unlike molecules/tabs (panels switched in the browser), every tab is a
   real link, so it works without JavaScript and can be bookmarked. */
@layer vf.molecules {
  .vf-link-tabs { min-width: 0; }

  .vf-link-tabs__list {
    display: flex;
    gap: var(--vf-space-xs);
    border-bottom: 1px solid var(--vf-color-border-subtle);
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: thin;
  }

  .vf-link-tabs__tab {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: var(--vf-space-sm);
    min-height: var(--vf-size-tab);
    padding: 0 var(--vf-space-md);
    color: var(--vf-color-text-secondary);
    font-weight: var(--vf-font-weight-medium);
    text-decoration: none;
    white-space: nowrap;
    flex: none;
  }

  .vf-link-tabs__tab:hover { color: var(--vf-color-text-primary); }

  .vf-link-tabs__tab[aria-current="page"] {
    color: var(--vf-color-brand-pressed);
    font-weight: var(--vf-font-weight-semibold);
  }

  .vf-link-tabs__tab[aria-current="page"]::after {
    content: "";
    position: absolute;
    left: var(--vf-space-sm);
    right: var(--vf-space-sm);
    bottom: -1px;
    height: 0.1875rem;
    border-radius: 0.125rem;
    background: var(--vf-color-brand);
  }

  .vf-link-tabs__tab:focus-visible {
    outline-offset: -0.125rem;
    border-radius: 0.375rem;
  }

  .vf-link-tabs__count[hidden] { display: none; }
}

/* Timeline: the steps of a process (an alert's trail) in order. A step is
   done (filled node + solid line), current (ring with a dot), pending (empty
   ring + dotted line) or an extra event (ring with an icon). The state is
   also written for screen readers, never shown by colour alone. */
@layer vf.molecules {
  .vf-timeline {
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .vf-timeline__item {
    position: relative;
    display: flex;
    gap: var(--vf-space-md);
    padding-bottom: var(--vf-space-lg);
  }

  .vf-timeline__item:last-child { padding-bottom: 0; }

  .vf-timeline__item::before {
    content: "";
    position: absolute;
    left: 0.6875rem;
    top: 1.625rem;
    bottom: 0.125rem;
    width: 0.125rem;
    border-radius: 0.0625rem;
    background: repeating-linear-gradient(to bottom, var(--vf-color-timeline-pending) 0 0.25rem, transparent 0.25rem 0.5rem);
  }

  .vf-timeline__item--done::before { background: var(--vf-color-brand); }
  .vf-timeline__item:last-child::before { display: none; }

  .vf-timeline__node {
    display: grid;
    place-items: center;
    width: 1.5rem;
    height: 1.5rem;
    flex: none;
    border-radius: var(--vf-radius-pill);
    background: var(--vf-color-surface);
    box-shadow: inset 0 0 0 0.125rem var(--vf-color-timeline-pending);
    color: var(--vf-color-on-brand);
  }

  .vf-timeline__item--done .vf-timeline__node {
    background: var(--vf-color-brand);
    box-shadow: none;
  }

  .vf-timeline__item--current .vf-timeline__node { box-shadow: inset 0 0 0 0.125rem var(--vf-color-brand); }

  .vf-timeline__item--current .vf-timeline__node::after {
    content: "";
    width: 0.625rem;
    height: 0.625rem;
    border-radius: var(--vf-radius-pill);
    background: var(--vf-color-brand);
  }

  .vf-timeline__item--event .vf-timeline__node {
    box-shadow: inset 0 0 0 0.125rem var(--vf-color-border-handle);
    color: var(--vf-color-brand);
    --vf-icon-tint: var(--vf-color-brand-subtle);
  }

  .vf-timeline__body {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxs);
    min-width: 0;
    padding-top: var(--vf-space-xxs);
  }

  .vf-timeline__title { font-weight: var(--vf-font-weight-medium); }

  .vf-timeline__meta {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-timeline__note {
    max-width: var(--vf-measure-read);
    margin-top: var(--vf-space-xs);
    padding: var(--vf-space-sm) var(--vf-space-md);
    border-radius: var(--vf-radius-sm);
    background: var(--vf-color-surface);
    box-shadow: inset 0 0 0 1px var(--vf-color-border-subtle);
    white-space: pre-line;
    overflow-wrap: anywhere;
  }
}

/* Filter bar: one compact row of filters over a list, as the prototype's
   chips row. Each __item is a small label beside a --sm control; the less
   used filters (dates) sit in a disclosure (__more) that opens inline and
   starts open when one of them is set. Used on the screen's own
   <form method="get">, so it works without JavaScript. --grid packs the
   filters in columns of at least 10rem, each control filling its cell, for
   a narrow card (the list of a master-detail); the open dates take a row.
   __search, __item--wide and __count make the wide row of a full-width
   list (patients): search first, a 14rem select, the count at the end;
   --roomy gives that row the same 0.75rem gap when it wraps. --stacked
   puts the filters in rows (__row) one under the other: chips that take
   the room left and a segmented control at the end, then the disclosure
   with the less used filters (the notices of a doctor). */
@layer vf.molecules {
  .vf-filter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-sm) var(--vf-space-md);
    min-width: 0;
  }

  .vf-filter-bar__item {
    display: inline-flex;
    align-items: center;
    gap: var(--vf-space-sm);
    min-width: 0;
  }

  /* a label with a wider control (the sort order's segmented control): on a
     narrow screen the control drops under its label instead of overflowing */
  .vf-filter-bar__item--group { flex-wrap: wrap; }

  .vf-filter-bar__label {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    font-weight: var(--vf-font-weight-medium);
    white-space: nowrap;
  }

  .vf-filter-bar__item .vf-input {
    width: auto;
    min-width: 6rem;
    max-width: 11rem;
  }

  .vf-filter-bar__item .vf-input[type="date"] {
    width: 9rem;
    min-width: 0;
    font-variant-numeric: tabular-nums;
  }

  .vf-filter-bar__item .vf-input[type="date"]::-webkit-calendar-picker-indicator {
    opacity: 0.7;
    cursor: pointer;
  }

  .vf-filter-bar__more {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-sm) var(--vf-space-md);
    min-width: 0;
  }

  .vf-filter-bar__toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    min-height: var(--vf-size-control-sm);
    padding: 0 var(--vf-space-md);
    border-radius: var(--vf-radius-pill);
    background: var(--vf-color-surface);
    box-shadow: inset 0 0 0 1px var(--vf-color-border-default);
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    font-weight: var(--vf-font-weight-medium);
    white-space: nowrap;
    list-style: none;
    cursor: pointer;
  }

  .vf-filter-bar__toggle::-webkit-details-marker { display: none; }

  .vf-filter-bar__toggle:hover {
    box-shadow: inset 0 0 0 1px var(--vf-color-brand);
    color: var(--vf-color-text-primary);
  }

  .vf-filter-bar__more[open] > .vf-filter-bar__toggle {
    background: var(--vf-color-brand-subtle);
    box-shadow: inset 0 0 0 1px var(--vf-color-brand);
    color: var(--vf-color-brand-pressed);
    font-weight: var(--vf-font-weight-semibold);
  }

  .vf-filter-bar__toggle .vf-icon:last-child { transition: transform var(--vf-duration-fast) var(--vf-easing-standard); }
  .vf-filter-bar__more[open] > .vf-filter-bar__toggle .vf-icon:last-child { transform: rotate(180deg); }

  .vf-filter-bar__panel {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-sm) var(--vf-space-md);
  }

  .vf-filter-bar__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-xs);
    margin-left: auto;
  }

  .vf-filter-bar--roomy { gap: var(--vf-space-md); }

  /* the list's own search field leads the row and takes the room left */
  .vf-filter-bar__search {
    flex: 1 1 20rem;
    max-width: 28rem;
    min-width: 0;
  }

  /* a filter with long options at the regular control size (14rem) */
  .vf-filter-bar__item--wide .vf-input {
    width: 14rem;
    max-width: 100%;
  }

  /* on a phone a wide filter takes the whole row, its select the room left
     after the label (never wider than the screen) */
  @media (max-width: 40rem) {
    .vf-filter-bar__item--wide { flex: 1 1 100%; }
    .vf-filter-bar__item--wide .vf-input { flex: 1 1 auto; width: auto; min-width: 0; }
  }

  /* on the narrowest phones, labels above their controls, controls and the
     filter bar's own button as wide as the bar */
  @media (max-width: 30rem) {
    .vf-filter-bar__item--wide,
    .vf-filter-bar__item--group { flex: 1 1 100%; flex-direction: column; align-items: stretch; gap: var(--vf-space-xs); }
    .vf-filter-bar__item--wide .vf-input { width: 100%; }
    .vf-filter-bar > .vf-button { flex: 1 1 100%; justify-content: center; }
  }

  /* the count of results, pushed to the end of the row */
  .vf-filter-bar__count {
    margin-left: auto;
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    white-space: nowrap;
  }

  .vf-filter-bar--stacked {
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
    gap: var(--vf-space-md);
  }

  .vf-filter-bar__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--vf-space-md) var(--vf-space-xl);
    min-width: 0;
  }

  .vf-filter-bar__row > .vf-filter-chips { flex: 1 1 24rem; }

  .vf-filter-bar--grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(10rem, 100%), 1fr));
    align-items: center;
  }

  .vf-filter-bar--grid .vf-filter-bar__item .vf-input {
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
    max-width: none;
  }

  .vf-filter-bar--grid .vf-filter-bar__more[open] { grid-column: 1 / -1; }
  .vf-filter-bar--grid .vf-filter-bar__actions { grid-column: -2 / -1; justify-self: end; }
}

/* Person link: a whole-row link to a person's page on a tinted chip (the
   patient of an open alert): avatar, name, facts and the action that says
   where it goes ("Ver ficha >"). Grows to fill its row from 18rem. */
@layer vf.molecules {
  .vf-person-link {
    display: flex;
    align-items: center;
    gap: var(--vf-space-md);
    flex: 1 1 18rem;
    min-width: 0;
    min-height: 3rem;
    padding: var(--vf-space-sm) var(--vf-space-md);
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-background);
    color: inherit;
    text-decoration: none;
  }

  .vf-person-link:hover { background: var(--vf-color-surface-pressed); }

  .vf-person-link__text {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxs);
    flex: 1 1 auto;
    min-width: 0;
  }

  .vf-person-link__name {
    font-weight: var(--vf-font-weight-medium);
    overflow-wrap: anywhere;
  }

  .vf-person-link__meta {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    overflow-wrap: anywhere;
  }

  .vf-person-link:hover .vf-person-link__action { text-decoration: underline; }
}

/* Filter chips: a labelled row of toggle chips over a list (the prototype's
   "Nivel" and "Vistas" rows). Each chip is a real checkbox (several at once)
   or radio (one of them) inside a GET form, so it works without
   JavaScript; the input is hidden and the chip face shows its state. A
   checked chip swaps its leading mark for a check, as the prototype. A
   chip wider than its row (a long label on a phone) wraps its text instead
   of overflowing the page. */
@layer vf.molecules {
  .vf-filter-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-md);
    min-width: 0;
  }

  .vf-filter-chips__label {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    font-weight: var(--vf-font-weight-medium);
  }

  .vf-filter-chips__list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-sm);
    min-width: 0;
  }

  .vf-filter-chips__chip {
    position: relative;
    display: inline-flex;
    max-width: 100%;
    cursor: pointer;
  }

  .vf-filter-chips__input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
  }

  .vf-filter-chips__face {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    min-height: var(--vf-size-control-sm);
    padding: 0 var(--vf-space-md);
    border-radius: var(--vf-radius-pill);
    background: var(--vf-color-surface);
    box-shadow: inset 0 0 0 1px var(--vf-color-border-default);
    color: var(--vf-color-text-secondary);
    font-weight: var(--vf-font-weight-medium);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    white-space: nowrap;
  }

  @media (max-width: 40rem) {
    .vf-filter-chips__face { white-space: normal; overflow-wrap: anywhere; }
  }

  .vf-filter-chips__chip:hover .vf-filter-chips__face {
    box-shadow: inset 0 0 0 1px var(--vf-color-brand);
    color: var(--vf-color-text-primary);
  }

  .vf-filter-chips__input:checked + .vf-filter-chips__face {
    background: var(--vf-color-brand-subtle);
    box-shadow: inset 0 0 0 1px var(--vf-color-brand);
    color: var(--vf-color-brand-pressed);
    font-weight: var(--vf-font-weight-semibold);
  }

  .vf-filter-chips__input:focus-visible + .vf-filter-chips__face {
    outline: 0.125rem solid var(--vf-color-border-focus);
    outline-offset: 0.125rem;
  }

  .vf-filter-chips__mark,
  .vf-filter-chips__check {
    display: inline-flex;
    flex: none;
  }

  .vf-filter-chips__check,
  .vf-filter-chips__input:checked + .vf-filter-chips__face .vf-filter-chips__mark { display: none; }

  .vf-filter-chips__input:checked + .vf-filter-chips__face .vf-filter-chips__check { display: inline-flex; }

  .vf-filter-chips__action { margin-left: var(--vf-space-xs); }
}

/* Section head: icon (or the Vivfy mark) + section title + an aside pushed
   to the right, for sections on the page background (home page). The icon
   and the title are one group (__main) that never splits; when the aside
   does not fit next to it, the aside drops to the next line. */
@layer vf.molecules {
  .vf-section-head {
    display: flex;
    flex-wrap: wrap; /* the aside drops under the title when both don't fit */
    align-items: center;
    gap: var(--vf-space-sm);
    min-height: 2rem;
    min-width: 0;
  }

  .vf-section-head__main {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
    flex: 1 1 auto;
    min-width: 0;
  }

  .vf-section-head__mark {
    width: 1rem;
    height: 1rem;
    flex: none;
  }

  .vf-section-head__mark-light { fill: var(--vf-color-brand-mark-light); }
  .vf-section-head__mark-mid { fill: var(--vf-color-brand-mark-mid); }
  .vf-section-head__mark-deep { fill: var(--vf-color-brand); }

  .vf-section-head__title {
    font-family: var(--vf-font-family-display);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-section);
    line-height: var(--vf-line-height-section);
    min-width: 0;
    overflow-wrap: anywhere;
  }

  .vf-section-head__note {
    color: var(--vf-color-text-secondary);
    font-weight: var(--vf-font-weight-regular);
  }

  .vf-section-head__aside {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-sm);
    margin-left: auto;
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }
}

/* Metric: a KPI tile on the page background (white, rest shadow): label
   with icon, big number, optional foot line. A quiet link in the foot keeps
   the foot's small size. */
@layer vf.molecules {
  .vf-metric {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xs);
    min-width: 0;
    padding: var(--vf-space-lg);
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-surface);
    box-shadow: var(--vf-shadow-rest);
  }

  .vf-metric__label {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-metric__label .vf-icon { width: 1.125rem; height: 1.125rem; flex: none; }

  .vf-metric__label > span { min-width: 0; }

  /* narrowest phones (two tiles per row): the icon goes above the label, so
     the label gets the whole tile and wraps between words */
  @media (max-width: 24rem) {
    .vf-metric__label { flex-direction: column; align-items: flex-start; gap: var(--vf-space-xs); }
  }

  .vf-metric__value {
    font-family: var(--vf-font-family-display);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-metric);
    line-height: var(--vf-line-height-metric);
    font-variant-numeric: tabular-nums;
  }

  .vf-metric__foot {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-metric__foot .vf-link--quiet { font-size: inherit; }
}

/* Alert card: a critical alert waiting for the doctor (home page). Red band
   with a red bar while pending; --reviewed (viewed, not attended yet) is a
   white card with a grey bar and a calmer title. Under 40rem the tag and the
   action drop below the text, on a row of their own that wraps (the action
   goes under the tag when both don't fit). */
@layer vf.molecules {
  .vf-alert-card {
    display: flex;
    align-items: center;
    gap: var(--vf-space-lg);
    min-width: 0;
    padding: var(--vf-space-lg);
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-danger-surface);
    box-shadow: inset 0 0 0 1px var(--vf-color-danger-border), inset 0.25rem 0 0 var(--vf-color-danger);
  }

  .vf-alert-card--reviewed {
    background: var(--vf-color-surface);
    box-shadow: inset 0 0 0 1px var(--vf-color-border-subtle), inset 0.25rem 0 0 var(--vf-color-border-handle);
  }

  .vf-alert-card__mark {
    display: flex;
    flex: none;
  }

  .vf-alert-card__mark .vf-level-mark { width: 1.75rem; height: 1.75rem; }

  .vf-alert-card__text {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xs);
    flex: 1 1 auto;
    min-width: 0;
  }

  .vf-alert-card__title {
    font-weight: var(--vf-font-weight-semibold);
    color: var(--vf-color-danger-text);
    overflow-wrap: anywhere;
  }

  .vf-alert-card--reviewed .vf-alert-card__title {
    font-weight: var(--vf-font-weight-medium);
    color: var(--vf-color-text-primary);
  }

  .vf-alert-card__meta {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    overflow-wrap: anywhere;
  }

  .vf-alert-card__note {
    display: flex;
    align-items: center;
    gap: var(--vf-space-xs);
    color: var(--vf-color-brand-pressed);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-alert-card__aside {
    display: flex;
    align-items: center;
    gap: var(--vf-space-lg);
    flex: none;
  }

  @media (max-width: 40rem) {
    .vf-alert-card { flex-wrap: wrap; }
    .vf-alert-card__text { flex-basis: calc(100% - 1.75rem - var(--vf-space-lg)); }
    .vf-alert-card__aside {
      flex: 1 1 100%; /* its own row, as wide as the card: never wider */
      flex-wrap: wrap;
      gap: var(--vf-space-sm) var(--vf-space-lg);
      min-width: 0;
      padding-left: calc(1.75rem + var(--vf-space-lg));
    }
  }
}

/* Level tiles: one tile per semáforo level (shape + name + count +
   meaning), each a link; white with the level's colour as a top bar, the
   current one tinted with the level's band and outlined. Five columns; the
   meaning hides under 64rem; one-line tiles under 40rem. */
@layer vf.molecules {
  .vf-level-tiles {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: var(--vf-space-md);
    min-width: 0;
  }

  .vf-level-tiles__tile {
    --vf-level-tile-color: var(--vf-color-level-no-data);
    --vf-level-tile-band: var(--vf-color-level-no-data-band);
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xs);
    min-width: 0;
    padding: var(--vf-space-md) var(--vf-space-lg);
    border-top: 0.25rem solid var(--vf-level-tile-color);
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-surface);
    box-shadow: var(--vf-shadow-rest);
    color: var(--vf-color-text-primary);
    text-decoration: none;
  }

  .vf-level-tiles__tile:hover { box-shadow: var(--vf-shadow-rest), inset 0 0 0 1px var(--vf-level-tile-color); }

  .vf-level-tiles__tile[aria-current="true"] {
    background: var(--vf-level-tile-band);
    box-shadow: inset 0 0 0 0.125rem var(--vf-level-tile-color);
  }

  .vf-level-tiles__tile--critical { --vf-level-tile-color: var(--vf-color-level-critical); --vf-level-tile-band: var(--vf-color-level-critical-band); }
  .vf-level-tiles__tile--alert { --vf-level-tile-color: var(--vf-color-level-alert); --vf-level-tile-band: var(--vf-color-level-alert-band); }
  .vf-level-tiles__tile--attention { --vf-level-tile-color: var(--vf-color-level-attention); --vf-level-tile-band: var(--vf-color-level-attention-band); }
  .vf-level-tiles__tile--normal { --vf-level-tile-color: var(--vf-color-level-normal); --vf-level-tile-band: var(--vf-color-level-normal-band); }

  .vf-level-tiles__head {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
    min-width: 0;
  }

  .vf-level-tiles__label {
    min-width: 0;
    font-weight: var(--vf-font-weight-semibold);
    overflow-wrap: anywhere;
  }

  .vf-level-tiles__count {
    font-family: var(--vf-font-family-display);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-metric);
    line-height: var(--vf-line-height-metric);
    font-variant-numeric: tabular-nums;
  }

  .vf-level-tiles__description {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  @media (max-width: 64rem) {
    .vf-level-tiles { gap: var(--vf-space-sm); }
    .vf-level-tiles__tile { padding: var(--vf-space-sm) var(--vf-space-md); }
    .vf-level-tiles__description { display: none; }
  }

  /* on a phone each tile is one line (shape, name, count at the right), as
     many columns of 10rem as fit: one on a 20rem phone */
  @media (max-width: 40rem) {
    .vf-level-tiles { grid-template-columns: repeat(auto-fill, minmax(min(100%, 10rem), 1fr)); }
    .vf-level-tiles__tile { flex-direction: row; align-items: center; gap: var(--vf-space-sm); }
    .vf-level-tiles__label { overflow-wrap: normal; }
    .vf-level-tiles__count { margin-left: auto; font-size: var(--vf-font-size-section); line-height: var(--vf-line-height-section); }
  }
}

/* Level bar: how a group splits across the semáforo levels. A track with one
   segment per level that has people, each as wide as its share (--vf-share,
   a unitless number the template sets inline, D28), and a legend with the
   level's shape, name and count, so colour is never the only cue. The track
   carries role="img" with every count in its label. */
@layer vf.molecules {
  .vf-level-bar {
    display: grid;
    gap: var(--vf-space-sm);
    min-width: 0;
  }

  .vf-level-bar__track {
    display: flex;
    gap: var(--vf-space-xxs);
    height: 0.625rem;
    border-radius: var(--vf-radius-pill);
    overflow: hidden;
    background: var(--vf-color-level-no-data-band);
  }

  .vf-level-bar__segment {
    --vf-share: 1;
    display: block;
    flex: var(--vf-share) 1 0;
    min-width: 0.25rem;
    background: var(--vf-color-level-no-data);
  }

  .vf-level-bar__segment--critical { background: var(--vf-color-level-critical); }
  .vf-level-bar__segment--alert { background: var(--vf-color-level-alert); }
  .vf-level-bar__segment--attention { background: var(--vf-color-level-attention); }
  .vf-level-bar__segment--normal { background: var(--vf-color-level-normal); }

  .vf-level-bar__legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--vf-space-xs) var(--vf-space-md);
    margin: 0;
    padding: 0;
    list-style: none;
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-level-bar__key {
    display: inline-flex;
    align-items: center;
    gap: var(--vf-space-xs);
  }

  .vf-level-bar__count {
    color: var(--vf-color-text-primary);
    font-weight: var(--vf-font-weight-semibold);
    font-variant-numeric: tabular-nums;
  }
}

/* Status hero: the level of a period said in words (title with the level
   shape + one reading sentence), tinted with the level's band and a left bar
   in the level's colour. The tone always comes from the level, never from a
   colour name. */
@layer vf.molecules {
  .vf-status-hero {
    display: grid;
    gap: var(--vf-space-sm);
    padding: var(--vf-space-lg);
    border-radius: var(--vf-radius-card);
    border-left: 0.375rem solid var(--vf-color-level-no-data);
    background: var(--vf-color-level-no-data-band);
  }

  .vf-status-hero__title {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
    margin: 0;
    font-size: var(--vf-font-size-card);
    line-height: var(--vf-line-height-card);
    font-weight: var(--vf-font-weight-semibold);
    color: var(--vf-color-level-no-data-ink);
  }

  .vf-status-hero__body {
    margin: 0;
    max-width: 48rem;
    font-size: var(--vf-font-size-read);
    line-height: var(--vf-line-height-read);
    color: var(--vf-color-text-primary);
  }

  .vf-status-hero--normal { border-left-color: var(--vf-color-level-normal); background: var(--vf-color-level-normal-band); }
  .vf-status-hero--normal .vf-status-hero__title { color: var(--vf-color-level-normal-ink); }
  .vf-status-hero--attention { border-left-color: var(--vf-color-level-attention); background: var(--vf-color-level-attention-band); }
  .vf-status-hero--attention .vf-status-hero__title { color: var(--vf-color-level-attention-ink); }
  .vf-status-hero--alert { border-left-color: var(--vf-color-level-alert); background: var(--vf-color-level-alert-band); }
  .vf-status-hero--alert .vf-status-hero__title { color: var(--vf-color-level-alert-ink); }
  .vf-status-hero--critical { border-left-color: var(--vf-color-level-critical); background: var(--vf-color-level-critical-band); }
  .vf-status-hero--critical .vf-status-hero__title { color: var(--vf-color-level-critical-ink); }
}

/* Segmented control: a pill of mutually exclusive links (or submit buttons
   of a form, aria-pressed) on a sunken track; the chosen one is white with
   brand ink. Wraps instead of overflowing on narrow screens. */
@layer vf.molecules {
  .vf-segmented {
    display: inline-flex;
    flex-wrap: wrap;
    gap: var(--vf-space-xxs);
    max-width: 100%;
    padding: 0.1875rem;
    border-radius: var(--vf-radius-xl); /* not the prototype's pill: the track wraps onto two lines on narrow screens */
    background: var(--vf-color-surface-sunken);
  }

  .vf-segmented__item {
    display: inline-flex;
    align-items: center;
    min-height: var(--vf-size-control-sm);
    padding: 0 var(--vf-space-md);
    border-radius: var(--vf-radius-pill);
    color: var(--vf-color-text-secondary);
    font-weight: var(--vf-font-weight-medium);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    text-decoration: none;
  }

  /* on the narrowest phones the options wrap in rows inside a squarer track */
  @media (max-width: 30rem) {
    .vf-segmented { border-radius: var(--vf-radius-md); }
    .vf-segmented__item { border-radius: var(--vf-radius-sm); }
  }

  button.vf-segmented__item {
    border: 0;
    background: transparent;
    font-family: inherit;
    cursor: pointer;
  }

  .vf-segmented__item:hover { color: var(--vf-color-text-primary); }

  .vf-segmented__item[aria-current="true"],
  .vf-segmented__item[aria-pressed="true"] {
    background: var(--vf-color-surface);
    color: var(--vf-color-brand-pressed);
    font-weight: var(--vf-font-weight-semibold);
    box-shadow: var(--vf-shadow-raised);
  }
}

/* Password input with a reveal toggle (molecules/password-input). The toggle
   is rendered hidden and js/password.js shows it, so without JavaScript the
   control is a plain password field. The pressed state (aria-pressed) picks
   which of its two icons shows. */
@layer vf.molecules {
  .vf-password-input {
    position: relative;
    min-width: 0;
  }

  .vf-password-input__control {
    padding-right: calc(var(--vf-size-icon-button) + var(--vf-space-md));
  }

  .vf-password-input__toggle {
    position: absolute;
    top: 50%;
    right: var(--vf-space-xs);
    transform: translateY(-50%);
  }

  .vf-password-input__toggle[hidden] { display: none; }

  .vf-password-input__toggle[aria-pressed="true"] .vf-password-input__icon--show,
  .vf-password-input__toggle:not([aria-pressed="true"]) .vf-password-input__icon--hide { display: none; }

  .vf-password-input__icon {
    display: inline-grid;
    place-items: center;
  }
}

/* Live list of the password rules (molecules/password-rules). Each rule says
   its state with an icon, the text colour and a visually hidden word
   ("cumplido", "pendiente", "no cumplido"), never with colour alone. The state
   class is is-ok / is-bad on the item; without either the rule is pending. */
@layer vf.molecules {
  .vf-password-rules {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xs);
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-password-rules__item {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
  }

  .vf-password-rules__item.is-ok { color: var(--vf-color-success); }

  .vf-password-rules__item.is-bad {
    color: var(--vf-color-danger-text);
    font-weight: var(--vf-font-weight-medium);
  }

  .vf-password-rules__mark { display: none; }

  .vf-password-rules__item:not(.is-ok):not(.is-bad) .vf-password-rules__mark--pending,
  .vf-password-rules__item.is-ok .vf-password-rules__mark--ok,
  .vf-password-rules__item.is-bad .vf-password-rules__mark--bad {
    display: inline-grid;
    place-items: center;
  }
}

/* One-time code input (molecules/otp-input): a single field, not one box per
   digit, so pasting and the SMS autofill (autocomplete="one-time-code") work.
   Large, spaced, centred digits. */
@layer vf.molecules {
  .vf-otp-input {
    max-width: 12rem;
    font-size: var(--vf-font-size-title);
    letter-spacing: 0.75rem;
    text-align: center;
    font-variant-numeric: tabular-nums;
  }

  .vf-otp-input::placeholder { letter-spacing: 0.75rem; }
}

/* Error summary of a form (molecules/error-summary): what to fix, each item
   a link to its field. Rendered first in the form and focused when the page
   loads (js/error-summary.js). */
@layer vf.molecules {
  .vf-error-summary {
    --vf-icon-tint: var(--vf-color-danger-tint);
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-sm);
    padding: var(--vf-space-md) var(--vf-space-lg);
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-danger-surface);
    /* 1px: the hairline border, the only px the design system allows (README) */
    box-shadow: inset 0 0 0 1px var(--vf-color-danger-border), inset 0.25rem 0 0 var(--vf-color-danger);
  }

  /* focused on render (js/error-summary.js): one ring in the focus colour,
     apart from the summary's own border, as every other focus in the DS */
  .vf-error-summary:focus,
  .vf-error-summary:focus-visible {
    outline: 0.125rem solid var(--vf-color-border-focus);
    outline-offset: 0.25rem;
  }

  .vf-error-summary__title {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
    color: var(--vf-color-danger-text);
    font-size: var(--vf-font-size-body);
    line-height: var(--vf-line-height-body);
    font-weight: var(--vf-font-weight-semibold);
  }

  .vf-error-summary__list {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xs);
    padding-left: 1.75rem;
    list-style: disc;
  }

  .vf-error-summary__link {
    color: var(--vf-color-danger-text);
    font-weight: var(--vf-font-weight-medium);
    text-decoration: underline;
    text-underline-offset: 0.1875rem;
  }
}

/* Prescription line (the prototype's "rx-line"): pill icon, drug and
   presentation, the dose sentence, instructions, who issued it and status
   tags, with optional actions at the end. --compact is the one-line row of
   a summary card (tags at the right). Also used for a diagnosis line with
   another icon. .vf-prescription-lines stacks lines with hairlines. */
@layer vf.molecules {
  .vf-prescription-lines {
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .vf-prescription-lines > * + * { border-top: 1px solid var(--vf-color-border-subtle); }

  .vf-prescription-line {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--vf-space-md);
    padding: var(--vf-space-md) var(--vf-space-lg);
    min-width: 0;
  }

  .vf-prescription-line__lead { padding-top: 0.125rem; }

  .vf-prescription-line__body {
    display: flex;
    flex: 1 1 14rem;
    flex-direction: column;
    gap: var(--vf-space-xs);
    min-width: 0;
    overflow-wrap: anywhere;
  }

  .vf-prescription-line__detail,
  .vf-prescription-line__meta {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-prescription-line__note {
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-prescription-line__tags,
  .vf-prescription-line__aside,
  .vf-prescription-line__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-xs);
  }

  .vf-prescription-line__actions { margin-left: auto; }

  .vf-prescription-line--compact { align-items: center; }
  .vf-prescription-line--compact .vf-prescription-line__meta { overflow-wrap: anywhere; }
}

/* Disclosure (the prototype's "details.disc"): a native <details> whose
   summary carries a chevron that turns when open; aria-controls points to
   the body. Inside a flush card it sits under the rows with a hairline;
   --card makes it a card of its own. Children of the body get hairlines. */
@layer vf.molecules {
  .vf-disclosure__summary {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
    min-height: 2.5rem;
    padding: 0 var(--vf-space-lg);
    border-top: 1px solid var(--vf-color-border-subtle);
    font-weight: var(--vf-font-weight-medium);
    list-style: none;
    cursor: pointer;
  }

  .vf-disclosure__summary::-webkit-details-marker { display: none; }
  .vf-disclosure__summary .vf-icon { transition: transform var(--vf-duration-fast) var(--vf-easing-standard); }
  .vf-disclosure[open] > .vf-disclosure__summary .vf-icon { transform: rotate(90deg); }
  .vf-disclosure__summary:hover { background: var(--vf-color-surface-pressed); }

  .vf-disclosure__body > * + * { border-top: 1px solid var(--vf-color-border-subtle); }
  .vf-disclosure[open] > .vf-disclosure__body { border-top: 1px solid var(--vf-color-border-subtle); }

  .vf-disclosure--card {
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-surface);
    box-shadow: var(--vf-shadow-rest);
    overflow: hidden;
  }

  .vf-disclosure--card > .vf-disclosure__summary { border-top: 0; min-height: 3rem; }
}

/* Safety bar: what the patient already takes, always in view on top of a
   prescription form (the prototype's "Toma actualmente"). */
@layer vf.molecules {
  .vf-safety-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--vf-space-xs) var(--vf-space-lg);
    min-width: 0;
    padding: var(--vf-space-sm) var(--vf-space-md);
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-surface-sunken);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-safety-bar__label { font-weight: var(--vf-font-weight-semibold); }

  .vf-safety-bar__items {
    min-width: 0;
    overflow-wrap: anywhere;
  }
}

/* Dose sentence: the fields of one dose (quantity, frequency, first dose,
   duration, start) flowing as one line that wraps, and under them what the
   server computed from them (doses per day, total, end date, schedule). */
@layer vf.molecules {
  .vf-dose-sentence {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-md);
    min-width: 0;
  }

  .vf-dose-sentence__fields {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--vf-space-md);
    min-width: 0;
  }

  .vf-dose-sentence__fields > * {
    flex: 1 1 8rem;
    min-width: 0;
  }

  .vf-dose-sentence__summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-xs);
    min-width: 0;
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }
}

/* Phone preview: a schematic of what the patient will see in the app (the
   prototype's "Así lo verá"). Content only, no real device chrome. */
@layer vf.molecules {
  .vf-phone-preview {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-sm);
    min-width: 0;
  }

  .vf-phone-preview__caption {
    display: flex;
    align-items: center;
    gap: var(--vf-space-xs);
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-phone-preview__device {
    overflow: hidden;
    border-radius: 1.5rem;
    background: var(--vf-color-surface);
    box-shadow: inset 0 0 0 1px var(--vf-color-border-default);
  }

  .vf-phone-preview__top {
    padding: var(--vf-space-lg);
    background: var(--vf-color-brand);
    color: var(--vf-color-on-brand);
  }

  .vf-phone-preview__kicker { font-size: var(--vf-font-size-small); }
  .vf-phone-preview__title { font-weight: var(--vf-font-weight-semibold); }

  .vf-phone-preview__body {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-sm);
    padding: var(--vf-space-md);
    background: var(--vf-color-surface-sunken);
  }

  .vf-phone-preview__card {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xs);
    min-width: 0;
    padding: var(--vf-space-md);
    border-radius: 0.75rem;
    background: var(--vf-color-surface);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    overflow-wrap: anywhere;
  }

  .vf-phone-preview__note {
    flex-direction: row;
    align-items: center;
    gap: var(--vf-space-sm);
  }

  .vf-phone-preview__card-title { font-weight: var(--vf-font-weight-semibold); }

  .vf-phone-preview__rows {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxs);
    margin: 0;
  }

  .vf-phone-preview__row {
    display: flex;
    justify-content: space-between;
    gap: var(--vf-space-sm);
  }

  .vf-phone-preview__row dd {
    margin: 0;
    text-align: right;
  }

  .vf-phone-preview__foot {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-phone-preview__bubble {
    margin: 0;
    padding: var(--vf-space-md) var(--vf-space-lg);
    border-radius: var(--vf-radius-lg) var(--vf-radius-lg) var(--vf-radius-lg) var(--vf-radius-xs);
    background: var(--vf-color-surface-sunken);
    color: var(--vf-color-text-primary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    overflow-wrap: anywhere;
  }

  .vf-phone-preview--sms .vf-phone-preview__foot {
    padding: 0;
    color: var(--vf-color-text-secondary);
  }
}

/* Prescription sheet: the printable "Fórmula médica" of one prescription
   order. On screen it is a sheet of paper on the desk; printed, only the
   sheet goes out (layouts/print.css hides the shell), in letter or A5. */
@layer vf.molecules {
  .vf-prescription-sheet {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xl);
    width: min(54rem, 100%);
    min-width: 0;
    margin-inline: auto;
    padding: var(--vf-space-xxxl);
    border-radius: var(--vf-radius-xs);
    background: var(--vf-color-surface);
    box-shadow: var(--vf-shadow-rest);
    overflow-wrap: anywhere;
  }

  .vf-prescription-sheet--a5 {
    width: min(37rem, 100%);
    gap: var(--vf-space-lg);
    padding: var(--vf-space-xxl);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-prescription-sheet__head {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: var(--vf-space-lg);
    padding-bottom: var(--vf-space-md);
    border-bottom: 0.125rem solid var(--vf-color-text-primary);
  }

  .vf-prescription-sheet__brand { font-weight: var(--vf-font-weight-semibold); }

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

  .vf-prescription-sheet__title {
    font-family: var(--vf-font-family-display);
    font-size: var(--vf-font-size-title);
    line-height: var(--vf-line-height-title);
    font-weight: var(--vf-font-weight-semibold);
  }

  .vf-prescription-sheet__section {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-sm);
  }

  .vf-prescription-sheet__section-title {
    font-family: var(--vf-font-family-display);
    font-size: var(--vf-font-size-card);
    line-height: var(--vf-line-height-card);
    font-weight: var(--vf-font-weight-semibold);
  }

  .vf-prescription-sheet__facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(12rem, 100%), 1fr));
    gap: var(--vf-space-sm) var(--vf-space-lg);
    margin: 0;
  }

  .vf-prescription-sheet__key {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-caption);
    line-height: var(--vf-line-height-caption);
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }

  .vf-prescription-sheet__value { margin: 0; }
  .vf-prescription-sheet__value--strong { font-weight: var(--vf-font-weight-semibold); }

  .vf-prescription-sheet__items {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-md);
    margin: 0;
    padding-left: var(--vf-space-xl);
  }

  .vf-prescription-sheet__item {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxs);
  }

  .vf-prescription-sheet__sentence { font-weight: var(--vf-font-weight-semibold); }

  .vf-prescription-sheet__sign {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xs);
    padding-top: var(--vf-space-lg);
    border-top: 1px solid var(--vf-color-border-default);
  }

  .vf-prescription-sheet__small,
  .vf-prescription-sheet__foot {
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-prescription-sheet__foot { color: var(--vf-color-text-secondary); }

  @media print {
    .vf-prescription-sheet {
      width: auto;
      padding: 0;
      box-shadow: none;
      border-radius: 0;
    }

    .vf-prescription-sheet--letter { page: vf-letter; }
    .vf-prescription-sheet--a5 { page: vf-a5; }
  }
}

@page vf-letter { size: letter; margin: 1.5rem; }
@page vf-a5 { size: A5; margin: 1rem; }

/* Chat thread: what the care team sent to the patient, oldest first, with day
   separators. Own messages go to the end side; the list scrolls on its own
   (focusable, so a keyboard can scroll it). */
@layer vf.molecules {
  .vf-chat-thread {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-sm);
    min-width: 0;
    max-height: 28rem;
    margin: 0;
    padding: var(--vf-space-md);
    overflow-y: auto;
    list-style: none;
  }

  .vf-chat-thread--empty {
    max-height: none;
    color: var(--vf-color-text-secondary);
    text-align: center;
  }

  .vf-chat-thread__day {
    align-self: center;
    padding: var(--vf-space-xs) 0;
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-caption);
    line-height: var(--vf-line-height-caption);
  }

  .vf-chat-thread__bubble {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxs);
    align-self: flex-start;
    max-width: min(32rem, 85%);
    min-width: 0;
    padding: var(--vf-space-sm) var(--vf-space-md);
    border-radius: var(--vf-radius-lg);
    background: var(--vf-color-surface-sunken);
    overflow-wrap: anywhere;
  }

  .vf-chat-thread__bubble--mine {
    align-self: flex-end;
    background: var(--vf-color-brand-subtle);
  }

  .vf-chat-thread__bubble--urgent { box-shadow: inset 0.25rem 0 0 var(--vf-color-warning); }

  .vf-chat-thread__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-xs);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-chat-thread__meta {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-caption);
    line-height: var(--vf-line-height-caption);
  }
}

/* Composer: the form under a chat thread (kind, templates, text, send). */
@layer vf.molecules {
  .vf-composer {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-md);
    min-width: 0;
    padding: var(--vf-space-md);
    border-top: 0.0625rem solid var(--vf-color-border-subtle);
  }

  .vf-composer__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--vf-space-sm);
    min-width: 0;
  }

  .vf-composer__body {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-md);
    min-width: 0;
  }

  .vf-composer__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--vf-space-sm);
  }
}

/* Quote: words the patient wrote, shown as they came, with who and where. */
@layer vf.molecules {
  .vf-quote {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxs);
    min-width: 0;
    margin: 0;
    padding: var(--vf-space-sm) var(--vf-space-md);
    border-left: 0.25rem solid var(--vf-color-brand);
    border-radius: var(--vf-radius-md);
    background: var(--vf-color-surface-sunken);
  }

  .vf-quote__text {
    margin: 0;
    overflow-wrap: anywhere;
  }

  .vf-quote__caption {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }
}

/* Change list: what a save changes, field by field, before (struck through)
   and after. A tag marks fields that need extra confirmation (identity). */
@layer vf.molecules {
  .vf-change-list {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-sm);
    min-width: 0;
  }

  .vf-change-list__title { font-weight: var(--vf-font-weight-semibold); }

  .vf-change-list__items {
    margin: 0;
    padding: 0;
    list-style: none;
    border: 1px solid var(--vf-color-border-subtle);
    border-radius: var(--vf-radius-md);
  }

  .vf-change-list__item {
    display: grid;
    grid-template-columns: minmax(0, 12rem) minmax(0, 1fr);
    gap: var(--vf-space-xs) var(--vf-space-lg);
    align-items: center;
    padding: var(--vf-space-md) var(--vf-space-lg);
  }

  .vf-change-list__item + .vf-change-list__item { border-top: 1px solid var(--vf-color-border-subtle); }

  .vf-change-list__label {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-xs);
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-change-list__values {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-sm);
    min-width: 0;
    overflow-wrap: anywhere;
  }

  .vf-change-list__before { color: var(--vf-color-text-secondary); }

  .vf-change-list__after {
    text-decoration: none;
    font-weight: var(--vf-font-weight-semibold);
  }

  @media (max-width: 40rem) {
    .vf-change-list__item { grid-template-columns: minmax(0, 1fr); }
  }
}

/* Diff: one recorded value before (struck through) and after (link colour,
   semibold). Inline pair, or one side alone inside a table cell. */
@layer vf.molecules {
  .vf-diff {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-xs);
    min-width: 0;
  }

  .vf-diff__old {
    color: var(--vf-color-text-secondary);
    text-decoration: line-through;
    overflow-wrap: anywhere;
  }

  .vf-diff__new {
    color: var(--vf-color-text-link);
    font-weight: var(--vf-font-weight-semibold);
    text-decoration: none;
    overflow-wrap: anywhere;
  }

  .vf-diff__same {
    color: var(--vf-color-text-primary);
    overflow-wrap: anywhere;
  }
}

/* File input: the native input is visually hidden and its label is styled as
   a small secondary button; the list beside it shows the chosen files (filled
   by js/file-input.js). Errors use the field's invalid state. */
@layer vf.molecules {
  .vf-file-input__box {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-sm) var(--vf-space-md);
    min-width: 0;
    padding: var(--vf-space-sm) var(--vf-space-md);
    border: 1px dashed var(--vf-color-border-default);
    border-radius: var(--vf-radius-input);
  }

  .vf-field--invalid .vf-file-input__box { border-color: var(--vf-color-border-danger); }

  .vf-file-input__input:focus-visible + .vf-button {
    outline: 0.125rem solid var(--vf-color-brand);
    outline-offset: 0.125rem;
  }

  .vf-file-input__list {
    display: grid;
    gap: var(--vf-space-xs);
    min-width: 0;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--vf-font-size-small);
  }

  .vf-file-input__empty { color: var(--vf-color-text-secondary); }

  .vf-file-input__file {
    display: flex;
    align-items: center;
    gap: var(--vf-space-xs);
    min-width: 0;
  }

  .vf-file-input__name { overflow-wrap: anywhere; }

  .vf-file-input__meta {
    color: var(--vf-color-text-secondary);
    white-space: nowrap;
  }
}

/* Checklist: requirements with a state icon (done, missing, info) and a
   visually hidden "(completo)" / "(pendiente)" for screen readers. */
@layer vf.molecules {
  .vf-checklist {
    display: grid;
    gap: var(--vf-space-sm);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .vf-checklist__item {
    display: flex;
    align-items: flex-start;
    gap: var(--vf-space-sm);
    min-width: 0;
  }

  .vf-checklist__item > span {
    min-width: 0;
    overflow-wrap: anywhere;
  }
}

/* Notice mark: the round mark that leads a notice row and says what kind of
   notice it is (a hospital discharge, missing doses, an orange reading).
   An icon on a tinted disc: --brand for neutral news, --warn for something
   to look at; --level holds a semáforo level mark instead of an icon (its
   shape and label carry the level, never the colour alone). The icon is
   decorative: the row's text names the kind of notice. */
@layer vf.molecules {
  .vf-notice-mark {
    display: inline-grid;
    place-items: center;
    flex: none;
    width: 2rem;
    height: 2rem;
    border-radius: var(--vf-radius-pill);
    background: var(--vf-color-surface-sunken);
    color: var(--vf-color-text-secondary);
  }

  .vf-notice-mark--brand {
    background: var(--vf-color-brand-subtle);
    color: var(--vf-color-brand);
  }

  .vf-notice-mark--warn,
  .vf-notice-mark--level {
    background: var(--vf-color-warning-surface);
    color: var(--vf-color-level-alert-ink);
  }

  .vf-notice-mark .vf-level-mark {
    width: 1.125rem;
    height: 1.125rem;
  }
}

/* Day group: the items of one day under a small heading («Hoy · lunes 19 de
   octubre»), as a notices list grouped by day. The heading sits just above
   its content (a flush card with a row list); the space between days
   belongs to the parent stack. */
@layer vf.molecules {
  .vf-day-group {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xs);
    min-width: 0;
  }

  .vf-day-group__title {
    margin: 0;
    padding: 0 var(--vf-space-xs);
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    font-weight: var(--vf-font-weight-semibold);
  }
}

/* Media thumb: a small cropped image (or an icon placeholder) that leads a
   table row, and the full-width 3:1 banner image. */
@layer vf.molecules {
  .vf-media-thumb {
    display: block;
    flex: none;
    object-fit: cover;
    border-radius: var(--vf-radius-sm);
    background: var(--vf-color-surface-sunken);
  }

  .vf-media-thumb--sm { width: 4rem; height: 3rem; }

  .vf-media-thumb--placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .vf-media-thumb--banner {
    width: 100%;
    height: auto;
    aspect-ratio: 3 / 1;
    border-radius: var(--vf-radius-md);
  }
}

/* App post: one post as the patient app shows it (Comunidad tab), inside a
   phone preview. Author, text, at most one image and the like/share row. */
@layer vf.molecules {
  .vf-app-post {
    display: grid;
    gap: var(--vf-space-sm);
    padding: var(--vf-space-md);
    border-radius: 0.75rem;
    background: var(--vf-color-surface);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    overflow-wrap: anywhere;
  }

  .vf-app-post__author {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
  }

  .vf-app-post__image {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: var(--vf-radius-sm);
  }

  .vf-app-post__acts {
    display: flex;
    gap: var(--vf-space-lg);
    color: var(--vf-color-text-secondary);
  }

  .vf-app-post__act {
    display: inline-flex;
    align-items: center;
    gap: var(--vf-space-xxs);
  }
}

/* Week strip: seven days Monday to Sunday, a check on the days with something done
   and today highlighted (the patient's activity plan). */
@layer vf.molecules {
  .vf-week {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: var(--vf-space-xs);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .vf-week__day {
    display: grid;
    justify-items: center;
    gap: var(--vf-space-xxs);
    padding: var(--vf-space-xs) 0;
    border-radius: var(--vf-radius-md);
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-week__dot {
    display: grid;
    place-items: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 50%;
    box-shadow: inset 0 0 0 0.125rem var(--vf-color-border-default);
    color: var(--vf-color-surface);
  }

  .vf-week__day--done .vf-week__dot {
    background: var(--vf-color-level-normal);
    box-shadow: none;
  }

  .vf-week__day--today {
    background: var(--vf-color-surface-quiet);
    color: var(--vf-color-text-primary);
    font-weight: var(--vf-font-weight-semibold);
  }
}

/* Doses of a day (molecules/dose-list): one row per scheduled dose with its
   time as the lead, the medication and amount, a status tag and the actions
   that apply to it. On a phone the status drops under the text and the
   actions take their own full-width row with 2.75rem touch targets. */
@layer vf.molecules {
  .vf-dose-list {
    display: grid;
    gap: 0;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .vf-dose {
    display: grid;
    grid-template-columns: 5.5rem minmax(0, 1fr) auto;
    grid-template-areas:
      "time text status"
      ". actions actions";
    gap: var(--vf-space-xs) var(--vf-space-md);
    align-items: start;
    padding: var(--vf-space-md) var(--vf-space-lg);
    border-top: 0.0625rem solid var(--vf-color-border-subtle);
  }

  .vf-dose:first-child { border-top: 0; }

  .vf-dose--due,
  .vf-dose--late { background: var(--vf-color-surface-quiet); }

  .vf-dose__time {
    grid-area: time;
    font-weight: var(--vf-font-weight-semibold);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }

  .vf-dose__text {
    grid-area: text;
    display: grid;
    gap: 0;
    min-width: 0;
    overflow-wrap: anywhere;
  }

  .vf-dose__drug { font-weight: var(--vf-font-weight-medium); }

  .vf-dose__amount,
  .vf-dose__note {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-dose__status { grid-area: status; }

  .vf-dose__actions {
    grid-area: actions;
    display: flex;
    flex-wrap: wrap;
    gap: var(--vf-space-sm);
  }

  .vf-dose__actions form { display: contents; }

  .vf-dose--taken .vf-dose__drug,
  .vf-dose--missed .vf-dose__drug,
  .vf-dose--not-taken .vf-dose__drug { color: var(--vf-color-text-secondary); }

  @media (max-width: 40rem) {
    .vf-dose {
      grid-template-columns: 4.75rem minmax(0, 1fr);
      grid-template-areas:
        "time text"
        ". status"
        "actions actions";
      padding: var(--vf-space-md);
    }

    .vf-dose__actions .vf-button { min-height: 2.75rem; flex: 1 1 auto; }
  }
}

/* Portal sidebar: blue column with the brand, grouped navigation and a footer.
   The current item has aria-current="page"; focus ring turns white on blue.
   A foot item may be a form's submit button (vf-sidebar__item--button).
   When the menu is taller than the window only the navigation scrolls, with
   a thin light scrollbar, so the brand and the footer (Salir) stay in sight. */
@layer vf.organisms {
  .vf-sidebar {
    position: sticky;
    top: 0;
    align-self: start;
    height: 100vh;
    overflow-x: hidden;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-lg);
    padding: var(--vf-space-lg) var(--vf-space-md);
    background: var(--vf-color-brand);
    color: var(--vf-color-on-brand-muted);
    z-index: var(--vf-z-shell);
  }

  .vf-sidebar :focus-visible {
    outline: 0.125rem solid #FFFFFF;
    outline-offset: 0.125rem;
  }

  .vf-sidebar__brand {
    display: flex;
    align-items: center;
    gap: var(--vf-space-md);
    min-height: 2.5rem;
    padding: var(--vf-space-xs);
    border-radius: var(--vf-radius-pill);
  }

  .vf-sidebar__logo {
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--vf-radius-pill);
    background: #FFFFFF;
    flex: none;
  }

  .vf-sidebar__logo svg { width: 1.375rem; height: 1.375rem; }

  .vf-sidebar__word {
    display: flex;
    flex-direction: column;
    min-width: 0;
  }

  .vf-sidebar__name {
    font-family: var(--vf-font-family-display);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-section);
    line-height: 1.5rem;
    color: #FFFFFF;
  }

  .vf-sidebar__portal {
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-sidebar__nav {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxs);
    flex: 0 1 auto;
    min-height: 0;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* room for the focus ring, which overflow would clip */
    margin: calc(-1 * var(--vf-space-xs));
    padding: var(--vf-space-xs);
  }

  /* Thin light scrollbar without arrow buttons. Chromium ignores every
     ::-webkit-scrollbar rule once scrollbar-width/-color are set (and then
     draws arrows on Windows), so the standard properties are only for the
     browsers without ::-webkit-scrollbar (Firefox). */
  @supports not selector(::-webkit-scrollbar) {
    .vf-sidebar,
    .vf-sidebar__nav {
      scrollbar-width: thin;
      scrollbar-color: rgba(255, 255, 255, 0.35) transparent;
    }
  }

  .vf-sidebar::-webkit-scrollbar,
  .vf-sidebar__nav::-webkit-scrollbar {
    width: 0.375rem;
    height: 0.375rem;
  }

  .vf-sidebar::-webkit-scrollbar-button,
  .vf-sidebar__nav::-webkit-scrollbar-button {
    display: none;
    width: 0;
    height: 0;
  }

  .vf-sidebar::-webkit-scrollbar-track,
  .vf-sidebar__nav::-webkit-scrollbar-track,
  .vf-sidebar::-webkit-scrollbar-corner,
  .vf-sidebar__nav::-webkit-scrollbar-corner { background: transparent; }

  .vf-sidebar::-webkit-scrollbar-thumb,
  .vf-sidebar__nav::-webkit-scrollbar-thumb {
    border-radius: var(--vf-radius-pill);
    background: rgba(255, 255, 255, 0.35);
  }

  .vf-sidebar::-webkit-scrollbar-thumb:hover,
  .vf-sidebar__nav::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.55); }

  .vf-sidebar__group {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxs);
  }

  .vf-sidebar__label {
    padding: var(--vf-space-md) var(--vf-space-md) var(--vf-space-xs);
    font-size: var(--vf-font-size-caption);
    line-height: var(--vf-line-height-caption);
    font-weight: var(--vf-font-weight-semibold);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    opacity: 0.9;
  }

  .vf-sidebar__item {
    --vf-icon-tint: rgba(255, 255, 255, 0.22);
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--vf-space-md);
    min-height: var(--vf-size-nav-item);
    padding: 0 var(--vf-space-md);
    border-radius: var(--vf-radius-pill);
    color: var(--vf-color-on-brand-muted);
    font-weight: var(--vf-font-weight-medium);
  }

  /* a foot item that submits a form (Cerrar sesión: POST with its token) */
  .vf-sidebar__form { display: flex; flex-direction: column; }

  .vf-sidebar__item--button {
    width: 100%;
    border: 0;
    background: transparent;
    font: inherit;
    text-align: start;
    cursor: pointer;
  }

  .vf-sidebar__item:hover {
    background: rgba(255, 255, 255, 0.1);
    color: #FFFFFF;
  }

  .vf-sidebar__item[aria-current="page"] {
    --vf-icon-tint: var(--vf-color-brand-subtle-pressed);
    --vf-icon-color: var(--vf-color-brand);
    background: #FFFFFF;
    color: var(--vf-color-brand-pressed);
    font-weight: var(--vf-font-weight-semibold);
  }

  .vf-sidebar__text {
    flex: 1;
    min-width: 0;
    padding: var(--vf-space-xs) 0;
    line-height: 1.125rem;
    overflow-wrap: anywhere;
  }

  .vf-sidebar__item .vf-count { box-shadow: 0 0 0 0.125rem var(--vf-color-brand); }
  .vf-sidebar__item[aria-current="page"] .vf-count { box-shadow: none; }

  .vf-sidebar__foot {
    margin-top: auto;
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxs);
  }
}

/* Top bar: breadcrumbs on the left, the global patient search, status
   badge, actions (bell) and the user. When space runs out the search
   shrinks first (down to 12rem); the crumbs keep at least 10rem and only
   the last crumb truncates, with an ellipsis. At phone width (40rem) only
   the current crumb is shown and the search collapses to a 2.5rem icon
   field; while it has focus it spreads over the whole bar (same 3.5rem
   height, so sticky offsets keep working) and Enter still submits it. */
@layer vf.organisms {
  .vf-topbar {
    position: sticky;
    top: 0;
    z-index: var(--vf-z-shell);
    display: flex;
    align-items: center;
    gap: var(--vf-space-lg);
    height: var(--vf-size-topbar);
    padding: 0 var(--vf-space-xxl);
    background: rgba(239, 240, 249, 0.92);
    backdrop-filter: saturate(1.4) blur(0.5rem);
    border-bottom: 1px solid var(--vf-color-border-subtle);
  }

  .vf-topbar__crumbs {
    flex: 1 1 auto;
    min-width: 10rem;
    overflow: hidden;
  }

  .vf-topbar__crumb-list {
    display: flex;
    align-items: center;
    gap: var(--vf-space-xs);
    color: var(--vf-color-text-secondary);
    min-width: 0;
    font-size: var(--vf-font-size-small);
    white-space: nowrap;
  }

  .vf-topbar__crumb {
    display: inline-flex;
    align-items: center;
    gap: var(--vf-space-xs);
    flex: none;
  }

  .vf-topbar__crumb:last-child {
    flex: 0 1 auto;
    min-width: 0;
  }

  .vf-topbar__crumb .vf-icon { flex: none; }

  .vf-topbar__crumb a {
    color: var(--vf-color-brand-pressed);
    font-weight: var(--vf-font-weight-medium);
  }

  .vf-topbar__crumb a:hover { text-decoration: underline; }

  .vf-topbar__crumb [aria-current="page"] {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .vf-topbar__search {
    flex: 0 10 26rem; /* shrinks ten times faster than the crumbs */
    min-width: 12rem;
    margin-left: auto;
  }

  .vf-topbar__badge { flex: none; }

  .vf-topbar__actions {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
    flex: none;
  }

  .vf-topbar__user {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
    min-height: 2.5rem;
    padding: 0 var(--vf-space-sm) 0 var(--vf-space-xs);
    border-radius: var(--vf-radius-pill);
    flex: none;
  }

  .vf-topbar__user-name {
    max-width: 14rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: var(--vf-font-weight-medium);
  }

  @media (max-width: 80rem) {
    .vf-topbar__search { flex-basis: 22rem; }
  }

  @media (max-width: 64rem) {
    .vf-topbar { padding: 0 var(--vf-space-lg); gap: var(--vf-space-md); }
    .vf-topbar__user-name { display: none; }
  }

  @media (max-width: 40rem) {
    .vf-topbar__crumbs { min-width: 0; }
    .vf-topbar__crumb:not(:last-child),
    .vf-topbar__crumb > .vf-icon { display: none; }

    .vf-topbar__search {
      flex: none;
      width: var(--vf-size-control-md);
      min-width: 0;
    }

    .vf-topbar__search .vf-input {
      padding-right: 0;
      cursor: pointer;
    }

    .vf-topbar__search .vf-input::placeholder { color: transparent; }

    .vf-topbar__search:focus-within {
      position: absolute;
      inset: 0;
      z-index: 2;
      display: flex;
      align-items: center;
      width: auto;
      margin-left: 0;
      padding: 0 var(--vf-space-lg);
      background: var(--vf-color-background); /* hides the bell badge behind it */
    }

    .vf-topbar__search:focus-within .vf-search-box { flex: 1 1 auto; }

    .vf-topbar__search:focus-within .vf-input {
      padding-right: var(--vf-space-md);
      cursor: text;
    }

    .vf-topbar__search:focus-within .vf-input::placeholder { color: var(--vf-color-text-muted); }
  }
}

/* Card: borderless surface with the rest shadow. --flush removes the padding
   so rows (vf-card__row) run edge to edge. --sunken is a tinted panel for
   secondary groups and only reads as such INSIDE a white surface (a card,
   the hero, a drawer or a dialog): on the page background it looks grey
   and flat. --hero is the main card of a screen (open alert); its context
   panels are --sunken cards inside it. __tools is a strip of controls along
   the edge of a --flush card (filters over a list, --bottom for the strip
   under it). */
@layer vf.organisms {
  .vf-card {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-md);
    min-width: 0;
    padding: var(--vf-space-lg);
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-surface);
    box-shadow: var(--vf-shadow-rest);
  }

  .vf-card--hero { padding: var(--vf-space-xl); }
  .vf-card--hero > .vf-card__body { gap: var(--vf-space-md); }

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

  .vf-card--sunken {
    background: var(--vf-color-background);
    box-shadow: inset 0 0 0 1px var(--vf-color-border-subtle);
  }

  .vf-card__head {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
    min-height: 2rem;
  }

  /* --wrap-head (opt-in): a long title and a large aside (a level badge, a
     link) wrap to two lines instead of overflowing on a phone */
  .vf-card--wrap-head > .vf-card__head { flex-wrap: wrap; }

  .vf-card--flush > .vf-card__head {
    padding: var(--vf-space-md) var(--vf-space-lg);
    border-bottom: 1px solid var(--vf-color-border-subtle);
  }

  .vf-card__title {
    font-family: var(--vf-font-family-display);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-card);
    line-height: var(--vf-line-height-card);
  }

  .vf-card__aside {
    margin-left: auto;
    display: flex;
    gap: var(--vf-space-sm);
    align-items: center;
  }

  .vf-card__body {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-md);
    min-width: 0;
  }

  .vf-card__foot {
    display: flex;
    gap: var(--vf-space-sm);
    align-items: center;
    padding-top: var(--vf-space-md);
    border-top: 1px solid var(--vf-color-border-subtle);
  }

  .vf-card--flush > .vf-card__foot { padding: var(--vf-space-md) var(--vf-space-lg); }

  .vf-card__tools {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-sm) var(--vf-space-md);
    min-width: 0;
    padding: var(--vf-space-md) var(--vf-space-lg);
    border-bottom: 1px solid var(--vf-color-border-subtle);
  }

  .vf-card__tools--slim {
    justify-content: flex-end;
    padding-top: var(--vf-space-xs);
    padding-bottom: var(--vf-space-xs);
  }

  .vf-card__tools--bottom {
    border-bottom: 0;
    border-top: 1px solid var(--vf-color-border-subtle);
  }

  /* a group of actions inside a card, on a sunken strip (alert actions) */
  .vf-card__toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-sm);
    padding: var(--vf-space-md);
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-background);
  }

  /* rows inside a card (lists of treatments, alerts...) */
  .vf-card__rows { display: flex; flex-direction: column; }
  .vf-card__rows > * + * { border-top: 1px solid var(--vf-color-border-subtle); }

  .vf-card__row {
    display: flex;
    align-items: flex-start;
    gap: var(--vf-space-md);
    min-height: var(--vf-size-row);
    padding: var(--vf-space-md) var(--vf-space-lg);
  }

  .vf-card__row-text {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxs);
  }

  .vf-card__row-title { font-weight: var(--vf-font-weight-semibold); }

  .vf-card__row-meta {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-card__row-actions {
    display: flex;
    gap: var(--vf-space-xs);
    flex: none;
    flex-wrap: wrap;
    justify-content: flex-end;
  }

  .vf-card__row.is-new { background: linear-gradient(90deg, var(--vf-color-brand-subtle), var(--vf-color-surface) 60%); }

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

  .vf-metric__label {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
  }
}

/* Row list: a list of links, one row each (alerts, patients to review).
   Each row is a single <a> (lead, text, aside) plus an optional action
   outside the link, so the action is never a control nested in a link.
   --pending marks rows waiting for the doctor (red bar + bold title),
   --quiet rows already seen, --unread a notice not read yet (brand bar,
   tinted row, bold title; the item's sr_prefix says it to screen readers);
   the open row carries aria-current. Rows end
   with a chevron (__chevron) unless the item opts out. --center centres
   lead and aside vertically (rows whose aside is a single line). --wrap
   moves the aside under the text below 40rem (badge and time stacked);
   __col--wide / --end are aside columns of fixed width that line up from
   row to row on wide screens; --meta-wrap lets the meta wrap on a phone
   (all of it stays readable). Guard: the text never shrinks under 7rem; when the aside does
   not fit next to it, the aside goes to the next line instead of the text
   collapsing to one letter per line. */
@layer vf.organisms {
  .vf-row-list {
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .vf-row-list__item {
    position: relative;
    display: flex;
    align-items: stretch;
    min-width: 0;
  }

  .vf-row-list__item + .vf-row-list__item { border-top: 1px solid var(--vf-color-border-subtle); }

  .vf-row-list__link {
    display: flex;
    flex-wrap: wrap; /* guard: see the text's min-width */
    align-items: flex-start;
    gap: var(--vf-space-md);
    flex: 1 1 auto;
    min-width: 0;
    min-height: var(--vf-size-row);
    padding: var(--vf-space-sm) var(--vf-space-lg);
    color: inherit;
    text-decoration: none;
  }

  .vf-row-list--center .vf-row-list__link { align-items: center; }

  .vf-row-list__link:hover { background: var(--vf-color-surface-hover); }
  .vf-row-list__link:hover .vf-row-list__title { text-decoration: underline; }

  .vf-row-list__link:focus-visible {
    outline-offset: -0.125rem;
    border-radius: var(--vf-radius-xs);
  }

  .vf-row-list__lead {
    display: flex;
    align-items: center;
    flex: none;
    min-height: var(--vf-line-height-body);
  }

  .vf-row-list__lead .vf-level-mark { width: 1.25rem; height: 1.25rem; }

  .vf-row-list__chevron {
    display: flex;
    align-items: center;
    flex: none;
    min-height: var(--vf-line-height-body);
    color: var(--vf-color-text-muted);
  }

  .vf-row-list__chevron .vf-icon { width: 1.125rem; height: 1.125rem; }

  .vf-row-list__text {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxs);
    flex: 1 1 0;
    min-width: min(7rem, 100%);
  }

  .vf-row-list__title {
    font-weight: var(--vf-font-weight-medium);
    overflow-wrap: anywhere;
  }

  /* one line: a long name or disease ends in an ellipsis (full text in title) */
  .vf-row-list__meta {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .vf-row-list__tags {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-xs) var(--vf-space-sm);
    margin-top: var(--vf-space-xs);
  }

  .vf-row-list__aside {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
    flex: none;
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
  }

  .vf-row-list__action {
    display: flex;
    align-items: center;
    flex: none;
    padding-right: var(--vf-space-md);
  }

  .vf-row-list__col {
    display: flex;
    align-items: center;
    gap: var(--vf-space-xs);
    flex: none;
    min-width: 0;
  }

  /* fixed widths that fit the longest content (a level badge alone, "Sin
     datos"; "Última: 26 sept." with its clock), so badges and times line up
     and the name keeps the room */
  .vf-row-list__col--wide { flex: 0 0 7rem; }
  .vf-row-list__col--end { flex: 0 0 8.25rem; justify-content: flex-end; }

  @media (max-width: 80rem) {
    .vf-row-list__col--wide { flex: none; }
  }

  @media (max-width: 64rem) {
    .vf-row-list__col--end { flex: none; }
  }

  @media (max-width: 40rem) {
    .vf-row-list--wrap .vf-row-list__link { flex-wrap: wrap; row-gap: var(--vf-space-xs); }
    /* the text takes the rest of the first line; its meta stays one line with "…" */
    .vf-row-list--wrap .vf-row-list__text { flex: 1 1 0; min-width: 0; }
    .vf-row-list--wrap .vf-row-list__meta { max-width: 100%; }
    .vf-row-list--wrap .vf-row-list__aside {
      order: 1; /* after the chevron: a line of its own under the text */
      flex: 1 1 100%;
      flex-direction: column; /* badge, then time: always stacked */
      align-items: flex-start;
      gap: var(--vf-space-xs);
      min-width: 0;
      /* under the text, past the lead (a sm avatar by default) */
      padding-left: calc(var(--vf-row-list-lead-size, 2rem) + var(--vf-space-md));
    }
    /* columns shrink and a long badge ("Sin datos · Sin configurar") wraps */
    .vf-row-list--wrap .vf-row-list__col { flex: 0 1 auto; min-width: 0; max-width: 100%; }
    .vf-row-list--wrap .vf-row-list__col .vf-level-badge { flex-wrap: wrap; row-gap: 0; white-space: normal; max-width: 100%; }
    /* a badge value goes under the level, without a dangling "·" */
    .vf-row-list--wrap .vf-row-list__col .vf-level-badge__sep { display: none; }
    .vf-row-list--wrap .vf-row-list__col .vf-level-badge__value { flex-basis: 100%; padding-left: 1.375rem; white-space: nowrap; }
    /* --meta-wrap: the whole meta wraps (an alert's reading and its time) */
    .vf-row-list--meta-wrap .vf-row-list__meta { white-space: normal; overflow: visible; overflow-wrap: anywhere; }
  }

  /* on the narrowest phones the aside starts under the lead: more room */
  @media (max-width: 24rem) {
    .vf-row-list--wrap .vf-row-list__aside { padding-left: 0; }
    /* the diseases may take two lines, never cut with a "…" mid-line */
    .vf-row-list--wrap .vf-row-list__meta {
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
      white-space: normal;
      /* between words; a word longer than the line breaks instead of being
         clipped (no reliance on hyphenation) */
      overflow-wrap: anywhere;
      word-break: normal;
      text-overflow: clip; /* the clamp adds its own "…" at the end of line 2 */
    }
  }

  .vf-row-list__item--pending .vf-row-list__link { box-shadow: inset 0.25rem 0 0 var(--vf-color-danger); }
  .vf-row-list__item--pending .vf-row-list__title { font-weight: var(--vf-font-weight-semibold); }

  .vf-row-list__item--unread { background: var(--vf-color-brand-subtle); }
  .vf-row-list__item--unread .vf-row-list__link { box-shadow: inset 0.25rem 0 0 var(--vf-color-brand); }
  .vf-row-list__item--unread .vf-row-list__title { font-weight: var(--vf-font-weight-semibold); }

  .vf-row-list__item--quiet { background: var(--vf-color-surface-quiet); }
  .vf-row-list__item--quiet .vf-row-list__title { color: var(--vf-color-text-secondary); }

  .vf-row-list__link[aria-current="true"] {
    background: var(--vf-color-brand-subtle);
    box-shadow: inset 0.25rem 0 0 var(--vf-color-brand);
  }
}

/* Data table: real <table> with <caption>, column headers with scope and
   aria-sort, numeric columns right aligned. Scrolls horizontally inside its
   own wrapper, never the page. */
@layer vf.organisms {
  .vf-data-table {
    position: relative;
    display: flex;
    flex-direction: column;
    min-width: 0;
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-surface);
    box-shadow: var(--vf-shadow-rest);
    overflow: hidden;
  }

  /* while a remote region reloads the table (remote-region.js) */
  [aria-busy="true"] > .vf-data-table { opacity: 0.6; transition: opacity var(--vf-duration-fast) var(--vf-easing-standard); }

  .vf-data-table__scroll {
    position: relative;
    overflow-x: auto;
  }

  .vf-data-table__table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
  }

  .vf-data-table__caption {
    padding: var(--vf-space-md) var(--vf-space-lg);
    text-align: left;
    font-family: var(--vf-font-family-display);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-card);
    line-height: var(--vf-line-height-card);
    border-bottom: 1px solid var(--vf-color-border-subtle);
  }

  .vf-data-table__th {
    height: 2.5rem;
    padding: var(--vf-size-cell-padding);
    text-align: left;
    font-size: var(--vf-font-size-small);
    line-height: 1rem;
    font-weight: var(--vf-font-weight-medium);
    color: var(--vf-color-text-secondary);
    background: var(--vf-color-surface);
    border-bottom: 1px solid var(--vf-color-border-subtle);
    white-space: nowrap;
  }

  .vf-data-table__th[aria-sort="ascending"],
  .vf-data-table__th[aria-sort="descending"] {
    color: var(--vf-color-brand-pressed);
    font-weight: var(--vf-font-weight-semibold);
  }

  .vf-data-table__sort {
    display: inline-flex;
    align-items: center;
    gap: var(--vf-space-xs);
    min-height: 1.75rem;
    margin: 0 calc(-1 * var(--vf-space-xs));
    padding: 0 var(--vf-space-xs);
    border-radius: var(--vf-radius-xs);
    color: inherit;
    font-weight: inherit;
    text-decoration: none;
  }

  .vf-data-table__sort:hover {
    background: var(--vf-color-surface-hover);
    color: var(--vf-color-text-primary);
  }

  .vf-data-table__td {
    height: var(--vf-size-row);
    padding: var(--vf-size-cell-padding);
    border-bottom: 1px solid var(--vf-color-border-subtle);
    vertical-align: middle;
  }

  .vf-data-table__td--row-header {
    text-align: left;
    font-weight: var(--vf-font-weight-medium);
  }

  .vf-data-table__th--num,
  .vf-data-table__td--num {
    text-align: right;
    font-variant-numeric: tabular-nums;
  }

  .vf-data-table__td--actions {
    width: 1%;
    white-space: nowrap;
    text-align: right;
  }

  .vf-data-table__table tbody tr:last-child .vf-data-table__td { border-bottom: 0; }
  .vf-data-table__table tbody tr:hover .vf-data-table__td { background: var(--vf-color-surface-hover); }

  .vf-data-table--compact .vf-data-table__td { height: var(--vf-size-row-compact); }

  .vf-data-table__cell-main {
    display: flex;
    align-items: center;
    gap: var(--vf-space-md);
    min-width: 0;
  }

  .vf-data-table__td--state { padding: var(--vf-space-xxxl) var(--vf-space-lg); }

  .vf-data-table__table tbody tr:hover .vf-data-table__td--state { background: none; }

  /* cell anatomy of a person row: avatar + name (link) + facts under it */
  .vf-data-table__cell-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
  }

  .vf-data-table__cell-title {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
    min-width: 0;
  }

  .vf-data-table__cell-link {
    color: inherit;
    font-weight: var(--vf-font-weight-medium);
    white-space: nowrap;
    text-decoration: none;
  }

  .vf-data-table__cell-link:hover {
    color: var(--vf-color-brand-pressed);
    text-decoration: underline;
  }

  .vf-data-table__cell-meta {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    font-weight: var(--vf-font-weight-regular);
    white-space: nowrap;
  }

  .vf-data-table__tags {
    display: flex;
    flex-wrap: wrap;
    gap: var(--vf-space-xs);
    max-width: 22rem;
  }

  /* a column of tags takes a fixed share of the table: several long
     disease names wrap instead of widening it and pushing the rest right */
  .vf-data-table__th--tags { width: 20%; }

  /* "last measurement" cell: relative time, in warning ink when stale */
  .vf-data-table__ago {
    display: inline-flex;
    align-items: center;
    gap: var(--vf-space-xs);
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    white-space: nowrap;
  }

  .vf-data-table__ago--stale {
    color: var(--vf-color-warning);
    font-weight: var(--vf-font-weight-medium);
  }

  .vf-data-table__none { color: var(--vf-color-text-muted); }

  .vf-data-table__row-actions {
    display: inline-flex;
    align-items: center;
    gap: var(--vf-space-xs);
  }

  .vf-data-table__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--vf-space-md);
    min-height: 3rem;
    padding: var(--vf-space-sm) var(--vf-space-lg);
    border-top: 1px solid var(--vf-color-border-subtle);
  }

  @media (max-width: 64rem) {
    .vf-data-table__hide-md { display: none; }
  }

  @media (max-width: 85rem) {
    .vf-data-table__hide-lg { display: none; }
  }
}

/* Drawer (side panel). Markup ships hidden; js/drawer.js opens it, locks the
   page scroll, traps Tab, closes on Esc and returns focus to the opener. */
@layer vf.organisms {
  .vf-drawer {
    position: fixed;
    inset: 0;
    z-index: var(--vf-z-overlay);
    display: flex;
  }

  .vf-drawer__scrim {
    position: absolute;
    inset: 0;
    background: var(--vf-color-scrim);
  }

  .vf-drawer__panel {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(var(--vf-size-drawer), calc(100vw - 3rem));
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--vf-color-background);
    border-radius: var(--vf-radius-overlay) 0 0 var(--vf-radius-overlay);
    box-shadow: var(--vf-shadow-modal);
  }

  .vf-drawer--wide .vf-drawer__panel { width: min(var(--vf-size-drawer-wide), calc(100vw - 3rem)); }
  .vf-drawer__panel:focus { outline: none; }

  .vf-drawer.is-opening .vf-drawer__scrim { animation: vf-fade var(--vf-duration-fast) var(--vf-easing-enter); }
  .vf-drawer.is-opening .vf-drawer__panel { animation: vf-slide-in var(--vf-duration-base) var(--vf-easing-enter); }

  .vf-drawer__head {
    display: flex;
    align-items: flex-start;
    gap: var(--vf-space-md);
    padding: var(--vf-space-lg) var(--vf-space-lg) var(--vf-space-md) var(--vf-space-xxl);
    background: var(--vf-color-surface);
    border-bottom: 1px solid var(--vf-color-border-subtle);
  }

  .vf-drawer__titles {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxs);
  }

  .vf-drawer__title {
    font-family: var(--vf-font-family-display);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-section);
    line-height: var(--vf-line-height-section);
  }

  .vf-drawer__subtitle { color: var(--vf-color-text-secondary); }

  .vf-drawer__sub {
    padding: var(--vf-space-sm) var(--vf-space-xxl);
    background: var(--vf-color-surface);
    border-bottom: 1px solid var(--vf-color-border-subtle);
  }

  .vf-drawer__body {
    flex: 1;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-gutter: stable;
    padding: var(--vf-space-xxl);
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-lg);
  }

  .vf-drawer__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--vf-space-md);
    padding: var(--vf-space-md) var(--vf-space-xxl);
    background: var(--vf-color-surface);
    border-top: 1px solid var(--vf-color-border-subtle);
  }

  .vf-drawer__foot .vf-button-row { margin-left: auto; }

  .vf-drawer__foot-start,
  .vf-drawer__foot-end {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-sm);
  }

  .vf-drawer__foot-start:empty { display: none; }
  .vf-drawer__foot-end { margin-left: auto; justify-content: flex-end; }

  /* Form drawer (prop form): a white panel holding form sections, no cards.
     Head and foot stay put while the body scrolls. The body's right padding
     gives back the reserved scrollbar gutter, so fields end on the same line
     as the footer's primary button. */
  .vf-drawer--form .vf-drawer__panel { background: var(--vf-color-surface); }

  .vf-drawer--form .vf-drawer__head,
  .vf-drawer--form .vf-drawer__sub,
  .vf-drawer--form .vf-drawer__foot { flex: none; }

  .vf-drawer--form .vf-drawer__body {
    min-height: 0;
    gap: var(--vf-space-xl);
    padding-right: calc(var(--vf-space-xxl) - 0.375rem);
  }

  @keyframes vf-fade { from { opacity: 0; } }
  @keyframes vf-slide-in { from { transform: translateX(2.5rem); opacity: 0; } }

  @supports not selector(::-webkit-scrollbar) {
    .vf-drawer__body {
      scrollbar-width: thin;
      scrollbar-color: var(--vf-color-border-handle) transparent;
    }

    .vf-drawer--form .vf-drawer__body { padding-right: calc(var(--vf-space-xxl) - 0.5rem); }
  }

  .vf-drawer__body::-webkit-scrollbar { width: 0.375rem; }
  .vf-drawer__body::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
  .vf-drawer__body::-webkit-scrollbar-track { background: transparent; }
  .vf-drawer__body::-webkit-scrollbar-thumb { background: var(--vf-color-border-handle); border-radius: 999px; }
}

/* Dialog (modal). Same guarantees as the drawer: focus trap, Esc, focus
   return, scroll lock. --danger marks destructive confirmations. */
@layer vf.organisms {
  .vf-dialog {
    position: fixed;
    inset: 0;
    z-index: var(--vf-z-overlay);
  }

  .vf-dialog__scrim {
    position: absolute;
    inset: 0;
    background: var(--vf-color-scrim);
  }

  .vf-dialog__wrap {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    padding: var(--vf-space-lg);
    pointer-events: none;
  }

  .vf-dialog__panel {
    pointer-events: auto;
    width: min(var(--vf-size-dialog), 100%);
    max-height: calc(100vh - 2rem);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    background: var(--vf-color-surface);
    border-radius: var(--vf-radius-overlay);
    box-shadow: var(--vf-shadow-modal);
  }

  .vf-dialog__panel:focus { outline: none; }

  .vf-dialog.is-opening .vf-dialog__scrim { animation: vf-fade var(--vf-duration-fast) var(--vf-easing-enter); }
  .vf-dialog.is-opening .vf-dialog__panel { animation: vf-pop var(--vf-duration-fast) var(--vf-easing-enter); }

  .vf-dialog--wide .vf-dialog__panel { width: min(46rem, 100%); }

  .vf-dialog--danger .vf-dialog__panel { box-shadow: inset 0 0.25rem 0 var(--vf-color-danger), var(--vf-shadow-modal); }

  .vf-dialog__head {
    flex: none;
    display: flex;
    align-items: flex-start;
    gap: var(--vf-space-md);
    padding: var(--vf-space-xxl) var(--vf-space-xxl) var(--vf-space-sm);
  }

  .vf-dialog__title {
    flex: 1;
    min-width: 0;
    font-family: var(--vf-font-family-display);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-section);
    line-height: var(--vf-line-height-section);
  }

  .vf-dialog__titles {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxs);
  }

  .vf-dialog__titles .vf-dialog__title { flex: none; }

  .vf-dialog__subtitle {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  /* A modal taller than the window scrolls its body; head and foot stay in
     view. The gutter is always reserved, so the content doesn't jump when the
     scrollbar appears, and the right padding gives it back so the fields end
     on the same line as the footer's buttons. */
  .vf-dialog__body {
    flex: 1 1 auto;
    min-height: 0;
    min-width: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-gutter: stable;
    overflow-wrap: anywhere;
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-lg);
    padding: var(--vf-space-sm) calc(var(--vf-space-xxl) - 0.375rem) var(--vf-space-lg) var(--vf-space-xxl);
  }

  @supports not selector(::-webkit-scrollbar) {
    .vf-dialog__body {
      scrollbar-width: thin;
      scrollbar-color: var(--vf-color-border-handle) transparent;
      padding-right: calc(var(--vf-space-xxl) - 0.5rem);
    }
  }

  .vf-dialog__body::-webkit-scrollbar { width: 0.375rem; }
  .vf-dialog__body::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
  .vf-dialog__body::-webkit-scrollbar-track { background: transparent; }
  .vf-dialog__body::-webkit-scrollbar-thumb { background: var(--vf-color-border-handle); border-radius: var(--vf-radius-pill); }

  .vf-dialog__foot {
    flex: none;
    display: flex;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: var(--vf-space-sm);
    padding: var(--vf-space-sm) var(--vf-space-xxl) var(--vf-space-xxl);
  }

  @keyframes vf-pop { from { transform: scale(0.96); opacity: 0; } }
}

/* Toasts: one polite live region at the bottom centre, above overlays. */
@layer vf.organisms {
  .vf-toast-region {
    position: fixed;
    left: 50%;
    bottom: var(--vf-space-xxl);
    transform: translateX(-50%);
    z-index: var(--vf-z-toast);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--vf-space-sm);
    max-width: calc(100vw - 2rem);
    pointer-events: none;
  }

  .vf-toast {
    --vf-icon-tint: rgba(139, 195, 74, 0.35);
    --vf-icon-color: #A5D66F;
    pointer-events: auto;
    display: flex;
    align-items: center;
    gap: var(--vf-space-md);
    max-width: 36rem;
    padding: var(--vf-space-md) var(--vf-space-md) var(--vf-space-md) var(--vf-space-lg);
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-text-primary);
    color: var(--vf-color-text-inverse);
    box-shadow: var(--vf-shadow-modal);
    animation: vf-toast-in var(--vf-duration-base) var(--vf-easing-enter);
  }

  .vf-toast--bad { --vf-icon-color: #FF8A80; --vf-icon-tint: rgba(255, 138, 128, 0.3); }
  .vf-toast__message { flex: 1; min-width: 0; }

  .vf-toast__action {
    min-height: 2rem;
    padding: 0 var(--vf-space-sm);
    border-radius: var(--vf-radius-pill);
    color: #BFD3FF;
    font-weight: var(--vf-font-weight-semibold);
  }

  .vf-toast__action:hover { background: rgba(255, 255, 255, 0.12); }

  .vf-toast .vf-icon-button { --vf-icon-color: #FFFFFF; color: #FFFFFF; }
  .vf-toast .vf-icon-button:hover { background: rgba(255, 255, 255, 0.12); }
  .vf-toast :focus-visible { outline-color: #FFFFFF; }

  /* small screens: the region spans the width between 1rem gutters (centred
     with left: 50% it could only shrink to half the screen) */
  @media (max-width: 40rem) {
    .vf-toast-region {
      left: var(--vf-space-lg);
      right: var(--vf-space-lg);
      bottom: var(--vf-space-lg);
      transform: none;
      max-width: none;
      align-items: stretch;
    }

    .vf-toast { max-width: none; }
  }

  @keyframes vf-toast-in { from { transform: translateY(0.75rem); opacity: 0; } }

  @media (prefers-reduced-motion: reduce) {
    .vf-toast { animation: none; }
  }
}

/* Line chart over the level bands. Points use the level shapes and a data
   table always comes with it. The server draws the chart (.vf-chart__fallback)
   with the proportions of the ECharts chart that js/chart.js mounts on top
   (when assets/vendor/echarts is loaded) inside the same .vf-chart__plot:
   the plot box has the canvas height with or without scripting, the plot
   area (.vf-chart__area) keeps the grid margins of chart.js (left 2.5rem,
   right 6rem beside the band labels or 1rem, top 1.25rem, bottom 2rem or
   5rem under a zoom slider; mini 2.5rem / 1rem / 0.5rem / 0.5rem or 1.75rem
   with an axis), the geometry is an SVG stretched over that area with
   non-scaling strokes, and labels and point shapes are HTML in rem placed in
   percent, so text never scales. Below 30rem of chart width (a container
   query, as chart.js switches to its compact layout) the band labels and
   extremes go and the axes use the compact ticks. ECharts hides the fallback
   once it is drawn; if it fails, the fallback stays as the chart. */
@layer vf.organisms {
  .vf-chart {
    position: relative;
    width: 100%;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-sm);
  }

  .vf-chart__svg {
    display: block;
    width: 100%;
    height: auto;
    max-height: 16rem;
    overflow: visible;
  }

  .vf-chart__svg[hidden] { display: none; }

  .vf-chart__plot { position: relative; min-width: 0; height: 20rem; }
  .vf-chart--mini .vf-chart__plot { height: 5.5rem; }
  .vf-chart--mini.vf-chart--axis .vf-chart__plot { height: 7rem; }

  .vf-chart__fallback {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    container-type: inline-size;
  }

  .vf-chart__fallback[hidden] { display: none; }

  .vf-chart__area {
    position: absolute;
    top: 1.25rem;
    right: 1rem;
    bottom: 2rem;
    left: 2.5rem;
  }

  .vf-chart__fallback--bands .vf-chart__area { right: 6rem; }
  .vf-chart__fallback--zoom .vf-chart__area { bottom: 5rem; }
  .vf-chart--mini .vf-chart__area { top: 0.5rem; right: 1rem; bottom: 0.5rem; left: 2.5rem; }
  .vf-chart--mini.vf-chart--axis .vf-chart__area { bottom: 1.75rem; }

  .vf-chart__area > .vf-chart__svg {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    max-height: none;
    overflow: hidden;
  }

  .vf-chart__split {
    fill: none;
    stroke: var(--vf-color-border-subtle);
    stroke-width: 1;
    stroke-dasharray: 3 4;
    vector-effect: non-scaling-stroke;
  }

  .vf-chart__fill-start { stop-color: var(--vf-color-brand); stop-opacity: 0.12; }
  .vf-chart__fill-end { stop-color: var(--vf-color-brand); stop-opacity: 0; }

  .vf-chart__average {
    fill: none;
    stroke: var(--vf-color-text-muted);
    stroke-width: 1.25;
    stroke-dasharray: 8 5;
    vector-effect: non-scaling-stroke;
  }

  .vf-chart__tick {
    position: absolute;
    font-family: var(--vf-font-family-body);
    font-size: var(--vf-font-size-caption);
    line-height: 1;
    color: var(--vf-color-text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    pointer-events: none;
  }

  .vf-chart__tick--y { right: 100%; margin-right: var(--vf-space-md); transform: translateY(-50%); }
  .vf-chart__tick--x { top: 100%; margin-top: var(--vf-space-md); transform: translateX(-50%); }
  .vf-chart__tick--compact,
  .vf-chart__split--compact { display: none; }

  .vf-chart__band-label {
    position: absolute;
    left: 100%;
    margin-left: var(--vf-space-md);
    transform: translateY(-50%);
    font-family: var(--vf-font-family-body);
    font-size: var(--vf-font-size-caption);
    line-height: 1;
    font-weight: var(--vf-font-weight-medium);
    white-space: nowrap;
    pointer-events: none;
  }

  .vf-chart__band-label--normal { color: var(--vf-color-level-normal-ink); }
  .vf-chart__band-label--attention { color: var(--vf-color-level-attention-ink); }
  .vf-chart__band-label--alert { color: var(--vf-color-level-alert-ink); }
  .vf-chart__band-label--critical { color: var(--vf-color-level-critical-ink); }

  .vf-chart__mark {
    position: absolute;
    width: 0.4375rem;
    height: 0.4375rem;
    overflow: visible;
    transform: translate(-50%, -50%);
  }

  .vf-chart__mark path { stroke: var(--vf-color-surface); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
  .vf-chart__mark--normal path { fill: var(--vf-color-level-normal); stroke-width: 1; }
  .vf-chart__mark--attention { width: 0.875rem; height: 0.875rem; }
  .vf-chart__mark--attention path { fill: var(--vf-color-level-attention); }
  .vf-chart__mark--alert { width: 0.9375rem; height: 0.9375rem; }
  .vf-chart__mark--alert path { fill: var(--vf-color-level-alert); }
  .vf-chart__mark--critical { width: 0.8125rem; height: 0.8125rem; }
  .vf-chart__mark--critical path { fill: var(--vf-color-level-critical); }
  .vf-chart__mark--neutral { width: 0.5625rem; height: 0.5625rem; }
  .vf-chart__mark--neutral path { fill: var(--vf-color-level-no-data); stroke-width: 1; }
  .vf-chart--mini .vf-chart__mark--normal { width: 0.3125rem; height: 0.3125rem; }
  .vf-chart--mini .vf-chart__mark--attention { width: 0.65625rem; height: 0.65625rem; }
  .vf-chart--mini .vf-chart__mark--alert { width: 0.703125rem; height: 0.703125rem; }
  .vf-chart--mini .vf-chart__mark--critical { width: 0.609375rem; height: 0.609375rem; }
  .vf-chart--mini .vf-chart__line { stroke-width: 1.5; }

  .vf-chart__extreme {
    position: absolute;
    font-family: var(--vf-font-family-body);
    font-size: var(--vf-font-size-caption);
    line-height: 1;
    font-weight: var(--vf-font-weight-semibold);
    color: var(--vf-color-text-secondary);
    white-space: nowrap;
    pointer-events: none;
    text-shadow: 0 0 0.125rem var(--vf-color-surface), 0 0 0.125rem var(--vf-color-surface), 0 0 0.125rem var(--vf-color-surface);
  }

  .vf-chart__extreme--max { transform: translate(-50%, calc(-100% - 1rem)); }
  .vf-chart__extreme--min { transform: translate(-50%, 0.75rem); }
  .vf-chart__extreme--min-raised { transform: translate(-50%, calc(-100% - 1rem)); }

  .vf-chart__empty {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    margin: 0;
    padding: var(--vf-space-sm) var(--vf-space-md);
    border: 0.0625rem solid var(--vf-color-border-subtle);
    border-radius: var(--vf-radius-sm);
    background: var(--vf-color-surface);
    font-size: var(--vf-font-size-small);
    color: var(--vf-color-text-secondary);
    white-space: nowrap;
  }

  @container (max-width: 29.99rem) {
    .vf-chart:not(.vf-chart--mini) .vf-chart__area { left: 2rem; }
    .vf-chart__fallback--bands .vf-chart__area { right: 1rem; }
    .vf-chart__band-label,
    .vf-chart__extreme,
    .vf-chart__tick--wide,
    .vf-chart__split--wide { display: none; }
    .vf-chart__tick--compact,
    .vf-chart__split--compact { display: block; }
  }

  .vf-chart__band--normal { fill: var(--vf-color-level-normal-band); }
  .vf-chart__band--attention { fill: var(--vf-color-level-attention-band); }
  .vf-chart__band--alert { fill: var(--vf-color-level-alert-band); }
  .vf-chart__band--critical { fill: var(--vf-color-level-critical-band); }
  .vf-chart__area .vf-chart__band--attention,
  .vf-chart__area .vf-chart__band--alert,
  .vf-chart__area .vf-chart__band--critical { opacity: 0.5; }

  .vf-chart__line {
    fill: none;
    stroke: var(--vf-color-brand);
    stroke-width: 2;
    stroke-linejoin: round;
    stroke-linecap: round;
  }

  .vf-chart__area .vf-chart__line { vector-effect: non-scaling-stroke; }

  .vf-chart__threshold {
    fill: none;
    stroke: var(--vf-color-level-alert);
    stroke-width: 1;
    opacity: 0.55;
  }

  .vf-chart__area .vf-chart__threshold { vector-effect: non-scaling-stroke; }
  .vf-chart__threshold--normal { stroke: var(--vf-color-level-normal); }
  .vf-chart__threshold--attention { stroke: var(--vf-color-level-attention); }
  .vf-chart__threshold--critical { stroke: var(--vf-color-level-critical); }

  .vf-chart__table-toggle > summary {
    cursor: pointer;
    color: var(--vf-color-text-link);
    font-weight: var(--vf-font-weight-medium);
    min-height: 1.5rem;
  }

  .vf-chart__canvas {
    width: 100%;
    height: 20rem;
    border-radius: var(--vf-radius-sm);
  }

  .vf-chart__canvas svg text { font-variant-numeric: tabular-nums; }
  .vf-chart__canvas:focus-visible { outline: 0.125rem solid var(--vf-color-border-focus); outline-offset: 0.25rem; }
  .vf-chart__canvas--mini { height: 5.5rem; }
  .vf-chart--axis .vf-chart__canvas--mini { height: 7rem; }
  .vf-chart__canvas--spark { height: 3.5rem; }
  .vf-chart__canvas--mini:focus-visible,
  .vf-chart__canvas--spark:focus-visible { outline-offset: 0.125rem; }

  .vf-chart--spark { gap: 0; }
  .vf-chart--spark .vf-chart__svg { height: 3rem; max-height: 3rem; overflow: hidden; }
  .vf-chart--spark .vf-chart__line { stroke-width: 1.75; vector-effect: non-scaling-stroke; }
  .vf-chart--spark .vf-chart__threshold { vector-effect: non-scaling-stroke; }

  .vf-chart__spark-end { position: absolute; display: flex; transform: translate(-50%, -50%); pointer-events: none; }
  .vf-chart[data-vf-chart-ready="true"] .vf-chart__spark-end { display: none; }

  .vf-chart__spark-cell { display: block; width: 8rem; max-width: 100%; }
  .vf-chart__spark-cell .vf-chart__canvas--spark,
  .vf-chart__spark-cell .vf-chart__svg { height: 2.5rem; max-height: 2.5rem; }

  .vf-chart__legend {
    display: none;
    flex-wrap: wrap;
    gap: var(--vf-space-xs) var(--vf-space-md);
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--vf-font-size-caption);
    line-height: var(--vf-line-height-caption);
    color: var(--vf-color-text-secondary);
  }

  .vf-chart__legend li { display: inline-flex; align-items: center; gap: var(--vf-space-xs); }
  .vf-chart--compact .vf-chart__legend { display: flex; }

  .vf-chart-card {
    background: var(--vf-color-surface);
    border-radius: var(--vf-radius-card);
    box-shadow: var(--vf-shadow-rest);
    padding: var(--vf-space-xl) var(--vf-space-xl) var(--vf-space-lg);
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-lg);
    min-width: 0;
  }

  .vf-chart-card__head {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: flex-start;
    gap: var(--vf-space-lg) var(--vf-space-xxl);
  }

  .vf-chart-card__titles { display: flex; flex-direction: column; gap: var(--vf-space-xxs); min-width: 0; }

  .vf-chart-card__title {
    margin: 0;
    font-family: var(--vf-font-family-display);
    font-size: var(--vf-font-size-card);
    line-height: var(--vf-line-height-card);
    font-weight: var(--vf-font-weight-semibold);
    color: var(--vf-color-text-primary);
  }

  .vf-chart-card__subtitle {
    margin: 0;
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
    color: var(--vf-color-text-secondary);
    font-variant-numeric: tabular-nums;
  }

  .vf-chart-card__latest { display: flex; flex-direction: column; align-items: flex-end; gap: var(--vf-space-xxs); text-align: right; }
  .vf-chart-card__eyebrow { font-size: var(--vf-font-size-caption); line-height: var(--vf-line-height-caption); color: var(--vf-color-text-secondary); font-variant-numeric: tabular-nums; }
  .vf-chart-card__reading { display: flex; align-items: baseline; gap: var(--vf-space-xs); }

  .vf-chart-card__value {
    font-family: var(--vf-font-family-display);
    font-size: var(--vf-font-size-metric);
    line-height: var(--vf-line-height-metric);
    font-weight: var(--vf-font-weight-semibold);
    color: var(--vf-color-text-primary);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
  }

  .vf-chart-card__unit { font-size: var(--vf-font-size-small); color: var(--vf-color-text-secondary); }
  .vf-chart-card__status { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: var(--vf-space-xs) var(--vf-space-sm); }
  .vf-chart-card__delta { font-size: var(--vf-font-size-caption); color: var(--vf-color-text-secondary); font-variant-numeric: tabular-nums; }

  .vf-chart-card__bar {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: var(--vf-space-sm) var(--vf-space-lg);
    padding-top: var(--vf-space-md);
    border-top: 0.0625rem solid var(--vf-color-border-subtle);
  }

  .vf-chart-card__stats { display: flex; flex-wrap: wrap; gap: var(--vf-space-xs) var(--vf-space-sm); margin: 0; padding: 0; list-style: none; }

  .vf-chart-card__stat {
    display: inline-flex;
    align-items: baseline;
    gap: var(--vf-space-xs);
    padding: var(--vf-space-xxs) var(--vf-space-sm);
    border-radius: var(--vf-radius-pill);
    background: var(--vf-color-surface-hover);
    border: 0.0625rem solid var(--vf-color-border-subtle);
    font-size: var(--vf-font-size-caption);
    line-height: var(--vf-line-height-body);
    color: var(--vf-color-text-secondary);
  }

  .vf-chart-card__stat strong { color: var(--vf-color-text-primary); font-weight: var(--vf-font-weight-semibold); font-size: var(--vf-font-size-small); font-variant-numeric: tabular-nums; }
  .vf-chart-card__avg-swatch { display: inline-block; width: var(--vf-size-icon-sm); border-top: 0.125rem dashed var(--vf-color-text-muted); align-self: center; }

  .vf-chart-card__compare {
    display: inline-flex;
    align-items: center;
    gap: var(--vf-space-sm);
    font-size: var(--vf-font-size-small);
    color: var(--vf-color-text-secondary);
    cursor: pointer;
    min-height: var(--vf-size-icon-lg);
  }

  .vf-chart-card__compare[hidden] { display: none; }
  .vf-chart-card__compare.is-pending { display: none; }

  @media (scripting: enabled) {
    .vf-chart-card__compare.is-pending { display: inline-flex; visibility: hidden; }
  }
  .vf-chart-card__compare input { width: 1rem; height: 1rem; accent-color: var(--vf-color-brand); margin: 0; }
  .vf-chart-card__swatch { width: 1.25rem; border-top: 0.125rem dashed var(--vf-color-border-default); }

  .vf-chart-card__foot { margin: 0; font-size: var(--vf-font-size-caption); line-height: var(--vf-line-height-caption); color: var(--vf-color-text-secondary); }

  .vf-chart-tooltip { padding: 0 !important; }

  .vf-chart-tip { display: flex; flex-direction: column; gap: var(--vf-space-xs); padding: var(--vf-space-md) var(--vf-space-md) var(--vf-space-sm); min-width: 11rem; }
  .vf-chart-tip__date { font-size: var(--vf-font-size-caption); line-height: var(--vf-line-height-caption); color: var(--vf-color-text-secondary); font-variant-numeric: tabular-nums; }
  .vf-chart-tip__reading { display: flex; align-items: baseline; gap: var(--vf-space-xs); }
  .vf-chart-tip__value { font-family: var(--vf-font-family-display); font-size: var(--vf-font-size-title); line-height: var(--vf-line-height-title); font-weight: var(--vf-font-weight-semibold); color: var(--vf-color-text-primary); font-variant-numeric: tabular-nums; }
  .vf-chart-tip__unit { font-size: var(--vf-font-size-small); color: var(--vf-color-text-secondary); }
  .vf-chart-tip__delta,
  .vf-chart-tip__compare { font-size: var(--vf-font-size-caption); line-height: var(--vf-line-height-caption); color: var(--vf-color-text-secondary); font-variant-numeric: tabular-nums; }
  .vf-chart-tip__compare { display: flex; align-items: center; gap: var(--vf-space-xs); padding-top: var(--vf-space-xs); border-top: 0.0625rem solid var(--vf-color-border-subtle); }
  .vf-chart-tip__swatch { width: 0.875rem; border-top: 0.125rem dashed var(--vf-color-border-default); }
  .vf-chart-tip__level--compare { padding-left: var(--vf-space-lg); }
  .vf-chart-tip__level { display: flex; flex-wrap: wrap; align-items: center; gap: var(--vf-space-xs) var(--vf-space-sm); }
  .vf-chart-tip__score,
  .vf-chart-tip__time,
  .vf-chart-tip__more { font-size: var(--vf-font-size-caption); line-height: var(--vf-line-height-caption); color: var(--vf-color-text-secondary); font-variant-numeric: tabular-nums; }
  .vf-chart-tip__details { display: flex; flex-direction: column; gap: var(--vf-space-xxs); margin: 0; padding: 0; list-style: none; font-size: var(--vf-font-size-small); line-height: var(--vf-line-height-small); color: var(--vf-color-text-primary); font-variant-numeric: tabular-nums; }
  .vf-chart-tip--day { min-width: 15rem; }
  .vf-chart-tip__list { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
  .vf-chart-tip__item { display: flex; flex-direction: column; gap: var(--vf-space-xxs); margin: 0 calc(-1 * var(--vf-space-sm)); padding: var(--vf-space-xs) var(--vf-space-sm); border-radius: var(--vf-radius-xs); }
  .vf-chart-tip__item + .vf-chart-tip__item { border-top: 0.0625rem solid var(--vf-color-border-subtle); }
  .vf-chart-tip__item.is-current { background: var(--vf-color-surface-hover); }
  .vf-chart-tip__row { display: flex; align-items: center; gap: var(--vf-space-sm); }
  .vf-chart-tip__time { min-width: 4.5rem; white-space: nowrap; }
  .vf-chart-tip__row-value { font-weight: var(--vf-font-weight-semibold); color: var(--vf-color-text-primary); font-variant-numeric: tabular-nums; white-space: nowrap; }
  .vf-chart-tip__row-level { margin-left: auto; }
  .vf-chart-tip__item .vf-chart-tip__details { padding-left: calc(4.5rem + var(--vf-space-sm)); }

  .vf-chart-multiples { display: flex; flex-direction: column; }

  .vf-chart-multiple {
    display: grid;
    grid-template-columns: minmax(9rem, 13rem) minmax(0, 1fr);
    gap: var(--vf-space-lg);
    align-items: center;
    padding: var(--vf-space-sm) 0;
    border-top: 0.0625rem solid var(--vf-color-border-subtle);
  }

  .vf-chart-multiple:first-child { border-top: 0; }
  .vf-chart-multiple__head { display: flex; flex-direction: column; gap: var(--vf-space-xxs); min-width: 0; }
  .vf-chart-multiple__name { margin: 0; font-size: var(--vf-font-size-small); font-weight: var(--vf-font-weight-medium); color: var(--vf-color-text-primary); }
  .vf-chart-multiple__reading { display: flex; flex-wrap: wrap; align-items: center; gap: var(--vf-space-xs) var(--vf-space-sm); font-variant-numeric: tabular-nums; }
  .vf-chart-multiple__value { font-family: var(--vf-font-family-display); font-size: var(--vf-font-size-section); line-height: var(--vf-line-height-section); font-weight: var(--vf-font-weight-semibold); color: var(--vf-color-text-primary); }
  .vf-chart-multiple__date { font-size: var(--vf-font-size-caption); color: var(--vf-color-text-secondary); }
  .vf-chart-multiple .vf-chart { gap: 0; }

  .vf-chart-state {
    min-height: 16rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--vf-space-md);
    text-align: center;
    padding: var(--vf-space-xl);
    border-radius: var(--vf-radius-sm);
    background: var(--vf-color-surface-hover);
  }

  .vf-chart-state__art { width: 7.5rem; height: auto; }
  .vf-chart-state__grid { fill: none; stroke: var(--vf-color-border-handle); stroke-dasharray: 2 3; }
  .vf-chart-state__line { fill: none; stroke: var(--vf-color-brand-edge); stroke-width: 2; stroke-linecap: round; stroke-dasharray: 4 5; }
  .vf-chart-state__line--bad { stroke: var(--vf-color-danger-border); stroke-dasharray: none; }
  .vf-chart-state__dot { fill: var(--vf-color-surface); stroke: var(--vf-color-brand-edge); stroke-width: 2; }
  .vf-chart-state__title { margin: 0; font-family: var(--vf-font-family-display); font-size: var(--vf-font-size-card); line-height: var(--vf-line-height-card); font-weight: var(--vf-font-weight-semibold); color: var(--vf-color-text-primary); }
  .vf-chart-state__body { margin: 0; max-width: 28rem; font-size: var(--vf-font-size-small); line-height: var(--vf-line-height-small); color: var(--vf-color-text-secondary); }

  @media (max-width: 36rem) {
    .vf-chart-card { padding: var(--vf-space-lg) var(--vf-space-md) var(--vf-space-md); }
    .vf-chart__plot { height: 17.5rem; }
    .vf-chart--mini .vf-chart__plot { height: 5rem; }
    .vf-chart--mini.vf-chart--axis .vf-chart__plot { height: 6.5rem; }
    .vf-chart__canvas { height: 17.5rem; }
    .vf-chart__canvas--mini { height: 5rem; }
    .vf-chart--axis .vf-chart__canvas--mini { height: 6.5rem; }
    .vf-chart__canvas--spark { height: 3rem; }
    .vf-chart-card__latest { align-items: flex-start; text-align: left; }
    .vf-chart-card__status { justify-content: flex-start; }
    .vf-chart .vf-chart__legend { display: flex; }
    .vf-chart-multiple { grid-template-columns: minmax(0, 1fr); gap: var(--vf-space-xxs); }
  }
}

/* Page header: the only <h1> of the screen, subtitle and page actions. */
@layer vf.organisms {
  .vf-page-header {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--vf-space-lg);
  }

  .vf-page-header__titles {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xs);
    min-width: 0;
  }

  .vf-page-header__eyebrow {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    font-weight: var(--vf-font-weight-medium);
  }

  .vf-page-header__title {
    font-family: var(--vf-font-family-display);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-title);
    line-height: var(--vf-line-height-title);
    letter-spacing: -0.01em;
  }

  .vf-page-header__subtitle { color: var(--vf-color-text-secondary); }

  .vf-page-header__actions {
    display: flex;
    gap: var(--vf-space-sm);
    flex-wrap: wrap;
    align-items: center;
  }

  /* Actions that are only a region with nothing to show yet (an export
     that appears with results) take no room in the wrapped header. */
  .vf-page-header__actions:has(> [data-vf-remote]:empty):not(:has(> :not([data-vf-remote]:empty))) {
    display: none;
  }
}

/* Sticky clinical summary of a patient (the prototype's "psum"): identity
   and the record's actions, then one row of clinical facts (allergies,
   active medication, levels) that stays visible while the record scrolls. */
@layer vf.organisms {
  .vf-clinical-summary {
    position: sticky;
    top: var(--vf-size-topbar);
    z-index: var(--vf-z-sticky);
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-sm);
    padding: var(--vf-space-md) var(--vf-space-lg);
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-surface);
    box-shadow: var(--vf-shadow-rest);
  }

  .vf-clinical-summary__top {
    display: flex;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: var(--vf-space-md);
  }

  .vf-clinical-summary__identity {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xs);
    min-width: 0;
    flex: 1 1 14rem;
  }

  .vf-clinical-summary__heading {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-md);
  }

  .vf-clinical-summary__name {
    font-family: var(--vf-font-family-display);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-title);
    line-height: var(--vf-line-height-title);
    letter-spacing: -0.01em;
  }

  .vf-clinical-summary__facts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--vf-space-xs) var(--vf-space-lg);
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-clinical-summary__fact {
    display: inline-flex;
    align-items: center;
    gap: var(--vf-space-xs);
  }

  .vf-clinical-summary__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-sm);
    margin-left: auto;
  }

  .vf-clinical-summary__clinical {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-sm) var(--vf-space-lg);
  }

  .vf-clinical-summary__item {
    display: inline-flex;
    align-items: center;
    gap: var(--vf-space-sm);
    min-width: 0;
    max-width: 100%;
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-clinical-summary__item--medications { max-width: min(28rem, 100%); }

  .vf-clinical-summary__label {
    color: var(--vf-color-text-secondary);
    font-weight: var(--vf-font-weight-medium);
    white-space: nowrap;
  }

  .vf-clinical-summary__ellipsis {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .vf-clinical-summary__ago {
    color: var(--vf-color-text-muted);
    white-space: nowrap;
  }

  /* on a phone the summary scrolls with the record (sticky it took half the
     screen), the actions take their own row and long labels wrap */
  @media (max-width: 48rem) {
    .vf-clinical-summary { position: static; }
    .vf-clinical-summary__actions { width: 100%; margin-left: 0; }
    .vf-clinical-summary__actions > * { flex: 1 1 auto; }
    .vf-clinical-summary__item { flex-wrap: wrap; }
    .vf-clinical-summary__label { white-space: normal; }
  }

  @media (max-height: 56rem) {
    .vf-clinical-summary { padding: var(--vf-space-sm) var(--vf-space-lg); gap: var(--vf-space-xs); }
    .vf-clinical-summary .vf-avatar--lg { width: 2.5rem; height: 2.5rem; font-size: var(--vf-font-size-body); }
  }
}

/* Action menu: the "more actions" button of a row and its list of links
   (the prototype's row menu). A native <details>: without JavaScript the
   list opens under the button; js/menu.js pins it to the viewport (so a
   scrolling table never clips it), flips it above the button when there is
   no room below, closes it on Esc, outside clicks and scroll, and moves
   with the arrow keys. */
@layer vf.organisms {
  .vf-action-menu {
    position: relative;
    display: inline-flex;
  }

  .vf-action-menu__button {
    display: inline-grid;
    place-items: center;
    width: var(--vf-size-control-md);
    height: var(--vf-size-control-md);
    border-radius: var(--vf-radius-pill);
    color: var(--vf-color-text-secondary);
    list-style: none;
    cursor: pointer;
  }

  .vf-action-menu__button::-webkit-details-marker { display: none; }

  /* with button_label the summary is a tertiary button with icon and text */
  .vf-action-menu__text-button { list-style: none; cursor: pointer; }
  .vf-action-menu__text-button::-webkit-details-marker { display: none; }

  .vf-action-menu__button:hover,
  .vf-action-menu[open] > .vf-action-menu__button {
    background: var(--vf-color-surface-pressed);
    color: var(--vf-color-text-primary);
  }

  .vf-action-menu__list {
    position: absolute;
    top: calc(100% + 0.375rem);
    right: 0;
    z-index: var(--vf-z-popover);
    display: flex;
    flex-direction: column;
    min-width: 15rem;
    padding: var(--vf-space-xs);
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-surface);
    box-shadow: var(--vf-shadow-modal);
    text-align: left;
  }

  .vf-action-menu__item {
    display: flex;
    align-items: center;
    gap: var(--vf-space-md);
    width: 100%;
    min-height: var(--vf-size-control-md);
    padding: 0 var(--vf-space-md);
    border-radius: var(--vf-radius-input);
    color: var(--vf-color-text-primary);
    font-size: var(--vf-font-size-body);
    line-height: var(--vf-line-height-body);
    font-weight: var(--vf-font-weight-regular);
    white-space: nowrap;
    text-decoration: none;
  }

  .vf-action-menu__item:hover,
  .vf-action-menu__item:focus-visible { background: var(--vf-color-surface-hover); }

  .vf-action-menu__item:focus-visible { outline-offset: -0.125rem; }

  .vf-action-menu__item > .vf-icon { width: 1.125rem; height: 1.125rem; }

  .vf-action-menu__item--danger {
    --vf-icon-tint: var(--vf-color-danger-tint);
    color: var(--vf-color-danger-text);
  }
}

/* Entry list: rows that are not links (a degree, a job, a document type),
   each with an icon, a title, a meta line, extras (tags, file links) and its
   own actions. row-list is for rows that are a single link. */
@layer vf.organisms {
  .vf-entry-list {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .vf-entry-list__item {
    display: flex;
    align-items: flex-start;
    gap: var(--vf-space-md);
    padding: var(--vf-space-md) var(--vf-space-lg);
    border-top: 1px solid var(--vf-color-border-subtle);
  }

  .vf-entry-list__item:first-child { border-top: 0; }

  .vf-entry-list__icon {
    flex: none;
    padding-top: var(--vf-space-xxs);
  }

  .vf-entry-list__text {
    flex: 1 1 auto;
    display: grid;
    gap: var(--vf-space-xxs);
    min-width: 0;
  }

  .vf-entry-list__title {
    margin: 0;
    font-weight: var(--vf-font-weight-semibold);
    overflow-wrap: anywhere;
  }

  .vf-entry-list__meta {
    margin: 0;
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    overflow-wrap: anywhere;
  }

  .vf-entry-list__extra {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-xs) var(--vf-space-md);
    min-width: 0;
    padding-top: var(--vf-space-xxs);
    font-size: var(--vf-font-size-small);
  }

  .vf-entry-list__extra .vf-link { overflow-wrap: anywhere; }

  .vf-entry-list__actions {
    flex: none;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--vf-space-xs);
  }

  @media (max-width: 30rem) {
    .vf-entry-list__item { flex-wrap: wrap; }
    .vf-entry-list__actions { flex-basis: 100%; justify-content: flex-start; }
  }
}

/* Post (Muro): author and audience, title, text with links, images, a
   YouTube video as a link (never an iframe), attachments, a toggle "Me gusta"
   (aria-pressed) and the comments with their reply field. */
@layer vf.organisms {
  .vf-post {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-md);
    min-width: 0;
    padding: var(--vf-space-xl);
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-surface);
    box-shadow: var(--vf-shadow-rest);
    scroll-margin-top: 5rem;
  }

  .vf-post--new { box-shadow: 0 0 0 0.125rem var(--vf-color-brand-edge), var(--vf-shadow-rest); }

  .vf-post__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-sm) var(--vf-space-md);
  }

  .vf-post__byline {
    display: flex;
    flex: 1 1 10rem;
    flex-direction: column;
    min-width: 0;
  }

  .vf-post__author {
    font-weight: var(--vf-font-weight-semibold);
    overflow-wrap: anywhere;
  }

  .vf-post__meta {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-post__tools {
    display: flex;
    align-items: center;
    gap: var(--vf-space-xs);
    margin-left: auto;
  }

  .vf-post__title {
    margin: 0;
    font-size: var(--vf-font-size-card);
    line-height: var(--vf-line-height-card);
    font-weight: var(--vf-font-weight-semibold);
    overflow-wrap: anywhere;
  }

  .vf-post__untitled {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    font-weight: var(--vf-font-weight-regular);
  }

  .vf-post__text {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-sm);
    font-size: var(--vf-font-size-read);
    line-height: var(--vf-line-height-read);
    overflow-wrap: anywhere;
  }

  .vf-post__gallery {
    display: grid;
    gap: var(--vf-space-sm);
  }

  .vf-post__gallery--many { grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); }

  .vf-post__image {
    display: block;
    width: 100%;
    height: auto;
    max-height: 28rem;
    object-fit: contain;
    border-radius: var(--vf-radius-input);
    background: var(--vf-color-surface-sunken);
  }

  .vf-post__gallery--many .vf-post__image {
    aspect-ratio: 1 / 1;
    object-fit: cover;
  }

  .vf-post__video,
  .vf-post__file {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-md);
    min-width: 0;
    padding: var(--vf-space-md);
    border: 1px solid var(--vf-color-border-subtle);
    border-radius: var(--vf-radius-input);
    color: var(--vf-color-text-primary);
    text-decoration: none;
  }

  .vf-post__video:hover,
  .vf-post__file:hover { background: var(--vf-color-surface-hover); }

  .vf-post__video-text {
    display: flex;
    flex: 1 1 10rem;
    flex-direction: column;
    min-width: 0;
  }

  .vf-post__files {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xs);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .vf-post__file-name {
    flex: 1;
    min-width: 0;
    font-weight: var(--vf-font-weight-medium);
    overflow-wrap: anywhere;
  }

  .vf-post__acts {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--vf-space-sm);
    padding-top: var(--vf-space-sm);
    border-top: 1px solid var(--vf-color-border-subtle);
  }

  .vf-post__like[aria-pressed="true"] {
    --vf-icon-tint: var(--vf-color-danger-tint);
    color: var(--vf-color-danger-text);
    background: var(--vf-color-danger-surface);
  }

  .vf-post__comments {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-md);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .vf-post__comment {
    display: flex;
    align-items: flex-start;
    gap: var(--vf-space-sm);
  }

  .vf-post__comment-body {
    flex: 1;
    min-width: 0;
    padding: var(--vf-space-sm) var(--vf-space-md);
    border-radius: var(--vf-radius-input);
    background: var(--vf-color-surface-sunken);
    overflow-wrap: anywhere;
  }

  .vf-post__reply {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--vf-space-sm);
  }

  .vf-post__reply-field {
    flex: 1 1 12rem;
    min-width: 0;
  }
}

/* Wall post as the patient sees it (Comunidad): author, title, text, one image or a
   video link, and a like toggle with a fixed label and aria-pressed. No comments. */
@layer vf.organisms {
  .vf-wall-post { max-width: 40rem; }

  .vf-wall-post__body {
    display: grid;
    gap: var(--vf-space-md);
    overflow-wrap: anywhere;
  }

  .vf-wall-post__author {
    display: flex;
    align-items: center;
    gap: var(--vf-space-sm);
  }

  .vf-wall-post__byline { display: grid; gap: 0; }

  .vf-wall-post__name { font-weight: var(--vf-font-weight-medium); }

  .vf-wall-post__meta {
    color: var(--vf-color-text-secondary);
    font-size: var(--vf-font-size-small);
    line-height: var(--vf-line-height-small);
  }

  .vf-wall-post__title {
    margin: 0;
    font-size: var(--vf-font-size-section);
    line-height: var(--vf-line-height-section);
    font-weight: var(--vf-font-weight-semibold);
  }

  .vf-wall-post__text {
    margin: 0;
    font-size: var(--vf-font-size-read);
    line-height: var(--vf-line-height-read);
    white-space: pre-line;
  }

  .vf-wall-post__image {
    display: block;
    width: 100%;
    height: auto;
    max-height: 22rem;
    object-fit: cover;
    border-radius: var(--vf-radius-sm);
  }

  .vf-wall-post__acts { display: flex; gap: var(--vf-space-md); margin: 0; }

  .vf-wall-like {
    display: inline-flex;
    align-items: center;
    gap: var(--vf-space-xs);
    min-height: var(--vf-size-control-lg);
    padding: 0 var(--vf-space-md);
    border: 0.0625rem solid var(--vf-color-border-default);
    border-radius: var(--vf-radius-pill);
    background: var(--vf-color-surface);
    color: var(--vf-color-text-primary);
    font: inherit;
    cursor: pointer;
  }

  .vf-wall-like:hover { border-color: var(--vf-color-brand); }

  .vf-wall-like.is-liked {
    border-color: var(--vf-color-brand);
    background: var(--vf-color-brand-subtle);
    color: var(--vf-color-brand-pressed);
    font-weight: var(--vf-font-weight-medium);
  }

  .vf-wall-like__count { font-variant-numeric: tabular-nums; }
}

/* Promo: the institution's notices (Banners) as an accessible carousel in
   the side column: one image at a time, previous / next with aria-controls
   and "1 de N" (js/promo.js). Without JavaScript the images stack. */
@layer vf.organisms {
  .vf-promo {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-md);
    padding: var(--vf-space-xl);
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-brand);
    color: var(--vf-color-on-brand);
  }

  .vf-promo__heading {
    margin: 0;
    font-size: var(--vf-font-size-card);
    line-height: var(--vf-line-height-card);
    font-weight: var(--vf-font-weight-semibold);
  }

  .vf-promo__slides {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-sm);
  }

  .vf-promo__slide[hidden] { display: none; }

  .vf-promo__image {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--vf-radius-input);
    background: var(--vf-color-brand-motif-deep);
  }

  .vf-promo__nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--vf-space-sm);
  }

  .vf-promo__nav[hidden] { display: none; }

  .vf-promo__nav .vf-icon-button {
    --vf-icon-color: var(--vf-color-on-brand);
    color: var(--vf-color-on-brand);
  }

  .vf-promo__count { font-size: var(--vf-font-size-small); }
}

/* Moderation list: comments of a post, each with its author, text and a
   delete action on the right. Lives inside a flush card. */
@layer vf.organisms {
  .vf-moderation-list {
    display: grid;
    gap: 0;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .vf-moderation-list__item {
    display: flex;
    gap: var(--vf-space-md);
    align-items: flex-start;
    padding: var(--vf-space-md) var(--vf-space-lg);
    border-top: 0.0625rem solid var(--vf-color-border-subtle);
  }

  .vf-moderation-list__item:first-child { border-top: 0; }

  .vf-moderation-list__body {
    display: grid;
    gap: var(--vf-space-xxs);
    flex: 1 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;
  }
}

/* Banner grid: the wall banners as cards (image, state and actions); one
   column on small screens, two from 64rem and three from 100rem. An inactive
   banner (--off) dims its image. */
@layer vf.organisms {
  .vf-banner-grid {
    display: grid;
    gap: var(--vf-space-lg);
    grid-template-columns: minmax(0, 1fr);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  @media (min-width: 64rem) {
    .vf-banner-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }

  @media (min-width: 100rem) {
    .vf-banner-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  }

  .vf-banner-tile {
    display: grid;
    gap: var(--vf-space-md);
    align-content: start;
  }

  .vf-banner-tile--off .vf-media-thumb { opacity: 0.55; }
}

/* Portal layout: sidebar column + main column (topbar, then <main>).
   Breakpoints 64 / 80 / 120rem. */
@layer vf.layouts {
  /* <html> of the portal layout: the scrollbar always keeps its gutter, so a
     short page and a long one lay out at the same width (a master-detail
     list does not change size when the page starts to scroll). */
  .vf-portal-document { scrollbar-gutter: stable; }

  .vf-portal {
    display: grid;
    grid-template-columns: var(--vf-size-sidebar) minmax(0, 1fr);
    min-height: 100vh;
  }

  .vf-portal__column {
    display: flex;
    flex-direction: column;
    min-width: 0;
  }

  .vf-portal__main {
    flex: 1;
    min-width: 0;
    padding: var(--vf-space-xxl) var(--vf-space-xxl) 4rem;
  }

  .vf-portal__main:focus { outline: none; }

  .vf-portal__inner {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxl);
    max-width: var(--vf-size-content-max);
    margin: 0 auto;
  }

  .vf-skip-link {
    position: absolute;
    left: var(--vf-space-lg);
    top: -4rem;
    z-index: var(--vf-z-skip-link);
    padding: var(--vf-space-sm) var(--vf-space-lg);
    border-radius: var(--vf-radius-pill);
    background: var(--vf-color-surface);
    color: var(--vf-color-brand-pressed);
    box-shadow: var(--vf-shadow-modal);
    font-weight: var(--vf-font-weight-semibold);
  }

  .vf-skip-link:focus { top: var(--vf-space-sm); }

  @media (max-width: 64rem) {
    .vf-portal { grid-template-columns: 4.5rem minmax(0, 1fr); }
    .vf-portal .vf-sidebar { padding: var(--vf-space-lg) var(--vf-space-sm); align-items: center; }
    .vf-portal .vf-sidebar__word,
    .vf-portal .vf-sidebar__label,
    .vf-portal .vf-sidebar__text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
    .vf-portal .vf-sidebar__item { width: 2.5rem; padding: 0; justify-content: center; }
    .vf-portal .vf-sidebar__item .vf-count { position: absolute; top: -0.125rem; right: -0.25rem; }
    .vf-portal__main { padding: var(--vf-space-lg) var(--vf-space-lg) 3rem; }
  }

  /* Opt-in bottom tab bar (layout prop tabbar => true, patient portal): on a
     phone the sidebar becomes a bar fixed at the bottom with the first
     navigation group as equal tabs; the brand, the other groups and the foot
     items are hidden (the patient signs out from the profile). Placed after the 64rem rule so it wins over it.
     Wider screens keep the sidebar. */
  @media (max-width: 40rem) {
    .vf-portal--tabbar { grid-template-columns: minmax(0, 1fr); }

    .vf-portal--tabbar .vf-sidebar {
      position: fixed;
      inset: auto 0 0 0;
      height: auto;
      flex-direction: row;
      align-items: stretch;
      gap: var(--vf-space-xxs);
      padding: var(--vf-space-xxs) var(--vf-space-xs) calc(var(--vf-space-xxs) + env(safe-area-inset-bottom, 0rem));
      overflow: visible;
    }

    .vf-portal--tabbar .vf-sidebar__brand,
    .vf-portal--tabbar .vf-sidebar__nav > .vf-sidebar__group:not(:first-child),
    .vf-portal--tabbar .vf-sidebar__label { display: none; }

    .vf-portal--tabbar .vf-sidebar__nav {
      flex: 1 1 0;
      margin: 0;
      padding: 0;
      overflow: visible;
    }

    .vf-portal--tabbar .vf-sidebar__nav > .vf-sidebar__group:first-child > ul {
      display: grid;
      grid-auto-flow: column;
      grid-auto-columns: minmax(0, 1fr);
      gap: var(--vf-space-xxs);
      margin: 0;
      padding: 0;
      list-style: none;
    }

    .vf-portal--tabbar .vf-sidebar__foot { display: none; }

    .vf-portal--tabbar .vf-sidebar__item {
      flex-direction: column;
      justify-content: center;
      gap: var(--vf-space-xxs);
      width: auto;
      min-height: var(--vf-size-control-lg);
      padding: var(--vf-space-xxs) 0;
      border-radius: var(--vf-radius-md);
      font-size: var(--vf-font-size-caption);
      line-height: var(--vf-line-height-caption);
      text-align: center;
    }

    .vf-portal--tabbar .vf-sidebar__text {
      position: static;
      flex: none;
      width: auto;
      max-width: 100%;
      height: auto;
      padding: 0;
      overflow: hidden;
      clip: auto;
      white-space: nowrap;
      text-overflow: ellipsis;
    }

    .vf-portal--tabbar .vf-sidebar__item .vf-count { position: absolute; top: 0; left: calc(50% + var(--vf-space-sm)); right: auto; }
    .vf-portal--tabbar .vf-portal__main { padding: var(--vf-space-lg) var(--vf-space-lg) 6.5rem; }
    .vf-portal--tabbar .vf-topbar__user { display: none; }
    .vf-portal-document--tabbar .vf-toast-region { bottom: 5rem; }
  }

  @media (min-width: 120rem) {
    .vf-portal__main { padding: var(--vf-space-xxxl) var(--vf-space-xxxl) 4rem; }
  }
}

/* Auth layout (login, password recovery, error pages): brand panel + centred
   form card (prototype v2 "auth"). The panel holds the logo and "Vivfy" at
   the top, the headline and lead (or the tagline, when a page passes neither)
   centred in the remaining height, and the brand mark as a large translucent
   motif at the bottom right. Below 64rem the panel hides and a compact brand
   heads the card instead. */
@layer vf.layouts {
  .vf-auth {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    min-height: 100vh;
  }

  .vf-auth__side {
    position: relative;
    overflow: hidden;
    display: grid;
    grid-template-rows: auto 1fr;
    gap: var(--vf-space-xxl);
    padding: var(--vf-space-xxxl);
    background: var(--vf-color-brand);
    color: var(--vf-color-on-brand);
  }

  .vf-auth__motif {
    position: absolute;
    right: -4rem;
    bottom: -4rem;
    width: 22.5rem;
    height: 22.5rem;
    opacity: 0.22;
    pointer-events: none;
  }

  .vf-auth__motif .vf-auth__mark-v { fill: var(--vf-color-brand-motif-light); }
  .vf-auth__motif .vf-auth__mark-h { fill: var(--vf-color-brand-motif-deep); }
  .vf-auth__motif .vf-auth__mark-c { fill: var(--vf-color-brand-motif-overlap); }

  .vf-auth__brand {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--vf-space-md);
  }

  .vf-auth__logo {
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--vf-radius-pill);
    background: #FFFFFF;
    flex: none;
  }

  .vf-auth__logo-mark { width: 1.375rem; height: 1.375rem; }
  .vf-auth__logo-mark .vf-auth__mark-v { fill: var(--vf-color-brand-mark-light); }
  .vf-auth__logo-mark .vf-auth__mark-h { fill: var(--vf-color-brand-mark-mid); }
  .vf-auth__logo-mark .vf-auth__mark-c { fill: var(--vf-color-brand-mark-overlap); }

  .vf-auth__name {
    font-family: var(--vf-font-family-display);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-section);
    line-height: 1.5rem;
  }

  .vf-auth__pitch {
    position: relative;
    align-self: center;
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-md);
    max-width: 28rem;
  }

  .vf-auth__headline {
    font-family: var(--vf-font-family-display);
    font-weight: var(--vf-font-weight-semibold);
    font-size: var(--vf-font-size-display);
    line-height: var(--vf-line-height-display);
    letter-spacing: -0.01em;
  }

  .vf-auth__lead,
  .vf-auth__tagline {
    color: var(--vf-color-on-brand-muted);
    font-size: var(--vf-font-size-read);
    line-height: var(--vf-line-height-read);
  }

  .vf-auth__main {
    display: grid;
    place-items: center;
    padding: var(--vf-space-xxxl) var(--vf-space-xxl);
  }

  .vf-auth__card {
    width: min(26rem, 100%);
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xxl);
  }

  /* long forms (doctor sign-up) */
  .vf-auth__card--wide { width: min(40rem, 100%); }

  /* the compact brand heads the card only where the panel is hidden */
  .vf-auth__brand--compact { display: none; }
  .vf-auth__brand--compact .vf-auth__logo { box-shadow: inset 0 0 0 1px var(--vf-color-border-subtle); }
  .vf-auth__brand--compact .vf-auth__name { color: var(--vf-color-brand-pressed); }

  @media (max-width: 64rem) {
    .vf-auth { grid-template-columns: minmax(0, 1fr); }
    .vf-auth__side { display: none; }
    .vf-auth__main { place-items: start center; padding: var(--vf-space-xxl) var(--vf-space-lg); }
    .vf-auth__brand--compact { display: flex; }
  }
}

/* Print: drop the shell and interactive chrome, keep the content in ink on
   white. Elements marked .vf-print-hide never print. */
@layer vf.layouts {
  .vf-print {
    max-width: 48rem;
    margin: 0 auto;
    padding: var(--vf-space-xxxl);
    background: var(--vf-color-surface);
  }

  @media print {
    .vf-root { background: #FFFFFF; }

    .vf-root .vf-sidebar,
    .vf-root .vf-topbar,
    .vf-root .vf-skip-link,
    .vf-root .vf-toast-region,
    .vf-root .vf-drawer,
    .vf-root .vf-dialog,
    .vf-root .vf-print-hide {
      display: none !important;
    }

    .vf-root .vf-portal { display: block; }
    .vf-root .vf-portal__main { padding: 0; }
    .vf-root .vf-clinical-summary { position: static; box-shadow: none; }
    .vf-root .vf-card,
    .vf-root .vf-data-table { box-shadow: none; border: 1px solid #C9CEDD; break-inside: avoid; }
    .vf-root .vf-tabs__panel[hidden] { display: block !important; }
    .vf-print { padding: 0; max-width: none; }
  }
}

/* Hidden on screen, read by assistive technology. --focusable shows it again
   when it receives focus (skip links). */
@layer vf.utilities {
  .vf-visually-hidden:not(.vf-visually-hidden--focusable:focus) {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }
}

/* Layout primitives: vertical stack, horizontal cluster and grids. Gaps use
   the spacing scale (xs 0.25 / sm 0.5 / md 0.75 / lg 1 / xxl 1.5 / xxxl 2rem). */
@layer vf.utilities {
  .vf-stack { display: flex; flex-direction: column; min-width: 0; gap: var(--vf-space-lg); }
  /* a stack centred on its axis, text included (the identity card of Mi perfil) */
  .vf-stack--center { align-items: center; text-align: center; }
  .vf-cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--vf-space-sm); min-width: 0; }
  .vf-cluster--between { justify-content: space-between; }
  .vf-cluster--end { justify-content: flex-end; }
  .vf-cluster--start { align-items: flex-start; }
  .vf-cluster--nowrap { flex-wrap: nowrap; }

  .vf-gap-none { gap: 0; }
  .vf-gap-xs { gap: var(--vf-space-xs); }
  .vf-gap-sm { gap: var(--vf-space-sm); }
  .vf-gap-md { gap: var(--vf-space-md); }
  .vf-gap-lg { gap: var(--vf-space-lg); }
  .vf-gap-xxl { gap: var(--vf-space-xxl); }
  .vf-gap-xxxl { gap: var(--vf-space-xxxl); }

  .vf-grow { flex: 1 1 auto; min-width: 0; }

  /* a narrow column centred in the content area (a form alone on its page,
     such as Cambiar contraseña): as wide as a dialog */
  .vf-center-column { width: 100%; max-width: var(--vf-size-dialog); margin-inline: auto; }

  /* a form that is the whole page (Estoy en el hospital): a readable column
     that starts on the page title's left edge, never centred */
  .vf-form-column {
    width: 100%;
    max-width: 46rem;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-xl);
  }

  .vf-grid { display: grid; gap: var(--vf-space-lg); min-width: 0; }
  .vf-grid > * { min-width: 0; }
  .vf-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .vf-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .vf-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .vf-grid--auto { grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); }

  /* one column, two once each gets 24rem, never more; an odd last item takes
     the whole row so no panel is left alone at half width */
  .vf-grid--pair { grid-template-columns: repeat(auto-fit, minmax(max(min(24rem, 100%), calc((100% - var(--vf-space-lg)) / 2)), 1fr)); }
  .vf-grid--pair > :last-child:nth-child(odd):not(:first-child) { grid-column: 1 / -1; }
  .vf-grid--main-aside { grid-template-columns: minmax(0, 1fr) minmax(18rem, 22rem); align-items: start; gap: var(--vf-space-xxl); }

  /* the aside column of vf-grid--main-aside stays in view while the main
     column scrolls, under the sticky top bar; never taller than the screen:
     it scrolls inside instead (its children keep their height, never
     shrink), so its bottom is always reachable, and once it reaches its end
     the wheel goes on scrolling the page. A small inner padding, taken back
     with a negative margin, keeps focus rings and the cards' shadows inside
     the scrolling box. Back to the flow in one column. */
  .vf-sticky-aside {
    position: sticky;
    top: calc(var(--vf-size-topbar) + var(--vf-space-lg) - var(--vf-space-sm));
    align-self: start;
    max-height: calc(100vh - var(--vf-size-topbar) - 2 * var(--vf-space-lg) + 2 * var(--vf-space-sm));
    overflow-y: auto;
    scrollbar-width: thin;
    margin: calc(-1 * var(--vf-space-sm));
    padding: var(--vf-space-sm);
  }

  .vf-sticky-aside > * { flex-shrink: 0; }

  /* sticky only where it fits: on a short screen the aside flows with the
     page (no scroll inside a scroll on a normal laptop) */
  @media (max-height: 52rem) {
    .vf-sticky-aside { position: static; max-height: none; overflow: visible; margin: 0; padding: 0; }
  }

  @media (max-width: 64rem) {
    .vf-grid--2,
    .vf-grid--main-aside { grid-template-columns: minmax(0, 1fr); }
    .vf-sticky-aside { position: static; max-height: none; overflow: visible; margin: 0; padding: 0; }
    .vf-grid--3,
    .vf-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }
}

/* Master-detail: a list (__master) next to the open item (__detail). Up to
   64rem there is room for one column only: the screen shows the list, or the
   detail with its back link (__back) when the container carries
   --detail (an item is open). */
@layer vf.utilities {
  .vf-master-detail {
    display: grid;
    grid-template-columns: minmax(20rem, 0.85fr) minmax(0, 1.4fr);
    gap: var(--vf-space-lg);
    align-items: start;
    min-width: 0;
  }

  .vf-master-detail__master,
  .vf-master-detail__detail { min-width: 0; }

  .vf-master-detail__back { display: none; }

  @media (max-width: 80rem) {
    .vf-master-detail { grid-template-columns: minmax(17rem, 0.8fr) minmax(0, 1.4fr); }
  }

  @media (max-width: 64rem) {
    .vf-master-detail { grid-template-columns: minmax(0, 1fr); }
    .vf-master-detail--detail > .vf-master-detail__master { display: none; }
    .vf-master-detail:not(.vf-master-detail--detail) > .vf-master-detail__detail { display: none; }
    .vf-master-detail__back { display: inline-flex; }
  }
}

/* Action bar: the row of buttons at the end of a wizard step or a long form
   (Cancel on the left, the main action on the right). --sticky keeps it at
   the bottom of the viewport while the form scrolls; the page then keeps that
   much room at the bottom when it scrolls a field into view (focus, anchors),
   so the bar never hides the field being filled. */
@layer vf.utilities {
  .vf-action-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--vf-space-sm);
    padding-top: var(--vf-space-lg);
    border-top: 1px solid var(--vf-color-border-subtle);
  }

  .vf-action-bar--sticky {
    position: sticky;
    bottom: var(--vf-space-lg);
    z-index: 1;
    padding: var(--vf-space-lg);
    border-top: 0;
    border-radius: var(--vf-radius-card);
    background: var(--vf-color-surface);
    box-shadow: inset 0 0 0 1px var(--vf-color-border-subtle);
  }

  :root:has(.vf-action-bar--sticky) {
    scroll-padding-bottom: calc(var(--vf-size-control-md) + 4 * var(--vf-space-lg));
  }
}

/* Text lists inside cards and dialogs: the reset removes list markers, these
   bring them back where the content is a real list. Also a plain fieldset
   for groups of controls with a legend, and single-line truncation. */
@layer vf.utilities {
  .vf-list {
    display: flex;
    flex-direction: column;
    gap: var(--vf-space-sm);
    margin: 0;
    padding: 0;
  }

  .vf-list--bullets { list-style: disc; padding-left: 1.25rem; }
  .vf-list--numbered { list-style: decimal; padding-left: 1.25rem; gap: var(--vf-space-xs); }
  .vf-list--tight { gap: var(--vf-space-xs); }

  .vf-fieldset {
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
  }

  .vf-fieldset > legend {
    padding: 0;
    margin-bottom: var(--vf-space-sm);
  }

  .vf-truncate {
    overflow: hidden;
    min-width: 0;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .vf-min-0 { min-width: 0; }
}

/* Compose grid: a form (or a detail) next to its previews. From 64rem the
   preview column (__preview-stack) sits on the right and stays in view.
   vf-status-cell keeps a status tag and its date stacked to the left. */
@layer vf.utilities {
  .vf-compose-grid {
    display: grid;
    gap: var(--vf-space-xxl);
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
  }

  @media (min-width: 64rem) {
    .vf-compose-grid { grid-template-columns: minmax(0, 1fr) minmax(20rem, 28rem); }

    .vf-compose-grid > .vf-preview-stack {
      position: sticky;
      top: calc(var(--vf-size-topbar) + var(--vf-space-lg));
    }
  }

  .vf-preview-stack {
    display: grid;
    gap: var(--vf-space-xl);
    align-content: start;
    min-width: 0;
  }

  .vf-preview-stack .vf-post {
    box-shadow: inset 0 0 0 0.0625rem var(--vf-color-border-subtle);
    border-radius: var(--vf-radius-card);
  }

  .vf-status-cell { align-items: flex-start; }
}

/* Regions that reload themselves from their own page (js/remote-region.js,
   data-vf-remote="self") keep the old content until the answer arrives and
   only dim once it takes longer than 200 ms, so quick loads never flash. */
@layer vf.utilities {
  [data-vf-remote="self"] {
    transition: opacity var(--vf-duration-fast) var(--vf-easing-standard);
  }

  [data-vf-remote="self"][aria-busy="true"] {
    opacity: 0.6;
    transition-delay: 200ms;
  }

  /* A cluster holding only its no-JavaScript fallback (the filters'
     "Aplicar" in <noscript>, with no "Quitar filtros" to show) and hidden
     fields (per_page, status) takes no room, so the filter card does not
     keep an empty row; it shows again as soon as a region brings "Quitar
     filtros" into it. */
  @media (scripting: enabled) {
    .vf-cluster:has(> noscript):not(:has(> :not(noscript, input[type="hidden"]))) {
      display: none;
    }
  }
}

/* Touch targets for daily patient actions (class vf-touch on a wrapper): on
   a phone every button, icon button and link button inside is at least
   2.75rem in both directions. Wider screens keep the regular control sizes. */
@layer vf.utilities {
  @media (max-width: 40rem) {
    .vf-touch .vf-button,
    .vf-touch .vf-icon-button {
      min-height: 2.75rem;
      min-width: 2.75rem;
    }
  }
}

