/* hiddenprimary.ch — Swiss Refined
   Typography: IBM Plex Sans (UI) + IBM Plex Mono (data/code)
   Palette: warm neutrals + Swiss red accent
*/

/* ---------------------------------------------------------------- */
/* Fonts (self-hosted — no third-party requests, revDSG-safe)       */
/* ---------------------------------------------------------------- */
@font-face { font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 300; font-display: swap; src: url('/static/fonts/ibm-plex-sans-300.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 400; font-display: swap; src: url('/static/fonts/ibm-plex-sans-400.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 500; font-display: swap; src: url('/static/fonts/ibm-plex-sans-500.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 600; font-display: swap; src: url('/static/fonts/ibm-plex-sans-600.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 700; font-display: swap; src: url('/static/fonts/ibm-plex-sans-700.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('/static/fonts/ibm-plex-mono-400.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 500; font-display: swap; src: url('/static/fonts/ibm-plex-mono-500.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 600; font-display: swap; src: url('/static/fonts/ibm-plex-mono-600.woff2') format('woff2'); }

/* ---------------------------------------------------------------- */
/* Tokens                                                            */
/* ---------------------------------------------------------------- */
:root {
  --bg: #f7f7f5;
  --surface: #ffffff;
  --surface-2: #f0efec;
  --surface-dark: #1a1a1a;
  --border: #ddd9d3;
  --border-heavy: #1a1a1a;
  --text: #1a1a1a;
  --text-2: #555;
  --text-3: #666666; /* muted but still WCAG AA (≥4.5:1) on --bg, white AND --surface-2 (table headers, badge-muted) */
  --text-inv: #f7f7f5;
  --red: #d93025;
  --red-light: #fce8e6;
  --red-dark: #b71c1c;
  --green: #1e8e3e;
  --green-light: #e6f4ea;
  --amber: #b25b00; /* 4.46:1 on --amber-light — NOT enough for small text; use --amber-text there */
  --amber-light: #fef7e0;
  --blue: #1a73e8;
  --blue-light: #e8f0fe;
  /* Small-text-on-tinted-chip colors. The brand hues above keep serving large
     text, borders and status dots (non-text needs only 3:1); these darkened
     variants are for SMALL text on the matching *-light / --surface-2
     backgrounds. Badge text is ~9px at weight 600, so the WCAG large-text
     exemption does not apply and 4.5:1 is the floor. Ratios are pinned by
     TestBadgeTextContrastMeetsWCAGAA (internal/handler/portal/ui_contrast_test.go). */
  --green-text: #177a33; /* 4.78:1 on --green-light, 4.72:1 on --surface-2 */
  --red-text: #c02a20;   /* 4.96:1 on --red-light,   5.08:1 on --surface-2 */
  --amber-text: #a85600; /* 4.90:1 on --amber-light */
  --blue-text: #1566cc;  /* 4.82:1 on --blue-light */
  /* The accent used for "you are here" markers. Was referenced by
     .sidebar li a.active without ever being defined, which silently dropped
     that rule's inset bar (an undefined var() invalidates the declaration). */
  --accent: var(--red);
  --font: 'IBM Plex Sans', -apple-system, sans-serif;
  --mono: 'IBM Plex Mono', monospace;
  --radius: 6px;
  --shadow-sm: 0 1px 3px rgba(0,0,0,.06), 0 1px 2px rgba(0,0,0,.04);
  --shadow-md: 0 4px 12px rgba(0,0,0,.06), 0 2px 4px rgba(0,0,0,.04);
  --shadow-lg: 0 12px 40px rgba(0,0,0,.08), 0 4px 12px rgba(0,0,0,.04);
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 15px; scroll-padding-top: 4.5rem; /* sticky nav must not cover anchor targets */ }
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
body { font-family: var(--font); background: var(--bg); color: var(--text); line-height: 1.6; }

/* Links are unstyled by default: nav items, cards, tab bars, sidebar entries
   and .btn anchors are all <a> and must not be underlined. Anything that is a
   link INSIDE a block of running text opts in with .link instead — WCAG 2.1
   SC 1.4.1 (failure F73) forbids colour as the only distinction unless the
   link reaches 3:1 against the surrounding copy, which no accent on this
   palette does. `.link.text-muted` keeps the underline and takes the grey (the
   utility is declared later in this file, so it wins the colour). */
a { color: inherit; text-decoration: none; }
.link { color: var(--red-text); text-decoration: underline; text-underline-offset: 2px; text-decoration-thickness: 1px; }
.link:hover, .link:focus-visible { text-decoration-thickness: 2px; }

.container { max-width: 1120px; margin: 0 auto; padding: 0 2rem; }
/* Portal pages carry wide data tables; the marketing pages keep the narrower
   measure that the type is designed for. */
.container-wide { max-width: 1400px; }
/* For cells whose value is meaningless when broken across lines. */
.nowrap { white-space: nowrap; }
.section-label { font-size: .68rem; text-transform: uppercase; letter-spacing: .14em; color: var(--text-3); font-weight: 600; margin-bottom: 1.75rem; }

/* Skip link: first focusable element, visible only on keyboard focus */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--text); color: white;
  padding: .6rem 1rem; border-radius: 0 0 6px 0;
  font-size: .8rem; font-weight: 600;
}
.skip-link:focus { left: 0; }

/* Admin impersonation banner */
.impersonation-banner {
  background: var(--red); color: white; text-align: center;
  padding: .4rem; font-size: .8rem; font-weight: 600;
  position: relative; z-index: 101;
}
/* The shipped exit control is an <a> (class .impersonation-exit-link): only a
   server-side round trip can clear the HttpOnly session cookie, so the
   <button> branch in layout.html is a dead JS-only fallback. Both are styled
   here — the global `a { color: inherit; text-decoration: none }` would
   otherwise render the only working exit as plain banner text. */
.impersonation-banner button,
.impersonation-banner a.impersonation-exit-link {
  color: white; text-decoration: underline;
  background: none; border: none; cursor: pointer; font: inherit;
}

/* ---------------------------------------------------------------- */
/* Nav                                                               */
/* ---------------------------------------------------------------- */
nav {
  border-bottom: 2px solid var(--red);
  padding: .8rem 0;
  position: sticky; top: 0;
  background: rgba(247,247,245,.88);
  backdrop-filter: blur(12px);
  z-index: 100;
}
nav .container { display: flex; justify-content: space-between; align-items: center; }
.brand { font-weight: 700; font-size: 1.1rem; letter-spacing: -.02em; }
.brand em { font-style: normal; color: var(--red); }
.nav-links { display: flex; gap: .25rem; list-style: none; align-items: center; }
.nav-links a, .nav-links button {
  color: var(--text-2); font-size: .82rem; font-weight: 500;
  padding: .4rem .7rem; border-radius: var(--radius); transition: all .15s;
  background: none; border: none; cursor: pointer; font-family: var(--font);
}
.nav-links a:hover, .nav-links button:hover { color: var(--text); background: var(--surface-2); }
.team-switcher {
  font-family: var(--font); font-size: .78rem; font-weight: 500;
  padding: .3rem .5rem; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); color: var(--text-2); cursor: pointer;
}

/* Buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  padding: .5rem 1.3rem;
  font-family: var(--font); font-size: .8rem; font-weight: 600;
  letter-spacing: .02em; text-transform: uppercase;
  border: 2px solid var(--text); border-radius: var(--radius);
  background: var(--text); color: white;
  cursor: pointer; transition: all .15s; text-decoration: none;
}
.btn:hover { background: var(--red); border-color: var(--red); }
.btn-outline { background: transparent; color: var(--text); }
.btn-outline:hover { background: var(--text); color: white; border-color: var(--text); }
.btn-red { background: var(--red); border-color: var(--red); }
.btn-red:hover { background: var(--red-dark); border-color: var(--red-dark); }
.btn-white { background: white; color: var(--text); border-color: rgba(255,255,255,.3); }
.btn-white:hover { background: rgba(255,255,255,.9); border-color: white; }
.btn-outline-light { background: transparent; color: rgba(255,255,255,.7); border-color: rgba(255,255,255,.25); }
.btn-outline-light:hover { background: white; color: var(--text); border-color: white; }
.btn-sm { padding: .35rem .9rem; font-size: .72rem; }
.btn-block { width: 100%; text-align: center; }
.btn-ghost {
  background: none; border: none;
  color: var(--text-2); font-size: .82rem; font-weight: 500;
  padding: .4rem .7rem; border-radius: var(--radius);
  cursor: pointer; font-family: var(--font); transition: all .15s;
}
.btn-ghost:hover { color: var(--text); background: var(--surface-2); }
.btn-danger { background: transparent; color: var(--red); border: 2px solid var(--red); }
.btn-danger:hover { background: var(--red); color: white; }

/* ---------------------------------------------------------------- */
/* Hero                                                              */
/* ---------------------------------------------------------------- */
.hero { padding: 5rem 0 4.5rem; border-bottom: 1px solid var(--border); }
.hero-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 3.5rem; align-items: center; }
.hero h1 { font-size: 3rem; font-weight: 700; letter-spacing: -.04em; line-height: 1.06; margin-bottom: 1.25rem; }
.hero h1 span { display: block; color: var(--red); }
.hero p { font-size: 1.05rem; color: var(--text-2); max-width: 440px; margin-bottom: 1.75rem; font-weight: 300; line-height: 1.65; }
.hero-actions { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; }
.hero-actions .note { font-size: .72rem; color: var(--text-3); margin-left: .25rem; }

/* Terminal */
.terminal {
  background: var(--surface-dark);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  font-family: var(--mono);
  font-size: .78rem;
  line-height: 1.85;
  color: #b8b8b8;
}
.terminal-bar {
  background: #252525;
  padding: .55rem 1rem;
  display: flex; align-items: center; gap: 7px;
  border-bottom: 1px solid #333;
}
.terminal-dot { width: 10px; height: 10px; border-radius: 50%; }
.terminal-dot.r { background: #ff5f56; }
.terminal-dot.y { background: #ffbd2e; }
.terminal-dot.g { background: #27c93f; }
.terminal-title { margin-left: auto; font-size: .65rem; color: #666; }
.terminal-body { padding: 1.25rem 1.5rem; }
.terminal .prompt { color: var(--red); font-weight: 600; }
.terminal .dim { opacity: .35; }
.terminal .num { color: #a5d6a7; }
.terminal .key { color: #90a4ae; }

/* ---------------------------------------------------------------- */
/* Trust bar                                                         */
/* ---------------------------------------------------------------- */
/* Landing sections span the page naturally inside main.landing-page.
   (The old 100vw breakout hack caused a permanent horizontal scrollbar on
   browsers with classic scrollbars — 100vw includes the scrollbar width.) */
.full-width { width: 100%; }

/* Landing page: remove main padding since sections handle their own */
.landing-page { padding: 0; }

.trust {
  padding: 2.25rem 0;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.trust .container { display: flex; justify-content: center; gap: 3rem; flex-wrap: wrap; }
.trust-item { text-align: center; }
.trust-num { font-family: var(--mono); font-size: 1.35rem; font-weight: 700; }
.trust-label { font-size: .65rem; text-transform: uppercase; letter-spacing: .1em; color: var(--text-3); font-weight: 500; margin-top: .1rem; }

/* ---------------------------------------------------------------- */
/* How it works                                                      */
/* ---------------------------------------------------------------- */
.how { padding: 4rem 0; border-bottom: 1px solid var(--border); }
/* Use cases: same card language as .steps, two columns so four fit above the
   fold on a laptop without shrinking the type. */
.usecases { background: var(--surface-2); padding: 4rem 0; }
.section-lead { color: var(--text-2); margin: -.5rem 0 1.75rem; font-weight: 300; }
/* auto-fit so the block stays balanced whether there are four cards or five. */
.uc-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); gap: 1.25rem; }
.uc-card { background: var(--bg); border: 1px solid var(--border); border-radius: 10px; padding: 1.5rem; }
.uc-card h3 { font-size: 1rem; font-weight: 700; letter-spacing: -.01em; margin-bottom: .15rem; }
.uc-card p { font-size: .9rem; line-height: 1.6; color: var(--text-2); font-weight: 300; }
.uc-who { font-size: .72rem; text-transform: uppercase; letter-spacing: .06em; color: var(--text-3); margin-bottom: .6rem; font-weight: 600; }
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; }
.step {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.75rem;
  position: relative;
  transition: all .2s;
}
.step:hover { box-shadow: var(--shadow-md); border-color: #ccc; }
.step-num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  background: var(--surface-dark); color: white;
  font-family: var(--mono); font-size: .75rem; font-weight: 600;
  border-radius: 50%;
  margin-bottom: 1rem;
}
.step h3 { font-size: .95rem; font-weight: 600; margin-bottom: .5rem; }
.step p { font-size: .8rem; color: var(--text-2); font-weight: 300; line-height: 1.6; margin-bottom: .75rem; }
.step code {
  display: block;
  font-family: var(--mono); font-size: .72rem;
  color: var(--text-2);
  background: var(--surface-2);
  padding: .5rem .75rem;
  border-radius: 4px;
  border-left: 3px solid var(--red);
}

/* ---------------------------------------------------------------- */
/* Features                                                          */
/* ---------------------------------------------------------------- */
.features { padding: 4rem 0; border-bottom: 1px solid var(--border); }
.f-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.25rem; }
.f-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.5rem;
  transition: all .2s;
}
.f-card:hover { box-shadow: var(--shadow-md); border-color: #ccc; }
.f-tag {
  display: inline-block;
  font-family: var(--mono); font-size: .6rem;
  text-transform: uppercase; letter-spacing: .08em;
  padding: .15rem .5rem;
  border-radius: 3px;
  margin-bottom: .75rem;
  font-weight: 500;
}
.f-tag-core { background: var(--red-light); color: var(--red-text); }
.f-tag-security { background: var(--green-light); color: var(--green-text); }
.f-tag-auto { background: var(--blue-light); color: var(--blue-text); }
.f-tag-ops { background: var(--amber-light); color: var(--amber-text); }
/* Card titles are h2 since the a11y pass — they sit directly under the page h1
   and as h3 they skipped a level. Two traps live in this one selector:
   `.f-card` exists ONLY inside `<section class="imprint">` (docs.html), and a
   bare `.f-card h2` is 0,0,1,1 exactly like `.imprint h2` further down the file,
   so source order would hand the ten /docs card titles to the section-label
   treatment — small, uppercase, grey. Hence the `.imprint` qualifier (0,0,2,1),
   same reasoning as `.imprint .lead`. And hence the resets: `.imprint h2` sets
   text-transform, letter-spacing, colour and a 1.5rem top margin, so anything
   not restated here stays in force. The values are the mockup's `.f-card h3`,
   which renders outside `.imprint` and therefore always looked right there. */
.imprint .f-card h2 {
  font-size: .9rem; font-weight: 600;
  text-transform: none; letter-spacing: -.02em;
  color: var(--text);
  margin: 0 0 .4rem;
}
.f-card p { font-size: .78rem; color: var(--text-2); font-weight: 300; line-height: 1.55; margin: 0; }

/* "What you get": a plain two-column list, deliberately NOT cards. The page
   already uses cards for the use cases, and a third grid of them is what made
   it read as assembled rather than written. */
.value-list { display: grid; grid-template-columns: 1fr 1fr; gap: 1.75rem 3rem; }
.value h3 { font-size: .92rem; font-weight: 700; letter-spacing: -.01em; margin-bottom: .3rem; line-height: 1.35; }
.value p { font-size: .85rem; color: var(--text-2); font-weight: 300; line-height: 1.6; margin: 0; }

/* ---------------------------------------------------------------- */
/* Pricing                                                           */
/* ---------------------------------------------------------------- */
.pricing { padding: 4rem 0; border-bottom: 1px solid var(--border); }
.pricing-header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 1.75rem; }
.pricing-header .section-label { margin: 0; }
.pricing-header p { font-size: .82rem; color: var(--text-3); }
.p-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; }
.p-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 2rem;
  transition: all .2s;
  position: relative;
  display: flex; flex-direction: column;
}
.p-card .p-features { flex: 1; }
.p-card .btn-block { margin-top: auto; }
.p-card:hover { box-shadow: var(--shadow-md); }
.p-card.featured {
  background: var(--surface-dark);
  color: var(--text-inv);
  border-color: var(--surface-dark);
  box-shadow: var(--shadow-lg);
}
.p-card.featured .p-detail { color: rgba(255,255,255,.4); border-color: rgba(255,255,255,.1); }
.p-card.featured .p-features li { border-color: rgba(255,255,255,.08); color: rgba(255,255,255,.65); }
.p-card.featured .p-features li.hl { color: white; font-weight: 500; }
.p-card.featured .p-yearly { color: rgba(255,255,255,.3); }
.p-badge {
  position: absolute; top: -10px; right: 16px;
  background: var(--red); color: white;
  font-size: .58rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em;
  padding: .2rem .65rem; border-radius: 50px;
}
.p-name { font-size: .68rem; text-transform: uppercase; letter-spacing: .1em; font-weight: 600; color: var(--text-3); margin-bottom: .75rem; }
.p-card.featured .p-name { color: var(--red); }
.p-price { font-family: var(--mono); font-size: 2.4rem; font-weight: 700; letter-spacing: -.03em; line-height: 1; }
.p-price small { font-size: .82rem; font-weight: 400; opacity: .4; }
.p-yearly { font-family: var(--mono); font-size: .7rem; color: var(--text-3); margin-top: .2rem; }
.p-detail {
  font-size: .78rem; color: var(--text-3);
  margin: .75rem 0 1.25rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--border);
}
.p-features { list-style: none; margin-bottom: 1.5rem; }
.p-features li {
  padding: .35rem 0;
  border-bottom: 1px solid var(--border);
  font-size: .78rem; color: var(--text-2);
  display: flex; align-items: center; gap: .5rem;
}
.p-features li:last-child { border-bottom: none; }
.p-features li::before {
  content: ''; width: 14px; height: 14px; flex-shrink: 0;
  border-radius: 50%;
  background: var(--green-light) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3E%3Cpath d='M1.5 4l1.5 1.5 3.5-3.5' fill='none' stroke='%231e8e3e' stroke-width='1.2' stroke-linecap='round'/%3E%3C/svg%3E") center no-repeat;
}
.p-card.featured .p-features li::before {
  background-color: rgba(30,142,62,.2);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3E%3Cpath d='M1.5 4l1.5 1.5 3.5-3.5' fill='none' stroke='%2366bb6a' stroke-width='1.2' stroke-linecap='round'/%3E%3C/svg%3E");
}

