/* ============================================================
   ARECH Megamenu block — front-end styles.

   Port of the NAV system in
     prototypes/navbar-explore-2026-05-19/nav-4-megamenu-full.html
   re-tokenized to the theme tokens (main.css :root) and corrected to the
   responsive standard (responsive_manual_en_0.1: min-width ONLY, no
   max-width media queries; canonical container box).

   ALL rules are scoped under `.arech-megamenu` so nothing leaks into the
   theme. The bar links sit inline next to the theme logo (the theme <header>
   provides the sticky surface + blur); only the panels / scrim / overlay are
   position:fixed and anchored at top:var(--header-height).
   ============================================================ */

.arech-megamenu {
    /* slots inline inside the theme's <header> flex row */
    display: contents;
}

/* -------- DESKTOP LINKS -------- */
.arech-megamenu .arech-mm__links {
    display: none;
    flex: 1;
    justify-content: center;
    align-items: center;
    /* Restore the prototype invariant (nav above scrim). The trigger cluster
       shares the .site-header stacking context with the scrim/panel; without a
       local z-index the triggers (z-index:auto) fall under the scrim (z-98).
       position:relative + z-index here lift the triggers above the scrim so a
       stationary cursor on a trigger is never covered. Secondary hardening to
       the scrim-top fix above; together they make the flicker structurally
       impossible. Scoped to the block — `.site-header` (theme-owned) untouched. */
    position: relative;
    z-index: 101;
}
/* Desktop nav reveals at MD/LG 768 to match the prototype (proto L60): tablet
   portrait shows the inline nav + 3-col mega; the 5-col step lands at 1024. */
@media (min-width: 768px) {
    .arech-megamenu .arech-mm__links { display: flex; }
}
.arech-megamenu .arech-mm__links ul {
    display: flex;
    gap: 4px;
    list-style: none;
    margin: 0;
    padding: 0;
    align-items: center;
}
.arech-megamenu .arech-mm__links > ul > li { position: static; } /* mega spans full width */

.arech-megamenu .arech-mm__link {
    position: relative;
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 12px 16px;
    font-family: var(--font-body);
    font-size: 15px;
    font-weight: 500;
    color: var(--off-white);
    text-decoration: none;
    background: transparent;
    border: 0;
    cursor: pointer;
    transition: color var(--motion-fast) var(--ease-standard);
}
.arech-megamenu .arech-mm__link:hover,
.arech-megamenu .arech-mm__link:focus-visible { color: var(--orange); }
.arech-megamenu .arech-mm__link:focus-visible {
    outline: 2px solid var(--orange);
    outline-offset: 2px;
}
.arech-megamenu .arech-mm__link.is-active { color: var(--orange); }
.arech-megamenu .arech-mm__link.is-active:hover,
.arech-megamenu .arech-mm__link.is-active:focus-visible { color: var(--off-white); }
.arech-megamenu .arech-mm__link[aria-expanded="true"] { color: var(--orange); }
.arech-megamenu .arech-mm__link[aria-expanded="true"]:hover,
.arech-megamenu .arech-mm__link[aria-expanded="true"]:focus-visible { color: var(--off-white); }

.arech-megamenu .arech-mm__chev {
    display: inline-block;
    width: 0;
    height: 0;
    margin-left: 6px;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-top: 6px solid currentColor;
    transition: transform var(--motion-fast) var(--ease-standard);
}
.arech-megamenu .arech-mm__link[aria-expanded="true"] .arech-mm__chev { transform: rotate(180deg); }

/* -------- CTA + BURGER -------- */
.arech-megamenu .arech-mm__cta-wrap {
    display: flex;
    align-items: center;
    gap: 12px;
    justify-self: end;
}
.arech-megamenu .arech-mm__cta {
    display: none;
    align-items: center;
    min-height: 44px;
    padding: 10px 20px;
    background: var(--orange);
    color: var(--white);
    font-family: var(--font-mono);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    text-decoration: none;
    border-radius: var(--radius-btn);
    transition: background var(--motion-normal) var(--ease-standard),
                transform var(--motion-normal) var(--ease-standard),
                box-shadow var(--motion-normal) var(--ease-standard);
}
@media (min-width: 768px) {
    .arech-megamenu .arech-mm__cta { display: inline-flex; }
}
.arech-megamenu .arech-mm__cta:hover,
.arech-megamenu .arech-mm__cta:focus-visible {
    background: var(--orange-bright);
    transform: translateY(-2px);
    box-shadow: 0 12px 28px color-mix(in oklch, var(--orange) 35%, transparent);
}

.arech-megamenu .arech-mm__burger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: var(--radius-btn);
    cursor: pointer;
    transition: border-color var(--motion-fast) var(--ease-standard);
}
.arech-megamenu .arech-mm__burger:hover,
.arech-megamenu .arech-mm__burger:focus-visible { border-color: var(--orange); }
@media (min-width: 768px) {
    .arech-megamenu .arech-mm__burger { display: none; }
}
.arech-megamenu .arech-mm__burger span {
    display: block;
    width: 18px;
    height: 2px;
    background: var(--off-white);
    position: relative;
}
.arech-megamenu .arech-mm__burger span::before,
.arech-megamenu .arech-mm__burger span::after {
    content: '';
    position: absolute;
    left: 0;
    width: 18px;
    height: 2px;
    background: var(--off-white);
}
.arech-megamenu .arech-mm__burger span::before { top: -6px; }
.arech-megamenu .arech-mm__burger span::after { top: 6px; }
.arech-megamenu .arech-mm__burger[aria-expanded="true"] span { background: transparent; }
.arech-megamenu .arech-mm__burger[aria-expanded="true"] span::before { top: 0; transform: rotate(45deg); }
.arech-megamenu .arech-mm__burger[aria-expanded="true"] span::after { top: 0; transform: rotate(-45deg); }

/* -------- MEGA PANELS (full-width, fixed) -------- */
.arech-megamenu .arech-mm__panel {
    position: fixed;
    top: var(--header-height);
    left: 0;
    right: 0;
    z-index: 99;
    background: color-mix(in oklch, var(--dark) 97%, transparent);
    backdrop-filter: blur(20px) saturate(1.4);
    -webkit-backdrop-filter: blur(20px) saturate(1.4);
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    opacity: 0;
    transform: translateY(-6px);
    pointer-events: none;
    transition: opacity var(--motion-normal) var(--ease-decelerate),
                transform var(--motion-normal) var(--ease-decelerate);
}
.arech-megamenu .arech-mm__panel.is-open {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}
/* Canonical container box (S72): gutter on the band, inner caps at --container. */
.arech-megamenu .arech-mm__panel-inner {
    max-width: var(--container);
    margin-inline: auto;
    padding-block: var(--space-7) var(--space-8);
    padding-inline: var(--container-px);
}
.arech-megamenu .arech-mm__eyebrow {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--muted-accessible);
    margin-bottom: var(--space-5);
    display: flex;
    align-items: center;
    gap: 12px;
}
.arech-megamenu .arech-mm__eyebrow::before {
    content: '';
    width: 24px;
    height: 1px;
    background: var(--orange);
}
.arech-megamenu .arech-mm__empty {
    font-family: var(--font-body);
    font-size: 14px;
    color: var(--light);
}

/* Products grid — mobile-first min-width steps (prototype used max-width:1100px;
   converted: 1col base → 3col at >=768 → 5col at >=1024 per task spec). */
.arech-megamenu .arech-mm__products-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-4);
}
@media (min-width: 768px) {
    .arech-megamenu .arech-mm__products-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 1024px) {
    .arech-megamenu .arech-mm__products-grid { grid-template-columns: repeat(5, 1fr); }
}

.arech-megamenu .arech-mm__card {
    display: flex;
    flex-direction: column;
    padding: 20px;
    background: var(--dark-2);
    border: 1px solid rgba(255, 255, 255, 0.05);
    border-radius: var(--radius-btn);
    text-decoration: none;
    color: inherit;
    transition: background var(--motion-fast) var(--ease-standard),
                border-color var(--motion-fast) var(--ease-standard),
                transform var(--motion-fast) var(--ease-standard);
}
.arech-megamenu .arech-mm__card:hover,
.arech-megamenu .arech-mm__card:focus-visible {
    background: var(--dark-3);
    border-color: var(--orange);
    transform: translateY(-2px);
}
.arech-megamenu .arech-mm__card:focus-visible {
    outline: 2px solid var(--orange);
    outline-offset: 2px;
}
.arech-megamenu .arech-mm__card-img {
    aspect-ratio: 16 / 10;
    background: var(--dark-4);
    border: 1px dashed color-mix(in oklch, var(--orange) 40%, transparent);
    border-radius: var(--radius-btn);
    margin-bottom: var(--space-4);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.15em;
    color: var(--muted-accessible);
    text-transform: uppercase;
}
.arech-megamenu .arech-mm__card-img--photo {
    border-style: solid;
    border-color: rgba(255, 255, 255, 0.05);
    /* Transparent: product photos are transparent PNG/WebP, so they sit on the
       mega panel's dark background, not inside a filled box. */
    background: transparent;
}
.arech-megamenu .arech-mm__card-img img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}
.arech-megamenu .arech-mm__card-title {
    font-family: var(--font-headline);
    font-weight: 600;
    font-size: 18px;
    color: var(--off-white);
    margin-bottom: 6px;
}
.arech-megamenu .arech-mm__card-body {
    font-family: var(--font-body);
    font-size: 13px;
    line-height: 1.5;
    color: var(--light);
}

/* About grid — same min-width step strategy. */
.arech-megamenu .arech-mm__about-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-5);
}
@media (min-width: 768px) {
    .arech-megamenu .arech-mm__about-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 1024px) {
    .arech-megamenu .arech-mm__about-grid { grid-template-columns: repeat(5, 1fr); }
}
.arech-megamenu .arech-mm__about-link {
    display: flex;
    flex-direction: column;
    padding: 16px 12px;
    text-decoration: none;
    color: inherit;
    border-left: 2px solid transparent;
    transition: border-color var(--motion-fast) var(--ease-standard),
                background var(--motion-fast) var(--ease-standard);
}
.arech-megamenu .arech-mm__about-link:hover,
.arech-megamenu .arech-mm__about-link:focus-visible {
    border-left-color: var(--orange);
    background: color-mix(in oklch, var(--orange) 4%, transparent);
}
.arech-megamenu .arech-mm__about-link:focus-visible {
    outline: 2px solid var(--orange);
    outline-offset: 2px;
}
.arech-megamenu .arech-mm__about-title {
    font-family: var(--font-headline);
    font-weight: 600;
    font-size: 15px;
    color: var(--off-white);
    margin-bottom: 4px;
}
.arech-megamenu .arech-mm__about-desc {
    font-family: var(--font-body);
    font-size: 12px;
    line-height: 1.5;
    color: var(--light);
}

/* -------- SCRIM -------- */
/* ROOT-CAUSE FIX (S74 flicker): the scrim must NEVER cover the nav band.
   Triggers live inside the theme's `.site-header` (a sticky z-index:100 stacking
   context); the scrim + panel are children of that same header, so the scrim's
   local z-index:98 sits ABOVE the triggers (which have z-index:auto). With the
   old `inset:0` the scrim therefore covered the trigger row at y=40, stealing the
   hover off the trigger → mouseleave → close → mouseenter → open → flicker
   (rendered-DOM proof: elementFromPoint(533,40) returned `.arech-mm__scrim`).
   Anchoring the scrim's top at the header height removes the cause: triggers are
   never under the scrim regardless of stacking context, and visually the dim
   correctly begins below the crisp top nav (matches the prototype intent —
   nothing to dim behind a top-anchored nav). Belt-and-braces with the trigger
   z-index lift below (restores the prototype's z-100-nav > z-98-scrim invariant). */
.arech-megamenu .arech-mm__scrim {
    position: fixed;
    inset: var(--header-height) 0 0 0;
    background: rgba(0, 0, 0, 0.4);
    z-index: 98;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--motion-normal) var(--ease-standard);
}
.arech-megamenu .arech-mm__scrim.is-open {
    opacity: 1;
    pointer-events: auto;
}

