/*
 * chrome.css — the site chrome: header and footer, on EVERY page.
 *
 * WHY THIS FILE EXISTS AND landing.css DOES NOT COVER IT
 * ---------------------------------------------------------------------------
 * The header and the footer used to be styled inside landing.css, which is
 * enqueued on the front page only. Every other page — shop, cart, checkout,
 * account, /activar and the five legal pages — loads global.css and nothing
 * else, so lifting the markup out of the shortcode without lifting the CSS out
 * of landing.css would have produced an unstyled navbar on nine tenths of the
 * site.
 *
 * The two rejected alternatives, and why:
 *
 *   a) Enqueue landing.css everywhere.
 *      landing.css opens with a verbatim port of the approved design, and that
 *      port carries `*, *::before, *::after { margin: 0; padding: 0 }`,
 *      `body { overflow-x: hidden }` and an @import of Google Fonts. Applying
 *      that reset to a WooCommerce checkout or to an editor-authored legal page
 *      flattens every paragraph and list in the document. It would also ship
 *      1400 lines of hero, pricing and demo CSS to pages that have none of it.
 *
 *   b) Move the chrome rules out of landing.css into this file, so there is one
 *      owner, and enqueue this file everywhere.
 *      This is the right end state and it is NOT what shipped today, for one
 *      reason: landing.css is being rewritten in parallel (its PART 5 adds the
 *      mobile-first geometry for the landing's body). Cutting 500 lines out of
 *      the middle of a file another process is appending to is how you lose
 *      somebody's work. The removal is a follow-up, not a risk worth taking in
 *      the same change that puts the header on nine new pages.
 *
 * WHAT SHIPPED, AND THE RULE THAT KEEPS IT HONEST
 * ---------------------------------------------------------------------------
 * ONE PAGE, ONE STYLESHEET FOR THE CHROME. They never both load:
 *
 *   front page      → landing.css (PART 1 + PART 4) dresses the chrome.
 *   everything else → this file dresses the chrome.
 *
 * functions.php enqueues this file only when landing.css is NOT enqueued, so
 * there is no cascade to reason about, no specificity tie to lose and no way
 * for this file to override the landing work in flight next door.
 *
 * PARTS B and C ARE A COPY. They are the header and footer rules of
 * landing.css PART 1, PART 2, PART 3 and PART 4, reproduced value for value.
 * A change to the header must be made in BOTH files until the follow-up merges
 * them. That is the price of not racing a concurrent rewrite, and it is
 * written here rather than discovered later.
 *
 * HOW IT IS WRITTEN
 * ---------------------------------------------------------------------------
 * MOBILE FIRST, without exception. Every base rule describes the small screen
 * and min-width queries build the desktop up from it. There is not one
 * max-width rule in this file.
 *
 * THE NO-JAVASCRIPT CONTRACT
 * ---------------------------------------------------------------------------
 * Nothing here hides content by default waiting for a class to be added. The
 * menu is a native <details> disclosure, so the browser owns its open state;
 * assets/js/chrome.js only adds the focus trap, the scroll lock, Escape and the
 * aria-expanded sync. This project has already shipped a blank page once by
 * letting CSS hide content that only JavaScript could bring back.
 */

/* ==========================================================================
   PART A — design tokens

   Mirror of landing.css PART 1's :root, restricted to what the chrome reads.
   Pages other than the landing never load that file, so the values have to be
   declared somewhere they can reach. On the landing this block re-declares
   identical values after landing.css and is therefore a no-op.
   ========================================================================== */

:root {
  --bg-body: #f6f9fc;
  --bg-surface: #ffffff;
  --bg-surface-elevated: #f8fafc;
  --border-subtle: #e2e8f0;

  --stripe-indigo: #635bff;
  --stripe-teal: #00d4b4;

  --text-main: #0a2540;
  --text-muted: #425466;
  --text-dim: #6b7c93;

  --shadow-card: 0 15px 35px rgba(50, 50, 93, 0.06), 0 5px 15px rgba(0, 0, 0, 0.04);

  --font-sans: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;
  --font-heading: 'Space Grotesk', var(--font-sans);

  /* Chrome can force its own dark rendering on any site that does not declare
     a colour scheme. This design ships its own dark theme via [data-theme], so
     declaring the scheme opts out of the browser's guesswork. */
  color-scheme: only light;
}

[data-theme="dark"] {
  --bg-body: #0a2540;
  --bg-surface: #0e3054;
  --bg-surface-elevated: #163d66;
  --border-subtle: rgba(255, 255, 255, 0.12);
  --text-main: #ffffff;
  --text-muted: #adbdcc;
  --text-dim: #8898aa;
  color-scheme: dark;
}

/* Dark values as a CLASS rather than as a document state.
   /activar paints its own near-black canvas from activate.css and cannot use
   [data-theme], because that attribute belongs to the visitor's day/night
   choice. Without this the light glass bar sat on a black page with navy text
   on it. PHP adds the class through the ddb_chrome_classes filter. */
.ddb-chrome-dark {
  --bg-surface: #0e3054;
  --bg-surface-elevated: #163d66;
  --border-subtle: rgba(255, 255, 255, 0.12);
  --text-main: #ffffff;
  --text-muted: #adbdcc;
  --text-dim: #8898aa;
}

