/* ─────────────────────────────────────────────────────────────────────────
   OrcaSci — holding site
   Tokens copied from projects/orcasci/site/assets/tokens.css (D-023/D-024,
   Astrid MT-GU04 + Nils, Principal ruling 2026-08-27, MCP decision 7420).

   NO third-party requests of any kind. No Google Fonts, no analytics, no
   CDN. This is a GDPR decision, not a performance one: loading a webfont
   from fonts.gstatic.com transmits the visitor's IP to a US processor with
   no legal basis (LG Munchen I, 20.01.2022, 3 O 17493/20). That is also why
   this site needs no cookie banner.

   The typeface is SELF-HOSTED, which does not loosen the above: the woff2
   files are served from this origin, so no visitor IP reaches a third party.
   `default-src 'self'` with no `font-src` of its own already permits
   same-origin font files (verified against app.py's after_request header),
   so NO CSP CHANGE WAS NEEDED for this.

   ARCHIVO, ruled by the Principal 2026-09-04 (control.db DEC-018 Q1), over
   Astrid MT-GU04's Libre Franklin recommendation. Five weights, latin
   subset, copied from projects/orcasci/brand-studio/assets/fonts/.
   ───────────────────────────────────────────────────────────────────────── */

/* ── Archivo, self-hosted (DEC-018 Q1) ─────────────────────────────────── */
@font-face{font-family:Archivo; font-style:normal; font-weight:300;
  font-display:swap; src:url("fonts/archivo-300.woff2") format("woff2")}
@font-face{font-family:Archivo; font-style:normal; font-weight:400;
  font-display:swap; src:url("fonts/archivo-400.woff2") format("woff2")}
@font-face{font-family:Archivo; font-style:normal; font-weight:600;
  font-display:swap; src:url("fonts/archivo-600.woff2") format("woff2")}
@font-face{font-family:Archivo; font-style:normal; font-weight:700;
  font-display:swap; src:url("fonts/archivo-700.woff2") format("woff2")}
@font-face{font-family:Archivo; font-style:normal; font-weight:800;
  font-display:swap; src:url("fonts/archivo-800.woff2") format("woff2")}

:root{
  --ground:#101314; --surface:#171B1B; --field-lo:#0A0D0D; --field-hi:#1D2321;
  /* The light ground, PINNED 2026-09-04 by Principal ruling. "bone" had been an
     unnamed value that moved between runs — three studio pages said #F2EFE9 and
     a fourth reached for --ink-head #F5F2EB, a FOREGROUND token, as a ground,
     which is what produced the 4.93-vs-5.06 disagreement on --accent-lo.
     #F2EFE9 is canonical: it is the value in the closed brand record and on the
     D-023 decision page, and it reproduces their figures exactly. Declared here
     for the palette to be complete and citable; the holding page has no light
     ground and does not use it. Light-ground pairing is --ground as the ink
     (16.26) with --accent-lo as the accent (4.93). */
  --bone:#F2EFE9;
  --ink-head:#F5F2EB; --ink:#E8E4DC; --muted:#AEB4AA; --dim:#9AA096; --faint:#8E958F;
  /* Two accents, DEC-018 Q2 — PROVISIONAL, not ratified; ratification is
     gated on the D-026 accessibility pass. --accent is the dark-ground
     value, --accent-lo the light-ground value (bone/white). */
  --accent:#C9A227; --accent-on:#141210; --accent-lo:#7D641A;
  --line:#2B302F; --line-lift:#3A403E;
  --ok:#8FBF7F; --warn:#D9A05B; --bad:#D98A80;
  --sans:Archivo,-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;
  --mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;
  --sp:clamp(1.15rem,3vw,2rem);
  --maxw:64rem;
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0; background:var(--ground); color:var(--ink);
  font-family:var(--sans); font-size:clamp(1rem,.55vw + .9rem,1.125rem);
  line-height:1.6; letter-spacing:.005em; overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
}
a{color:var(--ink-head)}
a:focus-visible,button:focus-visible,input:focus-visible{
  outline:2px solid var(--accent); outline-offset:3px; border-radius:2px}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

