/* ==========================================================================
   CyberVPN, Design Tokens  ·  "Field Notes" editorial system
   Warm graphite ground, a single burnt-copper signal, paper-cream ink.
   A dossier/press-kit reading of a security product, serif display type,
   typewriter data, hairline rules, in place of the violet-glass SaaS
   default. No neon, no motion tied to the cursor, no background grid.
   ========================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,340;9..144,480;9..144,600&family=Inter:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&display=swap');

:root{
  /* surfaces, warm graphite, not cold black */
  --void:        #0a0906;
  --void-2:      #0e0c08;
  --panel:       #141109;
  --panel-2:     #1a160d;
  --line:        rgba(244,240,229,0.09);
  --line-strong: rgba(244,240,229,0.18);
  --hair:        rgba(244,240,229,0.06);

  /* one restrained signal color, burnt copper, plus cream as the true accent */
  --violet:      #c2683c;
  --violet-2:    #e08a54;
  --violet-dim:  rgba(194,104,60,0.32);

  /* text, paper cream, not pure white */
  --ink-0:       #f4efe3;
  --ink-1:       #cdc4b0;
  --ink-2:       #928871;
  --ink-3:       #5a5340;

  /* state, a cool mint reads as "verified" against the warm ground */
  --ok:          #7fd4ab;
  --warn:        #e0b054;
  --danger:      #e2685a;

  /* type, editorial serif display, typewriter data, humanist body */
  --f-display: 'Fraunces', Georgia, serif;
  --f-body:    'Inter', system-ui, sans-serif;
  --f-mono:    'IBM Plex Mono', 'SFMono-Regular', monospace;

  /* geometry, near-square, drafting-table precision; pills reserved for controls */
  --radius-xs: 2px;
  --radius-s:  3px;
  --radius-m:  4px;
  --radius-l:  6px;
  --radius-pill: 999px;

  --ease-out:    cubic-bezier(.16,.8,.3,1);
  --ease-spring: cubic-bezier(.34,1.56,.64,1);
}

*, *::before, *::after{ box-sizing: border-box; }
html{ scroll-behavior: smooth; height: 100%; }
html, body{ min-height: 100%; }

