/* ============================================================
   AMI Documentation — extra.css  (clean-room)
   Source of truth: 3forge Enterprise Client Portal.
   Stock Material for MkDocs, restyled to the portal's token
   system and component primitives. No legacy AMI colors.
   Palette in mkdocs.yml is `custom`; this file defines the
   brand colors per scheme (required by `custom`).
   ============================================================ */

/* ------------------------------------------------------------
   1. Portal tokens, per Material color scheme
   slate = DARK, default = LIGHT
   ------------------------------------------------------------ */
[data-md-color-scheme="slate"] {                 /* DARK */
  --tf-bg:            #0B0C11;
  --tf-surface-0:     #13151E;
  --tf-surface-1:     #1C1F2D;
  --tf-surface-2:     #252840;
  --tf-surface-3:     #2F3352;
  --tf-surface-4:     #3A3E64;
  --tf-border-dim:    rgba(255,255,255,0.05);
  --tf-border-subtle: rgba(255,255,255,0.09);
  --tf-border-strong: rgba(255,255,255,0.15);
  --tf-text-primary:   #E3E5F0;
  --tf-text-secondary: #8A8FA8;
  --tf-text-tertiary:  #6B7090;
  --tf-text-dim:       #50566E;
  --tf-text-label:     #9BA1BC;
  --tf-accent:         #4E8DAD;
  --tf-accent-dark:    #3B6A82;
  --tf-accent-subtle:  rgba(78,141,173,0.12);
  --tf-ok: #44BF80;  --tf-warn: #FFA040;  --tf-elevated: #F06030;  --tf-err: #E8456A;
  /* Portal cards: surface-0 in dark */
  --tf-card:      var(--tf-surface-0);
  --tf-card-head: var(--tf-surface-1);
  --tf-input-bg:  var(--tf-surface-1);
  --tf-pink-tint: #e8549b;
}
[data-md-color-scheme="default"] {               /* LIGHT */
  --tf-bg:            #F4F5FA;
  --tf-surface-0:     #ECEEF5;
  --tf-surface-1:     #E2E5F0;
  --tf-surface-2:     #D6DAE8;
  --tf-surface-3:     #C9CEDF;
  --tf-surface-4:     #BCC2D6;
  --tf-border-dim:    rgba(0,0,0,0.06);
  --tf-border-subtle: rgba(0,0,0,0.10);
  --tf-border-strong: rgba(0,0,0,0.18);
  --tf-text-primary:   #1A1D2E;
  --tf-text-secondary: #4A4F66;
  --tf-text-tertiary:  #606680;
  --tf-text-dim:       #8A8FA8;
  --tf-text-label:     #565B78;
  --tf-accent:         #1F6F94;
  --tf-accent-dark:    #175370;
  --tf-accent-subtle:  rgba(31,111,148,0.12);
  --tf-ok: #1E8A50;  --tf-warn: #C96800;  --tf-elevated: #C44020;  --tf-err: #B52247;
  /* Portal cards: pure white in light */
  --tf-card:      #ffffff;
  --tf-card-head: var(--tf-surface-0);
  --tf-input-bg:  #ffffff;
  --tf-pink-tint: #e8549b;
}

/* ------------------------------------------------------------
   2. Map tokens -> Material variables (both schemes)
   ------------------------------------------------------------ */
[data-md-color-scheme="slate"],
[data-md-color-scheme="default"] {
  --md-primary-fg-color:        var(--tf-surface-1);
  --md-primary-fg-color--light: var(--tf-surface-2);
  --md-primary-fg-color--dark:  var(--tf-surface-0);
  --md-primary-bg-color:        var(--tf-text-primary);
  --md-primary-bg-color--light: var(--tf-text-secondary);

  --md-accent-fg-color:             var(--tf-accent);
  --md-accent-fg-color--transparent:var(--tf-accent-subtle);

  --md-default-bg-color:           var(--tf-bg);
  --md-default-fg-color:           var(--tf-text-primary);
  --md-default-fg-color--light:    var(--tf-text-secondary);
  --md-default-fg-color--lighter:  var(--tf-text-tertiary);
  --md-default-fg-color--lightest: var(--tf-border-subtle);
  --md-typeset-color:              var(--tf-text-primary);
  --md-typeset-a-color:            var(--tf-accent);

  --md-code-bg-color:              var(--tf-card);
  --md-code-fg-color:              var(--tf-text-primary);

  --md-footer-bg-color:            var(--tf-surface-0);
  --md-footer-bg-color--dark:      var(--tf-bg);
}

