/* TOMORIS.Design · tomoris-patterns.css · OPTIONAL · EXPERIMENTAL
   Layout and product patterns harvested from Atlas, PIA and the website.
   Requires tomoris-tokens.css. Works best together with tomoris-base.css and
   tomoris-components.css, but needs neither.

   Every class in this file is classified "experimental" in
   tomoris.stability.json: names and rules may still change between minor
   versions. Pin the package exactly and read the CHANGELOG before upgrading.

   Rules this file keeps, all enforced by tests:
   - No colour literal. Every colour is a role or a color-mix of roles, so the
     patterns follow every product world and both modes without a line of
     world-specific CSS. Atlas proved this works: its whole UI has zero hex
     values.
   - Roles stay in the property class they are made for
     (test/rollenverwendung.mjs reads this file).
   - No physical direction (test/sprachen.mjs): start/end, inline/block.
   - Motion only inside prefers-reduced-motion: no-preference. The plain rules
     are the finished picture; animation is an addition, never a requirement
     (the Atlas rule from docs/ui.md).
   - Per-element parameters use the prefix --tmx- (for example --tmx-value on
     a progress ring). --tm- is reserved for package tokens. */

@layer tomoris.patterns {

  /* Every pattern sizes its border box. Several patterns combine width:100%
     with padding (container, top bar, inputs); in the content-box model they
     overflow by their padding, measured 56px of horizontal scroll at 1440px.
     Scoped to package classes, zero specificity, so it never fights an
     application rule. */
  :where([class*="tm-"]), :where([class*="tm-"])::before, :where([class*="tm-"])::after{ box-sizing:border-box }
  a.tm-btn, a.tm-cta, a.tm-stage-button{ text-decoration:none }
  /* The hidden attribute wins over every display value a pattern sets. Tab
     panels, drawers and empty states are toggled with hidden; without this
     line a .tm-panel or .tm-stack with hidden stays visible, because any
     author display value beats the browser's [hidden] rule. */
  :where([class*="tm-"])[hidden]{ display:none !important }

  /* =========================================================
     1. Page frame
     ========================================================= */

  /* Content width. Marketing pages breathe at 84rem, application pages use
     90rem like Atlas. The inline padding scales with the viewport so a 390px
     phone keeps 1rem and a wide screen gets 3rem. */
  /* The page element (usually body, together with .tm-root). Removes the
     browser margin so stage sections and top bars run edge to edge. */
  .tm-page{ margin:0; min-height:100dvh; background:var(--tm-bg) }

  .tm-container{ width:100%; max-width:84rem; margin-inline:auto;
    padding-inline:clamp(1rem, 4vw, 3rem) }
  .tm-container--app{ max-width:90rem }
  .tm-container--narrow{ max-width:48rem }

  .tm-stack{ display:flex; flex-direction:column; gap:1rem }
  .tm-stack--tight{ gap:.5rem }
  .tm-stack--loose{ gap:2rem }
  .tm-cluster{ display:flex; flex-wrap:wrap; align-items:center; gap:.75rem }
  .tm-cluster--end{ justify-content:flex-end }
  .tm-cluster--between{ justify-content:space-between }
  /* The one grid every product needs: cards that wrap without breakpoints. */
  .tm-grid{ display:grid; gap:clamp(.75rem, 2vw, 1.25rem);
    grid-template-columns:repeat(auto-fill, minmax(min(100%, var(--tmx-min, 18rem)), 1fr)) }
  /* Fit: a known small number of items (prices, three steps) stretches over
     the full width instead of leaving empty tracks. */
  .tm-grid--fit{ grid-template-columns:repeat(auto-fit, minmax(min(100%, var(--tmx-min, 18rem)), 1fr)) }

  /* Two panes: start and end side by side from 64rem, stacked below. The
     share of each side is a per-element parameter (--tmx-start, --tmx-end,
     fr values, default 1fr each). --page makes it the whole page (sign-in):
     no gap, at least the viewport high, both sides stretch. __pane is one
     side with generous padding; __pane--center centres a column of at most
     --tmx-max (28rem) in it, for a form card; __pane--spread pushes the first
     and last child to the edges (logo at the top, a note at the bottom).
     Not to be confused with .tm-split (main column plus side column). */
  .tm-panes{ display:grid; gap:clamp(1rem, 2.5vw, 1.5rem) }
  @media (min-width: 64rem){
    .tm-panes{ grid-template-columns:minmax(0, var(--tmx-start, 1fr)) minmax(0, var(--tmx-end, 1fr)) }
  }
  .tm-panes--page{ gap:0; min-height:100dvh; align-items:stretch; grid-template-rows:auto 1fr }
  @media (min-width: 64rem){ .tm-panes--page{ grid-template-rows:none } }
  .tm-panes__pane{ display:flex; flex-direction:column; justify-content:center; gap:clamp(1.5rem, 4vw, 2.5rem);
    min-width:0; padding:clamp(1.5rem, 5vw, 4rem) clamp(1rem, 5vw, 4rem) }
  .tm-panes__pane--center{ align-items:center }
  .tm-panes__pane--spread{ justify-content:space-between }
  .tm-panes__pane--center > *{ width:min(100%, var(--tmx-max, 28rem)) }
  /* Main column plus side column (dashboards, detail pages). No breakpoint:
     the side column starts at --tmx-side, the main column takes the rest,
     and both stack as soon as the main column would drop below 60 percent
     of the row. Works the same inside a shell with or without sidebar. */
  .tm-split{ display:flex; flex-wrap:wrap; gap:clamp(.75rem, 2vw, 1.25rem) }
  .tm-split > *{ flex:1 1 var(--tmx-side, 20rem); min-width:0 }
  .tm-split > :first-child{ flex:999 1 0%; min-width:60% }

  .tm-sr-only{ position:absolute; width:1px; height:1px; padding:0; margin:-1px;
    overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0 }
  .tm-skip-link{ position:absolute; inset-block-start:.75rem; inset-inline-start:.75rem; z-index:100;
    padding:.6rem 1rem; border-radius:var(--tm-radius-button);
    background:var(--tm-accent); color:var(--tm-accent-ink); font-weight:800;
    transform:translateY(-200%) }
  .tm-skip-link:focus{ transform:none }

  .tm-icon{ display:inline-block; flex:none; width:1.25em; height:1.25em; vertical-align:-.2em;
    fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round }
  .tm-kbd{ display:inline-block; min-width:1.6em; padding:.1em .4em; border:1px solid var(--tm-border-strong);
    border-block-end-width:2px; border-radius:var(--tm-radius-marker); background:var(--tm-surface-2);
    color:var(--tm-text-2); font-family:var(--tm-font-mono); font-size:var(--tm-size-mono); text-align:center }

  /* =========================================================
     2. Application frame: shell, sidebar, top bar, navigation
     ========================================================= */

  /* Two layouts, one class. With a sidebar (PIA, admin areas) the shell is a
     two-column grid; without one (Atlas) the top bar carries the navigation. */
  .tm-shell{ display:grid; grid-template-columns:minmax(0, 1fr); min-height:100dvh;
    background:var(--tm-bg); color:var(--tm-text-2) }
  .tm-shell__main{ min-width:0; display:flex; flex-direction:column }
  .tm-shell__content{ flex:1; padding-block:clamp(1rem, 3vw, 2rem) clamp(2rem, 5vw, 4rem) }
  @media (min-width: 64rem){
    .tm-shell:has(> .tm-sidebar){ grid-template-columns:16rem minmax(0, 1fr) }
  }

  /* The sidebar is a stage surface: dark in the light product, and it stays
     dark in dark mode. Navigation text uses the stage text roles, which are
     checked at 4.5 against the stage. */
  .tm-sidebar{ position:sticky; inset-block-start:0; z-index:40; display:flex; flex-direction:column;
    gap:1.25rem; height:100dvh; padding:1.25rem .9rem; overflow-y:auto;
    background:var(--tm-stage); color:var(--tm-stage-text-2);
    border-inline-end:1px solid var(--tm-stage-border) }
  .tm-sidebar :where(h1,h2,h3,h4){ color:var(--tm-stage-ink) }
  /* Below 64rem the sidebar becomes a drawer. The application toggles
     data-open on the element and aria-expanded on its menu button; a closed
     drawer is hidden from the accessibility tree with the inert attribute. */
  @media (max-width: 63.99rem){
    .tm-sidebar{ position:fixed; inset-block:0; inset-inline-start:0; width:min(18rem, 86vw);
      transform:translateX(-105%); visibility:hidden; box-shadow:var(--tm-shadow-overlay) }
    [dir="rtl"] .tm-sidebar{ transform:translateX(105%) }
    /* transition-property: visibility must switch at once when the drawer
       opens, or the application cannot move focus into it in the same task
       (focus() on a still hidden element does nothing). Measured: both the
       motion rule in section 11 and the reduced-motion rule of
       tomoris-base.css (0.01ms on "all") kept it hidden at that moment.
       Closing still runs the full transition from the closed rule. */
    .tm-sidebar[data-open="true"]{ transform:none; visibility:visible; transition-property:transform }
    .tm-sidebar-scrim{ position:fixed; inset:0; z-index:39; background:var(--tm-scrim) }
    .tm-sidebar-scrim[hidden]{ display:none }
  }
  @media (min-width: 64rem){ .tm-sidebar-scrim{ display:none } }

  .tm-nav{ display:flex; flex-direction:column; gap:.15rem; margin:0; padding:0; list-style:none }
  .tm-nav__group{ margin:1rem 0 .35rem; padding-inline:.65rem; color:var(--tm-stage-text-3);
    font-size:var(--tm-size-eyebrow); font-weight:800; letter-spacing:var(--tm-track-eyebrow); text-transform:uppercase }
  .tm-nav__item{ display:flex; align-items:center; gap:.7rem; width:100%; min-height:2.5rem;
    padding:.5rem .65rem; border:0; border-radius:var(--tm-radius-tile);
    background:transparent; color:var(--tm-stage-text-2); font:inherit; font-weight:600;
    text-align:start; text-decoration:none; cursor:pointer;
    transition:background var(--tm-dur-fast) var(--tm-ease), color var(--tm-dur-fast) var(--tm-ease) }
  .tm-nav__item:hover{ background:color-mix(in srgb, var(--tm-stage-3) 70%, transparent); color:var(--tm-stage-ink) }
  /* The current page is carried by aria-current, never by a class alone, so
     what screen readers announce and what the eye sees cannot drift apart. */
  .tm-nav__item[aria-current="page"]{ background:var(--tm-stage-3); color:var(--tm-stage-ink);
    box-shadow:inset 3px 0 0 0 var(--tm-stage-accent) }
  [dir="rtl"] .tm-nav__item[aria-current="page"]{ box-shadow:inset -3px 0 0 0 var(--tm-stage-accent) }
  .tm-nav__count{ margin-inline-start:auto; min-width:1.5rem; padding:.05rem .45rem;
    border-radius:var(--tm-radius-pill); background:var(--tm-stage-2); color:var(--tm-stage-ink);
    font-size:var(--tm-size-eyebrow); font-weight:800; text-align:center }
  /* Bottom of the sidebar: the signed-in user and a sign-out button. The
     automatic start margin pins it to the end of the column. */
  .tm-sidebar__foot{ display:flex; align-items:center; gap:.7rem; margin-block-start:auto; padding:1rem .4rem 0;
    border-block-start:1px solid color-mix(in srgb, var(--tm-stage-border) 35%, transparent);
    font-size:var(--tm-size-label); line-height:1.35 }
  .tm-sidebar__foot strong{ display:block; color:var(--tm-stage-ink) }
  .tm-sidebar__foot > :last-child{ margin-inline-start:auto }

  /* Top bar. Atlas signature: glass over the stage, a hairline that flows from
     Pulse Blue into Fusion, and a soft brand shadow. Sticky, so content scrolls
     underneath the blur. */
  .tm-topbar{ position:sticky; inset-block-start:0; z-index:30;
    /* 94 and not the 88 percent of Atlas: over a light page the stage gets
       lighter with every percent of transparency. Measured in the PIA world,
       --tm-stage-text-3 fell to 4.2 : 1 at 88 percent and holds 5.0 at 94. */
    background:color-mix(in srgb, var(--tm-stage) 94%, transparent);
    color:var(--tm-stage-text-2);
    -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px);
    border-block-end:1px solid color-mix(in srgb, var(--tm-stage-border) 35%, transparent);
    box-shadow:0 10px 30px color-mix(in srgb, var(--tm-brand-1) 25%, transparent) }
  .tm-topbar::after{ content:""; position:absolute; inset-inline:0; inset-block-end:-1px; height:1px;
    background:linear-gradient(90deg, transparent, var(--tm-brand-2), var(--tm-brand-3), transparent);
    background-size:200% 100%; opacity:.8; pointer-events:none }
  .tm-topbar__inner{ display:flex; align-items:center; gap:1rem; min-height:3.75rem;
    width:100%; max-width:90rem; margin-inline:auto; padding:.6rem clamp(1rem, 3vw, 2rem) }
  .tm-topbar__spacer{ flex:1 }
  .tm-topbar :where(h1,h2,h3,h4){ color:var(--tm-stage-ink) }
  @media (max-width: 40rem){ .tm-topbar{ position:static } .tm-topbar .tm-topbar__hide-sm{ display:none } }

  /* Product lockup: logo image or signet, the eyebrow "TOMORIS" and the
     product name. The brand dot is the TOMORIS. full stop in Fusion. */
  .tm-brandmark{ display:inline-flex; align-items:center; gap:.65rem; color:inherit; text-decoration:none; line-height:1 }
  .tm-brandmark__logo{ display:block; width:auto; height:2rem; flex:none }
  .tm-brandmark__text{ display:flex; flex-direction:column; gap:.2rem }
  .tm-brandmark__house{ color:var(--tm-text-3); font-size:.62rem; font-weight:800;
    letter-spacing:.16em; text-transform:uppercase; white-space:nowrap }
  .tm-brandmark__name{ color:var(--tm-text-1); font-size:1.2rem; font-weight:800; letter-spacing:-.01em }
  /* Up to 368px (320px is the WCAG reflow width) the top bar keeps the
     logo and drops the text lines; otherwise lockup, one button and the
     avatar overflowed by up to 55px. The brand link carries an aria-label
     with the product name. */
  @media (max-width: 23rem){ .tm-topbar .tm-brandmark__text{ display:none } }
  /* The full stop of "TOMORIS." drawn as a shape, not as a character: as a
     shape it may carry the brand value Fusion on any surface, as text it
     would need a checked text role. */
  .tm-brandmark__dot{ display:inline-block; width:.3em; height:.3em; margin-inline-start:.06em;
    border-radius:50%; background:var(--tm-brand-3); vertical-align:baseline }

  .tm-menu-button{ display:inline-grid; place-items:center; width:2.5rem; height:2.5rem; flex:none;
    border:1px solid color-mix(in srgb, var(--tm-stage-border) 70%, transparent); border-radius:var(--tm-radius-tile);
    background:transparent; color:var(--tm-stage-ink); cursor:pointer }
  /* Repeated after the definition above: the hiding rule in section 2 comes
     earlier with the same specificity and lost to display:inline-grid, so
     the drawer button stayed visible next to the open sidebar. */
  @media (min-width: 64rem){ .tm-menu-button{ display:none } }

  /* Avatar. Accent fill and accent ink, because both are checked against each
     other in every world. A gradient of brand values (Atlas) would put white
     on PIA's sun yellow. */
  .tm-avatar{ display:inline-grid; place-items:center; flex:none; width:2.25rem; height:2.25rem;
    border-radius:50%; background:var(--tm-accent); color:var(--tm-accent-ink);
    font-size:.8rem; font-weight:800; letter-spacing:.02em;
    box-shadow:0 0 0 2px color-mix(in srgb, var(--tm-brand-3) 55%, transparent) }
  .tm-avatar--lg{ width:3rem; height:3rem; font-size:1rem }
  .tm-avatar--sm{ width:1.75rem; height:1.75rem; font-size:.66rem;
    box-shadow:0 0 0 1px color-mix(in srgb, var(--tm-brand-3) 45%, transparent) }

  /* Pill button for dark surfaces (top bar, hero). The stage-link role is the
     operating colour on the stage and is checked at 4.5 against it. */
  .tm-stage-button{ display:inline-flex; align-items:center; gap:.5rem; min-height:2.25rem;
    padding:.4rem .95rem; border:1px solid color-mix(in srgb, var(--tm-stage-border) 80%, transparent);
    border-radius:var(--tm-radius-pill); background:transparent; color:var(--tm-stage-ink);
    font:inherit; font-size:var(--tm-size-label); font-weight:700; text-decoration:none; cursor:pointer;
    transition:border-color var(--tm-dur-fast) var(--tm-ease), background var(--tm-dur-fast) var(--tm-ease) }
  .tm-stage-button:hover{ border-color:var(--tm-stage-link);
    background:color-mix(in srgb, var(--tm-stage-3) 55%, transparent) }
  /* Icon-only variant (notifications, sign-out). Always give it an
     aria-label. A .tm-pulse inside marks unread items. */
  .tm-stage-button--icon{ position:relative; justify-content:center; width:2.25rem; padding:0 }
  .tm-stage-button--icon > .tm-pulse{ position:absolute; inset-block-start:.3rem; inset-inline-end:.3rem;
    background:var(--tm-brand-3) }

  .tm-breadcrumb{ display:flex; flex-wrap:wrap; align-items:center; gap:.4rem; margin:0; padding:0;
    list-style:none; color:var(--tm-text-3); font-size:var(--tm-size-label) }
  .tm-breadcrumb li + li::before{ content:"/"; margin-inline-end:.4rem; color:var(--tm-text-3) }
  .tm-breadcrumb a{ color:var(--tm-accent-text); text-decoration:none }
  .tm-breadcrumb a:hover{ text-decoration:underline }
  .tm-breadcrumb [aria-current="page"]{ color:var(--tm-text-1); font-weight:700 }

  /* =========================================================
     3. Stage visuals (Atlas): glow, aurora, dot floor, glass
     ========================================================= */

  /* A stage with depth. Put .tm-glow (and optionally .tm-aurora or
     .tm-dotfloor) as aria-hidden children into any element with .tm-stage and
     .tm-stage-scene. The scene clips them and stacks the content above. */
  .tm-stage-scene{ position:relative; isolation:isolate; overflow:hidden }
  /* A scene as a card inside application content (Atlas welcome band). Use
     it together with .tm-stage. box-shadow replaces the stage edge of
     .tm-stage instead of adding to it, so the inset ring is repeated here. */
  .tm-stage-scene--card{ padding:clamp(1.25rem, 3.5vw, 2.5rem); border-radius:calc(var(--tm-radius-card) * 1.5);
    box-shadow:inset 0 0 0 1px var(--tm-stage-border), 0 24px 60px color-mix(in srgb, var(--tm-brand-1) 22%, transparent) }
  .tm-glow, .tm-aurora, .tm-dotfloor{ position:absolute; z-index:-1; pointer-events:none }
  .tm-glow{ inset:-90% -10% -70% 35%;
    background:
      radial-gradient(45% 60% at 30% 40%, color-mix(in srgb, var(--tm-brand-2) 48%, transparent), transparent 70%),
      radial-gradient(30% 45% at 80% 30%, color-mix(in srgb, var(--tm-brand-3) 24%, transparent), transparent 70%);
    filter:blur(26px) }
  .tm-aurora{ inset:-25%;
    background:
      radial-gradient(38% 34% at 22% 30%, color-mix(in srgb, var(--tm-brand-2) 58%, transparent), transparent 70%),
      radial-gradient(32% 30% at 78% 62%, color-mix(in srgb, var(--tm-brand-3) 34%, transparent), transparent 72%),
      radial-gradient(28% 24% at 62% 18%, color-mix(in srgb, var(--tm-stage-border) 52%, transparent), transparent 70%);
    filter:blur(28px) }
  .tm-dotfloor{ inset-inline:-20%; inset-block-end:-10%; height:60%;
    background-image:radial-gradient(circle, color-mix(in srgb, var(--tm-stage-border) 85%, transparent) 1.2px, transparent 1.7px);
    background-size:34px 34px; transform:perspective(620px) rotateX(64deg); transform-origin:bottom;
    -webkit-mask-image:linear-gradient(to top, black 8%, transparent 82%);
    mask-image:linear-gradient(to top, black 8%, transparent 82%); opacity:.5 }

  /* Glass panel on the stage (Atlas feature visual, fact tiles). */
  .tm-glass-panel{ position:relative; overflow:hidden; display:flex; flex-direction:column; gap:1rem;
    margin:0; padding:clamp(1rem, 3vw, 1.6rem);
    border:1px solid color-mix(in srgb, var(--tm-stage-border) 45%, transparent);
    border-radius:calc(var(--tm-radius-card) * 1.5);
    background:
      radial-gradient(120% 90% at 25% 0%, color-mix(in srgb, var(--tm-brand-2) 24%, transparent), transparent 62%),
      color-mix(in srgb, var(--tm-stage-2) 55%, transparent);
    -webkit-backdrop-filter:blur(12px); backdrop-filter:blur(12px);
    box-shadow:0 30px 80px color-mix(in srgb, var(--tm-brand-1) 55%, transparent);
    color:var(--tm-stage-text-2) }
  .tm-glass-panel :where(h2,h3,h4){ color:var(--tm-stage-ink) }

  /* Gradient headline. The gradient starts and ends in currentColor, the text
     role the element already carries, and only tints towards the brand in
     between. Every stop keeps at least 40 percent of the checked text colour,
     so the headline stays readable in every world; it is meant for display
     sizes only. Without background-clip support the text simply keeps its
     colour. */
  .tm-gradient-text{ color:var(--tm-text-1) }
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel) .tm-gradient-text,
  .tm-gradient-text--stage{ color:var(--tm-stage-ink) }
  @supports ((-webkit-background-clip: text) or (background-clip: text)){
    .tm-gradient-text, .tm-gradient-text--stage{
      background-image:linear-gradient(100deg, currentColor 0%,
        color-mix(in srgb, currentColor 45%, var(--tm-brand-3)) 38%,
        color-mix(in srgb, currentColor 40%, var(--tm-brand-2)) 68%, currentColor 100%);
      background-size:220% 100%; background-position:0 0;
      -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent }
  }

  /* =========================================================
     4. Typography helpers for pages
     ========================================================= */
  .tm-display{ margin:0; font-size:clamp(2.3rem, 5vw, 4.3rem); font-weight:800; line-height:1.04;
    letter-spacing:-.03em; text-wrap:balance }
  .tm-title{ margin:0; font-size:clamp(1.8rem, 3.6vw, 3rem); font-weight:800; line-height:1.1;
    letter-spacing:-.02em; text-wrap:balance }
  .tm-heading{ margin:0; font-size:clamp(1.25rem, 2.4vw, 1.8rem); font-weight:800; line-height:1.15;
    letter-spacing:-.015em }
  .tm-lead{ margin:0; max-width:42rem; color:var(--tm-text-2);
    font-size:clamp(1.02rem, 1.35vw, 1.22rem); line-height:1.6; text-wrap:pretty }
  .tm-muted{ color:var(--tm-text-3) }
  /* Text link in copy, forms and help lines. Underlined, because a link in
     running text must not depend on colour alone (WCAG 1.4.1). */
  .tm-link{ color:var(--tm-accent-text); font-weight:700; text-decoration:underline;
    text-decoration-thickness:1px; text-underline-offset:.2em }
  .tm-link:hover{ text-decoration-thickness:2px }
  .tm-display, .tm-title, .tm-heading{ color:var(--tm-text-1) }

  /* Stage contexts. This layer comes after tomoris.components in the cascade
     and therefore wins regardless of specificity; every rule above that sets
     a text colour for the normal surface needs its stage counterpart here,
     or dark text would land on the dark stage. */
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel)
    :is(.tm-display, .tm-title, .tm-heading, .tm-brandmark__name){ color:var(--tm-stage-ink) }
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel)
    :is(.tm-lead){ color:var(--tm-stage-text-2) }
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel)
    :is(.tm-muted, .tm-brandmark__house){ color:var(--tm-stage-text-3) }
  /* Repairs a cascade defect of tomoris-components.css (3.7.0): there
     ".tm-stage :where(.tm-eyebrow)" comes BEFORE ".tm-eyebrow" with the same
     specificity, so the later rule wins and the stage rule never applies.
     Measured: the eyebrow keeps --tm-accent-text on the stage, which is about
     2.5 : 1 in light mode, below AA. Same for .tm-mono. This layer comes after
     the components layer and restores the intended stage roles. */
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel)
    .tm-eyebrow{ color:var(--tm-stage-accent) }
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel)
    .tm-mono{ color:var(--tm-stage-text-3) }
  /* Repairs the pressed state of .tm-theme-switch (components 3.7.0): it sets
     --tm-accent-text on --tm-accent-soft, the very pair --tm-accent-soft-ink
     was introduced for. Measured in the PIA world: 4.31 : 1, below AA. */
  .tm-theme-switch > button[aria-pressed="true"]{ color:var(--tm-accent-soft-ink) }
  /* Focus ring on stage surfaces that do not carry .tm-stage. The default
     ring role (--tm-accent-text) is checked against the page, not against
     the stage: measured 2.6 : 1 on the light-mode sidebar. Same hook and
     same role as .tm-stage in tomoris-components.css, so an application
     colour set through --tm-focus-color still wins. */
  :where(.tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel){ --tm-focus-color-default:var(--tm-stage-accent) }
  /* Theme switch on the stage. The component draws a light pill on
     --tm-surface-2, which sits as a bright patch in a dark top bar or
     footer; here it takes the stage roles like every other control. Comes
     after the generic pressed-state repair above and wins on the stage. */
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel) .tm-theme-switch{
    border-color:color-mix(in srgb, var(--tm-stage-border) 60%, transparent);
    background:color-mix(in srgb, var(--tm-stage-2) 70%, transparent) }
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel) .tm-theme-switch > button{
    color:var(--tm-stage-text-2) }
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel) .tm-theme-switch > button:hover{
    color:var(--tm-stage-ink) }
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel) .tm-theme-switch > button[aria-pressed="true"]{
    background:var(--tm-stage-3); color:var(--tm-stage-ink);
    box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--tm-stage-border) 80%, transparent) }
  /* The house line is .62rem; in the top bar it takes the stronger stage
     text role (PIA light measured 4.21 with stage-text-3 on a translucent
     bar, before the bar became 94 percent opaque). */
  .tm-topbar .tm-brandmark__house{ color:var(--tm-stage-text-2) }
  /* Breadcrumb and text link on the stage (workspace header band). */
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel)
    :is(.tm-breadcrumb, .tm-breadcrumb li + li::before){ color:var(--tm-stage-text-3) }
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel)
    :is(.tm-breadcrumb a, .tm-link){ color:var(--tm-stage-link) }
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel)
    .tm-breadcrumb [aria-current="page"]{ color:var(--tm-stage-ink) }

  /* =========================================================
     5. Marketing sections: announcement, hero, section, features, steps,
        prices, FAQ, final call, footer
     ========================================================= */

  /* Announcement bar (PIA). Accent-soft surface with its own checked ink. */
  .tm-announce{ display:flex; justify-content:center; align-items:center; gap:.6rem; padding:.55rem 1rem;
    background:var(--tm-accent-soft); color:var(--tm-accent-soft-ink);
    font-size:var(--tm-size-label); font-weight:700; text-align:center }
  .tm-announce a{ color:inherit; font-weight:800 }
  .tm-pulse{ display:inline-block; width:.5rem; height:.5rem; flex:none; border-radius:50%; background:var(--tm-accent) }

  .tm-hero{ padding-block:clamp(3rem, 8vw, 6.5rem) clamp(3.5rem, 9vw, 7rem) }
  .tm-hero__grid{ display:grid; gap:clamp(2rem, 5vw, 4rem); align-items:center }
  @media (min-width: 64rem){ .tm-hero__grid{ grid-template-columns:1.05fr 1fr } }
  .tm-hero__actions{ display:flex; flex-wrap:wrap; gap:.75rem; margin-block-start:1.75rem }
  .tm-hero .tm-eyebrow{ margin-block-end:1rem }
  .tm-hero .tm-lead{ margin-block-start:1.25rem }
  .tm-hero .tm-checks{ margin-block-start:1.75rem }

  /* Call to action. Accent fill with accent ink (checked in every world), a
     soft brand glow and, with motion allowed, a shine that sweeps once and a
     halo that breathes. Use one per view. */
  .tm-cta{ position:relative; isolation:isolate; overflow:hidden; display:inline-flex; align-items:center; gap:.6rem;
    min-height:3rem; padding:.8rem 1.5rem; border:0; border-radius:var(--tm-radius-pill);
    background:var(--tm-accent); color:var(--tm-accent-ink); font:inherit; font-weight:800;
    white-space:nowrap; text-decoration:none; cursor:pointer;
    box-shadow:0 14px 40px color-mix(in srgb, var(--tm-accent) 45%, transparent),
      inset 0 0 0 1px color-mix(in srgb, var(--tm-border-elevated) 40%, transparent);
    transition:transform var(--tm-dur-fast) var(--tm-ease), box-shadow var(--tm-dur-fast) var(--tm-ease), background var(--tm-dur-fast) var(--tm-ease) }
  .tm-cta::before{ content:""; position:absolute; inset:0; z-index:-1; pointer-events:none;
    background:linear-gradient(100deg, transparent 30%, color-mix(in srgb, var(--tm-brand-4) 38%, transparent) 50%, transparent 70%);
    transform:translateX(-130%) }
  .tm-cta--small{ min-height:2.4rem; padding:.5rem 1.1rem; font-size:var(--tm-size-label) }
  .tm-cta:hover{ background:var(--tm-accent-hover); transform:translateY(-2px);
    box-shadow:0 22px 60px color-mix(in srgb, var(--tm-accent) 55%, transparent),
      0 0 0 6px color-mix(in srgb, var(--tm-accent) 20%, transparent) }
  .tm-cta .tm-icon{ transition:transform var(--tm-dur-fast) var(--tm-ease) }
  .tm-cta:hover .tm-icon{ transform:translateX(3px) }
  [dir="rtl"] .tm-cta .tm-icon{ transform:scaleX(-1) }
  [dir="rtl"] .tm-cta:hover .tm-icon{ transform:scaleX(-1) translateX(3px) }

  .tm-section{ padding-block:clamp(3.5rem, 8vw, 6.5rem) }
  /* Soft band as in PIA (".alt"): surface-2 with a line above and below.
     Not --tm-bg-soft: the accent text role is checked against surface and bg,
     and on bg-soft it measured 4.15 : 1 in the PIA world, below AA. */
  .tm-section--soft{ background:var(--tm-surface-2); border-block:1px solid var(--tm-border) }
  /* Application rhythm: a workspace header band or a content block. */
  .tm-section--compact{ padding-block:clamp(1.25rem, 3.5vw, 2.5rem) }
  .tm-section__head{ display:flex; flex-direction:column; gap:.8rem; max-width:46rem; margin-block-end:clamp(1.75rem, 4vw, 3rem) }
  .tm-section__head--center{ align-items:center; margin-inline:auto; text-align:center }
  .tm-section__head--center .tm-lead{ margin-inline:auto }

  .tm-feature{ display:flex; flex-direction:column; gap:.6rem; padding:1.4rem;
    border:1px solid var(--tm-border-elevated); border-radius:var(--tm-radius-card); background:var(--tm-surface);
    transition:transform var(--tm-dur-fast) var(--tm-ease), box-shadow var(--tm-dur-fast) var(--tm-ease) }
  .tm-feature:hover{ transform:translateY(-2px); box-shadow:var(--tm-shadow) }
  .tm-feature h3{ margin:0; color:var(--tm-text-1); font-size:1.15rem; font-weight:800 }
  .tm-feature p{ margin:0; color:var(--tm-text-2); line-height:1.6 }
  .tm-feature .tm-tile{ width:2.75rem; height:2.75rem; border-radius:calc(var(--tm-radius-tile) + 2px) }

  /* Outline numerals (Atlas feature index). Decorative: the stroke uses the
     stage-link role, which is a checked line colour on the stage. */
  .tm-outline-number{ font-size:clamp(2.8rem, 5vw, 4.2rem); font-weight:800; line-height:1;
    color:transparent; -webkit-text-stroke:1px var(--tm-stage-link) }

  /* Numbered steps on the stage (PIA "Schleier", Atlas onboarding). */
  .tm-steps{ display:grid; gap:.9rem; margin:0; padding:0; list-style:none; counter-reset:tm-step }
  @media (min-width: 48rem){ .tm-steps{ grid-template-columns:repeat(auto-fit, minmax(12rem, 1fr)) } }
  .tm-step{ position:relative; padding:1.1rem 1rem; counter-increment:tm-step;
    border:1px solid color-mix(in srgb, var(--tm-stage-border) 70%, transparent); border-radius:var(--tm-radius-card);
    background:var(--tm-stage-2); color:var(--tm-stage-text-2) }
  .tm-step::before{ content:counter(tm-step); display:inline-grid; place-items:center; width:1.6rem; height:1.6rem;
    margin-block-end:.6rem; border-radius:50%; background:var(--tm-stage-3); color:var(--tm-stage-accent);
    box-shadow:inset 0 0 0 1px var(--tm-stage-accent); font-size:.8rem; font-weight:800 }
  .tm-step h3{ margin:0 0 .3rem; color:var(--tm-stage-ink); font-size:1rem; font-weight:800 }
  .tm-step p{ margin:0; font-size:var(--tm-size-label); line-height:1.55 }

  /* Check list (PIA). The tick sits on the ok fill with the ok ink. */
  .tm-checks{ display:grid; gap:.55rem; margin:0; padding:0; list-style:none }
  .tm-checks li{ position:relative; padding-inline-start:2rem; line-height:1.5 }
  .tm-checks li::before{ content:"\2713"; position:absolute; inset-inline-start:0; inset-block-start:.05rem;
    display:grid; place-items:center; width:1.4rem; height:1.4rem; border-radius:50%;
    background:var(--tm-ok-fill); color:var(--tm-ok-ink); font-size:.8rem; font-weight:800 }

  /* Price cards (PIA packages). The recommended one gets an accent edge. */
  .tm-price{ display:flex; flex-direction:column; gap:1rem; padding:1.6rem;
    border:1px solid var(--tm-border-elevated); border-radius:var(--tm-radius-card); background:var(--tm-surface) }
  .tm-price--featured{ border:2px solid var(--tm-accent); box-shadow:var(--tm-shadow) }
  .tm-price__name{ margin:0; color:var(--tm-text-1); font-size:1.15rem; font-weight:800 }
  .tm-price__amount{ color:var(--tm-text-1); font-size:clamp(1.9rem, 3vw, 2.4rem); font-weight:800;
    letter-spacing:-.02em; font-variant-numeric:tabular-nums }
  .tm-price__amount small{ color:var(--tm-text-3); font-size:var(--tm-size-label); font-weight:600; letter-spacing:0 }
  .tm-price .tm-checks{ flex:1 }

  /* FAQ on native details/summary: keyboard and screen reader support for free. */
  .tm-faq{ border-block-end:1px solid var(--tm-border) }
  .tm-faq summary{ display:flex; justify-content:space-between; align-items:center; gap:1rem; padding:1.1rem 0;
    color:var(--tm-text-1); font-weight:700; list-style:none; cursor:pointer }
  .tm-faq summary::-webkit-details-marker{ display:none }
  .tm-faq summary::after{ content:"+"; flex:none; display:grid; place-items:center; width:1.75rem; height:1.75rem;
    border-radius:50%; background:var(--tm-accent-soft); color:var(--tm-accent-soft-ink); font-weight:800;
    transition:transform var(--tm-dur-fast) var(--tm-ease) }
  .tm-faq[open] summary::after{ transform:rotate(45deg) }
  .tm-faq__body{ padding-block-end:1.1rem; color:var(--tm-text-2); line-height:1.65 }

  /* Logo row ("trusted by", partner badges). Muted until hovered. */
  .tm-logo-row{ display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:clamp(1.25rem, 4vw, 3rem);
    color:var(--tm-text-3); font-weight:800; letter-spacing:.04em }
  .tm-logo-row > *{ opacity:.75; transition:opacity var(--tm-dur-fast) var(--tm-ease) }
  .tm-logo-row > *:hover{ opacity:1 }

  /* Marquee of principles (Atlas). Duplicate the list once with aria-hidden
     for the seamless loop; without motion it is a wrapping row. */
  .tm-marquee{ overflow:hidden }
  .tm-marquee__track{ display:flex; flex-wrap:wrap; gap:.75rem; width:max-content; max-width:100% }
  .tm-marquee__item{ display:inline-flex; align-items:center; gap:.6rem; padding:.55rem 1rem; white-space:nowrap;
    border:1px solid color-mix(in srgb, var(--tm-stage-border) 70%, transparent); border-radius:var(--tm-radius-pill);
    color:var(--tm-stage-ink); font-weight:700 }
  /* The duplicate set only exists for the seamless loop. Without motion it
     would repeat the list on screen. */
  .tm-marquee__item[aria-hidden="true"]{ display:none }
  .tm-marquee__item::before{ content:""; width:.45rem; height:.45rem; border-radius:50%; background:var(--tm-brand-3);
    box-shadow:0 0 10px var(--tm-brand-3) }

  .tm-footer{ padding-block:clamp(2.5rem, 6vw, 4rem) 2rem; background:var(--tm-stage); color:var(--tm-stage-text-2) }
  .tm-footer a{ color:var(--tm-stage-link); text-decoration:none }
  .tm-footer a:hover{ text-decoration:underline }
  .tm-footer :where(h2,h3,h4){ margin:0 0 .75rem; color:var(--tm-stage-ink); font-size:var(--tm-size-label);
    letter-spacing:var(--tm-track-eyebrow); text-transform:uppercase }
  .tm-footer ul{ margin:0; padding:0; list-style:none }
  .tm-footer__grid{ display:grid; gap:2rem; grid-template-columns:repeat(auto-fit, minmax(11rem, 1fr)) }
  .tm-footer__legal{ display:flex; flex-wrap:wrap; justify-content:space-between; gap:1rem; margin-block-start:2.5rem;
    padding-block-start:1.25rem; border-block-start:1px solid color-mix(in srgb, var(--tm-stage-border) 50%, transparent);
    color:var(--tm-stage-text-3); font-size:var(--tm-size-label) }

  /* Device frame for product screenshots (PIA). */
  .tm-device{ padding:.6rem; border-radius:calc(var(--tm-radius-card) + 6px); background:var(--tm-stage);
    box-shadow:var(--tm-shadow), inset 0 0 0 1px var(--tm-stage-border) }
  .tm-device > *{ display:block; width:100%; border-radius:calc(var(--tm-radius-card) - 3px); overflow:hidden }

  /* =========================================================
     6. Data: KPI tiles, progress, heat scale, bars, timeline, lists
     ========================================================= */

  .tm-kpi{ display:flex; flex-direction:column; gap:.35rem; padding:1.1rem 1.2rem;
    border:1px solid var(--tm-border-elevated); border-radius:var(--tm-radius-card); background:var(--tm-surface) }
  .tm-kpi__label{ color:var(--tm-text-3); font-size:var(--tm-size-eyebrow); font-weight:800;
    letter-spacing:.1em; text-transform:uppercase }
  .tm-kpi__value{ color:var(--tm-text-1); font-size:clamp(1.7rem, 3vw, 2.4rem); font-weight:800; line-height:1.05;
    letter-spacing:-.02em; font-variant-numeric:tabular-nums }
  .tm-kpi__meta{ display:flex; flex-wrap:wrap; align-items:center; gap:.5rem; color:var(--tm-text-3); font-size:var(--tm-size-label) }
  .tm-delta{ display:inline-flex; align-items:center; gap:.2rem; padding:.05rem .45rem; border-radius:var(--tm-radius-pill);
    font-size:var(--tm-size-eyebrow); font-weight:800; font-variant-numeric:tabular-nums }
  .tm-delta--up{ background:var(--tm-ok-fill); color:var(--tm-ok-ink) }
  .tm-delta--down{ background:var(--tm-crit-fill); color:var(--tm-crit-ink) }
  .tm-delta--flat{ background:var(--tm-unknown-fill); color:var(--tm-unknown-ink) }
  /* Glass variant for the stage (Atlas fact tiles). */
  .tm-kpi--glass{ border-color:color-mix(in srgb, var(--tm-stage-border) 42%, transparent);
    background:color-mix(in srgb, var(--tm-stage-2) 62%, transparent);
    -webkit-backdrop-filter:blur(12px); backdrop-filter:blur(12px) }
  .tm-kpi--glass .tm-kpi__label{ color:var(--tm-stage-text-3) }
  .tm-kpi--glass .tm-kpi__value{ color:var(--tm-stage-ink) }
  .tm-kpi--glass .tm-kpi__meta{ color:var(--tm-stage-text-2) }

  .tm-progress{ position:relative; height:.5rem; overflow:hidden; border-radius:var(--tm-radius-pill); background:var(--tm-surface-3) }
  .tm-progress > span{ display:block; width:var(--tmx-value, 0%); height:100%; border-radius:inherit;
    background:linear-gradient(90deg, var(--tm-accent), color-mix(in srgb, var(--tm-accent) 70%, var(--tm-brand-3))) }
  /* Progress ring: set --tmx-value as a percentage, for example 64%. */
  .tm-ring{ --tmx-size:4.5rem; position:relative; display:inline-grid; place-items:center; width:var(--tmx-size); height:var(--tmx-size);
    border-radius:50%;
    background:conic-gradient(var(--tm-accent) var(--tmx-value, 0%), var(--tm-surface-3) 0) }
  .tm-ring::before{ content:""; position:absolute; inset:.45rem; border-radius:50%; background:var(--tm-surface) }
  .tm-ring > *{ position:relative; color:var(--tm-text-1); font-weight:800; font-variant-numeric:tabular-nums }

  /* Heat scale (Atlas potential map). Five levels from Pulse Blue to Fusion,
     built from brand values, so a world with its own brand gets its own
     scale. Never carry the value by colour alone: write the level next to it
     or in the accessible name. */
  .tm-heat{ display:inline-block; min-width:1.5rem; min-height:1.5rem; border-radius:6px;
    border:1px dashed var(--tm-border-strong); background:transparent }
  .tm-heat[data-level="1"]{ border:0; background:var(--tm-brand-2) }
  .tm-heat[data-level="2"]{ border:0; background:color-mix(in srgb, var(--tm-brand-2) 45%, var(--tm-brand-4)) }
  .tm-heat[data-level="3"]{ border:0; background:color-mix(in srgb, var(--tm-brand-3) 55%, var(--tm-brand-4)) }
  .tm-heat[data-level="4"]{ border:0; background:var(--tm-brand-3);
    box-shadow:0 0 14px color-mix(in srgb, var(--tm-brand-3) 55%, transparent) }

  /* Horizontal bar for simple charts and road maps. Width via --tmx-value. */
  .tm-bar{ height:.65rem; width:var(--tmx-value, 100%); margin-inline-start:var(--tmx-offset, 0%);
    border-radius:var(--tm-radius-pill);
    background:linear-gradient(90deg, var(--tm-brand-2), var(--tm-brand-3)) }

  /* Road map (Atlas Fahrplan): a label and a time track per row. The track
     draws --tmx-cols period lines (default 4, quarters); a .tm-bar inside is
     placed with --tmx-offset and sized with --tmx-value, both as a share of
     the track. Put the period names into a .tm-columns-axis in the first
     row. Below 40rem the track moves under its label. Give each track
     role="img" and an aria-label with the period in words. */
  .tm-roadmap{ display:grid; grid-template-columns:minmax(0, 1fr); gap:.35rem 1.25rem; align-items:center }
  @media (min-width: 40rem){ .tm-roadmap{ grid-template-columns:minmax(0, 15rem) minmax(0, 1fr); row-gap:.6rem } }
  .tm-roadmap__label{ display:flex; flex-direction:column; gap:.1rem; min-width:0;
    color:var(--tm-text-3); font-size:var(--tm-size-label) }
  .tm-roadmap__label strong{ overflow:hidden; color:var(--tm-text-1); font-size:var(--tm-size-body);
    text-overflow:ellipsis; white-space:nowrap }
  .tm-roadmap__track{ display:flex; align-items:center; min-height:2.25rem; padding-inline:.15rem;
    border-radius:var(--tm-radius-tile);
    background:linear-gradient(90deg, var(--tm-border) 1px, transparent 1px) 0 0 / calc(100% / var(--tmx-cols, 4)) 100%, var(--tm-surface-2) }
  .tm-roadmap__track > .tm-bar{ height:.85rem; box-shadow:0 4px 14px color-mix(in srgb, var(--tm-brand-2) 28%, transparent) }
  .tm-roadmap .tm-columns-axis{ margin:0 }

  .tm-timeline{ position:relative; display:grid; gap:1rem; margin:0; padding:0; list-style:none }
  .tm-timeline::before{ content:""; position:absolute; inset-block:.4rem; inset-inline-start:.35rem; width:2px; background:var(--tm-border) }
  .tm-timeline > li{ position:relative; display:grid; gap:.15rem; padding-inline-start:1.6rem }
  .tm-timeline > li > .tm-dot{ position:absolute; inset-inline-start:0; inset-block-start:.35rem; width:.75rem; height:.75rem;
    box-shadow:0 0 0 3px var(--tm-surface) }
  .tm-timeline__title{ color:var(--tm-text-1); font-weight:700 }
  .tm-timeline__meta{ color:var(--tm-text-3); font-size:var(--tm-size-label) }

  .tm-list{ display:flex; flex-direction:column; margin:0; padding:0; list-style:none }
  .tm-list__row{ display:flex; align-items:center; gap:.85rem; padding:.8rem .25rem; border-block-end:1px solid var(--tm-border-weak) }
  .tm-list__row:last-child{ border-block-end:0 }
  .tm-list__main{ display:flex; flex-direction:column; gap:.1rem; min-width:0; flex:1 }
  .tm-list__title{ overflow:hidden; color:var(--tm-text-1); font-weight:700; text-overflow:ellipsis; white-space:nowrap }
  .tm-list__meta{ color:var(--tm-text-3); font-size:var(--tm-size-label) }

  /* Wraps a .tm-table so wide tables scroll on phones instead of the page. */
  .tm-table-wrap{ overflow-x:auto; border:1px solid var(--tm-border-elevated); border-radius:var(--tm-radius-card); background:var(--tm-surface) }
  .tm-table-wrap > .tm-table th, .tm-table-wrap > .tm-table td{ padding:.7rem .9rem; white-space:nowrap }
  .tm-table-wrap > .tm-table thead th{ background:var(--tm-surface-2) }
  /* Amount columns: the header aligns with its numbers. Links in a cell
     (the record title) read as the row's name, not as running text. */
  .tm-table-wrap > .tm-table th.tm-amount{ text-align:end }
  .tm-table-wrap > .tm-table a{ color:var(--tm-text-1); font-weight:700; text-decoration:none }
  .tm-table-wrap > .tm-table a:hover{ color:var(--tm-accent-text); text-decoration:underline }
  /* A row whose selection checkbox is checked gets an accent edge at its
     start, the same signal as the current navigation item. Deliberately no
     fill: under translucent badge fills (dark mode) an accent-soft row
     pushed badge text below 4.5 in the PIA world (measured 3.95). */
  .tm-table-wrap > .tm-table tbody tr:has(input[type="checkbox"]:checked) td:first-child{
    box-shadow:inset 3px 0 0 0 var(--tm-accent) }
  [dir="rtl"] .tm-table-wrap > .tm-table tbody tr:has(input[type="checkbox"]:checked) td:first-child{
    box-shadow:inset -3px 0 0 0 var(--tm-accent) }

  /* =========================================================
     7. Panels: card header, empty state, skeleton, locked preview
     ========================================================= */
  .tm-panel{ display:flex; flex-direction:column; gap:1rem; padding:clamp(1rem, 2.5vw, 1.4rem);
    border:1px solid var(--tm-border-elevated); border-radius:var(--tm-radius-card); background:var(--tm-surface) }
  .tm-panel__head{ display:flex; flex-wrap:wrap; justify-content:space-between; align-items:center; gap:.75rem }
  .tm-panel__title{ margin:0; color:var(--tm-text-1); font-size:1.05rem; font-weight:800 }
  /* The gap spaces the parts; a browser margin on top would double it. */
  .tm-panel p, .tm-locked__card p{ margin:0 }

  /* Empty state (Atlas). A dashed frame says "nothing here yet", not "broken". */
  .tm-empty{ display:flex; flex-direction:column; align-items:center; gap:.75rem; padding:clamp(1.5rem, 5vw, 3rem) 1.25rem;
    border:1.5px dashed var(--tm-border-strong); border-radius:var(--tm-radius-card); background:var(--tm-surface-2);
    color:var(--tm-text-2); text-align:center }
  .tm-empty h3{ margin:0; color:var(--tm-text-1); font-size:1.1rem; font-weight:800 }
  .tm-empty p{ margin:0; max-width:32rem; line-height:1.6 }
  /* stroke-width: an icon drawn for 24px gets 6px strokes at 4.5rem with
     the .tm-icon width of 2; 1.25 keeps the line art light. */
  .tm-empty__art{ width:4.5rem; height:4.5rem; color:var(--tm-accent-text); stroke-width:1.25 }
  /* Empty state on the stage: glass instead of the light surface. */
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-glass-panel) .tm-empty{
    border-color:color-mix(in srgb, var(--tm-stage-border) 80%, transparent);
    background:color-mix(in srgb, var(--tm-stage-2) 60%, transparent); color:var(--tm-stage-text-2) }
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-glass-panel) .tm-empty h3{ color:var(--tm-stage-ink) }
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-glass-panel) .tm-empty__art{ color:var(--tm-stage-accent) }

  /* Skeleton while loading. Static without motion; it shimmers with motion.
     Pair it with aria-busy on the region, the skeleton itself is aria-hidden. */
  .tm-skeleton{ display:block; width:var(--tmx-value, auto); height:var(--tmx-height, 1em); border-radius:var(--tm-radius-marker);
    background:linear-gradient(90deg, var(--tm-surface-3) 0%, var(--tm-hover) 50%, var(--tm-surface-3) 100%);
    background-size:200% 100% }

  /* "Visible but locked" preview (PIA premium). Content stays in the DOM but
     inert; the overlay card explains the lock. */
  .tm-locked{ position:relative; isolation:isolate; display:grid }
  .tm-locked > *{ grid-area:1 / 1 }
  .tm-locked__content{ filter:blur(5px) saturate(.75); opacity:.55; pointer-events:none; user-select:none }
  .tm-locked__card{ z-index:2; align-self:center; justify-self:center; max-width:24rem; padding:1.4rem;
    border:1px solid var(--tm-border-elevated); border-radius:var(--tm-radius-card);
    background:var(--tm-surface); box-shadow:var(--tm-shadow-overlay); text-align:center }

  /* =========================================================
     8. Forms
     ========================================================= */
  .tm-field{ display:flex; flex-direction:column; gap:.4rem; min-width:0 }
  .tm-label{ color:var(--tm-text-1); font-size:var(--tm-size-label); font-weight:700 }
  .tm-label__optional{ color:var(--tm-text-3); font-weight:600 }
  /* Inputs carry border-elevated: an input is a user interface component in
     the sense of WCAG 1.4.11 and its edge needs 3.0 against its neighbours,
     the same reason .tm-btn uses it. 44px minimum height for touch (PIA). */
  .tm-input{ width:100%; min-height:2.75rem; padding:.6rem .85rem;
    border:1px solid var(--tm-border-elevated); border-radius:var(--tm-radius-box);
    background:var(--tm-field); color:var(--tm-text-1); font:inherit;
    transition:border-color var(--tm-dur-fast) var(--tm-ease), box-shadow var(--tm-dur-fast) var(--tm-ease) }
  .tm-input::placeholder{ color:var(--tm-text-3); opacity:1 }
  .tm-input:hover{ border-color:var(--tm-accent) }
  .tm-input:focus-visible{ border-color:var(--tm-accent);
    box-shadow:0 0 0 3px color-mix(in srgb, var(--tm-accent) 22%, transparent) }
  .tm-input[aria-invalid="true"]{ border-color:var(--tm-crit) }
  .tm-input:disabled{ cursor:not-allowed; opacity:.6 }
  textarea.tm-input{ min-height:7rem; resize:vertical; line-height:1.55 }
  select.tm-input{ cursor:pointer }
  .tm-hint{ color:var(--tm-text-3); font-size:var(--tm-size-label) }
  .tm-error{ display:flex; align-items:center; gap:.4rem; color:var(--tm-crit-ink); font-size:var(--tm-size-label); font-weight:700 }
  .tm-form-grid{ display:grid; gap:1rem 1.25rem }
  @media (min-width: 48rem){ .tm-form-grid{ grid-template-columns:repeat(2, minmax(0, 1fr)) }
    .tm-form-grid > .tm-field--wide{ grid-column:1 / -1 } }

  /* Labelled divider between two ways to do one thing ("oder"). */
  .tm-divider{ display:flex; align-items:center; gap:.75rem; color:var(--tm-text-2); font-size:var(--tm-size-label); font-weight:700 }
  .tm-divider::before, .tm-divider::after{ content:""; flex:1; height:1px; background:var(--tm-border) }

  .tm-check{ display:inline-flex; align-items:flex-start; gap:.6rem; color:var(--tm-text-2); line-height:1.45; cursor:pointer }
  .tm-check input{ flex:none; width:1.15rem; height:1.15rem; margin-block-start:.1rem; accent-color:var(--tm-accent) }

  /* Switch on a native checkbox with role="switch": the state lives in the
     checked property, so assistive technology reads on and off correctly. */
  .tm-switch{ position:relative; flex:none; width:2.6rem; height:1.5rem; margin:0; appearance:none; cursor:pointer;
    border:1px solid var(--tm-border-elevated); border-radius:var(--tm-radius-pill); background:var(--tm-surface-3);
    transition:background var(--tm-dur-fast) var(--tm-ease), border-color var(--tm-dur-fast) var(--tm-ease) }
  .tm-switch::before{ content:""; position:absolute; inset-block-start:.15rem; inset-inline-start:.15rem; width:1.1rem; height:1.1rem;
    border-radius:50%; background:var(--tm-surface); box-shadow:var(--tm-shadow-sm);
    transition:transform var(--tm-dur-fast) var(--tm-ease) }
  .tm-switch:checked{ border-color:var(--tm-accent); background:var(--tm-accent) }
  .tm-switch:checked::before{ transform:translateX(1.1rem) }
  [dir="rtl"] .tm-switch:checked::before{ transform:translateX(-1.1rem) }

  /* Choice cards (Atlas roles, PIA "Wahl"): a radio or checkbox inside a
     label; the card follows the checked state through :has(). */
  .tm-choice{ display:flex; gap:.75rem; padding:1rem; cursor:pointer;
    border:1px solid var(--tm-border-elevated); border-radius:var(--tm-radius-box); background:var(--tm-surface);
    transition:border-color var(--tm-dur-fast) var(--tm-ease), background var(--tm-dur-fast) var(--tm-ease) }
  .tm-choice:hover{ border-color:var(--tm-accent) }
  .tm-choice:has(input:checked){ border-color:var(--tm-accent); background:var(--tm-accent-soft) }
  .tm-choice input{ flex:none; margin-block-start:.2rem; accent-color:var(--tm-accent) }
  .tm-choice__title{ display:block; color:var(--tm-text-1); font-weight:800 }
  .tm-choice:has(input:checked) .tm-choice__title{ color:var(--tm-accent-soft-ink) }
  .tm-choice__text{ display:block; color:var(--tm-text-2); font-size:var(--tm-size-label); line-height:1.5 }

  /* Search field with a leading icon. */
  .tm-search{ position:relative; display:flex; align-items:center; min-width:min(100%, 16rem) }
  .tm-search .tm-icon{ position:absolute; inset-inline-start:.8rem; color:var(--tm-text-3); pointer-events:none }
  .tm-search .tm-input{ padding-inline-start:2.4rem }

  /* Sticky action bar at the end of long forms. */
  .tm-actionbar{ position:sticky; inset-block-end:0; z-index:20; display:flex; flex-wrap:wrap; justify-content:flex-end;
    align-items:center; gap:.75rem; padding:.85rem clamp(1rem, 3vw, 1.4rem);
    border-block-start:1px solid var(--tm-border); background:var(--tm-glass);
    -webkit-backdrop-filter:blur(12px); backdrop-filter:blur(12px) }
  /* Status text at the start of the bar ("3 selected", "saved 2 min ago");
     the buttons stay at the end. */
  .tm-actionbar__status{ margin-inline-end:auto; color:var(--tm-text-1); font-size:var(--tm-size-label); font-weight:700 }
  /* Floating variant for a selection inside content (list pages): it hovers
     above the rows it acts on instead of reading as one more row. */
  .tm-actionbar--float{ inset-block-end:1rem; border:1px solid var(--tm-border-elevated);
    border-radius:var(--tm-radius-card); box-shadow:var(--tm-shadow-overlay) }

  /* Fields on the stage (search in the top bar). Same reason as the stage
     contexts in section 4: the field roles are made for the page. The edge
     keeps --tm-stage-border, which is checked against the stage. */
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel) .tm-input{
    border-color:var(--tm-stage-border); background:color-mix(in srgb, var(--tm-stage-2) 70%, transparent);
    color:var(--tm-stage-ink) }
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel) .tm-input::placeholder{
    color:var(--tm-stage-text-3) }
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel) .tm-input:is(:hover, :focus-visible){
    border-color:var(--tm-stage-link) }
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-topbar, .tm-sidebar, .tm-footer, .tm-glass-panel) .tm-search .tm-icon{
    color:var(--tm-stage-text-3) }
  .tm-topbar .tm-search{ flex:0 1 26rem }

  /* =========================================================
     9. Navigation inside a page: tabs, segmented control, filter bar,
        pagination
     ========================================================= */

  /* Tabs on role="tablist" / role="tab" / aria-selected. The selected tab is
     an accent pill (Atlas). The application handles arrow keys. */
  .tm-tabs{ display:flex; gap:.25rem; max-width:100%; padding:.3rem; overflow-x:auto;
    border:1px solid var(--tm-border); border-radius:calc(var(--tm-radius-box) + 2px); background:var(--tm-surface-2) }
  .tm-tabs [role="tab"]{ flex:none; display:inline-flex; align-items:center; gap:.45rem; min-height:2.4rem;
    padding:.45rem .95rem; border:0; border-radius:calc(var(--tm-radius-box) - 4px); background:transparent;
    color:var(--tm-text-2); font:inherit; font-weight:700; white-space:nowrap; cursor:pointer;
    transition:background var(--tm-dur-fast) var(--tm-ease), color var(--tm-dur-fast) var(--tm-ease), box-shadow var(--tm-dur-fast) var(--tm-ease) }
  .tm-tabs [role="tab"]:hover{ color:var(--tm-text-1); background:var(--tm-hover) }
  .tm-tabs [role="tab"][aria-selected="true"]{ background:var(--tm-accent); color:var(--tm-accent-ink);
    box-shadow:0 6px 18px color-mix(in srgb, var(--tm-accent) 35%, transparent) }

  /* Segmented control on radio inputs: one choice from a few. */
  .tm-segmented{ display:inline-flex; gap:.2rem; padding:.25rem; border:1px solid var(--tm-border);
    border-radius:var(--tm-radius-pill); background:var(--tm-surface-2) }
  .tm-segmented label{ position:relative; display:inline-flex; align-items:center; min-height:2.1rem; padding:.35rem .9rem;
    border-radius:var(--tm-radius-pill); color:var(--tm-text-3); font-size:var(--tm-size-label); font-weight:700; cursor:pointer }
  .tm-segmented input{ position:absolute; opacity:0; inset:0; margin:0; cursor:pointer }
  .tm-segmented label:has(input:checked){ background:var(--tm-accent-soft); color:var(--tm-accent-soft-ink) }
  .tm-segmented label:has(input:focus-visible){
    outline:var(--tm-focus-width) solid var(--tm-focus-color, var(--tm-focus-color-default, var(--tm-accent-text)));
    outline-offset:var(--tm-focus-offset) }

  .tm-filterbar{ display:flex; flex-wrap:wrap; align-items:center; gap:.65rem; padding:.75rem;
    border:1px solid var(--tm-border); border-radius:var(--tm-radius-card); background:var(--tm-surface) }
  .tm-filterbar .tm-search{ flex:1 1 16rem }

  .tm-chip--toggle{ cursor:pointer; font:inherit; font-size:var(--tm-size-label) }
  .tm-chip--toggle[aria-pressed="true"]{ border-color:var(--tm-accent); background:var(--tm-accent-soft); color:var(--tm-accent-soft-ink) }

  .tm-pagination{ display:flex; flex-wrap:wrap; justify-content:space-between; align-items:center; gap:.75rem;
    color:var(--tm-text-3); font-size:var(--tm-size-label) }
  .tm-pagination__pages{ display:flex; gap:.25rem }
  .tm-pagination__pages a, .tm-pagination__pages span{ display:inline-grid; place-items:center; min-width:2.25rem; height:2.25rem;
    padding-inline:.5rem; border-radius:var(--tm-radius-tile); color:var(--tm-text-2); font-weight:700; text-decoration:none }
  .tm-pagination__pages a:hover{ background:var(--tm-hover) }
  .tm-pagination__pages [aria-current="page"]{ background:var(--tm-accent); color:var(--tm-accent-ink) }

  /* =========================================================
     10. Overlays: dialog, drawer, toast
     ========================================================= */

  /* Native <dialog> with showModal(): focus trap, Escape and inert background
     come from the browser. */
  .tm-dialog{ width:min(32rem, calc(100vw - 2rem)); max-height:calc(100dvh - 2rem); padding:0;
    border:1px solid var(--tm-border-elevated); border-radius:var(--tm-radius-card);
    background:var(--tm-surface); color:var(--tm-text-2); box-shadow:var(--tm-shadow-overlay) }
  .tm-dialog::backdrop{ background:var(--tm-scrim); -webkit-backdrop-filter:blur(4px); backdrop-filter:blur(4px) }
  .tm-dialog__head{ display:flex; justify-content:space-between; align-items:center; gap:1rem; padding:1.1rem 1.25rem .4rem }
  .tm-dialog__head h2{ margin:0; color:var(--tm-text-1); font-size:1.15rem; font-weight:800 }
  .tm-dialog__body{ padding:.4rem 1.25rem 1rem; line-height:1.6 }
  .tm-dialog__foot{ display:flex; flex-wrap:wrap; justify-content:flex-end; gap:.6rem; padding:1rem 1.25rem;
    border-block-start:1px solid var(--tm-border); background:var(--tm-surface-2);
    border-end-start-radius:inherit; border-end-end-radius:inherit }
  .tm-dialog--drawer{ width:min(28rem, 100vw); height:100dvh; max-height:none; margin:0; margin-inline-start:auto;
    border-radius:0; border-block:0; border-inline-end:0 }
  /* Open drawer: the body takes the height and scrolls, the foot stays at
     the bottom edge. Only with [open], or the closed dialog would show. */
  .tm-dialog--drawer[open]{ display:flex; flex-direction:column }
  .tm-dialog--drawer > .tm-dialog__body{ flex:1; overflow-y:auto }

  .tm-toast-region{ position:fixed; inset-block-end:1.25rem; inset-inline:1rem; z-index:90; display:flex; flex-direction:column;
    align-items:center; gap:.6rem; pointer-events:none }
  .tm-toast{ --tmx-edge:var(--tm-stage-accent);
    display:flex; align-items:center; gap:.75rem; max-width:min(30rem, 100%); padding:.75rem 1rem;
    border-radius:var(--tm-radius-box); background:var(--tm-stage); color:var(--tm-stage-ink);
    box-shadow:var(--tm-shadow-overlay), inset 3px 0 0 0 var(--tmx-edge);
    pointer-events:auto; font-weight:600 }
  [dir="rtl"] .tm-toast{ box-shadow:var(--tm-shadow-overlay), inset -3px 0 0 0 var(--tmx-edge) }
  .tm-toast--ok{ --tmx-edge:var(--tm-ok) }
  .tm-toast--warn{ --tmx-edge:var(--tm-warn) }
  .tm-toast--crit{ --tmx-edge:var(--tm-crit) }

  /* =========================================================
     10b. Charts and mobile navigation
     ========================================================= */

  /* Navigation links in the top bar (marketing header, Atlas top bar). */
  .tm-topnav{ display:flex; flex-wrap:wrap; align-items:center; gap:.25rem; margin:0; padding:0; list-style:none }
  .tm-topnav a{ display:inline-flex; align-items:center; min-height:2.25rem; padding:.35rem .75rem;
    border-radius:var(--tm-radius-pill); color:var(--tm-stage-text-2); font-size:var(--tm-size-label); font-weight:700;
    text-decoration:none; transition:color var(--tm-dur-fast) var(--tm-ease), background var(--tm-dur-fast) var(--tm-ease) }
  .tm-topnav a:hover{ color:var(--tm-stage-ink); background:color-mix(in srgb, var(--tm-stage-3) 55%, transparent) }
  .tm-topnav a[aria-current="page"]{ color:var(--tm-stage-ink); box-shadow:inset 0 -2px 0 0 var(--tm-stage-accent) }
  @media (max-width: 56rem){ .tm-topnav--collapse{ display:none } }
  /* Paired with a .tm-tabbar: hidden below 48rem, where the tab bar carries
     the same links, shown from 48rem, where the tab bar hides. */
  @media (max-width: 47.99rem){ .tm-topnav--tabbar{ display:none } }

  /* Heat map grid: a label column plus --tmx-cols cells per row. */
  .tm-heatmap{ display:grid; grid-template-columns:minmax(5.5rem, auto) repeat(var(--tmx-cols, 4), minmax(0, 1fr));
    gap:.35rem; align-items:center; font-size:var(--tm-size-label) }
  .tm-heatmap > .tm-heat{ width:100%; min-height:1.6rem }
  .tm-heatmap__label{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
  .tm-heat-legend{ display:flex; flex-wrap:wrap; align-items:center; gap:.4rem .9rem; font-size:var(--tm-size-label) }
  .tm-heat-legend .tm-heat{ min-width:1rem; min-height:1rem; vertical-align:middle; margin-inline-end:.35rem }

  /* Column chart. Each child span gets its height through --tmx-value. Give
     the chart role="img" and an aria-label that states the numbers. */
  .tm-columns{ display:flex; align-items:flex-end; gap:clamp(.25rem, 1vw, .5rem); height:var(--tmx-height, 8rem) }
  .tm-columns > span{ flex:1; height:var(--tmx-value, 50%); min-height:4px; border-radius:6px 6px 2px 2px;
    background:linear-gradient(180deg, var(--tm-brand-2), color-mix(in srgb, var(--tm-brand-2) 45%, var(--tm-brand-3))) }
  .tm-columns > span:is(.is-current, [data-current="true"]){ background:linear-gradient(180deg, var(--tm-brand-3), color-mix(in srgb, var(--tm-brand-3) 60%, var(--tm-brand-2))) }
  .tm-columns-axis{ display:flex; gap:clamp(.25rem, 1vw, .5rem); margin-block-start:.4rem; color:var(--tm-text-3); font-size:var(--tm-size-mono) }
  .tm-columns-axis > span{ flex:1; text-align:center }
  :where(.tm-stage, .tm-stage-2, .tm-stage-3, .tm-glass-panel) .tm-columns-axis{ color:var(--tm-stage-text-3) }

  /* Sparkline in an inline SVG: <svg class="tm-sparkline" viewBox="0 0 100 30">
     with a <path class="tm-sparkline__area"> and a <polyline>. */
  .tm-sparkline{ display:block; width:100%; height:2.5rem; overflow:visible }
  .tm-sparkline polyline, .tm-sparkline path:not(.tm-sparkline__area){ fill:none; stroke:var(--tm-accent); stroke-width:2;
    stroke-linecap:round; stroke-linejoin:round; vector-effect:non-scaling-stroke }
  .tm-sparkline__area{ fill:color-mix(in srgb, var(--tm-accent) 14%, transparent); stroke:none }
  .tm-kpi--glass .tm-sparkline polyline{ stroke:var(--tm-stage-link) }
  .tm-kpi--glass .tm-sparkline__area{ fill:color-mix(in srgb, var(--tm-stage-border) 30%, transparent) }

  /* Bottom tab bar for phone-first applications (PIA parents app). Fixed,
     respects the safe area of notched phones, hidden from 48rem up where the
     sidebar or top bar takes over. */
  .tm-tabbar{ position:fixed; inset-inline:0; inset-block-end:0; z-index:50; display:flex; justify-content:space-around;
    padding:.35rem .5rem calc(.35rem + env(safe-area-inset-bottom));
    border-block-start:1px solid var(--tm-border); background:var(--tm-glass);
    -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px) }
  .tm-tabbar a{ display:flex; flex:1; flex-direction:column; align-items:center; gap:.15rem; max-width:6rem; padding:.35rem .25rem;
    border-radius:var(--tm-radius-tile); color:var(--tm-text-3); font-size:.7rem; font-weight:700; text-decoration:none }
  .tm-tabbar a[aria-current="page"]{ color:var(--tm-accent-text) }
  .tm-tabbar a[aria-current="page"] .tm-icon{ stroke-width:2.4 }
  .tm-tabbar-spacer{ height:calc(4.5rem + env(safe-area-inset-bottom)) }
  @media (min-width: 48rem){ .tm-tabbar, .tm-tabbar-spacer{ display:none } }

  /* =========================================================
     11. Motion. Everything below runs only when the user allows motion.
     ========================================================= */
  @media (prefers-reduced-motion: no-preference){
    .tm-topbar::after{ animation:tm-flow 8s linear infinite }
    .tm-glow{ animation:tm-drift 18s var(--tm-ease) infinite alternate }
    .tm-aurora{ animation:tm-drift 22s var(--tm-ease) infinite alternate }
    .tm-gradient-text, .tm-gradient-text--stage{ animation:tm-sheen 6s var(--tm-ease) infinite alternate }
    .tm-cta::before{ animation:tm-shine 900ms var(--tm-ease) 620ms 1 forwards }
    .tm-cta--halo{ animation:tm-halo 2.6s var(--tm-ease) infinite }
    .tm-pulse{ animation:tm-pulse 2.4s var(--tm-ease) infinite }
    .tm-skeleton{ animation:tm-shimmer 1.4s linear infinite }
    .tm-marquee{ -webkit-mask-image:linear-gradient(90deg, transparent, black 10%, black 90%, transparent);
      mask-image:linear-gradient(90deg, transparent, black 10%, black 90%, transparent) }
    .tm-marquee__track{ flex-wrap:nowrap; max-width:none; animation:tm-marquee 42s linear infinite }
    .tm-marquee__item[aria-hidden="true"]{ display:inline-flex }
    .tm-marquee:hover .tm-marquee__track{ animation-play-state:paused }
    .tm-sidebar{ transition:transform var(--tm-dur-slow) var(--tm-ease), visibility var(--tm-dur-slow) }
    .tm-dialog[open]{ animation:tm-rise var(--tm-dur-slow) var(--tm-ease) both }
    .tm-toast{ animation:tm-rise var(--tm-dur-slow) var(--tm-ease) both }

    /* Entrance. Children of .tm-stagger rise one after another; set --tmx-i
       on a child to override its position in the sequence. */
    .tm-rise{ animation:tm-rise calc(var(--tm-dur-slow) * 1.5) var(--tm-ease) backwards }
    .tm-stagger > *{ animation:tm-rise calc(var(--tm-dur-slow) * 1.5) var(--tm-ease) backwards;
      animation-delay:calc(min(var(--tmx-i, 0), 8) * 70ms) }
    .tm-stagger > :nth-child(2){ --tmx-i:1 } .tm-stagger > :nth-child(3){ --tmx-i:2 }
    .tm-stagger > :nth-child(4){ --tmx-i:3 } .tm-stagger > :nth-child(5){ --tmx-i:4 }
    .tm-stagger > :nth-child(6){ --tmx-i:5 } .tm-stagger > :nth-child(7){ --tmx-i:6 }
    .tm-stagger > :nth-child(n+8){ --tmx-i:7 }

    /* Scroll reveal without JavaScript where the browser supports
       scroll-driven animations; elsewhere the element is simply visible. */
    @supports (animation-timeline: view()){
      .tm-reveal{ animation:tm-reveal linear both; animation-timeline:view(); animation-range:entry 0% entry 60% }
    }
  }
  @keyframes tm-flow{ to{ background-position:-200% 0 } }
  @keyframes tm-drift{ from{ transform:translate3d(0, 0, 0) scale(1) } to{ transform:translate3d(-4%, 3%, 0) scale(1.08) } }
  @keyframes tm-sheen{ from{ background-position:0 0 } to{ background-position:100% 0 } }
  @keyframes tm-shine{ to{ transform:translateX(130%) } }
  @keyframes tm-halo{ 0%{ box-shadow:0 14px 40px color-mix(in srgb, var(--tm-accent) 45%, transparent), 0 0 0 0 color-mix(in srgb, var(--tm-accent) 40%, transparent) }
    100%{ box-shadow:0 14px 40px color-mix(in srgb, var(--tm-accent) 45%, transparent), 0 0 0 18px transparent } }
  @keyframes tm-pulse{ 0%, 100%{ opacity:1; transform:scale(1) } 50%{ opacity:.35; transform:scale(.78) } }
  @keyframes tm-shimmer{ from{ background-position:200% 0 } to{ background-position:-200% 0 } }
  @keyframes tm-marquee{ to{ transform:translateX(-50%) } }
  @keyframes tm-rise{ from{ opacity:0; transform:translateY(12px) } to{ opacity:1; transform:none } }
  @keyframes tm-reveal{ from{ opacity:0; transform:translateY(32px) scale(.98) } to{ opacity:1; transform:none } }

  /* Forced colours (Windows contrast themes): glass and gradients disappear,
     so give every surface a system border and let text use system colours. */
  @media (forced-colors: active){
    .tm-gradient-text, .tm-gradient-text--stage{ -webkit-text-fill-color:currentColor; background:none }
    .tm-glass-panel, .tm-kpi, .tm-panel, .tm-toast, .tm-step, .tm-topbar{ border:1px solid CanvasText }
    .tm-glow, .tm-aurora, .tm-dotfloor{ display:none }
    .tm-nav__item[aria-current="page"]{ outline:2px solid Highlight }
    .tm-tabs [role="tab"][aria-selected="true"], .tm-pagination__pages [aria-current="page"]{ outline:2px solid Highlight }
  }
}
