﻿/* =========================================================
   Platform design system
   Derived from docs/frontend-template/styles.css

   THIS FILE IS THE SOURCE. Do not edit the copies under
   frontend/*/wwwroot/shared/ — they are overwritten and pruned by
   ./tools/sync-design-assets.ps1.

   Differences from the template export, each deliberate:

   1. Fonts are self-hosted. The template @imports them from
      fonts.googleapis.com, which means every page load calls out to a
      third party, fails on an isolated network and needs a CSP entry.
   2. Two font roles instead of one. The template sets Kalam on the whole
      body; a back-office grid of identifiers and amounts in a handwriting
      face is genuinely hard to scan, so --font-data carries tabular and
      form content while the handwriting stays on chrome and prose.
   3. Legal prose is carried over; chat bubbles still are not. Both were left
      out while only the back office consumed this file. The member site now
      renders terms and policy pages, so .terms-prose earns its place; the
      message bubbles wait for the slice that builds the inbox, because a rule
      nothing uses is a rule nobody maintains. The template's --hot-red became
      --hot-red-ink here: prose bullets and inline strong are small text, and
      that is exactly the case the deepened red exists for.
   4. doodle-hero.png is 600px wide, not the export's 2000px. The CSS renders
      it at exactly 600px as a repeating, half-opacity texture, so the extra
      resolution bought nothing and cost 3.2 MB on every page load. The
      full-resolution original stays in docs/frontend-template/images/.
   ========================================================= */

/* ------------------------------------------------------------------ fonts */
/* Latin and latin-ext only: the product is Italian and English. Adding
   Cyrillic or Devanagari would triple the payload for nothing. */