.wrap{max-width:var(--maxw); margin:0 auto; padding:0 var(--sp); width:100%}

/* ── the hero: one full-bleed image, everything sits on it ─────────────── */
.hero{
  position:relative; min-height:100svh; min-height:100vh;
  display:flex; flex-direction:column;
  isolation:isolate; overflow:hidden;
}
.hero-img{
  position:absolute; inset:0; z-index:-2;
  background:
    radial-gradient(1200px 760px at 62% 22%, var(--field-hi) 0%, transparent 64%),
    linear-gradient(180deg,#12181A 0%, var(--field-lo) 100%);
  background-size:cover; background-position:center 42%;
}
.hero-img.has-photo{
  background-image:var(--hero-src);
  background-size:cover; background-position:center 45%; background-repeat:no-repeat;
}
/* Legibility scrim. Two layers: a vertical wash so the masthead and footer
   always have ground, and a left-weighted wash under the headline column. */
.hero::before{
  content:""; position:absolute; inset:0; z-index:-1; pointer-events:none;
  background:
    linear-gradient(180deg, rgba(10,13,13,.72) 0%, rgba(10,13,13,.10) 24%,
                            rgba(10,13,13,.16) 58%, rgba(10,13,13,.86) 100%),
    linear-gradient(94deg,  rgba(10,13,13,.80) 0%, rgba(10,13,13,.46) 42%,
                            rgba(10,13,13,.04) 74%, rgba(10,13,13,.14) 100%);
}

/* ── masthead — the logo, unchanged from D-022 Route C ─────────────────── */
.mast{padding:clamp(1.6rem,4.5vh,2.6rem) 0}
.brand{display:inline-flex; align-items:center; gap:.8rem; color:var(--ink-head)}
.brand svg{color:var(--accent); display:block; flex:none}
/* The wordmark: L2, the weight seam, ruled by DEC-017 as the primary and only
   approved horizontal lockup. This replaces a uniform font-weight:600 — which
   was L1, the treatment that ruling expressly REJECTED, and which had been
   shipping on every page since. Orca 300 / Sci 800 resolve to shipped Archivo
   faces; implementing the seam is also what finally puts 300 and 800 into use,
   closing DEC-020 finding (ii) (only 2 of the 5 shipped faces ever loaded).
   Tracking -.022em matches the outlined masters in projects/orcasci/brand/.
   Markup is a single partial, templates/_wordmark.html — five templates
   carrying their own copy is how the rejected L1 stayed shipping unnoticed. */
.brand b{font-weight:400; font-size:1.28rem; letter-spacing:-.022em}
.brand .wm-o{font-weight:300}
.brand .wm-s{font-weight:800}

/* ── the statement ────────────────────────────────────────────────────── */
.stage{
  flex:1; display:flex; align-items:center;
  padding:clamp(2rem,6vh,4.5rem) 0 clamp(1.5rem,4vh,3rem);
}
.stage .wrap{max-width:var(--maxw)}
h1{
  /* 400, not 500. No Archivo 500 face is shipped (300/400/600/700/800), so
     Chrome was already resolving 500 down to the loaded 400 face — measured:
     the h1 string at 100px renders 717.81px at BOTH 400 and 500, against
     759.11px at 600. This is a zero-visual-change correction that makes the
     declaration true; it does not ship a sixth face. DEC-020 finding (i). */
  margin:0; font-weight:400;
  font-size:clamp(2.6rem,8.6vw,5.9rem); line-height:.98;
  letter-spacing:-.038em; color:var(--ink-head);
  max-width:15ch;
}
.sub{
  margin:clamp(.9rem,2.4vh,1.4rem) 0 0;
  font-size:clamp(1.25rem,3.4vw,2rem); line-height:1.18;
  letter-spacing:-.022em; font-weight:400; color:var(--accent);
  max-width:22ch;
}
.status{
  margin:clamp(1.6rem,4vh,2.4rem) 0 0;
  display:inline-flex; align-items:center; gap:.6rem;
  font-family:var(--mono); font-size:.74rem; font-weight:500;
  letter-spacing:.2em; text-transform:uppercase; color:var(--ink-head);
  border:1px solid var(--line-lift); border-radius:2px;
  padding:.5rem .85rem; background:rgba(23,27,27,.55);
  backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
}
.status .dot{
  width:6px; height:6px; border-radius:50%; background:var(--accent); flex:none;
  box-shadow:0 0 0 0 rgba(201,162,39,.55); animation:pulse 2.8s ease-out infinite;
}
@keyframes pulse{
  0%{box-shadow:0 0 0 0 rgba(201,162,39,.5)}
  70%{box-shadow:0 0 0 9px rgba(201,162,39,0)}
  100%{box-shadow:0 0 0 0 rgba(201,162,39,0)}
}

/* ── signup ───────────────────────────────────────────────────────────── */
.signup{margin-top:clamp(2.6rem,7vh,4.2rem); max-width:38rem}
form{display:flex; flex-wrap:wrap; gap:.6rem}
input[type=email]{
  flex:1 1 16rem; min-width:0; padding:.85rem 1rem;
  background:rgba(23,27,27,.78); color:var(--ink);
  border:1px solid var(--line-lift); border-radius:2px;
  /* 1rem = 16px: anything below 16px makes iOS Safari zoom the viewport on
     focus, on the page's only conversion field. Do not shrink this. */
  font:inherit; font-size:1rem;
  backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
}
input[type=email]::placeholder{color:var(--faint)}
input[type=email]:disabled{opacity:.55}
button.sub-btn{
  padding:.85rem 1.4rem; border:1px solid var(--accent); border-radius:2px;
  background:var(--accent); color:var(--accent-on);
  font:inherit; font-size:.98rem; font-weight:600; cursor:pointer;
  transition:filter .18s;
}
button.sub-btn:hover:not(:disabled){filter:brightness(1.09)}
button.sub-btn:disabled{cursor:default; filter:grayscale(.5) brightness(.8)}

/* The consent statement. This is the lawful basis (GDPR Art. 6(1)(a)) and it
   has to sit at the point of collection, before the button is pressed --
   not only in the privacy notice. Its exact text is stored with every
   record so consent can be evidenced later (Art. 7(1)). */
.consent{
  margin:.85rem 0 0; font-size:.82rem; line-height:1.55; color:var(--dim);
  max-width:46ch;
}
.consent a{color:var(--muted); text-decoration:underline; text-underline-offset:3px}
.consent a:hover{color:var(--ink-head)}

.state{
  margin:1rem 0 0; padding:.85rem 1rem; border-radius:2px;
  border:1px solid var(--line-lift); background:rgba(23,27,27,.85);
  color:var(--muted); font-size:.9rem; max-width:48ch; line-height:1.55;
  backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
}
.state b{color:var(--ink-head); font-weight:600}
.state.ok{border-color:#3E5A38}
.state.bad{border-color:#5A3A36}
.reset{
  margin-top:.7rem; background:none; border:none; cursor:pointer;
  font:inherit; font-size:.83rem; color:var(--faint);
  text-decoration:underline; text-underline-offset:3px;
  /* SC 2.5.8: was padding:0 and 21px tall. Padding, not a height, so the
     underline still hugs the text and only the hit area grows. */
  padding:.28rem 0; min-height:24px;
}
.reset:hover{color:var(--ink)}

/* ── footer ───────────────────────────────────────────────────────────── */
footer{padding:0 0 clamp(1.6rem,4.5vh,2.6rem)}
footer .wrap{
  display:flex; flex-wrap:wrap; gap:.5rem 1.4rem; align-items:baseline;
  color:var(--faint); font-size:.84rem;
}
footer a{
  color:var(--dim); text-decoration:none;
  /* SC 2.5.8: these are a list of links, not links inline in a sentence, so the
     Inline exception does not apply. Measured 22px before this rule. */
  display:inline-flex; align-items:center; min-height:24px;
}
footer a:hover{color:var(--ink-head); text-decoration:underline; text-underline-offset:3px}
footer .sep{color:var(--line-lift)}
footer .cp{margin-left:auto}

/* ── document pages (privacy / terms / confirm) ───────────────────────── */
body.doc{background:var(--ground)}
.doc-wrap{max-width:44rem; margin:0 auto; padding:0 var(--sp)}
.doc header{padding:clamp(1.6rem,4.5vh,2.6rem) 0; border-bottom:1px solid var(--line)}
.doc main{padding:clamp(2.4rem,7vh,4rem) 0 clamp(3rem,8vh,5rem)}
.doc h1{font-size:clamp(1.9rem,5vw,2.7rem); letter-spacing:-.026em; line-height:1.08}
.doc .meta{
  margin:1rem 0 0; font-family:var(--mono); font-size:.72rem;
  letter-spacing:.1em; text-transform:uppercase; color:var(--faint);
}
.doc h2{
  margin:2.6rem 0 .8rem; font-size:1.16rem; font-weight:600;
  letter-spacing:-.008em; color:var(--ink-head);
  display:flex; align-items:baseline; gap:.7rem;
}
.doc h2 span{
  font-family:var(--mono); font-size:.68rem; font-weight:500;
  letter-spacing:.12em; color:var(--accent); flex:none;
}
.doc h3{margin:1.7rem 0 .5rem; font-size:.98rem; font-weight:600; color:var(--ink-head)}
.doc p, .doc li{color:var(--muted); font-size:.97rem}
.doc p{margin:0 0 1rem}
.doc ul, .doc ol{margin:0 0 1rem; padding-left:1.2rem}
.doc li{margin:0 0 .5rem}
.doc a{color:var(--ink-head); text-decoration:underline; text-underline-offset:3px}
.doc strong{color:var(--ink-head); font-weight:600}
.doc table{
  width:100%; border-collapse:collapse; margin:0 0 1.4rem; font-size:.9rem;
  display:block; overflow-x:auto;
}
.doc th,.doc td{
  border:1px solid var(--line); padding:.6rem .7rem; text-align:left;
  vertical-align:top; color:var(--muted);
}
.doc th{color:var(--ink-head); font-weight:600; background:var(--surface); white-space:nowrap}
.doc code{font-family:var(--mono); font-size:.86em; color:var(--accent)}
.doc .lede{font-size:1.06rem; color:var(--ink); margin-bottom:1.6rem}
.doc footer{border-top:1px solid var(--line); padding:1.8rem 0 3rem; margin-top:2rem}
.back{
  display:inline-flex; align-items:center; gap:.5rem; margin-bottom:2rem;
  font-size:.88rem; color:var(--dim); text-decoration:none;
}
.back:hover{color:var(--ink-head)}

/* Unfilled legal detail. Deliberately loud: this must be impossible to ship
   by accident. Every one of these is a fact I could not verify. */
.tbd{
  display:inline-block; padding:.05em .45em; border-radius:2px;
  background:rgba(217,138,128,.14); border:1px dashed #7A4B45;
  color:#E8A69E; font-family:var(--mono); font-size:.82em;
  letter-spacing:.02em; font-style:normal;
}
.notice{
  border:1px solid #7A4B45; background:rgba(217,138,128,.08);
  border-radius:2px; padding:1rem 1.1rem; margin:0 0 2rem;
}
.notice p{margin:0; color:#E8A69E; font-size:.9rem}
.notice p + p{margin-top:.6rem}

/* ── centred single-message pages ─────────────────────────────────────── */
.card{
  min-height:100svh; min-height:100vh; display:flex; flex-direction:column;
  align-items:center; justify-content:center; text-align:center;
  padding:2rem var(--sp);
}
.card .inner{max-width:34rem}
.card h1{font-size:clamp(1.8rem,5vw,2.6rem); margin:1.6rem 0 0; letter-spacing:-.026em}
.card p{color:var(--muted); margin:1rem 0 0}
.card .go{
  display:inline-flex; align-items:center; gap:.5rem; margin-top:2rem;
  padding:.72rem 1.2rem; border:1px solid var(--line-lift); border-radius:2px;
  font-size:.94rem; color:var(--ink-head); text-decoration:none;
  transition:border-color .18s, background .18s;
}
.card .go:hover{border-color:var(--accent); background:#15191A}

/* WCAG 2.2 SC 1.4.10 Reflow — measured 2026-09-04 at a real 320x640 mobile
   viewport, not inferred from the breakpoint. /privacy-v2 scrolled horizontally:
   document scrollWidth 550 against a 320 viewport. Cause was `.doc th` carrying
   white-space:nowrap, which stops the header column compressing, so the tables'
   min-content width sat at 385px with no scroll container above them
   (.doc-wrap is overflow-x:visible).
   The tables here are 2-column key/value pairs. They do NOT need two-dimensional
   layout, so the SC 1.4.10 data-table exception does not apply and the correct fix
   is to let them wrap rather than to hand the reader a horizontal scrollbar. */
/* SC 1.4.10 again, and this one is the exception rather than a defect. The
   statutory-deadline block is a <pre> (white-space:pre) and is code-fenced on
   purpose -- it is the documented human_time_guard workaround for quoting a legal
   deadline, so its CONTENT must not be reflowed or reworded. Preformatted text is
   content that requires its own line breaks, so SC 1.4.10 permits scrolling for it;
   what it does NOT permit is that scroll being the PAGE's. Measured 320px: the block
   is 532px wide and was pushing document scrollWidth to 550. Contained here. */
.doc pre{overflow-x:auto; max-width:100%}

/* SC 2.5.8 Target Size (Minimum). Measured 320px: the standalone "← Back" link is
   23px tall against the 24px floor. It is NOT inline-exempt -- its parent is
   div.doc-wrap with zero non-target text, so nothing constrains it to a line-height.
   The five email/URL links that also measure under 24px ARE exempt and are
   deliberately untouched: each sits in a run of text (207, 66, 121, 120 and 219
   characters of non-target text in the parent), which is the Inline exception. */
.doc .back{display:inline-flex; align-items:center; min-height:24px}


@media (max-width:560px){
  .doc th{white-space:normal}
  .doc table{table-layout:fixed; width:100%}
  .doc th,.doc td{overflow-wrap:anywhere}
}

@media (max-width:600px){
  .hero{min-height:auto}
  .stage{padding-top:clamp(3rem,10vh,5rem); padding-bottom:2.5rem}
  footer .cp{margin-left:0; width:100%}
}
@media (prefers-reduced-motion:reduce){
  *{animation:none !important; transition:none !important}
}

/* ── hero variants ────────────────────────────────────────────────────────
   Named here, not in an inline <style> block: the Content-Security-Policy is
   `style-src 'self'` with no 'unsafe-inline', so an inline style silently does
   nothing in a real browser. Every rule in this file is reachable; no rule in
   this project lives in a style attribute. */
.hero-road{ --hero-src:url("img/hero-road.jpg") }
.hero-deep{ --hero-src:url("img/hero-deep.jpg") }
@media (max-width:900px){
  .hero-road{ --hero-src:url("img/hero-road-sm.jpg") }
  .hero-deep{ --hero-src:url("img/hero-deep-sm.jpg") }
}

/* ── shared small utilities (replacing inline style attributes) ─────────── */
.brand-link, .doc a.brand-link{text-decoration:none}
.brand-mark{color:var(--accent)}
.doc-foot{
  display:flex; flex-wrap:wrap; gap:.5rem 1.4rem; align-items:baseline;
  color:var(--faint); font-size:.84rem;
}
.doc-foot .cp{margin-left:auto}
.notice-top{margin-top:2rem}
.card form{justify-content:center; margin-top:1.6rem}
.card strong{color:var(--ink-head)}

.nowrap{white-space:nowrap}