/* ---------------------------------------------------------------- */
/* API                                                               */
/* ---------------------------------------------------------------- */
.api { padding: 4rem 0; border-bottom: 1px solid var(--border); background: var(--surface); }
.api-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 3rem; align-items: start; }
.api-text h3 { font-size: 1.4rem; font-weight: 700; letter-spacing: -.02em; margin-bottom: .75rem; }
.api-text p { font-size: .88rem; color: var(--text-2); margin-bottom: 1.25rem; font-weight: 300; line-height: 1.6; }
.api-endpoints { list-style: none; }
.api-endpoints li {
  padding: .45rem 0; border-bottom: 1px solid var(--border);
  font-size: .8rem; display: flex; align-items: center; gap: .75rem;
}
.method {
  font-family: var(--mono); font-size: .62rem; font-weight: 600;
  text-transform: uppercase; min-width: 3rem; text-align: center;
  padding: .15rem .35rem; border-radius: 3px;
}
.method-get { background: var(--green-light); color: var(--green-text); }
.method-post { background: var(--blue-light); color: var(--blue-text); }
.method-del { background: var(--red-light); color: var(--red-text); }
.path { font-family: var(--mono); font-size: .75rem; color: var(--text-2); }

.api-code {
  background: var(--surface-dark);
  color: #b8b8b8;
  font-family: var(--mono); font-size: .75rem;
  padding: 1.5rem;
  border-radius: 10px;
  line-height: 1.8;
  box-shadow: var(--shadow-lg);
}
/* Syntax colours for the two dark code surfaces: the landing page's .api-code
   block and the .terminal blocks in the docs guides. They must be one selector
   list — the guides shipped .cmt/.kw spans for months against rules that only
   named .api-code, so comments and keywords rendered at the same brightness as
   the surrounding command text.
   The comment grey is #8b8b8b, not the former #616161: on --surface-dark that
   value measures 2.8:1 and fails WCAG AA for small text. #8b8b8b is 5.1:1 and
   still reads clearly dimmer than the .terminal/.api-code body colour
   (#b8b8b8, 8.8:1). */