@font-face {
  font-family: 'Caveat';
  font-style: normal;
  font-weight: 400 700; /* variable: one file covers the whole range */
  font-display: swap;
  src: url('../fonts/caveat-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Caveat';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/caveat-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308,
    U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
    U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Kalam';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/kalam-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Kalam';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/kalam-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308,
    U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
    U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Kalam';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/kalam-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Kalam';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/kalam-700-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308,
    U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
    U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Permanent Marker';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/permanent-marker-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* -------------------------------------------------------------- variables */

*, *::before, *::after { box-sizing: border-box; }

:root {
  --cream-50: #FBF2D4;
  --cream-100: #F5E4B4;
  --cream-200: #EDD79A;
  --cream-300: #E5C879;
  --cream-bg: #F5E4B4;
  --ink-900: #2A1A0A;
  --ink-700: #5A3A1B;
  --ink-500: #7E5530;
  /* --ink-300 is ~2.6:1 on cream. Kept for decorative rules only; anything
     that carries meaning uses --ink-500 or darker. */
  --ink-300: #B08856;
  --gold: #E8B83E;
  --gold-soft: #F5C748;
  --blue: #A8C5C8;
  --blue-dark: #6E9B9F;
  --orange: #E8923E;

  /* Two reds, because one cannot do both jobs accessibly.

     --hot-red is the template's brand red. Against cream it measures 4.16:1,
     which clears the 3:1 bar for large text and non-text, so it stays on
     button fills, focus rings and borders where the brand colour belongs.

     --hot-red-ink is the same hue deepened to 5.33:1 on the card and 4.73:1 on
     the page. It carries every piece of small red text — error messages above
     all, which are exactly the words someone needs to read and exactly the ones
     that would have been hardest to. It also fills the small red chips, whose
     cream labels are below large-text size. */
  --hot-red: #C84B31;
  --hot-red-ink: #AE3E26;

  /* Two roles. Handwriting carries the personality; the sans carries the data. */
  --font-display: 'Caveat', 'Segoe Script', cursive;
  --font-marker: 'Permanent Marker', 'Caveat', cursive;
  --font-hand: 'Kalam', 'Segoe Print', cursive;
  --font-data: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;

  color-scheme: light;
}

/* ------------------------------------------------------------------- base */

html, body {
  margin: 0;
  padding: 0;
  background: var(--cream-bg);
  color: var(--ink-900);
}

body {
  font-family: var(--font-data);
  font-weight: 400;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  background-color: var(--cream-bg);
  /* The paper grain from the template: a 40px repeating dotted tile. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40'><circle cx='1' cy='1' r='0.8' fill='%237E5530' opacity='0.18'/></svg>");
}

img { max-width: 100%; display: block; }
a { color: inherit; }

h1, h2, h3, h4, h5 {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--ink-900);
  line-height: 1.05;
  margin: 0;
}

button { font-family: inherit; cursor: pointer; }
::selection { background: var(--gold); color: var(--ink-900); }

/* Focus must always be visible and must never be removed without a
   replacement. The offset keeps the ring clear of the hard shadows. */
:focus-visible {
  outline: 3px solid var(--hot-red);
  outline-offset: 3px;
}

/* Except on the page heading. Blazor's <FocusOnNavigate Selector="h1"> moves focus
   there after every navigation so a screen reader announces the new page — which is
   right, and which would otherwise draw a red box around the heading on every single
   page load. A heading is never a tab stop, so nothing is lost by hiding its ring. */
h1:focus,
h1:focus-visible,
[tabindex="-1"]:focus {
  outline: none;
}

/* Honour the reduced-motion preference: the doodle style leans on wobble
   and hover-translate, which is exactly what this setting is asking to stop. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ------------------------------------------------------------ typography */

.font-display { font-family: var(--font-display); font-weight: 700; }
.font-body    { font-family: var(--font-hand); }
.font-marker  { font-family: var(--font-marker); }
.font-data    { font-family: var(--font-data); }

.text-hot     { color: var(--hot-red-ink); }
.text-orange  { color: var(--orange); }
.text-ink-500 { color: var(--ink-500); }
.text-ink-700 { color: var(--ink-700); }

/* Prose keeps the handwriting face; it is short, large and set in wide
   measures, where legibility holds. */
.prose { font-family: var(--font-hand); line-height: 1.5; }

/* ---------------------------------------------------------------- surfaces */

.paper-card {
  background: var(--cream-50);
  border: 2.5px solid var(--ink-700);
  border-radius: 22px 28px 24px 30px / 28px 22px 30px 24px;
  box-shadow: 6px 6px 0 var(--ink-900);
  position: relative;
}

.paper-card-soft {
  background: var(--cream-50);
  border: 2px solid var(--ink-700);
  border-radius: 20px 24px 22px 26px / 24px 20px 26px 22px;
  box-shadow: 4px 4px 0 var(--ink-900);
}

.sticker {
  position: relative;
  background: var(--cream-50);
  padding: 1.25rem 1.5rem;
  border: 2.5px solid var(--ink-900);
  box-shadow: 6px 6px 0 var(--ink-900);
  display: inline-block;
}
.sticker-yellow { background: var(--gold-soft); }
.sticker-blue   { background: var(--blue); }
.sticker-red    { background: var(--hot-red); color: var(--cream-50); }

.tilt-left  { transform: rotate(-2deg); }
.tilt-right { transform: rotate(2deg); }
.tilt-more  { transform: rotate(-4deg); }

/* ----------------------------------------------------------------- buttons */

.btn-doodle {
  background: var(--gold);
  color: var(--ink-900);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.35rem;
  padding: 0.65rem 1.75rem;
  border: 2.5px solid var(--ink-900);
  border-radius: 24px 28px 22px 30px / 26px 22px 30px 24px;
  box-shadow: 4px 4px 0 var(--ink-900);
  transition: transform .15s ease, box-shadow .15s ease;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  line-height: 1;
  /* Touch target: 44px is the floor, and the doodle padding alone does not
     always reach it at the mini size. */
  min-height: 2.75rem;
  text-decoration: none;
}
.btn-doodle:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 var(--ink-900); }
.btn-doodle:disabled { opacity: 0.55; cursor: not-allowed; transform: none; box-shadow: 4px 4px 0 var(--ink-900); }

.btn-doodle-blue  { background: var(--blue);     color: var(--ink-900); }
.btn-doodle-ghost { background: var(--cream-50); color: var(--ink-900); }
.btn-doodle-red   { background: var(--hot-red);  color: var(--cream-50); }
.btn-mini { font-size: 1rem; padding: 0.4rem 1rem; box-shadow: 3px 3px 0 var(--ink-900); min-height: 2.5rem; }

/* ------------------------------------------------------------------ inputs */

.input-doodle {
  background: var(--cream-50);
  border: 2.5px solid var(--ink-700);
  color: var(--ink-900);
  padding: 0.75rem 1rem;
  border-radius: 16px 20px 18px 22px / 20px 16px 22px 18px;
  width: 100%;
  /* Data face, not handwriting: these hold email addresses, codes and
     identifiers, where a misread character costs a sign-in. */
  font-family: var(--font-data);
  font-weight: 400;
  font-size: 1rem;
  min-height: 2.75rem;
}
.input-doodle::placeholder { color: var(--ink-500); font-style: italic; }
.input-doodle:focus { outline: none; border-color: var(--ink-900); box-shadow: 3px 3px 0 var(--ink-900); }
.input-doodle:focus-visible { outline: 3px solid var(--hot-red); outline-offset: 3px; }
.input-doodle.invalid { border-color: var(--hot-red); }

/* A form label is always present and always visible. The template's pages use
   placeholder-only inputs; claude.md forbids that, and a placeholder vanishes
   the moment someone starts typing. */
.field-label {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.2rem;
  margin-bottom: 0.35rem;
}

.field-hint { font-family: var(--font-data); font-size: 0.875rem; color: var(--ink-500); margin: 0.35rem 0 0; }
.field-error { font-family: var(--font-data); font-size: 0.875rem; color: var(--hot-red-ink); display: block; margin-top: 0.35rem; }

/* --------------------------------------------------------------- chips */

.tier-chip {
  display: inline-flex; align-items: center; gap: 0.3rem;
  font-family: var(--font-display); font-weight: 700; font-size: 1rem;
  padding: 0.15rem 0.75rem;
  border-radius: 14px 18px 16px 20px / 18px 14px 20px 16px;
  border: 2px solid var(--ink-900);
  background: var(--cream-50); color: var(--ink-900);
  box-shadow: 2px 2px 0 var(--ink-900);
}
.tier-premium { background: var(--gold-soft); }
/* Deepened fill: the label is 1rem bold, below the large-text threshold, so it
   needs the full 4.5:1 rather than the 3:1 the brand red would give. */
.tier-vip     { background: var(--hot-red-ink); color: var(--cream-50); }

.filter-chip {
  font-family: var(--font-display); font-weight: 700; font-size: 1.15rem;
  padding: 0.35rem 1rem;
  border: 2.5px solid var(--ink-900); background: var(--cream-50);
  border-radius: 20px 24px 22px 26px / 24px 20px 26px 22px;
  box-shadow: 2px 2px 0 var(--ink-900);
}
.filter-chip.active { background: var(--hot-red-ink); color: var(--cream-50); box-shadow: 3px 3px 0 var(--ink-900); }

/* -------------------------------------------------------- doodle surfaces */

.doodle-bg {
  background-image: url("../images/doodle-hero.png");
  background-size: 600px auto;
  background-repeat: repeat;
}

.doodle-overlay { position: relative; }
.doodle-overlay::before {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(245, 228, 180, 0.85) 0%, rgba(245, 228, 180, 0.7) 50%, rgba(245, 228, 180, 0.95) 100%);
  pointer-events: none;
}
.doodle-overlay > * { position: relative; z-index: 1; }

/* ------------------------------------------------------------- animations */

@keyframes wobble { 0%,100%{transform:rotate(-2deg);} 50%{transform:rotate(2deg);} }
.wobble { animation: wobble 4s ease-in-out infinite; transform-origin: center; }
@keyframes fadeUp { from { opacity: 0; transform: translateY(20px);} to { opacity: 1; transform: translateY(0);} }
.fade-up { animation: fadeUp 0.8s ease-out forwards; }

/* --------------------------------------------------------------- navbar */

.navbar {
  position: sticky; top: 0; z-index: 50;
  background: var(--cream-100);
  border-bottom: 2.5px solid var(--ink-900);
  padding: 0.85rem 1.5rem;
}
.navbar .nav-inner {
  max-width: 1280px; margin: 0 auto;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
}
.navbar nav { display: flex; gap: 1.75rem; flex-wrap: wrap; }
.navbar nav a { font-family: var(--font-display); font-size: 1.35rem; font-weight: 700; text-decoration: none; }
.navbar nav a:hover { color: var(--orange); }
.navbar .active { color: var(--hot-red-ink); }

/* The template hides navigation entirely below 768px, which on a back office
   would strand an operator with no way to move between screens. It wraps here
   instead. */
@media (max-width: 768px) {
  .navbar nav { width: 100%; gap: 1rem; }
  .navbar nav a { font-size: 1.2rem; }
}

/* The brand lockup: two words, two faces, opposed tilts. */
.brand { display: inline-flex; align-items: baseline; gap: 0.25rem; text-decoration: none; }
.brand__first { font-family: var(--font-display); font-weight: 700; font-size: 2.25rem; display: inline-block; transform: rotate(-3deg); }
.brand__second { font-family: var(--font-marker); font-size: 1.35rem; color: var(--hot-red-ink); display: inline-block; transform: rotate(3deg); }

/* --------------------------------------------------------------- footer */

footer.site-footer {
  background: var(--cream-200);
  border-top: 2.5px solid var(--ink-900);
  margin-top: 4rem;
  position: relative;
}
footer.site-footer::before {
  content: ""; position: absolute; inset: 0;
  background-image: url("../images/doodle-hero.png");
  background-size: 600px auto; background-repeat: repeat;
  opacity: 0.5; pointer-events: none;
}
footer.site-footer::after {
  content: ""; position: absolute; inset: 0;
  background: rgba(245,228,180,0.75); pointer-events: none;
}
footer.site-footer > * { position: relative; z-index: 1; }
/*
   The multi-column footer, added when the member site arrived — the back office
   footer is a single line and never needed it. Two columns rather than four on a
   phone, because four columns of link lists at 375px is four columns of one word
   each.
*/
footer .foot-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 3rem;
  padding: 4rem 1.5rem;
  max-width: 1280px;
  margin: 0 auto;
}

