/* DynDyn.Pdf Portal design system. No inline styles are used anywhere in the markup — every rule
   lives here, which keeps the Content-Security-Policy's style-src at 'self' with no
   'unsafe-inline'. No external font requests: both faces are Google Fonts (Plus Jakarta Sans,
   Inter), self-hosted from wwwroot/fonts and subset to latin. */

/* Display face for headings, stats and prices. Variable weight file, subset to latin. */
@font-face {
  font-family: "Plus Jakarta Sans";
  src: url("../fonts/plus-jakarta-sans.woff2") format("woff2-variations");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}

/* Body face. Variable weight file, subset to latin. */
@font-face {
  font-family: "Inter";
  src: url("../fonts/inter.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light;
  --bg: #ffffff;
  --bg-raised: #f6f7f9;
  --bg-inset: #eef0f3;
  --fg: #14171a;
  --fg-muted: #52585f;
  --border: #d8dce1;
  --link: #0a5fd6;
  --link-hover: #08419a;
  --accent: #0a5fd6;
  --accent-fg: #ffffff;
  --danger: #b3261e;
  --danger-bg: #fdecea;
  --success: #1b7a3d;
  --success-bg: #e9f7ee;
  --warn: #8a5a00;
  --warn-bg: #fff4e0;
  --focus: #0a5fd6;
  --shadow: 0 1px 2px rgba(22, 30, 51, 0.05), 0 10px 30px rgba(22, 30, 51, 0.07);
  --shadow-lift: 0 2px 4px rgba(22, 30, 51, 0.06), 0 18px 44px rgba(22, 30, 51, 0.13);
  --radius: 10px;
  --radius-lg: 16px;
  --font: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
  --font-mono: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
  --font-display: "Plus Jakarta Sans", "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Brand anchors, 2026-09-10. --ink is the wordmark navy from the logo lockups:
     it carries headings and primary actions; links stay --link blue for contrast. */
  --ink: #1f2a44;
  --ink-deep: #141b30;
  --ink-hover: #2a3a5e;
  /* Product accents, taken from the four lockups: the light tone is for marks and
     fills, the -deep tone is dark enough to set text in on a light surface.
     co = company (slate), cv = Convert (green), tg = Trigger (amber), ds = Describe (sky). */
  --pc-co: #5c6b8a;  --pc-co-deep: #1f2a44;
  --pc-cv: #97c459;  --pc-cv-deep: #4e7619;
  --pc-tg: #ef9f27;  --pc-tg-deep: #8a5e10;
  --pc-ds: #85b7eb;  --pc-ds-deep: #1d62ac;
  --eyebrow-accent: var(--pc-co);
  --grid-line: rgba(31, 42, 68, 0.05);
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0f1115;
  --bg-raised: #171a20;
  --bg-inset: #1d212a;
  --fg: #eef1f5;
  --fg-muted: #a7afba;
  --border: #2c323d;
  --link: #6fa9ff;
  --link-hover: #9cc4ff;
  --accent: #3b82f6;
  --accent-fg: #0b0e14;
  --danger: #ff8a80;
  --danger-bg: #3a1613;
  --success: #6fd897;
  --success-bg: #0f2b1c;
  --warn: #ffcf6b;
  --warn-bg: #332406;
  --focus: #6fa9ff;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 1px 8px rgba(0, 0, 0, 0.3);
  --shadow-lift: 0 2px 6px rgba(0, 0, 0, 0.45), 0 20px 48px rgba(0, 0, 0, 0.4);
  /* Ink inverts: display text and primary buttons flip to light-on-dark.
     Product -deep tones brighten so accent text keeps its contrast. */
  --ink: #e8edf6;
  --ink-deep: #0b0e18;
  --ink-hover: #c6d2e8;
  --pc-co: #8d9cb8;  --pc-co-deep: #aeb9cf;
  --pc-cv: #97c459;  --pc-cv-deep: #a9d973;
  --pc-tg: #ef9f27;  --pc-tg-deep: #f2b257;
  --pc-ds: #85b7eb;  --pc-ds-deep: #9cc6f2;
  --grid-line: rgba(232, 237, 246, 0.05);
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.55;
}
img, svg { max-width: 100%; }
main { display: block; }

a { color: var(--link); text-decoration: underline; text-underline-offset: 2px; }
a:hover { color: var(--link-hover); }
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

/* Nav-cluster components restate the same ring explicitly: their hover/hit
   areas have their own border-radius, and relying only on the bare a/button
   rule above left the ring visually adrift on the pill- and card-shaped ones. */
.nav__trigger:focus-visible, .nav__toggle:focus-visible, .theme-toggle:focus-visible,
.docs-item:focus-visible, .way:focus-visible, .prod:focus-visible,
.quick:focus-visible, .chip:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--radius);
}