.api-code .cmt, .terminal .cmt { color: #8b8b8b; }
.api-code .str, .terminal .str { color: #ef9a9a; }
.api-code .kw,  .terminal .kw  { color: #90a4ae; }

/* ---------------------------------------------------------------- */
/* Dashboard preview (landing page)                                  */
/* ---------------------------------------------------------------- */
.dash { padding: 4rem 0; border-bottom: 1px solid var(--border); }

/* ---------------------------------------------------------------- */
/* Portal chrome (used by landing preview + actual portal sidebar)   */
/* ---------------------------------------------------------------- */
.portal {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}
.portal-topbar {
  background: var(--surface-dark);
  color: var(--text-inv);
  padding: .6rem 1.25rem;
  display: flex; justify-content: space-between; align-items: center;
  font-size: .78rem;
}
.portal-topbar .brand { color: white; font-size: .9rem; }
.portal-topbar .brand em { color: var(--red); }
.portal-tabs { display: flex; gap: 0; }
.portal-tabs a, .portal-tabs span {
  padding: .4rem .85rem; font-size: .75rem; color: rgba(255,255,255,.5); font-weight: 500; transition: all .12s;
}
.portal-tabs a:hover { color: rgba(255,255,255,.8); }
.portal-tabs a.active, .portal-tabs span.active { color: white; background: rgba(255,255,255,.08); border-radius: 4px; }
.portal-body { display: grid; grid-template-columns: 190px 1fr; }
.portal-side {
  padding: 1.25rem;
  border-right: 1px solid var(--border);
  background: var(--surface-2);
}
.portal-side h4, .portal-side .preview-title {
  font-size: .6rem; text-transform: uppercase; letter-spacing: .12em;
  color: var(--text-3); font-weight: 600; margin-bottom: .65rem;
}
.portal-side ul { list-style: none; }
.portal-side li a, .portal-side li .preview-zone {
  display: flex; align-items: center; gap: .4rem;
  padding: .3rem .5rem; margin: 0 -.5rem;
  font-size: .78rem; color: var(--text-2); border-radius: 4px; transition: all .12s;
}
.portal-side li a:hover { background: var(--surface); color: var(--text); }
.portal-side li a.active, .portal-side li .preview-zone.active { background: var(--surface); color: var(--red); font-weight: 600; }
.portal-side .dot-ok, .portal-side .dot-err, .portal-side .dot-warn { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.portal-side .dot-ok { background: var(--green); }
.portal-side .dot-err { background: var(--red); }
.portal-side .dot-warn { background: var(--amber); }

.portal-main { padding: 1.5rem; }
.portal-main h2, .portal-main > .preview-title { font-size: 1.1rem; font-weight: 700; margin-bottom: 1.25rem; letter-spacing: -.02em; }

/* ---------------------------------------------------------------- */
/* Stats (dashboard cards)                                           */
/* ---------------------------------------------------------------- */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: .75rem; margin-bottom: 1.5rem; }
.stat {
  background: var(--surface-2);
  border-radius: 8px;
  padding: 1rem;
}
.stat-label { font-size: .6rem; text-transform: uppercase; letter-spacing: .1em; color: var(--text-3); font-weight: 500; margin-bottom: .15rem; }
.stat-value { font-family: var(--mono); font-size: 1.8rem; font-weight: 700; line-height: 1.2; }
.stat-value.ok { color: var(--green); }
.stat-value.err { color: var(--red); }
.stat-value.warn { color: var(--amber); }
/* .stat sits on --surface-2, where the brand green/red only reach ~3.7-4.2:1
   at this size — the darkened text variants clear 4.5:1 there. */
.stat-sub { font-family: var(--mono); font-size: .65rem; color: var(--green-text); margin-top: .1rem; }
.stat-sub.neg { color: var(--red-text); }

/* ---------------------------------------------------------------- */
/* Section head (table header with action button)                    */
/* ---------------------------------------------------------------- */
.section-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: .65rem; }
.section-head h3, .section-head .preview-title { font-size: .82rem; font-weight: 600; letter-spacing: -.02em; margin: 0; }

/* ---------------------------------------------------------------- */
/* Tables                                                            */
/* ---------------------------------------------------------------- */
table { width: 100%; border-collapse: collapse; font-size: .78rem; }
thead th {
  text-align: left; padding: .45rem .6rem;
  border-bottom: 2px solid var(--surface-dark);
  font-size: .6rem; text-transform: uppercase; letter-spacing: .1em;
  color: var(--text-3); font-weight: 600; background: var(--surface-2);
}
thead th.sortable { cursor: pointer; user-select: none; white-space: nowrap; }
thead th.sortable::after { content: "\2195"; opacity: .35; margin-left: .3em; }
thead th.sortable[data-dir="asc"]::after { content: "\2191"; opacity: .8; }
thead th.sortable[data-dir="desc"]::after { content: "\2193"; opacity: .8; }
td { padding: .45rem .6rem; border-bottom: 1px solid var(--border); color: var(--text-2); }
td a, td .preview-link { color: var(--text); font-weight: 600; }
td a:hover { color: var(--red); }

/* ---------------------------------------------------------------- */
/* Badges                                                            */
/* ---------------------------------------------------------------- */
.badge {
  display: inline-flex; align-items: center; gap: .25rem;
  padding: .12rem .45rem; border-radius: 50px;
  font-size: .62rem; font-weight: 600; text-transform: uppercase; letter-spacing: .03em;
  /* A badge is one label: breaking it mid-phrase ("NOT / REACHABLE") reads as
     two states and doubles the row height. */
  white-space: nowrap;
}
.badge::before { content: ''; width: 5px; height: 5px; border-radius: 50%; }
/* Badge text uses the --*-text variants (≥4.5:1 on the badge background);
   the ::before dot keeps the brighter brand hue — it is non-text and only
   needs 3:1. Both pinned by ui_contrast_test.go. */
.badge-ok { background: var(--green-light); color: var(--green-text); }
.badge-ok::before { background: var(--green); }
.badge-err { background: var(--red-light); color: var(--red-text); }
.badge-err::before { background: var(--red); }
.badge-pending { background: var(--amber-light); color: var(--amber-text); }
.badge-pending::before { background: var(--amber); }
/* badge-warn: amber, for states that are not broken but not done either
   (e.g. a signed zone whose DS is not published yet). */
.badge-warn { background: var(--amber-light); color: var(--amber-text); }
.badge-warn::before { background: var(--amber); }
.badge-info { background: var(--blue-light); color: var(--blue-text); }
.badge-info::before { background: var(--blue); }
.badge-success { background: var(--green-light); color: var(--green-text); }
.badge-success::before { background: var(--green); }
.badge-danger { background: var(--red-light); color: var(--red-text); }
.badge-danger::before { background: var(--red); }
.badge-muted { background: var(--surface-2); color: var(--text-3); }
.badge-muted::before { background: var(--text-3); }
.badge-accent { background: var(--red-light); color: var(--red-text); }
.badge-accent::before { background: var(--red); }
.mono { font-family: var(--mono); font-size: .75rem; }

/* ---------------------------------------------------------------- */
/* FAQ                                                               */
/* ---------------------------------------------------------------- */
.faq { padding: 4rem 0; border-bottom: 2px solid var(--text); background: var(--surface); }
.faq-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.5rem 2.5rem; }
.faq-item h3 { font-size: .9rem; font-weight: 600; margin-bottom: .4rem; }
.faq-item p { font-size: .8rem; color: var(--text-2); font-weight: 300; line-height: 1.6; margin: 0; }
/* Same SC 1.4.1 fix as `.imprint a` below — the landing FAQ had the identical
   colour-only link. */
.faq-item p a { color: var(--red-text); text-decoration: underline; text-underline-offset: 2px; text-decoration-thickness: 1px; }
.faq-item p a:hover, .faq-item p a:focus-visible { text-decoration-thickness: 2px; }

/* ---------------------------------------------------------------- */
/* CTA                                                               */
/* ---------------------------------------------------------------- */
.cta {
  padding: 5rem 0;
  background: var(--surface-dark);
  color: var(--text-inv);
  text-align: center;
}
.cta h2 { font-size: 2rem; font-weight: 700; letter-spacing: -.03em; margin-bottom: .65rem; }
.cta p { font-size: .95rem; color: rgba(255,255,255,.5); font-weight: 300; margin-bottom: 2rem; max-width: 440px; margin-left: auto; margin-right: auto; }
.cta-actions { display: flex; gap: .65rem; justify-content: center; }

/* ---------------------------------------------------------------- */
/* Imprint                                                           */
/* ---------------------------------------------------------------- */
.imprint { padding: 4rem 0 3rem; }
.imprint h1 { font-size: 2rem; font-weight: 700; letter-spacing: -.03em; margin-bottom: 2rem; }
/* Section heads on the public pages are h2. They sit directly under the page
   h1, so an h3 here made all 16 of them skip a heading level (WCAG 2.1
   SC 1.3.1 — the programmatic level must match the visual structure). The
   declarations are byte-for-byte the ones this rule carried as `.imprint h3`,
   so the pages render exactly as before; only the element moved. */
.imprint h2 { font-size: .95rem; font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--text-3); margin: 1.5rem 0 .5rem; }
/* Sub-heads within a section — the former h4s in the TSIG, Terraform and
   migration guides, demoted with their parents so the level step stays 1.
   Sized as they were as h4 rather than at the global h3 size. */