@media (max-width: 768px) {
  footer .foot-grid { grid-template-columns: 1fr 1fr; gap: 2rem; }
}

footer .foot-grid ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.5rem; }
footer .foot-grid a:hover { color: var(--hot-red-ink); text-decoration: underline wavy; }

footer .foot-bot {
  border-top: 2px dashed var(--ink-700);
  padding: 1.25rem 1.5rem;
  text-align: center;
  color: var(--ink-700);
  font-family: var(--font-data);
  font-size: 0.9rem;
}
footer .foot-bot a { color: var(--ink-700); }

/* ----------------------------------------------------------- legal prose */

/*
   Long-form terms and policy pages. Member-side only — the back office has no
   prose of this shape — but shared rather than kept in the member application,
   because the member site is not the only thing that will ever render the terms
   somebody agreed to, and a second copy would drift from this one.

   The bullet is a marker-face glyph rather than a list-style, so it picks up the
   same hand-drawn character as the rest of the system.
*/
.terms-prose ul { list-style: none; padding-left: 0; margin: 0; }
.terms-prose ul > li { position: relative; padding-left: 1.6rem; margin-bottom: 0.65rem; }
.terms-prose ul > li::before {
  content: "✦";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--hot-red-ink);
  font-family: var(--font-marker);
  font-size: 1.1rem;
}
.terms-prose strong { color: var(--hot-red-ink); font-weight: 700; }
.terms-prose p { margin-bottom: 0.6rem; }

