/* datenwed — base.css (CHARTER §3 design-token shell · §2.1c-ii LOCAL carve-out).
 *
 * HAND-AUTHORED from site.json.theme tokens. There is no token-CSS generator at v2.0
 * (tools/SHARED_DESIGN does not exist yet), so this file is the one legitimately-LOCAL
 * frontend asset and has NO anti-drift backstop until the v2.1 generator lands (§2.1d).
 * The three theme colors below are the entire site-specific surface — retheming a site
 * = changing these three custom properties.
 *
 * site.json.theme → :root tokens (keep in sync; the v2.1 generator will emit these):
 *   primary_color   #2563eb
 *   secondary_color #1e40af
 *   accent_color    #38bdf8
 */
:root {
  /* --- theme tokens (from site.json.theme) --- */
  --color-primary: #2563eb;
  --color-secondary: #1e40af;
  --color-accent: #38bdf8;

  /* Foreground for text/icons sitting ON a brand-colored surface (buttons,
   * active chips, badges). Theme-INDEPENDENT (not from site.json.theme): brand
   * surfaces stay saturated in both light and dark, so their foreground must
   * not flip with the theme the way a --text-inverse token would. Backported
   * 2026-07-17 after five TubeRaker page teams independently re-invented a
   * page-local white-on-brand token (see websites/TUBERAKER pages/*.css). */
  --color-on-brand: #ffffff;

  /* --- shared guest header brand accent (CARRIER — do not delete) ----------
   * SHARED_DASHBOARD's css/header-embed.css paints the injected guest header
   * from two custom properties it READS but never DEFINES:
   *
   *     --he-accent:      var(--site-accent-fill, #3b82f6)
   *     --he-accent-glow: var(--site-accent-glow, rgba(59, 130, 246, 0.2))
   *
   * Through header-embed v2.2.1 (the commit in shared-components.lock.json) the
   * bundle ALSO resolved the accent in JavaScript -- from site.json's
   * accent_color plus a hardcoded per-site table -- and wrote both onto <html>
   * as an inline style. An inline style outranks stylesheets, so those
   * fallbacks were unreachable and no site had to define anything. v2.2.3
   * DELETES both paths, leaving the stylesheet fallback as the only source: a
   * site defining neither property renders a BLUE header the moment its
   * SHARED_DASHBOARD pin moves past v2.2.0.
   *
   * These two lines are that definition. Derived from --color-accent rather
   * than restated as literals, deliberately and for two reasons:
   *   - scaffold/site_vars.py rewrites theme hexes ONLY inside the four files
   *     in its _PORT_HEX_EXACT allowlist, of which this is one. A hex written
   *     into any OTHER file would survive scaffolding unchanged and every new
   *     site would silently inherit the TEMPLATE's colour, not its own.
   *   - one literal cannot drift from another that does not exist. A glow whose
   *     RGB has wandered off the fill is a header whose hover states belong to
   *     a different brand than its text.
   *
   * NOT inert at the current pin: v2.2.1 already guards its inline write on
   * --site-accent-fill computing non-empty (_siteBrandActive), so defining it
   * here suppresses that write today and this file supplies the colour instead.
   * Verified in-browser: the guard reads through the var() indirection, and
   * color-mix(... 20%/10%, transparent) is pixel-identical to the _hexToRgba()
   * rgba(r,g,b,0.20/0.10) the bundle produced. Measured 2026-08-29 against
   * SHARED_DASHBOARD 575e8bd (v2.2.1) and db610965 (v2.2.3).
   * Runbook: DOCS/NEW_WEBSITE_BUILD/SHARED_HEADER_ACCENT_CARRIER_GATE.md */
  --site-accent-fill: var(--color-accent);
  --site-accent-glow: color-mix(in srgb, var(--color-accent) 20%, transparent);

  /* --- derived brand surfaces --- */
  --brand-gradient: linear-gradient(135deg, var(--color-primary), var(--color-secondary));
  --accent-glow: 0 0 0 0.0625rem color-mix(in srgb, var(--color-accent) 40%, transparent),
                 0 0.75rem 2.5rem -0.75rem color-mix(in srgb, var(--color-primary) 55%, transparent);

  /* --- neutral ink/canvas (dark identity-platform) --- */
  --ink-0: #05070d;          /* canvas */
  --ink-1: #0b0f1a;          /* raised surface */
  --ink-2: #131829;          /* card */
  --line: color-mix(in srgb, var(--color-accent) 14%, #1d2438);
  --text-hi: #f3f6ff;
  --text-mid: #aeb8d4;
  --text-low: #6b7596;

  /* --- type --- */
  --font-display: "Fraunces", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --font-body: "IBM Plex Sans", ui-sans-serif, "Segoe UI", Helvetica, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", monospace;

  /* --- scale --- */
  --space: clamp(1rem, 0.6rem + 1.6vw, 1.75rem);
  --radius: 0.875rem;
  --radius-lg: 1.375rem;
  --maxw: 71.25rem;
}

/* The bundle dimmed the glow on light theme (_hexToRgba(hex, isLight ? 0.10 :
 * 0.20)); a single flat alpha would be a regression against what it rendered.
 * header-embed writes data-theme explicitly ("dark"/"light"), so keying off the
 * attribute is sufficient. */
:root[data-theme="light"] {
  --site-accent-glow: color-mix(in srgb, var(--color-accent) 10%, transparent);
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font-body);
  color: var(--text-mid);
  background:
    radial-gradient(75rem 38.75rem at 78% -8%, color-mix(in srgb, var(--color-primary) 26%, transparent), transparent 70%),
    radial-gradient(51.25rem 32.5rem at 6% 8%, color-mix(in srgb, var(--color-secondary) 22%, transparent), transparent 68%),
    var(--ink-0);
  min-height: 100vh;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* subtle grain so the gradients read as atmosphere, not flat fills */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

a { color: var(--color-accent); text-decoration: none; transition: color .18s ease; }
a:hover { color: var(--text-hi); }

.container { width: min(var(--maxw), 100% - 2.5rem); margin-inline: auto; position: relative; z-index: 1; }

/* ---------- header / nav ---------- */
.site-header {
  position: sticky; top: 0; z-index: 20;
  backdrop-filter: blur(0.875rem);
  background: color-mix(in srgb, var(--ink-0) 72%, transparent);
  border-bottom: 0.0625rem solid var(--line);
}
.nav { display: flex; align-items: center; gap: 1.25rem; padding: 1.05rem 0; }
.brand { display: inline-flex; align-items: center; gap: .65rem; font-family: var(--font-display);
  font-weight: 600; font-size: 1.18rem; color: var(--text-hi); letter-spacing: -0.01em; }
.brand-mark {
  width: 2.125rem; height: 2.125rem; border-radius: 0.5625rem; display: grid; place-items: center;
  background: var(--brand-gradient); box-shadow: var(--accent-glow); color: #fff;
}
.brand-mark svg { width: 1.1875rem; height: 1.1875rem; }
.nav-links { display: flex; flex-wrap: wrap; gap: 1.4rem; margin-left: auto; align-items: center; justify-content: flex-end; }
.nav-links a { color: var(--text-mid); font-size: .94rem; font-weight: 500; }
.nav-links a:hover { color: var(--text-hi); }
.nav-cta { display: inline-flex; gap: .6rem; align-items: center; }
/* Auth-state nav clusters (#auth-guest-nav / #auth-user-nav) are gated in the
   AUTH-AWARE LANDING CONTRACT section near the bottom of this file. Read the
   comment there before touching either one. */
.nav-group { display: inline-flex; gap: 1.4rem; align-items: center; }

/* ---------- buttons ---------- */
.btn {
  --btn-bg: transparent; --btn-fg: var(--text-hi); --btn-bd: var(--line);
  display: inline-flex; align-items: center; gap: .5rem; cursor: pointer;
  font-family: var(--font-body); font-weight: 600; font-size: .94rem; line-height: 1;
  padding: .72rem 1.15rem; border-radius: 0.625rem; border: 0.0625rem solid var(--btn-bd);
  background: var(--btn-bg); color: var(--btn-fg); transition: transform .16s ease, box-shadow .2s ease, border-color .2s ease;
}
.btn:hover { transform: translateY(-0.0625rem); }
.btn-ghost:hover { border-color: color-mix(in srgb, var(--color-accent) 55%, var(--line)); color: var(--text-hi); }
.btn-primary {
  --btn-fg: #fff; --btn-bd: transparent;
  background: var(--brand-gradient); box-shadow: var(--accent-glow);
}
.btn-primary:hover { box-shadow: 0 0 0 0.0625rem color-mix(in srgb, var(--color-accent) 60%, transparent),
  0 1.125rem 3rem -0.875rem color-mix(in srgb, var(--color-primary) 70%, transparent); }

/* ---------- hero ---------- */
.hero { padding: clamp(3.5rem, 7vw, 6.5rem) 0 clamp(2.5rem, 5vw, 4rem); }
.eyebrow {
  display: inline-flex; align-items: center; gap: .55rem; font-family: var(--font-mono);
  font-size: .76rem; letter-spacing: .14em; text-transform: uppercase; color: var(--color-accent);
  padding: .4rem .8rem; border: 0.0625rem solid var(--line); border-radius: 999rem;
  background: color-mix(in srgb, var(--color-accent) 7%, transparent);
}
.hero h1 {
  font-family: var(--font-display); font-weight: 600; color: var(--text-hi);
  font-size: clamp(2.5rem, 5.4vw, 4.4rem); line-height: 1.03; letter-spacing: -0.025em;
  margin: 1.3rem 0 0; max-width: 16ch;
}
.hero h1 .grad {
  background: linear-gradient(115deg, var(--color-accent), var(--color-primary));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.hero p.lede { font-size: clamp(1.05rem, 1.6vw, 1.25rem); max-width: 52ch; margin: 1.5rem 0 2.2rem; color: var(--text-mid); }
.hero-actions { display: flex; flex-wrap: wrap; gap: .9rem; }

/* ---------- capability grid ---------- */
.section { padding: clamp(2.5rem, 5vw, 4.5rem) 0; }
.section-title { font-family: var(--font-display); color: var(--text-hi); font-weight: 600;
  font-size: clamp(1.5rem, 2.6vw, 2rem); letter-spacing: -0.02em; margin: 0 0 .5rem; }
.section-sub { color: var(--text-low); max-width: 56ch; margin: 0 0 2rem; }
.grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(15.5rem, 1fr)); }
.card {
  background: linear-gradient(180deg, var(--ink-2), var(--ink-1));
  border: 0.0625rem solid var(--line); border-radius: var(--radius-lg); padding: 1.5rem 1.5rem 1.65rem;
  transition: transform .18s ease, border-color .2s ease;
}
.card:hover { transform: translateY(-0.1875rem); border-color: color-mix(in srgb, var(--color-accent) 45%, var(--line)); }
.card-ico {
  width: 2.5rem; height: 2.5rem; border-radius: 0.6875rem; display: grid; place-items: center; margin-bottom: 1rem;
  color: var(--color-accent); background: color-mix(in srgb, var(--color-accent) 12%, transparent);
  border: 0.0625rem solid color-mix(in srgb, var(--color-accent) 28%, transparent); font-size: 1.05rem;
}
.card h3 { font-family: var(--font-body); color: var(--text-hi); font-size: 1.05rem; margin: 0 0 .4rem; font-weight: 600; }
.card p { margin: 0; font-size: .92rem; color: var(--text-low); }