.imprint h3 { font-size: .95rem; margin: 1.25rem 0 .4rem; }
.imprint p { font-size: .95rem; color: var(--text-2); line-height: 1.7; }
/* Intro paragraph under the h1. Must be `.imprint .lead` (0,0,2,0), not a bare
   `.lead` (0,0,1,0): `.imprint p` above is 0,0,1,1 and would win, leaving a
   rule that exists and still does nothing. */
.imprint .lead { font-size: 1.05rem; color: var(--text); margin-bottom: .5rem; }
/* WCAG 2.1 SC 1.4.1 (Use of Color), failure F73: link red against the
   surrounding --text-2 body copy measures 1.56:1, far below the 3:1 that
   technique G183 requires before colour alone may carry the link — so the
   underline is permanent rather than hover-only, and it thickens on focus as
   well as hover. --red-text instead of --red also lifts the link itself from
   4.45:1 to 5.45:1 on --bg (SC 1.4.3 at the .imprint p size).
   NOTE: docs.html's whole-card links match this rule too and stay clean only
   because they carry inline `text-decoration:none;color:inherit`, which beats
   any non-!important rule. If those inline styles are ever refactored into a
   class, that class must restate both declarations or the ten cards suddenly
   render as underlined red blocks. */
.imprint a { color: var(--red-text); text-decoration: underline; text-underline-offset: 2px; text-decoration-thickness: 1px; }
.imprint a:hover, .imprint a:focus-visible { text-decoration-thickness: 2px; }

