/* Portfara — the public surface (phase 6)
   ======================================

   This stylesheet is DELIBERATELY not wired to frontend/src/lib/tokens.js, and
   that is not an oversight to be tidied up later.

   Three reasons, in order of weight:

     1. Different medium. Marketing type runs two to three steps larger than app
        type and wants more air; the app's scale exists to fit dense tables into
        a workspace. Sharing one scale would compromise both.
     2. Different origin. Once the app moves to app.portfara.com this file is
        served by Caddy from a static directory, with no build step and no
        bundler. A JS module cannot reach it.
     3. `check:tokens` only scans frontend/src, so a shared palette would grow a
        consumer the guard cannot see — worse than an honest, stated copy.

   The values below are RELATED to the app's (same blues, same amber off the
   wordmark) but they are their own set. If the app's palette moves, this does
   not automatically follow, and that is the intended behaviour.

   ZERO JAVASCRIPT. Theme comes from prefers-color-scheme, the FAQ from native
   <details>, and there is no script tag on any page — which is what lets the
   Caddy block set `script-src 'none'` and lets /security say so honestly.
*/

/* --- Fonts ---------------------------------------------------------------
   Self-hosted, same face as the app. No fonts.gstatic.com, so no visitor IP
   reaches Google and font-src stays 'self'. */
@font-face {
  font-family: "DM Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/dm-sans-latin-400-normal.woff2") format("woff2");
}
@font-face {
  font-family: "DM Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/fonts/dm-sans-latin-500-normal.woff2") format("woff2");
}
@font-face {
  font-family: "DM Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/fonts/dm-sans-latin-700-normal.woff2") format("woff2");
}

/* --- Palette -------------------------------------------------------------
   Dark is the identity. The app is a dark, dense instrument and every
   screenshot is dark, so a dark page lets the captures sit IN the layout
   rather than float in a white void. Light is a full, tested variant rather
   than an afterthought: visitors arrive with whatever setting they arrive
   with. */
:root {
  --ground:     #0E1114;
  --ground-2:   #161A1D;
  --surface:    #1A1F24;
  --surface-2:  #242B32;
  --line:       #2A3238;
  --line-soft:  #21282E;

  --ink:        #E8EDF2;
  --ink-mid:    #A6B4BF;
  --ink-faint:  #8496A4;

  --accent:     #41BBD9;
  --accent-ink: #0E1114;
  --accent-bg:  #15343E;
  --amber:      #F0A03C;
  --good:       #1DB37E;

  --shot-frame:  #2A3238;
  --shot-shadow: 0 8px 24px rgba(0, 0, 0, 0.38);

  --measure: 68ch;
  --page: 1120px;
  --r-sm: 6px;
  --r-md: 10px;
  --r-lg: 16px;
}

@media (prefers-color-scheme: light) {
  :root {
    --ground:     #FFFFFF;
    --ground-2:   #F4F7F9;
    --surface:    #FFFFFF;
    --surface-2:  #F0F3F5;
    --line:       #E2E8ED;
    --line-soft:  #EDF1F4;

    --ink:        #141A20;
    --ink-mid:    #43505F;
    --ink-faint:  #5A6A78;

    --accent:     #006E90;
    --accent-ink: #FFFFFF;
    --accent-bg:  #E1F0F5;

    /* Darker than the wordmark's own orange. The swoosh is a graphic at a 3:1
       floor; this token is used as TEXT, which answers to 4.5:1. Same family,
       different job — the app records the identical split as gain/gainText. */
    --amber:      #A85F13;
    --good:       #0F7F58;

    --shot-frame:  #D6DEE5;
    --shot-shadow: 0 6px 18px rgba(20, 34, 48, 0.11);
  }
}

/* --- Reset and base ------------------------------------------------------*/
*, *::before, *::after { box-sizing: border-box; }

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

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: "DM Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; display: block; }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { text-decoration-thickness: 2px; }

/* The app learned this the hard way — nineteen components killed their focus
   ring with an inline outline:none and the CSS comment claimed it was fixed.
   Nothing in this file overrides it. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

h1, h2, h3 { line-height: 1.15; letter-spacing: -0.02em; margin: 0; text-wrap: balance; }
p { margin: 0; text-wrap: pretty; }

.skip {
  position: absolute;
  left: -9999px;
  background: var(--accent);
  color: var(--accent-ink);
  padding: 10px 16px;
  border-radius: var(--r-sm);
  z-index: 100;
}
.skip:focus { left: 12px; top: 12px; }

.wrap {
  width: 100%;
  max-width: var(--page);
  margin-inline: auto;
  padding-inline: 24px;
}

/* --- Header --------------------------------------------------------------*/
/* Opaque, not a translucent blur. A backdrop-filter on a sticky element forces
   the whole page onto its own compositing layer, which cost real frames here
   and made screenshot capture time out outright. The visual gain was a few
   pixels of show-through; the cost was a header that could stall the page. */