h1, h2, h3, h4 { line-height: 1.15; margin: 0 0 0.6em; font-family: var(--font-display); color: var(--ink); letter-spacing: -0.015em; }
h1 { font-size: clamp(2.1rem, 1.5rem + 2.4vw, 3.2rem); }
h2 { font-size: clamp(1.5rem, 1.25rem + 1vw, 2.1rem); }
h3 { font-size: 1.25rem; }
p { margin: 0 0 1em; color: var(--fg); }
.lede { font-size: 1.15rem; color: var(--fg-muted); }
code, pre { font-family: var(--font-mono); }
pre { background: var(--bg-inset); border: 1px solid var(--border); border-radius: var(--radius); padding: 1em; overflow-x: auto; }
code { background: var(--bg-inset); border-radius: 4px; padding: 0.1em 0.35em; }
pre code { background: none; padding: 0; }

.container { width: 100%; max-width: 1080px; margin-inline: auto; padding-inline: 1.25rem; }
.section { padding-block: clamp(2rem, 1.5rem + 2vw, 4rem); }
.section--raised { background: var(--bg-raised); }

.site-header {
  border-bottom: 1px solid var(--border);
  background: var(--bg); /* fallback for browsers without color-mix */
  background: color-mix(in srgb, var(--bg) 84%, transparent);
  backdrop-filter: blur(14px) saturate(1.35);
  -webkit-backdrop-filter: blur(14px) saturate(1.35);
  position: sticky;
  top: 0;
  z-index: 20;
}
.site-header__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-block: 0.85rem;
}
.brand { display: flex; align-items: center; gap: 0.5rem; font-weight: 700; font-size: 1.1rem; color: var(--fg); text-decoration: none; }
.brand:hover { color: var(--fg); }
.brand__logo { height: 38px; width: auto; flex: none; }
.brand__name { display: flex; flex-direction: column; font-family: var(--font-display); color: var(--ink); letter-spacing: -.01em; line-height: 1; }
.brand__tag { font-family: var(--font); font-size: 0.56rem; font-weight: 300; text-transform: uppercase; letter-spacing: 0.34em; color: var(--fg-muted); margin-top: 3px; }

/* The base rings mark (logo1.svg) is drawn in ink navy; lift its luminosity on
   dark surfaces so it never disappears into the header or footer. The product
   marks already carry a light tone, so they need a gentler lift. */
[data-theme="dark"] .mark { filter: brightness(1.35); }
[data-theme="dark"] .brand__logo,
[data-theme="dark"] .site-footer__brand img { filter: brightness(1.9) saturate(1.05); }
.nav { display: flex; align-items: center; gap: 1.25rem; flex-wrap: wrap; }
.nav a { color: var(--fg-muted); text-decoration: none; font-weight: 500; }
.nav a:hover, .nav a[aria-current="page"] { color: var(--fg); }
.nav__actions { display: flex; align-items: center; gap: 0.6rem; margin-left: auto; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  border-radius: var(--radius);
  border: 1px solid transparent;
  padding: 0.6rem 1.1rem;
  font-size: 0.95rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  font-family: inherit;
  transition: transform .15s ease, box-shadow .2s ease, background .2s ease, border-color .2s ease;
}
.btn:active { transform: translateY(1px) scale(0.99); }
/* Primary actions wear the brand ink (wordmark navy) rather than the link blue;
   both tokens flip together in dark theme so the pair always contrasts. */
.btn-primary { background: var(--ink); color: var(--bg); box-shadow: 0 1px 2px rgba(20, 27, 48, 0.3), 0 8px 20px rgba(31, 42, 68, 0.18); }
.btn-primary:hover { background: var(--ink-hover); color: var(--bg); transform: translateY(-1px); box-shadow: 0 2px 4px rgba(20, 27, 48, 0.3), 0 14px 30px rgba(31, 42, 68, 0.24); }
.btn-secondary { background: var(--bg-raised); color: var(--fg); border-color: var(--border); box-shadow: 0 1px 2px rgba(22, 30, 51, 0.05); }
.btn-secondary:hover { background: var(--bg-inset); color: var(--fg); border-color: var(--border); transform: translateY(-1px); }
.btn-ghost { background: transparent; color: var(--fg-muted); border-color: var(--border); }
.btn-ghost:hover { color: var(--fg); }
.btn-sm { padding: 0.35rem 0.7rem; font-size: 0.85rem; }
.btn[disabled] { opacity: 0.55; cursor: not-allowed; }

.theme-toggle {
  background: var(--bg-raised);
  border: 1px solid var(--border);
  color: var(--fg);
  border-radius: 999px;
  width: 2.25rem;
  height: 2.25rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
}