/* ---------------------------------------------------------------- layout */

.container { max-width: 1280px; margin: 0 auto; padding: 0 1.5rem; }
.max-3xl { max-width: 48rem; margin: 0 auto; }
.max-4xl { max-width: 56rem; margin: 0 auto; }
.max-5xl { max-width: 64rem; margin: 0 auto; }
.max-6xl { max-width: 72rem; margin: 0 auto; }

.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.5rem; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; }
@media (max-width: 768px) {
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
}

.flex { display: flex; }
.flex-wrap { flex-wrap: wrap; }
.gap-2 { gap: 0.5rem; } .gap-3 { gap: 0.75rem; } .gap-4 { gap: 1rem; } .gap-6 { gap: 1.5rem; } .gap-8 { gap: 2rem; }
.items-center { align-items: center; }
.items-baseline { align-items: baseline; }
.justify-center { justify-content: center; }
.justify-between { justify-content: space-between; }
.text-center { text-align: center; }
.mb-2 { margin-bottom: 0.5rem; } .mb-3 { margin-bottom: 0.75rem; } .mb-4 { margin-bottom: 1rem; } .mb-6 { margin-bottom: 1.5rem; } .mb-8 { margin-bottom: 2rem; } .mb-10 { margin-bottom: 2.5rem; } .mb-12 { margin-bottom: 3rem; }
.mt-2 { margin-top: 0.5rem; } .mt-4 { margin-top: 1rem; } .mt-6 { margin-top: 1.5rem; } .mt-8 { margin-top: 2rem; } .mt-12 { margin-top: 3rem; }
.p-4 { padding: 1rem; } .p-5 { padding: 1.25rem; } .p-6 { padding: 1.5rem; } .p-8 { padding: 2rem; } .p-10 { padding: 2.5rem; }
.py-10 { padding-top: 2.5rem; padding-bottom: 2.5rem; }
.py-16 { padding-top: 4rem; padding-bottom: 4rem; }
.px-6 { padding-left: 1.5rem; padding-right: 1.5rem; }
.rounded-full { border-radius: 999px; }
.w-full { width: 100%; }
.min-h-screen { min-height: 100vh; }
/* Portrait card ratios, from the template. A content card is 4:5 there; 3:4 is the tighter
   variant the experiences page uses. Both were dropped when this file was derived by hand, which
   left the catalogue with no way to reserve a card's space and the layout shifting as posters
   arrived. */