/* =============================================================================
   OTROTL AUTH-AWARE LANDING CONTRACT   (canonical — copy into every new site)
   -----------------------------------------------------------------------------
   GUEST-FIRST BY DESIGN. The default render is the marketing view, so Googlebot
   indexes marketing copy and the page stays CDN-cacheable. NEVER server-render
   two variants. The authenticated chrome ships in the HTML for EVERY visitor and
   is merely revealed by adding `is-authenticated` to <body> after /auth/me
   resolves 2xx (see frontend/js/auth-state.js — read its header before changing
   anything here; the session is an httpOnly cookie and is NOT readable from JS).

   Because the authenticated chrome ships to everyone, it must never contain
   server-rendered or hardcoded user data — only [data-auth-field] placeholders.
   ============================================================================= */

/* ---- (1) SECTION-LEVEL CONTRACT — keep these five lines byte-identical ----
   Used for whole page sections / blocks. `data-auth-display` opts a revealed
   block into flex/grid instead of the default `block`. Do NOT add a
   `data-auth-display` to anything whose display must CHANGE across breakpoints
   — force-setting a display value overrides the responsive rule. Gate those the
   display:none-only way shown in (2) instead. Judge per element. */
[data-auth-show="authenticated"] { display: none !important; }
body.is-authenticated [data-auth-show="authenticated"] { display: block !important; }
body.is-authenticated [data-auth-show="guest"]         { display: none  !important; }
body.is-authenticated [data-auth-show="authenticated"][data-auth-display="flex"] { display: flex !important; }
body.is-authenticated [data-auth-show="authenticated"][data-auth-display="grid"] { display: grid !important; }

