/* Design system ported from _artifacts/hmm-course-portal-ui.html (the
   verified, contrast-measured mockup). Tokens, type scale, and component
   classes below are a direct lift, not a reinterpretation -- see that file
   for the contrast measurements and reasoning behind each decision.
   Self-hosted fonts (both Perfectly Nineties and Rethink Sans) rather than
   the mockup's base64-embedded/Google-Fonts-linked versions -- those exist
   only so the mockup renders standalone; this is a live product. */

@font-face {
  font-family: "Perfectly Nineties";
  src: url("fonts/PerfectlyNineties-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Perfectly Nineties";
  src: url("fonts/PerfectlyNineties-Italic.ttf") format("truetype");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Rethink Sans";
  src: url("fonts/RethinkSans_400Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Rethink Sans";
  src: url("fonts/RethinkSans_500Medium.ttf") format("truetype");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Rethink Sans";
  src: url("fonts/RethinkSans_600SemiBold.ttf") format("truetype");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Rethink Sans";
  src: url("fonts/RethinkSans_700Bold.ttf") format("truetype");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* =========================================================================
   RESET
   ========================================================================= */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
button { font: inherit; color: inherit; background: none; border: none; padding: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }
img, svg { display: block; max-width: 100%; }
input { font: inherit; color: inherit; }

/* =========================================================================
   TOKENS -- values copied verbatim from the mockup, which copied them
   verbatim from lib/theme.ts. Do not introduce new colors here.
   ========================================================================= */
:root {
  --dark-brown: #593904;
  --mid-brown: #af9983;
  --light-brown: #c8b19b;
  --beige: #efdece;
  --additional-brown: #eadfd4;
  --off-white: #f9f1e9;
  --site-white: #fffcf8;
  --green: #848241;
  --warn: #b85c00;
  --overlay: rgba(89, 57, 4, 0.55);

  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 32px;
  --space-xxl: 48px;

  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-xl: 20px;
  --radius-xxl: 32px;
  --radius-xxxl: 40px;
  --radius-pill: 999px;

  --font-heading: 'Perfectly Nineties', Georgia, 'Times New Roman', serif;
  --font-body: 'Rethink Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}

/* =========================================================================
   CONTRAST DECISIONS (measured against this palette, not eyeballed --
   see the mockup file for the full ratio table). The consequences that
   matter while editing this file:
   1. midBrown is NEVER a text color. Dividers, disabled fills, and resting
      placeholder text only (placeholders are contrast-exempt under WCAG).
   2. Input borders use darkBrown, not lightBrown/midBrown -- the lighter
      browns fail the 3:1 non-text minimum against both the page and the
      input's own near-white fill.
   3. Buttons keep the app's real green fill/text (matches Button.tsx).
   4. Italic emphasis renders in darkBrown, never green, so it stays
      legible at body-copy sizes.
   ========================================================================= */

body {
  background: var(--off-white);
  color: var(--dark-brown);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* =========================================================================
   TYPOGRAPHY
   ========================================================================= */
.pn-72, .pn-56, .pn-36, .pn-24, .pn-18 {
  font-family: var(--font-heading);
  font-weight: 400;
  font-style: normal;
  line-height: 1.1;
  color: var(--dark-brown);
  margin: 0;
}
.pn-72 { font-size: clamp(42px, 5vw + 24px, 72px); }
.pn-56 { font-size: clamp(34px, 4vw + 20px, 56px); }
.pn-36 { font-size: clamp(27px, 3vw + 16px, 36px); }
.pn-24 { font-size: clamp(21px, 1.5vw + 15px, 24px); }
.pn-18 { font-size: clamp(17px, 1vw + 12px, 18px); }

/* Emphasis: Perfectly Nineties italic, never bold, always darkBrown. */
.emph {
  font-family: var(--font-heading);
  font-style: italic;
  font-weight: 400;
  color: var(--dark-brown);
}

.rs-24 { font-family: var(--font-body); font-size: 24px; font-weight: 400; }
.rs-20 { font-family: var(--font-body); font-size: 20px; font-weight: 400; }
.rs-18 { font-family: var(--font-body); font-size: 18px; font-weight: 400; }
.rs-16 { font-family: var(--font-body); font-size: 16px; font-weight: 400; }
.rs-14 { font-family: var(--font-body); font-size: 14px; font-weight: 400; }
.rs-semibold { font-weight: 600; }
.rs-bold { font-weight: 700; }

.lede { font-family: var(--font-body); font-size: 18px; line-height: 1.5; color: var(--dark-brown); max-width: 46em; margin: 0; }
.body-copy { font-family: var(--font-body); font-size: 16px; line-height: 1.5; color: var(--dark-brown); max-width: 46em; margin: 0; }

.field-label {
  display: block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--dark-brown);
  margin-bottom: var(--space-sm);
}

/* =========================================================================
   ICONS
   ========================================================================= */
.icon { width: 22px; height: 22px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; flex-shrink: 0; }
.icon-sm { width: 16px; height: 16px; }
.icon-fill { fill: currentColor; stroke: none; }

/* =========================================================================
   LAYOUT SHELL
   ========================================================================= */
.shell {
  max-width: 720px;
  margin-inline: auto;
  padding-inline: clamp(20px, 5vw, 40px);
}
.view { min-height: 100vh; }

/* =========================================================================
   SHARED PORTAL HEADER
   Sign-in intentionally does not use this header -- an unauthenticated
   visitor has nowhere it could take her yet.
   ========================================================================= */
.portal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-sm);
  padding: var(--space-md) clamp(20px, 5vw, 40px);
  border-bottom: 1px solid var(--light-brown);
}
.wordmark {
  font-family: var(--font-heading);
  font-size: 20px;
  color: var(--dark-brown);
}
.header-links { display: flex; align-items: center; gap: var(--space-md); }
.signout-link, .help-link {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  color: var(--dark-brown);
  padding: var(--space-sm);
  margin: calc(var(--space-sm) * -1);
  border-radius: var(--radius-sm);
}
.signout-link:hover, .help-link:hover { text-decoration: underline; }

/* =========================================================================
   BUTTONS -- mirrors components/ui/Button.tsx (padding, radius, fill,
   weight). min-height asserted explicitly for the 44-52px touch target.
   ========================================================================= */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  min-height: 52px;
  padding: 16px 32px;
  border-radius: var(--radius-pill);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 16px;
  width: 100%;
  text-align: center;
}
.btn-primary { background: var(--green); color: var(--site-white); }
.btn-secondary { background: var(--dark-brown); color: var(--site-white); }
.btn-outline { background: transparent; border: 1.5px solid var(--green); color: var(--green); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }
.btn-inline { width: auto; padding: 12px 20px; min-height: 44px; font-size: 14px; }

a:focus-visible, button:focus-visible, input:focus-visible, [tabindex]:focus-visible {
  outline: 3px solid var(--dark-brown);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* =========================================================================
   FORM FIELDS
   ========================================================================= */
.field { margin-bottom: var(--space-lg); }
.text-input {
  width: 100%;
  min-height: 52px;
  padding: 0 var(--space-md);
  background: var(--site-white);
  border: 1.5px solid var(--dark-brown);
  border-radius: var(--radius-md);
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--dark-brown);
}
.text-input::placeholder { color: var(--mid-brown); }
.text-input:focus { outline: none; border-width: 2px; box-shadow: 0 0 0 3px rgba(89, 57, 4, 0.15); }

/* =========================================================================
   CARDS
   ========================================================================= */
.card {
  display: block;
  background: var(--beige);
  border-radius: var(--radius-lg);
  padding: 20px;
  box-shadow: 0 1px 3px rgba(89, 57, 4, 0.08);
}

/* =========================================================================
   REDUCED MOTION -- motion is opted IN only here, so a user who prefers
   reduced motion (or whose browser doesn't support the query) gets instant
   state changes by default.
   ========================================================================= */
@media (prefers-reduced-motion: no-preference) {
  .module-panel { transition: grid-template-rows 0.25s ease; }
  .icon-chevron { transition: transform 0.2s ease; }
  .auth-card, .library-state { transition: opacity 0.2s ease; }
}

/* =========================================================================
   BANNERS -- not in the mockup (it has no error states to design), kept
   from the working build. Styled with the ported tokens.
   ========================================================================= */
.banner {
  padding: var(--space-md);
  border-radius: var(--radius-md);
  margin: 0 0 var(--space-lg);
  font-family: var(--font-body);
  font-size: 15px;
  color: var(--dark-brown);
  background: var(--additional-brown);
  border: 1.5px solid var(--light-brown);
}
.banner.error { border-color: var(--warn); }

/* Loading skeletons, not in the mockup either -- neutral fill only. */
.skeleton { background: var(--beige); border-radius: var(--radius-lg); height: 88px; opacity: 0.6; }

/* =========================================================================
   SIGN IN
   ========================================================================= */
.auth-shell {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-xl) var(--space-md);
}
/* The single flex child of .auth-shell -- see the comment on this element
   in index.html for why it must stay the only one. Banner and both cards
   stack inside it in normal block flow. */