/* ==========================================================================
   PART B — chrome primitives

   Values copied from landing.css PART 1 (navbar, brand, buttons, footer) and
   PART 2/PART 3 (theme-toggle icons, inline language pill, footer columns).
   Nothing here changes a colour, a shadow, a radius or a gradient.
   ========================================================================== */

/* --- Local reset ----------------------------------------------------------
   landing.css PART 1 zeroes every margin in the document. That reset only
   ships on the landing, so the chrome carries its own — scoped to the chrome,
   so it can never reach the editor's content on a legal page. Without it the
   footer's <p> and <ul> pick up the user agent's margins and bullets. */

.navbar,
.navbar *,
.navbar *::before,
.navbar *::after,
.footer,
.footer *,
.footer *::before,
.footer *::after {
  box-sizing: border-box;
}

.navbar h1, .navbar h2, .navbar p, .navbar ul, .navbar ol, .navbar li,
.footer h1, .footer h2, .footer p, .footer ul, .footer ol, .footer li {
  margin: 0;
  padding: 0;
}

.navbar ul,
.footer ul {
  list-style: none;
}

.navbar svg,
.footer svg {
  flex-shrink: 0;
}

/* The parent theme sets the document font from theme.json. The chrome states
   its own, so the bar and the footer read identically on the landing and on a
   WooCommerce screen. */
.navbar,
.footer {
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.6;
}

/* --- The bar -------------------------------------------------------------- */

.navbar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 1000;
  background: rgba(255, 255, 255, 0.85);
  -webkit-backdrop-filter: blur(20px);
          backdrop-filter: blur(20px);
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
  /* The source wrote `transition: all`, which also animates `top` when the
     admin bar changes height and `padding` at every breakpoint. Same visual
     result, none of the accidents. */
  transition: background-color 0.3s ease, border-color 0.3s ease;
}

[data-theme="dark"] .navbar,
.navbar.ddb-chrome-dark {
  background: rgba(10, 37, 64, 0.85);
  border-bottom-color: rgba(255, 255, 255, 0.1);
}

.navbar-container {
  margin: 0 auto;
}

.nav-brand {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  text-decoration: none;
  color: var(--text-main);
  font-weight: 800;
  font-size: 1.35rem;
  font-family: var(--font-heading);
  letter-spacing: -0.03em;
}

.brand-icon {
  width: 36px;
  height: 36px;
  min-width: 36px;
  min-height: 36px;
  border-radius: 10px;
  background: var(--stripe-indigo);
  color: #ffffff;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 12px rgba(99, 91, 255, 0.3);
}

.nav-link {
  text-decoration: none;
  color: var(--text-muted);
  font-size: 0.95rem;
  font-weight: 600;
  transition: color 0.2s ease;
}

.nav-link:hover {
  color: var(--text-main);
}

/* --- Buttons -------------------------------------------------------------- */

.btn-theme-toggle {
  background: rgba(0, 0, 0, 0.05);
  border: 1px solid var(--border-subtle);
  color: var(--text-main);
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}

.btn-theme-toggle:hover {
  background: rgba(0, 0, 0, 0.1);
}

.ddb-chrome-dark .btn-theme-toggle { background: rgba(255, 255, 255, 0.08); }
.ddb-chrome-dark .btn-theme-toggle:hover { background: rgba(255, 255, 255, 0.14); }

/* Both icons ship in the markup and CSS decides which is visible. The source
   swapped innerHTML from JavaScript instead, which meant the button was empty
   until the script ran and lost its icon entirely if the script failed.
   (Copy of landing.css PART 2.) */
.btn-theme-toggle .theme-icon { display: none; }
[data-theme="light"] .btn-theme-toggle .theme-icon--moon { display: block; }
[data-theme="dark"]  .btn-theme-toggle .theme-icon--sun  { display: block; }

/* No data-theme yet (first paint, before the script runs): show the moon, which
   matches the default light canvas. */
html:not([data-theme]) .btn-theme-toggle .theme-icon--moon { display: block; }

.btn-primary {
  background: var(--stripe-indigo);
  color: #ffffff;
  padding: 0.65rem 1.35rem;
  border-radius: 50px;
  font-weight: 700;
  font-size: 0.9rem;
  text-decoration: none;
  border: none;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(99, 91, 255, 0.35);
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
              box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1),
              background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  white-space: nowrap;
  flex-shrink: 0;
}

.btn-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 22px rgba(99, 91, 255, 0.45);
  background: #534be0;
}

/* --- Language pill, inline form -------------------------------------------
   global.css positions the switcher as a fixed top-right overlay, which was the
   only form it had on pages with no navbar. Every page has a navbar now, so
   inside the bar it is always an inline control.
   (Copy of landing.css PART 3.) */