/* ---------------------------------------------------------------- */
/* Footer                                                            */
/* ---------------------------------------------------------------- */
footer { padding: 2.5rem 0; background: var(--surface-dark); color: rgba(255,255,255,.65); border-top: 1px solid #333; }
footer.simple { padding: 1.5rem 0; text-align: center; font-size: .78rem; }
.footer-grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 2rem; }
.footer-brand { font-weight: 700; font-size: 1rem; color: white; margin-bottom: .4rem; }
.footer-brand em { font-style: normal; color: var(--red); }
.footer-desc { font-size: .78rem; max-width: 260px; line-height: 1.55; }
.footer-col h5, .footer-col .footer-col-title { font-size: .6rem; text-transform: uppercase; letter-spacing: .12em; color: rgba(255,255,255,.5); font-weight: 600; margin-bottom: .65rem; }
.footer-col ul { list-style: none; }
.footer-col li { margin-bottom: .3rem; }
.footer-col a { font-size: .78rem; color: rgba(255,255,255,.65); transition: color .12s; }
.footer-col a:hover { color: white; }
.footer-bottom { margin-top: 2rem; padding-top: 1.25rem; border-top: 1px solid #333; display: flex; justify-content: space-between; font-size: .7rem; }

/* ---------------------------------------------------------------- */
/* Main layout (portal pages)                                        */
/* ---------------------------------------------------------------- */
main { flex: 1; padding: 1.5rem 0 3rem; }
body { min-height: 100vh; display: flex; flex-direction: column; }

.layout-sidebar {
  display: grid;
  grid-template-columns: 190px 1fr;
  gap: 1.5rem;
}
/* The content column — the anonymous <div> beside the <aside class="sidebar">
   in layout.html (the child combinator deliberately misses the aside). A grid
   item's implicit min-width is auto, so one wide data table stretches the 1fr
   track past the viewport and the whole page pans; min-width: 0 lets the track
   shrink so the table can scroll inside its column instead (the mobile media
   query below adds the overflow-x). Same fix as .portal-main carries for the
   landing preview. */
.layout-sidebar > div { min-width: 0; }

/* ---------------------------------------------------------------- */
/* Portal sidebar (reuse portal-side styles for actual sidebar)      */
/* ---------------------------------------------------------------- */
.sidebar {
  padding-top: .5rem;
  border-right: 1px solid var(--border);
  background: var(--surface-2);
  border-radius: 10px;
  padding: 1.25rem;
}
.sidebar h4 {
  font-size: .6rem; text-transform: uppercase; letter-spacing: .12em;
  color: var(--text-3); font-weight: 600; margin-bottom: .65rem;
}
.sidebar ul { list-style: none; }
.sidebar li a {
  display: flex; align-items: center; gap: .4rem;
  padding: .3rem .5rem; margin: 0 -.5rem;
  font-size: .78rem; color: var(--text-2); border-radius: 4px; transition: all .12s;
}
.sidebar li a:hover { background: var(--surface); color: var(--text); }
/* The zone you are currently looking at. The left rule carries the accent so
   the dot beside the name keeps meaning "transfer status" and nothing else. */
.sidebar li a.active {
  background: var(--surface);
  color: var(--text);
  font-weight: 600;
  box-shadow: inset 2px 0 0 var(--accent);
}
.sidebar .dot-ok, .sidebar .dot-err, .sidebar .dot-warn { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; display: inline-block; }
.sidebar .dot-ok { background: var(--green); }
.sidebar .dot-err { background: var(--red); }
.sidebar .dot-warn { background: var(--amber); }

/* ---------------------------------------------------------------- */
/* Cards (portal)                                                    */
/* ---------------------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.25rem;
  margin-bottom: 1rem;
}
.card-header {
  font-weight: 600;
  margin-bottom: 1rem;
  padding-bottom: .75rem;
  border-bottom: 1px solid var(--border);
}

/* ---------------------------------------------------------------- */
/* Tabs (zone detail nav)                                            */
/* ---------------------------------------------------------------- */
nav ul.tabs { display: flex; list-style: none; gap: .25rem; border-bottom: 2px solid var(--border); margin-bottom: 1.5rem; padding: 0; }
nav ul.tabs li a {
  display: block;
  padding: .5rem 1rem;
  font-size: .82rem;
  font-weight: 500;
  color: var(--text-3);
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  transition: all .15s;
}
nav ul.tabs li a:hover { color: var(--text); }
nav ul.tabs li a[aria-current="page"] {
  color: var(--red);
  border-bottom-color: var(--red);
}

/* ---------------------------------------------------------------- */
/* Forms                                                             */
/* ---------------------------------------------------------------- */
input[type="text"], input[type="email"], input[type="password"],
input[type="number"], input[type="url"], select, textarea {
  display: block; width: 100%;
  padding: .55rem .75rem;
  background: white;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-family: var(--font);
  font-size: .88rem;
  transition: all .15s;
  margin-bottom: 1rem;
  outline: none;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--text);
  box-shadow: 0 0 0 3px rgba(26,26,26,.06);
}
input::placeholder { color: var(--text-3); }
select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='%23999'%3E%3Cpath d='M6 8L1 3h10z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .75rem center;
  padding-right: 2rem;
}
label { display: block; font-size: .82rem; font-weight: 500; color: var(--text-2); margin-bottom: .35rem; }
/* A field that must span the whole width of a two-column form grid — used by
   the admin plan editor for the two entries that carry a long explanatory
   <small>. The class was in the markup for months with no rule behind it. */