.card { background: var(--bg-raised); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 1.25rem; box-shadow: var(--shadow); }
.card-grid { display: grid; gap: 1.25rem; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: 0.7rem 0.85rem; border-bottom: 1px solid var(--border); vertical-align: top; }
th { color: var(--fg-muted); font-weight: 600; font-size: 0.72rem; letter-spacing: 0.07em; text-transform: uppercase; }
tbody tr { transition: background 0.12s ease; }
tbody tr:hover { background: color-mix(in srgb, var(--accent) 4%, transparent); }

.pricing-grid { display: grid; gap: 1.25rem; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); align-items: stretch; }
.pricing-card { display: flex; flex-direction: column; gap: 0.75rem; }
.pricing-card__price { font-size: 1.6rem; font-weight: 700; }
.pricing-card__features { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; color: var(--fg-muted); }

.badge { display: inline-block; border-radius: 999px; padding: 0.15rem 0.65rem; font-size: 0.78rem; font-weight: 600; background: var(--bg-inset); color: var(--fg-muted); }
.badge--success { background: var(--success-bg); color: var(--success); }
.badge--warn { background: var(--warn-bg); color: var(--warn); }
.badge--danger { background: var(--danger-bg); color: var(--danger); }

.banner { border-radius: var(--radius); border: 1px solid var(--border); padding: 0.9rem 1.1rem; margin-bottom: 1.5rem; }
.banner--warn { background: var(--warn-bg); border-color: var(--warn); color: var(--warn); }
.banner--danger { background: var(--danger-bg); border-color: var(--danger); color: var(--danger); }
.banner--success { background: var(--success-bg); border-color: var(--success); color: var(--success); }

form { display: flex; flex-direction: column; gap: 1rem; max-width: 32rem; }
.form-row { display: flex; flex-direction: column; gap: 0.35rem; }
label { font-weight: 600; font-size: 0.9rem; }
input, select, textarea {
  font: inherit;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--fg);
}
.field-hint { color: var(--fg-muted); font-size: 0.85rem; }
.field-error { color: var(--danger); font-size: 0.85rem; }
.validation-summary-errors ul { margin: 0; padding-left: 1.2rem; color: var(--danger); }

.site-footer { border-top: 1px solid var(--border); background: var(--bg-raised); margin-top: 3rem; }
/* Explicit grid, not flex-wrap: the brand cell is wide enough that the fifth column ("Company")
   wrapped to a second row at every desktop width, leaving a ~220px empty band across columns
   2-4. A wider brand cell plus four equal link columns fits the same five cells on one row. */
.site-footer__grid { display: grid; grid-template-columns: 1.6fr repeat(4, minmax(0, 1fr)); gap: 2rem; padding-block: 2rem; }
.site-footer__col { display: flex; flex-direction: column; gap: 0.5rem; align-content: start; }
.site-footer__brand { display: flex; align-items: center; gap: 12px; }
.site-footer__brand img { height: 34px; width: auto; }
.site-footer__brand .brand__name { font-size: 1.05rem; font-weight: 700; }
.site-footer__brand .brand__tag { font-size: 0.56rem; }
.site-footer__col a { color: var(--fg-muted); text-decoration: none; }
.site-footer__col a:hover { color: var(--fg); }
.site-footer__legal { color: var(--fg-muted); font-size: 0.85rem; padding-bottom: 1.5rem; }

.docs-body h1, .docs-body h2, .docs-body h3 { margin-top: 1.4em; }
.docs-body ul, .docs-body ol { padding-left: 1.4rem; }
.docs-body table { margin-block: 1rem; }

.stack { display: flex; flex-direction: column; gap: 1rem; }
.cluster { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }
.text-muted { color: var(--fg-muted); }
.hero { position: relative; padding-block: clamp(2.5rem, 2rem + 3vw, 5rem); }
.hero__actions { display: flex; gap: 0.75rem; flex-wrap: wrap; margin-top: 1.5rem; }

@media (max-width: 640px) {
  .site-header__bar { flex-wrap: wrap; }
  .nav { gap: 0.85rem; }
}

/* Secondary navigation for the signed-in portal and admin areas (rendered by _Layout.cshtml). */
.sub-nav { background: var(--bg-raised); border-bottom: 1px solid var(--border); }
.sub-nav .container { display: flex; gap: 0.25rem; overflow-x: auto; }
.sub-nav a { display: inline-block; padding: 0.65rem 0.75rem; color: var(--fg-muted); text-decoration: none; border-bottom: 2px solid transparent; white-space: nowrap; }
.sub-nav a:hover { color: var(--fg); }
.sub-nav a[aria-current="page"] { color: var(--fg); border-bottom-color: var(--accent); }
/* ==========================================================================
   Redesign components, 2026-09-02.

   Everything below comes from the design canvas. It is written as classes
   rather than inline style attributes on purpose: the portal's CSP sets
   style-src 'self' with no 'unsafe-inline', so a style="" attribute is
   dropped by the browser and the element silently loses its layout.
   ========================================================================== */