.auth-card-wrap { width: 100%; max-width: 420px; }
.auth-card { width: 100%; max-width: 420px; }
.auth-wordmark { font-family: var(--font-heading); font-size: 22px; text-align: center; margin-bottom: var(--space-xl); }
.auth-heading { margin-bottom: var(--space-sm); }
.auth-lede { margin-bottom: var(--space-xl); }

/* Real Turnstile widget mounts inside .turnstile-box (interaction-only
   appearance -- invisible unless Cloudflare's risk engine forces a
   challenge). The box's border/padding gives it a defined, findable home
   on the page even when the widget itself renders nothing. */
.turnstile-box {
  display: flex;
  align-items: center;
  min-height: 24px;
  margin-bottom: var(--space-lg);
}

.help-row { text-align: center; margin-top: var(--space-lg); font-size: 14px; }
.help-row a { text-decoration: underline; font-weight: 600; }

.sent-icon {
  width: 56px; height: 56px;
  border-radius: 50%;
  border: 2px solid var(--dark-brown);
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto var(--space-lg);
}
.resend-row { margin-top: var(--space-lg); }
.resend-note { text-align: center; font-size: 14px; margin-top: var(--space-sm); }

/* =========================================================================
   LIBRARY
   ========================================================================= */
.library-main { padding-top: var(--space-xl); padding-bottom: var(--space-xxl); }
.library-main h1 { margin-bottom: var(--space-sm); }
.library-main .lede { margin-bottom: var(--space-xl); }