.aspect-45 { aspect-ratio: 4 / 5; }
.aspect-34 { aspect-ratio: 3 / 4; }
.aspect-video { aspect-ratio: 16 / 9; }
.object-cover { object-fit: cover; width: 100%; height: 100%; }
.relative { position: relative; }
.absolute { position: absolute; }
.inset-0 { inset: 0; }
.overflow-hidden { overflow: hidden; }
.hidden { display: none; }

/* Wide content must scroll inside its own container; the page body must never
   scroll sideways. Data grids and code blocks are the usual offenders. */
.scroll-x { overflow-x: auto; max-width: 100%; }

/* ------------------------------------------------------------ text sizes */

.text-sm { font-size: 0.9rem; }
.text-base { font-size: 1rem; }
.text-lg { font-size: 1.15rem; }
.text-xl { font-size: 1.35rem; }
.text-2xl { font-size: 1.75rem; }
.text-3xl { font-size: 2.25rem; }
.text-4xl { font-size: 3rem; }
.text-5xl { font-size: 3.75rem; }
.text-6xl { font-size: 4.75rem; }

/* The two largest steps were also lost in derivation, and three page headings have been asking for
   text-7xl since slice 2b-i and rendering at the browser's default h1 size instead. Restored at the
   template's own values. */
.text-7xl { font-size: 6rem; }
.text-8xl { font-size: 7.5rem; }
@media (max-width: 768px) {
  .text-8xl, .text-7xl, .text-6xl { font-size: 3.5rem; }
  .text-5xl { font-size: 2.75rem; }
  .text-4xl { font-size: 2.25rem; }
}
