/* Vault365 marketing/legal site — plain CSS, mobile-first, no framework.
 * Tokens come from tokens.css (loaded before this file on every page). */

* { box-sizing: border-box; }

/* The shell and the measure are two different decisions (2026-10-06,
 * after the live site read "squeezed in" on desktop - one variable,
 * main's old max-width: 720px, had been doing both jobs). The shell is
 * how wide the page's own frame runs - header, footer, main's outer
 * bound, and the brand-panel banner that fills whatever main's width
 * is. The measure is how wide a run of body text gets to be, and it
 * does not grow just because the shell did. It is set once per
 * content block (main > section, below) rather than per element
 * inside one - a first pass set it on <p> and .card directly, which
 * left it uncentred and left headings out, so a heading ran the full
 * shell width while the prose under it stopped short (Colin's own
 * correction, same day). --site-measure-width stays near the old
 * 720px reading width on purpose; only --site-shell-width widens at
 * desktop.
 *
 * --site-shell-inset is a third decision, added the same day once the
 * first two were in place: "the top isn't centered but the bottom is"
 * (Colin). main's own horizontal padding (16px, unrelated to the hero)
 * and .brand-panel__inner's (48px desktop/24px mobile, the hero's own
 * figure) were two different numbers with no relationship, so the
 * page had two left edges - hero text and body text each centred on
 * a different width, 172px apart at 1440px wide. Both now read their
 * horizontal padding from this one variable, so there is exactly one
 * inset and the measured section below (no longer separately centred
 * - just flush against it) lines up under the hero rather than
 * floating in the middle of the shell. */
:root {
  --site-shell-width: 720px;
  --site-measure-width: 680px;
  --site-shell-inset: 24px;
}

@media (min-width: 768px) {
  :root {
    /* Fluid up to the cap, not a jump: at 768-1120px main still just
       fills the viewport (full-bleed, minus its own side padding), so
       there is no awkward in-between step right where this query
       fires. The cap only engages past 1120px, where it centers with
       margin either side rather than stretching the banner edge to
       edge. Same breakpoint for the inset, for the same reason - one
       query deciding both, not two thresholds (this one, and the
       hero's old, separate 640px) that could drift apart again. */
    --site-shell-width: 1120px;
    --site-shell-inset: 48px;
  }
}

body {
  margin: 0;
  /* Sticky footer (2026-10-06, Colin's own diagnosis: body has no
     page-level layout, so the footer sits wherever content ends
     rather than at the bottom of the viewport - about 400px of empty
     page below it on index.html). dvh first, vh as the fallback for a
     browser that doesn't parse dvh - dvh so mobile browser chrome
     showing and hiding doesn't move the footer under your thumb.
     header, main and footer are body's only children; main is the one
     that grows, below. */
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--vault-color-page);
  color: var(--vault-color-ink);
  font-family: var(--vault-type-body-family);
  font-weight: var(--vault-type-body-weight);
  font-size: var(--vault-type-body-size-mobile);
  line-height: var(--vault-type-body-line-height-mobile);
}

a { color: var(--vault-color-action); }

/* ---- Header / nav --------------------------------------------------- */

header.site-header {
  background: var(--vault-color-surface);
  border-bottom: 1px solid var(--vault-color-line);
}

.site-header__inner {
  max-width: var(--site-shell-width);
  margin: 0 auto;
  padding: var(--vault-space-16);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--vault-space-16);
}

.site-header__wordmark {
  font-family: var(--vault-type-page-title-family);
  font-weight: 700;
  font-size: 19px;
  color: var(--vault-color-ink);
  text-decoration: none;
  letter-spacing: 0.02em;
}

nav.site-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--vault-space-16);
}

nav.site-nav a {
  color: var(--vault-color-ink-muted);
  text-decoration: none;
  font-size: var(--vault-type-secondary-size-mobile);
  font-weight: 600;
}

nav.site-nav a:hover,
nav.site-nav a[aria-current="page"] {
  color: var(--vault-color-action);
}

/* ---- Layout ----------------------------------------------------------- */