/* Portal-style wide layout: left nav pinned to the LEFT edge, table of contents
   pinned to the RIGHT edge, and a max-width article column centered between them
   so text lines stay readable.
   Material caps every row via .md-grid and centers it (the narrow-column look);
   removing the cap lets the row span the viewport, which pushes the two
   fixed-width sidebars out to the screen edges. Capping .md-content then keeps
   the prose measure sane, and the auto inline margins center it in the space
   left between the sidebars. */
.md-grid { max-width: initial; }
.md-content {
  max-width: 52rem;        /* readable measure; tune to taste */
  margin-inline: auto;     /* centers the column between the pinned sidebars */
  padding: 0 1.2rem;
}

/* ------------------------------------------------------------
   3. Header — portal topbar gradient (accent -> surface-1 -> pink)
   ------------------------------------------------------------ */
.md-header {
  background: linear-gradient(to right,
    color-mix(in srgb, var(--tf-accent) 6%, var(--tf-surface-0)),
    var(--tf-surface-1) 55%,
    color-mix(in srgb, var(--tf-pink-tint) 8%, var(--tf-surface-1)));
  color: var(--tf-text-primary);
  border-bottom: 1px solid var(--tf-border-subtle);
  box-shadow: none;
}
.md-header--shadow { box-shadow: 0 0 .2rem rgba(0,0,0,.1), 0 .2rem .4rem rgba(0,0,0,.2); }

/* Inner row: portal topbar proportions — 43px tall, 12px gutters, 6px gaps */
.md-header__inner {
  min-height: 43px;
  padding: 0 12px;
  gap: 6px;
}

/* The crumb replaces Material's site-name/page-title text. Keep the title
   element as the flexible spacer that pushes the controls to the right,
   but hide its text. */
.md-header__title { flex-grow: 1; }
.md-header__title .md-header__ellipsis { visibility: hidden; }

/* --- Edition selector (overrides/partials/header.html) ---
   The theme builds the selector in JS and appends it into the first
   .md-header__topic. That template puts a single, empty one here as a direct child
   of .md-header__inner, between the spacer above and the search control, so the
   selector renders in the header's right-hand group.

   Material styles .md-header__topic as absolutely positioned, for the title-swap
   animation it normally drives. That is wrong for a flex child, so reset it.

   Note the rule above is inert while that template is in use: it renders no
   .md-header__ellipsis. It is kept so the stylesheet still behaves if the header
   override is removed. */
.tf-edition {
  position: static;
  max-width: none;
  transition: none;
  display: flex;
  align-items: center;
  align-self: stretch;      /* fill the header row, so the box below can centre in it */
  margin-right: 6px;

  /* Reserve the width of the open dropdown. Material anchors .md-version__list to
     the trigger's left edge and sizes it to the longest entry, so with the group
     packed against the search box a short label ("Classic") sits further right and
     the list spills over search. A floor wide enough for the longest edition name
     keeps that edge fixed. Raise this if an edition longer than "Enterprise" is
     added. */

     /* how flush the drop down box is to the search bar */
  min-width: 6.5rem;
}

/* Material gives .md-version a fixed height of 2.4rem, sized for its own header,
   and lets the trigger button flow from the top of that box. This topbar is 43px,
   so the box overflows the row and the label sits high. Fill the row instead and
   centre the trigger inside it. The dropdown list is absolutely positioned and is
   not affected. */
.tf-edition .md-version {
  height: 100%;
  display: flex;
  align-items: center;
}

/* Material indents the label by 1.4rem to clear its own header title. The reserved
   width above already provides that spacing, so drop it and let the label sit at
   the left of the box. */
.tf-edition .md-version__current { margin-left: 0; }