@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior: auto; }
  *, *::before, *::after{
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

body{
  margin: 0;
  background: var(--void);
  color: var(--ink-0);
  font-family: var(--f-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3, h4{
  font-family: var(--f-display);
  font-weight: 480;
  font-optical-sizing: auto;
  line-height: 1.04;
  margin: 0;
  letter-spacing: -0.01em;
}
h1, h2{ font-weight: 480; }
h3, h4{ font-weight: 600; }

p{ margin: 0; color: var(--ink-1); }
a{ color: inherit; text-decoration: none; }
ul{ list-style: none; margin: 0; padding: 0; }
button{ font-family: inherit; cursor: pointer; }
img, svg{ display: block; max-width: 100%; }

::selection{ background: var(--violet); color: var(--ink-0); }

:focus-visible{
  outline: 2px solid var(--violet-2);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ==========================================================================
   Ambient background, a live, continuously-animated line-field shader
   (see /js/floating-lines-bg.js), rendered on a <canvas> that JS injects
   into .ambient. No grid, no particles. Motion is driven purely by time;
   nothing here or in the JS reacts to the cursor. Fixed, pointer-events:
   none, z-index: -1, strictly behind .wrap (z-index: 1) so it can never
   block clicks, hovers, or form interactions.

   .ambient itself carries the CSS gradient fallback that's visible
   immediately on load and stays visible underneath the canvas the whole
   time (the canvas uses mix-blend-mode: screen, so it adds light on top
   rather than covering this gradient), and it's also the only thing
   shown if WebGL is unavailable and the canvas never renders.

   FULL-VIEWPORT COVERAGE, DONE RIGHT:
   This layer is pinned with `position: fixed; inset: 0`, NOT sized with
   `width: 100vw; height: 100vh`. That distinction is the actual fix for
   the black-bar/cropping bug, and it's worth spelling out why, because
   100vw/100vh looks "more explicit" but is the less correct tool here:

     - `100vw` is measured against the *window* width, which on desktop
       Chrome/Firefox/Edge includes the vertical scrollbar's track. The
       real visible area (`document.documentElement.clientWidth`) is
       narrower than that by the scrollbar's width, so a `100vw` box
       overshoots past the right edge of the visible page, on a page
       with `overflow-x: hidden` that overshoot doesn't create a
       scrollbar, but the element is still wider than the viewport and
       can be clipped/mis-clipped by the UA in exactly the "cropped"
       way described.
     - `100vh` is pinned to the *largest possible* viewport (address bar
       hidden). Mobile browsers show/hide their chrome without
       necessarily re-running layout in a way that recomputes a `vh`-sized
       fixed element in step, so while the address bar is visible, the
       real visible viewport is shorter than the `100vh` box reserved,
       and the difference is exactly the solid black strip at the bottom
       (the body's own `--void` background showing through the gap).

   `inset: 0` sizes the box directly from its four edges against the
   viewport (the initial containing block, since no ancestor here sets
   transform/filter/perspective/will-change/contain to hijack it) rather
   than from a width/height *calculation*, there is no scrollbar-gutter
   arithmetic to get wrong and no "largest possible" vs "currently
   visible" distinction to fall out of sync with. It is the one CSS
   value that structurally cannot overshoot or undershoot the viewport,
   which is why it, not 100vw/100vh, is what "strictly covers the
   entire viewport" actually requires. This block, and everything else
   in style.css, is shared by index.html, auth.html, and dashboard.html,
   so the fix applies identically across the whole app.
   ========================================================================== */

.ambient{
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
  /* Brighter, immediately-visible fallback wash, this alone (no JS,
     no WebGL) must already read as "warm copper ember on graphite", not
     black, and not the previous violet/blue. */
  background:
    radial-gradient(ellipse 62% 48% at 14% -6%, rgba(224,138,84,0.26), transparent 62%),
    radial-gradient(ellipse 58% 44% at 100% 6%, rgba(194,104,60,0.20), transparent 66%),
    radial-gradient(ellipse 70% 60% at 50% 100%, rgba(122,72,46,0.16), transparent 70%);
}

.ambient-canvas{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
  /* 'screen' keeps every line additive/glowing against the obsidian base
     and the fallback gradient beneath it, rather than producing a flat
     block of color. */
  mix-blend-mode: screen;
  opacity: 0;
  transition: opacity 0.6s var(--ease-out);
}

.ambient-canvas--ready{
  opacity: 0.55;
}

.noise-vignette{
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  /* `farthest-corner` (not a fixed % radius) guarantees the 100% stop
     lands exactly on the box's farthest corner regardless of viewport
     height/aspect ratio, so tall/large-monitor viewports can no longer
     fall past the ellipse's edge into a flat solid-black region below it,
     which is what caused the black band on tall screens.

     The flat rgba(...) layer stacked underneath it is new: the radial
     vignette alone only darkens the far edges/corners, so a bright
     shader line crossing the *middle* of the viewport (e.g. behind the
     hero paragraph) passed through it completely untouched and washed
     out pale text sitting on top of it. This flat layer dims the whole
     viewport evenly, including the middle, on top of the canvas'
     own reduced opacity above, so no single line can read as
     near-white against light text anymore. */
  background:
    radial-gradient(ellipse farthest-corner at 50% -10%, transparent 40%, var(--void) 100%),
    rgba(10, 9, 6, 0.4);
}

/* ==========================================================================
   Layout shells
   ========================================================================== */

.wrap{ position: relative; z-index: 1; }
.container{ max-width: 1180px; margin: 0 auto; padding: 0 24px; }

.eyebrow{
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--f-mono);
  font-size: 11.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.eyebrow::before{
  content: '';
  width: 18px; height: 1px;
  background: var(--violet-2);
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn{
  --btn-h: 50px;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  height: var(--btn-h);
  padding: 0 26px;
  border-radius: var(--radius-s);
  font-family: var(--f-mono);
  font-weight: 500;
  font-size: 13.5px;
  letter-spacing: 0.02em;
  border: 1px solid transparent;
  transition: transform .2s var(--ease-out), box-shadow .2s var(--ease-out), border-color .2s, background .2s;
  white-space: nowrap;
}
.btn:active{ transform: translateY(1px); }

.btn-primary{
  color: var(--void);
  background: var(--violet-2);
  border-color: var(--violet-2);
  font-weight: 600;
}
.btn-primary:hover{
  background: #eda874;
  border-color: #eda874;
  box-shadow: 0 8px 22px -10px rgba(224,138,84,.55);
}

.btn-ghost{
  color: var(--ink-0);
  background: rgba(10,9,6,0.35);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border-color: var(--line-strong);
}
.btn-ghost:hover{
  border-color: var(--violet-2);
  color: var(--violet-2);
  background: rgba(10,9,6,0.5);
}

.btn-block{ width: 100%; }
.btn-sm{ --btn-h: 38px; padding: 0 16px; font-size: 12px; }

/* ==========================================================================
   Glass panel, reworked as a "field card": a warm paper-toned surface
   with one quiet hairline border and a faint inset top highlight, like
   card stock rather than frosted glass. Blur kept minimal so it still
   separates from busy backgrounds without reading as generic
   glassmorphism.
   ========================================================================== */

.glass{
  position: relative;
  background: linear-gradient(175deg, rgba(26,22,13,0.92), rgba(16,13,8,0.88));
  border: 1px solid var(--line);
  border-radius: var(--radius-l);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 1px 0 0 rgba(244,240,229,0.05) inset, 0 24px 50px -32px rgba(0,0,0,0.75);
}

/* ==========================================================================
   Nav
   ========================================================================== */

.nav{
  position: sticky;
  top: 0;
  z-index: 50;
  padding: 18px 0;
}
.nav-inner{
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 11px 12px 11px 20px;
}
.brand{
  display: flex;
  align-items: center;
  gap: 11px;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 18px;
  letter-spacing: 0.005em;
  font-style: italic;
}
.brand-mark{
  width: 24px; height: 24px;
  flex: none;
  object-fit: contain;
  display: block;
}

.nav-links{
  display: flex;
  gap: 30px;
  font-family: var(--f-mono);
  font-size: 13px;
  color: var(--ink-1);
}
.nav-links a{ transition: color .2s; }
.nav-links a:hover{ color: var(--ink-0); }

.nav-cta{ display: flex; align-items: center; gap: 10px; }
.nav-user-email{
  font-family: var(--f-mono);
  font-size: 12px;
  color: var(--ink-2);
  /* Full username, never truncated: no max-width/overflow/ellipsis here.
     Usernames are capped at 32 chars server side, and the responsive
     nav rules below let this wrap onto its own line on narrow screens
     instead of being clipped or forcing horizontal overflow. */
  word-break: break-word;
}

.nav-toggle{
  display: none;
  width: 40px; height: 40px;
  border-radius: var(--radius-s);
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--ink-0);
  align-items: center;
  justify-content: center;
}

@media (max-width: 860px){
  .nav-links{ display: none; }
  .nav-toggle{ display: inline-flex; }
}

/* Long usernames (up to the 32-char server-side max) plus a CTA button
   plus the mobile menu toggle can outgrow a single row on narrow phones.
   Wrapping here, instead of clipping the username or letting the row
   overflow horizontally, is what keeps the whole username visible on
   every screen size per the "no truncation" requirement. */
@media (max-width: 480px){
  .nav-inner{ flex-wrap: wrap; row-gap: 10px; }
  .dash-user{ order: 3; width: 100%; }
  .nav-user-email{ font-size: 12.5px; }
}

/* ==========================================================================
   Utility: reveal-on-scroll
   ========================================================================== */

.reveal{
  opacity: 0;
  transform: translateY(20px);
  transition: opacity .6s var(--ease-out), transform .6s var(--ease-out);
}
.reveal.in{ opacity: 1; transform: translateY(0); }

/* ==========================================================================
   Section scaffolding
   ========================================================================== */

section{ position: relative; padding: 118px 0; }
@media (max-width: 760px){
  section{ padding: 76px 0; }
}
@media (max-width: 480px){
  section{ padding: 56px 0; }
  .container{ padding: 0 16px; }
}
.section-head{
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  max-width: 580px;
  margin: 0 auto 60px;
  text-align: center;
}
.section-head h2{ font-size: clamp(30px, 4vw, 46px); font-style: italic; }
.section-head p{ font-size: 16px; color: var(--ink-2); max-width: 460px; margin-left: auto; margin-right: auto; }
.section-index{
  font-family: var(--f-mono);
  font-size: 12px;
  color: var(--ink-3);
  letter-spacing: 0.08em;
}
@media (max-width: 480px){
  .section-head{ margin-bottom: 40px; gap: 12px; }
}

/* ==========================================================================
   Footer
   ========================================================================== */

footer{ padding: 64px 0 40px; border-top: 1px solid var(--line); text-align: center; }
.footer-grid{
  display: grid;
  grid-template-columns: 1fr 1.3fr 1fr;
  gap: 32px;
}
.footer-col{ display: flex; flex-direction: column; align-items: center; }
.footer-col h4{
  font-family: var(--f-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-3);
  margin-bottom: 18px;
}
.footer-col p{ margin-left: auto; margin-right: auto; }
.footer-col ul{ display: flex; flex-direction: column; align-items: center; gap: 10px; }
.footer-col a{ color: var(--ink-2); font-size: 14px; transition: color .2s; }
.footer-col a:hover{ color: var(--ink-0); }
.footer-bottom{
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
  margin-top: 48px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  font-size: 12px;
  color: var(--ink-3);
  font-family: var(--f-mono);
  letter-spacing: 0.03em;
}
@media (max-width: 760px){
  .footer-grid{ grid-template-columns: 1fr; }
  .footer-bottom{ flex-direction: column; gap: 12px; align-items: center; }
}
