/* ============================================================
   a360 — Where Transformation Begins
   Palette: paper #FFFFFF · ink #17181C · muted #5C6067
   Brand: light blue #0E8FC8 · dark blue #0B384F, with derived
   shades #1273A1 · #35A7D9 · #6CC3E8 · #B9E2F5
   Type: Bricolage Grotesque (display) · Figtree (body/UI) ·
         Baloo 2 800 (wordmark type); logo artwork in /assets
   ============================================================ */

:root {
  --paper: #ffffff;
  --ink: #17181c;
  --muted: #5c6067;
  --line: #e8e8ec;
  --pill: #f1f2f4;
  --panel: #060608;
  --brand: #0e8fc8;       /* light blue */
  --brand-dark: #0b384f;  /* dark blue */
  --heading: var(--brand-dark);
  /* derived shades keep the legacy accent slots on-brand */
  --azure: #0e8fc8;
  --teal: #35a7d9;
  --amber: #6cc3e8;
  --coral: #1273a1;
  --violet: #0b384f;
  --display: "Eurostile GEO Mt", "Bricolage Grotesque", "Noto Sans Georgian", sans-serif;
  --body: "Figtree", "Noto Sans Georgian", sans-serif;
  --mono: "JetBrains Mono", monospace;
  --wordmark: "Baloo 2", sans-serif;
  --radius-panel: 28px;
  --gutter: clamp(20px, 3.5vw, 50px);
  /* One vertical rhythm scale for section spacing (was ad-hoc per section). */
  --section-y: clamp(88px, 12vh, 160px);
  --section-y-sm: clamp(56px, 8vh, 104px);
  --content-max: 1440px;
}

/* Eurostile GEO Mt Demi is used for headings (--display) in both English and
   Georgian. Body copy (--body) is untouched. */
@font-face {
  font-family: "Eurostile GEO Mt";
  src: url("../assets/fonts/Dachi the Lynx-46841546889.otf") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
/* Eurostile GEO Mt is a wide, geometric face — at the same px it reads much
   larger and runs much wider than Bricolage, so the biggest display headings
   (.hero__title, .footerpanel__content h2, .builtfor__title, .statement__text)
   are scaled down and de-tightened at their definitions further below. */

/* ---------- Logo (official artwork) ---------- */
.logo-img { width: auto; display: block; }
.logo-img--nav { height: 30px; }
.logo-img--showcase { height: clamp(64px, 9vw, 120px); }
.logo-img--footer { height: 26px; }
.logo-img--hero { height: clamp(44px, 4.6vw, 66px); }

/* ---------- Wordmark type (matches the logo lettering) ---------- */
.wordmark {
  font-family: var(--wordmark);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--brand-dark);
  display: inline-block;
  transform: skewX(-7deg);
  padding-top: 0.24em; /* room for the macron bar over the 0 */
}
.wordmark__a { color: var(--brand); }
.wordmark__o { position: relative; display: inline-block; }
.wordmark__o::after {
  content: "";
  position: absolute;
  top: -0.22em;
  left: 56%;
  transform: translateX(-50%);
  width: 0.64em;
  height: 0.15em;
  border-radius: 0.075em;
  background: var(--brand);
}
.wordmark--hero { font-size: clamp(34px, 3.6vw, 52px); }

* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }

/* Georgian: hold the text back until it's translated.
   The copy ships in the HTML in English and i18n.js swaps it in a deferred
   script, so without this the browser paints a frame of English on every load
   and navigation. The inline <head> script adds .i18n-wait before first paint
   when the stored language is `ka`, and i18n.js removes it the moment the swap
   is done. `visibility` (not `display`) keeps layout and the themed background
   intact, so this reads as text arriving, not a blank page.

   Two things stop this ever stranding a page invisible: the class is only added
   by JS, so a visitor without JS sees English immediately and never sees this
   rule at all; and the same inline script arms a 2s timer that clears the class
   even if i18n.js fails to load. English (`lang` unset or `en`) never gets the
   class, so it is unaffected. */
.i18n-wait body { visibility: hidden; }

/* Entrance animations: hold the elements back until GSAP owns them.
   js/main.js builds its reveals with gsap.from({autoAlpha: 0}), which can only
   hide an element once the script has run — and it runs late (deferred, after
   the GSAP CDN, and on a CMS page after the body has been fetched). Without
   this the browser paints the finished layout first, GSAP then rewinds it to
   invisible, and the copy flashes in, out, and back in.

   Same shape as .i18n-wait above: the inline <head> script adds .anim-wait
   before first paint, so the elements are already invisible when GSAP records
   their from-state; main.js clears the class as soon as every tween is built,
   which also restores anything GSAP didn't claim. The class is only ever added
   with JS on and motion allowed, and the same inline script arms a timer that
   clears it if the CDN or main.js never arrives. */
.anim-wait [data-hero],
.anim-wait .section-head > *,
.anim-wait [data-reveal],
.anim-wait [data-reveal-group] > *,
.anim-wait .showcase__lockup,
.anim-wait .feature__copy,
.anim-wait .feature .card,
.anim-wait .ucase,
.anim-wait .cta__col,
.anim-wait .post,
.anim-wait [data-flip] > *,
.anim-wait [data-settle],
.anim-wait [data-steps] .pstep { visibility: hidden; }
@media (prefers-reduced-motion: reduce) {
  /* Nothing animates in, so nothing should be held back. */
  .anim-wait [data-hero],
  .anim-wait .section-head > *,
  .anim-wait [data-reveal],
  .anim-wait [data-reveal-group] > *,
  .anim-wait .showcase__lockup,
  .anim-wait .feature__copy,
  .anim-wait .feature .card,
  .anim-wait .ucase,
  .anim-wait .cta__col,
  .anim-wait .post,
  .anim-wait [data-flip] > *,
  .anim-wait [data-settle],
  .anim-wait [data-steps] .pstep { visibility: visible; }
}