.form-row { grid-column: 1 / -1; }
/* A control sized to sit inline beside a button instead of filling its row
   (the form controls above are display:block/width:100% with a 1rem margin).
   padding-right is deliberately NOT set: `select` reserves 2rem there for its
   drop-down arrow, and a `padding` shorthand here would print the arrow on top
   of the selected option's text. */
.input-sm {
  display: inline-block; width: auto; margin-bottom: 0; font-size: .78rem;
  padding-top: .3rem; padding-bottom: .3rem; padding-left: .5rem;
}
fieldset { border: 1px solid var(--border); border-radius: var(--radius); padding: 1.25rem; margin-bottom: 1rem; }
fieldset legend { padding: 0 .5rem; font-weight: 600; font-size: .82rem; color: var(--text-2); }

/* ---------------------------------------------------------------- */
/* Description lists                                                 */
/* ---------------------------------------------------------------- */
dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: .4rem 1.5rem;
  font-size: .88rem;
}
dt { color: var(--text-3); font-weight: 500; }
dd { color: var(--text); font-family: var(--mono); font-size: .82rem; }

/* ---------------------------------------------------------------- */
/* Code / pre                                                        */
/* ---------------------------------------------------------------- */
code, pre {
  font-family: var(--mono);
  font-size: .82rem;
}
code {
  background: var(--surface-2);
  border: 1px solid var(--border);
  padding: .15em .4em;
  border-radius: 4px;
  color: var(--text);
}
pre {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem;
  overflow-x: auto;
  color: var(--text-2);
}
pre code {
  background: none;
  border: none;
  padding: 0;
  color: inherit;
}