.card-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-md);
}
@media (min-width: 640px) {
  .card-grid { grid-template-columns: repeat(2, 1fr); }
}
/* Single-item state: cap the card width instead of letting grid stretch
   one card across a whole desktop row. Not an edge case -- 598 of 1,193
   members own exactly one product. */
.card-grid.card-grid--single {
  grid-template-columns: minmax(0, 420px);
}

.product-card { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-sm); }
.tag {
  display: inline-flex;
  align-items: center;
  padding: 3px 12px;
  border-radius: var(--radius-pill);
  border: 1.5px solid var(--green);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--dark-brown);
}
.product-card h2 { margin-top: var(--space-xs); }
.product-card-meta { font-size: 15px; color: var(--dark-brown); margin: 0; }
.card-cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: var(--space-sm);
  font-size: 15px;
  font-weight: 700;
  color: var(--dark-brown);
}
.card-cta .icon { width: 16px; height: 16px; }

.empty-state {
  text-align: center;
  padding: var(--space-xxl) var(--space-md);
  max-width: 440px;
  margin: 0 auto;
}
.empty-state svg { margin: 0 auto var(--space-lg); }
.empty-state h1 { margin-bottom: var(--space-sm); }
.empty-state .body-copy { margin: 0 auto var(--space-lg); }
.empty-state .help-text { font-size: 14px; }
.empty-state .help-text a { text-decoration: underline; font-weight: 600; }

/* =========================================================================
   PRODUCT
   ========================================================================= */
.product-main { padding-top: var(--space-lg); padding-bottom: var(--space-xxl); }
.back-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 15px;
  font-weight: 600;
  margin-bottom: var(--space-lg);
  padding: var(--space-xs) 0;
}
.back-link .icon { width: 18px; height: 18px; }
.product-main h1 { margin-bottom: var(--space-sm); }
#course-meta { color: var(--dark-brown); font-size: 15px; margin-bottom: var(--space-md); }

.module {
  border-top: 1px solid var(--light-brown);
}
.module:last-child { border-bottom: 1px solid var(--light-brown); }
.module-header {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-md) 4px;
  min-height: 56px;
  text-align: left;
}
.module-header-text { display: flex; flex-direction: column; gap: 2px; }
.module-title { font-family: var(--font-body); font-weight: 700; font-size: 17px; color: var(--dark-brown); }
.module-meta { font-size: 14px; color: var(--dark-brown); opacity: 0.75; }
.module-header[aria-expanded="true"] .icon-chevron { transform: rotate(180deg); }