body {
  transition: background-color 0.3s, color 0.3s;
  font-family: var(--body);
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img, svg, canvas { display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

/* Consistent, visible keyboard focus across every interactive element
   (previously only .btn had one — nav links, icon buttons, and card
   links fell back to inconsistent/no browser default). */
a:focus-visible, button:focus-visible {
  outline: 2px solid var(--azure);
  outline-offset: 3px;
  border-radius: 6px;
}
.navctl:focus-visible, .carousel__btn:focus-visible, .ucase__play:focus-visible {
  border-radius: 50%;
}

::selection { background: rgba(14, 143, 200, 0.2); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--body);
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
  padding: 11px 22px;
  border-radius: 999px;
  white-space: nowrap;
  transition: transform 0.25s cubic-bezier(0.3, 0.7, 0, 1), background-color 0.25s, box-shadow 0.25s;
  will-change: transform;
}
.btn svg { width: 15px; height: 15px; flex: none; }
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }
.btn--dark { background: var(--brand-dark); color: #fff; }
.btn--dark:hover { background: #082a3c; box-shadow: 0 10px 24px -10px rgba(11, 56, 79, 0.55); }
.btn--ghost { background: var(--pill); color: var(--ink); }
.btn--ghost:hover { background: #e8e9ed; }
/* Always sits on white, so the ink is fixed rather than theme-bound. */
.btn--light { background: #fff; color: #17181c; }
.btn--light:hover { box-shadow: 0 12px 30px -10px rgba(255, 255, 255, 0.45); }
.btn--lg { font-size: 15.5px; padding: 14px 27px; }

/* ---------- Section head (eyebrow + lead) ----------
   Self-contained content column: aligns to the shared 1440 column on wide
   screens and to the gutter on mobile, independent of the parent section. */
.section-head {
  max-width: calc(var(--content-max) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
  margin-bottom: clamp(38px, 5.5vh, 68px);
}
.eyebrow {
  display: inline-flex;
  align-items: center;
  font-family: var(--body);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--brand);
  margin-bottom: 18px;
}
.section-head__title {
  font-family: var(--display);
  color: var(--heading);
  font-size: clamp(26px, 3vw, 44px);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.012em;
  max-width: 18ch;
}
.section-head__lead {
  margin-top: 16px;
  font-size: clamp(15.5px, 1.15vw, 18px);
  line-height: 1.6;
  color: var(--muted);
  max-width: 54ch;
}

/* ---------- Nav ---------- */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  transition: background-color 0.35s, box-shadow 0.35s, backdrop-filter 0.35s;
}
.nav.is-scrolled {
  background: rgba(255, 255, 255, 0.82);
  backdrop-filter: blur(14px);
}
.nav__inner {
  display: flex;
  align-items: center;
  gap: 30px;
  max-width: calc(var(--content-max) + 2 * var(--gutter));
  margin: 0 auto;
  padding: 14px var(--gutter);
}
.nav__brand { display: flex; align-items: center; }
.nav__links { display: flex; gap: 4px; margin-left: 12px; }
.nav__links a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  padding: 8px 14px;
  border-radius: 999px;
  white-space: nowrap;
  transition: background-color 0.2s;
}
.nav__links a:hover { background: var(--pill); }
.nav__links svg { width: 9px; height: 6px; opacity: 0.55; }
.nav__cta { margin-left: auto; padding: 10px 19px; font-size: 14px; }
@media (max-width: 1024px) { .nav__links { display: none; } }
@media (max-width: 560px) { .nav__cta { display: none; } }

/* ---------- Mega menu (desktop dropdowns) ---------- */
.nav__caret { transition: transform 0.28s cubic-bezier(0.3, 0.7, 0, 1); }
.nav__trigger[aria-expanded="true"] { background: var(--pill); }
.nav__trigger[aria-expanded="true"] .nav__caret { transform: rotate(180deg); }

/* Hides every caret until js/cms-nav.js has confirmed which sections actually
   have a dropdown — otherwise all three flash a caret on load, then two of
   them lose it a moment later once the empty ones are pruned. */
.nav--menus-pending .nav__caret { display: none; }
/* Keep the bar opaque while a panel is open (even at the top, un-scrolled). */
.nav.nav--open { background: var(--paper); }

.mega {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  overflow: hidden;
  height: 0;
  background: var(--paper);
  box-shadow: 0 24px 40px -28px rgba(23, 24, 28, 0.4);
}
/* The border used to sit on .mega itself, but a border is part of the box
   model and paints even at height:0 — overflow:hidden only clips content, not
   the element's own border — so it showed as a permanent hairline under the
   nav regardless of whether the dropdown was open. Living on .mega__inner
   instead, it's clipped away by the parent's height:0 until the panel actually
   opens. */
.mega__inner {
  max-width: calc(var(--content-max) + 2 * var(--gutter));
  margin: 0 auto;
  padding: clamp(26px, 3vh, 42px) var(--gutter) clamp(30px, 4vh, 46px);
  border-bottom: 1px solid var(--line);
}
.mega__panel { display: none; }
.mega__panel.is-active {
  display: grid;
  grid-template-columns: minmax(210px, 300px) 1fr;
  gap: clamp(30px, 5vw, 96px);
}
.mega__head {
  font-family: var(--display);
  font-size: clamp(19px, 1.5vw, 25px);
  font-weight: 600;
  line-height: 1.16;
  letter-spacing: -0.02em;
  color: var(--heading);
  max-width: 15ch;
}
.mega__cta { margin-top: 22px; }
.mega__label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 12px;
  padding-left: 12px;
}
.mega__grid--logos { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px 8px; }
@media (max-width: 1080px) { .mega__grid--logos { grid-template-columns: repeat(2, 1fr); } }
.mega__co {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 12px;
  border-radius: 12px;
  font-size: 14.5px;
  font-weight: 500;
  color: var(--ink);
  transition: background-color 0.2s;
}
.mega__co:hover { background: var(--pill); }
.mega__co-ic {
  width: 28px;
  height: 28px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: var(--pill);
}
.mega__co:hover .mega__co-ic { background: var(--paper); box-shadow: inset 0 0 0 1px var(--line); }
.mega__co-ic img { width: 62%; height: 62%; object-fit: contain; filter: grayscale(1); opacity: 0.78; transition: filter 0.2s, opacity 0.2s; }
.mega__co:hover .mega__co-ic img { filter: none; opacity: 1; }
.mega__list { display: flex; flex-direction: column; gap: 2px; list-style: none; margin: 0; padding: 0; }
.mega__list a {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 11px 12px;
  border-radius: 10px;
  font-size: 15.5px;
  font-weight: 500;
  color: var(--ink);
  transition: background-color 0.2s;
}
.mega__list a:hover { background: var(--pill); }
.mega__li-ic { width: 18px; height: 18px; flex: none; display: grid; place-items: center; color: var(--brand); }
.mega__li-ic svg { width: 18px; height: 18px; }
.mega__li-ic img { width: 100%; height: 100%; object-fit: contain; border-radius: 3px; }
.mega__go { width: 9px; height: 6px; margin-left: 4px; opacity: 0.5; }

.mega-backdrop {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: rgba(23, 24, 28, 0.06);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
:root[data-theme="dark"] .mega-backdrop { background: rgba(0, 0, 0, 0.5); }
:root[data-theme="dark"] .mega { box-shadow: 0 24px 44px -28px rgba(0, 0, 0, 0.7); }
:root[data-theme="dark"] .mega__co:hover .mega__co-ic { background: var(--pill); box-shadow: inset 0 0 0 1px var(--line); }
:root[data-theme="dark"] .mega__co-ic img { filter: grayscale(1) brightness(1.5); }
:root[data-theme="dark"] .mega__co:hover .mega__co-ic img { filter: none; }
@media (max-width: 1024px) { .mega, .mega-backdrop { display: none !important; } }

/* ---------- Hero ---------- */
.hero {
  position: relative;
  min-height: 100vh;
  display: grid;
  place-items: center;
  overflow: hidden;
}
.hero__canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.hero__content {
  position: relative;
  text-align: center;
  padding: 120px var(--gutter) 60px;
  pointer-events: none;
  /* The hero is a centred grid, so without this the content sizes to
     max-content and a long headline word pushes it wider than the viewport —
     which reads as "not centred" once body's overflow-x clips the left side. */
  width: 100%;
  max-width: 100%;
}
.hero__content a { pointer-events: auto; }
.hero__lockup {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-bottom: 26px;
}
.hero__title {
  font-family: var(--display);
  font-size: clamp(34px, 5.4vw, 76px);
  font-weight: 600;
  line-height: 1.04;
  letter-spacing: -0.02em;
  /* Brand navy (pale blue on the dark theme) — --heading is theme-aware. */
  color: var(--heading);
}
.hero__line { display: block; }
/* Phones: the min of the clamp above is still too large for the longest
   headline word, so scale it down rather than letting the line overflow. */
@media (max-width: 560px) {
  .hero__title { font-size: clamp(24px, 6.8vw, 34px); }
}
.hero__actions {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin-top: 44px;
  flex-wrap: wrap;
}

/* ---------- Showcase (dark panel) ---------- */
.showcase { padding: clamp(40px, 8vh, 90px) var(--gutter) 0; }
.showcase__panel {
  position: relative;
  max-width: 1600px;
  margin: 0 auto;
  height: min(92vh, 900px);
  background: var(--panel);
  border-radius: var(--radius-panel);
  overflow: hidden;
  transform-origin: 50% 20%;
}
.showcase__canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.showcase__lockup {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  color: #fff;
}
.showcase__slogan {
  font-size: clamp(13px, 1.2vw, 16px);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.75);
}

/* Anchored targets clear the fixed nav when jumped to. */
[id] { scroll-margin-top: 88px; }

/* ---------- Statement / icon strip ---------- */
.statement { padding: var(--section-y) var(--gutter); }
.iconstrip { overflow: hidden; padding-block: 42px; margin-bottom: clamp(50px, 9vh, 120px); touch-action: pan-y; }
.iconstrip__row {
  display: flex;
  gap: 18px;
  width: max-content;
  will-change: transform;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
.iconstrip__row.is-dragging { cursor: grabbing; }
.chip {
  width: clamp(64px, 6.5vw, 92px);
  height: clamp(64px, 6.5vw, 92px);
  flex: none;
  will-change: transform; /* the wave rides on the chip itself */
}
.chip__disc {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: #f6f6f8;
  transition: transform 0.3s cubic-bezier(0.3, 0.7, 0, 1), filter 0.3s, opacity 0.3s;
}
.chip img {
  width: 54%;
  height: 54%;
  object-fit: contain;
  filter: grayscale(1);
  opacity: 0.75;
  transition: filter 0.3s, opacity 0.3s;
  /* Belt-and-suspenders alongside the dragstart preventDefault in js/main.js
     — Safari has needed this too, on top of cancelling the event, to fully
     give up its own "pick this image up" gesture. */
  -webkit-user-drag: none;
  user-drag: none;
}
/* hovering the strip softens every chip… */
.iconstrip__row:hover .chip__disc { filter: blur(3px); opacity: 0.6; }
/* …except the one under the cursor, which sharpens, colors, and grows */
.iconstrip__row .chip:hover .chip__disc { filter: none; opacity: 1; transform: scale(1.16); }
.chip:hover img { filter: none; opacity: 1; }
.statement__text {
  color: var(--heading);
  max-width: 980px;
  /* Align the left edge to the shared 1440 content column (matches features,
     blog, footer) instead of sitting flush against the gutter. */
  margin-left: max(0px, calc((100% - var(--content-max)) / 2));
  font-family: var(--display);
  font-size: clamp(24px, 3.1vw, 44px);
  font-weight: 500;
  line-height: 1.22;
  letter-spacing: -0.012em;
}
.statement__text .ch { opacity: 0.08; transition: opacity 0.08s linear; }
.statement__text .ch.is-on { opacity: 1; }
.statement__caret {
  display: inline-block;
  width: 3px;
  height: 0.92em;
  margin-left: 6px;
  background: var(--brand);
  vertical-align: -0.12em;
  animation: caret 1.05s steps(1) infinite;
}
@keyframes caret { 50% { opacity: 0; } }

/* ---------- Features ---------- */
.features { display: flex; flex-direction: column; gap: clamp(90px, 14vh, 190px); padding: 0 var(--gutter) var(--section-y); }
.feature {
  display: grid;
  grid-template-columns: minmax(280px, 420px) 1fr;
  gap: clamp(40px, 6vw, 110px);
  max-width: 1440px;
  margin: 0 auto;
  width: 100%;
  align-items: center;
}
.feature__copy { align-self: start; position: sticky; top: 18vh; }
.feature__title { font-family: var(--display); font-size: clamp(28px, 2.6vw, 40px); font-weight: 600; letter-spacing: -0.02em; margin-bottom: 16px; color: var(--heading); }
.feature__desc { font-size: 15.5px; line-height: 1.65; color: var(--muted); max-width: 40ch; margin-bottom: 26px; }
.feature__media { min-width: 0; }
@media (max-width: 900px) {
  .feature { grid-template-columns: 1fr; }
  .feature__copy { position: static; }
}

.card {
  position: relative;
  border-radius: 26px;
  aspect-ratio: 1.06 / 1;
  max-height: 640px;
  width: 100%;
  overflow: hidden;
  display: grid;
  place-items: center;
}

/* Platform card — rainbow aura */
.card--aura { background: #efefef; }
.card--aura::before {
  content: "";
  position: absolute;
  inset: -12%;
  background:
    radial-gradient(38% 42% at 12% 30%, rgba(14, 143, 200, 0.55), transparent 70%),
    radial-gradient(36% 40% at 88% 26%, rgba(11, 56, 79, 0.45), transparent 70%),
    radial-gradient(40% 44% at 85% 78%, rgba(108, 195, 232, 0.55), transparent 70%),
    radial-gradient(38% 42% at 14% 80%, rgba(53, 167, 217, 0.5), transparent 70%),
    radial-gradient(30% 34% at 50% 8%, rgba(18, 115, 161, 0.4), transparent 70%);
  filter: blur(38px);
  animation: aura 14s ease-in-out infinite alternate;
}
@keyframes aura {
  0% { transform: rotate(0deg) scale(1); }
  100% { transform: rotate(8deg) scale(1.08); }
}
.card--aura::after {
  content: "";
  position: absolute;
  inset: 7%;
  background: #f2f2f3;
  border-radius: 20px;
}
.promptui { position: relative; z-index: 1; width: min(78%, 460px); font-size: 13px; }
.promptui__project {
  display: flex; align-items: center; gap: 7px;
  font-weight: 600; color: #3a3d44; margin-bottom: 12px;
}
.promptui__project svg { width: 14px; height: 14px; }
.promptui__project svg:last-child { width: 9px; height: 6px; opacity: 0.5; }
.promptui__box { background: #fff; border-radius: 14px; padding: 14px 14px 10px; box-shadow: 0 2px 8px rgba(23, 24, 28, 0.05); }
.promptui__placeholder { color: #9599a1; margin-bottom: 14px; }
.promptui__row { display: flex; align-items: center; gap: 10px; }
.promptui__pill { display: grid; place-items: center; width: 24px; height: 24px; border-radius: 50%; background: #f1f2f4; color: #5c6067; font-weight: 600; }
.promptui__model { display: inline-flex; align-items: center; gap: 6px; color: #3a3d44; font-weight: 500; }
.promptui__model svg { width: 9px; height: 6px; opacity: 0.5; }
.promptui__mic { margin-left: auto; width: 30px; height: 30px; display: grid; place-items: center; border-radius: 50%; background: #f1f2f4; }
.promptui__mic svg { width: 15px; height: 15px; }
.promptui__row--tags { margin-top: 12px; background: #eceef1; border-radius: 0 0 10px 10px; margin-inline: -14px; margin-bottom: -10px; padding: 9px 14px; }
.promptui__tag { display: inline-flex; align-items: center; gap: 6px; color: #6a6e76; font-size: 12px; font-weight: 500; }
.promptui__tag svg { width: 12px; height: 12px; }
.promptui__tag svg:last-child { width: 8px; height: 5px; }
.promptui__menu {
  position: absolute;
  left: 12px;
  margin-top: 10px;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 10px 30px rgba(23, 24, 28, 0.14);
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 180px;
}
.promptui__menu span { display: flex; align-items: center; gap: 8px; padding: 7px 10px; border-radius: 8px; font-weight: 500; color: #3a3d44; }
.promptui__menu span:hover { background: #f4f5f7; }
.promptui__menu svg { width: 13px; height: 13px; }

/* Academy card — dark glowing ring */
.card--dark { background: radial-gradient(120% 120% at 50% 50%, #0d3d5c 0%, #071e2e 55%, #040f18 100%); }
.ring {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 74%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(closest-side, transparent 62%, rgba(14, 143, 200, 0.18) 70%, rgba(80, 190, 240, 0.78) 78%, rgba(185, 226, 245, 0.92) 82%, rgba(80, 190, 240, 0.55) 86%, transparent 96%);
  filter: blur(6px);
  animation: ringPulse 6s ease-in-out infinite alternate;
}
@keyframes ringPulse {
  0% { transform: scale(0.97); opacity: 0.85; }
  100% { transform: scale(1.03); opacity: 1; }
}
.card--dark__label {
  position: relative;
  z-index: 1;
  color: #eaf1ff;
  font-family: var(--display);
  font-size: clamp(26px, 2.8vw, 42px);
  font-weight: 600;
  letter-spacing: -0.01em;
  text-shadow: 0 0 26px rgba(110, 200, 245, 0.85);
}

/* Studio card — code editor */
.card--code { background: linear-gradient(135deg, #f2f4f8 0%, #fdf9f2 60%, #f7f1e8 100%); }
.codeui {
  width: min(86%, 560px);
  background: #fff;
  border-radius: 14px;
  box-shadow: 0 14px 44px rgba(23, 24, 28, 0.1);
  font-family: var(--mono);
  font-size: 12.5px;
  overflow: hidden;
}
.codeui__tabs { display: flex; gap: 18px; padding: 12px 18px; border-bottom: 1px solid var(--line); font-family: var(--body); font-size: 12.5px; color: #9599a1; font-style: italic; }
.codeui__file { display: inline-flex; align-items: center; gap: 6px; }
.codeui__file svg { width: 12px; height: 12px; }
.codeui__file--react { color: var(--brand); font-style: normal; font-weight: 600; }
.codeui__crumbs { padding: 12px 18px; font-family: var(--body); font-size: 13px; color: #9599a1; }
.codeui__crumbs i { font-style: normal; margin: 0 6px; }
.codeui__crumbs b { color: var(--ink); font-weight: 600; }
.codeui__body { display: flex; padding: 6px 0 26px; }
.codeui__gutter { display: flex; flex-direction: column; gap: 8px; padding: 4px 14px 0 18px; color: #b6bac2; text-align: right; }
.codeui__code { flex: 1; position: relative; padding-top: 4px; }
.codeui__linehl { background: #e6f3fa; padding: 2px 8px; border-radius: 3px; display: inline-block; min-width: 60%; }
.tok-kw { color: #9d3fd1; font-weight: 500; }
.tok-teal { color: var(--teal); }
.tok-mono { color: #7a7f88; }
.codeui__cursor { display: inline-block; width: 2px; height: 13px; background: #2b2d33; vertical-align: -2px; animation: caret 0.9s steps(1) infinite; }
.codeui__suggest {
  position: absolute;
  left: 8px;
  top: 30px;
  z-index: 2;
  background: #fff;
  border: 1px solid var(--line);
  box-shadow: 0 10px 26px rgba(23, 24, 28, 0.12);
  border-radius: 6px;
  padding: 4px;
  width: min(84%, 300px);
}
.codeui__suggest div { display: flex; align-items: center; gap: 8px; padding: 4px 8px; border-radius: 4px; color: #3a3d44; }
.codeui__suggest div.is-active { background: #e9eefb; }
.codeui__suggest i { font-style: normal; width: 16px; color: #9d3fd1; }
.codeui__suggest b { font-weight: 500; }
.codeui__suggest em { font-style: normal; margin-left: auto; color: #b0b4bc; font-size: 11px; }

/* ---------- Built-for ---------- */
.builtfor {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: clamp(30px, 5vw, 90px);
  align-items: end;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: 0 var(--gutter) var(--section-y);
}
.builtfor__title {
  color: var(--heading);
  font-family: var(--display);
  font-size: clamp(30px, 3.4vw, 50px);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.015em;
}
.builtfor__title span { display: block; }
.builtfor__desc { font-size: 15.5px; line-height: 1.65; color: var(--muted); max-width: 46ch; justify-self: end; }
@media (max-width: 900px) {
  .builtfor { grid-template-columns: 1fr; align-items: start; }
  .builtfor__desc { justify-self: start; }
}

/* ---------- Use cases carousel ----------
   Two cards sit inside a 1440px stage; everything wider than that is peek room
   where the neighbouring cards show through, scaled down and desaturated by
   js/main.js so the focused pair reads as the subject. --uc-pad is the leftover
   space on one side, which is also the offset that centres a pair (js/main.js
   snaps to it). Snapping and easing live in JS, not scroll-snap-type, so the
   GSAP glide isn't fighting the browser's own snap. */
.usecases { padding: 0 0 var(--section-y); }
.carousel {
  position: relative;
  --uc-gap: clamp(20px, 2.4vw, 40px);
  --uc-peek: clamp(56px, 7vw, 280px);
  --uc-w: min(
    (1440px - var(--uc-gap)) / 2,
    (100vw - 2 * var(--uc-peek) - var(--uc-gap)) / 2
  );
  --uc-pad: calc(50% - var(--uc-w) - var(--uc-gap) / 2);
}
.carousel__track {
  display: flex;
  gap: var(--uc-gap);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  padding: 0 var(--uc-pad);
  cursor: grab;
}
.carousel__track::-webkit-scrollbar { display: none; }
.carousel__track.is-dragging { cursor: grabbing; user-select: none; }
.ucase { flex: 0 0 var(--uc-w); }
/* The focus scale/fade rides on the inner wrapper so it never collides with the
   entrance tween GSAP runs on .ucase itself. Vertical origin sits at the middle
   of the artwork so shrunken neighbours stay aligned with the focused pair; the
   horizontal half is set per card in JS (a neighbour shrinks towards the stage,
   otherwise it would pull its sliver right out of the viewport). */
.ucase__inner { transform-origin: 50% 38%; will-change: transform; }
@media (max-width: 980px) {
  /* One card at a time; --uc-pad centres a single card instead of a pair. */
  .carousel {
    --uc-gap: 18px;
    --uc-w: min(84vw, 560px);
    --uc-pad: calc(50% - var(--uc-w) / 2);
  }
}
.ucase__media {
  position: relative;
  border-radius: 22px;
  aspect-ratio: 16 / 9.2;
  overflow: hidden;
  display: flex;
  align-items: center;
}
.ucase__media--a { background: linear-gradient(150deg, #a9adb4 0%, #8f959d 50%, #7d838d 100%); }
.ucase__media--b { background: linear-gradient(150deg, #b3b0a8 0%, #9a978e 50%, #85837b 100%); }
.ucase__media--c { background: linear-gradient(150deg, #adb3ae 0%, #939b95 50%, #7f8781 100%); }
.ucase__media--d { background: linear-gradient(150deg, #b0acb6 0%, #96919e 50%, #817c8a 100%); }
.ucase__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(90% 130% at 78% 115%, rgba(23, 24, 28, 0.5), transparent 55%),
    radial-gradient(60% 80% at 50% -10%, rgba(255, 255, 255, 0.28), transparent 60%);
}
.ucase__title {
  position: relative;
  z-index: 1;
  padding-left: clamp(20px, 3vw, 44px);
  color: #fff;
  font-family: var(--display);
  font-size: clamp(24px, 2.6vw, 40px);
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: -0.01em;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.25);
}
.ucase__play {
  position: absolute;
  right: 22px;
  bottom: 22px;
  z-index: 1;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.22);
  backdrop-filter: blur(6px);
  display: grid;
  place-items: center;
  color: #fff;
  transition: background-color 0.25s, transform 0.25s;
}
.ucase__play:hover { background: rgba(255, 255, 255, 0.4); transform: scale(1.06); }
.ucase__play svg { width: 16px; height: 16px; }
.ucase__body { max-width: 420px; padding: 24px 4px 0; }
.ucase__body h3 { font-size: 15.5px; font-weight: 700; margin-bottom: 8px; }
.ucase__body p { font-size: 14.5px; line-height: 1.6; color: var(--muted); margin-bottom: 14px; }
.ucase__body a { display: inline-flex; align-items: center; gap: 7px; font-size: 14px; font-weight: 600; }
.ucase__body a svg { width: 9px; height: 6px; transition: transform 0.2s; }
.ucase__body a:hover svg { transform: rotate(-90deg) translateY(3px) !important; }
.carousel__nav { display: flex; gap: 10px; justify-content: flex-end; padding: 18px var(--uc-pad) 0; }
.carousel__btn {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--pill);
  display: grid;
  place-items: center;
  transition: background-color 0.2s, transform 0.2s;
}
.carousel__btn:hover { background: #e6e7eb; transform: scale(1.05); }
.carousel__btn svg { width: 11px; height: 7px; }
.carousel__btn:disabled { opacity: 0.35; cursor: default; }

/* ---------- CTA columns ---------- */
.cta { position: relative; padding: var(--section-y) var(--gutter); overflow: hidden; }
.cta__canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.cta__cols {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(40px, 6vw, 100px);
  max-width: 1280px;
  margin: 0 auto;
}
.cta__col { text-align: center; padding: clamp(30px, 6vh, 80px) 20px; }
.cta__eyebrow { display: block; font-size: 12.5px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--brand); margin-bottom: 14px; }
.cta__title {
  color: var(--heading);
  font-family: var(--display);
  font-size: clamp(26px, 2.9vw, 44px);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin-bottom: 26px;
}
.cta__title span { font-weight: 500; color: #3a3d44; }
@media (max-width: 800px) { .cta__cols { grid-template-columns: 1fr; } }

/* ---------- Blog ---------- */
/* max-width includes the gutters so inner content is a true 1440 column,
   aligned with .features / .sitefooter (previously double-inset by 1 gutter). */
.blog { max-width: calc(var(--content-max) + 2 * var(--gutter)); margin: 0 auto; padding: 0 var(--gutter) var(--section-y); }
.blog__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 40px; }
.blog__head h2 { color: var(--heading); font-family: var(--display); font-size: clamp(30px, 3.2vw, 46px); font-weight: 600; letter-spacing: -0.02em; }
.blog__grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(18px, 2.2vw, 34px); }
@media (max-width: 1080px) { .blog__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .blog__grid { grid-template-columns: 1fr; } }
.post h3 { font-family: var(--display); font-size: clamp(19px, 1.6vw, 24px); font-weight: 600; line-height: 1.2; letter-spacing: -0.015em; margin: 18px 0 10px; }
.post__meta { display: flex; gap: 16px; font-size: 13px; color: var(--muted); margin-bottom: 8px; }
.post > a { display: inline-flex; align-items: center; gap: 7px; font-size: 13.5px; font-weight: 600; }
.post > a svg { width: 9px; height: 6px; }
.post__art {
  position: relative;
  aspect-ratio: 1 / 0.94;
  border-radius: 18px;
  background: #0a0a0c;
  overflow: hidden;
  display: grid;
  place-items: center;
}
.post__wordmark {
  position: absolute;
  bottom: 20px;
  left: 0;
  right: 0;
  text-align: center;
  color: #fff;
  font-family: var(--display);
  font-weight: 600;
  font-size: 17px;
}
.post__wordmark b { font-size: 11px; vertical-align: super; background: #2b2d33; border-radius: 3px; padding: 1px 4px; }

/* pixel "a" tile */
.pixelA {
  width: 56%;
  aspect-ratio: 1;
  background:
    conic-gradient(from 40deg, var(--coral), var(--amber), var(--teal), var(--azure), var(--violet), var(--coral));
  -webkit-mask:
    radial-gradient(circle at 50% 42%, #000 26%, transparent 27%),
    radial-gradient(circle at 50% 42%, transparent 12%, #000 13%, #000 26%, transparent 27%),
    linear-gradient(#000 0 0) 78% 60% / 14% 52% no-repeat;
  -webkit-mask-composite: source-over;
  mask-composite: add;
  image-rendering: pixelated;
  filter: contrast(1.1);
  animation: hueSpin 9s linear infinite;
}
@keyframes hueSpin { to { filter: contrast(1.1) hue-rotate(360deg); } }

/* pixel peak tile */
.pixelPeak {
  width: 52%;
  aspect-ratio: 1.15;
  background: conic-gradient(from 210deg at 50% 30%, var(--azure), var(--teal), var(--amber), var(--coral), var(--violet), var(--azure));
  clip-path: polygon(
    50% 0%, 58% 12%, 66% 24%, 58% 24%, 66% 36%, 74% 48%, 66% 48%, 76% 62%, 86% 78%, 62% 78%, 62% 100%,
    38% 100%, 38% 78%, 14% 78%, 24% 62%, 34% 48%, 26% 48%, 34% 36%, 42% 24%, 34% 24%, 42% 12%
  );
  image-rendering: pixelated;
}
.post__art--cli::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(120, 150, 255, 0.5) 1px, transparent 1.4px);
  background-size: 26px 26px;
  mask-image: radial-gradient(70% 70% at 50% 50%, transparent 30%, #000 75%);
}

/* mini UI tile */
.miniui { width: 74%; color: #c9ccd2; font-size: 10.5px; align-self: start; margin-top: 14%; }
.miniui__row { display: flex; align-items: center; gap: 6px; font-weight: 600; margin-bottom: 10px; }
.miniui__row svg { width: 11px; height: 11px; }
.miniui__ghost { background: #1b1c20; border-radius: 7px; padding: 7px 9px; color: #6a6e76; margin-bottom: 7px; }
.miniui__ghost--short { width: 62%; }
.miniui__ghost--tiny { width: 40%; }

/* mini terminal tile */
.miniterm { width: 72%; align-self: start; margin-top: 16%; font-family: var(--mono); font-size: 10.5px; }
.miniterm__cmd { background: #202127; color: #e6e8ee; border-radius: 6px; padding: 7px 9px; margin-bottom: 7px; width: fit-content; }
.miniterm__opt { display: flex; justify-content: space-between; gap: 10px; background: #17181d; color: #7a7f88; border-radius: 6px; padding: 6px 9px; margin-bottom: 6px; }
.miniterm__opt em { font-style: normal; color: #4c4f57; }

/* ---------- Footer panel ---------- */
.footerpanel { padding: 0 var(--gutter) clamp(28px, 4vh, 48px); }
.footerpanel__panel {
  position: relative;
  max-width: 1600px;
  margin: 0 auto;
  background: var(--panel);
  border-radius: var(--radius-panel);
  overflow: hidden;
}
.footerpanel__canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.footerpanel__content {
  position: relative;
  text-align: center;
  color: #fff;
  padding: clamp(80px, 12vh, 150px) var(--gutter) clamp(70px, 10vh, 130px);
}
.footerpanel__content h2 {
  font-family: var(--display);
  font-size: clamp(34px, 4.8vw, 74px);
  font-weight: 600;
  letter-spacing: -0.018em;
  margin-bottom: 18px;
}
.footerpanel__content > p { color: #9599a1; font-size: 16px; margin-bottom: 34px; }
.footerpanel__actions { margin-bottom: clamp(20px, 4vh, 40px); }
/* ---------- Site footer (separate, light) ---------- */
.sitefooter {
  background: var(--paper);
  border-top: 1px solid var(--line);
  padding: clamp(40px, 6vh, 64px) var(--gutter) 28px;
  margin-top: clamp(28px, 4vh, 48px);
}
.sitefooter__inner { max-width: 1440px; margin: 0 auto; }
.sitefooter__top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: clamp(30px, 6vw, 100px);
  flex-wrap: wrap;
  margin-bottom: clamp(36px, 5vh, 56px);
}
.sitefooter__links { display: flex; gap: clamp(40px, 7vw, 120px); text-align: left; }
.sitefooter__links div { display: flex; flex-direction: column; gap: 10px; }
.sitefooter__links span { font-size: 12.5px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); margin-bottom: 6px; }
.sitefooter__links a { font-size: 14.5px; color: var(--ink); transition: color 0.2s; }
.sitefooter__links a:hover { color: var(--brand); }
.sitefooter__base {
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-top: 1px solid var(--line);
  padding-top: 22px;
  color: var(--muted);
  font-size: 13px;
}
.sitefooter__legal a { color: inherit; transition: color 0.2s; }
.sitefooter__legal a:hover { color: var(--brand); }

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .card--aura::before, .ring, .pixelA { animation: none; }
  .statement__text .ch { opacity: 1; }
}


/* ---------- Nav controls (theme + language) ---------- */
.nav__ctls { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.nav__cta { margin-left: 0; }
.navctl {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--pill);
  color: var(--ink);
  transition: background-color 0.2s, transform 0.2s;
}
.navctl:hover { background: #e6e7eb; transform: scale(1.06); }
.navctl svg { width: 17px; height: 17px; }
/* Language switch: shows the flag of the language you'd switch to. Greyscale
   at rest so it stays quiet in the bar; full colour on hover/focus. */
.navctl--lang { padding: 0; overflow: hidden; }
.navctl--lang .flag {
  width: 22px; height: 22px;
  border-radius: 4px;
  filter: grayscale(1);
  opacity: 0.65;
  transition: filter 0.22s, opacity 0.22s, transform 0.22s;
}
.navctl--lang:hover .flag,
.navctl--lang:focus-visible .flag { filter: grayscale(0); opacity: 1; transform: scale(1.08); }
.navctl--lang .flag { display: none; }
.navctl--lang[data-next="en"] .flag--en { display: block; }
.navctl--lang[data-next="ka"] .flag--ka { display: block; }

/* ---------- Account avatar (also carries the cart count) ---------- */
.avatar {
  position: relative;
  display: grid; place-items: center;
  width: 44px; height: 44px;
  border-radius: 50%;
  transition: transform 0.2s, background-color 0.2s, box-shadow 0.2s;
}
.avatar[hidden] { display: none; }   /* beats the display:grid above */
.avatar:hover { transform: scale(1.06); }
.avatar__glyph {
  display: grid; place-items: center;
  width: 100%; height: 100%;
  border-radius: 50%;
  font-size: 15px; font-weight: 700; letter-spacing: 0.02em;
}
/* Signed in — solid brand disc with the first-name initial. */
.avatar--user .avatar__glyph {
  background: var(--brand);
  color: #fff;
  border: 0;
}
.avatar--user:hover { box-shadow: 0 8px 20px -8px rgba(14, 143, 200, 0.6); }
.avatar__badge {
  position: absolute; top: -2px; right: -2px;
  min-width: 18px; height: 18px; padding: 0 5px;
  display: grid; place-items: center;
  background: var(--brand-dark); color: #fff;
  font-size: 11px; font-weight: 700; line-height: 1;
  border-radius: 999px; border: 2px solid var(--paper);
}
:root[data-theme="dark"] .avatar__badge { background: var(--brand); border-color: var(--paper); }
.icon-sun { display: none; }
:root[data-theme="dark"] .icon-sun { display: block; }
:root[data-theme="dark"] .icon-moon { display: none; }

/* ---------- Mobile menu (hamburger) ---------- */
.navctl--menu { display: none; }
.navctl--menu .icon-close { display: none; }
.navctl--menu[aria-expanded="true"] .icon-menu { display: none; }
.navctl--menu[aria-expanded="true"] .icon-close { display: block; }
@media (max-width: 1024px) {
  .navctl--menu { display: grid; }
}
.mobilemenu {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 99;
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
  padding: 8px var(--gutter) calc(22px + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 20px 34px -22px rgba(23, 24, 28, 0.3);
  transform: translateY(-6px);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: transform 0.22s ease, opacity 0.18s ease, visibility 0.22s;
  /* js/main.js sets max-height to the space under the fixed nav bar and
     locks body scroll — this is what makes a touch drag over a long
     expanded section (e.g. Solutions) scroll the menu instead of the page
     behind it. */
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.mobilemenu.is-open { transform: translateY(0); opacity: 1; visibility: visible; pointer-events: auto; }
.mobilemenu__links { display: flex; flex-direction: column; }
.mobilemenu__links a {
  padding: 14px 4px;
  font-size: 16px;
  font-weight: 500;
  color: var(--ink);
  border-bottom: 1px solid var(--line);
}
.mobilemenu__cta { margin-top: 16px; justify-content: center; }

/* Solutions/Academy/Services rows: the section link stays a plain link, the
   chevron button next to it expands the CMS pages underneath instead of
   listing them all inline all the time. */
.mobilemenu__item { display: flex; align-items: stretch; border-bottom: 1px solid var(--line); }
.mobilemenu__item a { flex: 1; border-bottom: none; }
.mobilemenu__expand {
  display: grid;
  place-items: center;
  width: 44px;
  flex: none;
  background: none;
  border: none;
  color: var(--ink);
  cursor: pointer;
}
/* [hidden] and .mobilemenu__expand carry equal specificity, so without this
   the class's display:grid above wins the cascade tie and shows the button
   even while js/cms-nav.js has left it hidden — the icon appeared for every
   section regardless of whether it actually has any pages under it. */
.mobilemenu__expand[hidden] { display: none; }
.mobilemenu__expand svg { width: 11px; height: 7px; transition: transform 0.2s ease; }
.mobilemenu__expand[aria-expanded="true"] svg { transform: rotate(180deg); }

/* Collapsed via grid-template-rows so the open/close height animates without
   any JS measuring the content. */
.mobilemenu__sub { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.25s ease; }
.mobilemenu__sub > div { overflow: hidden; min-height: 0; display: flex; flex-direction: column; }
.mobilemenu__sub.is-open { grid-template-rows: 1fr; }
.mobilemenu__sub a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 4px 10px 12px;
  font-size: 14px;
  font-weight: 500;
  opacity: 0.82;
  color: var(--ink);
  border-bottom: 1px solid var(--line);
}
.mobilemenu__sub a:last-child { border-bottom: none; }
@media (min-width: 1025px) { .mobilemenu { display: none; } }

/* ---------- Dark theme ---------- */
:root[data-theme="dark"] {
  --paper: #0b1118;
  --ink: #e9eef3;
  --muted: #9db0be;
  --line: #1e2c38;
  --pill: #152230;
  --panel: #04070b;
  --heading: #cfe7f5;
}
:root[data-theme="dark"] .nav.is-scrolled {
  background: rgba(11, 17, 24, 0.85);
}
:root[data-theme="dark"] .btn--dark { background: var(--brand); }
:root[data-theme="dark"] .btn--dark:hover { background: #0d7cb0; box-shadow: 0 10px 24px -10px rgba(14, 143, 200, 0.5); }
:root[data-theme="dark"] .btn--ghost:hover { background: #1c2d3d; }
:root[data-theme="dark"] .navctl:hover { background: #1c2d3d; }
:root[data-theme="dark"] .chip__disc { background: #131f2b; }
:root[data-theme="dark"] .chip img { filter: grayscale(1) brightness(1.6); }
:root[data-theme="dark"] .chip:hover img { filter: none; }
:root[data-theme="dark"] .carousel__btn { background: #152230; }
:root[data-theme="dark"] .carousel__btn:hover { background: #1c2d3d; }
:root[data-theme="dark"] ::selection { background: rgba(14, 143, 200, 0.35); }
:root[data-theme="dark"] .ucase__media::after {
  background:
    radial-gradient(90% 130% at 78% 115%, rgba(0, 0, 0, 0.55), transparent 55%),
    radial-gradient(60% 80% at 50% -10%, rgba(255, 255, 255, 0.18), transparent 60%);
}

/* ============================================================
   SUBPAGES — shared building blocks (Solutions, Academy,
   Pricing, Blog, About). Reuse the home design language.
   ============================================================ */

/* Active nav link */
.nav__links a[aria-current="page"] { background: var(--pill); }

/* ---------- Page hero (shorter than the home hero) ---------- */
.pagehero {
  position: relative;
  min-height: clamp(460px, 68vh, 720px);
  display: grid;
  place-items: center;
  overflow: hidden;
  text-align: center;
}
.pagehero__canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.pagehero__content {
  position: relative;
  max-width: 900px;
  padding: 140px var(--gutter) 70px;
}
.pagehero__title {
  font-family: var(--display);
  font-size: clamp(32px, 4.4vw, 64px);
  font-weight: 600;
  line-height: 1.04;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.pagehero__sub {
  margin: 22px auto 0;
  max-width: 60ch;
  font-size: clamp(16px, 1.3vw, 19px);
  line-height: 1.6;
  color: var(--muted);
}
.pagehero__actions { display: flex; justify-content: center; gap: 12px; margin-top: 34px; flex-wrap: wrap; }

/* ---------- Generic section wrapper ---------- */
.section {
  max-width: calc(var(--content-max) + 2 * var(--gutter));
  margin: 0 auto;
  padding: var(--section-y) var(--gutter);
}
.section--tight { padding-block: var(--section-y-sm); }
/* A section-head already carries its own bottom margin — don't stack the
   next section's top padding on top of it and open a hole. */
.section-head + .section { padding-top: 0; }

/* ---------- Card grid (capabilities, values, steps) ---------- */
.cardgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: clamp(16px, 2vw, 26px); --cardgrid-gap: clamp(16px, 2vw, 26px); }
/* Company products / Companies (js/cms-render.js): a CSS grid's row tracks
   are fixed for the whole grid, so a last row with fewer cards than columns
   just leaves empty cells at the end — the cards themselves stay left-packed
   rather than centering in the space they actually have. Grid has no way to
   center a ragged row on its own; flex does, since each row is independent.
   flex-grow: 0 keeps cards a fixed width (matching the grid's 250px floor, or
   the exact width `columns` computes) instead of stretching to fill a short
   row, which is what centering the leftovers actually requires. */
/* align-items: flex-start replaces flex's default stretch — without it every
   card in a row is stretched to match its tallest sibling (a two-line title
   forcing height onto a one-line neighbour), which fights the square shape
   below: each card now sizes to its own aspect-ratio instead. */
.cardgrid--center { display: flex; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
/* min-width: 0 overrides the flex item's default min-width: auto, which
   otherwise floors the box at its content's max-content size — with title
   wrapping off (white-space: nowrap on .tile h3), a long unbroken label like
   "Power Point" is wider than 150px and would grow that one card (and, via
   aspect-ratio, its height) past its neighbours', reintroducing the same
   icon-row stagger nowrap was meant to fix. Every card now stays exactly
   150px regardless of its label; an unusually wide one just overflows past
   its own edges instead of resizing the box. */
.cardgrid--center > * { flex: 0 1 150px; min-width: 0; }
/* Company products / Companies / Child pages tiles: a small square card with
   the icon and text centered, rather than the taller left-aligned block
   .tile is everywhere else — scoped to .cardgrid--center, the flex layout
   unique to these three auto-populated grids (see the comment above it), so
   nothing else that reuses .tile (capabilities, values, steps) is affected.
   Icon and type scale down with the card (36px icon, smaller heading/line)
   rather than just shrinking the box around unchanged content, which would
   have left everything cramped against the edges instead of reading as a
   genuinely smaller card. */
/* justify-content: flex-start, not center — centering the whole
   icon+title(+caption) block as a unit was what originally misaligned the
   icon row: a 1-line title made a shorter block than a 2-line neighbour's,
   so centering landed their icons at different heights. Top-aligning
   fixes that on its own (the icon's fixed size is then all that
   determines its position), but flush-top reads wrong for a row whose
   tallest title is still just one line, or one where a two-line title
   should get to sit centered rather than pinned up top.
   js/cms-render.js's alignCardGridRows() resolves both: it measures the
   tallest icon+title+caption block actually present in each row (flex-
   wrap's row, not the grid as a whole) and sets --tile-top-offset on every
   tile sharing it to whatever margin centers *that* block in the square.
   A row where every title is one line gets a full centering offset, same
   as this used to look before top-alignment; a row with a two-line title
   gets a smaller offset sized to its own tallest block, so every tile's
   icon still lines up (same offset applied to all) while the block reads
   as centered rather than stuck to the top edge. --tile-top-offset
   defaults to 0 (flush top) for a row that hasn't been measured yet.
   overflow: hidden is the backstop for the line-clamp below — without it,
   an extreme title could still clip past the box's own rounded corners
   instead of stopping cleanly at the clamp's ellipsis. */
.cardgrid--center .tile {
  aspect-ratio: 1 / 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  text-align: center;
  padding: clamp(12px, 1.4vw, 18px);
  overflow: hidden;
}
.cardgrid--center .tile__ic { width: 36px; height: 36px; margin: var(--tile-top-offset, 0px) auto 10px; flex-shrink: 0; }
.cardgrid--center .tile__ic svg { width: 18px; height: 18px; }
.cardgrid--center .tile__ic img { width: 18px; height: 18px; }
/* line-clamp: 2 rather than nowrap — a long, unbroken name (e.g. "Google
   Workspace Admin Console") used to overflow past the card's own edges
   instead of resizing the box (nowrap left it nowhere else to go). Wrapping
   up to two lines, then ellipsis past that, keeps every card's box the
   same fixed size (the aspect-ratio above, tied to width alone) while
   letting all but the longest outlier names show in full. No min-height
   here (an earlier pass added one to fix icon alignment) — the icon's
   alignment is the top-aligned flex column's job now (see .tile's own
   comment), so the title is free to size to its actual 1 or 2 lines and
   let the caption below sit right against it. */
.cardgrid--center .tile h3 {
  font-size: clamp(13px, 1vw, 15px);
  line-height: 1.25;
  margin-bottom: 4px;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: normal;
  /* Room above the first line for the caps to sit in, taken straight back out
     with the negative margin so nothing below moves: the padding only pushes
     the clip edge up, it doesn't push the text down.

     Without it the tops of the letters were being shaved off. Eurostile GEO
     Mt's own line box is 1.35em tall (0.95 ascent + 0.40 descent — the descent
     is Georgian-sized, and every Latin cap is paid for by it), which is taller
     than the 1.25 line-height above, so the half-leading is *negative* and the
     baseline lands 0.90em under the box's top edge. The face's caps are
     0.89em, which leaves 0.01em of headroom — under a tenth of a pixel at
     these sizes, so once Chrome rounds the clip rectangle to a whole pixel the
     top row of every capital goes with it. This is the only clamped heading in
     --display on the site, and the only one that clips: everywhere else the
     ink is free to overhang the line box, which is why nothing but these three
     grids shows it. */
  padding-top: 0.14em;
  margin-top: -0.14em;
}
.cardgrid--center .tile p { font-size: 12px; }

/* ---------- Feature tabs ---------- */
/* Back to .feature's own minmax(280px,420px)/1fr, not the 1.2fr/1fr this
   briefly became: giving the text column a *proportional* share (1.2fr)
   rather than a *content-fitting* cap (420px) sized it far past what a
   short title/one-line description ever needs — .ftabs__tab's flex
   align-items:stretch default then stretched .ftabs__title/.ftabs__body to
   that same width regardless, leaving several hundred pixels of invisible
   padding between the visible text and the column's real edge. Verified on
   the live page: at a 1440px section the title span measured 716px wide
   while the visible words "The first thing" needed about 120 — that gap,
   not the real 90px column gap below, was what read as empty space. A
   content-fitting cap removes it. */
/* align-items: start on the grid itself, with both columns then re-centered
   via their own align-self below (.ftabs__tabs and .ftabs__panels) rather
   than centering here — same reasoning as .ftabs__panels' comment: the
   active item's picture is the only one ever in the layout (.ftabs__panel
   is display:none/block, one at a time) and different items' images can
   differ in height, so the row's own height changes depending on which tab
   is active. Two independent align-self:center rules re-center *both*
   columns on that same row height, so the pair always shares a middle line
   without either being hard-pinned to the top.

   The picture column is capped at 620px (matching .cmsfig's own max-width
   below — a track wider than the thing inside it just wastes space) rather
   than 1fr, and justify-content:center pulls the whole list+picture pair
   into the middle of the section instead of anchoring it to the left edge
   and leaving the leftover width stranded past the picture. A capped track
   with no centering was tried first and rejected: it left-packs, so the
   picture sits flush after the list with a lopsided gulf of empty space to
   its right on anything wider than ~1130px — center is what makes the pair
   read as one deliberately-placed block regardless of section width. */
.ftabs { display: grid; grid-template-columns: minmax(280px, 420px) minmax(0, 620px); gap: clamp(40px, 6vw, 90px); align-items: start; justify-content: center; }
.ftabs__tabs { display: flex; flex-direction: column; align-self: center; }
.ftabs__tab {
  all: unset;
  position: relative;
  cursor: pointer;
  text-align: left;
  padding: 16px 0 16px 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
/* The static line every item shows, and the blue fill that draws over it
   while an item is active — two layers rather than one animating color, so
   the fill's height can run from 0 to 100% without also having to fade a
   border-color at the same time. */
.ftabs__track { position: absolute; left: 0; top: 0; bottom: 0; width: 2px; background: var(--line); }
.ftabs__fill { display: block; width: 100%; height: 0; background: var(--brand); transform-origin: top; }
/* Runs only while mountFeatureTabs (js/cms-render.js) has confirmed there's
   an actual timer to represent — .is-rotating is never added at all when
   there's one item (nothing to advance to) or prefers-reduced-motion is on
   (no autoplay to preview). --ftabs-interval is set inline per block from
   the same `interval` prop the JS timer itself reads, so the fill always
   finishes exactly when the timer advances. */
.ftabs.is-rotating .ftabs__tab.is-active .ftabs__fill { animation: ftabsFill var(--ftabs-interval, 5s) linear forwards; }
.ftabs.is-paused .ftabs__fill { animation-play-state: paused; }
@keyframes ftabsFill { from { height: 0; } to { height: 100%; } }
@media (prefers-reduced-motion: reduce) { .ftabs__fill { animation: none !important; } }
.ftabs__title { font-family: var(--display); font-size: clamp(17px, 1.2vw, 19px); font-weight: 600; color: var(--muted); transition: color 0.2s; }
.ftabs__body { font-size: 15px; line-height: 1.6; color: var(--muted); max-width: 42ch; display: none; }
.ftabs__tab.is-active .ftabs__title { color: var(--heading); }
.ftabs__tab.is-active .ftabs__body { display: block; }
/* Same markup shape featureShowcase's own picture uses (mediaFigure() in
   js/cms-render.js: a bare <figure class="cmsfig"> around the <img>, no
   wrapping box of this block's own) so it gets the exact same CSS
   (css/cms.css: .cmsfig { margin:0 }, .cmsfig img { width:100%; height:auto
   } — no background, no forced crop). featureShowcase only ever shows one
   image so that was free there; here .ftabs__panel is display:none/block
   (only the active one is ever in the layout, so nothing holds the column
   open to a size that isn't the current image's) rather than the two both
   showing at once, so switching is a swap rather than a fade. min-width:0 is
   the same fix .feature__media needs for the same reason: a grid item's
   default min-width is auto, which can force the column wider than its
   track to avoid shrinking an image below its intrinsic width. */
/* align-self: center (rather than align-items:center on .ftabs itself —
   see the comment there) centers the picture on the row's height, matching
   .ftabs__tabs' own align-self:center above so the list and picture share a
   middle line regardless of which item's image is currently active.
   Horizontal placement is the grid's job now (grid-template-columns/
   justify-content on .ftabs, same comment); this is vertical only. */
.ftabs__panels { min-width: 0; align-self: center; }
.ftabs__panel { display: none; }
/* The cap+center lives on .cmsfig itself, not on .ftabs__panels (the grid
   item) — max-width/margin-inline:auto on a grid item flips its sizing to
   grid's own shrink-to-fit-content algorithm (auto margins there mean
   "align start, size to content" per the Box Alignment spec), so before the
   image finishes loading — no intrinsic size yet to shrink-wrap around — the
   whole column collapsed to 0 width instead of reserving space. A plain
   block like .cmsfig doesn't have that grid-item sizing rule: width:auto
   fills the available space up to max-width regardless of content, exactly
   like every ordinary max-width+margin:auto centered container, so the
   column still reserves full-width room immediately and the image only
   crops down to size once it actually has one. Scoped to .ftabs__panels
   .cmsfig rather than the bare .cmsfig class cms.css already styles, so
   featureShowcase/companyHero's own picture (never oversized the way a tall
   ftabs screenshot can be) is untouched. */
/* Fixed aspect-ratio + object-fit:cover (not the earlier-rejected
   aspect-ratio/contain — see spec doc §3a round two) so the panel's box
   height never depends on whichever item's image happens to be active:
   height:auto here previously let a tall/short/wide source image resize
   this row and shove every section below it up or down as tabs switched. */
.ftabs__panels .cmsfig { max-width: 620px; margin-inline: auto; aspect-ratio: 16 / 10; overflow: hidden; }
.ftabs__panels .cmsfig img, .ftabs__panels .cmsfig video { width: 100%; height: 100%; object-fit: cover; }
.ftabs__panel.is-active { display: block; animation: ftabsFadeIn 0.3s ease; }
@keyframes ftabsFadeIn { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .ftabs__panel.is-active { animation: none; } }
@media (max-width: 900px) {
  .ftabs { grid-template-columns: 1fr; }
  .ftabs__body { display: block; }
}

/* Company products / Companies / Child pages: centered by default, to match
   the square, centered tiles above — a left-aligned heading over centered
   cards read as mismatched. The exact same fix .cmsb--pricing already needed
   (below): text-align alone only centers *inline* content, so it does
   nothing for .section-head__title / .section-head__lead, which are
   block-level and capped by their own max-width (18ch / 54ch) — without
   margin-inline the box itself still sits flush left. This is the block's own
   default rather than an entry in schema/blocks.ts's `style.align`,
   specifically so it reaches every one of these already published — a schema
   default only applies the moment a new block is inserted, and there is no
   way to backfill `style.align` onto a page saved before this existed.
   !important for the same reason pricing's does: the individual-element
   inspector writes text-align as an inline style, which beats any external
   rule regardless of specificity otherwise. */
.cmsb--companyProducts .section-head,
.cmsb--companies .section-head,
.cmsb--childPages .section-head {
  text-align: center !important;
}
.cmsb--companyProducts .section-head .eyebrow,
.cmsb--companies .section-head .eyebrow,
.cmsb--childPages .section-head .eyebrow {
  justify-content: center !important;
}
.cmsb--companyProducts .section-head__title,
.cmsb--companyProducts .section-head__lead,
.cmsb--companies .section-head__title,
.cmsb--companies .section-head__lead,
.cmsb--childPages .section-head__title,
.cmsb--childPages .section-head__lead {
  margin-inline: auto !important;
}

.tile {
  border: 1px solid var(--line);
  border-radius: 22px;
  padding: clamp(24px, 3vw, 36px);
  background: var(--paper);
  transition: transform 0.3s cubic-bezier(0.3, 0.7, 0, 1), box-shadow 0.3s, border-color 0.3s;
}
.tile:hover {
  transform: translateY(-4px);
  /* --pill over --paper is the same step the App row's cards take on hover
     (css/cms.css, .approw__item:hover) — the one custom property that reads
     as a highlight in both themes rather than the near-invisible shift
     --paper itself gives in dark mode, where it already sits close to the
     page colour. The hairline keeps the card's edge readable once its own
     border goes transparent below. */
  background: var(--pill);
  box-shadow: 0 22px 48px -30px rgba(23, 24, 28, 0.4), inset 0 0 0 1px var(--line);
  border-color: transparent;
}
.tile__ic {
  width: 46px; height: 46px;
  display: grid; place-items: center;
  border-radius: 13px;
  background: var(--pill);
  color: var(--brand);
  margin-bottom: 20px;
}
.tile__ic svg { width: 24px; height: 24px; }
.tile__ic img { width: 24px; height: 24px; object-fit: contain; }
.tile__num {
  font-family: var(--display);
  font-size: 15px; font-weight: 600;
  color: var(--brand);
  margin-bottom: 14px;
}
.tile h3 { font-family: var(--display); font-size: clamp(19px, 1.5vw, 23px); font-weight: 600; letter-spacing: -0.015em; color: var(--heading); margin-bottom: 10px; }
.tile p { font-size: 15px; line-height: 1.62; color: var(--muted); }

/* ---------- Stats row (About) ---------- */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: clamp(20px, 3vw, 48px); }
.stat__num { font-family: var(--display); font-size: clamp(38px, 4.4vw, 66px); font-weight: 600; letter-spacing: -0.03em; color: var(--heading); line-height: 1; }
.stat__label { margin-top: 10px; font-size: 14.5px; color: var(--muted); }

/* ---------- Pricing ---------- */
/* Centered unconditionally, not just by default: a left-aligned heading over
   a centered Monthly/Annual switch and a full-width three-column grid reads
   as a layout mistake, not a legitimate editorial choice, so this doesn't
   defer to alignment settings the way most section headings do (new pricing
   blocks default their block-level Text alignment to Center anyway — see the
   "pricing" entry in schema/blocks.ts — this is what carries the same look to
   a block created before that default existed, or one where the *heading
   element itself* was individually set to a side). The individual-element
   inspector writes text-align as an inline style (partStyle() in
   cms-render.js), which beats any external rule regardless of specificity —
   !important is the only way an external stylesheet ever wins that fight. */
.cmsb--pricing .section-head { text-align: center !important; }
.cmsb--pricing .section-head .eyebrow { justify-content: center !important; }
/* text-align centers *inline* content — it does nothing for .section-head__title
   and .section-head__lead, which are block-level and capped by their own
   max-width (18ch / 54ch), so without margin-inline the box itself just sits
   flush left regardless of what text-align says. The two rules above were a
   real fix for .eyebrow (inline-flex, positioned by the parent's text-align)
   and a no-op for the title and lead — this is the part that was missing. */
.cmsb--pricing .section-head__title,
.cmsb--pricing .section-head__lead {
  margin-inline: auto !important;
}
/* Feature tabs: same centered-heading treatment as pricing above, and the
   same two-part fix — text-align for .eyebrow, margin-inline for
   .section-head__title/__lead, since text-align alone does nothing for
   block-level content capped by its own max-width. The row underneath stays
   left-aligned regardless (list + picture, not text), which is what the
   reference this was matched against does too. */
.cmsb--featureTabs .section-head { text-align: center !important; }
.cmsb--featureTabs .section-head .eyebrow { justify-content: center !important; }
.cmsb--featureTabs .section-head__title,
.cmsb--featureTabs .section-head__lead {
  margin-inline: auto !important;
}
/* Flexbox, not CSS Grid: a product's plan count varies (1, 2, 3, 4+), and a
   fixed repeat(3, 1fr) either stretched a lone card to a third of the whole
   section's width or left an empty column where a second one was missing.
   grid's own repeat(auto-fit, minmax(...)) looked like the fix, but its
   fit-counting algorithm decides how many tracks *could* exist before ever
   growing them toward their max — verified live: three cards each capped at
   380px wrapped to two rows in a 1080px-wide section, even though three at
   ~344px would have fit on one line easily. Flexbox decides wrapping from
   each card's flex-basis (300px) instead, so three cards (900px + gaps) fit
   and then grow together toward the 380px cap; only a plan count that
   wouldn't fit even at the *minimum* width wraps. justify-content: center is
   what centers the row (or the last, partial row) when the cards don't fill
   it — align-items: stretch (flexbox's own default, stated explicitly) is
   what keeps every card in a row the same height regardless of which one has
   the most features, the tallest sets the row and the CTA's margin-top:auto
   still pins every button to the same baseline. */
.price-grid { --price-gap: clamp(18px, 2vw, 28px); display: flex; flex-wrap: wrap; justify-content: center; gap: var(--price-gap); align-items: stretch; }
/* max-width: 380px on .price-card applies regardless of flex-basis, so
   flex-basis: 100% alone still left two cards fitting side by side at their
   380px cap on a narrow viewport — clearing that cap too is what actually
   lets a card fill the (now-narrowed) grid instead of just being allowed to. */
@media (max-width: 900px) {
  .price-grid { max-width: 460px; margin-inline: auto; }
  .price-card { flex-basis: 100% !important; max-width: none !important; }
}
.price-card {
  position: relative;
  flex: 1 1 300px;
  max-width: 380px;
  border: 1px solid var(--line);
  border-radius: 24px;
  padding: clamp(26px, 3vw, 38px);
  background: var(--paper);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.price-card--featured {
  border-color: transparent;
  box-shadow: 0 30px 60px -34px rgba(11, 56, 79, 0.55);
  outline: 2px solid var(--brand);
}
.price-card__badge {
  position: absolute; top: -13px; left: 50%; transform: translateX(-50%);
  background: var(--brand); color: #fff;
  font-size: 11.5px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 5px 14px; border-radius: 999px;
}
.price-card__name { font-family: var(--display); font-size: 20px; font-weight: 600; color: var(--heading); }
/* The amount is the one number a visitor scans for; its caption is metadata,
   not a peer — hence the two-step scale (32-42px vs 13px) and the caption
   dropping to its own line below rather than crowding the same baseline. */
.price-card__price { margin-top: 6px; }
.price-card__amount { font-family: var(--display); font-size: clamp(32px, 3.2vw, 42px); font-weight: 600; letter-spacing: -0.03em; color: var(--heading); line-height: 1.05; }
.price-card__period { display: block; margin-top: 3px; font-family: var(--body); font-size: 13px; font-weight: 500; color: var(--muted); letter-spacing: 0; }
.price-card__desc { font-size: 14.5px; line-height: 1.55; color: var(--muted); margin-bottom: 8px; }
.price-card .btn { justify-content: center; margin: 14px 0 6px; }
.price-card__list { display: flex; flex-direction: column; gap: 11px; margin-top: 6px; }
.price-card__list li { display: flex; align-items: flex-start; gap: 10px; font-size: 14.5px; line-height: 1.45; color: var(--ink); list-style: none; }
.price-card__list svg { width: 17px; height: 17px; flex: none; color: var(--brand); margin-top: 1px; }
/* Optional row of small logos at the foot of a card — the apps or services a
   plan includes, say. Full colour and full opacity throughout, unlike the
   logo-rail block's dimmed "as seen in" treatment: these are content, read
   at a glance, not a trust signal meant to fade until hovered.
   min-height holds the strip's height even when this particular card has no
   logos of its own — cms-render.js still renders the (empty) div once a
   sibling card has some, so every button in the row keeps the same amount of
   room below it and lands on the same line either way. */
.price-card__logos { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 16px; min-height: 26px; }
.price-card__logo { display: inline-flex; }
.price-card__logo img { width: 26px; height: 26px; object-fit: contain; }
/* A feature list past the fold collapses into <details> rather than a script
   toggling a class — same CSP reasoning as the Monthly/Annual switch below,
   and native <details> is already how FAQ answers do this on this site. */
.price-card__more { display: block; }
.price-card__more summary {
  display: flex; align-items: center; gap: 6px;
  font-size: 13.5px; font-weight: 600; color: var(--brand);
  cursor: pointer; list-style: none; padding: 2px 0; margin-top: 2px;
  min-height: 32px;
}
.price-card__more summary::-webkit-details-marker { display: none; }
.price-card__more summary::after {
  content: ""; width: 7px; height: 7px; flex: none;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg); transition: transform 0.15s ease;
}
.price-card__more[open] summary::after { transform: rotate(-135deg); }
.price-card__more-list { display: flex; flex-direction: column; gap: 11px; margin: 8px 0 0; padding: 0; }
.price-card__more-list li { display: flex; align-items: flex-start; gap: 10px; font-size: 14.5px; line-height: 1.45; color: var(--ink); list-style: none; }
.price-card__more-list svg { width: 17px; height: 17px; flex: none; color: var(--brand); margin-top: 1px; }

/* Monthly/Annual switch — a radio pair, not a script: the CSP allows no
   inline script and cannot allowlist one generated per page, per block (see
   docs/CMS.md §9), so a later sibling combinator does the showing and hiding
   instead of a click handler. */
/* A control bar above the grid reads as centered no matter how the section's
   own heading is aligned — display: flex + width: fit-content is what lets
   margin-inline auto center it; inline-flex ignores auto margins entirely. */
.price-toggle { display: flex; width: fit-content; align-items: center; gap: 2px; padding: 4px; margin: 0 auto 28px; background: var(--pill); border-radius: 999px; }
.price-toggle__input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.price-toggle__label { position: relative; display: flex; align-items: center; gap: 8px; padding: 9px 20px; border-radius: 999px; font-size: 14px; font-weight: 600; color: var(--muted); cursor: pointer; transition: color 0.15s ease, background 0.15s ease; }
.price-toggle__input:checked + .price-toggle__label { background: var(--paper); color: var(--heading); box-shadow: 0 4px 14px -8px rgba(11, 56, 79, 0.4); }
.price-toggle__save { font-size: 11px; font-weight: 700; padding: 3px 9px; border-radius: 999px; background: var(--brand); color: #fff; }
/* One switch above the grid, or one inside every card that bills more than one
   way. The second is what lets a plan with a Monthly/Annual choice sit beside
   one that only bills annually — which is most real price lists. */
.price-toggle--card { margin: 4px 0 10px; padding: 3px; }
.price-toggle--card .price-toggle__label { padding: 6px 14px; font-size: 13px; }
.price-toggle--card .price-toggle__save { font-size: 10px; padding: 2px 7px; }

/* ---------- Billing periods ----------
   Which period is showing is decided by CSS alone: the CSP allows no inline
   script and cannot allowlist one generated per page, per block (see
   docs/CMS.md §9), so :has() reads the checked radio and these rules do the
   showing and hiding. That is also why the count is capped — every period
   needs its own pair of rules written out, and MAX_PRICE_PERIODS in
   js/cms-render.js is the same 4 this block stops at.

   An element with no data-period at all is never touched, which is how a
   "Custom" or "Free" line stays put under every period without the author
   retyping the same figure once per period.

   --pv is each element's own display when it *is* showing, because these are a
   mix of blocks and inline runs and a blanket `display: block` would break the
   ones that sit on a line with their label. */
.price-card [data-period] { display: none; }
.price-card [data-period="0"] { display: var(--pv, block); }

.price-toggle--section:has(.price-toggle__input[data-p="1"]:checked) ~ .price-grid .price-card [data-period="0"],
.price-card:has(.price-toggle__input[data-p="1"]:checked) [data-period="0"] { display: none; }
.price-toggle--section:has(.price-toggle__input[data-p="1"]:checked) ~ .price-grid .price-card [data-period="1"],
.price-card:has(.price-toggle__input[data-p="1"]:checked) [data-period="1"] { display: var(--pv, block); }

.price-toggle--section:has(.price-toggle__input[data-p="2"]:checked) ~ .price-grid .price-card [data-period="0"],
.price-card:has(.price-toggle__input[data-p="2"]:checked) [data-period="0"] { display: none; }
.price-toggle--section:has(.price-toggle__input[data-p="2"]:checked) ~ .price-grid .price-card [data-period="2"],
.price-card:has(.price-toggle__input[data-p="2"]:checked) [data-period="2"] { display: var(--pv, block); }

.price-toggle--section:has(.price-toggle__input[data-p="3"]:checked) ~ .price-grid .price-card [data-period="0"],
.price-card:has(.price-toggle__input[data-p="3"]:checked) [data-period="0"] { display: none; }
.price-toggle--section:has(.price-toggle__input[data-p="3"]:checked) ~ .price-grid .price-card [data-period="3"],
.price-card:has(.price-toggle__input[data-p="3"]:checked) [data-period="3"] { display: var(--pv, block); }

/* ---------- Composed plan cards ----------
   A card is a stack of rows: price lines, headings, lists, buttons, notes,
   rules, in whatever order the plan was written. Everything here styles one
   kind of row; nothing assumes how many of each a card has, which is the
   whole point of the shape. */

/* A price line. With a label it reads as a row in a rate table — label left,
   amount right — which is how a plan that sells three different seats lists
   them. Without one the amount is the headline, and gets the display face and
   the size a single-price tier needs. */
.price-line { display: flex; flex-direction: column; gap: 6px; padding: 4px 0; }
.price-line__head { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; }
.price-line__label { font-family: var(--display); font-size: 17px; font-weight: 600; color: var(--heading); }
.price-line__values { display: block; }
.price-line__value { --pv: inline-flex; display: inline-flex; align-items: baseline; gap: 2px; white-space: nowrap; }
.price-line__amount { font-family: var(--display); font-size: 21px; font-weight: 600; letter-spacing: -0.02em; color: var(--heading); }
.price-line__suffix { font-family: var(--body); font-size: 13px; font-weight: 500; color: var(--muted); letter-spacing: 0; }
.price-line__caption { --pv: block; font-size: 13px; line-height: 1.45; color: var(--muted); }
.price-line--solo .price-line__head { display: block; }
.price-line--solo .price-line__amount { font-size: clamp(32px, 3.2vw, 42px); letter-spacing: -0.03em; line-height: 1.05; }
.price-line--solo .price-line__suffix { font-size: 15px; }
.price-line--solo .price-line__caption { margin-top: 3px; }

/* The little marks under a price line saying what the seat opens up. Tinted
   washes rather than full-colour brand glyphs, so a strip of eight doesn't
   out-shout the number above it. */
.price-line__glyphs { display: flex; flex-wrap: wrap; gap: 5px; }
.price-glyph {
  display: inline-flex; align-items: center; justify-content: center;
  width: 21px; height: 21px; border-radius: 6px;
  background: var(--pill); color: var(--muted);
}
.price-glyph svg { width: 13px; height: 13px; }
.price-glyph--brand { background: color-mix(in srgb, var(--brand) 14%, transparent); color: var(--brand); }
.price-glyph--blue { background: rgba(56, 132, 255, 0.14); color: #2f6fd0; }
.price-glyph--green { background: rgba(31, 175, 106, 0.14); color: #17915a; }
.price-glyph--purple { background: rgba(140, 92, 246, 0.14); color: #7048d8; }
.price-glyph--orange { background: rgba(247, 144, 44, 0.16); color: #c9711a; }
.price-glyph--pink { background: rgba(236, 92, 168, 0.14); color: #cc408b; }
.price-glyph--red { background: rgba(226, 74, 74, 0.14); color: #c33b3b; }

/* Rows that are a group of things rather than one thing — a headed list, a
   button on its own line. The [style] hook is "push to the bottom": the row
   carries margin-top:auto, which in a stretched flex column lines every card's
   button up on one baseline. */
.price-rowgroup { display: flex; flex-direction: column; gap: 8px; }
/* .price-card .btn carries the margins that space a lone button in a plain
   card; inside a row the card's own gap already does that, and a button that
   fills its column is the shape a composed card wants. */
.price-rowgroup--btn .btn { margin: 4px 0; width: 100%; }
.price-card__h { font-size: 14px; font-weight: 600; color: var(--heading); margin-top: 6px; }
.price-card__text { font-size: 14.5px; line-height: 1.55; color: var(--muted); }
.price-card__note { font-size: 13px; line-height: 1.5; color: var(--muted); margin-top: 4px; }
.price-card__note a { color: var(--brand); text-decoration: underline; text-underline-offset: 2px; }
.price-card__billing { font-size: 13.5px; font-weight: 500; color: var(--muted); }
.price-card__rule { padding: 8px 0; }
.price-card__rule span { display: block; height: 1px; background: var(--line); }

/* List markers. A check in a disc is the "this is definitely included" one; a
   plain dot is for a list that is describing who the plan suits rather than
   ticking off what it contains. */
.price-mark { display: inline-flex; align-items: center; justify-content: center; width: 17px; height: 17px; flex: none; margin-top: 1px; color: var(--brand); }
.price-mark svg { width: 17px; height: 17px; }
.price-mark--disc { border-radius: 999px; background: #1faf6a; color: #fff; width: 16px; height: 16px; margin-top: 2px; }
.price-mark--disc svg { width: 11px; height: 11px; }
.price-mark--dot::before { content: ""; width: 5px; height: 5px; border-radius: 999px; background: var(--muted); }
.price-mark--dash::before { content: ""; width: 9px; height: 1.5px; border-radius: 2px; background: var(--muted); }

/* ---------- Columns instead of boxes ----------
   A dense comparison — several price lines per plan, two headed lists under
   each — reads better as columns divided by hairlines than as four heavy
   rounded boxes, which is the shape most large price lists actually use. */
.price-grid--flat { gap: 0; align-items: stretch; }
.price-grid--flat .price-card {
  border: 0;
  border-left: 1px solid var(--line);
  border-radius: 0;
  background: transparent;
  padding: clamp(18px, 2vw, 30px);
}
.price-grid--flat .price-card:first-child { border-left: 0; }
.price-grid--flat .price-card--featured { outline: 0; box-shadow: none; background: var(--pill); }
.price-grid--flat .price-card__badge { position: static; transform: none; align-self: flex-start; }
.price-grid--flat .price-line { border-top: 1px solid var(--line); padding: 14px 0; }
.price-grid--flat .price-line:first-of-type { border-top: 0; }
@media (max-width: 900px) {
  .price-grid--flat { gap: var(--price-gap); }
  .price-grid--flat .price-card { border-left: 0; border-top: 1px solid var(--line); padding-top: 24px; }
  .price-grid--flat .price-card:first-child { border-top: 0; }
}

/* ---------- FAQ ---------- */
.faq { max-width: 760px; margin-inline: auto; }
.faq__item { border-bottom: 1px solid var(--line); padding: 22px 0; }
.faq__q { font-family: var(--display); font-size: clamp(17px, 1.4vw, 20px); font-weight: 600; color: var(--heading); margin-bottom: 8px; }
.faq__a { font-size: 15px; line-height: 1.62; color: var(--muted); }

/* ---------- Blog page: category chips ---------- */
.chips { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: clamp(28px, 4vh, 44px); }
.chip-btn { padding: 8px 16px; border-radius: 999px; background: var(--pill); font-size: 13.5px; font-weight: 500; color: var(--ink); transition: background-color 0.2s, color 0.2s; }
.chip-btn:hover, .chip-btn[aria-pressed="true"] { background: var(--brand); color: #fff; }

/* ---------- Logo wall (Solutions) ---------- */
.logowall { display: grid; grid-template-columns: repeat(auto-fill, minmax(158px, 1fr)); gap: 4px 8px; }

/* ---------- Contact ---------- */
.contactgrid { display: grid; grid-template-columns: 1.3fr 1fr; gap: clamp(32px, 5vw, 80px); align-items: start; }
@media (max-width: 860px) { .contactgrid { grid-template-columns: 1fr; } }
.form { display: flex; flex-direction: column; gap: 18px; }
/* display on a class beats the UA rule behind the hidden attribute, so both of
   these need saying explicitly — the sign-in dialog keeps its two forms in one
   panel and hides the one it is not showing. */
.form[hidden], .field[hidden] { display: none; }
.field { display: flex; flex-direction: column; gap: 8px; }
.field label { font-size: 13.5px; font-weight: 600; color: var(--heading); }
.field input, .field textarea {
  font: inherit;
  font-size: 15px;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 13px 15px;
  transition: border-color 0.2s, box-shadow 0.2s;
  width: 100%;
}
.field textarea { resize: vertical; min-height: 130px; }
.field input:focus, .field textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(14, 143, 200, 0.15);
}
.field input::placeholder, .field textarea::placeholder { color: var(--muted); opacity: 0.7; }
.form .btn { align-self: flex-start; margin-top: 4px; }
.form__note { font-size: 14px; color: var(--brand); font-weight: 500; }
/* "You're asking about X" — the service a visitor arrived from, above the
   fields rather than inside them, because it isn't something they typed. */
.form__about {
  display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap;
  padding: 11px 14px; border-radius: 11px; background: var(--pill);
  font-size: 13.5px; color: var(--muted);
}
.form__about[hidden], .form__ok[hidden], .form__ok a[hidden] { display: none; }
.form__about b { color: var(--heading); font-weight: 600; }
.form__about a { margin-left: auto; color: var(--brand); font-weight: 600; font-size: 13px; }
.form__ok {
  display: flex; flex-direction: column; gap: 6px;
  padding: 13px 16px; border-radius: 11px;
  border: 1px solid rgba(14, 143, 200, 0.3); background: rgba(14, 143, 200, 0.08);
  font-size: 14px; color: var(--ink);
}
.form__ok a { color: var(--brand); font-weight: 600; }
.contact-side { display: flex; flex-direction: column; gap: 14px; }
.contact-card {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 20px 22px;
  transition: border-color 0.3s, transform 0.3s cubic-bezier(0.3, 0.7, 0, 1);
}
.contact-card:hover { transform: translateY(-3px); border-color: var(--brand); }
.contact-card__ic { width: 40px; height: 40px; flex: none; display: grid; place-items: center; border-radius: 11px; background: var(--pill); color: var(--brand); }
.contact-card__ic svg { width: 21px; height: 21px; }
.contact-card h3 { font-family: var(--display); font-size: 16px; font-weight: 600; color: var(--heading); margin-bottom: 3px; }
.contact-card p, .contact-card a { font-size: 14.5px; line-height: 1.5; color: var(--muted); }
.contact-card a:hover { color: var(--brand); }

/* ---------- Auth pages (login / register) ---------- */
.authwrap {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 110px var(--gutter) 60px;
  position: relative;
  overflow: hidden;
}
.auth__canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.authcard {
  position: relative;
  width: 100%;
  max-width: 440px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 24px;
  padding: clamp(28px, 4vw, 44px);
  box-shadow: 0 30px 70px -40px rgba(23, 24, 28, 0.5);
}
.authcard__title { font-family: var(--display); font-size: clamp(26px, 3vw, 34px); font-weight: 600; letter-spacing: -0.025em; color: var(--heading); }
.authcard__sub { margin-top: 8px; font-size: 15px; color: var(--muted); }
.authcard .form { margin-top: 26px; }
.authcard .btn { justify-content: center; width: 100%; }
.auth__alt { margin-top: 20px; font-size: 14.5px; color: var(--muted); text-align: center; }
.auth__alt a { color: var(--brand); font-weight: 600; }
.auth__error {
  margin-top: 4px; padding: 11px 14px;
  background: rgba(220, 60, 60, 0.1);
  border: 1px solid rgba(220, 60, 60, 0.3);
  border-radius: 11px;
  color: #c0392b; font-size: 14px; font-weight: 500;
}
:root[data-theme="dark"] .auth__error { color: #ff9a8f; background: rgba(220, 60, 60, 0.14); }

/* ----- Social sign-in ----- */
.authsocial { display: flex; flex-direction: column; gap: 10px; margin-top: 22px; }
/* The providers sit side by side, so each label is just the brand name — at
   half a card's width there is no room for "Continue with".
   The basis has to beat .sbtn's own width:100%, or each button measures a full
   row and the pair always breaks. One shared basis rather than each button's
   own content width keeps the two the same size; the wrap is what handles a
   phone too narrow for both, without a breakpoint to keep in step. Brand names
   are the same length in every language, so the number below stays true. */
.authsocial__row { display: flex; flex-wrap: wrap; gap: 10px; }
.authsocial__row .sbtn {
  flex: 1 1 124px; /* the wider label + its mark + padding, to the pixel */
  padding-left: 12px; padding-right: 12px;
  white-space: nowrap;
}
.sbtn {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; padding: 12px 18px;
  font: inherit; font-size: 14.5px; font-weight: 600;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
  transition: border-color 0.2s, background-color 0.2s, transform 0.25s cubic-bezier(0.3, 0.7, 0, 1);
}
.sbtn:hover { border-color: var(--brand); transform: translateY(-2px); }
.sbtn:disabled { opacity: 0.55; cursor: progress; transform: none; }
.sbtn__ic { width: 18px; height: 18px; flex: none; }
/* A provider that is shown but not yet wired up (see `features` in
   js/supabase-config.js). Dimmed and disabled rather than hidden, so the
   method reads as "coming", not "gone" — the tag says which. :hover still
   matches a disabled button, so the lift has to be cancelled explicitly. */
.sbtn--soon:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }
.sbtn--soon:hover { border-color: var(--line); transform: none; }
/* Says why the button above it is dead. Under the button, not inside it: at a
   phone's width the label already fills the button on its own. */
.sbtn__soon { margin-top: -4px; text-align: center; font-size: 12.5px; color: var(--muted); }
.sbtn__soon[hidden] { display: none; }
/* The provider marks must keep their own brand colours in dark mode, so they
   are deliberately left out of any theme inversion. */
/* Sits midway between the submit button above and the providers below: the
   22px above it and the 12px + the column's 10px gap below it put the rule on
   the centre line. It used to hang 40px under the button and 12px over the
   buttons, which read as part of the pair rather than a divider between. */
.authdiv { display: flex; align-items: center; gap: 12px; margin: 0 0 12px; }
.authdiv::before, .authdiv::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.authdiv span { font-size: 12.5px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }

/* ----- Email / phone tabs ----- */
.authtabs {
  display: flex; gap: 4px; margin-top: 24px; padding: 4px;
  background: var(--pill); border-radius: 999px;
}
.authtabs[hidden] { display: none; }
.authtabs__t {
  flex: 1; padding: 9px 14px;
  font: inherit; font-size: 14px; font-weight: 600;
  color: var(--muted); background: none; border: 0; border-radius: 999px;
  cursor: pointer; transition: background-color 0.2s, color 0.2s;
}
.authtabs__t.is-active { background: var(--paper); color: var(--heading); box-shadow: 0 1px 3px rgba(23, 24, 28, 0.12); }

/* ----- OTP ----- */
.field__hint { font-size: 12.5px; color: var(--muted); }
.auth__sent { font-size: 14.5px; color: var(--muted); }
.auth__sent b { color: var(--heading); }
.otpinput {
  font-family: var(--mono) !important;
  font-size: 22px !important;
  letter-spacing: 0.42em;
  text-align: center;
  padding-left: 0.42em !important; /* re-centre against the trailing letter-space */
}
.auth__otpfoot { display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.auth__link {
  font: inherit; font-size: 13.5px; font-weight: 600;
  color: var(--brand); background: none; border: 0; padding: 0;
  cursor: pointer; text-align: left;
}
.auth__link:hover { text-decoration: underline; }
.auth__link:disabled { color: var(--muted); cursor: default; text-decoration: none; }
.auth__link--right { align-self: flex-end; margin-top: -2px; }
.auth__note {
  margin-top: 4px; padding: 11px 14px;
  background: rgba(14, 143, 200, 0.1);
  border: 1px solid rgba(14, 143, 200, 0.28);
  border-radius: 11px;
  color: var(--brand); font-size: 14px; font-weight: 500;
}

/* ----- Post-signup "confirm your email" ----- */
.authverify { text-align: center; }
.authverify__ic {
  display: inline-grid; place-items: center;
  width: 54px; height: 54px; margin-bottom: 16px;
  border-radius: 16px; background: var(--pill); color: var(--brand);
}
.authverify__ic svg { width: 26px; height: 26px; }
.authverify h2 { font-family: var(--display); font-size: 22px; font-weight: 600; color: var(--heading); }
.authverify p { margin-top: 10px; font-size: 14.5px; line-height: 1.6; color: var(--muted); }
.authverify p b { color: var(--heading); word-break: break-word; }
.authverify__acts { display: flex; flex-direction: column; gap: 10px; margin-top: 22px; }

/* ----- Callback spinner ----- */
.authspin {
  display: block; width: 30px; height: 30px; margin: 0 auto 20px;
  border: 3px solid var(--line); border-top-color: var(--brand);
  border-radius: 50%;
  animation: authspin 0.7s linear infinite;
}
@keyframes authspin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .authspin { animation-duration: 2.4s; } }

/* A busy button shouldn't also invite another click. */
.btn[data-busy] { opacity: 0.6; cursor: progress; transform: none !important; }

/* ---------- Dashboard ---------- */
.dash { max-width: calc(var(--content-max) + 2 * var(--gutter)); margin: 0 auto; padding: clamp(120px, 16vh, 180px) var(--gutter) var(--section-y); }
.dash__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; margin-bottom: clamp(30px, 5vh, 52px); }
.dash__greet { font-family: var(--display); font-size: clamp(30px, 3.6vw, 50px); font-weight: 600; letter-spacing: -0.03em; color: var(--heading); }
.dash__greet span { color: var(--brand); }
.dash__grid { display: grid; grid-template-columns: 320px 1fr; gap: clamp(20px, 3vw, 40px); align-items: start; }
@media (max-width: 820px) { .dash__grid { grid-template-columns: 1fr; } }
.dash__card { border: 1px solid var(--line); border-radius: 22px; padding: clamp(22px, 3vw, 32px); background: var(--paper); }
.dash__card h2 { font-family: var(--display); font-size: 20px; font-weight: 600; color: var(--heading); margin-bottom: 18px; letter-spacing: -0.015em; }
.dash__meta { font-size: 14px; color: var(--muted); margin-bottom: 6px; }
.dash__meta b { color: var(--ink); font-weight: 600; }
.dash__actions { margin-top: 22px; display: flex; flex-direction: column; gap: 10px; }
.dash__actions .btn { justify-content: center; }
.profileNote { margin-top: 12px; font-size: 13.5px; color: var(--brand); font-weight: 500; }

/* ============================================================
   Inner pages (Solutions / Academy / Services)
   Same visual language as the home page — full-bleed WebGL hero,
   alternating feature rows, dark panel, two-column CTA — with a
   different scene + signature motion per page.
   ============================================================ */

/* Page hero: home's hero, a little shorter, eyebrow instead of the logo */
.hero--page { min-height: clamp(560px, 78vh, 760px); }
.hero--page .hero__title { font-size: clamp(38px, 6.4vw, 92px); }
.hero--page .hero__sub {
  margin: 22px auto 0; max-width: 58ch;
  font-size: clamp(15px, 1.35vw, 18.5px); line-height: 1.7; color: var(--muted);
}

/* Count-up stat band (Academy) */
.statband {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: clamp(16px, 2vw, 30px);
}
.statband__cell {
  text-align: center; padding: clamp(24px, 2.6vw, 36px) 18px;
  border: 1px solid var(--line); border-radius: 20px; background: var(--paper);
}
.statband__n {
  font-family: var(--display); font-weight: 600; letter-spacing: -0.03em;
  font-size: clamp(34px, 4.4vw, 60px); color: var(--brand); line-height: 1;
}
.statband__l { margin-top: 10px; font-size: 14px; color: var(--muted); }

/* Process with a drawn connector line (Services) */
.proc { position: relative; display: grid; gap: clamp(18px, 2.4vw, 30px); }
.proc__line { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; }
.proc__line path { fill: none; stroke: var(--brand); stroke-width: 2; stroke-dasharray: 6 8; opacity: 0.55; }
.pstep {
  position: relative; display: grid; grid-template-columns: auto 1fr; gap: clamp(18px, 2vw, 28px);
  align-items: start; padding: clamp(22px, 2.4vw, 32px);
  border: 1px solid var(--line); border-radius: 20px; background: var(--paper);
}
.pstep__dot {
  width: 46px; height: 46px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  font-family: var(--display); font-size: 15px; font-weight: 700;
  background: var(--brand); color: #fff;
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--brand) 14%, transparent);
}
.pstep h3 { font-family: var(--display); font-size: clamp(18px, 1.8vw, 23px); font-weight: 600; color: var(--heading); margin-bottom: 7px; }
:root[data-theme="dark"] .pstep h3 { color: var(--ink); }
.pstep p { font-size: 15px; line-height: 1.65; color: var(--muted); max-width: 62ch; }
@media (min-width: 900px) {
  .proc { grid-template-columns: 1fr 1fr; }
  .proc .pstep:nth-child(odd) { margin-right: 8%; }
  .proc .pstep:nth-child(even) { margin-left: 8%; margin-top: 34px; }
}

/* Mock-UI card bodies used inside feature media (home .card language) */
.mockrow {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 11px 14px; border-radius: 11px;
  background: var(--pill); font-size: 13px; color: var(--ink);
}
.mockrow + .mockrow { margin-top: 9px; }
.mockrow b { font-weight: 600; }
.mockrow em { font-style: normal; color: var(--muted); font-size: 12px; }
.mocktag {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border-radius: 999px;
  background: color-mix(in srgb, var(--brand) 15%, transparent);
  color: var(--brand); font-size: 11.5px; font-weight: 600;
}
.mockbar { height: 7px; border-radius: 99px; background: var(--pill); overflow: hidden; }
.mockbar i { display: block; height: 100%; border-radius: 99px; background: linear-gradient(90deg, var(--brand), var(--teal)); }

/* ============================================================
   Hub pages (Solutions / Academy / Services) + detail pages.
   Motion classes are driven by js/main.js scroll scenes.
   ============================================================ */

/* ---------- Vendor / track rail: the clickable row at the top ---------- */
/* Fixed column counts rather than auto-fill: 12 vendors then divide evenly
   (2/3/4/6) instead of wrapping to an orphaned last row of tiny tiles. */
.rail {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(12px, 1.4vw, 20px);
}
@media (min-width: 560px)  { .rail { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 900px)  { .rail { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1200px) { .rail { grid-template-columns: repeat(6, 1fr); } }
/* Short sets (courses, services) would leave most of a 6-up row empty. */
.rail--few { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); max-width: 940px; }
@media (min-width: 560px)  { .rail--few { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); } }
@media (min-width: 900px)  { .rail--few { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); } }
@media (min-width: 1200px) { .rail--few { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); } }

.railcard {
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  padding: clamp(22px, 2vw, 30px) 16px clamp(18px, 1.6vw, 24px);
  border: 1px solid var(--line); border-radius: 18px;
  background: var(--paper);
  text-align: center;
  transition: transform 0.25s, box-shadow 0.25s, border-color 0.25s;
}
.railcard:hover {
  transform: translateY(-4px);
  border-color: color-mix(in srgb, var(--brand) 45%, transparent);
  box-shadow: 0 22px 44px -26px rgba(11, 56, 79, 0.4);
}
/* Vendor logos are drawn for light backgrounds — keep the chip light in both
   themes so dark-inked marks stay legible on the dark theme. */
.railcard__ic {
  /* flex:none — in a column flex card the chip is a flex item, so without it
     the browser is free to shrink its height and the logo comes out squashed. */
  flex: none;
  width: 58px; height: 58px; border-radius: 15px;
  display: grid; place-items: center;
  background: #fff;
  box-shadow: inset 0 0 0 1px rgba(11, 56, 79, 0.08);
}
.railcard__ic img { width: 32px; height: 32px; object-fit: contain; }
.railcard__ic svg { width: 26px; height: 26px; color: var(--brand); }
.railcard__name { font-size: 15px; font-weight: 600; color: var(--ink); line-height: 1.3; }
.railcard__n { font-size: 12.5px; color: var(--muted); }
:root[data-theme="dark"] .railcard:hover { box-shadow: 0 22px 44px -26px rgba(0, 0, 0, 0.85); }
:root[data-theme="dark"] .railcard:hover { box-shadow: 0 22px 44px -26px rgba(0, 0, 0, 0.8); }

/* ---------- Big statement: words colour in on scroll ---------- */
.bigstate {
  font-family: var(--display);
  font-size: clamp(26px, 3.6vw, 54px);
  font-weight: 600;
  line-height: 1.24;
  letter-spacing: -0.02em;
  color: var(--heading);
  max-width: 22ch;
  margin-inline: auto;
  text-align: center;
  text-wrap: balance;
}
.bigstate .w { display: inline-block; opacity: 0.16; }
.bigstate .w.is-on { opacity: 1; }
.bigstate mark {
  background: color-mix(in srgb, var(--brand) 18%, transparent);
  color: inherit; padding: 0 0.12em; border-radius: 6px;
}
:root[data-theme="dark"] .bigstate { color: var(--ink); }

/* ---------- Split headline with media between the halves ---------- */
.splithead {
  display: flex; align-items: center; justify-content: center;
  gap: clamp(14px, 3vw, 48px);
  font-family: var(--display);
  font-size: clamp(30px, 5.4vw, 78px);
  font-weight: 600; letter-spacing: -0.03em; line-height: 1;
  color: var(--heading);
}
:root[data-theme="dark"] .splithead { color: var(--ink); }
.splithead__media {
  flex: none;
  width: clamp(120px, 22vw, 300px);
  aspect-ratio: 4 / 3;
  border-radius: 20px;
  overflow: hidden;
  background: linear-gradient(140deg, var(--brand), var(--brand-dark));
  display: grid; place-items: center;
  box-shadow: 0 28px 60px -30px rgba(11, 56, 79, 0.55);
}
.splithead__media svg { width: 42%; height: 42%; color: #fff; opacity: 0.9; }

/* ---------- Word ticker ---------- */
.tickerwrap { overflow: clip; padding-block: clamp(26px, 4vh, 54px); }
.ticker { display: flex; align-items: center; gap: 26px; width: max-content; will-change: transform; }
.ticker span {
  font-family: var(--display); font-weight: 600;
  font-size: clamp(15px, 1.7vw, 24px); letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--muted); white-space: nowrap;
}
.ticker i { color: var(--brand); font-style: normal; }

/* ---------- Orbit ring ---------- */
.orbit {
  position: relative;
  width: min(460px, 84vw); aspect-ratio: 1;
  margin-inline: auto;
  display: grid; place-items: center;
}
.orbit::before {
  content: ""; position: absolute; inset: 34px;
  border: 1px dashed var(--line); border-radius: 50%;
}
.orbit__core {
  width: 42%; aspect-ratio: 1; border-radius: 50%;
  display: grid; place-items: center; text-align: center;
  background: var(--paper); border: 1px solid var(--line);
  box-shadow: 0 20px 50px -24px rgba(11, 56, 79, 0.4);
  font-family: var(--display); font-weight: 600; color: var(--heading);
  font-size: clamp(13px, 1.5vw, 17px); padding: 12px;
}
:root[data-theme="dark"] .orbit__core { color: var(--ink); }
.orbit__item {
  position: absolute; top: 50%; left: 50%;
  margin: -25px 0 0 -25px;
  width: 50px; height: 50px; border-radius: 15px;
  display: grid; place-items: center;
  background: var(--paper); border: 1px solid var(--line);
  box-shadow: 0 10px 24px -14px rgba(11, 56, 79, 0.4);
}
.orbit__item img { width: 26px; height: 26px; object-fit: contain; }

/* ---------- Detail pages (vendor / course / service) ---------- */
.dhero { padding: clamp(120px, 16vh, 190px) var(--gutter) clamp(40px, 6vh, 70px); }
.dhero__inner { max-width: var(--content-max); margin-inline: auto; }
.dhero__back { display: inline-flex; align-items: center; gap: 7px; font-size: 14px; color: var(--muted); margin-bottom: 22px; transition: color 0.2s; }
.dhero__back:hover { color: var(--brand); }
.dhero__back svg { width: 14px; height: 14px; }
.dhero__lockup { display: flex; align-items: center; gap: 18px; margin-bottom: 20px; }
.dhero__logo {
  width: 68px; height: 68px; border-radius: 19px;
  display: grid; place-items: center; flex: none;
  background: var(--pill); border: 1px solid var(--line);
}
.dhero__logo img { width: 38px; height: 38px; object-fit: contain; }
.dhero__logo svg { width: 32px; height: 32px; color: var(--brand); }
.dhero__title {
  font-family: var(--display); font-weight: 600;
  font-size: clamp(34px, 5vw, 66px); letter-spacing: -0.03em; line-height: 1.02;
  color: var(--heading);
}
:root[data-theme="dark"] .dhero__title { color: var(--ink); }
.dhero__tagline { font-size: clamp(16px, 1.6vw, 21px); color: var(--brand); font-weight: 500; margin-top: 6px; }
.dhero__blurb { margin-top: 22px; max-width: 62ch; font-size: clamp(15px, 1.25vw, 18px); line-height: 1.7; color: var(--muted); }

.pgroup { margin-top: clamp(40px, 6vh, 72px); }
.pgroup__name {
  font-size: 12px; font-weight: 600; letter-spacing: 0.15em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 16px;
}
.plist { display: grid; gap: 12px; }
.prow {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center; gap: clamp(14px, 2vw, 30px);
  padding: clamp(18px, 1.8vw, 24px) clamp(18px, 2vw, 28px);
  border: 1px solid var(--line); border-radius: 16px;
  background: var(--paper);
  transition: border-color 0.22s, box-shadow 0.22s, transform 0.22s;
}
.prow:hover { transform: translateY(-2px); border-color: transparent; box-shadow: 0 20px 44px -28px rgba(11, 56, 79, 0.4); }
.prow__name { font-family: var(--display); font-size: 17px; font-weight: 600; color: var(--heading); }
:root[data-theme="dark"] .prow__name { color: var(--ink); }
.prow__desc { font-size: 14px; color: var(--muted); margin-top: 4px; line-height: 1.55; }
.prow__price { font-family: var(--display); font-size: 19px; font-weight: 600; color: var(--heading); white-space: nowrap; }
:root[data-theme="dark"] .prow__price { color: var(--ink); }
@media (max-width: 700px) {
  .prow { grid-template-columns: 1fr auto; }
  .prow__price { grid-column: 1; grid-row: 2; }
}
:root[data-theme="dark"] .prow:hover { box-shadow: 0 20px 44px -28px rgba(0, 0, 0, 0.8); }

/* Company page: product rows that link through to a software page */
.dhero__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; }
.prow--link { cursor: pointer; text-decoration: none; }
.prow--link:hover { border-color: color-mix(in srgb, var(--brand) 45%, transparent); }
.prow__cta {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  font-size: 13.5px; font-weight: 600; color: var(--brand);
}
.prow__go { width: 15px; height: 15px; transition: transform 0.22s; }
.prow--link:hover .prow__go { transform: translate(2px, -2px); }
@media (max-width: 700px) { .prow__cta { grid-column: 1; } }

/* App-grid price sub-label (company page) */
.railcard__price { color: var(--brand); font-weight: 600; }

/* Small vendor tag above each feature heading (software page rows) */
.feat__tag { display: inline-flex; align-items: center; gap: 8px; margin-bottom: 14px; font-size: 13px; font-weight: 600; color: var(--muted); }
.feat__tag > span { line-height: 1; }
.feat__tag img { width: 20px; height: 20px; object-fit: contain; }
.feat__tag svg { width: 18px; height: 18px; color: var(--brand); }

/* Software page: pill, highlights, price block */
.swhero .swpill {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 8px 15px 8px 8px; border-radius: 999px;
  background: var(--paper); border: 1px solid var(--line);
  font-size: 13.5px; color: var(--muted);
}
.swpill__ic {
  width: 26px; height: 26px; border-radius: 8px; flex: none;
  display: grid; place-items: center; background: #fff;
  box-shadow: inset 0 0 0 1px rgba(11, 56, 79, 0.08);
}
.swpill__ic img { width: 16px; height: 16px; object-fit: contain; }
.swpill__ic svg { width: 15px; height: 15px; color: var(--brand); }
.swpill b { color: var(--heading); font-weight: 600; }
:root[data-theme="dark"] .swpill b { color: var(--ink); }
.swpill i { color: var(--line); font-style: normal; }
.swpill a { color: var(--brand); font-weight: 600; }

.featlist { list-style: none; display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 12px 26px; }
.featlist li { display: flex; align-items: flex-start; gap: 11px; font-size: 15.5px; color: var(--ink); line-height: 1.5; }
.featlist svg { flex: none; width: 20px; height: 20px; color: var(--brand); margin-top: 1px; }

.priceblock {
  max-width: 460px;
  padding: clamp(24px, 2.6vw, 34px);
  border: 1px solid var(--line); border-radius: 22px;
  background: color-mix(in srgb, var(--brand) 5%, var(--paper));
}
.priceblock__head { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; }
.priceblock__ic { width: 46px; height: 46px; border-radius: 12px; flex: none; display: grid; place-items: center; background: #fff; box-shadow: inset 0 0 0 1px rgba(11, 56, 79, 0.08); }
.priceblock__ic img { width: 28px; height: 28px; object-fit: contain; }
.priceblock__ic svg { width: 24px; height: 24px; color: var(--brand); }
.priceblock__head h3 { font-family: var(--display); font-size: 18px; font-weight: 600; color: var(--heading); }
:root[data-theme="dark"] .priceblock__head h3 { color: var(--ink); }
.priceblock__head p { font-size: 13px; color: var(--muted); }
.priceblock__price { font-family: var(--display); font-size: clamp(30px, 3.4vw, 44px); font-weight: 600; letter-spacing: -0.03em; color: var(--heading); }
:root[data-theme="dark"] .priceblock__price { color: var(--ink); }
.priceblock__note { font-size: 13.5px; color: var(--muted); line-height: 1.6; margin: 12px 0 20px; }
.priceblock .btn { width: 100%; justify-content: center; }

/* Numbered process steps (services) */
.steps { display: grid; gap: 14px; }
.step {
  display: grid; grid-template-columns: auto 1fr; gap: 20px; align-items: start;
  padding: clamp(20px, 2vw, 28px);
  border: 1px solid var(--line); border-radius: 18px; background: var(--paper);
}
.step__n {
  font-family: var(--display); font-size: 15px; font-weight: 700;
  width: 38px; height: 38px; border-radius: 11px; flex: none;
  display: grid; place-items: center;
  background: var(--brand); color: #fff;
}
.step h3 { font-family: var(--display); font-size: 18px; font-weight: 600; color: var(--heading); margin-bottom: 5px; }
:root[data-theme="dark"] .step h3 { color: var(--ink); }
.step p { font-size: 14.5px; color: var(--muted); line-height: 1.6; }

/* ---------- Services page: software + integrations + price ---------- */
.svgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: clamp(18px, 2vw, 28px);
}
.svcard {
  display: flex;
  flex-direction: column;
  padding: clamp(24px, 2.4vw, 34px);
  border: 1px solid var(--line);
  border-radius: 20px;
  background: var(--paper);
  transition: box-shadow 0.25s, transform 0.25s, border-color 0.25s;
}
.svcard:hover {
  transform: translateY(-3px);
  border-color: transparent;
  box-shadow: 0 26px 54px -30px rgba(11, 56, 79, 0.35);
}
.svcard__head { display: flex; gap: 16px; align-items: flex-start; }
.svcard__head h3 {
  font-family: var(--display); font-size: 20px; font-weight: 600;
  color: var(--heading); letter-spacing: -0.01em; margin-bottom: 6px;
}
.svcard__head p { font-size: 14.5px; line-height: 1.6; color: var(--muted); }
.svcard__int { margin-top: 22px; }
.svcard__intlabel {
  display: block; font-size: 11.5px; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 10px;
}
.intlist { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; }
.intchip {
  font-size: 13px; font-weight: 500; color: var(--ink);
  padding: 6px 12px; border-radius: 999px;
  background: var(--pill); border: 1px solid transparent;
  transition: border-color 0.2s, color 0.2s;
}
.svcard:hover .intchip { border-color: var(--line); }
.svcard__foot {
  margin-top: auto; padding-top: 24px;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.svcard__price { font-family: var(--display); font-size: 22px; font-weight: 600; color: var(--heading); }
:root[data-theme="dark"] .svcard:hover { box-shadow: 0 26px 54px -30px rgba(0, 0, 0, 0.75); }

/* Dashboard "Added products" card (the cart, shown inline for guests too) */
.dash__cartfoot { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }
.dash__cartrow {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 15px; font-weight: 600; color: var(--ink); margin-bottom: 4px;
}
.dash__cartfoot .btn { width: 100%; justify-content: center; margin-top: 12px; }
#dashCartList .cartline:first-child { border-top: 0; padding-top: 0; }

.purchase {
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  padding: 18px 0; border-bottom: 1px solid var(--line); flex-wrap: wrap;
}
.purchase:last-child { border-bottom: 0; }
.purchase__main { display: flex; flex-direction: column; gap: 6px; }
.purchase__tag { align-self: flex-start; font-size: 11px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; padding: 3px 9px; border-radius: 999px; }
.purchase__tag--course { background: rgba(14, 143, 200, 0.14); color: var(--brand); }
.purchase__tag--license { background: rgba(53, 167, 217, 0.16); color: var(--coral); }
.purchase__main h3 { font-family: var(--display); font-size: 17px; font-weight: 600; color: var(--heading); }
.purchase__key { font-family: var(--mono); font-size: 12.5px; color: var(--muted); background: var(--pill); padding: 3px 8px; border-radius: 6px; }
.purchase__status { font-size: 13px; color: var(--brand); font-weight: 600; }
.purchase__meta { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.purchase__price { font-family: var(--display); font-size: 18px; font-weight: 600; color: var(--heading); }
.purchase__date { font-size: 12.5px; color: var(--muted); }
.purchase__empty { text-align: center; padding: 30px 0; color: var(--muted); }
.purchase__empty .btn { margin-top: 16px; }

/* ---------- Dashboard: left section panel ----------
   The account divided by what the things in it are: a licence is a key, a
   course is a date and a place, a service is a conversation. The rail is a
   list of buttons rather than links because every panel is already on the
   page — switching is a class, not a navigation. */
.dash__layout { display: grid; grid-template-columns: 232px 1fr; gap: clamp(20px, 3vw, 44px); align-items: start; }
@media (max-width: 860px) { .dash__layout { grid-template-columns: 1fr; } }

.dashnav { display: flex; flex-direction: column; gap: 2px; position: sticky; top: 96px; }
@media (max-width: 860px) {
  /* Horizontal strip on a phone — five rows of rail above the content would be
     most of the screen before anything on the account appears. */
  .dashnav {
    position: static; flex-direction: row; gap: 6px; overflow-x: auto;
    padding-bottom: 6px; margin-bottom: 8px; scrollbar-width: none;
  }
  .dashnav::-webkit-scrollbar { display: none; }
  .dashnav__item { white-space: nowrap; }
  .dashnav__rule { display: none; }
}
.dashnav__item {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 11px 14px; border-radius: 12px; border: 1px solid transparent;
  font-size: 14.5px; font-weight: 500; color: var(--muted);
  background: none; text-align: left; cursor: pointer;
  transition: background 0.18s, color 0.18s, border-color 0.18s;
}
.dashnav__item:hover { color: var(--ink); background: var(--pill); }
.dashnav__item.is-active { color: var(--heading); font-weight: 600; background: var(--paper); border-color: var(--line); }
.dashnav__ic { width: 19px; height: 19px; flex: none; color: currentColor; }
.dashnav__item.is-active .dashnav__ic { color: var(--brand); }
.dashnav__n {
  margin-left: auto; min-width: 21px; padding: 1px 6px; border-radius: 999px;
  background: var(--pill); color: var(--muted);
  font-family: var(--mono); font-size: 11.5px; font-weight: 600; text-align: center;
}
.dashnav__item.is-active .dashnav__n { background: rgba(14, 143, 200, 0.14); color: var(--brand); }
.dashnav__rule { height: 1px; background: var(--line); margin: 10px 14px; }

/* Only the chosen panel exists as far as the layout is concerned — `hidden`
   would do the same, but a class keeps the choice in one place (showDashSection
   in js/auth.js) rather than split between an attribute and a stylesheet. */
.dashpanel { display: none; }
.dashpanel.is-active { display: block; }
.dashpanel__head { margin-bottom: clamp(18px, 2.4vw, 26px); }
.dashpanel__head h2 { font-family: var(--display); font-size: clamp(21px, 2.4vw, 27px); font-weight: 600; letter-spacing: -0.02em; color: var(--heading); }
.dashpanel__head .dash__meta { margin-top: 6px; margin-bottom: 0; max-width: 56ch; }
.dash__signin { padding: 26px 0; color: var(--muted); font-size: 14.5px; }
.dash__signin a { color: var(--brand); font-weight: 600; }

/* The flash after an enrolment lands, carried here by ?enrolled=. */
.dashflash {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 18px; margin-bottom: clamp(20px, 3vh, 30px);
  border: 1px solid rgba(14, 143, 200, 0.3); border-radius: 14px;
  background: rgba(14, 143, 200, 0.08); color: var(--ink); font-size: 14.5px;
}
/* display:flex beats the UA's [hidden] rule on specificity alone, so a panel
   that starts hidden has to say so again — the same reason .avatar[hidden] and
   .authtabs[hidden] exist above. */
.dashflash[hidden] { display: none; }
.dashflash svg { width: 20px; height: 20px; flex: none; color: var(--brand); }
.dashflash code { font-family: var(--mono); font-size: 13.5px; color: var(--heading); font-weight: 600; }
.dashflash--err { border-color: rgba(192, 57, 43, 0.35); background: rgba(192, 57, 43, 0.08); }
.dashflash--err svg { display: none; }

/* ---------- Dashboard: the small cards ---------- */
.minigrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(258px, 1fr)); gap: 16px; }
.minicard {
  display: flex; flex-direction: column; gap: 9px;
  padding: 18px 20px 20px; border: 1px solid var(--line); border-radius: 16px;
  background: var(--paper); transition: border-color 0.2s, box-shadow 0.2s;
}
.minicard:hover { border-color: var(--brand); box-shadow: 0 18px 40px -30px rgba(0, 0, 0, 0.4); }
.minicard--cancelled, .minicard.is-cancelled { opacity: 0.6; }
.minicard__top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.minicard__tag {
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 3px 9px; border-radius: 999px; background: var(--pill); color: var(--muted);
}
.minicard__tag--license { background: rgba(53, 167, 217, 0.16); color: var(--coral); }
.minicard__tag--course { background: rgba(14, 143, 200, 0.14); color: var(--brand); }
.minicard__tag--service { background: rgba(14, 143, 200, 0.14); color: var(--brand); }
.minicard__tag--enquiry { background: var(--pill); color: var(--muted); }
.minicard__date { font-size: 12px; color: var(--muted); white-space: nowrap; }
.minicard__name { font-family: var(--display); font-size: 16.5px; font-weight: 600; line-height: 1.3; color: var(--heading); }
.minicard__sub { font-size: 13.5px; color: var(--muted); }
.minicard__note, .minicard__excerpt { font-size: 13px; line-height: 1.5; color: var(--muted); }

/* Two columns of label/value, so the facts line up down the card rather than
   reading as a paragraph of run-together words. */
.minicard__facts { display: flex; flex-direction: column; gap: 5px; margin-top: 2px; }
.minicard__facts > div { display: flex; gap: 10px; align-items: baseline; font-size: 13px; }
.minicard__facts dt { flex: none; width: 74px; color: var(--muted); }
.minicard__facts dd { color: var(--ink); font-weight: 500; }

/* The code, rendered as the button that copies it. */
.minicard__key {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: auto; padding: 8px 11px; width: 100%;
  border: 1px dashed var(--line); border-radius: 9px; background: var(--pill);
  cursor: pointer; transition: border-color 0.18s, color 0.18s;
}
.minicard__key code { font-family: var(--mono); font-size: 12.5px; color: var(--ink); }
.minicard__key svg { width: 15px; height: 15px; flex: none; color: var(--muted); }
.minicard__key:hover { border-color: var(--brand); }
.minicard__key:hover svg { color: var(--brand); }
.minicard__key.is-copied { border-style: solid; border-color: var(--brand); }
.minicard__key.is-copied code { color: var(--brand); }
.minicard__status { align-self: flex-start; margin-top: 2px; font-size: 12.5px; font-weight: 600; color: var(--brand); }
.minicard__status[data-status="answered"], .minicard__status[data-status="closed"] { color: var(--muted); }

/* A pricing button that has something to say — "Course is full", the reason an
   enrolment was refused. Same box, different words, no layout shift. */
.btn.is-saying { pointer-events: none; opacity: 0.85; }
.btn.is-unavailable { opacity: 0.55; cursor: not-allowed; }

/* ---------- Product price + buy (tiles & cards) ---------- */
.tile__buy { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--line); }
.tile__price { font-family: var(--display); font-size: 20px; font-weight: 600; color: var(--heading); letter-spacing: -0.02em; }
.tile__buy .btn { padding: 9px 18px; font-size: 14px; }

/* Dark variants */
:root[data-theme="dark"] .tile:hover { box-shadow: 0 22px 48px -28px rgba(0, 0, 0, 0.7), inset 0 0 0 1px var(--line); }
:root[data-theme="dark"] .price-card--featured { box-shadow: 0 30px 60px -30px rgba(0, 0, 0, 0.75); }
/* The glyph tints are washes over the card, so their ink has to lift off a
   dark card the way the light values lift off a white one — same hues, taken
   up rather than down. */
:root[data-theme="dark"] .price-glyph--blue { background: rgba(96, 158, 255, 0.18); color: #8fb8ff; }
:root[data-theme="dark"] .price-glyph--green { background: rgba(52, 197, 128, 0.18); color: #6ddba4; }
:root[data-theme="dark"] .price-glyph--purple { background: rgba(160, 120, 250, 0.18); color: #bda2fb; }
:root[data-theme="dark"] .price-glyph--orange { background: rgba(247, 160, 70, 0.2); color: #f5b878; }
:root[data-theme="dark"] .price-glyph--pink { background: rgba(240, 120, 185, 0.18); color: #f39ac9; }
:root[data-theme="dark"] .price-glyph--red { background: rgba(235, 100, 100, 0.18); color: #f09292; }
:root[data-theme="dark"] .price-mark--disc { background: #2fbd7a; color: #06231a; }
:root[data-theme="dark"] .authcard { box-shadow: 0 30px 70px -36px rgba(0, 0, 0, 0.8); }
:root[data-theme="dark"] .purchase__tag--license { color: var(--teal); }
:root[data-theme="dark"] .minicard__tag--license { color: var(--teal); }
:root[data-theme="dark"] .minicard:hover { box-shadow: 0 22px 46px -28px rgba(0, 0, 0, 0.75); }

/* ============================================================
   CART DRAWER + CHECKOUT
   ============================================================ */
.navctl--cart { position: relative; }
.navctl__badge {
  position: absolute; top: -4px; right: -4px;
  min-width: 18px; height: 18px; padding: 0 5px;
  display: grid; place-items: center;
  background: var(--brand); color: #fff;
  font-size: 11px; font-weight: 700; line-height: 1;
  border-radius: 999px; border: 2px solid var(--paper);
}

.cart {
  position: fixed; top: 0; right: 0; bottom: 0;
  z-index: 120;
  width: min(420px, 100vw);
  transform: translateX(100%);
  transition: transform 0.38s cubic-bezier(0.3, 0.7, 0, 1);
  background: var(--paper);
  border-left: 1px solid var(--line);
  box-shadow: -30px 0 60px -30px rgba(23, 24, 28, 0.4);
  display: flex; flex-direction: column;
}
.cart.is-open { transform: translateX(0); }
.cart__head { display: flex; align-items: center; justify-content: space-between; padding: 22px var(--gutter); border-bottom: 1px solid var(--line); }
.cart__head h2 { font-family: var(--display); font-size: 20px; font-weight: 600; color: var(--heading); letter-spacing: -0.015em; }
.cart__close { width: 40px; height: 40px; display: grid; place-items: center; border-radius: 50%; color: var(--ink); transition: background-color 0.2s; }
.cart__close:hover { background: var(--pill); }
.cart__close svg { width: 18px; height: 18px; }
.cart__body { flex: 1; overflow-y: auto; padding: 8px var(--gutter); }
.cart__empty { padding: 40px var(--gutter); text-align: center; color: var(--muted); font-size: 15px; }
.cartline { display: grid; grid-template-columns: 1fr auto; gap: 6px 14px; padding: 18px 0; border-bottom: 1px solid var(--line); align-items: center; }
.cartline__info h3 { font-family: var(--display); font-size: 15.5px; font-weight: 600; color: var(--heading); }
.cartline__unit { font-size: 13px; color: var(--muted); }
.cartline__qty { display: inline-flex; align-items: center; gap: 6px; }
.qtybtn { width: 26px; height: 26px; display: grid; place-items: center; border-radius: 8px; background: var(--pill); color: var(--ink); font-size: 16px; line-height: 1; transition: background-color 0.2s; }
.qtybtn:hover { background: #e6e7eb; }
.qtybtn__n { min-width: 20px; text-align: center; font-weight: 600; font-size: 14px; }
.cartline__end { grid-column: 2; text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.cartline__total { font-family: var(--display); font-weight: 600; color: var(--heading); }
.cartline__rm { font-size: 12.5px; color: var(--muted); transition: color 0.2s; }
.cartline__rm:hover { color: #c0392b; }
.cart__foot { padding: 20px var(--gutter) calc(20px + env(safe-area-inset-bottom)); border-top: 1px solid var(--line); }
.cart__row { display: flex; justify-content: space-between; font-family: var(--display); font-size: 18px; font-weight: 600; color: var(--heading); }
.cart__vatnote { font-size: 12.5px; color: var(--muted); margin: 6px 0 16px; }
.cart__foot .btn { width: 100%; justify-content: center; }
.cart-backdrop { position: fixed; inset: 0; z-index: 110; background: rgba(23, 24, 28, 0.4); opacity: 0; visibility: hidden; pointer-events: none; transition: opacity 0.3s, visibility 0.3s; }
.cart-backdrop.is-open { opacity: 1; visibility: visible; pointer-events: auto; }
@media (prefers-reduced-motion: reduce) { .cart, .cart-backdrop { transition: none; } }

/* ---------- Sign-in dialog (the nav CTA) ---------- */
/* The same card login.html uses, floated over whatever page it was opened
   from — js/layout.js injects the markup, js/auth.js wires it. */
.authmodal { position: fixed; inset: 0; z-index: 130; }
.authmodal[hidden] { display: none; }
.authmodal__backdrop {
  position: absolute; inset: 0;
  background: rgba(23, 24, 28, 0.34);
  -webkit-backdrop-filter: blur(16px) saturate(1.1);
  backdrop-filter: blur(16px) saturate(1.1);
  opacity: 0;
  transition: opacity 0.3s;
}
/* Browsers without backdrop-filter get a heavier wash instead, so the card
   still separates from the page behind it. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .authmodal__backdrop { background: rgba(23, 24, 28, 0.62); }
}
/* Its own scroller, so a tall card (phone + OTP, an error message) stays
   reachable on a short viewport without the page behind it moving. */
.authmodal__scroll {
  position: relative;
  height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  padding: max(80px, 12vh) var(--gutter) 40px;
}
.authmodal__card {
  margin: auto;
  opacity: 0;
  transform: translateY(14px) scale(0.97);
  transition: opacity 0.28s, transform 0.4s cubic-bezier(0.3, 0.7, 0, 1);
}
.authmodal.is-open .authmodal__backdrop { opacity: 1; }
.authmodal.is-open .authmodal__card { opacity: 1; transform: none; }
.authmodal__card .authcard__title { padding-right: 46px; }
.authmodal__close {
  position: absolute; top: 14px; right: 14px;
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: var(--muted);
  transition: background-color 0.2s, color 0.2s;
}
.authmodal__close:hover { background: var(--pill); color: var(--ink); }
.authmodal__close svg { width: 17px; height: 17px; }
:root[data-theme="dark"] .authmodal__backdrop { background: rgba(0, 0, 0, 0.5); }
@media (prefers-reduced-motion: reduce) {
  .authmodal__backdrop, .authmodal__card { transition: none; }
}

/* Checkout page */
.checkout { max-width: calc(1080px + 2 * var(--gutter)); margin: 0 auto; padding: clamp(120px, 16vh, 180px) var(--gutter) var(--section-y); }
.checkout__title { font-family: var(--display); font-size: clamp(30px, 3.6vw, 48px); font-weight: 600; letter-spacing: -0.03em; color: var(--heading); margin-bottom: clamp(26px, 4vh, 44px); }
.checkout__grid { display: grid; grid-template-columns: 1fr 380px; gap: clamp(24px, 4vw, 56px); align-items: start; }
@media (max-width: 820px) { .checkout__grid { grid-template-columns: 1fr; } }
.co-card { border: 1px solid var(--line); border-radius: 22px; padding: clamp(22px, 3vw, 32px); background: var(--paper); }
.co-card + .co-card { margin-top: 20px; }
.co-card h2 { font-family: var(--display); font-size: 19px; font-weight: 600; color: var(--heading); margin-bottom: 18px; letter-spacing: -0.015em; }
.co-summary { position: sticky; top: 96px; }
.co-line { display: flex; justify-content: space-between; gap: 14px; padding: 10px 0; font-size: 14.5px; color: var(--ink); border-bottom: 1px solid var(--line); }
.co-line__name em { font-style: normal; color: var(--muted); }
.co-line__price { font-weight: 600; white-space: nowrap; }
.co-totals { margin-top: 16px; display: flex; flex-direction: column; gap: 9px; }
.co-totals__row { display: flex; justify-content: space-between; font-size: 14.5px; color: var(--muted); }
.co-totals__row--grand { font-family: var(--display); font-size: 20px; font-weight: 600; color: var(--heading); margin-top: 6px; padding-top: 12px; border-top: 1px solid var(--line); }
.co-pay { display: flex; align-items: center; gap: 12px; padding: 14px 16px; background: var(--pill); border-radius: 12px; }
.co-pay__card { font-family: var(--mono); font-size: 14px; color: var(--ink); }
.co-pay__ic { width: 34px; height: 22px; border-radius: 4px; background: linear-gradient(135deg, var(--brand), var(--brand-dark)); flex: none; }
.co-demo { display: flex; gap: 9px; align-items: flex-start; margin-top: 16px; font-size: 12.5px; line-height: 1.5; color: var(--muted); }
.co-demo svg { width: 16px; height: 16px; flex: none; margin-top: 1px; color: var(--brand); }
.co-place { width: 100%; justify-content: center; margin-top: 18px; }
.co-confirm { text-align: center; max-width: 520px; margin: 0 auto; padding: clamp(30px, 6vh, 70px) 0; }
.co-confirm__ic { width: 66px; height: 66px; margin: 0 auto 22px; display: grid; place-items: center; border-radius: 50%; background: rgba(14, 143, 200, 0.14); color: var(--brand); }
.co-confirm__ic svg { width: 34px; height: 34px; }
.co-confirm h1 { font-family: var(--display); font-size: clamp(28px, 3.4vw, 42px); font-weight: 600; letter-spacing: -0.03em; color: var(--heading); }
.co-confirm p { margin-top: 12px; color: var(--muted); font-size: 15.5px; }
.co-confirm code { font-family: var(--mono); color: var(--ink); background: var(--pill); padding: 2px 8px; border-radius: 6px; }
.co-confirm .btn { margin-top: 26px; }
.co-empty { text-align: center; padding: clamp(40px, 8vh, 90px) 0; color: var(--muted); }
.co-empty .btn { margin-top: 18px; }

/* Cart / checkout dark variants */
:root[data-theme="dark"] .qtybtn:hover { background: #1c2d3d; }
:root[data-theme="dark"] .cart-backdrop { background: rgba(0, 0, 0, 0.6); }
:root[data-theme="dark"] .cart { box-shadow: -30px 0 60px -30px rgba(0, 0, 0, 0.8); }

/* Lenis smooth-scroll: required so page height stays natural and the
   library's rAF loop owns scrolling instead of native smooth behavior. */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }
.lenis.lenis-smooth iframe { pointer-events: none; }

/* ---------- Solutions: vendor / family / licence pages ---------- */

/* Body copy blocks on the overview sections. */
.prose { max-width: 74ch; }
.prose p { font-size: clamp(15.5px, 1.2vw, 17px); line-height: 1.72; color: var(--ink); }
.prose p + p { margin-top: 14px; }

/* "Why choose / why buy" bullets. Two shapes: a heading with detail, or a
   single flowing sentence with a bolded lead-in (see bulletList in pages.js). */
.vlist { list-style: none; display: grid; gap: clamp(16px, 2vw, 26px);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); margin: 0; padding: 0; }
.vlist li {
  border: 1px solid var(--line); border-radius: 18px;
  padding: clamp(20px, 2.2vw, 28px); background: var(--paper);
  transition: border-color 0.3s, transform 0.3s cubic-bezier(0.3, 0.7, 0, 1);
}
.vlist li:hover { transform: translateY(-3px); border-color: var(--brand); }
.vlist h3 { font-family: var(--display); font-size: 17px; font-weight: 600; color: var(--heading); margin-bottom: 8px; }
.vlist p { font-size: 14.8px; line-height: 1.65; color: var(--muted); }
.vlist p b { color: var(--heading); font-weight: 600; }

/* Product family cards on the vendor page. */
.famgrid { display: grid; gap: clamp(16px, 2vw, 24px);
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); }
.famcard {
  display: flex; flex-direction: column; gap: 10px;
  border: 1px solid var(--line); border-radius: 20px;
  padding: clamp(22px, 2.4vw, 30px); background: var(--paper);
  transition: border-color 0.3s, transform 0.3s cubic-bezier(0.3, 0.7, 0, 1), box-shadow 0.3s;
}
.famcard:hover { transform: translateY(-4px); border-color: transparent; box-shadow: 0 22px 48px -30px rgba(23, 24, 28, 0.42); }
.famcard__ic { width: 40px; height: 40px; display: grid; place-items: center; border-radius: 11px; background: var(--pill); overflow: hidden; }
.famcard__ic img { width: 22px; height: 22px; object-fit: contain; }
.famcard__ic svg { width: 21px; height: 21px; color: var(--brand); }
.famcard__name { font-family: var(--display); font-size: 18px; font-weight: 600; color: var(--heading); }
.famcard__desc { font-size: 14.3px; line-height: 1.6; color: var(--muted); flex: 1; }
.famcard__n { font-size: 12.5px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--brand); }

/* Label / value rows — the backbone of the family and licence pages. */
.specs { display: grid; gap: 0; margin-top: clamp(24px, 3vh, 38px); border-top: 1px solid var(--line); }
.specs--lead { margin-top: 0; border-top: 0; }
.spec { display: grid; grid-template-columns: minmax(160px, 22%) 1fr; gap: clamp(16px, 3vw, 40px);
  padding: clamp(18px, 2.2vh, 26px) 0; border-bottom: 1px solid var(--line); }
.spec__k { font-size: 12.5px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); padding-top: 2px; }
.spec__v p { font-size: 15.5px; line-height: 1.7; color: var(--ink); }
@media (max-width: 640px) { .spec { grid-template-columns: 1fr; gap: 8px; } }

/* The commercial facts, sat directly above the tiers they qualify. Deliberately
   a plain list rather than the fact strip: the strip is the page's "reference
   detail" device and using it twice for two different jobs was what made the
   vendor pages hard to scan. */
.meter {
  list-style: none; margin: 0 0 clamp(24px, 3vh, 34px); padding: 0;
  display: grid; gap: clamp(10px, 1.4vw, 16px);
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
.meter li {
  font-size: 14.5px; line-height: 1.6; color: var(--muted);
  padding-left: 15px; border-left: 2px solid color-mix(in srgb, var(--brand) 35%, transparent);
}
.meter b {
  display: block; margin-bottom: 3px;
  font-size: 11.5px; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--brand);
}

/* Tier ladder. Shown where the catalogue has no priced plan rows, which is most
   vendors — the tiers are real, the price is a conversation. */
.tiers {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: clamp(12px, 1.6vw, 18px);
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}
.tier {
  position: relative; display: flex; flex-direction: column; gap: 6px;
  padding: clamp(16px, 2vw, 22px);
  border: 1px solid var(--line); border-radius: 16px; background: var(--paper);
}
.tier b {
  font-family: var(--display); font-weight: 600; letter-spacing: -0.01em;
  font-size: 17px; color: var(--heading);
}
:root[data-theme="dark"] .tier b { color: var(--ink); }
.tier em { font-style: normal; font-size: 14px; line-height: 1.5; color: var(--muted); }
.tier--pick { border-color: color-mix(in srgb, var(--brand) 55%, transparent); }
.tier__tag {
  margin-top: 4px; align-self: flex-start;
  padding: 4px 10px; border-radius: 999px;
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  color: var(--brand); font-size: 11.5px; font-weight: 600;
}
.tiers__note {
  margin-top: clamp(18px, 2.4vh, 26px);
  font-size: 14.5px; line-height: 1.7; color: var(--muted); max-width: 68ch;
}
.tiers__note a { color: var(--brand); font-weight: 600; }

/* "Included with X" — shown on the family pages of vendors that sell a plan
   rather than a product, so the page doesn't read as a listing with no price. */
.incnote {
  display: inline-flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin-top: 18px; padding: 10px 16px; border-radius: 999px;
  background: color-mix(in srgb, var(--brand) 10%, transparent);
  font-size: 14px; line-height: 1.5; color: var(--muted);
}
.incnote b { color: var(--brand); font-weight: 600; }

/* Fact strip — the short factual lines left over once the substance of a page
   has become illustrated sections. Deliberately small and scannable: these are
   things a buyer checks, not things they read. */
.factstrip {
  display: grid; gap: clamp(14px, 2vw, 28px);
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  margin-top: clamp(24px, 3vh, 38px);
  padding-top: clamp(20px, 2.5vh, 30px);
  border-top: 1px solid var(--line);
}
.factstrip__i { min-width: 0; }
.factstrip dt {
  font-size: 11.5px; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--brand); margin-bottom: 7px;
}
.factstrip dd { margin: 0; font-size: 14px; line-height: 1.6; color: var(--muted); }

/* Why-buy cards. The same five points as the old bullet list, laid out so the
   eye can take them three at a time instead of top to bottom. */
.whygrid {
  display: grid; gap: clamp(16px, 2vw, 26px);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.whygrid__i {
  padding: clamp(18px, 2vw, 24px);
  border: 1px solid var(--line); border-radius: 16px; background: var(--paper);
}
.whygrid__i h3 {
  font-family: var(--display); font-weight: 600; letter-spacing: -0.015em;
  font-size: 17px; line-height: 1.3; color: var(--heading);
}
:root[data-theme="dark"] .whygrid__i h3 { color: var(--ink); }
.whygrid__i p { margin-top: 8px; font-size: 14.5px; line-height: 1.65; color: var(--muted); }

/* Portfolio table. Scrolls inside itself rather than pushing the page wide. */
.ptable-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: 16px; }
.ptable { width: 100%; border-collapse: collapse; min-width: 520px; }
.ptable th, .ptable td { text-align: left; padding: 14px 18px; font-size: 14.8px; line-height: 1.6; border-bottom: 1px solid var(--line); }
.ptable thead th { font-size: 12.5px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); background: var(--pill); }
.ptable tbody tr:last-child td { border-bottom: 0; }
.ptable td b { color: var(--heading); }
.ptable td { color: var(--muted); }

/* FAQs — native <details> so they work without JS. */
.faqs { display: flex; flex-direction: column; border-top: 1px solid var(--line); }
.faq { border-bottom: 1px solid var(--line); }
.faq summary {
  list-style: none; cursor: pointer; padding: 18px 40px 18px 0; position: relative;
  font-family: var(--display); font-size: clamp(15.5px, 1.4vw, 17.5px); font-weight: 600;
  color: var(--heading); transition: color 0.2s;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--brand); }
.faq summary::after {
  content: ""; position: absolute; right: 6px; top: 50%;
  width: 9px; height: 9px; margin-top: -6px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg); transition: transform 0.28s cubic-bezier(0.3, 0.7, 0, 1);
}
.faq[open] summary::after { transform: rotate(-135deg); margin-top: -2px; }
.faq p { padding: 0 0 20px; font-size: 15px; line-height: 1.7; color: var(--muted); max-width: 74ch; }

/* Related-product chips. */
.chips { display: flex; flex-wrap: wrap; gap: 10px; }
.chip-link {
  display: inline-flex; align-items: center; padding: 9px 17px;
  border: 1px solid var(--line); border-radius: 999px;
  font-size: 14px; font-weight: 600; color: var(--ink);
  transition: border-color 0.2s, color 0.2s, transform 0.25s cubic-bezier(0.3, 0.7, 0, 1);
}
a.chip-link:hover { border-color: var(--brand); color: var(--brand); transform: translateY(-2px); }
.chip-link--flat { color: var(--muted); cursor: default; }

/* Legacy / maintenance-mode marker. */
.tag {
  display: inline-block; vertical-align: middle;
  padding: 3px 9px; border-radius: 999px;
  font-family: var(--body); font-size: 11px; font-weight: 700;
  letter-spacing: 0.05em; text-transform: uppercase;
}
.tag--legacy { background: rgba(214, 137, 16, 0.14); color: #a86a05; border: 1px solid rgba(214, 137, 16, 0.3); }
:root[data-theme="dark"] .tag--legacy { background: rgba(240, 170, 60, 0.16); color: #f0c076; }

.notice { margin-top: 18px; padding: 13px 16px; border-radius: 12px; font-size: 14.3px; line-height: 1.6; max-width: 70ch; }
.notice--warn { background: rgba(214, 137, 16, 0.1); border: 1px solid rgba(214, 137, 16, 0.28); color: var(--ink); }
:root[data-theme="dark"] .notice--warn { background: rgba(240, 170, 60, 0.12); }
/* Stating that something isn't sold on its own is information, not a warning —
   it shouldn't look like a problem with the product. */
.notice--info {
  background: color-mix(in srgb, var(--brand) 9%, transparent);
  border: 1px solid color-mix(in srgb, var(--brand) 26%, transparent);
  color: var(--ink);
}
.notice b { color: var(--heading); font-weight: 600; }
:root[data-theme="dark"] .notice b { color: var(--ink); }

/* Prices on rail cards sit closer to the name than the generic count does. */
.railcard__price { color: var(--brand); font-weight: 600; }

/* ---------- Legal pages (privacy / terms) ---------- */
.legal { max-width: 760px; margin: 0 auto; padding: 0 var(--gutter) var(--section-y); }
.legal__updated { color: var(--muted); font-size: 14px; margin-bottom: 40px; }
.legal h2 {
  font-family: var(--display); font-size: clamp(21px, 2.1vw, 27px);
  font-weight: 600; letter-spacing: -0.015em; color: var(--heading);
  margin: 44px 0 14px;
}
.legal h2:first-of-type { margin-top: 0; }
.legal p { font-size: 15.5px; line-height: 1.7; color: var(--ink); margin-bottom: 14px; }
.legal ul { margin: 0 0 14px; padding-left: 20px; display: flex; flex-direction: column; gap: 8px; }
.legal li { font-size: 15.5px; line-height: 1.65; color: var(--ink); }
.legal li b, .legal p b { color: var(--heading); }
.legal a { color: var(--brand); font-weight: 600; }
.legal a:hover { text-decoration: underline; }