/* ---- (2) NAV-LEVEL CONTRACT — display:none ONLY, never display:<anything> --
   THE RULE, and why it is not negotiable:

     * Gate the two nav clusters HERE, in CSS, with an ID selector + !important.
       Do NOT toggle a visibility class from JS. On Tailwind sites the classic
       `classList.toggle('hidden', …)` over `class="hidden md:flex"` DOES NOT
       WORK: `.hidden` and `.md\:flex` have equal specificity and `md:flex` is
       emitted ~4.4 MB later in tailwind.min.css, so at the `md` breakpoint and
       up it wins and adding `hidden` does nothing — "Sign In" stays visible after
       login. This site is plain semantic CSS, but the failure mode generalises:
       any JS-toggled class competes with the stylesheet's own rules. CSS keyed
       off one body class cannot lose that race.

     * Only ever force `display: none`. NEVER force `display: flex` (or block,
       or grid) on a nav container. Forcing a display value overrides the
       responsive utilities/media queries that decide how the container lays out
       per breakpoint, which leaks the desktop nav onto mobile. Hiding is safe;
       showing must be left to the element's own natural/responsive display. */
body.is-authenticated       #auth-guest-nav,
body:not(.is-authenticated) #auth-user-nav { display: none !important; }

/* Pre-resolution (`is-auth-loading`, i.e. neither class yet) the :not() above
   already hides the authenticated cluster, so the guest view is what paints
   first. Deliberately left unstyled otherwise — a skeleton here would be a
   flash of nothing for the majority (guest) case. */