/* --- Brand lockup: logo + divider + "Docs" crumb (overrides/partials/logo.html) --- */
.md-header__button.md-logo { padding: 0; margin: 0; }
.md-logo { display: flex; align-items: center; }
.tf-brand { display: inline-flex; align-items: center; gap: 6px; }
.tf-brand__logo {
  display: flex; align-items: center;
  height: 26px;
  padding-right: 14px;
  border-right: 1px solid var(--tf-border-subtle);
}
.tf-crumb {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 12px; font-weight: 500; letter-spacing: .01em;
  color: var(--tf-text-secondary); white-space: nowrap;
}
.tf-crumb strong { color: var(--tf-text-primary); font-weight: 600; }
.tf-crumb__icon { width: 16px; height: 16px; flex-shrink: 0; color: var(--tf-text-tertiary); }  /* inline SVG, fill=currentColor */
/* Mobile drawer title: show the logo alone (no divider / crumb) */
.md-nav__title .tf-crumb { display: none; }
.md-nav__title .tf-brand__logo { border-right: 0; padding-right: 0; }

/* --- Theme toggle: inline filled 'dark_mode' / 'light_mode' icons, pinned right ---
   Icons live at overrides/.icons/tf/{dark-mode,light-mode}.svg and are wired via
   mkdocs.yml palette toggle.icon (tf/dark-mode, tf/light-mode). Material inlines
   them as SVG (no webfont). The active scheme's label shows the CURRENT mode:
   light -> light_mode (sun), dark -> dark_mode (moon). Wired in mkdocs.yml. */
.md-header__option[data-md-component="palette"] { order: 100; }   /* right-most control */
.md-header__option .md-icon { color: var(--tf-text-secondary); }
.md-header__option .md-icon:hover { color: var(--tf-text-primary); }

/* Nav tabs bar */
.md-tabs {
  background-color: var(--tf-surface-0);
  color: var(--tf-text-secondary);
  border-bottom: 1px solid var(--tf-border-dim);
}
.md-tabs__link { opacity: .72; font-weight: 500; }
.md-tabs__link:hover, .md-tabs__link--active { opacity: 1; color: var(--tf-text-primary); }

@media screen and (max-width: 76.234375em) {
  .md-nav--primary .md-nav__title {
    background-color: var(--tf-surface-1) !important;
    color: var(--tf-text-primary) !important;
  }
}

/* ------------------------------------------------------------
   4. Sidebar / navigation — portal sidenav idiom
   ------------------------------------------------------------ */
.md-nav__title {
  color: var(--tf-text-tertiary);
  font-size: .62rem; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase;
}
/* Transparent border on every link so the active border adds no 1px shift */
.md-nav__link {
  color: var(--tf-text-secondary);
  font-weight: 500;
  border: 1px solid transparent;
  border-radius: 4px;
}
/* Portal-style item padding on the left menu, so the pill matches
   .sidenav__item (7px 10px). Scoped to primary nav; TOC is untouched. */
.md-nav--primary .md-nav__link {
  padding: 7px 10px;
}
.md-nav--primary .md-nav__link:hover,
.md-nav--primary .md-nav__link:focus {
  color: var(--tf-text-primary);
  background: var(--tf-surface-1);
}

/* Active page: blue text everywhere (left nav + TOC) */
.md-nav__link--active,
.md-nav__link[aria-current="page"] {
  color: var(--tf-accent) !important;
  font-weight: 600;
}

/* Left-nav active item: accent-subtle pill, matching .sidenav__item.is-active.
   Applied to BOTH regular pages and section-index pages (navigation.indexes) --
   the previous `.md-nav__item > .md-nav__link--active` child selector missed the
   index link (md-nav__link--index), which is why a section-index page showed blue
   text but no pill while sibling leaf pages got the pill. */
[dir="ltr"] .md-nav--primary .md-nav__link--active,
[dir="ltr"] .md-nav--primary .md-nav__link[aria-current="page"] {
  background: var(--tf-accent-subtle);
  border-color: color-mix(in srgb, var(--tf-accent) 35%, transparent);
}

/* Table of contents (secondary nav): text-only accent, never a pill.
   Placed last so it wins if a secondary link is nested under primary (mobile). */
.md-nav--secondary .md-nav__link--active,
.md-nav--secondary .md-nav__link[aria-current="page"] {
  background: transparent;
  border-color: transparent;
  color: var(--tf-accent) !important;
}

/* --- Section hierarchy ---
   A section (e.g. "Architecture") is a .md-nav__item--section whose DIRECT link is
   the section index; its child pages live in the nested .md-nav below it. Style the
   section link as a portal-style group header (uppercase / tertiary / letter-spaced)
   and indent the children under a guide line, so the section outranks its pages. */