/* ---------------------------------------------------------------- */
/* Auth container                                                    */
/* ---------------------------------------------------------------- */
.auth-container { max-width: 420px; margin: 3rem auto; padding: 0 2rem; }
/* Register honeypot: moved off-screen, not display:none, which form bots skip. */
.hp-trap { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }

/* ---------------------------------------------------------------- */
/* Alerts                                                            */
/* ---------------------------------------------------------------- */
.alert {
  padding: .75rem 1rem;
  border-radius: var(--radius);
  font-size: .82rem;
  margin-bottom: 1rem;
  border: 1px solid;
}
.alert-error, [role="alert"] {
  background: var(--red-light);
  border-color: var(--red);
  color: var(--red-dark);
  display: block;
  padding: .75rem 1rem;
  border-radius: var(--radius);
  font-size: .82rem;
  margin-bottom: 1rem;
}
.alert-success {
  background: var(--green-light);
  border-color: var(--green);
  color: var(--green-text);
}
.alert-info {
  background: var(--blue-light);
  border-color: var(--blue);
  color: var(--blue-text);
}

/* ---------------------------------------------------------------- */
/* Plans grid (billing page)                                         */
/* ---------------------------------------------------------------- */
.plans-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1.25rem;
}
.plan-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.5rem;
  text-align: center;
  transition: all .15s;
}
.plan-card:hover { box-shadow: var(--shadow-md); border-color: #ccc; }
.plan-card .plan-name {
  font-size: .68rem; text-transform: uppercase; letter-spacing: .1em;
  font-weight: 600; color: var(--text-3); margin-bottom: .75rem;
}
.plan-card .plan-price {
  font-family: var(--mono); font-size: 2.2rem; font-weight: 700;
  color: var(--text); line-height: 1; margin-bottom: .25rem;
}
.plan-card .plan-price small {
  font-size: .82rem; color: var(--text-3); font-weight: 400;
}
.plan-card .plan-yearly {
  font-family: var(--mono); font-size: .7rem; color: var(--text-3); margin-bottom: 1rem;
}
.plan-card ul {
  list-style: none; text-align: left;
  margin-bottom: 1.25rem; font-size: .82rem;
}
.plan-card ul li {
  padding: .35rem 0; color: var(--text-2);
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: .5rem;
}
.plan-card ul li:last-child { border-bottom: none; }
.plan-card ul li::before {
  content: ''; width: 14px; height: 14px; flex-shrink: 0;
  border-radius: 50%;
  background: var(--green-light) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3E%3Cpath d='M1.5 4l1.5 1.5 3.5-3.5' fill='none' stroke='%231e8e3e' stroke-width='1.2' stroke-linecap='round'/%3E%3C/svg%3E") center no-repeat;
}

/* ---------------------------------------------------------------- */
/* Utilities                                                         */
/* ---------------------------------------------------------------- */
.flex { display: flex; }
.flex-between { display: flex; justify-content: space-between; align-items: center; }
.gap-sm { gap: .5rem; }
.gap-md { gap: 1rem; }
.mt-1 { margin-top: .5rem; }
.mt-2 { margin-top: 1rem; }
.mt-3 { margin-top: 1.5rem; }
.mb-1 { margin-bottom: .5rem; }
.mb-2 { margin-bottom: 1rem; }
.mb-3 { margin-bottom: 1.5rem; }
.text-center { text-align: center; }
.text-muted { color: var(--text-3); }
.text-sm { font-size: .78rem; }
/* Text utilities land on white cards AND the #f7f7f5 page background; the
   brand hues miss 4.5:1 on at least one of those (green 3.92 on --bg, red
   4.45, amber 4.46), so they use the darkened text variants. */
.text-error { color: var(--red-text); }
.text-success { color: var(--green-text); }
.text-warning { color: var(--amber-text); }
.text-mono { font-family: var(--mono); }
.inline-form { display: inline; margin: 0; }

hr {
  border: none;
  border-top: 1px solid var(--border);
  margin: 1.5rem 0;
}

small { color: var(--text-3); font-size: .82rem; }

h1, h2, h3, h4, h5 {
  font-weight: 600;
  color: var(--text);
  letter-spacing: -.02em;
  line-height: 1.2;
}
h2 { font-size: 1.3rem; margin-bottom: 1rem; }
h3 { font-size: 1rem; margin-bottom: .75rem; }

p { margin-bottom: 1rem; }

mark { background: none; padding: 0; }

/* ---------------------------------------------------------------- */
/* Zone validation                                                   */
/* ---------------------------------------------------------------- */
.validation-issues {
    display: block;
    padding: 0 16px 12px;
}
.validation-issue {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 8px 0;
    border-bottom: 1px solid var(--border);
}
.validation-issue:last-child {
    border-bottom: none;
}
.validation-issue-body {
    flex: 1;
}
.validation-issue-msg {
    font-size: 0.8rem;
    font-weight: 500;
}

/* ---------------------------------------------------------------- */
/* Responsive                                                        */
/* ---------------------------------------------------------------- */
@media (max-width: 768px) {
  .hero-grid, .f-grid, .p-grid, .stats, .api-grid, .steps, .uc-grid, .value-list, .portal-body, .footer-grid, .layout-sidebar, .faq-grid { grid-template-columns: 1fr; }
  .hero h1 { font-size: 2.2rem; }
  .trust .container { gap: 1.5rem; }
  .portal-side { display: none; }
  .sidebar { display: none; }
  dl { grid-template-columns: 1fr; }
  nav .container { flex-wrap: wrap; justify-content: center; gap: .25rem; }
  .nav-links { flex-wrap: wrap; justify-content: center; }
  /* Preview tables scroll inside the card instead of clipping (also resets
     the grid item's implicit min-width so the track can shrink). */
  .portal-main { overflow-x: auto; }
  .portal-topbar { flex-wrap: wrap; gap: .4rem; }
  /* Real portal: .layout-sidebar collapses to one column above (the aside is
     hidden), leaving the content div as the only grid item. With its
     min-width: 0 (set unconditionally next to .layout-sidebar) this makes
     wide tables scroll inside the column instead of panning the whole page. */
  .layout-sidebar > div { overflow-x: auto; }
  /* Six zone-detail tabs exceed a phone viewport: the tab bar scrolls
     horizontally on its own (flex items already refuse to wrap). */
  nav ul.tabs { overflow-x: auto; }
  nav ul.tabs li a { white-space: nowrap; }
}