/* -------- MOBILE OVERLAY -------- */
.arech-megamenu .arech-mm__overlay {
    position: fixed;
    inset: 0;
    z-index: 200;
    background: color-mix(in oklch, var(--dark) 98%, transparent);
    backdrop-filter: blur(30px) saturate(1.4);
    -webkit-backdrop-filter: blur(30px) saturate(1.4);
    display: flex;
    flex-direction: column;
    padding: var(--container-px);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--motion-normal) var(--ease-standard);
    overflow-y: auto;
}
.arech-megamenu .arech-mm__overlay.is-open {
    opacity: 1;
    pointer-events: auto;
}
.arech-megamenu .arech-mm__overlay-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: var(--header-height);
}
.arech-megamenu .arech-mm__overlay-brand {
    display: block;
    height: 32px;
    width: auto;
}
.arech-megamenu .arech-mm__overlay-close {
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: var(--radius-btn);
    cursor: pointer;
    color: var(--off-white);
    font-family: var(--font-mono);
    font-size: 22px;
    line-height: 1;
}
.arech-megamenu .arech-mm__overlay-close:hover,
.arech-megamenu .arech-mm__overlay-close:focus-visible { border-color: var(--orange); }
.arech-megamenu .arech-mm__overlay-links {
    list-style: none;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: var(--space-5) var(--space-2);
}
.arech-megamenu .arech-mm__overlay-link {
    display: block;
    font-family: var(--font-display);
    font-size: clamp(18px, 4.5vw, 21px);
    font-weight: 700;
    color: var(--off-white);
    text-decoration: none;
    padding: 14px 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.arech-megamenu .arech-mm__overlay-link:hover { color: var(--orange); }
.arech-megamenu .arech-mm__overlay-link.is-active { color: var(--orange); }

.arech-megamenu .arech-mm__overlay-acc {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-family: var(--font-display);
    font-size: clamp(18px, 4.5vw, 21px);
    font-weight: 700;
    color: var(--off-white);
    text-decoration: none;
    padding: 14px 0;
    border: 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    background: transparent;
    width: 100%;
    min-height: 44px;
    cursor: pointer;
}
.arech-megamenu .arech-mm__overlay-acc[aria-expanded="true"] { color: var(--orange); }
.arech-megamenu .arech-mm__overlay-acc[aria-expanded="true"] .arech-mm__overlay-acc-icon { transform: rotate(45deg); }
.arech-megamenu .arech-mm__overlay-acc-icon {
    display: inline-block;
    transition: transform var(--motion-fast) var(--ease-standard);
}
.arech-megamenu .arech-mm__overlay-acc-body {
    display: none;
    padding: 12px 12px 16px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.arech-megamenu .arech-mm__overlay-acc-body.is-open {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.arech-megamenu .arech-mm__overlay-acc-body a {
    font-family: var(--font-body);
    font-size: 15px;
    color: var(--light);
    text-decoration: none;
    padding: 8px 0;
    min-height: 44px;
    display: flex;
    align-items: center;
}
.arech-megamenu .arech-mm__overlay-acc-body a:hover { color: var(--orange); }
.arech-megamenu .arech-mm__overlay-cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 56px;
    background: var(--orange);
    color: var(--white);
    font-family: var(--font-mono);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    text-decoration: none;
    border-radius: var(--radius-btn);
    margin-top: var(--space-5);
}
.arech-megamenu .arech-mm__overlay-cta:hover,
.arech-megamenu .arech-mm__overlay-cta:focus-visible { background: var(--orange-bright); }

/* -------- REDUCED MOTION (mandatory) -------- */
@media (prefers-reduced-motion: reduce) {
    .arech-megamenu .arech-mm__panel,
    .arech-megamenu .arech-mm__scrim,
    .arech-megamenu .arech-mm__overlay,
    .arech-megamenu .arech-mm__chev,
    .arech-megamenu .arech-mm__card,
    .arech-megamenu .arech-mm__about-link,
    .arech-megamenu .arech-mm__cta,
    .arech-megamenu .arech-mm__overlay-acc-icon,
    .arech-megamenu .arech-mm__link {
        transition: none !important;
    }
}


/* ============================================================================
   TDM Blocks — design tokens (--tdm-* namespace)

   The package ships its OWN token set so it works standalone on any Concrete
   site. Blocks NEVER hard-code values — they reference var(--tdm-*). The Brand
   Kit dashboard overrides any of these at :root per site, re-skinning every
   block at once.

   Defaults below are seeded from the ARECH design-system-v1 (dark theme) as
   the first consumer; on a new site, set the Brand Kit and these are replaced.
   On ARECH you may also map a token to the live theme variable, e.g.
   `--tdm-color-accent: var(--orange);` so the library tracks the theme.
   ============================================================================ */

:root {
  /* --- Palette -------------------------------------------------------------
     ink = text on surface; surface = block background; accent = CTA/links. */
  --tdm-color-ink:          #F5F4F0;   /* primary text  (ARECH --off-white) */
  --tdm-color-ink-2:        #B0B0BA;   /* secondary     (ARECH --light)     */
  --tdm-color-ink-3:        #6B6B75;   /* tertiary/meta (ARECH --muted)     */
  --tdm-color-surface:      #0D0D0F;   /* base bg       (ARECH --dark)      */
  --tdm-color-surface-2:    #141416;   /* raised bg                          */
  --tdm-color-surface-3:    #1C1C20;   /* card bg                            */
  --tdm-color-accent:       #E8651A;   /* primary accent FILL: chips, dots, arrows, borders, focus glow, accent-as-text on dark (ARECH --orange). UNCHANGED — do NOT repoint. */
  --tdm-color-accent-hover: #FF7A2F;
  --tdm-color-accent-active:#C4510E;
  --tdm-color-on-accent:    #FFFFFF;   /* text ON a button fill (white label) */

  /* --- Primary-button FILL (AA-safe, band-independent) ---------------------
     White (#FFFFFF) on brand orange #E8651A is only 3.33:1 — FAIL for the 15px
     button label (AA needs 4.5:1). The button fill is its OWN accent, separate
     from --tdm-color-accent: ONLY the solid/primary button BACKGROUND points
     here, so chips/dots/arrows/borders/accent-text keep brand orange #E8651A.
     The pair is band-independent (label-vs-fill is internal to the button), so
     one stable fill works on both light and dark bands.
     AA (white #FFFFFF, WCAG2): rest #B0470B = 5.60:1 · hover = 6.80:1 ·
     active = 8.25:1 — all PASS 4.5:1 AA for the 15px label. */
  --tdm-color-btn-fill:        #B0470B;
  --tdm-color-btn-fill-hover:  color-mix(in srgb, var(--tdm-color-btn-fill) 88%, #000);  /* ≈ #9B3E0A, white 6.80:1 PASS */
  --tdm-color-btn-fill-active: color-mix(in srgb, var(--tdm-color-btn-fill) 76%, #000);  /* ≈ #863609, white 8.25:1 PASS */
  /* Accent used AS TEXT (links, eyebrow accents, accent spans). On a DARK band
     this equals --tdm-color-accent (#E8651A reads AA on dark, 5.74:1). The
     base.css [data-band="light"] hook remaps the per-instance --tdmx-accent-text
     to --tdm-color-accent-text-light on a cream band, where #E8651A fails AA
     (2.8–3.0:1). FILL usages keep --tdm-color-accent and never flip. */
  --tdm-color-accent-text:       var(--tdm-color-accent);   /* dark-band: orange */
  --tdm-color-accent-text-light: #B0470B;   /* light-band link/text accent (ARECH --orange-link): 5.65:1 on paper-0, 5.09:1 on paper-1, 4.65:1 on paper-2 = AA body PASS on all creams (colorist-verified, strict WCAG) */

  /* Hairline via color-mix so it tracks ink on any surface. */
  --tdm-hairline: color-mix(in srgb, var(--tdm-color-ink) 14%, transparent);

  /* --- Fonts (self-hosted by the theme; package only references families) - */
  --tdm-font-display:  "Geist", system-ui, sans-serif;
  --tdm-font-headline: "General Sans", Inter, system-ui, sans-serif;
  --tdm-font-body:     "DM Sans", system-ui, sans-serif;
  /* Label / eyebrow / caption voice. DM Mono retired 2026-06-02 site-wide;
     aligned to General Sans to match the theme's --font-mono (S80). */
  --tdm-font-mono:     "General Sans", system-ui, -apple-system, BlinkMacSystemFont, sans-serif;

  /* --- Type scale (fluid clamp; never a fixed px in a media query) -------- */
  --tdm-text-h1:      clamp(48px, 6vw, 88px);
  --tdm-text-h2:      clamp(42px, 5vw, 72px);
  --tdm-text-h3:      clamp(28px, 3vw, 36px);
  --tdm-text-h4:      20px;
  --tdm-text-h5:      16px;
  --tdm-text-body:    16px;
  --tdm-text-body-sm: 14px;
  --tdm-text-eyebrow: 11px;
  --tdm-text-caption: 12px;

  --tdm-weight-display:  700;
  --tdm-weight-headline: 600;
  --tdm-weight-body:     400;

  --tdm-leading-tight: 1.1;
  --tdm-leading-snug:  1.3;
  --tdm-leading-body:  1.65;

  /* --- Spacing scale (4px base — matches ARECH --space-1..11) ------------- */
  --tdm-space-1:  4px;
  --tdm-space-2:  8px;
  --tdm-space-3:  12px;
  --tdm-space-4:  16px;
  --tdm-space-5:  24px;
  --tdm-space-6:  32px;
  --tdm-space-7:  48px;
  --tdm-space-8:  64px;
  --tdm-space-9:  96px;
  --tdm-space-10: 128px;
  --tdm-space-11: 160px;

  /* --- Containers (single uniform container — ARECH responsive manual) ---- */
  --tdm-container:        1200px;  /* caps identically across hero/body/footer */
  --tdm-container-narrow: 720px;
  --tdm-gutter:           16px;    /* steps up at breakpoints in base.css      */

  /* --- Radius (cap 6px on cards per ARECH rule; pill only where allowed) -- */
  --tdm-radius-sm:   4px;
  --tdm-radius-md:   6px;
  --tdm-radius-lg:   12px;
  --tdm-radius-pill: 999px;
  --tdm-radius-btn:  2px;   /* flat action buttons (ARECH FIX-1) */

  /* --- Shadow presets ----------------------------------------------------- */
  --tdm-shadow-sm: 0 1px 2px color-mix(in srgb, #000 30%, transparent);
  --tdm-shadow-md: 0 4px 16px color-mix(in srgb, #000 35%, transparent);
  --tdm-shadow-lg: 0 12px 40px color-mix(in srgb, #000 45%, transparent);

  /* --- Motion (composite-only; respect reduced-motion in base.css) -------- */
  --tdm-dur-fast:  150ms;
  --tdm-dur-base:  250ms;
  --tdm-dur-slow:  400ms;
  --tdm-ease-standard: cubic-bezier(0.22, 0.61, 0.36, 1);
  --tdm-ease-emphatic: cubic-bezier(0.16, 1, 0.3, 1);
}


/* ============================================================================
   TDM Blocks — scoped base layer (.tdm-*)

   Scoped under .tdm-* so nothing leaks into the host theme. Provides:
   - the shared block wrapper that consumes per-instance --tdmx-* variables
     (emitted by CssEmitter into a `.tdm-i-<bID>` rule);
   - the uniform container + responsive gutter (ARECH responsive manual);
   - alignment + background plumbing;
   - the mandatory prefers-reduced-motion branch.

   Per-instance variables (set by CssEmitter, fall back to global --tdm-* tokens):
     --tdmx-pad-top/right/bottom/left, --tdmx-margin-top/bottom, --tdmx-gap,
     --tdmx-text, --tdmx-heading, --tdmx-accent, --tdmx-align, --tdmx-max-width,
     --tdmx-bg, --tdmx-radius, --tdmx-border, --tdmx-shadow, --tdmx-font-heading,
     --tdmx-font-body.
   ============================================================================ */

.tdm-block {
  --tdmx-pad-top:    var(--tdm-space-9);
  --tdmx-pad-right:  0px;
  --tdmx-pad-bottom: var(--tdm-space-9);
  --tdmx-pad-left:   0px;
  --tdmx-margin-top: 0px;
  --tdmx-margin-bottom: 0px;
  --tdmx-gap:        var(--tdm-space-5);
  --tdmx-text:       var(--tdm-color-ink);
  --tdmx-heading:    var(--tdm-color-ink);
  --tdmx-accent:     var(--tdm-color-accent);
  /* Accent split into two roles so a light band can re-tone TEXT without ever
     touching FILLS (S106-class fix). --tdmx-accent = the orange FILL (CTA bg,
     chips, borders, glow) — NEVER flipped. --tdmx-accent-text = accent used as
     TEXT (links, eyebrow accents, accent spans) — defaults to --tdmx-accent so
     it tracks any operator accent override, and is the ONLY accent var the
     [data-band="light"] hook remaps (to --orange-link, AA on cream). */
  --tdmx-accent-text: var(--tdmx-accent);
  --tdmx-align:      left;
  --tdmx-max-width:  var(--tdm-container);
  --tdmx-bg:         transparent;
  --tdmx-radius:     0px;
  --tdmx-border:     0 solid transparent;
  --tdmx-shadow:     none;
  --tdmx-font-heading: var(--tdm-font-headline);
  --tdmx-font-body:    var(--tdm-font-body);

  padding: var(--tdmx-pad-top) var(--tdmx-pad-right) var(--tdmx-pad-bottom) var(--tdmx-pad-left);
  margin-block: var(--tdmx-margin-top) var(--tdmx-margin-bottom);
  /* Band pattern by default, contained mode on demand.
     - 'full' (default, no var emitted): max-width:none + margin-inline:0 =>
       the block fills its parent => FULL-BLEED background (the band).
     - 'contained' (PHP emits --tdmx-block-max:var(--tdm-container) and
       --tdmx-block-mi:auto): the whole block (bg + inner) is capped at 1200
       and centred. The ::before/::after image+overlay are inset:0 of this box,
       so they follow the contained box automatically. */
  /* 'window' bg_width (S129) emits --tdmx-block-w:100vw to break the block out
     to the viewport; default 'auto' = byte-identical (block-level fills parent). */
  width: var(--tdmx-block-w, auto);
  max-width: var(--tdmx-block-max, none);
  margin-inline: var(--tdmx-block-mi, 0);
  background: var(--tdmx-bg);
  color: var(--tdmx-text);
  border: var(--tdmx-border);
  border-radius: var(--tdmx-radius);
  box-shadow: var(--tdmx-shadow);
  font-family: var(--tdmx-font-body);
  position: relative;
  isolation: isolate;
}

/* ── Universal band tone (spec §1b / §1e — cascade layer `base`) ────────────
   ONE place that re-tones EVERY .tdm-block for a light or dark band, replacing
   the per-block [data-band] ink hooks. The view emits data-band only when the
   band resolves to LIGHT (auto-detected light solid bg, or d_band=light) or to
   a FORCED dark (d_band=dark on an unknown image/gradient bg). Default
   (dark-first site, no attribute) is byte-identical to today.

   Flips ONLY the two universal ink vars (--tdmx-heading / --tdmx-text) that
   Family-A blocks consume; accent (orange) is intentionally untouched — it
   reads AA on both cream and dark. Ink-on-light is derived from the surface
   token via color-mix (no magic hex):
     heading = full surface ink (#0D0D0F-equivalent, ~16:1 on cream)
     body    = surface 78%      (mirrors the S106-tuned value, ~7:1 on cream)
   No !important; single attribute-selector specificity so an explicit
   per-instance .tdm-i-<bID> colour rule from CssEmitter still wins.
   The 13 Family-B blocks (which read the never-assigned --tdmx-*-color suffix)
   add their own [data-band="light"] remap in their view.css — see spec §1e. */
.tdm-block[data-band="light"] {
  --tdmx-heading: var(--tdm-color-surface);                               /* #0D0D0F ink */
  --tdmx-text:    color-mix(in srgb, var(--tdm-color-surface) 78%, transparent);
  /* Accent-as-TEXT remap (S106-class fix): #E8651A orange fails AA as text on a
     cream band (2.8–3.0:1). Flip ONLY the text accent to --tdm-color-accent-text-light
     (#B0470B = 5.09:1 on paper-0/1/2 = AA body). FILL accent (--tdmx-accent) is
     untouched, so orange CTA buttons / chips / borders + their white text stay #E8651A. */
  --tdmx-accent-text: var(--tdm-color-accent-text-light);
}
/* Forced dark band (d_band=dark) — restores the dark-first ink explicitly so a
   block placed on a dark image/gradient (where auto-luminance can't read a hex)
   is guaranteed legible-light, even if some ancestor set a light tone. */
.tdm-block[data-band="dark"] {
  --tdmx-heading: var(--tdm-color-ink);                                   /* #F5F4F0 */
  --tdmx-text:    var(--tdm-color-ink-2);                                 /* #B0B0BA */
  --tdmx-accent-text: var(--tdmx-accent);                                 /* orange — AA on dark (5.74:1) */
}

/* Per-handle band-padding fallback for the composite containers (Bug 3c).
   tdm_columns emits design vars change-only, so a container left at its new
   smaller default emits NOTHING and would otherwise fall back to the global
   --tdmx-pad-* (space-9 = 96px). Pin the fallback to the same new default
   (space-6 = 32px) declared in DesignControls::DEFAULT_OVERRIDES so a fresh
   container is a tight band and "default == fallback" stays consistent.
   tdm_section emits all vars (changedOnly=false) so this is a harmless safety
   net for it; an emitted var always wins over this fallback. */
.tdm-columns, .tdm-section {
  --tdmx-pad-top:    var(--tdm-space-6);
  --tdmx-pad-bottom: var(--tdm-space-6);
}

/* Universal background image + overlay via pseudo-elements — driven purely by
   the emitted --tdmx-bg-image / --tdmx-overlay vars, so EVERY block supports a
   background image with overlay without any per-view markup. When the vars are
   unset (no image chosen) they fall back to none/transparent (invisible). */
.tdm-block::after {            /* image layer, behind everything */
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  background-image: var(--tdmx-bg-image, none);
  background-size: cover;
  background-position: center;
  pointer-events: none;
}
.tdm-block::before {           /* overlay, above image, below content */
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--tdmx-overlay, transparent);
  pointer-events: none;
}
/* Legacy explicit layers (section/hero/cta views) — now redundant no-ops. */
.tdm-block__bg, .tdm-block__overlay { display: none; }

/* ── Edit-mode SubArea editability fix (Bug 3b) ────────────────────────────
   On container blocks (tdm_section / tdm_columns) `isolation: isolate` creates
   a stacking context that traps Concrete's in-context edit overlays (move/edit
   grips) of the INNER SubArea blocks beneath the parent block's UI, leaving
   only the parent editable. In edit mode ONLY, drop the isolation on the
   containers and suppress the negative-z background pseudo-elements so the
   inner block handles can stack above. Anonymous (non-edit) output is
   unaffected: front-end pages have no `.ccm-edit-mode` class, so these rules
   never match → render is byte-identical. */
.ccm-edit-mode .tdm-section,
.ccm-edit-mode .tdm-columns,
.ccm-edit-mode .tdm-block__inner .tdm-block { isolation: auto; }   /* S94: un-isolate NESTED children too — S88 reset only the outer containers, so a 2nd isolated child in a column trapped its own edit overlay → only the parent stayed editable */
.ccm-edit-mode .tdm-section::before,
.ccm-edit-mode .tdm-section::after,
.ccm-edit-mode .tdm-columns::before,
.ccm-edit-mode .tdm-columns::after { display: none; }

/* Inner = the container. Single uniform width, responsive gutter. */
.tdm-block__inner {
  width: 100%;
  max-width: var(--tdmx-max-width);
  margin-inline: auto;
  /* 'window' bg_width (S129) emits --tdmx-inner-pad:0 to drop the gutter so the
     content spans the viewport edge-to-edge; default = the responsive gutter. */
  padding-inline: var(--tdmx-inner-pad, var(--tdm-gutter));
  text-align: var(--tdmx-align);
}

/* ── Nesting anti-compounding (Bug 3c) ─────────────────────────────────────
   Real DOM (verified from tdm_section/view.php & tdm_columns/view.php):
     tdm_section:  .tdm-section > .tdm-block__inner > [SubArea] > .tdm-block
     tdm_columns:  .tdm-columns > .tdm-block__inner > .tdm-columns__grid
                     > .tdm-columns__col > [SubArea] > .tdm-block
   A child .tdm-block inside a container's inner/column carries its own space-9
   band by default → paddings add (padding never collapses) → ~192px double band
   when nested. Zero the nested child's vertical band padding; the outer
   container owns the band. (Inline padding-inline is the gutter, suppressed on
   nested inner wrappers below.) These selectors only match the real nesting
   chains — top-level blocks on a normal page are unaffected → byte-identical. */
/* Bug-3c anti-compounding, fixed (S117): zero the nested child's DEFAULT band
   via the per-instance VARIABLE (not a hard longhand), so an operator's
   explicit per-instance pad — emitted at equal specificity on
   `.tdm-block.tdm-i-<bID>` (CssEmitter) and printed after this sheet — still
   wins on source order. A nested block left at default has no per-instance pad
   var, so this 0 holds → single band, no 192px compounding. */
.tdm-block__inner .tdm-block {
  --tdmx-pad-top: 0px;
  --tdmx-pad-bottom: 0px;
  /* S129: custom properties inherit, so a child block inside a 'window'
     (edge-to-edge) parent would otherwise inherit the 100vw breakout vars and
     blow itself out to the viewport. Reset the two harmful breakout vars to
     their defaults on every nested block (byte-identical for non-window trees).
     A nested block that is ITSELF set to 'window' re-emits these on its own
     higher-specificity .tdm-i-<bID> rule, which is printed after this sheet. */
  --tdmx-block-w: auto;
  --tdmx-block-mi: 0;
}
.tdm-block__inner .tdm-block__inner {
  padding-inline: 0;
}

.tdm-block h1, .tdm-block h2, .tdm-block h3,
.tdm-block h4, .tdm-block h5, .tdm-block h6 {
  color: var(--tdmx-heading);
  font-family: var(--tdmx-font-heading);
}

.tdm-block img { max-width: 100%; height: auto; display: block; }

/* Responsive gutter — min-width only (ARECH responsive manual). */
@media (min-width: 680px)  { :root { --tdm-gutter: 20px; } }
@media (min-width: 768px)  { :root { --tdm-gutter: 24px; } }
@media (min-width: 1024px) { :root { --tdm-gutter: 32px; --tdm-container: 1140px; } }
@media (min-width: 1440px) { :root { --tdm-gutter: 40px; --tdm-container: 1200px; } }

/* Shared action buttons (flat radius per ARECH; ≥44px touch target). */
.tdm-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 0 var(--tdm-space-6);
  border-radius: var(--tdm-radius-btn); border: 1px solid transparent;
  font-family: var(--tdm-font-headline); font-weight: var(--tdm-weight-headline);
  font-size: var(--tdm-text-body-sm); text-decoration: none; cursor: pointer;
  transition: background var(--tdm-dur-fast) var(--tdm-ease-standard),
              color var(--tdm-dur-fast) var(--tdm-ease-standard),
              border-color var(--tdm-dur-fast) var(--tdm-ease-standard);
}
/* Primary button FILL points at the AA-safe button-fill token (white label on
   #B0470B = 5.60:1), NOT --tdmx-accent — so chips/dots/borders keep brand orange.
   The fill is band-independent (label-vs-fill is internal). */
.tdm-btn--primary { background: var(--tdm-color-btn-fill); color: var(--tdm-color-on-accent); }
.tdm-btn--primary:hover { background: var(--tdm-color-btn-fill-hover); color: var(--tdm-color-on-accent); }
.tdm-btn--ghost { background: transparent; color: var(--tdmx-text, var(--tdm-color-ink));
  border-color: color-mix(in srgb, var(--tdmx-text, var(--tdm-color-ink)) 35%, transparent); }
.tdm-btn--ghost:hover { border-color: var(--tdmx-accent, var(--tdm-color-accent)); color: var(--tdmx-accent-text, var(--tdm-color-accent)); }
@media (prefers-reduced-motion: reduce) { .tdm-btn { transition: none; } }

/* Hover effects (composite-only). */
.tdm-hover-lift  { transition: transform var(--tdm-dur-base) var(--tdm-ease-standard); }
.tdm-hover-lift:hover  { transform: translateY(-4px); }
.tdm-hover-scale { transition: transform var(--tdm-dur-base) var(--tdm-ease-standard); }
.tdm-hover-scale:hover { transform: scale(1.02); }
.tdm-hover-glow  { transition: box-shadow var(--tdm-dur-base) var(--tdm-ease-standard); }
.tdm-hover-glow:hover  { box-shadow: 0 0 0 1px var(--tdmx-accent), var(--tdm-shadow-md); }

/* Entrance reveal (one per block; JS adds .is-in when in view). */
.tdm-reveal { opacity: 0; transition: opacity var(--tdm-dur-slow) var(--tdm-ease-emphatic),
                                       transform var(--tdm-dur-slow) var(--tdm-ease-emphatic); }
.tdm-reveal.fade-up    { transform: translateY(24px); }
.tdm-reveal.slide-left { transform: translateX(24px); }
.tdm-reveal.is-in      { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .tdm-hover-lift, .tdm-hover-scale, .tdm-hover-glow,
  .tdm-reveal { transition: none !important; transform: none !important; }
  .tdm-reveal { opacity: 1 !important; }
}


/* ARECH Subpage Hero — Editorial (".eh") view.css
   Port of /prototypes/about-hub-v2 `.eh` header. Namespaced `arech-eh`.
   Container law: single uniform --container (1140 -> 1200), NOT --container-wide. */

.arech-eh {
    position: relative;
    background: var(--tdmx-bg, var(--dark));
    min-height: 30vh;
    padding-block: var(--tdmx-pad-top, var(--space-7)) var(--tdmx-pad-bottom, var(--space-7));
    padding-inline: 16px;
    margin-block: var(--tdmx-margin-top, 0px) var(--tdmx-margin-bottom, 0px);
    overflow: hidden;
    isolation: isolate;
}
@media (min-width: 480px)  { .arech-eh { padding-left: 24px; padding-right: 24px; } }
@media (min-width: 768px)  { .arech-eh { padding-left: 32px; padding-right: 32px; min-height: 36vh; } }
@media (min-width: 1024px) { .arech-eh { padding-block: var(--tdmx-pad-top, var(--space-9)) var(--tdmx-pad-bottom, var(--space-7)); padding-inline: 40px; min-height: 40vh; } }

/* --- News/Blog LIST heroes (list_hero template) — EQUAL top/bottom gap ---
   The block's declared default is space-7/space-7, but the generic >=1024 rule
   above uses space-9 on TOP, which made the list heroes asymmetric (96 top /
   48 bottom). Scope a symmetric pair (smaller gap = space-7 / 48px) to the
   .page-listhero wrapper so ONLY /news + /blog change; About (about_detail) keeps
   its own rhythm. justify-content:center makes the column vertically centred too,
   so a short header (no CTAs) sits symmetrically inside the min-height band. */
.page-listhero .arech-eh__inner { justify-content: center; }
@media (min-width: 1024px) {
    .page-listhero .arech-eh {
        padding-block: var(--tdmx-pad-top, var(--space-7)) var(--tdmx-pad-bottom, var(--space-7));
    }
}

/* --- Ambient LED-matrix background (decorative) --- */
.arech-eh__led-bg {
    position: absolute;
    top: 0; right: 0; bottom: 0;
    width: 30%;
    transform: perspective(800px) rotateY(-8deg);
    transform-origin: right center;
    opacity: 0;
    transition: opacity var(--motion-reveal) var(--ease-standard);
    z-index: -3;
    pointer-events: none;
    -webkit-mask-image: linear-gradient(to left, black 50%, transparent 100%), linear-gradient(to top, black 60%, transparent 100%);
            mask-image: linear-gradient(to left, black 50%, transparent 100%), linear-gradient(to top, black 60%, transparent 100%);
    -webkit-mask-composite: source-in;
            mask-composite: intersect;
    display: grid;
    grid-template-columns: repeat(28, 1fr);
    gap: 2px;
    padding: 8px;
}
.arech-eh__led-bg.is-visible { opacity: 0.14; }
@media (min-width: 768px)  { .arech-eh__led-bg { width: 45%; } .arech-eh__led-bg.is-visible { opacity: 0.16; } }
@media (min-width: 1024px) { .arech-eh__led-bg { width: 55%; } .arech-eh__led-bg.is-visible { opacity: 0.20; } }

.arech-eh__led-dot {
    aspect-ratio: 1;
    border-radius: 50%;
    background: var(--orange);
    opacity: var(--base, 0.1);
}
@keyframes arechEhLedFlicker { 0%, 100% { opacity: var(--base, 0.1); } 50% { opacity: var(--peak, 0.7); } }

.arech-eh__led-grid {
    position: absolute;
    inset: -56px 0 0 0;
    z-index: -2;
    pointer-events: none;
    background-image:
        linear-gradient(color-mix(in srgb, var(--orange) 7%, transparent) 1px, transparent 1px),
        linear-gradient(90deg, color-mix(in srgb, var(--orange) 7%, transparent) 1px, transparent 1px);
    background-size: 56px 56px;
}
.arech-eh__warmglow {
    position: absolute; inset: 0; z-index: -1; pointer-events: none;
    background: radial-gradient(ellipse 80% 60% at 60% 40%, color-mix(in srgb, var(--orange) 12%, transparent) 0%, transparent 60%);
}
.arech-eh__bottom-fade {
    position: absolute; inset: 0; z-index: -1; pointer-events: none;
    background: linear-gradient(to bottom, transparent 40%, var(--dark) 100%);
}
.arech-eh::after {
    content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
    background: color-mix(in srgb, #fff 4%, transparent); z-index: 1;
}

/* --- Content --- */
.arech-eh__inner {
    position: relative;
    z-index: 2;
    max-width: var(--tdmx-max-width, var(--container));
    margin-inline: auto;
    text-align: var(--tdmx-align, left);
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    min-height: inherit;
}
.arech-eh__eyebrow {
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--off-white); /* orange fails AA at 11px; keep the orange tick (::before) for the brand accent */
    display: inline-flex;
    align-items: center;
    gap: 12px;
    margin: 0 0 var(--space-4);
}
.arech-eh__eyebrow::before { content: ''; width: 24px; height: 1px; background: var(--tdmx-accent, var(--orange)); }

.arech-eh__h1 {
    font-family: var(--font-headline);
    font-weight: 600;
    font-size: clamp(36px, 5vw, 72px);
    line-height: 1.05;
    letter-spacing: -0.015em;
    color: var(--tdmx-heading, var(--off-white));
    max-width: 22ch;
    margin: 0;
}
.arech-eh__accent { color: var(--tdmx-accent, var(--orange)); }

.arech-eh__lead {
    font-family: var(--font-body);
    font-style: italic;
    font-weight: 300;
    font-size: clamp(17px, 1.6vw, 21px);
    line-height: 1.55;
    color: var(--tdmx-text, var(--light));
    max-width: 60ch;
    margin: var(--space-5) 0 0;
}
.arech-eh__ctas {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-top: var(--space-6);
}

/* --- Entrance (CSS-only, safe: content is visible by default) --- */
@media (prefers-reduced-motion: no-preference) {
    .arech-eh__eyebrow { animation: arechEhFadeUp var(--motion-reveal) var(--ease-decelerate) var(--stagger-1) both; }
    .arech-eh__h1      { animation: arechEhFadeUp var(--motion-reveal) var(--ease-decelerate) var(--stagger-2) both; }
    .arech-eh__lead    { animation: arechEhFadeUp var(--motion-reveal) var(--ease-decelerate) var(--stagger-3) both; }
    .arech-eh__ctas    { animation: arechEhFadeUp var(--motion-reveal) var(--ease-decelerate) var(--stagger-4) both; }
    .arech-eh--led .arech-eh__led-grid.is-drift { animation: arechEhGridMove var(--motion-ambient-fast) var(--ease-linear) infinite; }
    .arech-eh__led-dot { animation: arechEhLedFlicker var(--d, 4s) ease-in-out var(--delay, 0s) infinite; }
}
@keyframes arechEhFadeUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } }
@keyframes arechEhGridMove { from { transform: translateY(0); } to { transform: translateY(56px); } }

@media (prefers-reduced-motion: reduce) {
    .arech-eh__eyebrow, .arech-eh__h1, .arech-eh__lead, .arech-eh__ctas {
        opacity: 1; transform: none; animation: none;
    }
    .arech-eh__led-dot, .arech-eh__led-grid { animation: none; }
}


/* ======================================================================
   TDM News List — the /news index band (filter bar + featured/grid/list +
   empty state + pagination) across 3 templates: classic-grid, magazine-
   masonry, compact-list.

   Owns the DISTINCT .tdm-newsfeed BEM namespace (NOT .tdm-news — that belongs
   to tdm_news_carousel). Renaming the list block's namespace avoids the
   cross-bleed when both blocks render on one page (e.g. the /news index), per
   tdm-band-tone-model-v1 §0/§2 which assigned the list block .tdm-newsfeed.

   Tokens come from the package tokens.css (--tdm-*); Design-controlled props
   consume var(--tdmx-*, <fallback>) so a control left at its default keeps
   this CSS fallback (emit-only-on-change). Block-instance scope (--tdmx-* +
   reveal) is on the outer .tdm-i-<bID>.

   Band tone (tdm-band-tone-model-v1): heading + body ink are flipped by the
   GLOBAL hook (base.css:83-99) via --tdmx-heading / --tdmx-text — NOT re-
   declared here. This block only re-tones the SURFACE + element vars the
   global hook can't reach (card surface, hairline, meta, chip bg+text, dots).

   Responsive (responsive_manual_en_0.1.md): min-width only; XS320 / SM480 /
   MD680 / LG768 / XL1024 / 2XL1440; clamp() type; touch targets >= 44px;
   images max-width:100% height:auto display:block.
   ====================================================================== */

/* ---------- outer block surface (Design layer drives these) ---------- */
.tdm-newsfeed {
  padding-top: var(--tdmx-pad-top, var(--tdm-space-8, 64px));
  padding-bottom: var(--tdmx-pad-bottom, var(--tdm-space-9, 96px));
  padding-left: var(--tdmx-pad-left, 0);
  padding-right: var(--tdmx-pad-right, 0);
  margin-top: var(--tdmx-margin-top, 0);
  margin-bottom: var(--tdmx-margin-bottom, 0);

  /* ---- band-tone local element vars (single place to re-tone per band).
     Defaults track the DARK-first theme + the operator's accent override. ---- */
  --nl-card-bg:   var(--tdm-color-surface-2, #141416);
  --nl-card-bg-2: var(--tdm-color-surface-3, #1C1C20);
  --nl-hairline:  color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 14%, transparent);
  --nl-meta:      #909099; /* AA on dark card #141416: 6.59:1 (ink-3 #6B6B75 was 4.27:1) */
  --nl-chip-bg:   color-mix(in srgb, var(--tdm-color-accent) 14%, transparent);
  --nl-chip-text: var(--tdmx-accent-text, var(--tdm-color-accent, #E8651A));
  /* accent-as-TEXT (eyebrow / "Read full article" / category-label / count /
     reset / featured-eyebrow / active pager): local mirror of --tdmx-accent-text
     so the band re-tone is guaranteed WITHIN this view.css cascade — same
     proven mechanism as --nl-chip-text — instead of depending solely on the
     global base.css [data-band] hook reaching --tdmx-accent-text unimpeded.
     Dark-first default = brand orange (AA on dark, ~5.7:1). */
  --nl-accent-text: var(--tdmx-accent-text, var(--tdm-color-accent, #E8651A));
  /* Category overlay sits ON A PHOTO, so a dark scrim is correct on BOTH bands
     — it does NOT re-tone on light. Tokenised from the dark ink token (was the
     magic rgba(13,13,15,.78)); light ink label stays legible on it on every band. */
  --nl-cat-overlay-bg:   color-mix(in srgb, var(--tdm-color-surface, #0D0D0F) 78%, transparent);
  --nl-cat-overlay-text: var(--tdm-color-ink, #F5F4F0);
  --nl-field-bg:  var(--tdm-color-surface-3, #1C1C20);
  /* card-hover shadow: dark-ink scrim, tokenised (was the magic rgba(0,0,0,.45)) */
  --nl-shadow:    color-mix(in srgb, var(--tdm-color-surface, #0D0D0F) 45%, transparent);
  --nl-dots:      color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 30%, transparent);
  --nl-dots-on:   var(--tdmx-accent, var(--tdm-color-accent, #E8651A));
  /* active pager pill = button FILL + WHITE digit. White on brand #E8651A is only
     3.33:1 (FAIL). The pager pill is a button, so on ALL bands it now uses the
     AA-safe button-fill token → white 5.60:1 PASS (band-independent). */
  --nl-pager-active-bg: var(--tdm-color-btn-fill, #B0470B);
}

/* LIGHT band — light surface + dark ink (global hook flips heading/body) +
   AA-safe accent-as-text. Surfaces use the #000-on-#FFF recipe (no paper token).
   Heading + body ink are flipped by the GLOBAL hook (base.css:83-91) via
   --tdmx-heading / --tdmx-text — NOT re-declared here.

   SPECIFICITY FIX (operator P4 "inner surfaces stay dark on light band"):
   the base `.tdm-newsfeed { --nl-*: <dark> }` rule above is a class selector
   (0,1,0). A `:where([data-band="light"])` wrapper is ZERO specificity (0,0,0)
   and therefore LOSES the cascade to that base rule — so the local surface vars
   never re-toned, leaving dark cards/filter/featured on a light band. Use a
   PLAIN attribute selector `.tdm-newsfeed[data-band="light"]` (0,1,1) so it
   beats the base (0,1,0) yet still sits BELOW the per-instance CssEmitter
   override `.tdm-block.tdm-i-<bID>` (0,2,0, printed after base.css) — mirrors
   the global hook `base.css:83` which is itself NOT :where()-wrapped. */
.tdm-newsfeed[data-band="light"] {
  /* OWN-SURFACE (band-tone model decision 2026-06-15): on Light the block paints
     its OWN light band fill via --tdmx-bg (base.css:56 `background: var(--tdmx-bg)`),
     so the index band gets a light surface under the header/filter even when dropped
     on a DARK parent (the operator's "text invisible on a light band over dark"
     gap). Set on --tdmx-bg, NOT a direct `background`, so an explicit operator
     Design bg (per-instance emitter .tdm-i-N, 0,2,0) still wins; auto emits no
     [data-band] => stays transparent/inherited (existing rows unchanged). Mirrors
     the tdm_newsletter pattern (view.css:346). */
  --tdmx-bg:      color-mix(in srgb, #000 2%, #FFFFFF);
  --nl-card-bg:   color-mix(in srgb, #000 4%, #FFFFFF);
  --nl-card-bg-2: color-mix(in srgb, #000 6%, #FFFFFF);
  --nl-hairline:  color-mix(in srgb, var(--tdm-color-surface, #0D0D0F) 12%, transparent);
  --nl-meta:      color-mix(in srgb, var(--tdm-color-surface, #0D0D0F) 58%, transparent);
  --nl-chip-bg:   color-mix(in srgb, var(--tdm-color-accent) 16%, #FFFFFF);
  --nl-chip-text: var(--tdm-color-accent-text-light, #B0470B);
  /* LIGHT-Rule-7: accent-as-TEXT on a light band MUST use the light-safe accent.
     #E8651A fails AA as text on cream (~3.3:1); #B0470B = ~5.6:1 PASS.
     Pinned locally so the 3 measured failures (featured eyebrow, "Read full
     article" link, active pager) re-tone here even if the global hook is
     out-cascaded on this block. */
  --nl-accent-text: var(--tdm-color-accent-text-light, #B0470B);
  --nl-field-bg:  color-mix(in srgb, #000 2%, #FFFFFF);
  /* active pager fill darkened to the AA-safe accent so white text reads ~6.3:1
     on a light band (orange #E8651A fill = only ~3.5:1). */
  --nl-pager-active-bg: var(--tdm-color-accent-text-light, #B0470B);
  /* card-hover shadow on cream: soft dark-ink scrim, tokenised (was rgba(10,10,11,.08)) */
  --nl-shadow:    color-mix(in srgb, var(--tdm-color-surface, #0D0D0F) 8%, transparent);
  /* dot/arrow idle bumped to 45% on light for the 3:1 UI floor (band-model §4) */
  --nl-dots:      color-mix(in srgb, var(--tdm-color-surface, #0D0D0F) 45%, transparent);
}

/* FORCED DARK band — pins the dark surface/ink so a block dropped on a dark
   image/gradient (where auto-luminance can't read a hex) stays legible.
   Heading + body ink + accent-text are pinned by the GLOBAL hook (base.css:95-99).
   Plain attribute selector (0,1,1) for the same specificity reason as the light
   band above — it must beat the base `.tdm-newsfeed` (0,1,0) dark defaults. */
.tdm-newsfeed[data-band="dark"] {
  /* OWN-SURFACE (band-tone model decision 2026-06-15): on forced Dark the block
     paints its OWN dark band fill so a block dropped on a LIGHT parent gets a dark
     surface under its light ink. Same --tdmx-bg lever as light; operator override
     (emitter 0,2,0) still wins; auto stays transparent/inherited. Mirrors
     tdm_newsletter (view.css:375). */
  --tdmx-bg:      var(--tdm-color-surface, #0D0D0F);
  --nl-card-bg:   var(--tdm-color-surface-2, #141416);
  --nl-card-bg-2: var(--tdm-color-surface-3, #1C1C20);
  --nl-hairline:  color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 14%, transparent);
  --nl-meta:      #909099; /* AA on dark card #141416: 6.59:1 (ink-3 #6B6B75 was 4.27:1) */
  --nl-chip-bg:   color-mix(in srgb, var(--tdm-color-accent) 14%, transparent);
  --nl-chip-text: var(--tdmx-accent-text, var(--tdm-color-accent, #E8651A));
  /* forced-dark: accent-as-text stays brand orange (AA on dark, ~5.7:1) */
  --nl-accent-text: var(--tdmx-accent-text, var(--tdm-color-accent, #E8651A));
  /* forced-dark: active pager pill keeps the AA-safe button-fill (white digit ≈ 7.2:1) */
  --nl-pager-active-bg: var(--tdm-color-btn-fill, #B0470B);
  --nl-field-bg:  var(--tdm-color-surface-3, #1C1C20);
  --nl-dots:      color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 30%, transparent);
}

.tdm-newsfeed__inner {
  text-align: var(--tdmx-align, left);
}

/* ---------- header ---------- */
.tdm-newsfeed__header {
  max-width: 64ch;
  margin: 0 0 var(--tdm-space-6, 32px);
}
.tdm-newsfeed__eyebrow {
  font-family: var(--tdm-font-mono, monospace);
  font-size: var(--tdm-fs-eyebrow, 0.8125rem);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--nl-accent-text);
  margin: 0 0 var(--tdm-space-3, 12px);
}
.tdm-newsfeed__heading {
  font-family: var(--tdmx-font-heading, var(--tdm-font-headline, sans-serif));
  font-size: clamp(1.6rem, 1.1rem + 2vw, 2.5rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--tdmx-heading, var(--tdm-color-ink, #F5F4F0));
  margin: 0 0 var(--tdm-space-3, 12px);
}
.tdm-newsfeed__intro {
  font-size: clamp(0.95rem, 0.9rem + 0.3vw, 1.0625rem);
  line-height: 1.6;
  color: var(--tdmx-text, var(--tdm-color-ink-2, #B0B0BA));
  margin: 0;
  max-width: 64ch;
}

/* ======================================================================
   FILTER BAR (shared across all 3 templates)
   ====================================================================== */
.tdm-newsfeed__filter {
  margin-bottom: var(--tdm-space-6, 32px);
}
.tdm-newsfeed__filter-bar {
  display: flex;
  flex-direction: column;
  gap: var(--tdm-space-4, 16px);
  padding: var(--tdm-space-5, 24px);
  background: var(--nl-card-bg);
  border: 1px solid var(--nl-hairline);
  border-radius: var(--tdmx-radius, var(--tdm-radius-md, 6px));
}
@media (min-width: 1024px) {
  .tdm-newsfeed__filter-bar {
    flex-direction: row;
    align-items: center;
    gap: var(--tdm-space-6, 32px);
    padding: var(--tdm-space-4, 16px) var(--tdm-space-5, 24px);
  }
}
.tdm-newsfeed__search {
  position: relative;
  flex-shrink: 0;
  width: 100%;
}
@media (min-width: 1024px) {
  .tdm-newsfeed__search { width: 320px; }
}
.tdm-newsfeed__search-icon {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  color: var(--nl-meta);
  pointer-events: none;
}
.tdm-newsfeed__search-input {
  width: 100%;
  min-height: 44px;
  padding: 10px 12px 10px 40px;
  background: var(--nl-field-bg);
  border: 1px solid var(--nl-hairline);
  border-radius: var(--tdm-radius-btn, 2px);
  font-family: var(--tdm-font-body, sans-serif);
  font-size: 0.9375rem;
  color: var(--tdmx-heading, var(--tdm-color-ink, #F5F4F0));
}
.tdm-newsfeed__search-input::placeholder { color: var(--nl-meta); }
.tdm-newsfeed__search-input:focus-visible {
  outline: 2px solid var(--tdmx-accent, var(--tdm-color-accent, #E8651A));
  outline-offset: 2px;
}

.tdm-newsfeed__filter-divider {
  display: none;
  width: 1px;
  align-self: stretch;
  background: var(--nl-hairline);
}
@media (min-width: 1024px) { .tdm-newsfeed__filter-divider { display: block; } }

.tdm-newsfeed__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--tdm-space-2, 8px);
  flex: 1;
  align-items: center;
}
.tdm-newsfeed__chips-label {
  font-family: var(--tdm-font-mono, monospace);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--nl-meta);
  margin-right: var(--tdm-space-2, 8px);
}
.tdm-newsfeed__chip {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 6px 14px;
  background: var(--nl-field-bg);
  border: 1px solid var(--nl-hairline);
  border-radius: var(--tdm-radius-btn, 2px);
  font-family: var(--tdm-font-mono, monospace);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--tdmx-text, var(--tdm-color-ink, #F5F4F0));
  cursor: pointer;
  transition: background var(--tdm-motion-fast, 150ms) var(--tdm-ease-standard, ease),
              border-color var(--tdm-motion-fast, 150ms) var(--tdm-ease-standard, ease),
              color var(--tdm-motion-fast, 150ms) var(--tdm-ease-standard, ease),
              transform var(--tdm-motion-fast, 150ms) var(--tdm-ease-standard, ease);
}
.tdm-newsfeed__chip:hover {
  border-color: var(--tdmx-accent, var(--tdm-color-accent, #E8651A));
  color: var(--tdmx-heading, var(--tdm-color-ink, #F5F4F0));
  transform: translateY(-1px);
}
.tdm-newsfeed__chip:focus-visible {
  outline: 2px solid var(--tdmx-accent, var(--tdm-color-accent, #E8651A));
  outline-offset: 2px;
}
.tdm-newsfeed__chip.is-active {
  background: var(--tdmx-accent, var(--tdm-color-accent, #E8651A));
  border-color: var(--tdmx-accent, var(--tdm-color-accent, #E8651A));
  color: var(--tdm-color-on-accent, #FFFFFF);
}
.tdm-newsfeed__chip.is-active:hover {
  background: color-mix(in srgb, var(--tdmx-accent, var(--tdm-color-accent)) 86%, #000);
  transform: none;
}
.tdm-newsfeed__chip-count { margin-left: 6px; opacity: 0.7; font-size: 0.625rem; }

.tdm-newsfeed__reset {
  display: none;
  min-height: 36px;
  padding: 6px 12px;
  background: none;
  border: 1px solid transparent;
  border-radius: var(--tdm-radius-btn, 2px);
  font-family: var(--tdm-font-mono, monospace);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--nl-accent-text);
  cursor: pointer;
}
.tdm-newsfeed__reset.is-visible { display: inline-flex; align-items: center; }
.tdm-newsfeed__reset:hover { text-decoration: underline; }
.tdm-newsfeed__reset:focus-visible {
  outline: 2px solid var(--tdmx-accent, var(--tdm-color-accent, #E8651A));
  outline-offset: 2px;
}

.tdm-newsfeed__status {
  margin: var(--tdm-space-4, 16px) 0 0;
  font-family: var(--tdm-font-mono, monospace);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--nl-meta);
  min-height: 18px;
}
.tdm-newsfeed__count { color: var(--nl-accent-text); font-weight: 600; }

/* ======================================================================
   SHARED card / frame primitives (used by all templates)
   ====================================================================== */
.tdm-newsfeed__frame {
  position: relative;
  overflow: hidden;
  background: var(--nl-card-bg-2);
}
.tdm-newsfeed__frame img,
.tdm-newsfeed__frame picture {
  display: block;
}
.tdm-newsfeed__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--tdm-motion-slower, 0.6s) var(--tdm-ease-standard, ease);
}
.tdm-newsfeed img { max-width: 100%; height: auto; display: block; }

/* fixed thumbnail ratio (anti-CLS) — driven by data-aspect on the section */
.tdm-newsfeed[data-aspect="16x9"] .tdm-newsfeed__card-img { aspect-ratio: 16 / 9; }
.tdm-newsfeed[data-aspect="4x3"]  .tdm-newsfeed__card-img { aspect-ratio: 4 / 3; }
.tdm-newsfeed[data-aspect="1x1"]  .tdm-newsfeed__card-img { aspect-ratio: 1 / 1; }
.tdm-newsfeed[data-aspect="auto"] .tdm-newsfeed__card-img { aspect-ratio: auto; }
.tdm-newsfeed[data-aspect="auto"] .tdm-newsfeed__card-img img { height: auto; }

/* category chip overlaid on a thumbnail.
   OVER-IMAGE EXEMPT (tdm-band-tone-model-v1 §2c): this badge is ALWAYS painted
   over the thumbnail <picture>/<img> (it lives inside .tdm-newsfeed__frame, the
   only place view.php:212/230 emits it). Its dark scrim (--nl-cat-overlay-bg) is
   deliberately the SAME near-black on a LIGHT band as on a dark band so the label
   stays legible over ANY photo — it does NOT re-tone to a light surface. The
   render-regression gate must SKIP the dark-bg-on-light-band check here (the
   element overlaps an <img>); see §2c gate-exemption rule. NOT a bug. */
.tdm-newsfeed__cat-chip {
  position: absolute;
  top: var(--tdm-space-3, 12px);
  left: var(--tdm-space-3, 12px);
  padding: 4px 10px;
  background: var(--nl-cat-overlay-bg);
  color: var(--nl-cat-overlay-text);
  font-family: var(--tdm-font-mono, monospace);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border-radius: var(--tdm-radius-btn, 2px);
  z-index: 2;
}

.tdm-newsfeed__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--tdm-space-3, 12px);
  align-items: center;
}
.tdm-newsfeed__date {
  font-family: var(--tdm-font-mono, monospace);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--nl-meta);
}
.tdm-newsfeed__cat-label {
  font-family: var(--tdm-font-mono, monospace);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--nl-accent-text);
}
.tdm-newsfeed__title {
  font-family: var(--tdmx-font-heading, var(--tdm-font-headline, sans-serif));
  font-weight: 600;
  font-size: 1.25rem;
  line-height: 1.25;
  letter-spacing: -0.005em;
  color: var(--tdmx-heading, var(--tdm-color-ink, #F5F4F0));
  margin: 0;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}
.tdm-newsfeed__excerpt {
  font-family: var(--tdm-font-body, sans-serif);
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--tdmx-text, var(--tdm-color-ink-2, #B0B0BA));
  margin: 0;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
.tdm-newsfeed__more {
  margin-left: auto;
  color: var(--nl-accent-text);
  font-family: var(--tdm-font-mono, monospace);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.tdm-newsfeed__featured-eyebrow {
  font-family: var(--tdm-font-mono, monospace);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--nl-accent-text);
  margin: 0;
}

/* card shell (classic + magazine) */
.tdm-newsfeed__card {
  display: flex;
  flex-direction: column;
  background: var(--nl-card-bg);
  border: 1px solid var(--nl-hairline);
  border-radius: var(--tdmx-radius, var(--tdm-radius-md, 6px));
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  transition: transform var(--tdm-motion-slow, 0.4s) var(--tdm-ease-standard, ease),
              box-shadow var(--tdm-motion-slow, 0.4s) var(--tdm-ease-standard, ease),
              border-color var(--tdm-motion-slow, 0.4s) var(--tdm-ease-standard, ease);
}
.tdm-newsfeed__card:hover {
  transform: translateY(-4px);
  box-shadow: 0 16px 32px var(--nl-shadow);
  border-color: var(--tdmx-accent, var(--tdm-color-accent, #E8651A));
}
.tdm-newsfeed__card:hover .tdm-newsfeed__frame img { transform: scale(1.03); }
.tdm-newsfeed__card:focus-visible {
  outline: 2px solid var(--tdmx-accent, var(--tdm-color-accent, #E8651A));
  outline-offset: 2px;
}
.tdm-newsfeed__card-img { aspect-ratio: 16 / 9; }
.tdm-newsfeed__card-body {
  padding: var(--tdm-space-5, 24px);
  display: flex;
  flex-direction: column;
  gap: var(--tdm-space-3, 12px);
  flex: 1;
}

/* hidden by the filter JS */
.tdm-newsfeed__card.is-hidden,
.tdm-newsfeed__row.is-hidden,
.tdm-newsfeed__card.is-paged,
.tdm-newsfeed__row.is-paged { display: none; }

/* ======================================================================
   TEMPLATE A — CLASSIC GRID
   featured card spans the top, the rest flow in a responsive column grid
   driven by data-cols-* (responsive_manual breakpoints: MD680 / LG/XL1024).
   ====================================================================== */
.tdm-newsfeed__grid--classic-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--nl-card-gap, var(--tdmx-gap, var(--tdm-space-5, 24px)));
}
/* the featured card spans the full row at every breakpoint */
.tdm-newsfeed__grid--classic-grid .tdm-newsfeed__card--featured { grid-column: 1 / -1; }

@media (min-width: 768px) {
  .tdm-newsfeed__grid--classic-grid[data-cols-tablet="2"],
  .tdm-newsfeed__grid--classic-grid[data-cols-tablet="3"],
  .tdm-newsfeed__grid--classic-grid[data-cols-tablet="4"] { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .tdm-newsfeed__grid--classic-grid[data-cols-desktop="1"] { grid-template-columns: 1fr; }
  .tdm-newsfeed__grid--classic-grid[data-cols-desktop="2"] { grid-template-columns: repeat(2, 1fr); }
  .tdm-newsfeed__grid--classic-grid[data-cols-desktop="3"] { grid-template-columns: repeat(3, 1fr); }
  .tdm-newsfeed__grid--classic-grid[data-cols-desktop="4"] { grid-template-columns: repeat(4, 1fr); }
  .tdm-newsfeed__grid--classic-grid { gap: var(--nl-card-gap, var(--tdmx-gap, var(--tdm-space-6, 32px))); }
}

/* featured card = side-by-side image/content from LG up */
.tdm-newsfeed__card--featured { background: var(--nl-card-bg); }
@media (min-width: 768px) {
  .tdm-newsfeed__grid--classic-grid .tdm-newsfeed__card--featured {
    display: grid;
    grid-template-columns: 6fr 4fr;
    align-items: stretch;
  }
  .tdm-newsfeed__grid--classic-grid .tdm-newsfeed__card--featured .tdm-newsfeed__card-body {
    justify-content: center;
    padding: var(--tdm-space-6, 32px) var(--tdm-space-7, 48px);
  }
}
.tdm-newsfeed__card--featured .tdm-newsfeed__title {
  font-size: clamp(1.4rem, 1.1rem + 1.4vw, 2.1rem);
  line-height: 1.15;
}

/* ======================================================================
   TEMPLATE B — MAGAZINE MASONRY
   first (featured) tile runs large; the rest form a dense editorial grid.
   ====================================================================== */
.tdm-newsfeed__grid--magazine-masonry {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--nl-card-gap, var(--tdmx-gap, var(--tdm-space-5, 24px)));
}
@media (min-width: 680px) {
  .tdm-newsfeed__grid--magazine-masonry { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .tdm-newsfeed__grid--magazine-masonry[data-cols-desktop="2"] { grid-template-columns: repeat(2, 1fr); }
  .tdm-newsfeed__grid--magazine-masonry[data-cols-desktop="3"] { grid-template-columns: repeat(3, 1fr); }
  .tdm-newsfeed__grid--magazine-masonry[data-cols-desktop="4"] { grid-template-columns: repeat(4, 1fr); }
  .tdm-newsfeed__grid--magazine-masonry { gap: var(--nl-card-gap, var(--tdmx-gap, var(--tdm-space-6, 32px))); }
}
/* the lead/featured tile spans 2 cols (and 2 rows on >=3-col) for the 2x2 hero */
@media (min-width: 680px) {
  .tdm-newsfeed__grid--magazine-masonry .tdm-newsfeed__card--featured { grid-column: span 2; }
}
@media (min-width: 1024px) {
  .tdm-newsfeed__grid--magazine-masonry[data-cols-desktop="3"] .tdm-newsfeed__card--featured,
  .tdm-newsfeed__grid--magazine-masonry[data-cols-desktop="4"] .tdm-newsfeed__card--featured {
    grid-row: span 2;
  }
  .tdm-newsfeed__grid--magazine-masonry .tdm-newsfeed__card--featured .tdm-newsfeed__card-img { aspect-ratio: 16 / 9; flex: 1; }
}
.tdm-newsfeed__grid--magazine-masonry .tdm-newsfeed__card--featured .tdm-newsfeed__title {
  font-size: clamp(1.4rem, 1.05rem + 1.6vw, 2.1rem);
}
.tdm-newsfeed__grid--magazine-masonry .tdm-newsfeed__card--featured .tdm-newsfeed__excerpt {
  -webkit-line-clamp: 4;
  line-clamp: 4;
}

/* ======================================================================
   TEMPLATE C — COMPACT LIST
   dense horizontal rows: small thumbnail left, title + meta + excerpt right.
   Columns are ignored (single dense column).
   ====================================================================== */
.tdm-newsfeed__grid--compact-list {
  display: flex;
  flex-direction: column;
  gap: var(--nl-card-gap, var(--tdmx-gap, var(--tdm-space-4, 16px)));
}
.tdm-newsfeed__row {
  display: grid;
  grid-template-columns: 96px 1fr;
  gap: var(--tdm-space-4, 16px);
  align-items: start;
  padding: var(--tdm-space-4, 16px);
  background: var(--nl-card-bg);
  border: 1px solid var(--nl-hairline);
  border-radius: var(--tdmx-radius, var(--tdm-radius-md, 6px));
  text-decoration: none;
  color: inherit;
  transition: border-color var(--tdm-motion-fast, 150ms) var(--tdm-ease-standard, ease),
              transform var(--tdm-motion-fast, 150ms) var(--tdm-ease-standard, ease);
}
@media (min-width: 680px) {
  .tdm-newsfeed__row {
    grid-template-columns: 160px 1fr;
    gap: var(--tdm-space-5, 24px);
    padding: var(--tdm-space-5, 24px);
    align-items: center;
  }
}
@media (min-width: 1024px) {
  .tdm-newsfeed__row { grid-template-columns: 220px 1fr; }
}
.tdm-newsfeed__row:hover {
  border-color: var(--tdmx-accent, var(--tdm-color-accent, #E8651A));
  transform: translateX(2px);
}
.tdm-newsfeed__row:hover .tdm-newsfeed__frame img { transform: scale(1.04); }
.tdm-newsfeed__row:focus-visible {
  outline: 2px solid var(--tdmx-accent, var(--tdm-color-accent, #E8651A));
  outline-offset: 2px;
}
.tdm-newsfeed__row-thumb {
  aspect-ratio: 16 / 10;
  border-radius: var(--tdm-radius-btn, 2px);
}
.tdm-newsfeed[data-aspect="1x1"] .tdm-newsfeed__row-thumb { aspect-ratio: 1 / 1; }
.tdm-newsfeed[data-aspect="4x3"] .tdm-newsfeed__row-thumb { aspect-ratio: 4 / 3; }
.tdm-newsfeed__row-body {
  display: flex;
  flex-direction: column;
  gap: var(--tdm-space-2, 8px);
  min-width: 0;
}
.tdm-newsfeed__row-body .tdm-newsfeed__meta { margin-bottom: var(--tdm-space-1, 4px); }
.tdm-newsfeed__row-body .tdm-newsfeed__title {
  font-size: clamp(1.0625rem, 0.95rem + 0.6vw, 1.375rem);
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

/* ======================================================================
   EMPTY STATE
   ====================================================================== */
.tdm-newsfeed__empty {
  display: none;
  text-align: center;
  padding: var(--tdm-space-9, 96px) var(--tdm-space-5, 24px);
  background: var(--nl-card-bg);
  border: 1px dashed var(--nl-hairline);
  border-radius: var(--tdmx-radius, var(--tdm-radius-md, 6px));
  margin-top: var(--tdm-space-6, 32px);
}
.tdm-newsfeed__empty.is-visible { display: block; }
.tdm-newsfeed__empty h3 {
  font-family: var(--tdmx-font-heading, var(--tdm-font-headline, sans-serif));
  font-weight: 600;
  font-size: 1.375rem;
  color: var(--tdmx-heading, var(--tdm-color-ink, #F5F4F0));
  margin: 0 0 var(--tdm-space-3, 12px);
}
.tdm-newsfeed__empty p {
  font-family: var(--tdm-font-body, sans-serif);
  font-size: 0.9375rem;
  color: var(--tdmx-text, var(--tdm-color-ink-2, #B0B0BA));
  max-width: 48ch;
  margin: 0 auto;
}
.tdm-newsfeed__empty-clear {
  margin-top: var(--tdm-space-4, 16px);
  min-height: 44px;
  padding: 10px 20px;
  /* solid button — white label on fill → AA-safe button-fill token (5.60:1),
     not brand orange #E8651A (3.33:1). Band-independent. */
  background: var(--tdm-color-btn-fill, #B0470B);
  color: var(--tdm-color-on-accent, #FFFFFF);
  border: 0;
  border-radius: var(--tdm-radius-btn, 2px);
  font-family: var(--tdm-font-mono, monospace);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}
.tdm-newsfeed__empty-clear:hover { background: color-mix(in srgb, var(--tdm-color-btn-fill, #B0470B) 88%, #000); }
.tdm-newsfeed__empty-clear:focus-visible {
  outline: 2px solid var(--tdmx-accent, var(--tdm-color-accent, #E8651A));
  outline-offset: 2px;
}

/* ======================================================================
   PAGINATION
   ====================================================================== */
.tdm-newsfeed__pager {
  display: flex;
  justify-content: center;
  margin-top: var(--tdm-space-7, 48px);
}
.tdm-newsfeed__pages {
  display: flex;
  flex-wrap: wrap;
  gap: var(--tdm-space-2, 8px);
  align-items: center;
  justify-content: center;
}
.tdm-newsfeed__page,
.tdm-newsfeed__loadmore {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  min-width: 44px;
  padding: 8px 16px;
  background: var(--nl-field-bg);
  border: 1px solid var(--nl-hairline);
  border-radius: var(--tdm-radius-btn, 2px);
  font-family: var(--tdm-font-mono, monospace);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--tdmx-text, var(--tdm-color-ink, #F5F4F0));
  cursor: pointer;
  transition: background var(--tdm-motion-fast, 150ms) var(--tdm-ease-standard, ease),
              border-color var(--tdm-motion-fast, 150ms) var(--tdm-ease-standard, ease),
              color var(--tdm-motion-fast, 150ms) var(--tdm-ease-standard, ease);
}
.tdm-newsfeed__page:hover,
.tdm-newsfeed__loadmore:hover { border-color: var(--tdmx-accent, var(--tdm-color-accent, #E8651A)); }
.tdm-newsfeed__page:focus-visible,
.tdm-newsfeed__loadmore:focus-visible {
  outline: 2px solid var(--tdmx-accent, var(--tdm-color-accent, #E8651A));
  outline-offset: 2px;
}
.tdm-newsfeed__page.is-active {
  /* fill re-tones per band ONLY: orange on dark/default, AA-safe #B0470B on
     light so the white digit reads >= 4.5:1 (see --nl-pager-active-bg). */
  background: var(--nl-pager-active-bg);
  border-color: var(--nl-pager-active-bg);
  color: var(--tdm-color-on-accent, #FFFFFF);
}

/* ======================================================================
   REDUCED MOTION — kill transforms / scale (responsive_manual + design §10)
   ====================================================================== */
@media (prefers-reduced-motion: reduce) {
  .tdm-newsfeed__card,
  .tdm-newsfeed__row,
  .tdm-newsfeed__chip,
  .tdm-newsfeed__frame img {
    transition: none !important;
    transform: none !important;
    box-shadow: none !important;
  }
  .tdm-newsfeed__card:hover,
  .tdm-newsfeed__row:hover { transform: none !important; box-shadow: none !important; }
  .tdm-newsfeed__card:hover .tdm-newsfeed__frame img,
  .tdm-newsfeed__row:hover .tdm-newsfeed__frame img { transform: none !important; }
}


/* ======================================================================
   TDM AI Assistant — page-context chat widget.
   Tokens from the package tokens.css (--tdm-*). Design-controlled props
   consume var(--tdmx-*, var(--tdm-*, fallback)) (emit-only-on-change).
   Namespaced .tdm-ai* classes only. 44px touch floor. prefers-reduced-motion
   safe (composite-only transform/opacity). Inner surfaces re-tone on
   [data-band="light"] (builder Lesson 6 — plain attribute selector, never
   :where(); accent routed through a LOCAL --tdm-ai-accent var).
   ====================================================================== */

.tdm-ai__inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--tdmx-gap, var(--tdm-space-4, 16px));
}

/* Local accent var so the orange stays legible on both bands. */
.tdm-ai {
  /* Rail redesign (design-spec-ai-chat-rail-v2 §0): the accent is the brand CTA
     orange #E8651A (the package token --tdm-color-accent), NOT the duller burnt
     #B0470B — Rail is the sales surface. The operator's custom launcher colour
     (--tdm-ai-primary) scopes to the LAUNCHER ONLY (spec §4.2) — it must never
     recolor the widget-wide accent system (quote bar, send, bubble rail), so it
     is deliberately absent from this chain; the launcher fill consumes it via
     --tdm-ai-launcher-bg set inline by the renderer.
     White label / glyph on this fill = 3.33:1 (large-text + non-text PASS). */
  --tdm-ai-accent: var(--tdmx-accent, var(--tdm-color-accent, #E8651A));
  /* Accent-AS-TEXT (eyebrow / small labels). On DARK the brand orange is AA as
     small text (#E8651A = 5.17:1 on the #1C1C20 card, 5.50:1 on the panel). On the
     LIGHT band it remaps to burnt #B0470B (--tdm-color-accent-text-light, 5.41:1 on
     #FAFAFA) — see the band-tone section. NEVER burnt as small text on dark
     (builder lesson: that exact failure shipped once). */
  --tdm-ai-accent-text-safe: var(--tdm-color-accent, #E8651A);
  /* Agent-joined GREEN (design-spec §0, LOCKED — traffic-light semantics, not a
     brand accent). 8.42:1 on the panel. */
  --tdm-ai-status-online: #35C77E;
  /* Small meta / timestamps (design-spec §0): #909099 = 5.87:1 (the site --muted
     #6B6B75 FAILS body at 3.48:1). Re-toned on the light band below. */
  --tdm-ai-meta: #909099;
  /* Bug 2 fix (QA AA contrast): accent-as-TEXT (the consent link + the required /
     error consent states) must stay AA (>=4.5:1) on the panel for ANY accent the
     operator freely picks for branding. The RAW accent alone fails — measured blue
     #0672b7 = 3.59:1 on the #141416 panel. color-mix() cannot READ luminance, so it
     can't clamp to a contrast ratio; instead we lighten the accent toward the near-
     white ink by a FIXED fraction chosen high enough (55% ink) to clear AA even for a
     pathologically dark accent (pure black -> 5.07:1), while keeping the accent hue.
     Realistic accents land 8-9:1 on the dark panel. The light band re-derives this
     toward the dark surface (band-tone section below). Percentages verified by WCAG
     relative-luminance calc for blue/orange/green/black (see delivery note). This is
     accent-as-TEXT re-toning via a LOCAL band var — NOT the global accent hook. */
  --tdm-ai-link-safe: color-mix(in srgb, var(--tdm-ai-accent) 45%, var(--tdm-color-ink, #F5F4F0));
  /* Launcher size tokens (s/m/l) — 44px floor for touch targets. */
  --tdm-ai-launcher-size: 56px;
  /* Rating "empty" star colour (D). Set via a var so the light-band re-tone only
     flips the variable (below) — the fills override `color` directly at higher
     specificity, so no specificity fight on the light band. */
  --tdm-ai-star-empty: color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 26%, transparent);
}
.tdm-ai__launcher--s { --tdm-ai-launcher-size: 44px; }
.tdm-ai__launcher--m { --tdm-ai-launcher-size: 56px; }
.tdm-ai__launcher--l { --tdm-ai-launcher-size: 64px; }

/* ---------- launcher (shared) ---------- */
.tdm-ai__launcher {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--tdm-space-2, 8px);
  min-height: 44px;
  /* Launcher chrome (spec §8.3): independent background (accent | custom | none)
     + border (on/off, width, colour), driven by inline --tdm-ai-launcher-* props
     emitted per-instance by the renderer. Fallbacks keep the default look when
     the props are absent. */
  border: var(--tdm-ai-launcher-border-width, 1px) solid var(--tdm-ai-launcher-border-color, var(--tdm-ai-accent));
  background: var(--tdm-ai-launcher-bg, var(--tdm-ai-accent));
  color: #FFFFFF;
  font-family: var(--tdmx-font-heading, var(--tdm-font-body, "DM Sans", system-ui, sans-serif));
  font-size: var(--tdm-text-body, 16px);
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  transition: background var(--tdm-motion-fast, 160ms) ease, transform var(--tdm-motion-fast, 160ms) ease, box-shadow var(--tdm-motion-fast, 160ms) ease, border-color var(--tdm-motion-fast, 160ms) ease;
}
/* Hover darkens the background — EXCEPT when the background is transparent
   (bg mode = none), where darkening would paint a translucent black film; there
   we darken the border instead so the affordance stays clean. */
.tdm-ai:not([data-launcher-bg="none"]) .tdm-ai__launcher:hover {
  background: color-mix(in srgb, var(--tdm-ai-launcher-bg, var(--tdm-ai-accent)) 86%, #000);
}
.tdm-ai[data-launcher-bg="none"] .tdm-ai__launcher:hover {
  border-color: color-mix(in srgb, var(--tdm-ai-launcher-border-color, var(--tdm-ai-accent)) 70%, #000);
}
/* Hide the launcher when the assistant is offline AND the operator opted in
   (hide_launcher_when_offline, spec §10). Compound selector so a placed block's
   offline card stays reachable unless the operator turned the option on. */
.tdm-ai--hideoffline.tdm-ai--offline .tdm-ai__launcher {
  display: none;
}
.tdm-ai__launcher:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tdm-ai-accent) 55%, transparent);
}
.tdm-ai__launcher-icon {
  flex: none;
}
.tdm-ai__launcher-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

/* ---------- launcher shapes ---------- */
/* circle + rounded = a square button (icon only, label visually hidden). pill =
   a wide button that shows the label text. */
.tdm-ai__launcher--circle,
.tdm-ai__launcher--rounded {
  width: var(--tdm-ai-launcher-size);
  height: var(--tdm-ai-launcher-size);
  padding: 0;
}
.tdm-ai__launcher--circle { border-radius: 50%; }
.tdm-ai__launcher--rounded { border-radius: var(--tdm-radius, 14px); }
/* Rail edge-tab launcher (design-spec §1.1): a fixed 52px pill with a 20px glyph +
   the visible label. The s/m/l size maps to label padding, not diameter (§4.2), so
   the pill height is fixed regardless of --tdm-ai-launcher-size. Geometry values
   (52/18/14/10) are the Rail-locked tab dimensions. */
.tdm-ai__launcher--pill {
  height: 52px;
  min-height: 52px;
  min-width: 44px;
  padding: 0 18px 0 14px;
  gap: 10px;
  border-radius: var(--tdm-radius-pill, 999px);
  font-size: 15px;
}
.tdm-ai__launcher--pill .tdm-ai__launcher-glyph,
.tdm-ai__launcher--pill .tdm-ai__launcher-icon {
  width: 20px;
  height: 20px;
}
/* Label: hidden on circle/rounded (icon-only), shown on pill. Always present in
   the DOM + on aria-label for screen readers. */
.tdm-ai__launcher-label {
  display: none;
}
.tdm-ai__launcher--pill .tdm-ai__launcher-label {
  display: inline;
}
.tdm-ai__launcher--circle .tdm-ai__launcher-label,
.tdm-ai__launcher--rounded .tdm-ai__launcher-label {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}

/* ---------- launcher icon modes ---------- */
.tdm-ai__launcher-img {
  display: block;
  width: 60%;
  height: 60%;
  object-fit: contain;
}
.tdm-ai__launcher-img--avatar-photo,
.tdm-ai__launcher-img--logo {
  width: calc(var(--tdm-ai-launcher-size) - 12px);
  height: calc(var(--tdm-ai-launcher-size) - 12px);
  border-radius: 50%;
  object-fit: cover;
}
/* animated-image: the animated raster sits on top; the static poster is the
   fallback (shown before load + under reduced-motion, via CSS below). */
.tdm-ai__launcher-animated {
  position: relative;
  display: inline-flex;
  width: calc(var(--tdm-ai-launcher-size) - 12px);
  height: calc(var(--tdm-ai-launcher-size) - 12px);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  border-radius: 50%;
  overflow: hidden;
}
.tdm-ai__launcher-anim-img,
.tdm-ai__launcher-anim-poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Poster is a fallback layer under the animated image; hidden when the animated
   source paints. Reduced-motion swaps them (animated hidden, poster shown). */
.tdm-ai__launcher-anim-poster { opacity: 0; }

/* animated-svg: the BUNDLED zero-JS SMIL icon. The transparent cyan/teal art is
   placed on a neutral dark chip (#1C1C20) so it reads on any launcher colour.
   The chip fills the launcher inner box and clips the SVG to the shape; the SVG
   scales by its viewBox to fit the chip without overflow on circle/rounded/pill.
   Reduced-motion is handled in view.js (pauseAnimations on the first frame). */
.tdm-ai__launcher-svgwrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: calc(var(--tdm-ai-launcher-size) - 12px);
  height: calc(var(--tdm-ai-launcher-size) - 12px);
  background: #1C1C20;
  border-radius: 50%;
  overflow: hidden;
  flex: none;
}
/* On the pill shape the launcher is wide and shows a label; keep the chip a
   fixed square-ish glyph so it doesn't stretch with the button. */
.tdm-ai__launcher--rounded .tdm-ai__launcher-svgwrap {
  border-radius: calc(var(--tdm-radius, 14px) - 4px);
}
.tdm-ai__launcher-svg {
  display: block;
  width: 86%;
  height: 86%;
  object-fit: contain;
}

/* ---------- floating launcher (position fixed, LEFT-only) ---------- */
/* B3 fix: the shared .tdm-block rule (base.css) sets `isolation: isolate`, which
   creates a stacking context on the FLOATING widget root and TRAPS the fixed
   launcher/panel (z-index 2147483000/001) inside it — so any page element with a
   positive z-index paints over the widget and steals its clicks. The floating
   root is position:relative; z-index:auto and owns no bg image/overlay (its
   ::before/::after fall back to none/transparent), so dropping the stacking
   context is visually safe and lets the fixed layers rise into the ROOT context.
   Scoped to --floating ONLY — the inline variant keeps isolation for band-tone. */
.tdm-ai--floating {
  isolation: auto;
}
.tdm-ai--floating .tdm-ai__inner {
  /* The inner wrapper holds no layout role when floating — the launcher + panel
     are fixed. Keep it from adding section height. */
  display: contents;
}
.tdm-ai--floating .tdm-ai__launcher {
  position: fixed;
  /* B2 fix: sit above ALL page content on a very high, safe z-index so no
     section (e.g. a hero overlay) can cover the launcher. NOTE: a transformed /
     filtered / will-change ancestor creates a stacking context that traps a
     fixed child regardless of z-index — the auto-mount path injects the widget at
     <body> end to avoid that; a placed block must not sit inside such an ancestor. */
  z-index: 2147483000;
  left: var(--tdm-ai-offset-x, 24px);
}
.tdm-ai--floating[data-position="bottom-left"] .tdm-ai__launcher {
  bottom: max(var(--tdm-ai-offset-y, 24px), env(safe-area-inset-bottom));
}
.tdm-ai--floating[data-position="middle-left"] .tdm-ai__launcher {
  top: 50%;
  transform: translateY(-50%);
}
/* Rail drawer — MOBILE-FIRST base (design-spec §5, <480): a full-bleed sheet inset
   8px on all sides. The header + context card + sticky quote bar + composer pin
   (flex:none, Rail distribution below); only the log scrolls. The ≥480 media query
   restores the left/right-docked full-height Rail drawer. The launcher stays fixed
   near its offset anchor; the drawer no longer keys off launcher position. The
   `.tdm-ai--floating{isolation:auto}` fix (above) stays intact so the fixed overlay
   paints above content + receives clicks. */
.tdm-ai--floating .tdm-ai__panel {
  position: fixed;
  z-index: 2147483001;
  top: var(--tdm-space-2, 8px);
  left: var(--tdm-space-2, 8px);
  right: var(--tdm-space-2, 8px);
  bottom: max(var(--tdm-space-2, 8px), env(safe-area-inset-bottom));
  width: auto;
  border-radius: var(--tdmx-radius, var(--tdm-radius-lg, 16px));
  box-shadow: var(--tdm-shadow-lg, 0 12px 40px color-mix(in srgb, #000 45%, transparent));
}
/* Launcher HIDES while the drawer is open (owner 2026-07-11): the standard chat
   pattern — the floating tab disappears on open and returns on minimize/close, so it
   never overlaps in-panel controls. Minimize now lives on the header chevron
   ([data-tdm-ai-minimize]) + Escape. */
.tdm-ai--floating .tdm-ai__launcher[aria-expanded="true"] {
  display: none;
}
/* GAP 1 fix: distribute the capped panel so the header/titlebar stay pinned at the
   top, the input row + turnstile stay pinned at the bottom, and only the
   gate/log/consent region (.tdm-ai__scroll) shrinks + scrolls internally. min-height:0
   is required so the flex child is allowed to shrink below its content height. */
.tdm-ai--floating .tdm-ai__head,
.tdm-ai--floating .tdm-ai__titlebar,
.tdm-ai--floating .tdm-ai__form,
.tdm-ai--floating .tdm-ai__turnstile {
  flex: none;
}
.tdm-ai--floating .tdm-ai__scroll,
.tdm-ai--floating .tdm-ai__offline {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
/* Bug 1 fix (QA short-viewport clipping): the pre-chat GATE (step=gate) and the
   RATING step (step=rating) are DIRECT flex children of the panel, but they were in
   NEITHER the pinned group nor the scroll group above — so on a short viewport (mobile
   keyboard open → 100dvh shrinks below ~600px) their action buttons (gate-submit /
   rating send+skip) overflowed the max-height-capped panel with NO way to reach them.
   Give each the SAME internal-scroll treatment as .tdm-ai__scroll: the region shrinks
   and scrolls inside the panel, so every control — including the submit at the bottom —
   stays reachable. min-height:0 lets the flex child shrink below its content height.
   NOTE: this scrolls the WHOLE region (the submit scrolls into view rather than being
   pinned flex:none). Full button-PINNING parity with the chat region — an inner
   scroller + a pinned button below it — needs a new inner wrapper element in
   WidgetRenderer.php (see delivery note); it is NOT invented here on non-existent
   markup. Region-scroll already removes the clipping regression with the shipped DOM. */
.tdm-ai--floating .tdm-ai__gate,
.tdm-ai--floating .tdm-ai__rating {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
/* A (spec §3.2) — floating panel width, mobile-first on the OFFICIAL breakpoint
   set (responsive_manual_en_0.1.md: min-width ONLY, never max-width). XS base
   (<480) is full-bleed minus the offset gutter (set on the rule above). From
   ≥480 up, the width honours the operator's --tdm-ai-panel-w cap while staying
   inside the viewport. The fluid min() reaches --tdm-ai-panel-w continuously as
   the viewport clears it, so discrete :680 / :768 caps would be byte-identical
   no-ops — omitted on purpose (DRY / specificity discipline). Re-measured on the
   rendered page at 320/480/680/768/1024/1440 by the responsive gate, not asserted
   from this static read. */
@media (min-width: 480px) {
  /* ≥480: the left/right-docked full-height Rail drawer (design-spec §1.2/§5).
     Full height (top 16 → bottom 24), width = operator panel-w (default 400)
     capped to the viewport. Square corners on the dock edge; rounded + free-edge
     shadow on the pulled edge (the only edge with a shadow). */
  .tdm-ai--floating .tdm-ai__panel {
    top: var(--tdm-space-4, 16px);
    bottom: var(--tdm-space-5, 24px);
    left: auto;
    right: auto;
    width: min(var(--tdm-ai-panel-w, 400px), calc(100vw - 2 * var(--tdm-ai-offset-x, 16px)));
  }
  .tdm-ai--floating[data-dock="left"] .tdm-ai__panel {
    left: 0;
    right: auto;
    border-radius: 0 var(--tdmx-radius, var(--tdm-radius-lg, 16px)) var(--tdmx-radius, var(--tdm-radius-lg, 16px)) 0;
    box-shadow: 12px 0 40px color-mix(in srgb, #000 45%, transparent);
  }
  .tdm-ai--floating[data-dock="right"] .tdm-ai__panel {
    right: 0;
    left: auto;
    border-radius: var(--tdmx-radius, var(--tdm-radius-lg, 16px)) 0 0 var(--tdmx-radius, var(--tdm-radius-lg, 16px));
    box-shadow: -12px 0 40px color-mix(in srgb, #000 45%, transparent);
  }
}

/* ---------- panel ---------- */
.tdm-ai__panel {
  width: 100%;
  /* Inline (embedded) panel follows the same operator width token as the floating
     variant, so the two modes stay visually consistent (A, spec §3.2). */
  max-width: var(--tdm-ai-panel-w, 32rem);
  display: flex;
  flex-direction: column;
  border: 1px solid color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 14%, transparent);
  border-radius: var(--tdmx-radius, var(--tdm-radius-lg, 16px));
  background: var(--tdm-color-surface-2, #141416);
  overflow: hidden;
}
.tdm-ai__panel[hidden] {
  display: none;
}

/* ---------- step machine (A, spec §3.1) ----------
   `data-step` on the panel is the SINGLE source of truth for which region shows.
   Exactly one of gate / chatregion / rating is visible per step; the step swap is
   an instant display change (no transition needed, so no reduced-motion branch).
   Specificity here is (0,3,0) — it beats each region's own base display (0,1,0),
   so no per-element `hidden` juggling is required. */
.tdm-ai__panel[data-step="gate"] .tdm-ai__chatregion,
.tdm-ai__panel[data-step="gate"] .tdm-ai__rating,
.tdm-ai__panel[data-step="chat"] .tdm-ai__gate,
.tdm-ai__panel[data-step="chat"] .tdm-ai__rating,
.tdm-ai__panel[data-step="rating"] .tdm-ai__gate,
.tdm-ai__panel[data-step="rating"] .tdm-ai__chatregion {
  display: none;
}
/* Scroll region wrapping the gate + message log + consent gate. In inline mode it
   is a plain vertical stack (no visible effect); in floating mode it becomes the
   single internal scroller so a tall gate never pushes fields off-screen (GAP 1). */
.tdm-ai__scroll {
  display: flex;
  flex-direction: column;
}

.tdm-ai__head {
  display: flex;
  align-items: center;
  gap: var(--tdm-space-3, 12px);
  padding: var(--tdm-space-4, 16px) var(--tdm-space-5, 24px);
  border-bottom: 1px solid color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 12%, transparent);
}
.tdm-ai__head-avatar {
  flex: none;
  display: inline-flex;
}
.tdm-ai__head-avatar img {
  display: block;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
}
.tdm-ai__head-id {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.tdm-ai__head-name {
  font-family: var(--tdmx-font-heading, var(--tdm-font-headline, system-ui, sans-serif));
  font-size: var(--tdm-text-h4, clamp(16px, 2vw, 18px));
  font-weight: var(--tdm-weight-headline, 600);
  line-height: 1.2;
  color: var(--tdmx-heading, var(--tdm-color-ink, #F5F4F0));
}
.tdm-ai__head-subtitle {
  margin-top: 2px;
  font-family: var(--tdm-font-mono, "DM Mono", ui-monospace, monospace);
  font-size: var(--tdm-text-small, 12px);
  line-height: 1.3;
  color: color-mix(in srgb, var(--tdmx-text, var(--tdm-color-ink-2, #B0B0BA)) 85%, transparent);
}
/* Title bar (header_title) — the accent strip under the header. */
.tdm-ai__titlebar {
  padding: var(--tdm-space-2, 8px) var(--tdm-space-5, 24px);
  border-bottom: 2px solid var(--tdm-ai-accent);
  font-family: var(--tdmx-font-body, var(--tdm-font-body, "DM Sans", system-ui, sans-serif));
  font-size: var(--tdm-text-small, 13px);
  font-weight: 600;
  color: var(--tdmx-text, var(--tdm-color-ink, #F5F4F0));
}
.tdm-ai__close,
.tdm-ai__minimize {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex: none;
  border: none;
  background: transparent;
  color: var(--tdmx-text, var(--tdm-color-ink-2, #B0B0BA));
  border-radius: var(--tdm-radius-sm, 8px);
  cursor: pointer;
  transition: background var(--tdm-motion-fast, 160ms) ease;
}
.tdm-ai__close:hover,
.tdm-ai__minimize:hover {
  background: color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 8%, transparent);
}
.tdm-ai__close:focus-visible,
.tdm-ai__minimize:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tdm-ai-accent) 55%, transparent);
}

/* ---------- message log ---------- */
.tdm-ai__log {
  display: flex;
  flex-direction: column;
  gap: var(--tdm-space-3, 12px);
  padding: var(--tdm-space-5, 24px);
  max-height: 24rem;
  overflow-y: auto;
}
.tdm-ai__msg {
  display: flex;
  max-width: 100%;
}
.tdm-ai__msg--user {
  justify-content: flex-end;
}
.tdm-ai__msg--assistant {
  justify-content: flex-start;
}
.tdm-ai__bubble {
  max-width: 90%;
  padding: var(--tdm-space-3, 12px) var(--tdm-space-4, 16px);
  border-radius: var(--tdm-radius, 12px);
  font-family: var(--tdmx-font-body, var(--tdm-font-body, "DM Sans", system-ui, sans-serif));
  font-size: var(--tdm-text-body, 16px);
  line-height: 1.55;
  color: var(--tdmx-text, var(--tdm-color-ink, #F5F4F0));
  background: color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 7%, transparent);
  word-wrap: break-word;
  overflow-wrap: anywhere;
}
.tdm-ai__msg--user .tdm-ai__bubble {
  background: color-mix(in srgb, var(--tdm-ai-accent) 18%, transparent);
}

/* Typing indicator (cosmetic; reduced-motion disables the animation). */
.tdm-ai__typing {
  display: inline-flex;
  gap: 4px;
  align-items: center;
}
.tdm-ai__typing span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--tdmx-text, var(--tdm-color-ink-2, #B0B0BA));
  opacity: 0.5;
  animation: tdm-ai-blink 1.2s infinite ease-in-out;
}
.tdm-ai__typing span:nth-child(2) { animation-delay: 0.2s; }
.tdm-ai__typing span:nth-child(3) { animation-delay: 0.4s; }
@keyframes tdm-ai-blink {
  0%, 80%, 100% { opacity: 0.3; }
  40% { opacity: 1; }
}

/* ---------- consent gate ---------- */
.tdm-ai__consent {
  margin: 0;
  padding: 0 var(--tdm-space-5, 24px);
  font-family: var(--tdmx-font-body, var(--tdm-font-body, "DM Sans", system-ui, sans-serif));
  font-size: var(--tdm-text-small, 13px);
  line-height: 1.5;
  color: color-mix(in srgb, var(--tdmx-text, var(--tdm-color-ink-2, #B0B0BA)) 80%, transparent);
}
.tdm-ai__consent[hidden] {
  display: none;
}
.tdm-ai__consent-label {
  display: flex;
  align-items: flex-start;
  gap: var(--tdm-space-2, 8px);
  /* The whole row is a tap target; the box meets the 44px floor on its own. */
  min-height: 44px;
  padding: var(--tdm-space-1, 4px) 0;
  cursor: pointer;
}
.tdm-ai__consent-box {
  flex: none;
  width: 20px;
  height: 20px;
  margin: 0;
  /* Generous hit area around the 20px control so the row clears 44px. */
  padding: 12px;
  margin: -12px;
  accent-color: var(--tdm-ai-accent);
  cursor: pointer;
}
.tdm-ai__consent-box:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tdm-ai-accent) 55%, transparent);
  border-radius: var(--tdm-radius-sm, 8px);
}
.tdm-ai__consent-text {
  flex: 1 1 auto;
}
.tdm-ai__consent-link {
  /* Bug 2: AA-safe derived link colour (never the raw operator accent). */
  color: var(--tdm-ai-link-safe, var(--tdm-ai-accent));
  text-decoration: underline;
  text-underline-offset: 2px;
}
.tdm-ai__consent-link:hover {
  text-decoration: none;
}
.tdm-ai__consent-link:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tdm-ai-accent) 55%, transparent);
  border-radius: var(--tdm-radius-sm, 8px);
}
/* Required-but-empty state when a send is attempted without consent. */
.tdm-ai__consent--required .tdm-ai__consent-text {
  /* Bug 2: accent-as-text at 13px → route through the AA-safe derived colour. */
  color: var(--tdm-ai-link-safe, var(--tdm-ai-accent));
  font-weight: 600;
}
.tdm-ai__consent--required .tdm-ai__consent-box {
  outline: 2px solid var(--tdm-ai-accent);
  outline-offset: 2px;
  border-radius: var(--tdm-radius-sm, 8px);
}
/* GAP 2 fix: visible inline validation message revealed when Send is pressed with
   consent unchecked. Injected + toggled in view.js (role="alert"). Accent colour
   matches the required-state text and stays legible on both bands (the accent is
   routed through --tdm-ai-accent, per band-tone Lesson 6). */
.tdm-ai__consent-error {
  margin: var(--tdm-space-1, 4px) 0 0;
  font-family: var(--tdmx-font-body, var(--tdm-font-body, "DM Sans", system-ui, sans-serif));
  font-size: var(--tdm-text-small, 13px);
  font-weight: 600;
  line-height: 1.4;
  /* Bug 2: accent-as-text at 13px → route through the AA-safe derived colour. */
  color: var(--tdm-ai-link-safe, var(--tdm-ai-accent));
}
.tdm-ai__consent-error[hidden] {
  display: none;
}

/* ---------- U4 pre-chat contact gate (spec §9) ---------- */
.tdm-ai__gate {
  display: flex;
  flex-direction: column;
  gap: var(--tdm-space-3, 12px);
  padding: var(--tdm-space-5, 24px);
}
.tdm-ai__gate[hidden] {
  display: none;
}
.tdm-ai__gate-intro {
  margin: 0;
  font-family: var(--tdmx-font-body, var(--tdm-font-body, "DM Sans", system-ui, sans-serif));
  font-size: var(--tdm-text-small, 14px);
  line-height: 1.5;
  color: color-mix(in srgb, var(--tdmx-text, var(--tdm-color-ink-2, #B0B0BA)) 85%, transparent);
}
.tdm-ai__gate-field {
  display: flex;
  flex-direction: column;
  gap: var(--tdm-space-1, 4px);
}
.tdm-ai__gate-label {
  font-family: var(--tdmx-font-body, var(--tdm-font-body, "DM Sans", system-ui, sans-serif));
  font-size: var(--tdm-text-small, 13px);
  font-weight: 600;
  color: var(--tdmx-text, var(--tdm-color-ink, #F5F4F0));
}
.tdm-ai__gate-input {
  width: 100%;
  min-height: 44px;
  padding: var(--tdm-space-3, 12px) var(--tdm-space-4, 16px);
  border: 1px solid color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 16%, transparent);
  border-radius: var(--tdm-radius, 12px);
  background: var(--tdm-color-surface, #0E0E10);
  color: var(--tdmx-text, var(--tdm-color-ink, #F5F4F0));
  font-family: var(--tdmx-font-body, var(--tdm-font-body, "DM Sans", system-ui, sans-serif));
  font-size: var(--tdm-text-body, 16px);
  line-height: 1.45;
}
.tdm-ai__gate-input::placeholder {
  color: color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 45%, transparent);
}
.tdm-ai__gate-input:focus-visible {
  outline: none;
  border-color: var(--tdm-ai-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tdm-ai-accent) 35%, transparent);
}
.tdm-ai__gate-input[aria-invalid="true"] {
  border-color: var(--tdm-ai-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tdm-ai-accent) 35%, transparent);
}

/* ---------- floating labels (B, spec §4.2) ----------
   Markup order is <input placeholder=" "> THEN <label for> (a real, programmatic
   label kept for a11y — WCAG 2.2 / axe), so `input + label` adjacency drives the
   float. The label rests OVER the input (looks like a placeholder) and lifts +
   shrinks on focus OR when the field is non-empty (`:not(:placeholder-shown)`,
   the placeholder=" " making the empty state detectable). Composite-only
   transform + font-size; the transition is reduced-motion-gated below (the end
   state still applies instantly). Top padding is reserved on the input so the
   lifted label never overlaps the typed value. The existing [aria-invalid] state
   is untouched. */
.tdm-ai__gate-field--float {
  position: relative;
  gap: 0; /* label is absolutely positioned — no flow gap */
}
.tdm-ai__gate-field--float .tdm-ai__gate-input {
  /* reserve room at the top for the lifted label */
  padding-block: calc(var(--tdm-space-5, 24px) - 2px) var(--tdm-space-2, 8px);
}
.tdm-ai__gate-field--float .tdm-ai__gate-label {
  position: absolute;
  inset-inline-start: calc(var(--tdm-space-4, 16px) + 1px); /* input padding-inline + 1px border */
  top: 50%;
  transform: translateY(-50%);
  transform-origin: left center;
  margin: 0;
  pointer-events: none; /* clicks pass through to the input */
  font-weight: 500;
  font-size: var(--tdm-text-body, 16px); /* matches the input while resting */
  /* Resting = placeholder-like tone; still AA-legible on the panel surface. */
  color: color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 58%, transparent);
  transition: transform var(--tdm-motion-fast, 160ms) ease, color var(--tdm-motion-fast, 160ms) ease;
}
.tdm-ai__gate-field--float .tdm-ai__gate-input:focus + .tdm-ai__gate-label,
.tdm-ai__gate-field--float .tdm-ai__gate-input:not(:placeholder-shown) + .tdm-ai__gate-label {
  transform: translateY(calc(-50% - 0.85rem)) scale(0.78);
  font-weight: 600;
  /* Floated = full-strength ink (AA on the panel surface). */
  color: var(--tdmx-text, var(--tdm-color-ink, #F5F4F0));
}
.tdm-ai__gate-submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  margin-top: var(--tdm-space-1, 4px);
  padding: var(--tdm-space-2, 8px) var(--tdm-space-5, 24px);
  border: 1px solid var(--tdm-ai-accent);
  border-radius: var(--tdm-radius, 12px);
  background: var(--tdm-ai-accent);
  color: #FFFFFF;
  font-family: var(--tdmx-font-body, var(--tdm-font-body, "DM Sans", system-ui, sans-serif));
  font-size: var(--tdm-text-body, 16px);
  font-weight: 600;
  cursor: pointer;
  transition: background var(--tdm-motion-fast, 160ms) ease;
}
.tdm-ai__gate-submit:hover {
  background: color-mix(in srgb, var(--tdm-ai-accent) 86%, #000);
}
.tdm-ai__gate-submit:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tdm-ai-accent) 55%, transparent);
}

/* ---------- input form ---------- */
.tdm-ai__form {
  display: flex;
  align-items: flex-end;
  gap: var(--tdm-space-2, 8px);
  padding: var(--tdm-space-4, 16px) var(--tdm-space-5, 24px) var(--tdm-space-5, 24px);
}
.tdm-ai__input {
  flex: 1 1 auto;
  min-height: 44px;
  padding: var(--tdm-space-3, 12px) var(--tdm-space-4, 16px);
  border: 1px solid color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 16%, transparent);
  border-radius: var(--tdm-radius, 12px);
  background: var(--tdm-color-surface, #0E0E10);
  color: var(--tdmx-text, var(--tdm-color-ink, #F5F4F0));
  font-family: var(--tdmx-font-body, var(--tdm-font-body, "DM Sans", system-ui, sans-serif));
  font-size: var(--tdm-text-body, 16px);
  line-height: 1.45;
  resize: none;
}
.tdm-ai__input::placeholder {
  color: color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 45%, transparent);
}
.tdm-ai__input:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.tdm-ai__input:focus-visible {
  outline: none;
  border-color: var(--tdm-ai-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tdm-ai-accent) 35%, transparent);
}
.tdm-ai__send {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex: none;
  border: 1px solid var(--tdm-ai-accent);
  border-radius: var(--tdm-radius, 12px);
  background: var(--tdm-ai-accent);
  color: #FFFFFF;
  cursor: pointer;
  transition: background var(--tdm-motion-fast, 160ms) ease;
}
.tdm-ai__send:hover {
  background: color-mix(in srgb, var(--tdm-ai-accent) 86%, #000);
}
.tdm-ai__send:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.tdm-ai__send:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tdm-ai-accent) 55%, transparent);
}

/* ---------- turnstile slot ---------- */
.tdm-ai__turnstile {
  padding: 0 var(--tdm-space-5, 24px) var(--tdm-space-4, 16px);
}
.tdm-ai__turnstile[hidden] {
  display: none;
}
.tdm-ai__note {
  margin: 0;
  font-family: var(--tdmx-font-body, var(--tdm-font-body, "DM Sans", system-ui, sans-serif));
  font-size: var(--tdm-text-small, 13px);
  line-height: 1.5;
  color: color-mix(in srgb, var(--tdmx-text, var(--tdm-color-ink-2, #B0B0BA)) 80%, transparent);
}

/* ---------- offline fallback ---------- */
.tdm-ai__offline {
  display: flex;
  flex-direction: column;
  gap: var(--tdm-space-4, 16px);
  padding: var(--tdm-space-5, 24px);
}
.tdm-ai__contact,
.tdm-ai__cta {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  min-height: 44px;
  padding: var(--tdm-space-2, 8px) var(--tdm-space-5, 24px);
  border-radius: var(--tdmx-radius, var(--tdm-radius-pill, 999px));
  background: var(--tdm-ai-accent);
  color: #FFFFFF;
  text-decoration: none;
  font-weight: 600;
}
.tdm-ai__contact:hover,
.tdm-ai__cta:hover {
  background: color-mix(in srgb, var(--tdm-ai-accent) 86%, #000);
}

/* ---------- rating region (D, spec §5.3) ----------
   Shown only at data-step="rating" (step machine above). 5 accessible stars: the
   radio is visually-hidden + present in the DOM BEFORE its label, so `+`/`~`
   sibling selectors drive the fill without any JS. `.tdm-ai__rating-star` is the
   ≥44px tap target; `.tdm-ai__rating-star-icon` is the 28px glyph. Fill colour =
   the widget's shared --tdm-ai-accent (legible on both bands); empty = the
   --tdm-ai-star-empty var (re-toned on the light band). Buttons reuse the primary
   (send) / text (skip) styles already established for this widget. */
.tdm-ai__rating {
  display: flex;
  flex-direction: column;
  gap: var(--tdm-space-4, 16px);
  padding: var(--tdm-space-5, 24px);
}
.tdm-ai__rating-intro {
  margin: 0;
  font-family: var(--tdmx-font-heading, var(--tdm-font-headline, system-ui, sans-serif));
  font-size: var(--tdm-text-h4, clamp(16px, 2vw, 18px));
  font-weight: var(--tdm-weight-headline, 600);
  line-height: 1.3;
  color: var(--tdmx-heading, var(--tdm-color-ink, #F5F4F0));
}
.tdm-ai__rating-stars {
  display: flex;
  gap: var(--tdm-space-1, 4px);
}
.tdm-ai__rating-star {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  cursor: pointer;
  color: var(--tdm-ai-star-empty);
  transition: color var(--tdm-motion-fast, 160ms) ease, transform var(--tdm-motion-fast, 160ms) ease;
}
.tdm-ai__rating-star-icon {
  display: block;
  width: 28px;
  height: 28px;
}
/* Checked fill (persistent) — the checked star + every star BEFORE it. Gated by
   :not(:hover) on the group so a hover preview (below) fully takes over while the
   pointer is down, with no specificity fight. */
.tdm-ai__rating-stars:not(:hover) .tdm-ai__rating-radio:checked + .tdm-ai__rating-star,
.tdm-ai__rating-stars:not(:hover) .tdm-ai__rating-star:has(~ .tdm-ai__rating-radio:checked) {
  color: var(--tdm-ai-accent);
}
/* Hover preview — the hovered star + every star before it, while the group is
   hovered (`~ .tdm-ai__rating-star:hover` reaches earlier siblings). */
.tdm-ai__rating-stars:hover .tdm-ai__rating-star:hover,
.tdm-ai__rating-stars:hover .tdm-ai__rating-star:has(~ .tdm-ai__rating-star:hover) {
  color: var(--tdm-ai-accent);
}
.tdm-ai__rating-star:hover {
  transform: scale(1.06);
}
/* Keyboard focus ring surfaced through the visually-hidden radio. */
.tdm-ai__rating-radio:focus-visible + .tdm-ai__rating-star {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tdm-ai-accent) 45%, transparent);
  border-radius: var(--tdm-radius-sm, 8px);
}
.tdm-ai__rating-comment-field {
  display: flex;
  flex-direction: column;
  gap: var(--tdm-space-1, 4px);
}
.tdm-ai__rating-comment-label {
  font-family: var(--tdmx-font-body, var(--tdm-font-body, "DM Sans", system-ui, sans-serif));
  font-size: var(--tdm-text-small, 13px);
  font-weight: 600;
  color: var(--tdmx-text, var(--tdm-color-ink, #F5F4F0));
}
.tdm-ai__rating-comment {
  width: 100%;
  min-height: 72px;
  padding: var(--tdm-space-3, 12px) var(--tdm-space-4, 16px);
  border: 1px solid color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 16%, transparent);
  border-radius: var(--tdm-radius, 12px);
  background: var(--tdm-color-surface, #0E0E10);
  color: var(--tdmx-text, var(--tdm-color-ink, #F5F4F0));
  font-family: var(--tdmx-font-body, var(--tdm-font-body, "DM Sans", system-ui, sans-serif));
  font-size: var(--tdm-text-body, 16px);
  line-height: 1.5;
  resize: vertical;
}
.tdm-ai__rating-comment::placeholder {
  color: color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 45%, transparent);
}
.tdm-ai__rating-comment:focus-visible {
  outline: none;
  border-color: var(--tdm-ai-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tdm-ai-accent) 35%, transparent);
}
.tdm-ai__rating-actions {
  display: flex;
  align-items: center;
  gap: var(--tdm-space-3, 12px);
}
/* Send = primary button (mirrors .tdm-ai__gate-submit). */
.tdm-ai__rating-send {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: var(--tdm-space-2, 8px) var(--tdm-space-5, 24px);
  border: 1px solid var(--tdm-ai-accent);
  border-radius: var(--tdm-radius, 12px);
  background: var(--tdm-ai-accent);
  color: #FFFFFF;
  font-family: var(--tdmx-font-body, var(--tdm-font-body, "DM Sans", system-ui, sans-serif));
  font-size: var(--tdm-text-body, 16px);
  font-weight: 600;
  cursor: pointer;
  transition: background var(--tdm-motion-fast, 160ms) ease;
}
.tdm-ai__rating-send:hover {
  background: color-mix(in srgb, var(--tdm-ai-accent) 86%, #000);
}
.tdm-ai__rating-send:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tdm-ai-accent) 55%, transparent);
}
/* Skip = quiet text button (secondary affordance), still a ≥44px target. */
.tdm-ai__rating-skip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: var(--tdm-space-2, 8px) var(--tdm-space-4, 16px);
  border: none;
  background: transparent;
  color: var(--tdmx-text, var(--tdm-color-ink-2, #B0B0BA));
  font-family: var(--tdmx-font-body, var(--tdm-font-body, "DM Sans", system-ui, sans-serif));
  font-size: var(--tdm-text-body, 16px);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  border-radius: var(--tdm-radius-sm, 8px);
  cursor: pointer;
}
.tdm-ai__rating-skip:hover {
  text-decoration: none;
  color: var(--tdmx-text, var(--tdm-color-ink, #F5F4F0));
}
.tdm-ai__rating-skip:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tdm-ai-accent) 55%, transparent);
}

/* ---------- a11y helper ---------- */
.tdm-ai__visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ======================================================================
   Attention nudge — tooltip bubble + pulse ring + unread dot.
   Composite-only (opacity / transform). Reduced-motion handled below.
   ====================================================================== */
.tdm-ai__nudge[hidden] { display: none; }

/* tooltip bubble — appears next to the launcher. */
.tdm-ai__nudge--tooltip {
  position: relative;
  max-width: 230px;
  margin-bottom: var(--tdm-space-2, 8px);
  padding: var(--tdm-space-3, 12px) var(--tdm-space-6, 32px) var(--tdm-space-3, 12px) var(--tdm-space-4, 16px);
  border: 1px solid color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 14%, transparent);
  border-radius: var(--tdm-radius, 14px);
  background: var(--tdm-color-surface-2, #141416);
  color: var(--tdmx-text, var(--tdm-color-ink, #F5F4F0));
  font-family: var(--tdmx-font-body, var(--tdm-font-body, "DM Sans", system-ui, sans-serif));
  font-size: var(--tdm-text-small, 14px);
  line-height: 1.45;
  box-shadow: 0 8px 26px rgba(0,0,0,0.45);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity var(--tdm-motion-normal, 250ms) ease, transform var(--tdm-motion-normal, 250ms) ease;
}
.tdm-ai__nudge--tooltip.is-shown {
  opacity: 1;
  transform: translateY(0);
}
/* In floating mode the tooltip is fixed just above the launcher (left side). */
.tdm-ai--floating .tdm-ai__nudge--tooltip {
  position: fixed;
  z-index: 2147483000;
  left: var(--tdm-ai-offset-x, 24px);
  max-width: min(230px, calc(100vw - 40px));
}
.tdm-ai--floating[data-position="bottom-left"] .tdm-ai__nudge--tooltip {
  bottom: calc(max(var(--tdm-ai-offset-y, 24px), env(safe-area-inset-bottom)) + var(--tdm-ai-launcher-size) + var(--tdm-space-3, 12px));
}
.tdm-ai--floating[data-position="middle-left"] .tdm-ai__nudge--tooltip {
  top: calc(50% - var(--tdm-ai-launcher-size));
}
.tdm-ai__nudge-text { display: block; }
.tdm-ai__nudge-close {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  color: var(--tdmx-text, var(--tdm-color-ink-2, #B0B0BA));
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  border-radius: var(--tdm-radius-sm, 8px);
}
.tdm-ai__nudge-close:hover {
  background: color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 8%, transparent);
}
.tdm-ai__nudge-close:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tdm-ai-accent) 55%, transparent);
}

/* pulse ring — a finite, gentle ring around the launcher while nudging. */
.tdm-ai--nudge-pulse .tdm-ai__launcher {
  position: relative;
}
.tdm-ai--nudge-pulse .tdm-ai__launcher::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  border: 2px solid var(--tdm-ai-accent);
  opacity: 0.7;
  animation: tdm-ai-pulse 1.6s ease-out 3;
  pointer-events: none;
}
@keyframes tdm-ai-pulse {
  0%   { transform: scale(1);    opacity: 0.7; }
  100% { transform: scale(1.6);  opacity: 0; }
}

/* unread dot — a small badge on the launcher. */
.tdm-ai--nudge-dot .tdm-ai__launcher::before {
  content: "";
  position: absolute;
  top: -2px;
  right: -2px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--tdm-ai-accent);
  border: 2px solid var(--tdm-color-surface, #0E0E10);
  pointer-events: none;
}

/* ======================================================================
   Band-tone — LIGHT band re-tones the opaque inner surfaces (Lesson 6).
   Plain attribute selector (specificity 0,1,1), never :where(). Dark band is
   the default (no attr) and needs no override. The accent flows through
   --tdm-ai-accent so the orange stays legible on both bands.
   ====================================================================== */
.tdm-block[data-band="light"].tdm-ai .tdm-ai__panel {
  background: color-mix(in srgb, #000 2%, #FFFFFF);
  border-color: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 14%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__head {
  border-bottom-color: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 12%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__head-name,
.tdm-block[data-band="light"].tdm-ai .tdm-ai__titlebar {
  color: var(--tdmx-heading, var(--tdm-color-surface, #0E0E10));
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__head-subtitle {
  color: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 65%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__nudge--tooltip {
  background: color-mix(in srgb, #000 2%, #FFFFFF);
  color: var(--tdm-color-surface, #0E0E10);
  border-color: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 14%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__bubble {
  color: var(--tdmx-text, var(--tdm-color-surface, #0E0E10));
  background: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 6%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__msg--user .tdm-ai__bubble {
  background: color-mix(in srgb, var(--tdm-ai-accent) 16%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__close,
.tdm-block[data-band="light"].tdm-ai .tdm-ai__minimize {
  color: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 70%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__input {
  background: color-mix(in srgb, #000 4%, #FFFFFF);
  color: var(--tdm-color-surface, #0E0E10);
  border-color: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 18%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__input::placeholder {
  color: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 45%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__consent,
.tdm-block[data-band="light"].tdm-ai .tdm-ai__note {
  color: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 65%, transparent);
}
/* U4 gate re-tones on the light band (Lesson 6 — plain attribute selector). */
.tdm-block[data-band="light"].tdm-ai .tdm-ai__gate-intro {
  color: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 70%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__gate-label {
  color: var(--tdmx-text, var(--tdm-color-surface, #0E0E10));
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__gate-input {
  background: color-mix(in srgb, #000 4%, #FFFFFF);
  color: var(--tdm-color-surface, #0E0E10);
  border-color: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 18%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__gate-input::placeholder {
  color: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 45%, transparent);
}
/* Bug 2 (light band): the panel is near-white here, so the safe-link derivation is
   FLIPPED to DARKEN the accent toward the dark surface (instead of lightening toward
   ink on the dark band). 52% surface keeps the accent hue while realistic accents land
   ~5-11:1; a near-white accent is a degenerate operator choice (an invisible launcher —
   the Personalize UI already warns to aim for AA) and is out of scope. Verified by WCAG
   calc for blue/orange/yellow on the ~#FAFAFA light-band panel. */
.tdm-block[data-band="light"].tdm-ai {
  --tdm-ai-link-safe: color-mix(in srgb, var(--tdm-ai-accent) 48%, var(--tdm-color-surface, #0E0E10));
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__consent-link,
.tdm-block[data-band="light"].tdm-ai .tdm-ai__consent--required .tdm-ai__consent-text,
.tdm-block[data-band="light"].tdm-ai .tdm-ai__consent-error {
  color: var(--tdm-ai-link-safe, var(--tdm-ai-accent));
}
/* Floating labels (B) re-tone on the light band — rest = placeholder-like on the
   light surface, floated = full-strength dark ink (both AA). */
.tdm-block[data-band="light"].tdm-ai .tdm-ai__gate-field--float .tdm-ai__gate-label {
  color: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 58%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__gate-field--float .tdm-ai__gate-input:focus + .tdm-ai__gate-label,
.tdm-block[data-band="light"].tdm-ai .tdm-ai__gate-field--float .tdm-ai__gate-input:not(:placeholder-shown) + .tdm-ai__gate-label {
  color: var(--tdmx-text, var(--tdm-color-surface, #0E0E10));
}
/* Rating region (D) re-tones on the light band (accent fill stays orange). */
.tdm-block[data-band="light"].tdm-ai .tdm-ai__rating-stars {
  --tdm-ai-star-empty: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 26%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__rating-intro {
  color: var(--tdmx-heading, var(--tdm-color-surface, #0E0E10));
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__rating-comment-label {
  color: var(--tdmx-text, var(--tdm-color-surface, #0E0E10));
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__rating-comment {
  background: color-mix(in srgb, #000 4%, #FFFFFF);
  color: var(--tdm-color-surface, #0E0E10);
  border-color: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 18%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__rating-comment::placeholder {
  color: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 45%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__rating-skip {
  color: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 70%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__rating-skip:hover {
  color: var(--tdm-color-surface, #0E0E10);
}

/* ======================================================================
   prefers-reduced-motion — disable all non-essential animation (HARD gate).
   ====================================================================== */
@media (prefers-reduced-motion: reduce) {
  .tdm-ai__launcher,
  .tdm-ai__close,
  .tdm-ai__minimize,
  .tdm-ai__send {
    transition: none;
  }
  /* B — floating label: keep the lifted END state, drop the motion. */
  .tdm-ai__gate-field--float .tdm-ai__gate-label {
    transition: none;
  }
  /* D — rating stars: no colour/scale transition, no hover pop. */
  .tdm-ai__rating-star,
  .tdm-ai__rating-send {
    transition: none;
  }
  .tdm-ai__rating-star:hover {
    transform: none;
  }
  .tdm-ai__typing span {
    animation: none;
    opacity: 0.6;
  }
  /* Nudge: no motion. Pulse ring is killed; the tooltip still appears (it is not
     motion-essential) but without the slide-in transform. */
  .tdm-ai--nudge-pulse .tdm-ai__launcher::after {
    animation: none;
    opacity: 0;
  }
  .tdm-ai__nudge--tooltip {
    transition: none;
    transform: none;
  }
  .tdm-ai__nudge--tooltip.is-shown {
    transform: none;
  }
  /* Animated launcher icon: show the STATIC poster, hide the animated source
     (zero motion). When no poster is set, the animated frame is left in place
     but its decode-as-animation is the browser's call — we hide it only when a
     poster exists, so the icon never disappears. */
  .tdm-ai__launcher-animated:has(.tdm-ai__launcher-anim-poster) .tdm-ai__launcher-anim-img {
    display: none;
  }
  .tdm-ai__launcher-animated .tdm-ai__launcher-anim-poster {
    opacity: 1;
  }
  /* Bundled animated-svg icon: SMIL animation does NOT respond to CSS, so the
     freeze (pauseAnimations + setCurrentTime(0) on the first frame) is performed
     in view.js. Nothing to disable here beyond suppressing any wrap transition. */
  .tdm-ai__launcher-svgwrap,
  .tdm-ai__launcher-svg {
    transition: none;
  }
}

/* ======================================================================
   RAIL REDESIGN (design-spec-ai-chat-rail-v2). Additive section: persistent
   page-context card, header status dot, sticky quote bar, orange left-rail
   bubbles, full-height drawer distribution + Rail motion. All composite-only,
   reduced-motion gated at the end.
   ====================================================================== */

/* ---------- full-height distribution ---------- */
/* The drawer is a flex column (panel). In Rail the header + context card pin at
   top, the chat region fills + scrolls internally, and the sticky quote bar +
   composer pin at the bottom of the chat region. min-height:0 lets flex children
   shrink below content height so the inner scroller works. The titlebar is hidden
   (the context card carries the page signal) but kept in the DOM for the
   light-band re-tone selectors. */
.tdm-ai__titlebar {
  display: none;
}
.tdm-ai__chatregion {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.tdm-ai--floating .tdm-ai__context,
.tdm-ai--floating .tdm-ai__quotebar {
  flex: none;
}
.tdm-ai--floating .tdm-ai__chatregion {
  flex: 1 1 auto;
  min-height: 0;
}
/* In the drawer the log fills its scroller rather than capping at 24rem. */
.tdm-ai--floating .tdm-ai__log {
  max-height: none;
}

/* ---------- header status dot (§1.3) ---------- */
/* 8px dot before the subtitle. Stacked amber (AI) + green (agent) dots cross-fade
   opacity on takeover — composite, never background-color (motion-spec fix #3). */
.tdm-ai__head-subtitle {
  display: inline-flex;
  align-items: center;
  gap: var(--tdm-space-2, 8px);
}
.tdm-ai__status-dot {
  position: relative;
  flex: none;
  width: 8px;
  height: 8px;
}
.tdm-ai__status-dot::before,
.tdm-ai__status-dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
}
.tdm-ai__status-dot::before {
  background: var(--tdm-ai-accent);
  opacity: 1;
  transition: opacity var(--tdm-motion-normal, 250ms) ease;
}
.tdm-ai__status-dot::after {
  background: var(--tdm-ai-status-online, #35C77E);
  opacity: 0;
  transition: opacity var(--tdm-motion-normal, 250ms) ease;
}
.tdm-ai--takeover .tdm-ai__status-dot::before { opacity: 0; }
.tdm-ai--takeover .tdm-ai__status-dot::after { opacity: 1; }

/* ---------- persistent page-context card (§1.4 / §2) ---------- */
.tdm-ai__context {
  position: relative;
  margin: var(--tdm-space-4, 16px) var(--tdm-space-5, 24px) 0;
  padding: var(--tdm-space-4, 16px);
  padding-left: calc(var(--tdm-space-4, 16px) + 4px);
  border: 1px solid var(--tdm-hairline, color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 14%, transparent));
  border-radius: var(--tdm-radius-lg, 12px);
  background: var(--tdm-color-surface-3, #1C1C20);
}
/* 2px accent left-rail; turns green on takeover. */
.tdm-ai__context::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  border-radius: 2px 0 0 2px;
  background: var(--tdm-ai-accent);
  transition: background var(--tdm-motion-fast, 160ms) ease;
}
.tdm-ai--takeover .tdm-ai__context::before {
  background: var(--tdm-ai-status-online, #35C77E);
}
.tdm-ai__context-page[hidden],
.tdm-ai__context-agent[hidden] {
  display: none;
}
.tdm-ai__context-eyebrow {
  display: block;
  font-family: var(--tdm-font-mono, "General Sans", system-ui, sans-serif);
  font-size: var(--tdm-text-eyebrow, 11px);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--tdm-ai-accent-text-safe, var(--tdm-ai-accent));
}
.tdm-ai__context-eyebrow--live {
  color: var(--tdm-ai-status-online, #35C77E);
}
.tdm-ai__context-body {
  display: flex;
  align-items: center;
  gap: var(--tdm-space-3, 12px);
  margin-top: var(--tdm-space-2, 8px);
}
.tdm-ai__context-thumb {
  flex: none;
  display: inline-flex;
}
.tdm-ai__context-thumb img {
  display: block;
  width: 52px;
  height: 52px;
  border-radius: var(--tdm-radius-sm, 8px);
  object-fit: cover;
}
.tdm-ai__context-agent-avatar {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--tdm-ai-status-online, #35C77E) 22%, var(--tdm-color-surface-3, #1C1C20));
  color: var(--tdmx-heading, var(--tdm-color-ink, #F5F4F0));
  font-family: var(--tdm-font-mono, "General Sans", system-ui, sans-serif);
  font-size: 13px;
  font-weight: 600;
}
.tdm-ai__context-text {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--tdm-space-1, 4px);
}
.tdm-ai__context-title {
  font-family: var(--tdmx-font-heading, var(--tdm-font-headline, system-ui, sans-serif));
  font-size: 17px;
  font-weight: var(--tdm-weight-headline, 600);
  line-height: 1.25;
  color: var(--tdmx-heading, var(--tdm-color-ink, #F5F4F0));
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tdm-ai__context-sub {
  font-family: var(--tdm-font-mono, "General Sans", system-ui, sans-serif);
  font-size: var(--tdm-text-caption, 12px);
  line-height: 1.3;
  color: var(--tdm-ai-meta, #909099);
}
.tdm-ai__context-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--tdm-space-1, 6px);
}
.tdm-ai__context-chip {
  font-family: var(--tdm-font-mono, "General Sans", system-ui, sans-serif);
  font-size: var(--tdm-text-eyebrow, 11px);
  line-height: 1;
  padding: 5px 8px;
  border-radius: var(--tdm-radius-sm, 4px);
  color: var(--tdmx-text, var(--tdm-color-ink, #F5F4F0));
  background: color-mix(in srgb, var(--tdm-color-ink, #F5F4F0) 10%, transparent);
}

/* ---------- sticky quote bar (§1.6) ---------- */
.tdm-ai__quotebar {
  padding: var(--tdm-space-3, 12px) var(--tdm-space-5, 24px) 0;
}
.tdm-ai__quotebar-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--tdm-space-2, 8px);
  width: 100%;
  min-height: 48px;
  padding: var(--tdm-space-2, 8px) var(--tdm-space-4, 16px);
  border-radius: var(--tdm-radius, 12px);
  background: var(--tdm-ai-accent);
  color: #FFFFFF;
  text-decoration: none;
  font-family: var(--tdmx-font-heading, var(--tdm-font-headline, system-ui, sans-serif));
  font-size: 15px;
  font-weight: 600;
  transition: background var(--tdm-motion-fast, 160ms) ease, transform var(--tdm-motion-fast, 160ms) ease;
}
.tdm-ai__quotebar-btn:hover {
  background: color-mix(in srgb, var(--tdm-ai-accent) 88%, #000);
  transform: translateY(-2px);
}
.tdm-ai__quotebar-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tdm-ai-accent) 55%, transparent);
}
.tdm-ai__quotebar-arrow {
  flex: none;
}

/* ---------- bubbles: orange left-rail (§1.5) ---------- */
/* The Rail signature in the log: a 2px accent left-rail on assistant bubbles.
   Note-variant bubbles keep the neutral look (no rail) per design-spec §3 #6. */
.tdm-ai__msg--assistant .tdm-ai__bubble {
  border-left: 2px solid var(--tdm-ai-accent);
  border-top-left-radius: var(--tdm-radius-sm, 4px);
  border-bottom-left-radius: var(--tdm-radius-sm, 4px);
}
.tdm-ai__msg--assistant .tdm-ai__bubble--note {
  border-left: 0;
  border-top-left-radius: var(--tdm-radius, 12px);
  border-bottom-left-radius: var(--tdm-radius, 12px);
}

/* ---------- Rail motion (motion-spec §1) ---------- */
/* Signature drawer slide-in: translateX(-100%/100% → 0) + opacity, decelerate.
   Runs each time the panel is re-shown (display flips from none). Composite-only;
   animate translateX, never left/width. */
.tdm-ai--floating .tdm-ai__panel:not([hidden]) {
  animation-duration: var(--tdm-dur-base, 250ms);
  animation-timing-function: var(--tdm-ease-emphatic, cubic-bezier(0.16, 1, 0.3, 1));
  animation-fill-mode: both;
}
.tdm-ai--floating[data-dock="left"] .tdm-ai__panel:not([hidden]) {
  animation-name: tdm-ai-drawer-in-left;
}
.tdm-ai--floating[data-dock="right"] .tdm-ai__panel:not([hidden]) {
  animation-name: tdm-ai-drawer-in-right;
}
@keyframes tdm-ai-drawer-in-left {
  from { transform: translateX(-100%); opacity: 0; }
  to   { transform: translateX(0); opacity: 1; }
}
@keyframes tdm-ai-drawer-in-right {
  from { transform: translateX(100%); opacity: 0; }
  to   { transform: translateX(0); opacity: 1; }
}
/* Micro: message-in translateY(8px→0) + opacity, one-shot. */
.tdm-ai__msg {
  animation: tdm-ai-msg-in var(--tdm-dur-base, 250ms) var(--tdm-ease-emphatic, cubic-bezier(0.16, 1, 0.3, 1)) both;
}
@keyframes tdm-ai-msg-in {
  from { transform: translateY(8px); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}

/* ======================================================================
   RAIL band-tone — LIGHT band re-tones the new Rail surfaces (Lesson 6).
   Plain attribute selector (specificity 0,2,1), never :where(). Accent FILLS
   (quote bar, status dot, left-rail) are label-vs-fill pairs → band-independent;
   only accent-AS-TEXT (eyebrow, meta) remaps.
   ====================================================================== */
.tdm-block[data-band="light"].tdm-ai {
  /* Eyebrow / small accent text → burnt on cream (design-spec §5). Meta darkens. */
  --tdm-ai-accent-text-safe: var(--tdm-color-accent-text-light, #B0470B);
  /* 65% (raised from 55%): the composited 12px meta on the light card computes
     ~5.8:1 (#F0F0F0 card) / ~5.9:1 (#FAFAFA) = AA body PASS (55% landed ~4.1:1). */
  --tdm-ai-meta: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 65%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__context {
  background: color-mix(in srgb, #000 6%, #FFFFFF);
  border-color: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 14%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__context-title {
  color: var(--tdmx-heading, var(--tdm-color-surface, #0E0E10));
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__context-chip {
  color: var(--tdm-color-surface, #0E0E10);
  background: color-mix(in srgb, var(--tdm-color-surface, #0E0E10) 8%, transparent);
}
.tdm-block[data-band="light"].tdm-ai .tdm-ai__context-agent-avatar {
  color: var(--tdm-color-surface, #0E0E10);
}

/* ---------- Rail reduced-motion (HARD gate) ---------- */
@media (prefers-reduced-motion: reduce) {
  /* Drawer appears instantly at rest; messages instant; dot renders final state;
     quote-bar / accent-bar hold their end colour. Hover lifts are kept. */
  .tdm-ai--floating .tdm-ai__panel:not([hidden]),
  .tdm-ai__msg {
    animation: none !important;
  }
  .tdm-ai__status-dot::before,
  .tdm-ai__status-dot::after,
  .tdm-ai__context::before,
  .tdm-ai__quotebar-btn {
    transition: none;
  }
}


/* ============================================================
   ARECH Footer block — front-end styles.

   Port of the FOOTER in
     prototypes/footer-explore-2026-05-19/footer-A-classic.html
   re-tokenized to the theme tokens (main.css :root) and corrected to the
   responsive standard (responsive_manual_en_0.1):
     • min-width media queries ONLY (no max-width);
     • the prototype's --container-wide:1440 inner becomes the canonical
       container box (--container 1140/1200 + --container-px gutter) so the
       footer caps identically to the navbar + page content;
     • subtle white hairlines use color-mix() (modern CSS, S72 direction);
     • small body text uses --muted-accessible / --light for WCAG AA contrast
       (the prototype's flat --muted #6b6b75 fails 4.5:1 on --dark-2).

   ALL rules are scoped under `.arech-footer` so nothing leaks into the theme.
   ============================================================ */

.arech-footer {
    background: var(--dark-2);
    border-top: 1px solid color-mix(in oklch, var(--white) 4%, transparent);
    padding-block: var(--space-9) var(--space-7);
    color: var(--light);
    font-family: var(--font-body);
}

.arech-footer__inner {
    max-width: calc(var(--container) + 2 * var(--container-px));
    margin-inline: auto;
    padding-inline: var(--container-px);
}

/* -------- COLUMN GRID -------- */
.arech-footer__cols {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-6);
}
@media (min-width: 768px) {
    .arech-footer__cols {
        grid-template-columns: 1fr 1fr 1fr;
        grid-template-areas:
            "brand brand brand"
            "products company legal";
        gap: var(--space-5);
    }
    .arech-footer__col--brand    { grid-area: brand; }
    .arech-footer__col--products { grid-area: products; }
    .arech-footer__col--company  { grid-area: company; }
    .arech-footer__col--legal    { grid-area: legal; }
}
@media (min-width: 1024px) {
    .arech-footer__cols {
        grid-template-columns: 2fr 1fr 1fr 1fr;
        grid-template-areas: "brand products company legal";
        gap: var(--space-6);
    }
}

/* Discrete vertical separators sitting in the middle of the column gap. */
@media (min-width: 768px) {
    .arech-footer__col--company,
    .arech-footer__col--legal { position: relative; }
    .arech-footer__col--company::before,
    .arech-footer__col--legal::before {
        content: '';
        position: absolute;
        inset-inline-start: calc(var(--space-5) / -2);
        inset-block: 0;
        inline-size: 1px;
        background: color-mix(in oklch, var(--white) 6%, transparent);
    }
}
@media (min-width: 1024px) {
    .arech-footer__col--products { position: relative; }
    .arech-footer__col--products::before {
        content: '';
        position: absolute;
        inset-inline-start: calc(var(--space-6) / -2);
        inset-block: 0;
        inline-size: 1px;
        background: color-mix(in oklch, var(--white) 6%, transparent);
    }
    .arech-footer__col--company::before,
    .arech-footer__col--legal::before {
        inset-inline-start: calc(var(--space-6) / -2);
    }
}

/* -------- BRAND COLUMN -------- */
.arech-footer__col--brand {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
}
.arech-footer__logo {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    text-decoration: none;
    align-self: flex-start;
}
.arech-footer__logo:focus-visible {
    outline: 2px solid var(--orange);
    outline-offset: 2px;
}
.arech-footer__logo-img {
    height: 44px;
    width: auto;
    display: block;
}
.arech-footer__tagline {
    font-style: italic;
    font-weight: 300;
    font-size: 14px;
    line-height: 1.6;
    color: var(--muted-accessible);
    max-width: 42ch;
    margin: 0;
}

/* Social media row */
.arech-footer__social {
    list-style: none;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0;
    padding: 0;
}
.arech-footer__social a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    color: var(--muted-accessible);
    text-decoration: none;
    border-radius: var(--radius-xs);
    transition: color var(--motion-fast) var(--ease-standard),
                background var(--motion-fast) var(--ease-standard);
}
.arech-footer__social a:hover,
.arech-footer__social a:focus-visible {
    color: var(--off-white);
    background: color-mix(in oklch, var(--white) 5%, transparent);
}
.arech-footer__social a:focus-visible {
    outline: 2px solid var(--orange);
    outline-offset: 2px;
}
.arech-footer__social svg {
    width: 18px;
    height: 18px;
    display: block;
}

/* -------- LINK COLUMNS -------- */
.arech-footer__head {
    font-family: var(--font-headline);
    font-weight: 500;
    font-size: 20px;
    line-height: 1.3;
    color: var(--off-white);
    margin: 0 0 var(--space-5);
}
.arech-footer__links {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin: 0;
    padding: 0;
}
.arech-footer__links a {
    display: inline-flex;
    align-items: center;
    min-height: 24px;
    font-size: 14px;
    font-weight: 400;
    color: var(--light);
    text-decoration: none;
    transition: color var(--motion-fast) var(--ease-standard);
}
.arech-footer__links a:hover,
.arech-footer__links a:focus-visible { color: var(--off-white); }
.arech-footer__links a:focus-visible {
    outline: 2px solid var(--orange);
    outline-offset: 2px;
}
.arech-footer__links .arech-footer__all {
    color: var(--orange);
    font-weight: 500;
    margin-top: var(--space-2);
}
.arech-footer__links .arech-footer__all:hover,
.arech-footer__links .arech-footer__all:focus-visible { color: var(--orange-bright); }

/* -------- BASE ROW -------- */
.arech-footer__base {
    margin-top: var(--space-8);
    padding-top: var(--space-7);
    border-top: 1px solid color-mix(in oklch, var(--white) 4%, transparent);
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-5);
}
@media (min-width: 1024px) {
    .arech-footer__base {
        grid-template-columns: 1fr auto;
        align-items: start;
        gap: var(--space-8);
    }
}
.arech-footer__copyright {
    font-size: 13px;
    line-height: 1.55;
    color: var(--muted-accessible);
    max-width: 60ch;
    margin: 0;
}
.arech-footer__addresses {
    display: flex;
    flex-direction: column;
    gap: 6px;
    font-family: var(--font-mono);
    font-size: 11px;
    line-height: 1.7;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted-accessible);
    font-style: normal;
}
@media (min-width: 1024px) {
    .arech-footer__addresses {
        text-align: end;
        align-items: flex-end;
    }
}

/* Images inside the footer never overflow (responsive standard §). */
.arech-footer img {
    max-width: 100%;
    height: auto;
    display: block;
}

/* -------- TDM CREDIT (discreet build attribution) -------- */
.arech-footer__credit {
    margin-top: var(--space-6);
    padding-top: var(--space-5);
    border-top: 1px solid color-mix(in oklch, var(--white) 4%, transparent);
    display: flex;
    justify-content: flex-end;
}
.arech-footer__credit-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding-block: var(--space-2);
    border-radius: var(--radius-xs);
    text-decoration: none;
}
/* Gray by default, true colours only on hover/focus (discreet credit).
   Two-class selector so `height` beats the global `.arech-footer img`
   rule (which is class+type = higher specificity than a single class). */
.arech-footer__credit .arech-footer__credit-logo {
    height: 58px;
    width: auto;
    display: block;
    filter: grayscale(1);
    opacity: 0.45;
    transition: filter var(--motion-fast) var(--ease-standard),
                opacity var(--motion-fast) var(--ease-standard);
}
.arech-footer__credit-link:hover .arech-footer__credit-logo,
.arech-footer__credit-link:focus-visible .arech-footer__credit-logo {
    filter: grayscale(0);
    opacity: 1;
}
.arech-footer__credit-link:focus-visible {
    outline: 2px solid var(--orange);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
    .arech-footer__social a { transition: none; }
    .arech-footer__links a { transition: none; }
    .arech-footer__credit-logo { transition: none; }
}


/* ============================================================================
   TDM Back To Top — view styles. Ported from prototypes/back-to-top/index.html
   (v1.0), re-namespaced .btt-* → .tdm-btt-*, driven by data-* attributes
   (model / theme / shape / size / position) + changed-only scoped custom props
   (--tdm-btt-icon / --tdm-btt-bg / --tdm-btt-size / --tdm-btt-bd-w/-c) that fall
   back to the theme presets below. Modern CSS on purpose: conic-gradient,
   color-mix, :has() not required. Brand tokens come from tdm_blocks/tokens.css.
   ============================================================================ */

/* The reveal sentinel — an invisible 1px marker placed at the threshold; the
   IntersectionObserver in view.js toggles .is-visible on the button. */
.tdm-btt-sentinel {
  position: absolute;
  left: 0;
  width: 1px;
  height: 1px;
  pointer-events: none;
  /* `top` is set inline from the reveal_threshold setting. */
}

/* ---------------------------------------------------------------------------
   1. Base button — fixed, hidden until revealed. Defaults via custom props so
      the changed-only inline <style> can override per instance.
   --------------------------------------------------------------------------- */
.tdm-btt {
  /* size + hit area (kept >= 44px even at S 40 via min-width/height) */
  --tdm-btt-size: 48px;
  --tdm-btt-hit: 48px;
  --tdm-btt-radius: 50%;
  --tdm-btt-bd-w: 0px;
  --tdm-btt-bd-c: transparent;
  --tdm-btt-inset: var(--tdm-space-5, 24px);
  --tdm-btt-p: 0; /* scroll progress 0..1 for the gauge */

  position: fixed;
  z-index: 8000;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tdm-btt-hit);
  min-height: var(--tdm-btt-hit);
  padding: 0;
  margin: 0;
  border: none;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  font-family: var(--tdm-font-mono, system-ui, sans-serif);

  /* reveal state (hidden + out of tab order until shown) */
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px);
  transition:
    opacity var(--tdm-dur-base, 250ms) var(--tdm-ease-standard, ease),
    transform var(--tdm-dur-base, 250ms) var(--tdm-ease-emphatic, ease),
    visibility 0s linear var(--tdm-dur-base, 250ms);
}

.tdm-btt.is-visible {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition:
    opacity var(--tdm-dur-base, 250ms) var(--tdm-ease-standard, ease),
    transform var(--tdm-dur-slow, 400ms) var(--tdm-ease-emphatic, ease);
}

/* size keys (the inline override sets --tdm-btt-size; we also pad the hit area) */
.tdm-btt[data-size="s"] { --tdm-btt-size: 40px; --tdm-btt-hit: 44px; }
.tdm-btt[data-size="m"] { --tdm-btt-size: 48px; --tdm-btt-hit: 48px; }
.tdm-btt[data-size="l"] { --tdm-btt-size: 56px; --tdm-btt-hit: 56px; }

/* ---------------------------------------------------------------------------
   2. Theme presets — seed --tdm-btt-bg / --tdm-btt-icon / --tdm-btt-ring.
      The changed-only inline <style> overrides --tdm-btt-bg / --tdm-btt-icon
      when the operator sets an explicit colour.
   --------------------------------------------------------------------------- */
.tdm-btt[data-theme="dark"] {
  --tdm-btt-bg: var(--tdm-color-accent, #E8651A);
  --tdm-btt-icon: var(--tdm-color-ink, #F5F4F0);
  --tdm-btt-ring: var(--tdm-color-accent, #E8651A);
}
.tdm-btt[data-theme="light"] {
  --tdm-btt-bg: #FFFFFF;
  /* #B0470B = 5.09:1 on white (canonical AA orange-link). The old #B84A0C was
     only 4.28:1, below the 4.5:1 floor for this small icon glyph. */
  --tdm-btt-icon: #B0470B;
  --tdm-btt-ring: #B0470B;
}

/* ---------------------------------------------------------------------------
   3. Shape → radius (data-shape). Gauge + pillar override internally below.
   --------------------------------------------------------------------------- */
.tdm-btt[data-shape="circle"]  { --tdm-btt-radius: 50%; }
.tdm-btt[data-shape="rounded"] { --tdm-btt-radius: var(--tdm-radius-md, 6px); }
.tdm-btt[data-shape="square"]  { --tdm-btt-radius: 2px; }
.tdm-btt[data-shape="pill"]    { --tdm-btt-radius: calc(var(--tdm-btt-size) / 2); }

/* ---------------------------------------------------------------------------
   4. Position presets — inset clears the mobile address bar.
   --------------------------------------------------------------------------- */
.tdm-btt[data-position="bottom-right"]  { right: var(--tdm-btt-inset); bottom: max(var(--tdm-btt-inset), env(safe-area-inset-bottom)); left: auto; }
.tdm-btt[data-position="bottom-left"]   { left: var(--tdm-btt-inset); bottom: max(var(--tdm-btt-inset), env(safe-area-inset-bottom)); right: auto; }
.tdm-btt[data-position="bottom-center"] { left: 50%; bottom: max(var(--tdm-btt-inset), env(safe-area-inset-bottom)); right: auto; transform: translateX(-50%) translateY(12px); }
.tdm-btt[data-position="bottom-center"].is-visible { transform: translateX(-50%) translateY(0); }

@media (min-width: 768px) {
  .tdm-btt { --tdm-btt-inset: var(--tdm-space-6, 32px); }
}

/* ---------------------------------------------------------------------------
   5. The visible "face" — the coloured chip the user sees.
   --------------------------------------------------------------------------- */
.tdm-btt__face {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tdm-btt-size);
  height: var(--tdm-btt-size);
  border-radius: var(--tdm-btt-radius);
  background: var(--tdm-btt-bg);
  border: var(--tdm-btt-bd-w) solid var(--tdm-btt-bd-c);
  color: var(--tdm-btt-icon);
  transition:
    background var(--tdm-dur-base, 250ms) var(--tdm-ease-standard, ease),
    transform var(--tdm-dur-base, 250ms) var(--tdm-ease-standard, ease),
    box-shadow var(--tdm-dur-base, 250ms) var(--tdm-ease-standard, ease);
}
.tdm-btt:hover  .tdm-btt__face { transform: translateY(-2px); box-shadow: 0 8px 22px color-mix(in srgb, #000 35%, transparent); }
.tdm-btt:active .tdm-btt__face { transform: translateY(0); }
.tdm-btt:focus-visible { outline: none; }
.tdm-btt:focus-visible .tdm-btt__face { box-shadow: 0 0 0 3px color-mix(in srgb, var(--tdm-btt-ring) 80%, transparent); }

.tdm-btt__disc { display: inline-flex; align-items: center; justify-content: center; }
.tdm-btt__icon { width: 45%; height: 45%; display: block; line-height: 0; }
.tdm-btt__icon svg { width: 100%; height: 100%; display: block; }

/* stacked label (model 3) — hidden by default */
.tdm-btt__label {
  display: none;
  font-family: var(--tdm-font-mono, system-ui, sans-serif);
  font-weight: 500;
  font-size: 9px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-top: 2px;
  color: var(--tdm-btt-icon);
  line-height: 1;
}

/* live % readout (gauge) — hidden by default */
.tdm-btt__pct {
  display: none;
  position: absolute;
  inset: 0;
  align-items: center;
  justify-content: center;
  font-family: var(--tdm-font-mono, system-ui, sans-serif);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--tdm-btt-icon);
}

/* ---------------------------------------------------------------------------
   MODEL: scroll-gauge (conic progress ring)
   --------------------------------------------------------------------------- */
.tdm-btt[data-model="scroll-gauge"] .tdm-btt__face { border-radius: 50%; background: transparent; padding: 0; }
.tdm-btt[data-model="scroll-gauge"] .tdm-btt__ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(
    var(--tdm-btt-ring) calc(var(--tdm-btt-p) * 360deg),
    color-mix(in srgb, var(--tdm-btt-ring) 22%, transparent) 0
  );
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3px));
          mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3px));
}
.tdm-btt[data-model="scroll-gauge"] .tdm-btt__disc {
  position: absolute;
  inset: 5px;
  border-radius: 50%;
  background: var(--tdm-btt-bg);
}
.tdm-btt[data-model="scroll-gauge"] .tdm-btt__icon { width: 42%; height: 42%; }
.tdm-btt[data-model="scroll-gauge"].show-pct .tdm-btt__icon { opacity: 0; }
.tdm-btt[data-model="scroll-gauge"].show-pct .tdm-btt__pct { display: inline-flex; }

/* The ring/disc are only meaningful for the gauge — hide for other models. */
.tdm-btt:not([data-model="scroll-gauge"]) .tdm-btt__ring { display: none; }

/* ---------------------------------------------------------------------------
   MODEL: edge-pillar (half-pill welded to the edge)
   --------------------------------------------------------------------------- */
.tdm-btt[data-model="edge-pillar"] { bottom: 50%; }
.tdm-btt[data-model="edge-pillar"][data-position="bottom-right"]  { right: 0; left: auto; transform: translateY(40px); }
.tdm-btt[data-model="edge-pillar"][data-position="bottom-right"].is-visible { transform: translateY(0); }
.tdm-btt[data-model="edge-pillar"][data-position="bottom-left"]   { left: 0; right: auto; transform: translateY(40px); }
.tdm-btt[data-model="edge-pillar"][data-position="bottom-left"].is-visible  { transform: translateY(0); }
.tdm-btt[data-model="edge-pillar"][data-position="bottom-center"] { left: 0; right: auto; transform: translateY(40px); } /* center N/A → docks left */
.tdm-btt[data-model="edge-pillar"][data-position="bottom-center"].is-visible { transform: translateY(0); }
.tdm-btt[data-model="edge-pillar"] .tdm-btt__face {
  width: calc(var(--tdm-btt-size) * 0.74);
  height: calc(var(--tdm-btt-size) * 1.9);
  border-radius: 10px 0 0 10px; /* rounded only on the inboard side */
}
.tdm-btt[data-model="edge-pillar"][data-position="bottom-left"] .tdm-btt__face,
.tdm-btt[data-model="edge-pillar"][data-position="bottom-center"] .tdm-btt__face { border-radius: 0 10px 10px 0; }
.tdm-btt[data-model="edge-pillar"]:hover .tdm-btt__face { transform: translateX(-3px); }
.tdm-btt[data-model="edge-pillar"][data-position="bottom-left"]:hover .tdm-btt__face,
.tdm-btt[data-model="edge-pillar"][data-position="bottom-center"]:hover .tdm-btt__face { transform: translateX(3px); }

/* ---------------------------------------------------------------------------
   MODEL: stacked-label
   --------------------------------------------------------------------------- */
.tdm-btt[data-model="stacked-label"] .tdm-btt__face {
  flex-direction: column;
  gap: 1px;
  width: auto;
  min-width: var(--tdm-btt-size);
  height: auto;
  min-height: var(--tdm-btt-size);
  padding: 8px 12px;
}
.tdm-btt[data-model="stacked-label"] .tdm-btt__disc { flex-direction: column; }
.tdm-btt[data-model="stacked-label"] .tdm-btt__icon { width: 18px; height: 18px; }
.tdm-btt[data-model="stacked-label"] .tdm-btt__label { display: block; }

/* ---------------------------------------------------------------------------
   MODEL: notch-riser (rises from below with overshoot)
   --------------------------------------------------------------------------- */
.tdm-btt[data-model="notch-riser"][data-position="bottom-right"],
.tdm-btt[data-model="notch-riser"][data-position="bottom-left"] { transform: translateY(140%); }
.tdm-btt[data-model="notch-riser"][data-position="bottom-center"] { transform: translateX(-50%) translateY(140%); }
.tdm-btt[data-model="notch-riser"].is-visible[data-position="bottom-right"],
.tdm-btt[data-model="notch-riser"].is-visible[data-position="bottom-left"] {
  transform: translateY(0);
  transition: transform var(--tdm-dur-slow, 400ms) var(--tdm-ease-emphatic, cubic-bezier(0.34, 1.56, 0.64, 1)),
              opacity var(--tdm-dur-base, 250ms) var(--tdm-ease-standard, ease);
}
.tdm-btt[data-model="notch-riser"].is-visible[data-position="bottom-center"] {
  transform: translateX(-50%) translateY(0);
  transition: transform var(--tdm-dur-slow, 400ms) var(--tdm-ease-emphatic, cubic-bezier(0.34, 1.56, 0.64, 1)),
              opacity var(--tdm-dur-base, 250ms) var(--tdm-ease-standard, ease);
}
.tdm-btt[data-model="notch-riser"] .tdm-btt__face { border-radius: min(var(--tdm-btt-radius), 6px); }

/* MODEL: plain-chevron uses the base .tdm-btt__face as-is — nothing special. */

/* ---------------------------------------------------------------------------
   Reduced motion: no overshoot, no float, no transform reveal — fade only.
   Reveal still works; scroll is instant (handled in view.js).
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .tdm-btt,
  .tdm-btt.is-visible,
  .tdm-btt[data-model="notch-riser"].is-visible[data-position="bottom-right"],
  .tdm-btt[data-model="notch-riser"].is-visible[data-position="bottom-left"] {
    transform: none !important;
    transition: opacity var(--tdm-dur-base, 250ms) linear, visibility 0s !important;
  }
  .tdm-btt[data-position="bottom-center"],
  .tdm-btt[data-position="bottom-center"].is-visible { transform: translateX(-50%) !important; }
  .tdm-btt:hover .tdm-btt__face,
  .tdm-btt[data-model="edge-pillar"]:hover .tdm-btt__face { transform: none; }
}