/* --- Brand lockup --------------------------------------------------------
   DynDyn Technologies is the company; DynDyn.Pdf is one product under it.
   The qualifier is set lighter so the wordmark still reads as one unit. */
.brand__co { font-weight: 500; color: var(--fg-muted); }

/* --- Primary nav ---------------------------------------------------------
   Three items only: two menu triggers and Pricing. The trigger is a button
   for keyboard and screen-reader reasons, so it needs the anchor's look
   rebuilt on it from scratch. */
.nav__trigger {
  display: inline-flex; align-items: center; gap: 5px;
  background: none; border: 0; padding: 0; margin: 0;
  color: var(--fg-muted); font-family: inherit; font-size: 1rem;
  font-weight: 500; line-height: inherit; cursor: pointer;
}
.nav__trigger:hover { color: var(--link-hover); }
.nav__trigger[aria-current="page"] { color: var(--fg); }
.nav__trigger[aria-expanded="true"] { color: var(--accent); font-weight: 600; }
.nav__trigger svg { transition: transform .12s ease; }
.nav__trigger[aria-expanded="true"] svg { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .nav__trigger svg { transition: none; }
}

/* The links wrapper stays transparent to flex layout on desktop (its buttons
   and the Pricing link are still direct flex items of .nav); below the nav
   breakpoint it is hidden in favour of .nav__toggle + #mobile-nav. */
.nav__links { display: contents; }

/* Hamburger disclosure for the stacked mobile panel. Hidden above the nav
   breakpoint via CSS only; a11y state (aria-expanded) is driven by nav.js,
   which treats it like any other [data-menu-trigger]. */
.nav__toggle {
  display: none;
  align-items: center; justify-content: center;
  width: 2.25rem; height: 2.25rem;
  background: var(--bg-raised); border: 1px solid var(--border); border-radius: var(--radius);
  color: var(--fg); cursor: pointer; padding: 0;
}
.nav__toggle:hover { border-color: var(--accent); }

/* --- Mega menus ----------------------------------------------------------
   Anchored to the header, full content width, closed by default. Hidden with
   [hidden] so the markup stays in the document for assistive tech and the
   panel needs no JS to be readable when scripting is off. */
.has-menu { position: relative; }
.mega { position: absolute; top: 100%; left: 0; right: 0; padding-top: 8px; z-index: 40; }
.mega[hidden] { display: none; }
.mega__panel {
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lift);
  padding: 24px;
}
.mega__split { display: grid; grid-template-columns: 288px minmax(0, 1fr); gap: 24px; }
.mega__foot {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--border);
}
.mega__scrim { position: fixed; inset: 0; background: rgba(20, 23, 26, .42); z-index: 30; }
.mega__scrim[hidden] { display: none; }

/* Mobile nav: same anchored/hidden pattern as .mega, stacked sections rather
   than the two-column mega layout so it reads on a phone. */
.mobile-nav { position: absolute; top: 100%; left: 0; right: 0; padding-top: 8px; z-index: 40; }
.mobile-nav[hidden] { display: none; }
.mobile-nav__panel {
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 16px 40px rgba(20, 23, 26, .18), 0 2px 8px rgba(20, 23, 26, .08);
  padding: 16px; max-height: calc(100vh - 72px); overflow-y: auto;
}
.mobile-nav__section { padding-block: 12px; border-top: 1px solid var(--border); }
.mobile-nav__section:first-child { border-top: 0; padding-top: 0; }
.mobile-nav__heading { margin: 0 0 8px; font-size: .8125rem; text-transform: uppercase; letter-spacing: .04em; color: var(--fg-muted); }
.mobile-nav__link { display: block; padding: 9px 4px; color: var(--fg); text-decoration: none; border-radius: 6px; }
.mobile-nav__link:hover { background: var(--bg-inset); }
.mobile-nav__link--top { font-weight: 600; }

/* The flagship product card in the Solutions menu. */
.prod {
  display: flex; flex-direction: column;
  border: 1px solid var(--pc-cv-deep); box-shadow: 0 0 0 1px var(--pc-cv-deep);
  border-radius: var(--radius); overflow: hidden;
  text-decoration: none; color: inherit; background: var(--bg);
  transition: transform .2s ease, box-shadow .25s ease;
}
.prod:hover { transform: translateY(-3px); box-shadow: 0 0 0 1px var(--pc-cv-deep), var(--shadow-lift); }
.prod__thumb { display: block; width: 100%; height: 124px; object-fit: cover; }
.prod__thumb--logo { object-fit: contain; padding: 22px 20px 10px; box-sizing: border-box; }
.prod__body { padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 7px; flex: 1; }
.prod__name { font-weight: 700; font-size: 1.0625rem; display: flex; align-items: center; gap: 8px; }
.prod__more { color: var(--accent); font-weight: 600; font-size: .9rem; margin-top: auto; padding-top: 8px; }