.module-panel {
  display: grid;
  grid-template-rows: 0fr;
}
.module-panel.is-open { grid-template-rows: 1fr; }
.module-panel-inner { overflow: hidden; min-height: 0; padding-bottom: var(--space-sm); }

/* Single-module products (all 3 flat products) skip the accordion header
   entirely and render lesson rows directly -- see product.js. */
.no-module-heading { padding-top: var(--space-sm); }

.lesson-row {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  min-height: 56px;
  padding: var(--space-sm) 4px;
  border-radius: var(--radius-md);
  color: var(--dark-brown);
}
a.lesson-row:hover, a.lesson-row:focus-visible { background: var(--additional-brown); }
.lesson-row .icon { color: var(--dark-brown); opacity: 0.6; }
.lesson-row-title { flex: 1; font-size: 16px; }
.lesson-row-files {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
  color: var(--dark-brown);
  opacity: 0.75;
  flex-shrink: 0;
}
.lesson-row-duration { font-size: 14px; color: var(--dark-brown); opacity: 0.75; flex-shrink: 0; }
.lesson-row--download { cursor: default; }
.lesson-row-dl {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  font-weight: 600;
  color: var(--dark-brown);
  padding: 6px 12px;
  border: 1.5px solid var(--dark-brown);
  border-radius: var(--radius-pill);
  flex-shrink: 0;
}

/* =========================================================================
   LESSON
   ========================================================================= */
.lesson-main { padding-top: var(--space-lg); padding-bottom: var(--space-xxl); max-width: 760px; }
.lesson-eyebrow { font-size: 13px; font-weight: 600; letter-spacing: 0.5px; text-transform: uppercase; color: var(--dark-brown); opacity: 0.75; margin-bottom: var(--space-xs); }
.lesson-main h1 { margin-bottom: var(--space-lg); }

/* Real Cloudflare Stream iframe, not the mockup's decorative placeholder
   transport bar -- the iframe embed already provides its own native
   controls (play/pause, scrubber, captions, fullscreen), so there is
   nothing for a second, non-functional control bar to do. The frame
   itself keeps the mockup's exact container treatment. */
.video-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--dark-brown);
  border-radius: var(--radius-lg);
  overflow: hidden;
  margin-bottom: var(--space-xl);
}
.video-frame iframe { width: 100%; height: 100%; border: 0; }
.video-placeholder-text {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--site-white);
  font-size: 14px;
  text-align: center;
  padding: var(--space-md);
}

/* Sanitized lesson body text (see lesson.js -- DOMPurify strips everything
   but plain structural/inline tags before this ever reaches the DOM).
   Typography matches body-copy; headings inside the source content are
   downgraded so they read as in-body emphasis, not a second page title
   competing with the real <h1> above. */
.lesson-body {
  margin-bottom: var(--space-xl);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  color: var(--dark-brown);
  max-width: 46em;
}
.lesson-body p { margin: 0 0 var(--space-md); }
.lesson-body p:last-child { margin-bottom: 0; }
.lesson-body ul, .lesson-body ol { margin: 0 0 var(--space-md); padding-left: 1.4em; list-style: disc; }
.lesson-body ol { list-style: decimal; }
.lesson-body li { margin-bottom: var(--space-xs); }
.lesson-body a { text-decoration: underline; font-weight: 600; }
.lesson-body blockquote {
  margin: 0 0 var(--space-md);
  padding-left: var(--space-md);
  border-left: 3px solid var(--light-brown);
  color: var(--dark-brown);
}
.lesson-body h1, .lesson-body h2, .lesson-body h3,
.lesson-body h4, .lesson-body h5, .lesson-body h6 {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 16px;
  color: var(--dark-brown);
  margin: 0 0 var(--space-sm);
}
.lesson-body hr { border: none; border-top: 1px solid var(--light-brown); margin: var(--space-lg) 0; }

.files-section h2 { margin-bottom: var(--space-md); }
.file-row {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  min-height: 56px;
  padding: var(--space-sm) 0;
  border-bottom: 1px solid var(--light-brown);
}
.file-row:last-child { border-bottom: none; }
.file-row .icon { color: var(--dark-brown); }
.file-row-name { flex: 1; font-size: 16px; }
.file-row-dl {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  font-weight: 600;
  color: var(--dark-brown);
  padding: 8px 14px;
  border: 1.5px solid var(--dark-brown);
  border-radius: var(--radius-pill);
  flex-shrink: 0;
}
.file-row-dl:hover, .file-row-dl:focus-visible { background: var(--additional-brown); }
