/* Bomb Hills brand layer. Shared by every page except the map app, which has
 * its own dense UI in style.css.
 *
 * Direction comes from how longboard and skate brands actually build a page
 * (Loaded Boards, Landyachtz, and the wider skate-media convention): a huge
 * condensed uppercase display face, wide-tracked small caps for labels, near
 * black and white with one hot accent, and imagery doing the emotional work.
 * Our imagery is the terrain itself.
 *
 * Bebas Neue is self-hosted rather than linked from Google Fonts. It is SIL
 * Open Font Licensed so that is permitted, and it keeps the promise in the
 * privacy policy that no third party sees visitors' IP addresses.
 */

@font-face {
  font-family: 'Bebas Neue';
  src: url('/fonts/bebasneue.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ---- design tokens ------------------------------------------------------ */
/* The site and app chrome are warm and light; the interactive map stays dark.
 * That contrast is the point, not an inconsistency: approachable surroundings
 * that hand you over to a darker data environment when you reach the map.
 *
 * Two rules govern every colour below, and both come from measuring rather
 * than taste:
 *
 * 1. Sunset orange and warm gold CANNOT be text on cream. Measured against
 *    #F7E9D7 the orange is 2.64:1 and the gold is 1.48:1, so both fail WCAG AA
 *    body text (4.5:1) and even the large-text floor (3:1). They are FILLS.
 *    Where the brand colour has to carry words on a light surface, use
 *    --primary-text (4.67:1) or put the colour behind dark ink.
 * 2. Anything sitting on a fill needs its own ink token, because the right ink
 *    flips with the fill. --primary-ink is near-black on orange; --on-pine is
 *    cream on pine. Never assume one "text colour" works everywhere.
 *
 * Ratios quoted in comments are against --bg (#F7E9D7) unless stated. */

:root {
  /* Brand anchors. Pine is the structural colour, orange the action colour,
     gold the reward colour. */
  --pine: #0E4D4B;
  --pine-2: #0A3B39;
  --on-pine: #F7E9D7;             /* 8.06:1 on pine */
  --on-pine-dim: #A9C4BE;         /* 5.19:1 on pine */

  --primary: #F2643C;             /* sunset orange. FILL ONLY. */
  --primary-hover: #E5522A;
  --primary-ink: #1A1108;         /* 5.91:1 on --primary */
  --primary-text: #AE3A1A;        /* 5.14:1. the orange when it must be text */

  --secondary: #2E7D8B;           /* ocean teal. FILL ONLY (3.98:1 as text). */
  --secondary-hover: #266B77;
  --secondary-ink: #FFFFFF;       /* 4.75:1 on --secondary */
  --secondary-text: #235F6E;      /* 6.00:1. the teal when it must be text */

  --gold: #F4B942;                /* FILL ONLY, or text on a dark chip. */
  --gold-ink: #2D2D2D;            /* 7.78:1 on --gold */

  /* Backgrounds and surfaces, warm cream through sand. */
  --bg: #F7E9D7;
  --bg-2: #F0DFC9;                /* recessed: inputs, table heads, wells */
  --surface: #FFFBF4;             /* raised: cards */
  --surface-2: #F3E6D2;           /* card hover, secondary chips */

  /* Text. */
  --fg: #2D2D2D;                  /* asphalt charcoal, 11.54:1 */
  --fg-muted: #5E5751;            /* 5.95:1 */

  /* Borders. --line is a hairline and carries no information; --line-strong is
     for anything whose boundary IS the control, which needs 3:1. */
  --line: #E2D0B6;
  --line-strong: #8E7A5A;         /* 3.46:1 */

  /* Semantic states, all darkened until they clear 4.5:1 on cream. The
     off-the-shelf brights do not: they are tuned for dark backgrounds. */
  --ok: #27632F;                  /* 6.04:1 */
  --warn: #8F4A00;                /* 5.59:1 */
  --bad: #B23122;                 /* 5.24:1 */

  /* Shadows are warm and shallow. A neutral black shadow on cream reads as
     dirt rather than depth. */
  --shadow-sm: 0 1px 2px rgba(74, 56, 34, 0.08);
  --shadow-md: 0 4px 14px rgba(74, 56, 34, 0.10);
  --shadow-lg: 0 14px 40px rgba(74, 56, 34, 0.16);

  --r-sm: 6px;
  --r-md: 9px;
  --r-lg: 12px;
  --r-xl: 18px;
  --r-pill: 999px;

  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 24px;
  --s-6: 32px;
  --s-7: 48px;
  --s-8: 64px;

  /* Legacy aliases. The rest of this file and every page's inline <style> were
     written against these names; pointing them at the new tokens re-themes the
     whole site without touching a single selector. New rules should use the
     tokens above. */
  --card: var(--surface);
  --card-hi: var(--surface-2);
  --dim: var(--fg-muted);
  --accent: var(--primary);
  --accent-2: var(--primary-text);

  --display: 'Bebas Neue', 'Haettenschweiler', 'Arial Narrow Bold', sans-serif;
  --sans: system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

  --wrap: 1080px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 16px/1.65 var(--sans);
  -webkit-text-size-adjust: 100%;
}

/* ---- type ------------------------------------------------------------- */

/* Display type carries the pine. It is the structural brand colour, so it wants
   to be on the biggest, most permanent thing on the page rather than sprinkled
   about as trim. */
h1, h2, h3, .display {
  font-family: var(--display);
  font-weight: 400;
  letter-spacing: 0.01em;
  line-height: 0.95;
  text-transform: uppercase;
  margin: 0;
  color: var(--pine);
}

h1 { font-size: clamp(44px, 11vw, 96px); }
h2 { font-size: clamp(28px, 5vw, 42px); margin-top: 48px; }
h3 { font-size: clamp(20px, 3vw, 26px); margin-top: 28px; }

/* Wide-tracked small caps. The label voice of the genre.
   --primary-text, not --primary: at 12px this is body-sized text, and the raw
   sunset orange measures 2.64:1 on cream. */
.eyebrow {
  display: block;
  margin-bottom: 10px;
  color: var(--primary-text);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

p { margin: 0 0 16px; }
a { color: var(--primary-text); text-decoration-thickness: 1px; text-underline-offset: 2px; }
/* Hover goes DARKER, into the pine. Going brighter, which is the instinct
   carried over from the dark theme, walks a link straight off the contrast
   floor on a cream page. */
a:hover { color: var(--pine); }

.lede { font-size: 18px; color: var(--fg-muted); }

/* ---- layout ------------------------------------------------------------ */

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 20px; }
.narrow { max-width: 720px; }

/* ---- site header ------------------------------------------------------- */

.site-head {
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(255, 251, 244, 0.92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.site-head .wrap {
  display: flex;
  align-items: center;
  gap: 18px;
  min-height: 58px;
  padding-top: env(safe-area-inset-top);
}

.logo {
  font-family: var(--display);
  font-size: 26px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--pine);
  text-decoration: none;
  white-space: nowrap;
}
/* Temporary wordmark: this is live text, so the final SVG lettering can be
   dropped in by replacing the contents of a.logo without touching the header
   layout around it. */
.logo b { color: var(--primary-text); font-weight: 400; }

.site-nav { margin-left: auto; display: flex; gap: 4px; flex-wrap: wrap; }
.site-nav a {
  padding: 7px 11px;
  border-radius: 7px;
  color: var(--dim);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
}
.site-nav a:hover { background: var(--surface-2); color: var(--pine); }
.site-nav a[aria-current] { color: var(--pine); background: var(--surface-2); }

/* ---- buttons ----------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 13px 22px;
  background: var(--primary);
  color: var(--primary-ink);
  border: 0;
  border-radius: var(--r-md);
  font: inherit;
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
}
.btn:hover { background: var(--primary-hover); color: var(--primary-ink); }
.btn:disabled {
  background: var(--surface-2);
  color: var(--fg-muted);
  border: 1px solid var(--line-strong);
  box-shadow: none;
  cursor: not-allowed;
}
/* The secondary action. Teal is the only other colour in the palette that can
   hold white text, so it is what "important but not the main thing" looks
   like. */
.btn.secondary { background: var(--secondary); color: var(--secondary-ink); }
.btn.secondary:hover { background: var(--secondary-hover); color: var(--secondary-ink); }
.btn.ghost {
  background: transparent;
  color: var(--pine);
  /* --line-strong, not --line: with no fill the border is the only thing
     saying "this is a button", so it has to clear the 3:1 non-text floor. */
  border: 1px solid var(--line-strong);
  box-shadow: none;
}
.btn.ghost:hover { background: var(--surface-2); color: var(--pine); }

/* ---- cards and forms --------------------------------------------------- */

.card {
  padding: 20px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
}

label.field { display: block; margin-bottom: 14px; }
label.field > span {
  display: block;
  margin-bottom: 6px;
  color: var(--dim);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
input[type=text], input[type=email], textarea, select {
  width: 100%;
  padding: 11px 12px;
  background: var(--surface);
  color: var(--fg);
  /* A field's edge is the whole of its affordance, so --line-strong. */
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  font: inherit;
  font-size: 15px;
}
/* Focus rings must clear 3:1 against what surrounds them. Raw sunset orange is
   2.64:1 on cream, so the ring uses the darkened orange instead. */
input:focus, textarea:focus, select:focus {
  outline: 2px solid var(--primary-text);
  outline-offset: 1px;
}
textarea { min-height: 140px; resize: vertical; }

.note { font-size: 13px; color: var(--dim); }
.note.bad { color: var(--bad); }
.note.ok { color: var(--ok); }

/* ---- footer ------------------------------------------------------------ */

/* A pine band. The footer is the one full-bleed element on these pages, so it
   is where the structural brand colour can actually be a surface rather than
   trim, and it gives the light pages a bottom edge instead of fading out.
   Text here uses the on-pine pair: --fg-muted would be 1.36:1 against pine. */
.site-foot {
  margin-top: var(--s-8);
  padding: 28px 0 calc(env(safe-area-inset-bottom) + 28px);
  background: var(--pine);
  border-top: 1px solid var(--pine-2);
  color: var(--on-pine-dim);
  font-size: 13px;
}
.site-foot .wrap { display: flex; gap: 16px; flex-wrap: wrap; align-items: baseline; }
.site-foot nav { margin-left: auto; display: flex; gap: 14px; flex-wrap: wrap; }
.site-foot a { color: var(--on-pine-dim); }
.site-foot a:hover { color: var(--on-pine); }

/* ---- misc -------------------------------------------------------------- */

hr { border: 0; border-top: 1px solid var(--line); margin: 32px 0; }

table { width: 100%; border-collapse: collapse; font-size: 14.5px; display: block; overflow-x: auto; }
th, td { padding: 9px 11px; border: 1px solid var(--line); text-align: left; vertical-align: top; }
th { background: var(--bg-2); color: var(--fg-muted); font-weight: 700; font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; }

code { padding: 1px 5px; background: var(--bg-2); border-radius: var(--r-sm); font-size: 13px; }

@media (max-width: 640px) {
  .site-nav a { padding: 6px 8px; font-size: 11.5px; }
  .logo { font-size: 22px; }
}

/* Sponsor logo upload, on the status page. The preview keeps a dark backdrop
   deliberately even though the page around it is now cream: sponsor logos are
   shown on the map, which is dark, so this is a preview of where the logo
   actually lands rather than of the page it is being uploaded from. */
/* The guard is load-bearing, not decoration. status.html renders this img with
   a `hidden` attribute and only clears it when a logo is actually on file, but
   the `display: block` below beats the user agent's `[hidden] {display:none}`,
   so the empty box was being painted on every visit. It went unnoticed because
   a near-black box on a near-black page looks like nothing; on cream it is an
   obvious empty frame. */
#logopreview[hidden] { display: none; }
#logopreview { max-width: 320px; max-height: 90px; display: block; margin-bottom: 10px;
  background: var(--pine); border: 1px solid var(--line-strong); border-radius: var(--r-md); padding: 8px; }
.spec { margin: 10px 0 14px; padding-left: 20px; color: var(--fg-muted); font-size: 14px; line-height: 1.6; }
.spec b { color: var(--fg); }

/* Terms acceptance on the sponsor form. */
.agree { display: flex; gap: 10px; align-items: flex-start; margin: 14px 0 16px;
  font-size: 14px; line-height: 1.5; color: var(--dim); cursor: pointer; }
.agree input { margin-top: 3px; flex: none; width: 17px; height: 17px; accent-color: var(--primary); }
.agree a { color: var(--primary-text); }

/* Landing page header: logo left, Map centred, Sponsor right.
   Only two links here, and centring the primary action gives it the weight it
   deserves without making it look like a lone button. display:contents lets the
   two links become grid items in their own right while the nav keeps its role
   in the accessibility tree. */
.site-head.split .wrap {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
}
.site-head.split .logo { justify-self: start; }
.site-head.split .site-nav { display: contents; }
.site-head.split .site-nav a:first-child { justify-self: center; }
.site-head.split .site-nav a:last-child  { justify-self: end; }

@media (max-width: 520px) {
  /* Too little room to centre anything meaningfully; fall back to a plain row. */
  .site-head.split .wrap { display: flex; }
  .site-head.split .site-nav { display: flex; margin-left: auto; }
}

/* The landing page carries only two links, so they can afford real weight.
   At 13px in a 6-link row they read as boilerplate; these are the two things
   a first-time visitor is here to do. */
.site-head.split .site-nav a {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 10px 18px;
  border-radius: 8px;
}
.site-head.split .site-nav a:last-child {
  border: 1px solid var(--line-strong);
  color: var(--primary-text);
}
/* Fills on hover rather than just brightening its border. A border-colour
   change to raw orange would be 2.64:1 against the header and read as nothing
   happening. */
.site-head.split .site-nav a:last-child:hover {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-ink);
}
@media (max-width: 520px) {
  .site-head.split .site-nav a { font-size: 15px; padding: 9px 13px; }
}

/* ---- mascot slots ------------------------------------------------------- */
/* Empty, replaceable slots. The artwork is being commissioned, so what is
 * reserved here is the SHAPE, not a picture: each slot declares its aspect
 * ratio, so the final illustration drops into an already correctly sized hole
 * and nothing around it has to move.
 *
 * aspect-ratio rather than a fixed height, and object-fit: contain, so art
 * delivered at any resolution lands in the same box.
 *
 *   <img class="mascot mascot--badge"    src="/img/mascot/mascot-badge.svg"    alt="">
 *   <img class="mascot mascot--riding"   src="/img/mascot/mascot-riding.svg"   alt="">
 *   <img class="mascot mascot--fullbody" src="/img/mascot/mascot-fullbody.svg" alt="">
 *
 * Decorative by default, hence alt="". Give it real alt text only where the
 * mascot is carrying meaning rather than atmosphere.
 *
 * Not placed on any page yet. Dropping a labelled empty box onto the live
 * homepage would read as a broken image to a visitor, and the homepage rewrite
 * is a separate piece of work. */
.mascot {
  display: block;
  width: 100%;
  height: auto;
  object-fit: contain;
}
.mascot--badge    { aspect-ratio: 1 / 1; max-width: 120px; border-radius: 50%; }
.mascot--riding   { aspect-ratio: 3 / 2; max-width: 520px; }
.mascot--fullbody { aspect-ratio: 2 / 3; max-width: 240px; }

/* ---- wordmark slot ------------------------------------------------------- */
/* The header logo is a SLOT, not a design.
   The brand pack's wordmark is a heavy brush script that needs commissioning or
   real vector work; what is set here is the condensed face we already had,
   beside the circular mark that could be drawn now because it is geometric.
   When the finished SVG wordmark exists, swap .logo-word for an <img> of it and
   nothing around it has to move: the badge, the spacing and the nav all stay. */
.logo { display: inline-flex; align-items: center; gap: 10px; }
.logo-badge { display: block; width: 34px; height: 34px; flex: none; }
.logo-word { display: inline-block; }

@media (max-width: 520px) {
  .logo-badge { width: 28px; height: 28px; }
}