/* Sibling products, demoted to a footnote until they exist. */
.sibling-row { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.sibling { display: inline-flex; align-items: center; gap: 7px; text-decoration: none; color: var(--fg-muted); font-size: .9rem; }
.sibling strong { color: var(--fg); font-weight: 600; }
.sibling img { width: 34px; height: 26px; border-radius: 4px; object-fit: cover; display: block; }
.sibling__logo { height: 24px !important; width: auto !important; max-width: 132px; object-fit: contain !important; border-radius: 4px; }
.sibling .badge { flex: none; }

/* --- Product family cards -------------------------------------------------
   One card per product, colour-coded via the .tint-* classes: the shared base
   mark (logo1.svg), a product-coloured hairline at the top edge, and the
   qualifier set in the product's deep tone. */
.product-card { position: relative; overflow: hidden; display: flex; align-items: flex-start; gap: 18px; transition: transform .2s ease, box-shadow .25s ease; }
.product-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); }
.product-card::before { content: ""; position: absolute; top: 0; left: 24px; right: 24px; height: 3px; border-radius: 0 0 4px 4px; background: linear-gradient(90deg, var(--pc, var(--pc-co)), transparent); }
.product-card__mark { flex: none; width: 58px; height: auto; margin-top: 14px; }
.product-card__body { min-width: 0; }
.product-card__title { margin: 2px 0 2px; font-size: 1.18rem; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.product-card__sub { margin: 0 0 10px; color: var(--pc-deep, var(--pc-co-deep)); font-weight: 600; font-size: 0.88rem; }
a.product-card { text-decoration: none; color: inherit; }

/* Featured pricing tier: ink outline ring + floating flag, shared by the home
   preview and the pricing page. */
.tier--featured { position: relative; border-color: var(--ink); box-shadow: 0 0 0 1.5px var(--ink), var(--shadow-lift); }
.tier__flag { position: absolute; top: -13px; left: 50%; transform: translateX(-50%); background: var(--ink); color: var(--bg); font-size: 0.72rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; padding: 5px 14px; border-radius: 999px; box-shadow: 0 0 0 5px var(--bg); white-space: nowrap; }

/* Decorative ring constellation inside .band--ink. */
.band__rings { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; opacity: 0.35; }

/* --- Delivery forms ------------------------------------------------------
   One engine, four packagings. Named the way a buyer asks for them — "can we
   get a binary", "is there an API" — not after our project names. Used both
   in the Solutions menu (compact) and on the home page (full). */
.ways { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.ways--compact { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; align-content: start; }
.way {
  display: flex; flex-direction: column; gap: 10px;
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 20px; background: var(--bg); box-shadow: var(--shadow);
  text-decoration: none; color: inherit;
}
.way:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: var(--shadow-lift); }
.way, .quick { transition: transform .2s ease, box-shadow .25s ease, border-color .2s ease; }
.way__t { font-weight: 700; font-size: 1.1rem; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.way__d { color: var(--fg-muted); font-size: .9rem; line-height: 1.5; }
.way__meta { margin-top: auto; padding-top: 12px; border-top: 1px solid var(--border); color: var(--fg-muted); font-size: .8125rem; }
.ways--compact .way { flex-direction: row; gap: 12px; align-items: flex-start; padding: 13px 14px; background: var(--bg-raised); box-shadow: none; }
.ways--compact .way__t { font-size: .95rem; }
.ways--compact .way__d { font-size: .84rem; display: block; margin-top: 2px; }

/* --- Docs menu -----------------------------------------------------------
   Two audiences that share almost no vocabulary: the person who files the
   report, and the engineer who wires the converter into a build. Splitting
   them here is cheaper than making every docs page hedge. */
.docs-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
.docs-col { border: 1px solid var(--border); border-radius: var(--radius); padding: 18px 20px 20px; background: var(--bg-raised); }
/* The developer column is marked with an accent edge rather than a tinted
   background: a hardcoded tint would have to be redefined for the dark theme,
   and this reads the same in both. */
.docs-col--dev { border-left: 3px solid var(--accent); }
.docs-col__head { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.docs-col__head h3 { margin: 0; font-size: 1.1rem; }
.docs-col__for { font-size: .8125rem; color: var(--fg-muted); margin: 0 0 14px; }
.docs-list { display: flex; flex-direction: column; gap: 2px; }
.docs-item { display: flex; gap: 11px; align-items: flex-start; padding: 8px; margin: -8px -8px 0; border-radius: 6px; text-decoration: none; color: inherit; }
.docs-item:hover { background: var(--bg); }
.docs-item__t { font-weight: 600; font-size: .925rem; }
.docs-item__d { color: var(--fg-muted); font-size: .84rem; line-height: 1.45; display: block; }

/* --- Small shared pieces ------------------------------------------------- */
/* The eyebrow bullet is the ring mark in miniature: two overlapping circles in
   the accent of the section's product (set --eyebrow-accent, defaults slate). */
.eyebrow { display: inline-flex; align-items: center; gap: 9px; font-size: .78rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--fg-muted); margin: 0 0 10px; }
.eyebrow::before { content: ""; flex: none; width: 18px; height: 12px; background:
  radial-gradient(circle 5px at 5px 6px, transparent 3.4px, var(--eyebrow-accent) 3.6px, var(--eyebrow-accent) 5px, transparent 5.2px),
  radial-gradient(circle 5px at 12px 6px, transparent 3.4px, var(--eyebrow-accent) 3.6px, var(--eyebrow-accent) 5px, transparent 5.2px); }
.icon-tile {
  width: 40px; height: 40px; border-radius: var(--radius);
  background: var(--bg-inset); border: 1px solid var(--border);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--accent); flex: none;
}
.icon-tile--sm { width: 32px; height: 32px; border-radius: 7px; background: var(--bg); }
.mono { font-family: var(--font-mono, ui-monospace, SFMono-Regular, Consolas, monospace); font-size: .8rem; color: var(--fg-muted); }
.credit { color: var(--fg-muted); font-size: .78rem; }
.step { display: flex; gap: 14px; align-items: flex-start; }
.step__num {
  width: 28px; height: 28px; border-radius: 999px; background: var(--accent); color: var(--accent-fg);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .875rem; font-weight: 700; flex: none;
}

/* --- Photographic bands --------------------------------------------------
   The scrim is what makes arbitrary photography safe to set type on. Never
   rely on the image's own contrast — a new photo will break it. */
.band { position: relative; overflow: hidden; }
.band__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.band__scrim { position: absolute; inset: 0; background: linear-gradient(90deg, rgba(9, 17, 30, .95) 0%, rgba(9, 17, 30, .88) 44%, rgba(9, 17, 30, .5) 100%); }
.band__scrim--down { background: linear-gradient(180deg, rgba(9, 17, 30, .9) 0%, rgba(9, 17, 30, .78) 100%); }
.band__inner { position: relative; }
.band__split { display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: 48px; align-items: center; }
.on-dark, .on-dark h2, .on-dark h3 { color: #ffffff; }
.on-dark .eyebrow { color: rgba(255, 255, 255, .7); }
.on-dark .text-muted, .on-dark .lede { color: rgba(255, 255, 255, .84); }
.btn-on-dark { background: #ffffff; color: #14171a; border-color: #ffffff; }
.btn-on-dark-ghost { background: rgba(255, 255, 255, .08); color: #ffffff; border-color: rgba(255, 255, 255, .45); }

/* --- Footer --------------------------------------------------------------
   Five columns: brand, Solutions, Client docs, Developer docs, Company.
   Legal moved into the bottom bar as an inline run so the docs split could
   have a column each. */
.site-footer__legal { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; }
.footer-legal-links { display: flex; flex-wrap: wrap; gap: 16px; }
.footer-legal-links a { color: var(--fg-muted); text-decoration: none; }

/* --- Portal overview ----------------------------------------------------- */
.page-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; flex-wrap: wrap; }
/* Column flex, not the default inline flow: label, value and hint are all <span>s, so as inline
   boxes they ran together on one wrapping line ("ACTIVE LICENCES 1 1 Evaluation") and the
   margin-top below was inert. As flex items they stack, and a .field-hint nested *inside*
   .stat__value ("0 of 1") still renders inline because it is not a direct child. */
.stat { background: var(--bg-inset); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px 18px; display: flex; flex-direction: column; align-items: stretch; }
.stat__label { display: flex; align-items: center; gap: 6px; color: var(--fg-muted); font-size: 0.72rem; font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase; }
.stat__value { font-family: var(--font-display); font-size: 1.85rem; font-weight: 600; letter-spacing: -0.02em; color: var(--ink); line-height: 1.15; margin-top: 4px; font-variant-numeric: tabular-nums; }
.stat > .field-hint { margin-top: 2px; }
/* The track sits on .stat, which already uses --bg-inset; borrow the border tone so it reads. */
.meter { height: 6px; border-radius: 999px; background: var(--border); overflow: hidden; margin-top: 10px; }
.meter__fill { height: 100%; background: var(--accent); border-radius: 999px; }
.kv { display: grid; grid-template-columns: max-content 1fr; gap: 8px 20px; margin: 0; }
.kv dt { color: var(--fg-muted); font-size: .875rem; }
.kv dd { margin: 0; font-size: .875rem; }
.quick { display: flex; gap: 12px; align-items: center; padding: 16px; border: 1px solid var(--border); border-radius: var(--radius); text-decoration: none; color: inherit; background: var(--bg); }
.quick:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: var(--shadow-lift); }

/* --- Licence list -------------------------------------------------------- */
.chip { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--border); border-radius: 999px; padding: 5px 12px; font-size: .8125rem; background: var(--bg); color: var(--fg-muted); text-decoration: none; }
.chip[aria-pressed="true"] { background: var(--bg-inset); color: var(--fg); font-weight: 600; }
.lic-card { border: 1px solid var(--border); border-radius: var(--radius); padding: 16px 18px; background: var(--bg-raised); display: flex; flex-direction: column; gap: 10px; }
.lic-card--muted { opacity: .72; }
.lic-card__top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.lic-id { font-family: var(--font-mono, ui-monospace, Consolas, monospace); font-size: .8rem; color: var(--fg-muted); }
.search { border: 1px solid var(--border); border-radius: var(--radius); padding: 7px 12px; color: var(--fg-muted); background: var(--bg); font-size: .875rem; min-width: 220px; }

/* --- Layout utilities ----------------------------------------------------
   Only what the pages actually need, because inline styles are not an option
   under the CSP. Kept deliberately small — a general utility framework here
   would outgrow the stylesheet it lives in. */
.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
.grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.grid-sidebar { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 24px; align-items: start; }
.measure-title { max-width: 22ch; }
.measure-lede { max-width: 62ch; }
.measure-copy { max-width: 70ch; }
.mt-auto { margin-top: auto; }
/* margin-top: auto resolves to 0 when the flex container has no spare height, so in a short card
   the trailing button row lands flush against the content above it. A floor keeps the gap either way. */
.card > .cluster.mt-auto { padding-top: 16px; }
.mb-0 { margin-bottom: 0; }
.mb-8 { margin-bottom: 8px; }
.mb-16 { margin-bottom: 16px; }
.mb-24 { margin-bottom: 24px; }
.mb-32 { margin-bottom: 32px; }
.section--tight { padding-block: 48px; }

/* --- Utilities merged from the feature stylesheets, 2026-09-03 -----------
   home.css, features.css and pricing.css each defined these independently
   during the parallel redesign (four agents, each told not to touch this
   file). Consolidated here so there is exactly one definition of each. */
.text-center { text-align: center; }
.mx-auto { margin-inline: auto; }
/* Mirrors the .mb-* set above, which only ever went one direction. */
.mt-16 { margin-top: 16px; }
.mt-20 { margin-top: 20px; }
.mt-24 { margin-top: 24px; }
.mt-32 { margin-top: 32px; }

/* justify-content modifiers for .cluster (which only sets flex-start/wrap
   by default). */
.cluster--between { justify-content: space-between; }
.cluster--center { justify-content: center; }

/* --- Shared card/icon-tile modifiers ---------------------------------------
   "accent" is the highlighted-tier / highlighted-stage treatment (the
   Pro pricing card on the home and pricing pages, and the final
   stage of the Features pipeline diagram); "base"/"flush" turn the default
   raised .card into a zero-padding, page-background card for wrapping a
   table so the table's own borders reach the edges. */
.card--accent { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent), 0 1px 6px rgba(20, 23, 26, .06); }
.card--base { background: var(--bg); }
.card--flush { padding: 0; }
.icon-tile--accent { border-color: var(--accent); color: var(--accent); }
.icon-tile--lg { width: 48px; height: 48px; }