.md-nav--primary .md-nav__item--section > .md-nav__link {
  text-transform: uppercase;
  font-size: .62rem;
  font-weight: 700;
  letter-spacing: .09em;
  color: var(--tf-text-tertiary);
  padding: 6px 10px 4px;
  margin-top: 6px;
  border: 0;
  border-radius: 0;
}
.md-nav--primary .md-nav__item--section > .md-nav__link:hover {
  background: transparent;
  color: var(--tf-text-secondary);
}
/* Section index as the active page: accent color, but keep the header shape (no pill) */
.md-nav--primary .md-nav__item--section > .md-nav__link.md-nav__link--active {
  color: var(--tf-accent) !important;
  background: transparent;
  border-color: transparent;
}
/* Child pages nested under a section: indent beneath a subtle guide line.
   margin-left is !important to override Material's --lifted negative margin,
   which otherwise drags the group (and its guide line) to the sidebar edge. */
.md-nav--primary .md-nav__item--section > .md-nav {
  margin-left: 4px !important;
  margin-top: 2px;
  margin-bottom: 6px;
  padding-left: 10px;
  border-left: 1px solid var(--tf-border-subtle);
}

/* ------------------------------------------------------------
   5. Typography
   ------------------------------------------------------------ */
.md-typeset { line-height: 1.65; }
.md-typeset h1 {
  font-size: 1.9rem; font-weight: 600; letter-spacing: -0.01em;
  color: var(--tf-text-primary);
}
.md-typeset h2 {
  font-weight: 600; letter-spacing: -0.01em;
  border-bottom: 1px solid var(--tf-border-subtle); padding-bottom: .3rem;
}
.md-typeset h3, .md-typeset h4 { font-weight: 600; }
.md-typeset a:hover { text-decoration: underline; }
.md-typeset :not(pre) > code {
  background: var(--tf-surface-2);
  color: var(--tf-text-primary);
  border: 1px solid var(--tf-border-subtle);
  border-radius: 3px; padding: .05em .35em;
}
.md-typeset pre > code {
  border: 1px solid var(--tf-border-subtle); border-radius: 6px;
}
.md-clipboard { color: var(--tf-text-tertiary); }
.md-clipboard:hover { color: var(--tf-accent); }
[data-md-color-scheme="slate"]  .md-typeset article > :is(h1,h2,h3,h4) { color: #ffffff; }

/* ------------------------------------------------------------
   6. Admonitions -> portal .panel + semantic left border
   ------------------------------------------------------------ */
.md-typeset .admonition,
.md-typeset details {
  background: var(--tf-card);
  border: 1px solid var(--tf-border-subtle);
  border-left-width: 3px;
  border-radius: 8px;               /* --radius-outer */
  box-shadow: none;
  font-size: .75rem;
}
.md-typeset .admonition > .admonition-title,
.md-typeset details > summary {
  background: var(--tf-card-head);
  color: var(--tf-text-primary);
  font-weight: 600;
}
.md-typeset :is(.note,.info,.abstract) { border-left-color: var(--tf-accent); }
.md-typeset :is(.note,.info,.abstract) > .admonition-title::before { background-color: var(--tf-accent); }
.md-typeset :is(.tip,.success) { border-left-color: var(--tf-ok); }
.md-typeset :is(.tip,.success) > .admonition-title::before { background-color: var(--tf-ok); }
.md-typeset :is(.warning,.caution) { border-left-color: var(--tf-warn); }
.md-typeset :is(.warning,.caution) > .admonition-title::before { background-color: var(--tf-warn); }
.md-typeset :is(.danger,.failure,.bug) { border-left-color: var(--tf-err); }
.md-typeset :is(.danger,.failure,.bug) > .admonition-title::before { background-color: var(--tf-err); }
.md-typeset .example { border-left-color: var(--tf-elevated); }
.md-typeset .example > .admonition-title::before { background-color: var(--tf-elevated); }

/* ------------------------------------------------------------
   7. Tables -> portal data-grid feel
   ------------------------------------------------------------ */
.md-typeset table:not([class]) {
  background: var(--tf-card);
  border: 1px solid var(--tf-border-subtle);
  border-radius: 8px; overflow: hidden;
  font-size: .72rem;
}
.md-typeset table:not([class]) th {
  background: var(--tf-surface-2);
  color: var(--tf-text-secondary);
  font-size: .62rem; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
  border-bottom: 2px solid var(--tf-accent);
}
.md-typeset table:not([class]) td { border-top: 1px solid var(--tf-border-dim); }
.md-typeset table:not([class]) tr:hover td { background: var(--tf-accent-subtle); }

/* ------------------------------------------------------------
   8. Buttons -> portal .btn primitives
   ------------------------------------------------------------ */
.md-typeset .md-button {
  border-radius: 4px;
  border: 1px solid var(--tf-border-strong);
  background: transparent;
  color: var(--tf-text-primary);
  font-weight: 600; font-size: .72rem;
  transition: background 100ms, border-color 100ms, color 100ms, transform 60ms;
}
.md-typeset .md-button:hover { background: var(--tf-surface-2); }
.md-typeset .md-button:active { transform: translateY(1px); }
.md-typeset .md-button--primary {
  background: var(--tf-accent); border-color: var(--tf-accent); color: #fff;
}
.md-typeset .md-button--primary:hover {
  background: color-mix(in srgb, var(--tf-accent) 88%, #fff);
  border-color: color-mix(in srgb, var(--tf-accent) 88%, #fff); color: #fff;
}
.md-typeset .md-button--primary:active { background: var(--tf-accent-dark); }

/* ------------------------------------------------------------
   9. Search — portal .input idiom
   ------------------------------------------------------------ */
.md-search__form {
  background: var(--tf-input-bg);
  border: 1px solid var(--tf-border-strong);
  border-radius: 4px; box-shadow: none;
}
.md-search__form:hover { background: var(--tf-input-bg); }
[data-md-toggle="search"]:checked ~ .md-header .md-search__form {
  box-shadow: 0 0 0 2px var(--tf-accent-subtle);
  border-color: var(--tf-accent);
}
.md-search__input::placeholder { color: var(--tf-text-dim); }

/* Content tabs (pymdownx.tabbed) */
.md-typeset .tabbed-set > input:checked + label {
  color: var(--tf-accent); border-color: var(--tf-accent);
}

/* Dark-mode scrollbar */
[data-md-color-scheme="slate"] ::-webkit-scrollbar { width: 10px; height: 10px; }
[data-md-color-scheme="slate"] ::-webkit-scrollbar-thumb { background: var(--tf-surface-3); border-radius: 6px; }
[data-md-color-scheme="slate"] ::-webkit-scrollbar-thumb:hover { background: var(--tf-surface-4); }

/* ------------------------------------------------------------
   9b. Code-block admonition ( !!! quote )
   The site maps the `quote` admonition to a code icon
   (icon.admonition.quote: fontawesome/solid/code in mkdocs.yml) and
   authors code-example callouts with it. Rebuilt here in the 3forge
   idiom: code-surface panel, monospace title. Overrides the generic
   admonition rules in section 6 for `.quote` only.
   ------------------------------------------------------------ */
.md-typeset .admonition.quote,
.md-typeset details.quote {
  background: var(--tf-card);
  border: 1px solid var(--tf-border-subtle);
  border-left-width: 1px;                 /* no semantic accent bar for code */
  border-radius: 6px;                     /* --radius-window */
  box-shadow: 0 0 0 .2rem var(--tf-accent-subtle);
  font-size: .72rem;
  line-height: 1.5;
}
.md-typeset .admonition.quote > .admonition-title,
.md-typeset details.quote > summary {
  background: var(--tf-surface-1);
  color: var(--tf-text-primary);
  font-family: var(--md-code-font-family, "Inconsolata", monospace);
  font-weight: 700;
  letter-spacing: 0;
}
.md-typeset .admonition.quote > .admonition-title::before,
.md-typeset details.quote > summary::before {
  background-color: var(--tf-accent);     /* the code icon, tinted accent */
}
/* Nested admonitions inside a code block render one step smaller */
.md-typeset .admonition.quote .admonition {
  font-size: .9em;
  margin-top: .6rem;
}

/* ------------------------------------------------------------
   10. Theme-sensitive logo (inlined via overrides/partials/logo.html)
   Colored mark stays constant; wordmark flips ink<->white per scheme,
   mirroring the portal's .brand-logo behavior.
   ------------------------------------------------------------ */
.md-logo .brand-logo,
.md-nav__title .brand-logo {
  height: 22px;            /* portal logo lockup ≈ 82x22 */
  width: auto;
  display: block;
}
/* Dark scheme keeps the SVG's native white wordmark.
   Light scheme flips it to the portal ink color. */
[data-md-color-scheme="default"] .brand-logo path[fill="#fff"] {
  fill: #1A1D2E;
}

/* ============================================================
   11. LANDING PAGE  (overrides/home.html, template: home.html)
   ============================================================ */
.tf-home-wrap { max-width: 62rem; margin: 0 auto; padding: 0 1.6rem; }

/* ---- Hero ---- */
.tf-home-hero {
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--tf-border-subtle);
  background:
    radial-gradient(65% 130% at 88% -10%, var(--tf-accent-subtle), transparent 60%),
    var(--tf-bg);
}
/* Faint dotted texture on the left, fading out (Stripe cue) */
.tf-home-hero::before {
  content: "";
  position: absolute; inset: 0;
  background-image: radial-gradient(var(--tf-border-strong) 1px, transparent 1px);
  background-size: 16px 16px;
  -webkit-mask-image: linear-gradient(to right, #000, transparent 42%);
          mask-image: linear-gradient(to right, #000, transparent 42%);
  opacity: .55; pointer-events: none;
}
.tf-home-hero__inner {
  position: relative; z-index: 1;
  display: flex; align-items: flex-start; gap: 2.4rem;
  padding-top: 3.4rem; padding-bottom: 3.4rem;
}
.tf-home-hero__text { flex: 1; min-width: 0; }
.tf-home-eyebrow {
  margin: 0 0 .5rem;
  font-size: .62rem; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--tf-accent);
}
.tf-home-title {
  margin: 0 0 .5rem;
  font-size: 2.6rem; line-height: 1.04; font-weight: 700;
  letter-spacing: -0.02em; color: var(--tf-text-primary);
}
.tf-home-tagline {
  margin: 0 0 1.5rem; max-width: 34rem;
  font-size: 1rem; line-height: 1.5; color: var(--tf-text-secondary);
}

/* CTA buttons (outside .md-typeset, so styled here) */
.tf-home-cta { display: flex; flex-wrap: wrap; gap: .6rem; }
.tf-home-cta .md-button {
  border-radius: 4px;
  border: 1px solid var(--tf-border-strong);
  background: transparent; color: var(--tf-text-primary);
  font-size: .82rem; font-weight: 600; padding: .5em 1.15em;
  transition: background 100ms, border-color 100ms, color 100ms;
}
.tf-home-cta .md-button:hover { background: var(--tf-surface-2); }
.tf-home-cta .md-button--primary {
  background: var(--tf-accent); border-color: var(--tf-accent); color: #fff;
}
.tf-home-cta .md-button--primary:hover {
  background: color-mix(in srgb, var(--tf-accent) 88%, #fff);
  border-color: transparent; color: #fff;
}

/* ---- Floating card ---- */
.tf-home-card {
  flex-shrink: 0; width: 17rem;
  border-radius: 10px;
  padding: 15px 16px;
}
/* Media variant: the card is a single image (placeholder, user-replaceable) */
.tf-home-card--media { padding: 0; overflow: hidden; }
.tf-home-card__img { display: block; width: 100%; height: auto; }
.tf-home-card__group + .tf-home-card__group { margin-top: 14px; }
.tf-home-card__label {
  font-size: .56rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--tf-text-tertiary);
  margin-bottom: 5px;
}
.tf-home-card__link {
  display: block; padding: 2px 0;
  font-size: .78rem; color: var(--tf-accent);
}
.tf-home-card__link:hover { text-decoration: underline; }

/* ---- Link columns ---- */
.tf-home-cols {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 1.8rem 2rem;
  padding-top: 2.8rem; padding-bottom: 3.2rem;
}
.tf-home-col__title {
  margin: 0 0 .7rem;
  font-size: 1rem; font-weight: 700; color: var(--tf-text-primary);
}
.tf-home-col__link {
  display: block; padding: 4px 0;
  font-size: .82rem; line-height: 1.4; color: var(--tf-accent);
}
.tf-home-col__link:hover { text-decoration: underline; }

/* ---- Responsive ---- */
@media screen and (max-width: 60em) {
  .tf-home-hero__inner { flex-direction: column; }
  .tf-home-card { display: none; }   /* featured card is hidden on narrow screens */
  .tf-home-cols { grid-template-columns: repeat(2, 1fr); }
}
@media screen and (max-width: 30em) {
  .tf-home-cols { grid-template-columns: 1fr; }
  .tf-home-title { font-size: 2.1rem; }
}