main {
  /* Explicit, not auto (2026-10-06, found while verifying the sticky
     footer below): main is now a flex item of body, and a flex item
     with width:auto plus horizontal auto margins doesn't fill its
     container and get capped the way a normal block does - stretch is
     suppressed by the auto margins, so it falls back to shrink-to-fit
     around its own content instead. main silently stopped reaching
     its shell width on every page whose content was narrower than the
     cap (every page except index.html, whose route-links grid happens
     to be wide enough to hide it). width: 100% sidesteps the
     ambiguity - max-width still clamps it, and the auto margins still
     centre the leftover space exactly as before. */
  width: 100%;
  max-width: var(--site-shell-width);
  margin: 0 auto;
  /* Horizontal padding is --site-shell-inset, not var(--vault-space-16)
     (2026-10-06): the one shared inset, so main's own left edge lands
     exactly where .brand-panel__inner's does - see the --site-shell-inset
     comment above. */
  padding: var(--vault-space-24) var(--site-shell-inset) var(--vault-space-32);
  /* Sticky footer, the other half of the rule (2026-10-06): grow to
     take whatever vertical space header and footer don't need, so
     footer lands at the bottom of a short page instead of right under
     main's own content. */
  flex: 1 0 auto;
}

section + section {
  margin-top: var(--vault-space-32);
}

/* The measure lives on the content container, not on each element
 * inside it (2026-10-06, Colin's own correction of the first pass,
 * which put max-width: var(--site-measure-width) on `main p` and on
 * .card directly). Two problems with that: neither rule centred what
 * it capped, so every measured block sat flush against the shell's
 * left edge instead of in the middle of the page; and the cap was
 * per element type, so h2 ran the full shell width while the p below
 * it stopped at 680px - a text block whose right edge depended on
 * which tag you were looking at, invisible today only because every
 * heading on the site is short enough to fit on one line regardless.
 * One rule instead: the <section> that holds a heading and its prose
 * together is the measured unit. .route-links is excluded - it's the
 * two-column grid of audience links, already sized by its own
 * grid-template-columns, not a prose block.
 *
 * No margin: auto here (2026-10-06, Colin's second correction, same
 * day - "the top isn't centered but the bottom is"). Centring this
 * block independently gave the page two left edges: hero text started
 * at the shell's own edge plus the hero's 48px padding, body text
 * started wherever centring a narrower box happened to land it - 172px
 * further right at 1440px wide. The fix isn't to centre the measure,
 * it's not to: left at its default margin, this block starts exactly
 * where main's own padding puts it, which is now the same inset
 * .brand-panel__inner uses (--site-shell-inset, above) - one left edge
 * for the whole page, hero and body alike. The shell itself is still
 * centred (main's own margin: 0 auto, untouched); only the narrower
 * column inside it stopped being centred a second time. */
main > section:not(.route-links) {
  max-width: var(--site-measure-width);
}

/* h1 has no bare rule here (2026-10-05, the one-vocabulary pass): every
 * page's <h1> is now .brand-thesis (assets/brand.css), inside the
 * brand-panel shell every page opens with. A bare h1{} rule with
 * nothing left to style is exactly the kind of orphaned CSS this pass
 * exists to remove. */

h2 {
  font-family: var(--vault-type-section-heading-family);
  font-weight: var(--vault-type-section-heading-weight);
  font-size: var(--vault-type-section-heading-size-mobile);
  line-height: var(--vault-type-section-heading-line-height);
  margin: 0 0 var(--vault-space-12);
}

/* The restrained accent for clubs.html/players.html's own five plain
 * <section>+h2+prose sections each (2026-10-06) - "plain h2 and prose
 * repeated five times is a wall." One strong field (the brand-panel
 * hero) already carries the page's visual weight; this is the quiet,
 * repeated device that gives the sections under it rhythm without a
 * second one - a short colour rule, not a box, not a background tint.
 * Scoped to a heading inside a <section> rather than every h2 on the
 * site: only these two pages' long-form sections have one. */
section h2 {
  border-left: 3px solid var(--vault-color-action);
  padding-left: var(--vault-space-12);
}