.site-head {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--ground);
  border-bottom: 1px solid var(--line-soft);
}
.site-head > .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 80px;
}
.brand { display: inline-flex; align-items: center; }
.brand img { height: 44px; width: auto; }

/* One wordmark per theme. The dark asset carries light ink and the light asset
   dark ink, so the wrong one is INVISIBLE rather than merely off — which is
   why this is two <img> and a media query, not one file. */
.brand .on-dark { display: block; }
.brand .on-light { display: none; }
@media (prefers-color-scheme: light) {
  .brand .on-dark { display: none; }
  .brand .on-light { display: block; }
}

.nav { display: flex; align-items: center; gap: 6px; }
.nav a {
  color: var(--ink-mid);
  text-decoration: none;
  padding: 8px 12px;
  border-radius: var(--r-sm);
  font-size: 15px;
}
.nav a:hover { color: var(--ink); background: var(--surface-2); }
.nav a[aria-current="page"] { color: var(--ink); }

/* Language switch. Two plain links in a bordered pill, not a select or any
   script — the landing has no JS at all (script-src 'none'), so switching
   language is just navigating to the other static tree (/ vs /tr/). The
   current language is the non-interactive-looking one: bold, no hover
   affordance, and it still points at itself rather than being a <span>, so
   a screen reader announces it the same way as the other option. */
.lang-toggle {
  display: inline-flex;
  align-items: center;
  margin-left: 4px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  overflow: hidden;
}
.lang-toggle a {
  padding: 6px 10px;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-mid);
  text-decoration: none;
  border-radius: 0;
}
.lang-toggle a:hover { background: var(--surface-2); color: var(--ink); }
.lang-toggle a[aria-current="page"] {
  background: var(--surface-2);
  color: var(--ink);
  font-weight: 700;
  cursor: default;
  pointer-events: none;
}

/* --- Buttons -------------------------------------------------------------*/
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 20px;
  border-radius: var(--r-sm);
  font-size: 15px;
  font-weight: 500;
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
.btn-primary { background: var(--accent); color: var(--accent-ink); }
.btn-primary:hover { background: color-mix(in srgb, var(--accent) 86%, var(--ink)); }
.btn-ghost { border-color: var(--line); color: var(--ink); }
.btn-ghost:hover { background: var(--surface-2); border-color: var(--ink-faint); }
.btn-sm { padding: 8px 14px; font-size: 14px; }

/* Nav labels and buttons must never wrap. Measured at 375px: "Sign in" broke
   across two lines and pushed the sticky header to 135px — a sixth of the
   viewport gone before any content, on the devices most visitors arrive on. */
.btn, .nav a { white-space: nowrap; }

@media (max-width: 560px) {
  .wrap { padding-inline: 16px; }
  .site-head > .wrap { min-height: 60px; gap: 8px; }
  .brand img { height: 30px; }
  .nav { gap: 2px; }
  .nav a { padding: 6px 8px; font-size: 14px; }
  .nav .btn-sm { padding: 7px 11px; }
  .lang-toggle a { padding: 5px 7px; font-size: 12px; }
}

/* --- Hero ----------------------------------------------------------------*/
.hero { padding: clamp(56px, 9vw, 108px) 0 0; text-align: center; }
.hero h1 {
  font-size: clamp(2.3rem, 6vw, 4.1rem);
  font-weight: 700;
  letter-spacing: -0.035em;
  max-width: 16ch;
  margin-inline: auto;
}
.hero .lead {
  margin: 22px auto 0;
  max-width: 56ch;
  font-size: clamp(1.05rem, 1.9vw, 1.28rem);
  color: var(--ink-mid);
}
.hero .cta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-top: 32px;
}
.hero .beta { margin-top: 16px; font-size: 14px; color: var(--ink-faint); }

/* --- Screenshots ---------------------------------------------------------
   A dark UI capture on a dark page needs a hairline to say where the product
   ends and the page begins. The frame is that hairline, not decoration. */