/* Accent-tinted badge ("Most chosen" on the highlighted pricing tier). */
.badge--accent { background: var(--bg-inset); color: var(--accent); }

@media (max-width: 900px) {
  .ways, .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Brand cell spans the row, link columns pair up beneath it. */
  .site-footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .site-footer__grid > .site-footer__col:first-child { grid-column: 1 / -1; }
  .grid-3, .grid-2, .grid-sidebar, .docs-cols, .mega__split, .band__split { grid-template-columns: minmax(0, 1fr); }
  .band__split { gap: 24px; }
  .nav__links { display: none; }
  .nav__toggle { display: inline-flex; }
}
@media (max-width: 560px) {
  .ways, .grid-4, .ways--compact { grid-template-columns: minmax(0, 1fr); }
  .site-footer__grid { grid-template-columns: minmax(0, 1fr); }
  .site-footer__legal { flex-direction: column; align-items: flex-start; }
}

/* ==========================================================================
   Brand layer, 2026-09-10 — Ink & Rings.

   Components that carry the logo system: product colour tints, the blueprint
   grid backdrop, the "live text" selection sweep, the ink CTA band, activity
   timelines with ring bullets, and scroll-reveal. All CSP-safe: no inline
   styles anywhere, tints are classes because a style="" attribute would be
   dropped by the policy.
   ========================================================================== */