/* ---- (3) Authenticated chrome, in the house design language --------------- */
.auth-avatar {
  width: 2.125rem; height: 2.125rem; border-radius: 999rem;
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto; background: var(--brand-gradient); color: #fff;
  font-weight: 600; font-size: .82rem; letter-spacing: .02em;
  box-shadow: var(--accent-glow);
}
.auth-identity {
  display: inline-flex; align-items: center; gap: .55rem;
  padding: .35rem .6rem; border-radius: 0.625rem;
  color: var(--text-hi); transition: background .18s ease;
}
.auth-identity:hover { background: color-mix(in srgb, var(--color-accent) 10%, transparent); }
.auth-identity-name {
  font-weight: 600; font-size: .94rem; max-width: 9rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Authenticated hero. Not gated per-breakpoint, so the section-level contract's
   `display: block` is correct for it — no data-auth-display needed. */
.auth-hero { padding: clamp(3rem, 6vw, 5rem) 0 clamp(2rem, 4vw, 3rem); }
.auth-hero-head { display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap; }
.auth-hero-head .auth-avatar { width: 3.5rem; height: 3.5rem; font-size: 1.3rem; }
.auth-hero h1 {
  font-family: var(--font-display); font-weight: 600; color: var(--text-hi);
  font-size: clamp(1.9rem, 3.6vw, 2.9rem); line-height: 1.08;
  letter-spacing: -0.022em; margin: 0;
}
.auth-hero-meta { margin: .3rem 0 0; color: var(--text-low); font-size: .94rem; }
.auth-hero-actions { display: flex; flex-wrap: wrap; gap: .9rem; margin: 1.8rem 0 2.4rem; }
.quick-actions { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(15.5rem, 1fr)); }
.quick-action {
  display: flex; align-items: center; gap: .9rem; color: inherit;
  background: linear-gradient(180deg, var(--ink-2), var(--ink-1));
  border: 0.0625rem solid var(--line); border-radius: var(--radius);
  padding: 1rem 1.1rem; transition: transform .18s ease, border-color .2s ease;
}
.quick-action:hover { transform: translateY(-0.125rem); border-color: color-mix(in srgb, var(--color-accent) 45%, var(--line)); }
.quick-action .card-ico { margin-bottom: 0; }
.quick-action b { display: block; color: var(--text-hi); font-weight: 600; font-size: .98rem; }
.quick-action small { color: var(--text-low); font-size: .85rem; }

.auth-fade-in { animation: authFadeIn .3s ease-in; }
@keyframes authFadeIn {
  from { opacity: 0; transform: translateY(0.5rem); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---------- footer ---------- */
.site-footer { border-top: 0.0625rem solid var(--line); margin-top: 2rem; padding: 2.2rem 0; }
.foot { display: flex; flex-wrap: wrap; gap: 1rem 2rem; align-items: center; color: var(--text-low); font-size: .88rem; }
.foot .brand { font-size: 1rem; }
.foot-links { display: flex; gap: 1.3rem; margin-left: auto; }
.foot-links a { color: var(--text-low); }
.foot-links a:hover { color: var(--text-hi); }

@media (max-width: 42.5rem) {
  .nav-links { gap: .9rem; }
  .nav-group { gap: .9rem; }
  /* Secondary nav items drop out on small screens. This is a display:none rule
     too, so it composes with the auth gating above instead of fighting it —
     never add a `display: <something>` here for an auth-gated container. */
  .nav-links .hide-sm { display: none; }
  .auth-identity-name { max-width: 6rem; }
}
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
}