/* h3 retired (2026-10-06, the cards-to-sections pass): its only
 * callers were contact.html's three <h3> card titles, now <h2> like
 * every other section heading on the site - "the contact page still
 * has the cards look and feel" (Colin). Zero callers left anywhere in
 * website/, held pages included (privacy.html/terms.html use <h2>
 * per section already). */

p { margin: 0 0 var(--vault-space-12); }

/* .eyebrow moved to assets/brand.css (2026-10-05, the one-vocabulary
 * pass): every eyebrow on the site now renders inside .brand-panel,
 * which is a dark surface - the light-surface version that lived here
 * had no caller left to serve. One definition, in the file that owns
 * its only context, instead of a light base here and a dark override
 * there. */

.muted { color: var(--vault-color-ink-soft); }

/* .card retired (2026-10-06): contact.html was its last caller, and
 * the cards-look read as a different vocabulary from the rest of the
 * site - "the contact page still has the cards look and feel... the
 * other pages use the left-rule heading pattern. He likes the clubs
 * page" (Colin). Its three blocks are now <section>s like clubs.html's
 * and players.html's, which gives them `section h2`'s own left-rule
 * accent and `main > section:not(.route-links)`'s measured, centred
 * column for free - the border/background/radius/padding a card
 * carried are gone with it, not replaced, because the left-rule
 * pattern doesn't box its content. Checked: zero remaining callers
 * anywhere in website/, including the held privacy.html/terms.html.
 *
 * .card-grid/.card-grid--2/.card-grid--3 and .card-action retired
 * earlier the same day (the copy revision that moved index.html's two
 * audience routes from cards to text links - .route-link below), by
 * which point .card itself was already down to contact.html alone and
 * didn't need a grid. Zero callers left for any of the three - moot
 * now that .card above is gone too. */

/* .hero retired (2026-10-05, the one-vocabulary pass, Colin's own
 * instruction): it was the old vocabulary's version of what
 * .brand-panel now does site-wide, and keeping both is what produced
 * the split look - one class, not two competing ones for the same
 * job. Its one caller (website/clubs.html) now opens with the same
 * brand-panel shell every other page does. */

/* ---- Route links (2026-10-06) -------------------------------------------
 * index.html's two audience routes, as text - not cards. Colin's own
 * framing for why the previous cards had to go: "the bottom two
 * sections look oddly disconnected and incongruous... blocky vs the
 * top which is simple, informative, and impactful." No border, no
 * background, no pill - the whole point is that this reads as the
 * same block as the panel above it, not a second visual language. */

.route-links {
  display: grid;
  gap: var(--vault-space-24);
  margin-top: var(--vault-space-32);
}

.route-link {
  display: block;
  color: inherit;
  text-decoration: none;
}

.route-link__label {
  display: block;
  font-family: var(--vault-type-page-title-family);
  font-weight: 700;
  font-size: 19px;
  color: var(--vault-color-action);
  margin-bottom: var(--vault-space-8);
}

.route-link:hover .route-link__label { text-decoration: underline; }

.route-link__desc {
  display: block;
  color: var(--vault-color-ink-muted);
  font-size: 15px;
  line-height: 1.55;
}

/* ---- Buttons ------------------------------------------------------------ */

.button {
  display: inline-block;
  padding: 12px 20px;
  border-radius: var(--vault-radius-pill);
  font-family: var(--vault-type-button-label-family);
  font-weight: var(--vault-type-button-label-weight);
  font-size: var(--vault-type-button-label-size-mobile);
  text-decoration: none;
}

.button--primary {
  background: var(--vault-color-action);
  color: var(--vault-color-surface);
}

/* A disabled button must read as "not yet," not as broken (2026-10-07,
 * login.html). Lower contrast and a not-allowed cursor are the two
 * signals a reader gets before ever reaching the line of copy beside
 * it - letting the browser's own default (near-unchanged colour, a
 * normal cursor) stand in for "disabled" would read as a bug instead
 * of a stated one. No separate class: `.button--primary:disabled`
 * only ever means this. */
.button:disabled,
.button--primary:disabled {
  background: var(--vault-color-line);
  color: var(--vault-color-ink-faint);
  cursor: not-allowed;
}