.shot {
  border: 1px solid var(--shot-frame);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--ground-2);
  box-shadow: var(--shot-shadow);
}
.shot img { width: 100%; }
.shot-hero { margin-top: clamp(40px, 6vw, 72px); }
figure { margin: 0; }
figcaption { margin-top: 12px; font-size: 14px; color: var(--ink-faint); text-align: center; }

/* --- Trust strip ---------------------------------------------------------*/
.trust {
  margin-top: clamp(48px, 7vw, 84px);
  border-block: 1px solid var(--line-soft);
  background: var(--ground-2);
}
.trust ul {
  list-style: none;
  margin: 0;
  padding: 22px 0;
  display: grid;
  gap: 14px 28px;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.trust li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 14.5px;
  color: var(--ink-mid);
}
.trust svg { flex: none; width: 17px; height: 17px; margin-top: 2px; color: var(--accent); }
.trust strong { color: var(--ink); font-weight: 500; }

/* --- Feature bands -------------------------------------------------------*/
.band {
  padding: clamp(64px, 10vw, 116px) 0;
  border-bottom: 1px solid var(--line-soft);
}
.band-inner {
  display: grid;
  gap: clamp(32px, 5vw, 64px);
  align-items: center;
  grid-template-columns: 1fr;
}
@media (min-width: 900px) {
  .band-inner { grid-template-columns: 0.85fr 1.15fr; }

  /* Flipping with `order` alone moves the shot into the NARROW column, so
     alternating bands rendered their screenshots at two different sizes —
     measured 578px against 426px. Reversing the track widths keeps the shot on
     the wide side whichever way round the band is read. */
  .band-flip { grid-template-columns: 1.15fr 0.85fr; }
  .band-flip .band-copy { order: 2; }
  .band-flip .band-shot { order: 1; }
}
.eyebrow {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 14px;
}
.band h2 { font-size: clamp(1.65rem, 3.2vw, 2.35rem); font-weight: 700; }
.band .body { margin-top: 16px; color: var(--ink-mid); font-size: 1.02rem; }
.band .body + .body { margin-top: 12px; }

.points { list-style: none; margin: 24px 0 0; padding: 0; display: grid; gap: 11px; }
.points li {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  font-size: 15px;
  color: var(--ink-mid);
}
.points svg { flex: none; width: 16px; height: 16px; margin-top: 4px; color: var(--good); }

/* --- Coverage ------------------------------------------------------------*/
.coverage { padding: clamp(64px, 9vw, 100px) 0; border-bottom: 1px solid var(--line-soft); }
.coverage h2 { font-size: clamp(1.5rem, 2.8vw, 2rem); font-weight: 700; }
.coverage .body { margin-top: 14px; color: var(--ink-mid); max-width: var(--measure); }
.chips { list-style: none; margin: 28px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 9px; }
.chips li {
  font-size: 14px;
  color: var(--ink-mid);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 7px 15px;
  background: var(--surface);
}

/* --- Security band -------------------------------------------------------*/
.security {
  padding: clamp(64px, 10vw, 116px) 0;
  border-bottom: 1px solid var(--line-soft);
  background: var(--ground-2);
}
.security h2 { font-size: clamp(1.65rem, 3.2vw, 2.35rem); font-weight: 700; max-width: 20ch; }
.security .body { margin-top: 18px; color: var(--ink-mid); max-width: var(--measure); }

/* border-radius stays 0 — a single-sided border with rounded corners reads as
   a rendering bug. The app's design notes make the same point. */
.pull {
  margin-top: 30px;
  padding: 22px 26px;
  border-left: 3px solid var(--accent);
  background: var(--accent-bg);
  border-radius: 0;
  font-size: 1.06rem;
  color: var(--ink);
}
.pull span { display: block; margin-top: 10px; font-size: 14px; color: var(--ink-mid); }

/* --- FAQ -----------------------------------------------------------------*/
.faq { padding: clamp(64px, 9vw, 100px) 0; }
.faq h2 { font-size: clamp(1.5rem, 2.8vw, 2rem); font-weight: 700; margin-bottom: 28px; }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  cursor: pointer;
  padding: 20px 0;
  list-style: none;
  font-size: 1.05rem;
  font-weight: 500;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "";
  flex: none;
  width: 10px;
  height: 10px;
  border-right: 2px solid var(--ink-faint);
  border-bottom: 2px solid var(--ink-faint);
  transform: rotate(45deg);
  transition: transform 0.18s ease;
  margin-right: 4px;
}
.faq details[open] summary::after { transform: rotate(-135deg); }
.faq .answer { padding: 0 0 22px; color: var(--ink-mid); max-width: var(--measure); }