/* Product tint: sets --pc (mark/fill tone), --pc-deep (text-safe tone) and the
   eyebrow bullet colour. Apply to any card, section or list. */
.tint-co { --pc: var(--pc-co); --pc-deep: var(--pc-co-deep); --eyebrow-accent: var(--pc-co); }
.tint-cv { --pc: var(--pc-cv); --pc-deep: var(--pc-cv-deep); --eyebrow-accent: var(--pc-cv); }
.tint-tg { --pc: var(--pc-tg); --pc-deep: var(--pc-tg-deep); --eyebrow-accent: var(--pc-tg); }
.tint-ds { --pc: var(--pc-ds); --pc-deep: var(--pc-ds-deep); --eyebrow-accent: var(--pc-ds); }

/* Blueprint grid backdrop for hero sections — documents, drafting, precision.
   Two soft brand-coloured glows keep it from reading as graph paper. */
.blueprint {
  background-image:
    radial-gradient(900px 420px at 85% -10%, color-mix(in srgb, var(--pc-ds) 16%, transparent), transparent 62%),
    radial-gradient(720px 380px at 4% 108%, color-mix(in srgb, var(--pc-cv) 13%, transparent), transparent 62%),
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: auto, auto, 28px 28px, 28px 28px;
}

/* "Live text" selection sweep: a highlight drawn across a word as if the
   reader were selecting it — the product's differentiator, on its headline. */