/* ---- Form fields (2026-10-07, login.html's first use) ------------------- */

/* BEGIN GENERATED SHARED FIELD RULE - see website/generate_shared_css.py, do not edit by hand */
.field {
  display: block;
  margin-bottom: var(--vault-space-16);
}
/* END GENERATED SHARED FIELD RULE */
.field label {
  display: block;
  font-size: var(--vault-type-secondary-size-mobile);
  font-weight: 600;
  margin-bottom: var(--vault-space-8);
}
.field input {
  display: block;
  width: 100%;
  max-width: 360px;
  box-sizing: border-box;
  padding: 10px 12px;
  border: 1px solid var(--vault-color-line);
  border-radius: 8px;
  font: inherit;
  color: var(--vault-color-ink);
  background: var(--vault-color-surface);
}
/* Same "not yet, not broken" treatment as the button above - a
 * disabled field that still looked typeable would invite someone to
 * type a real email and password into a form that goes nowhere. */
.field input:disabled {
  background: var(--vault-color-line-soft);
  color: var(--vault-color-ink-faint);
  cursor: not-allowed;
}

/* .password-field / .password-field__toggle retired (2026-10-11): their
 * one caller, login.html's password show/hide control, is gone with the
 * disabled form it belonged to - see that page's own comment. */

/* .button--secondary retired (2026-10-06): its one caller was
 * index.html's old "See the player side" link, gone with the cards
 * it belonged to. /clubs' own close is button--primary; nothing on
 * the site asks for the outlined treatment now. */

/* ---- Legal-document placeholders -------------------------------------- */

.tbd {
  display: inline;
  background: var(--vault-color-attention-tint);
  color: var(--vault-color-attention);
  border-radius: 4px;
  padding: 1px 6px;
  font-size: var(--vault-type-secondary-size-mobile);
  font-weight: 600;
}
/* white-space: nowrap removed (2026-10-07, found verifying privacy.html/
   terms.html at 390px for the first time - held pages, never rendered
   at mobile width before now). It held a short legal-placeholder badge
   together on one line, which it's never otherwise seen wrap - but the
   same class also wraps much longer standalone placeholder notes
   (website/README.md's own per-section legal markers), and nowrap on
   those forced real horizontal page overflow at 390px (privacy.html
   rendered 1058px wide in a 390px viewport, confirmed by screenshot
   dimensions, not assumed). Every caller of this class is on a held,
   unpublished page - zero effect on the live site. (Spelled out without
   the literal bracketed marker itself - this file is published, and
   that marker is exactly what the deploy's own placeholder guard
   refuses on sight.) */

.legal-notice {
  background: var(--vault-color-action-tint);
  border: 1px solid var(--vault-color-line);
  border-radius: var(--vault-radius-card);
  padding: var(--vault-space-16);
  margin-bottom: var(--vault-space-24);
}

.legal-notice p:last-child { margin-bottom: 0; }

ul, ol {
  padding-left: 20px;
  margin: 0 0 var(--vault-space-12);
}

li { margin-bottom: var(--vault-space-8); }

/* ---- Footer ------------------------------------------------------------ */

footer.site-footer {
  border-top: 1px solid var(--vault-color-line);
  margin-top: var(--vault-space-32);
}

.site-footer__inner {
  max-width: var(--site-shell-width);
  margin: 0 auto;
  padding: var(--vault-space-16);
  display: flex;
  flex-wrap: wrap;
  gap: var(--vault-space-16);
  justify-content: space-between;
  font-size: var(--vault-type-secondary-size-mobile);
  color: var(--vault-color-ink-faint);
}

.site-footer__inner a {
  color: var(--vault-color-ink-soft);
}

/* ---- Desktop refinements (mobile is the default, this only adds) ------ */

@media (min-width: 768px) {
  body {
    font-size: var(--vault-type-body-size-desktop);
    line-height: var(--vault-type-body-line-height-desktop);
  }
  h2 { font-size: var(--vault-type-section-heading-size-desktop); }
  .button { font-size: var(--vault-type-button-label-size-desktop); }
  .route-links { grid-template-columns: repeat(2, 1fr); gap: var(--vault-space-32); }
}