/* --- Footer --------------------------------------------------------------*/
.site-foot { border-top: 1px solid var(--line); background: var(--ground-2); padding: 56px 0 40px; }
.foot-cols { display: grid; gap: 32px; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
.foot-cols h3 {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 14px;
}
.foot-cols ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.foot-cols a { color: var(--ink-mid); text-decoration: none; font-size: 15px; }
.foot-cols a:hover { color: var(--ink); text-decoration: underline; }
.foot-cols .muted { color: var(--ink-faint); font-size: 15px; }
.foot-base {
  margin-top: 44px;
  padding-top: 24px;
  border-top: 1px solid var(--line-soft);
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: space-between;
  font-size: 14px;
  color: var(--ink-faint);
}

/* --- Document pages (/security, /about) ----------------------------------*/
.doc {
  padding: clamp(48px, 7vw, 88px) 0 clamp(64px, 9vw, 104px);
  /* A step down from the 17px body. These pages are long-form reading rather
     than a landing pitch, and the larger scale read as shouting. Headings
     below come down with it so the rhythm between levels is unchanged. */
  font-size: 15.5px;
  line-height: 1.62;
}

/* Centre the reading column inside the full-width wrap. Left-aligned, a 68ch
   measure inside a 1120px page leaves the right half of the screen empty and
   reads as a broken grid rather than as a deliberate measure. The header keeps
   the full width, so the page still frames at 1120. */
.doc-head,
.doc section,
.doc .updated { margin-inline: auto; }
.doc-head { max-width: var(--measure); }
.doc .updated { max-width: var(--measure); }
.doc-head h1 { font-size: clamp(1.75rem, 3.6vw, 2.35rem); font-weight: 700; }
.doc-head .lead { margin-top: 18px; font-size: clamp(0.98rem, 1.45vw, 1.08rem); color: var(--ink-mid); }
.doc section { margin-top: clamp(44px, 6vw, 68px); max-width: var(--measure); }
.doc h2 { font-size: clamp(1.18rem, 2vw, 1.4rem); font-weight: 700; }
.doc h3 { font-size: 1rem; font-weight: 500; margin-top: 26px; }
.doc p { margin-top: 14px; color: var(--ink-mid); }
.doc ul { margin: 16px 0 0; padding-left: 0; list-style: none; display: grid; gap: 12px; }
.doc ul li { display: flex; gap: 11px; align-items: flex-start; color: var(--ink-mid); }
.doc ul svg { flex: none; width: 16px; height: 16px; margin-top: 5px; color: var(--good); }
.doc .note {
  margin-top: 22px;
  padding: 18px 22px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  color: var(--ink-mid);
  font-size: 15px;
}
.doc .note strong { color: var(--ink); font-weight: 500; }

.card-grid {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  margin-top: 24px;
}
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 22px;
}
.card h3 { margin: 0 0 8px; font-size: 1rem; font-weight: 500; }
.card p { margin: 0; font-size: 14.5px; color: var(--ink-mid); }

.updated { margin-top: 56px; font-size: 14px; color: var(--ink-faint); }

/* --- Legal pages (/privacy, /terms, /cookies, /imprint, /sources) ---------
   Added 2026-09-16. Tables carry the inventory, recipients and retention —
   the parts a reader scans rather than reads — so they scroll inside their
   own box on a phone instead of widening the page. */
.doc .legal-meta { margin-top: 16px; font-size: 13.2px; color: var(--ink-faint); }
.doc ul.plain { list-style: disc; padding-left: 1.25em; gap: 8px; }
.doc ul.plain li { display: list-item; }
.doc .table-scroll { margin-top: 18px; overflow-x: auto; }
.doc table { width: 100%; border-collapse: collapse; font-size: 13.6px; line-height: 1.5; }
.doc th,
.doc td { text-align: left; vertical-align: top; padding: 10px 12px 10px 0; border-bottom: 1px solid var(--line); color: var(--ink-mid); }
.doc th { color: var(--ink); font-weight: 500; font-size: 12.4px; letter-spacing: 0.02em; }
.doc td:first-child { color: var(--ink); }
.doc table code { font-size: 0.92em; }
/* A draft placeholder. scripts/check_legal_pages.py fails CI while any page
   contains one, so this style exists for review builds only. */
.doc .todo { background: #FFE58A; color: #1A1A1A; padding: 0 4px; border-radius: 3px; font-weight: 600; }