.ddb-lang-switcher--inline {
  position: static;
  inset: auto;
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  padding: 0.2rem;
  border-radius: 999px;
  background: rgba(10, 37, 64, 0.05);
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

[data-theme="dark"] .ddb-lang-switcher--inline,
.ddb-chrome-dark .ddb-lang-switcher--inline { background: rgba(255, 255, 255, 0.08); }

.ddb-lang-switcher--inline .ddb-lang-btn {
  padding: 0.3rem 0.6rem;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  text-decoration: none;
  background: transparent;
}

.ddb-lang-switcher--inline .ddb-lang-btn[aria-current="true"] {
  background: var(--bg-surface);
  color: var(--text-main);
  box-shadow: 0 1px 2px rgba(50, 50, 93, 0.12);
}

[data-theme="dark"] .ddb-lang-switcher--inline .ddb-lang-btn[aria-current="true"],
.ddb-chrome-dark .ddb-lang-switcher--inline .ddb-lang-btn[aria-current="true"] {
  background: rgba(255, 255, 255, 0.16);
  color: #ffffff;
}

/* --- Footer ---------------------------------------------------------------
   Copy of landing.css PART 1 and PART 2, with the mobile-first corrections
   that PART 5 makes to the same selectors: one-column grid below 560px, two
   columns from there, three from 720px, and 44px touch targets on the links
   until a pointer-sized viewport takes over at 1024px. The two copies are
   value for value identical on purpose — the footer must not read differently
   on the privacy policy than it does on the landing. */

.footer {
  border-top: 1px solid var(--border-subtle);
  width: min(92%, 1140px);
  margin: 0 auto;
  padding-block: 3rem 1.5rem;
  color: var(--text-main);
}

@media (min-width: 640px) {
  .footer {
    width: min(90%, 1140px);
    padding-block: 4rem 2rem;
  }
}

/* A one-column grid is what the flex row rendered anyway, since .footer-nav
   inside it is width: 100%. Stating it removes the guesswork, and align-items:
   start stops a short brand column from floating in the middle of a tall
   navigation block. */
.footer-content {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  gap: 2rem;
  margin-bottom: 2rem;
}

.footer-nav {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 2rem;
  width: 100%;
  max-width: 1100px;
  margin-inline: auto;
  text-align: left;
}

@media (min-width: 560px) {
  /* Two columns are safe here and nowhere else: these are short link labels,
     not cards, and there are three groups of them. */
  .footer-nav { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 720px) {
  .footer-nav { grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(0, 1fr)); }
}

/* A grid item refuses to shrink below its content's minimum width unless it is
   told otherwise, and that is how one long word turns into a horizontal
   scrollbar for the whole page. */
.footer-brand-col,
.footer-col {
  min-width: 0;
}

.footer-brand-col { display: grid; gap: 0.85rem; align-content: start; }

.footer-tagline {
  max-width: 34ch;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--text-dim);
}

.footer-col { display: grid; gap: 0.7rem; align-content: start; }