.sweep { position: relative; z-index: 0; white-space: nowrap; }
.sweep::after {
  content: ""; position: absolute; left: -0.06em; right: -0.06em; top: 0.16em; height: 0.72em;
  border-radius: 3px; background: color-mix(in srgb, var(--accent) 20%, transparent);
  z-index: -1; transform-origin: left center;
  animation: sweep-draw 1.4s cubic-bezier(.6, 0, .3, 1) .6s both;
}
@keyframes sweep-draw { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* Ink CTA band: the photographic bands' quiet sibling. Deep navy with brand
   glows; pair with .on-dark and an inline ring-mark SVG in the markup. */
.band--ink {
  background:
    radial-gradient(700px 340px at 12% 0%, color-mix(in srgb, var(--pc-ds) 20%, transparent), transparent 62%),
    radial-gradient(620px 320px at 88% 100%, color-mix(in srgb, var(--pc-cv) 15%, transparent), transparent 62%),
    var(--ink-deep);
}

/* Activity timeline with ring-mark bullets (portal dashboard, admin overview). */
.timeline { display: flex; flex-direction: column; }
.tl { display: grid; grid-template-columns: 30px 1fr auto; gap: 12px; padding-block: 11px; border-bottom: 1px solid var(--border); align-items: baseline; }
.tl:last-child { border-bottom: 0; }
.tl__dot { justify-self: center; position: relative; top: 3px; }
.tl__when { color: var(--fg-muted); font-size: 0.78rem; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* --- Auth pages (Login, Register) -----------------------------------------
   Split card: an ink brand panel with the ring mark beside the form, so the
   two auth pages share one layout instead of card-form vs bare-form. */
.auth-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr); gap: 24px; align-items: stretch; max-width: 880px; margin-inline: auto; }
.auth-brand {
  position: relative; overflow: hidden; border-radius: var(--radius-lg);
  background:
    radial-gradient(420px 240px at 15% 0%, color-mix(in srgb, var(--pc-ds) 22%, transparent), transparent 62%),
    radial-gradient(380px 220px at 90% 100%, color-mix(in srgb, var(--pc-cv) 16%, transparent), transparent 62%),
    var(--ink-deep);
  color: #ffffff; padding: 36px 32px; display: flex; flex-direction: column; justify-content: space-between; gap: 40px;
}
.auth-brand h2 { color: #ffffff; font-size: 1.45rem; margin-bottom: 0.4em; }
.auth-brand p { color: rgba(255, 255, 255, 0.75); margin: 0; }
.auth-form h1 { font-size: 1.8rem; }
@media (max-width: 760px) {
  .auth-grid { grid-template-columns: minmax(0, 1fr); }
  .auth-brand { gap: 20px; padding: 28px 26px; }
}

/* Scroll-reveal. The pre-hide state is gated on html.js — the class the inline
   head script adds — so nothing is ever hidden when scripting is off. reveal.js
   adds .rv-in as elements enter the viewport. */
html.js .rv { opacity: 0; transform: translateY(14px); transition: opacity 0.65s cubic-bezier(.2, .7, .3, 1), transform 0.65s cubic-bezier(.2, .7, .3, 1); }
html.js .rv-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  html.js .rv { opacity: 1; transform: none; transition: none; }
  .sweep::after { animation: none; transform: scaleX(1); }
}
