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

      :root {
        --type-display: "Source Serif 4", "Iowan Old Style", Palatino, "New York", ui-serif, Georgia, serif;
        --type-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
        --type-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
        --bg-page: #ffffff; --bg-alt: #f7f5f1; --bg-card: #fdfcfa;
        --ink: #1d1d1f; --ink-soft: #3a3a3c; --ink-mute: #4d4d55;
        --rule: #e4e1da; --rule-strong: #c9c5bb;
        --link: #0a5566; --link-hover: #073f4c; --eyebrow: #684d00;
        --btn-bg: #1d1d1f; --btn-text: #ffffff; --focus-ring: #0a5566;
        --ok: #14532d; --bad: #7f1d1d;
        --code-bg: #14161c; --code-text: #f2f3f5; --code-mute: #a1a5b0;
        --shadow-sm: 0 1px 2px rgb(29 29 31 / 0.06);
        --shadow-md: 0 12px 32px -12px rgb(29 29 31 / 0.18);
        --radius-sm: 8px; --radius-md: 14px; --radius-pill: 999px;
      }
      [data-theme="dark"] {
        --bg-page: #0b0e14; --bg-alt: #131722; --bg-card: #161b26;
        --ink: #f5f5f7; --ink-soft: #d2d2d7; --ink-mute: #86868b;
        --rule: #232936; --rule-strong: #343c4e;
        --link: #40b5d0; --link-hover: #67c8de; --eyebrow: #e5b800;
        --btn-bg: #f5f5f7; --btn-text: #0b0e14; --focus-ring: #40b5d0;
        --ok: #4ade80; --bad: #f87171;
        --code-bg: #07090e; --code-text: #e6edf3; --code-mute: #a1a5b0;
      }

      * { box-sizing: border-box; margin: 0; padding: 0; }
      html { font-family: var(--type-body); font-size: 16px; line-height: 1.5; color: var(--ink); background: var(--bg-page); }
      body { min-height: 100vh; display: flex; flex-direction: column; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; }
      a { color: var(--link); }
      a:hover { color: var(--link-hover); }

      .wrap { width: 100%; max-width: 1280px; margin: 0 auto; padding: 0 1.75rem; }
      .skip-link { position: absolute; top: -100px; left: 1rem; background: var(--btn-bg); color: var(--btn-text); padding: 0.5rem 1rem; border-radius: var(--radius-sm); z-index: 2000; }
      .skip-link:focus { top: 1rem; }
      .visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

      /* ==== Navigation ==== */
      .ap-nav { position: sticky; top: 0; z-index: 1000; background: color-mix(in srgb, var(--bg-page) 92%, transparent); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); border-bottom: 1px solid var(--rule); }
      .ap-nav-wrap { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 1rem; min-height: 64px; }
      .ap-brand { justify-self: start; display: inline-flex; align-items: center; gap: 0.55rem; font-family: var(--type-display); font-size: 1.2rem; font-weight: 700; color: var(--ink); text-decoration: none; min-height: 44px; white-space: nowrap; }
      .ap-brand img { width: 26px; height: 26px; }
      .ap-menu { justify-self: center; display: flex; align-items: center; list-style: none; margin: 0; padding: 0; gap: 0.35rem; }
      .ap-menu > li { position: relative; display: inline-flex; align-items: center; }
      .ap-menu a { display: inline-flex; align-items: center; min-height: 44px; padding: 0 0.55rem; color: var(--ink-soft); text-decoration: none; font-size: 0.9rem; font-weight: 500; white-space: nowrap; border-radius: var(--radius-sm); }
      .ap-menu a:hover { color: var(--ink); background: var(--bg-alt); }
      .ap-nav-right { justify-self: end; display: inline-flex; align-items: center; gap: 0.35rem; }
      .theme-toggle, .ap-search-btn { display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem; min-width: 44px; min-height: 44px; padding: 0 0.5rem; background: transparent; border: 1px solid transparent; border-radius: 999px; color: var(--ink); cursor: pointer; font-family: inherit; }
      .ap-cta-mini { display: inline-flex; align-items: center; justify-content: center; min-height: 36px; padding: 0 0.9rem; background: var(--btn-bg); color: var(--btn-text); border-radius: var(--radius-pill); font-size: 0.85rem; font-weight: 600; text-decoration: none; }

      /* ==== Page header & Multi-Column Workbench Grid ==== */
      .page-header { padding: 3.5rem 0 2rem; border-bottom: 1px solid var(--rule); }
      .page-header h1 { font-family: var(--type-display); font-size: clamp(2.2rem, 4vw, 3.2rem); font-weight: 700; margin-bottom: 0.75rem; letter-spacing: -0.015em; }
      .deck { font-size: 1.2rem; color: var(--ink-soft); max-width: 62ch; line-height: 1.55; }
      .eyebrow { font-size: 0.8rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--eyebrow); margin-bottom: 0.8rem; }

      /* padding-block only; .wrap on the same element supplies the inline
         padding. Restating 1.75rem here happened to match, so this one was
         correct by luck rather than by construction. */
      .guide-grid { display: grid; grid-template-columns: 280px 1fr; gap: 2.5rem; padding-block: 3rem 4rem; margin: 0 auto; max-width: 1280px; align-items: start; }
      @media (max-width: 768px) { .guide-grid { grid-template-columns: 1fr; } }

      .guide-rail { display: flex; flex-direction: column; gap: 1.75rem; }
      .guide-block { background: var(--bg-alt); border: 1px solid var(--rule); border-radius: var(--radius-md); padding: 1.35rem; font-size: 0.92rem; }
      .guide-block h2 { font-family: var(--type-display); font-size: 1.15rem; font-weight: 700; margin-bottom: 0.85rem; color: var(--ink); }
      .check-list, .info-list { list-style: none; display: flex; flex-direction: column; gap: 0.75rem; color: var(--ink-soft); }
      .check-list li { display: flex; gap: 0.6rem; }
      .check-list .tick { color: var(--ok); font-weight: 800; }

      .tool-col { display: flex; flex-direction: column; gap: 2rem; }

      .demo-grid {
        display: grid;
        grid-template-columns: 1fr 1.1fr;
        gap: 1.5rem;
        align-items: start;
      }
      @media (max-width: 768px) {
        .demo-grid {
          grid-template-columns: 1fr;
        }
      }

      .demo-panel { background: var(--bg-card); border: 1px solid var(--rule); border-radius: var(--radius-md); padding: 1.75rem; box-shadow: var(--shadow-sm); height: 100%; }
      .step-head { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 1.25rem; }
      .step-num { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; background: var(--btn-bg); color: var(--btn-text); border-radius: 50%; font-size: 0.85rem; font-weight: 700; }
      .step-head h2 { font-family: var(--type-display); font-size: 1.3rem; font-weight: 700; color: var(--ink); margin: 0; }

      .dropzone { border: 2px dashed var(--rule-strong); border-radius: var(--radius-md); padding: 2.25rem 1.5rem; text-align: center; background: var(--bg-page); cursor: pointer; transition: all 0.2s ease; }
      .dropzone:hover { border-color: var(--link); background: var(--bg-alt); }
      .dropzone p { margin-bottom: 0.35rem; color: var(--ink); }
      .dropzone .hint { font-size: 0.85rem; color: var(--ink-mute); margin-bottom: 0; }

      .demo-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.25rem; align-items: center; }
      .pill-select, .pill { display: inline-flex; align-items: center; min-height: 40px; padding: 0 1rem; border-radius: var(--radius-pill); font-size: 0.88rem; font-weight: 600; cursor: pointer; transition: all 0.18s ease; font-family: inherit; }
      .pill-select { background: var(--bg-alt); border: 1px solid var(--rule-strong); color: var(--ink); }
      .pill-primary { background: var(--btn-bg); color: var(--btn-text); border: 1px solid var(--btn-bg); text-decoration: none; }
      .pill-primary:hover { opacity: 0.9; }
      .pill-ghost { background: var(--bg-alt); border: 1px solid var(--rule-strong); color: var(--ink); }
      .pill-ghost:hover { background: var(--bg-page); border-color: var(--ink-soft); }

      .editor-block { margin-top: 1.25rem; }
      .editor-label { font-size: 0.85rem; font-weight: 700; color: var(--ink); display: block; margin-bottom: 0.5rem; }
      #csv-input { width: 100%; height: 180px; font-family: var(--type-mono); font-size: 0.85rem; padding: 0.85rem; border: 1px solid var(--rule-strong); border-radius: var(--radius-sm); background: var(--bg-page); color: var(--ink); }

      .error-table-wrap { margin-top: 1rem; overflow-x: auto; border: 1px solid var(--rule); border-radius: var(--radius-sm); }
      .error-table { width: 100%; border-collapse: collapse; font-size: 0.82rem; font-family: var(--type-mono); text-align: left; }
      .error-table th { background: var(--bg-alt); padding: 0.5rem 0.6rem; border-bottom: 1px solid var(--rule-strong); color: var(--ink-mute); font-weight: 700; text-transform: uppercase; font-size: 0.72rem; }

      .xml-out { background: var(--code-bg); color: var(--code-text); padding: 1.25rem; border-radius: var(--radius-sm); font-family: var(--type-mono); font-size: 0.82rem; line-height: 1.5; height: 240px; overflow: auto; white-space: pre-wrap; word-break: break-all; margin-top: 1rem; border: 1px solid var(--rule); }
      /* --code-mute, not --ink-mute. The code surface is dark in both themes,
         but --ink-mute tracks the page background: in the light theme it is
         #4d4d55, which is 2.16:1 on #14161c — a WCAG AA failure that the
         happy-dom axe suite cannot see, because it resolves no stylesheets.
         --code-mute is 7.3:1 on the lighter code background and higher on the
         darker one. */
      .xml-placeholder { color: var(--code-mute); font-style: italic; }
      .status { font-weight: 600; font-size: 0.9rem; color: var(--ink-soft); margin-top: 0.5rem; }

      /* ssg's injected search trigger renders as: icon + "Search" + <kbd>K</kbd>,
         with aria-label="Search". Its visible text therefore includes "K" while
         its accessible name does not, which fails axe's
         label-content-name-mismatch. The workbench has no in-nav search of its
         own, so hiding the whole button would remove search from the page —
         hide only the shortcut hint, which the overlay states anyway. */
      #ssg-search-btn kbd { display: none; }

      /* These two were style attributes. The site's CSP is style-src 'self'
         'unsafe-hashes' <one hash>, so every other inline style attribute is
         blocked — the elements shipped unstyled and each one logged a CSP
         violation. */
      .error-overflow-note { font-size: 0.8rem; color: var(--ink-mute); padding: 0.4rem; }
      .xml-paste-area { width: 100%; font-family: var(--type-mono, monospace); font-size: 0.85rem; }

      /* Syntax-highlighter palette. ssg's highlighter emits these as inline
         style attributes, which the CSP blocks; fix-ssg-html rewrites them to
         these classes after the build so no inline style ships at all. */
      .hl-text { color: #c0c5ce; }
      .hl-keyword { color: #bf616a; }
      .hl-string { color: #a3be8c; }
      .hl-surface { background-color: #2b303b; }
      .hl-fn { color: #8fa1b3; }
      .hl-const { color: #b48ead; }
      .hl-num { color: #d08770; }
      .hl-type { color: #96b5b4; }
      .hl-comment { color: #65737e; }





      /* ssg injects a floating search trigger at position:fixed, z-index 9998,
         top-right — which lands exactly on top of the burger. page.html hides it
         because it has its own in-nav search button; this layout has none, so
         hiding it would remove search from the page entirely. Move it clear of
         the header instead, to the bottom corner, where nothing else sits. */
      @media (max-width: 1180px) {
        #ssg-search-btn {
          top: auto !important;
          bottom: max(1rem, env(safe-area-inset-bottom, 0px));
          right: 1rem !important;
          left: auto !important;
        }
      }

      /* A <select> sizes itself to its widest <option> and does not shrink, so
         this was locale-dependent: the French "Virement SEPA (2 enregistrements,
         EUR)" made it 331px and pushed the page over on a 375px screen while
         English fitted. Any locale with longer option text would do the same,
         which is why the overflow check measures a translated page and not only
         English. */
      .pill-select { max-width: 100%; min-width: 0; }
      .demo-actions { min-width: 0; }
      .demo-actions > * { max-width: 100%; }

      /* Grid children default to min-width:auto, so they refuse to shrink below
         their min-content width. Long unbreakable tokens — <code>
         requested_execution_date</code>, address_line1, pacs.008.001.13 — set
         that floor at ~365px in English and ~389px in French, which is wider than
         a phone. The grid item then cannot fit and mobile Chrome zooms the page
         out. Both halves are needed: min-width:0 lets the item shrink, and
         wrapping the tokens lets the content follow it. */
      .guide-grid > *, .tool-col, .demo-grid > *, .demo-panel { min-width: 0; }
      .guide-block code,
      .info-list code,
      .check-list code,
      .readiness-hint code { overflow-wrap: anywhere; }
      .guide-block, .info-list li, .check-list li { overflow-wrap: break-word; }

      /* Mobile navigation. This layout previously had none: a five-item menu in
         one row with no collapse, against page.html's burger. Its minimum width
         was ~748px, so on any phone mobile Chrome widened the layout viewport to
         fit it and zoomed the whole page out — text clipped at the leading edge,
         the reader panning sideways. scripts/check-mobile-overflow.mjs measures
         this; it is deliberately the same class names and breakpoints as
         page.html so the two layouts collapse identically. */
      .ap-toggle { position: absolute; opacity: 0; pointer-events: none; }
      .ap-burger {
        display: none; align-items: center; justify-content: center;
        width: 44px; height: 44px; cursor: pointer;
        font-size: 1.2rem; color: var(--ink); border-radius: var(--radius-sm);
        border: 1px solid var(--rule-strong); user-select: none;
      }
      .ap-toggle:focus-visible ~ .ap-nav-wrap .ap-burger {
        outline: 3px solid var(--focus-ring, var(--link)); outline-offset: 2px;
      }
      .ap-toggle:checked ~ .ap-nav-wrap .ap-burger { color: var(--link); border-color: var(--link); }

      @media (max-width: 1180px) {
        .ap-nav-wrap { grid-template-columns: auto auto; }
        .ap-brand { grid-row: 1; grid-column: 1; }
        .ap-nav-right { grid-row: 1; grid-column: 2; }
        .ap-burger { display: inline-flex; }
        .ap-nav nav { display: none; grid-row: 2; grid-column: 1 / -1; }
        .ap-toggle:checked ~ .ap-nav-wrap nav { display: block; }
        .ap-menu {
          display: block; width: 100%; justify-self: stretch;
          padding: 0.25rem 0 1rem;
          max-height: calc(100dvh - 76px); overflow: auto;
        }
        .ap-menu > li { display: block; }
        .ap-menu > li + li { border-top: 1px solid var(--rule); }
        .ap-menu > li > a {
          display: flex; justify-content: center; min-height: 48px;
          font-size: 1rem; font-weight: 600;
        }
      }
      @media (max-width: 720px) { .ap-cta-mini { display: none; } }

      .footer { border-top: 1px solid var(--rule); background: var(--bg-alt); margin-top: 5rem; padding: 3.5rem 0 2rem; font-size: 0.93rem; }
    