.footer-col-title {
  font-size: 0.72rem;
  font-weight: 800;
  line-height: 1.4;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Fifteen links stacked 0.55rem apart are about 22px tall each — half a touch
   target, and the legal ones are exactly the links a phone user has to be able
   to hit. The row gap pays for the extra height, so the block ends up the size
   it already was. Scoped to .footer-list so the mailto in the bottom bar keeps
   its inline flow inside its sentence. */
.footer-list { display: grid; gap: 0; margin: 0; padding: 0; list-style: none; }

.footer-item { font-size: 0.9rem; line-height: 1.5; }

.footer-link {
  color: var(--text-dim);
  text-decoration: none;
  transition: color 0.2s ease;
}

.footer-list .footer-link {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding-block: 0.25rem;
}

.footer-link:hover,
.footer-link:focus-visible { color: var(--stripe-indigo); }

/* A legal document that is not published yet. Rendered as plain text so nobody
   clicks through to a 404. */
.footer-link--pending {
  color: var(--text-dim);
  opacity: 0.6;
  cursor: default;
}

.footer-list .footer-link--pending {
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
}

.footer-pending-note {
  display: block;
  margin-top: 0.4rem;
  font-size: 0.76rem;
  line-height: 1.5;
  color: var(--text-dim);
  opacity: 0.75;
}

@media (min-width: 1024px) {
  /* Pointer-sized viewport: the 44px minimum is a touch requirement, and
     paying for it here would only stretch the block. */
  .footer-list { gap: 0.55rem; }

  .footer-list .footer-link {
    display: inline-flex;
    min-height: 0;
    padding-block: 0;
  }

  .footer-list .footer-link--pending { display: flex; }
}

.footer-bottom {
  text-align: center;
  color: var(--text-dim);
  font-size: 0.88rem;
  border-top: 1px solid var(--border-subtle);
  padding-top: 1.5rem;
}

@media (min-width: 640px) {
  .footer-bottom { padding-top: 2rem; }
}

.footer-sep { opacity: 0.4; padding-inline: 0.4rem; }

.footer-company { font-size: 0.85rem; color: var(--text-dim); }

/* A 39-character address inside a centred sentence is the one string in the
   footer that can force a horizontal scrollbar at 320px. */
.footer-company .footer-link { overflow-wrap: anywhere; }

.footer-copyright { font-size: 0.85rem; color: var(--text-dim); }

.footer-disclaimer {
  margin-top: 0.5rem;
  font-size: 0.8rem;
  line-height: 1.6;
  color: var(--text-dim);
  opacity: 0.85;
}

/* Footer links have to survive the parent theme's own link colour, which is
   applied from theme.json at the same specificity. Stated explicitly so the
   outcome does not depend on which stylesheet the browser saw last. */
.footer .footer-link,
.footer .nav-brand { text-decoration: none; }

/* ==========================================================================
   PART C — the responsive header

   COPY of landing.css PART 4, value for value. Two things differ: the comments
   that said "PART 1" now name where PART 1 lives, and the script this pairs
   with is assets/js/chrome.js. Edit both copies or the header on the shop
   stops matching the header on the landing.

   WHY IT EXISTS
   -------------
   antigravityWeb/styles.css is 886 lines, of which 31 sit inside a media
   query: 3.5%. The design was drawn at 1440px and its entire answer for a
   phone was one line —

       @media (max-width: 980px) { .nav-links { display: none; } }

   — which hides the navigation and puts nothing in its place. On a 402px
   iPhone that left the brand, the ES/EN pill and the CTA fighting for one line
   until the button was clipped to "Ins...", and the six sections of the page
   were unreachable.
   ========================================================================== */

/* --------------------------------------------------------------------------
   C.1 — Shared geometry
   -------------------------------------------------------------------------- */

:root {
  /* Height of the WordPress admin bar. Zero for every visitor; only a
     logged-in user ever sees a non-zero value. Declared once here so the
     navbar's offset, the panel's max-height and the anchor scroll-margin all
     read the same number instead of repeating the 32/46 pair three times. */
  --ddb-nav-offset: 0px;

  /* One optical line for every control in the bar. The hamburger, the theme
     button, the language pill and the CTA all resolve to this height, which is
     also the 44px minimum touch target. */
  --ddb-nav-control: 44px;

  /* Rendered navbar height. Read by the anchor offsets, the mobile panel's
     max-height and the top padding of every page that is not the landing. */
  --ddb-nav-height: 4.25rem;

  /* Width the scrollbar leaves behind when the body scroll is locked. The
     script measures and publishes it; this default keeps the calc() honest
     when there is no script at all. */
  --ddb-scrollbar-gap: 0px;
}

/* WordPress's own admin-bar breakpoint, expressed mobile first: the bar is
   46px tall and static on small screens, 32px and fixed from 783px up. */
.admin-bar { --ddb-nav-offset: 46px; }

@media screen and (min-width: 783px) {
  .admin-bar { --ddb-nav-offset: 32px; }
}

@media (min-width: 640px) {
  :root { --ddb-nav-height: 5rem; }
}

/* The navbar is pinned at top: 0, so without this the admin bar sits on top of
   it and clips the brand. */
.admin-bar .navbar { top: var(--ddb-nav-offset); }

/* --------------------------------------------------------------------------
   C.2 — The bar itself
   -------------------------------------------------------------------------- */

.navbar {
  /* 1.1rem top and bottom spends 35px of a 650px-tall phone viewport before a
     single word of content. Give it back below 640px. */
  padding: 0.75rem 0;
}

@media (min-width: 640px) {
  .navbar { padding: 1.1rem 0; }
}

.navbar-container {
  /* 92% matches the landing's .section on phones and 90% matches .hero and
     .section from 640px up, so the brand always sits on the same optical
     margin as the content directly below it. */
  width: min(92%, 1140px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  min-width: 0;
}

@media (min-width: 640px) {
  .navbar-container { width: min(90%, 1140px); }
}

.navbar .nav-brand {
  /* The source pinned the brand at flex-shrink: 0, so at 320px it pushed the
     hamburger off the screen rather than yield a pixel. It may shrink now, and
     the label truncates instead of overflowing — the last-resort guard that
     makes a horizontal scrollbar impossible at any width in the 320-1920
     range. */
  flex: 0 1 auto;
  min-width: 0;
  white-space: nowrap;
  font-size: clamp(1rem, 0.7rem + 0.75vw, 1.35rem);
}

.nav-brand-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   C.3 — Base (phone): the disclosure menu IS the navigation

   The desktop row is not "hidden on mobile"; it is simply not built yet. It
   gets added back by the min-width block in C.6.
   -------------------------------------------------------------------------- */

.nav-links-wrap,
.nav-actions {
  display: none;
}

.nav-mobile {
  flex: 0 0 auto;
}

/* Hamburger ---------------------------------------------------------------- */

.nav-toggle {
  /* `display` is deliberately left at the user agent's list-item. Changing a
     <summary>'s display has historically broken the disclosure in WebKit, so
     the two icons are absolutely positioned inside the button instead, which
     centres them without touching it. */
  position: relative;
  width: var(--ddb-nav-control);
  height: var(--ddb-nav-control);
  border: 1px solid var(--border-subtle);
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.05);
  color: var(--text-main);
  cursor: pointer;
  list-style: none;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 0.2s ease;
}

.nav-toggle::-webkit-details-marker { display: none; }
.nav-toggle::marker { content: ""; }

.nav-toggle:hover { background: rgba(0, 0, 0, 0.1); }

[data-theme="dark"] .nav-toggle,
.ddb-chrome-dark .nav-toggle { background: rgba(255, 255, 255, 0.08); }
[data-theme="dark"] .nav-toggle:hover,
.ddb-chrome-dark .nav-toggle:hover { background: rgba(255, 255, 255, 0.14); }

.nav-toggle-icon {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* CSS owns the icon swap and reads the element's own open state, so the button
   is never blank and never needs a script to draw itself. */
.nav-mobile:not([open]) .nav-toggle-icon--close { display: none; }
.nav-mobile[open] .nav-toggle-icon--menu { display: none; }

/* Scrim and panel ---------------------------------------------------------- */

.nav-scrim,
.nav-panel {
  position: absolute;
  /* .navbar is position: fixed, so it is the containing block for both. The
     extra pixel clears its bottom border instead of sitting on top of it. */
  top: calc(100% + 1px);
  left: 0;
  right: 0;
}

.nav-scrim {
  height: 100vh;
  height: 100dvh;
  background: rgba(10, 37, 64, 0.45);
}

[data-theme="dark"] .nav-scrim,
.ddb-chrome-dark .nav-scrim { background: rgba(0, 0, 0, 0.6); }

.nav-panel {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 0.75rem clamp(1rem, 4vw, 2rem) 1.5rem;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border-subtle);
  box-shadow: var(--shadow-card);
  /* Landscape phones and short windows: the panel scrolls itself rather than
     running off the bottom of the screen. overscroll-behavior stops the page
     underneath from taking over the gesture once the panel reaches its end. */
  max-height: calc(100vh - var(--ddb-nav-height) - var(--ddb-nav-offset) - 1rem);
  max-height: calc(100dvh - var(--ddb-nav-height) - var(--ddb-nav-offset) - 1rem);
  overflow-y: auto;
  overscroll-behavior: contain;
  animation: ddbNavPanelIn 0.22s cubic-bezier(0.4, 0, 0.2, 1) both;
}

@keyframes ddbNavPanelIn {
  from { opacity: 0; transform: translateY(-0.5rem); }
  to   { opacity: 1; transform: none; }
}

.nav-panel-links {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav-panel-link {
  display: flex;
  align-items: center;
  /* Comfortably past the 44px minimum: these are the six links the visitor
     could not reach at all on a phone. */
  min-height: 48px;
  padding: 0.5rem 0.25rem;
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text-main);
  font-size: 1rem;
  font-weight: 600;
  text-decoration: none;
  transition: color 0.2s ease;
}

.nav-panel-links li:last-child .nav-panel-link { border-bottom: 0; }

.nav-panel-link:hover,
.nav-panel-link:focus-visible { color: var(--stripe-indigo); }

.nav-panel-controls {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.nav-panel-cta {
  width: 100%;
  /* Its height is set in C.4, which has to come after .navbar .btn-primary. */
}

/* --------------------------------------------------------------------------
   C.4 — The three controls, sized from one token

   This is the desktop complaint in the brief: the theme button was not on the
   same line as anything else. It was not a vertical-centring bug — every
   control was centred correctly, they were just three different heights.
   -------------------------------------------------------------------------- */

.navbar .btn-theme-toggle {
  /* The source sizes this 38px, which never matched the 44px CTA beside it. */
  width: var(--ddb-nav-control);
  height: var(--ddb-nav-control);
  min-width: var(--ddb-nav-control);
  min-height: var(--ddb-nav-control);
  flex: 0 0 auto;
}

.navbar .btn-primary {
  min-height: var(--ddb-nav-control);
}

/* global.css sets .ddb-lang-btn { min-width: 44px; min-height: 44px } for the
   overlay form of the switcher, which made the pill about 50px tall inside its
   own padding — taller than everything around it. Size it from the shared
   token instead. */
.navbar .ddb-lang-switcher--inline {
  height: var(--ddb-nav-control);
  padding: 0.2rem;
  flex: 0 0 auto;
}

.navbar .ddb-lang-switcher--inline .ddb-lang-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Height comes from the pill so the control matches the CTA exactly; the
     width stays generous for the pointer. This copy is only ever displayed
     from the desktop breakpoint up, where the input device is a mouse and
     WCAG 2.2 AA asks for 24x24, not 44x44. */
  min-width: 38px;
  min-height: 0;
  height: 100%;
}

/* Everything inside the panel is touch-first, so it takes the full 44px in
   both axes rather than the bar's pointer-friendly compromise.

   These rules have to sit AFTER .navbar .btn-primary above, not up in C.3 with
   the rest of the panel: both selectors carry two classes, so specificity ties
   and source order is what decides. A .nav-panel-cta rule declared earlier
   silently lost its height to the bar's 44px. */
.nav-panel .ddb-lang-switcher--panel {
  height: auto;
  padding: 0.25rem;
}

.nav-panel .ddb-lang-switcher--panel .ddb-lang-btn {
  min-width: 52px;
  min-height: 44px;
  height: auto;
}

.nav-panel .nav-panel-cta {
  min-height: 48px;
}

/* --------------------------------------------------------------------------
   C.5 — The CTA label in the bar

   MEASURED DECISION, not an oversight. The approved design carried five links
   and no language switcher. This build carries six links plus an ES/EN pill,
   which is roughly 200px more inside the same 1140px container. With the full
   "Añadir al navegador" label the row does not fit at ANY viewport width,
   because the container caps at 1140px and stops growing at 1266px — so the
   long label would still overflow at 1920px. The bar therefore keeps the short
   label everywhere and the full sentence lives where there is room for it: the
   mobile panel's full-width CTA and the hero.

   Both spans stay in the markup so this is one CSS decision, not a PHP change.
   -------------------------------------------------------------------------- */

.btn-text-mobile { display: none; }

.nav-actions .btn-text-desktop { display: none; }
.nav-actions .btn-text-mobile { display: inline; }

/* --------------------------------------------------------------------------
   C.6 — Desktop bar, from 1140px

   WHY 1140 AND NOT 980. Eight things share this row: brand, six links, ES/EN
   pill, theme button and CTA. At 1024px the container is 922px wide and the
   row needs well over a thousand. The old 980px breakpoint was not a measured
   number, it was the width at which the author stopped looking. 1140px is
   where the full row fits with real margin, and every width below it now gets
   a menu that works instead of no navigation at all.

   assets/js/chrome.js declares NAV_DESKTOP_QUERY = "(min-width: 1140px)".
   The two MUST be changed together.
   -------------------------------------------------------------------------- */

@media (min-width: 1140px) {
  .nav-mobile { display: none; }

  .navbar-container {
    /* Three tracks instead of space-between, and the FLEXIBLE one is the
       middle. This is the "reparto irregular" from the brief, measured: the
       action group is 272px wide against a 208px brand, so pinning the links
       to the geometric centre of the bar (1fr auto 1fr) leaves 72px of air on
       the left and 8px on the right at 1140px — the links almost touching the
       language pill. Letting the brand and the actions take their content
       width and giving the leftover to the middle track centres the link row
       inside the space that actually remains, which lands about 60px on each
       side. Symmetric, and it stays symmetric when ES/EN changes the labels. */
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    column-gap: 1.25rem;
  }

  .nav-links-wrap {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 0;
  }

  .nav-links {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 1rem;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .nav-link {
    white-space: nowrap;
    font-size: 0.85rem;
  }

  .nav-actions {
    display: flex;
    align-items: center;
    justify-self: end;
    gap: 0.6rem;
  }
}

/* Past 1400px the container has already stopped growing (it caps at 1140px),
   so the extra room is real and fixed. Return the links to the size and
   breathing room the approved design drew them at. */
@media (min-width: 1400px) {
  .navbar-container { column-gap: 2rem; }
  .nav-links { gap: 1.25rem; }
  .nav-link { font-size: 0.95rem; }
}

/* --------------------------------------------------------------------------
   C.7 — Focus, motion and the locked scroll
   -------------------------------------------------------------------------- */

.nav-link:focus-visible,
.nav-panel-link:focus-visible,
.navbar .nav-brand:focus-visible,
.footer .footer-link:focus-visible,
.footer .nav-brand:focus-visible {
  outline: 2px solid var(--stripe-indigo);
  outline-offset: 3px;
  border-radius: 6px;
}

.nav-toggle:focus-visible,
.navbar .btn-theme-toggle:focus-visible,
.navbar .btn-primary:focus-visible,
.navbar .ddb-lang-btn:focus-visible {
  outline: 2px solid var(--stripe-indigo);
  outline-offset: 3px;
}

/* FREEZING THE PAGE BEHIND THE PANEL IS DONE IN CSS, read straight off the
   disclosure's own open state, so it works with no script at all. That matters
   for more than the requirement: the scrim is a viewport-tall box, and a page
   that cannot scroll cannot be lengthened by it.

   In its own rule on purpose. A browser that does not understand :has() throws
   away the entire selector list it appears in, so the class-based rule below
   must never share a list with it. */
body:has(.nav-mobile[open]) {
  overflow-y: hidden;
}

@media (min-width: 1140px) {
  /* The disclosure is display: none from here up, but its open attribute can
     still be set — a visitor who opened the menu and then widened the window
     while no script was running — and a frozen page with no visible menu is
     unrecoverable. */
  body:has(.nav-mobile[open]) { overflow-y: auto; }
}

/* The one thing CSS cannot do: measure the scrollbar. Locking the scroll takes
   it away, and everything sized against the viewport jumps sideways by its
   width — so the script measures it, publishes it as --ddb-scrollbar-gap and
   hands it back as padding to both the document and the fixed bar. Phones use
   overlay scrollbars, where the measurement is 0 and nothing moves; a desktop
   window is where the jump showed. Padding only. Never visibility. */
body.ddb-nav-open {
  overflow: hidden;
  padding-right: var(--ddb-scrollbar-gap, 0px);
}

body.ddb-nav-open .navbar {
  padding-right: var(--ddb-scrollbar-gap, 0px);
}

@media (prefers-reduced-motion: reduce) {
  /* REDUCE, not remove. The panel still fades in — it just stops sliding, and
     the hover colour changes survive untouched. */
  .nav-panel { animation: ddbNavPanelFade 0.15s ease both; }

  .nav-toggle,
  .nav-panel-link,
  .btn-primary {
    transition-property: color, background-color, border-color, opacity;
  }

  .btn-primary:hover { transform: none; }
}

@keyframes ddbNavPanelFade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* --------------------------------------------------------------------------
   C.8 — Anchor targets under a fixed bar

   Every section link is an in-page anchor on the landing and the bar is fixed,
   so without this the browser parks each section's heading underneath the
   navbar and the visitor lands on the wrong thing. The offset covers the bar,
   the admin bar and a little air.

   A new section reachable from the nav has to be added to this list.
   -------------------------------------------------------------------------- */

#como-funciona,
#caracteristicas,
#demostracion,
#familia,
#precios,
#faq {
  scroll-margin-top: calc(var(--ddb-nav-height) + var(--ddb-nav-offset) + 1rem);
}

/* ==========================================================================
   PART D — the page shell, everywhere except the landing

   The landing opens with a hero that already reserves 10.5rem of top padding
   for the fixed bar. No other page does, so before this block the parent
   theme's first heading sat underneath the navbar.
   ========================================================================== */

body.ddb-inner-page {
  padding-top: calc(var(--ddb-nav-height) + 1rem);
  /* The parent theme paints the canvas from theme.json, which is a fixed
     light value. Reading the token instead means the day/night toggle in the
     header does something on these pages rather than turning the bar dark over
     a white document. */
  background-color: var(--bg-body);
  color: var(--text-main);
}

/* Dark mode on pages the design system does not own end to end. The parent
   theme and WooCommerce set their text colours from theme.json, which is a
   fixed dark navy — unreadable on the dark canvas. Handing those elements the
   inherited colour is the smallest change that keeps them legible.

   :not(.ddb-act-body) excludes /activar, which paints its own palette from
   activate.css and would otherwise have its deliberate heading colours flattened
   to the body colour by these two rules. */
[data-theme="dark"] body.ddb-inner-page:not(.ddb-act-body)
  :where(h1, h2, h3, h4, h5, h6, p, li, dt, dd, th, td, label, legend, figcaption, blockquote) {
  color: inherit;
}

[data-theme="dark"] body.ddb-inner-page:not(.ddb-act-body) :where(input, select, textarea) {
  background-color: var(--bg-surface);
  color: var(--text-main);
  border-color: var(--border-subtle);
}

/* --- /activar -------------------------------------------------------------
   The activation route ships its own full-height canvas from activate.css. It
   keeps it; all it needs is room for the bar and one less viewport height so
   the page does not grow a scrollbar it never had. */

body.ddb-act-body.ddb-inner-page {
  padding-top: var(--ddb-nav-height);
}

body.ddb-act-body .ddb-act__main {
  min-height: calc(100vh - var(--ddb-nav-height));
  min-height: calc(100dvh - var(--ddb-nav-height));
}

/* Its footer sits on a near-black canvas, so it borrows the dark border. */
body.ddb-act-body .footer {
  border-top-color: rgba(255, 255, 255, 0.12);
}

/* ==========================================================================
   PART E — document pages

   The five legal pages, and any other page or post written in the editor.
   Before this they rendered with Twenty Twenty-Five's defaults: the system
   font stack, a 5.1rem clamped h1 and an 800px measure that runs to about a
   hundred characters a line. The brief asks for a comfortable measure, the
   design system's typography and real spacing — this is that, and nothing
   else. WooCommerce screens are excluded from the body class: a cart is not
   prose and does not want a 38rem column.
   ========================================================================== */

body.ddb-doc-page {
  font-family: var(--font-sans);
}

body.ddb-doc-page :where(h1, h2, h3, h4, h5, h6) {
  font-family: var(--font-heading);
  color: var(--text-main);
  letter-spacing: -0.02em;
}

/* One measure for the title and the body, so the column has one edge.
   38rem lands at roughly 70 characters a line at the size set below — the
   range typography research has agreed on for two centuries. */
body.ddb-doc-page .wp-block-post-title,
body.ddb-doc-page .wp-block-post-content,
body.ddb-doc-page .entry-content {
  width: 100%;
  max-width: 38rem;
  margin-inline: auto;
}

body.ddb-doc-page .wp-block-post-title {
  margin-bottom: 2rem;
  font-size: clamp(1.9rem, 1.25rem + 2.6vw, 2.8rem);
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -0.03em;
}

body.ddb-doc-page .wp-block-post-content,
body.ddb-doc-page .entry-content {
  font-size: 1.02rem;
  line-height: 1.75;
  color: var(--text-muted);
}

body.ddb-doc-page .wp-block-post-content > * + *,
body.ddb-doc-page .entry-content > * + * {
  margin-block-start: 1.25em;
}

body.ddb-doc-page .wp-block-post-content > :where(h2, h3, h4),
body.ddb-doc-page .entry-content > :where(h2, h3, h4) {
  margin-block-start: 2.25em;
}

body.ddb-doc-page .wp-block-post-content h2,
body.ddb-doc-page .entry-content h2 {
  font-size: clamp(1.28rem, 1.05rem + 0.9vw, 1.55rem);
  font-weight: 700;
  line-height: 1.25;
}

body.ddb-doc-page .wp-block-post-content h3,
body.ddb-doc-page .entry-content h3 {
  font-size: 1.1rem;
  font-weight: 700;
  line-height: 1.35;
}

body.ddb-doc-page .wp-block-post-content :where(ul, ol),
body.ddb-doc-page .entry-content :where(ul, ol) {
  padding-inline-start: 1.35rem;
}

body.ddb-doc-page .wp-block-post-content li + li,
body.ddb-doc-page .entry-content li + li {
  margin-block-start: 0.5em;
}

body.ddb-doc-page .wp-block-post-content :where(strong, b),
body.ddb-doc-page .entry-content :where(strong, b) {
  color: var(--text-main);
  font-weight: 700;
}

/* theme.json declares the link colour as rgba(99, 91, 255, 0.1) — a 10% alpha
   TEXT colour, which is a background value in the wrong slot and renders links
   very nearly invisible. It is corrected in theme.json; stated here as well so
   a legal document is legible even if that file is ever reverted. */
body.ddb-doc-page a:where(:not(.wp-element-button):not(.footer-link):not(.nav-link)) {
  color: var(--stripe-indigo);
  text-decoration: underline;
  text-underline-offset: 0.16em;
  text-decoration-thickness: 1px;
}

body.ddb-doc-page a:where(:not(.wp-element-button):not(.footer-link):not(.nav-link)):hover {
  color: #534be0;
}

/* Tables in a legal document (data-retention periods, cookie inventories) have
   to stay inside the column on a 320px screen. */
body.ddb-doc-page .wp-block-table {
  overflow-x: auto;
}

body.ddb-doc-page .wp-block-table table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
}

body.ddb-doc-page .wp-block-table :where(th, td) {
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--border-subtle);
  text-align: left;
  vertical-align: top;
}

body.ddb-doc-page .wp-block-table th {
  color: var(--text-main);
  font-weight: 700;
}

/* Long URLs and e-mail addresses inside a legal text are the classic source of
   horizontal overflow on a 320px screen. */
body.ddb-doc-page .wp-block-post-content,
body.ddb-doc-page .entry-content {
  overflow-wrap: break-word;
}

/* Storefront shortcuts in the navbar --------------------------------------- */

.nav-icon-link {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  color: var(--text-muted, #425466);
  transition: color 0.2s ease, background-color 0.2s ease;
}

.nav-icon-link:hover,
.nav-icon-link:focus-visible {
  color: var(--stripe-indigo, #635bff);
  background: rgba(99, 91, 255, 0.08);
}

.nav-cart-count {
  position: absolute;
  top: 2px;
  right: 0;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--stripe-indigo, #635bff);
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  line-height: 16px;
  text-align: center;
}

.nav-icon-link--panel {
  width: 44px;
  height: 44px;
}

/* ===========================================================================
   WooCommerce surfaces (cart, checkout, account) — corporate skin.
   These pages load chrome.css, never landing.css.
   =========================================================================== */

/* --- Notices: the "added to cart" banner and friends ---------------------- */
/* Covers both the classic .woocommerce-message and the blocks notice banner,
   restyled to the brand instead of WooCommerce's stock green. */

.woocommerce-message,
.wc-block-components-notice-banner.is-success {
  border: 1px solid rgba(99, 91, 255, 0.25);
  border-left: 4px solid var(--stripe-indigo, #635bff);
  border-radius: 12px;
  background: linear-gradient(180deg, #f8f7ff, #f2f1ff);
  color: var(--text-main, #0a2540);
  font-family: var(--ddb-sans);
  box-shadow: 0 8px 24px -16px rgba(50, 50, 93, 0.35);
}

.woocommerce-message::before,
.wc-block-components-notice-banner.is-success > svg {
  color: var(--stripe-indigo, #635bff);
  fill: var(--stripe-indigo, #635bff);
}

.woocommerce-message .button,
.wc-block-components-notice-banner .wc-forward {
  background: var(--stripe-indigo, #635bff);
  color: #fff;
  border-radius: 999px;
  padding: 0.5em 1.2em;
  font-weight: 700;
  text-decoration: none;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.woocommerce-message .button:hover,
.wc-block-components-notice-banner .wc-forward:hover {
  transform: translateY(-1px);
  box-shadow: 0 8px 18px -8px rgba(99, 91, 255, 0.6);
}

/* --- "Finalizar compra": make it read as THE button ----------------------- */
/* Classic cart and blocks cart both covered. */

.wc-proceed-to-checkout .checkout-button,
.wc-block-cart__submit-button,
.wc-block-cart__submit-container > a,
.wc-block-components-checkout-place-order-button {
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(180deg, #6f67ff, var(--stripe-indigo, #635bff)) !important;
  color: #fff !important;
  border: 0 !important;
  border-radius: 999px !important;
  padding: 0.95em 1.6em !important;
  font-family: var(--ddb-sans) !important;
  font-weight: 800 !important;
  font-size: 1rem !important;
  text-decoration: none !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.25),
    0 10px 24px -10px rgba(99, 91, 255, 0.7);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.wc-proceed-to-checkout .checkout-button:hover,
.wc-block-cart__submit-button:hover,
.wc-block-cart__submit-container > a:hover,
.wc-block-components-checkout-place-order-button:hover {
  transform: translateY(-2px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.25),
    0 16px 32px -12px rgba(99, 91, 255, 0.8);
}

/* --- Express payment: reserve the slot, kill the pop-in ------------------- */
/* Stripe's express element (Google Pay / Link) mounts asynchronously and used
   to appear seconds late, shoving the whole page down — read as lag. The slot
   now exists from the first paint at its final height with a quiet shimmer;
   when Stripe mounts, it fills the space that was always there. This is the
   honest version of "always show them": the real buttons CANNOT be rendered
   without Stripe's script, but the layout can stop lying about it. */

.wc-block-components-express-payment--checkout,
.wc-block-components-express-payment--cart,
#wc-stripe-express-checkout-element {
  min-height: 48px;
}

.wc-block-components-express-payment__event-buttons:empty,
#wc-stripe-express-checkout-element:empty {
  border-radius: 10px;
  background: linear-gradient(
    100deg,
    rgba(10, 37, 64, 0.05) 40%,
    rgba(10, 37, 64, 0.10) 50%,
    rgba(10, 37, 64, 0.05) 60%
  );
  background-size: 200% 100%;
  animation: ddb-express-shimmer 1.4s ease-in-out infinite;
}

@keyframes ddb-express-shimmer {
  from { background-position: 120% 0; }
  to   { background-position: -20% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .wc-block-components-express-payment__event-buttons:empty,
  #wc-stripe-express-checkout-element:empty {
    animation: none;
  }
}
