/* ==========================================================================
   CTDC Academy — theme layer for Bootstrap 5.3
   Loaded after bootstrap.min.css.

   Bootstrap's own classes are never redefined in this file. Everything here is
   one of three things:
     1. a design token on :root,
     2. the .theme-ctdc block, which feeds Bootstrap's public CSS variables and
        is scoped to the element carrying the class (the <body>),
     3. a custom class applied *alongside* a Bootstrap one — .btn btn-brand,
        .form-control field-input, and so on.

   So dropping `theme-ctdc` from the <body> leaves stock Bootstrap behind.
   ========================================================================== */

/* ---------------------------------------------------------------------------
 * Fonts, served from this domain.
 *
 * The same faces the rest of the site uses, declared again here because the
 * auth layout loads this stylesheet instead of front/css/app.css.
 *
 * These used to come from fonts.googleapis.com, which cost every page a
 * render-blocking stylesheet on a third-party origin before any text could
 * paint — and disclosed every visitor's IP address to Google, which is the
 * specific practice German courts have ruled against under GDPR.
 *
 * Only the latin and latin-ext subsets are kept. The site runs in English and
 * Arabic; latin-ext is what carries the accented characters in names like
 * "Tomás". Cyrillic, Greek and Vietnamese were dropped, which is most of the
 * weight Google was serving.
 *
 * Both are variable fonts, so one file covers every weight the design uses.
 * `font-display: swap` matches what Google served: text paints immediately in
 * the fallback and reflows once, rather than sitting invisible.
 * ------------------------------------------------------------------------- */

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('../../front/fonts/self-hosted/manrope-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: 'Manrope';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('../../front/fonts/self-hosted/manrope-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: 'Urbanist';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../../front/fonts/self-hosted/urbanist-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: 'Urbanist';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../../front/fonts/self-hosted/urbanist-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: 'Urbanist';
  font-style: italic;
  font-weight: 100 900;
  font-display: swap;
  src: url('../../front/fonts/self-hosted/urbanist-italic-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: 'Urbanist';
  font-style: italic;
  font-weight: 100 900;
  font-display: swap;
  src: url('../../front/fonts/self-hosted/urbanist-italic-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;
}


/* --------------------------------------------------------------------------
   1. Design tokens
   Text colours are chosen to clear WCAG 2.1 AA (4.5:1) on their own surface;
   the ratio is noted where it is close.
   -------------------------------------------------------------------------- */

:root {
  /*
   * Retuned to the front-end theme (front/css/main.css). The values are its
   * --tj-color-* tokens written out, because these pages load Bootstrap rather
   * than the template stylesheet and cannot read them: signing in should not
   * look like a different product, but it must not pull in 20,000 lines of
   * template CSS to prove it. The names stay as they were, so every rule below
   * keeps working.
   */
  --brand-50:  #faf8fe;  /* theme-bg-10 */
  --brand-100: #f9edff;  /* theme-bg-2  */
  --brand-200: #ece0ff;  /* the lilac end of the template's gradients */
  --brand-300: #dac2ff;
  --brand-400: #905de0;  /* theme-purple-2 */
  --brand-500: #6437cf;  /* theme-purple-4 */
  --brand-600: #3f3854;  /* theme-primary — 10.9:1 on white */
  --brand-700: #3c2166;  /* theme-purple  */
  --brand-800: #341d59;  /* theme-purple-3 — the aside's text colour */

  /* The accent the template uses for stars, prices and highlights. */
  --accent:    #ff4d00;  /* orange-1 */
  --accent-2:  #ffa838;  /* orange-2 */

  --ink:       #272f54;  /* heading-primary */
  --ink-soft:  #434966;  /* text-body */
  --muted:     #696d85;  /* text-body-3 — 4.9:1 on white */
  --muted-2:   #7c8095;  /* placeholders and icons — clears the 3:1 UI bar */

  --line:      #e6e7eb;  /* border-1 */
  --line-soft: rgba(39, 47, 84, .08);  /* border-2 */

  --canvas:    #faf8fe;  /* theme-bg-10 */
  --surface:   #ffffff;
  --surface-2: #faf8fe;
  --surface-3: #f9edff;  /* theme-bg-2 */

  --danger:      #d13030;  /* red-1 */
  --focus-ring:  var(--brand-50);
  --danger-ring: rgba(209, 48, 48, .15);
}

/* --------------------------------------------------------------------------
   2. Theme — Bootstrap's public variables, scoped to .theme-ctdc
   Set on the <body>, so every Bootstrap component inside inherits them while
   Bootstrap's defaults stay intact.
   -------------------------------------------------------------------------- */

.theme-ctdc {
  --bs-primary: var(--brand-600);
  --bs-primary-rgb: 63, 56, 84;

  /* Manrope for text, Urbanist for headings — the template's pairing, at the
     template's own metrics: 16px body, 1.625 leading, a hair of tracking. */
  --bs-body-font-family: 'Manrope', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --bs-heading-font-family: 'Urbanist', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --bs-body-font-size: 1rem;
  --bs-body-line-height: 1.625;
  --bs-body-color: var(--ink);
  --bs-body-color-rgb: 15, 23, 42;
  --bs-body-bg: var(--canvas);

  --bs-secondary-color: var(--muted);
  /*
   * `.text-secondary` never reads the variable above: in Bootstrap 5.3 it is
   * `rgba(var(--bs-secondary-rgb), ...)`, fed by the stock grey #6c757d, which
   * measures 4.45:1 on this canvas. That is under AA for the one-line intros and
   * the "Don't have an account?" lines on the sign-in, sign-up, reset and code
   * screens. The same --muted, as channels: 4.83:1 here, 5.09:1 on white.
   * (Final pre-production audit of 11 September 2026, M-82.)
   */
  --bs-secondary-rgb: 105, 109, 133;
  --bs-border-color: var(--line);
  --bs-border-color-translucent: var(--line-soft);

  /* Minimal radius — just enough to take the edge off. */
  --bs-border-radius-sm: 3px;
  --bs-border-radius: 5px;
  --bs-border-radius-lg: 7px;
  --bs-border-radius-xl: 10px;

  /*
   * Links follow the front end: body-coloured, no underline at rest, moving to
   * the theme primary when hovered. The template pairs that shift with a rule
   * that grows under the label (its footer and text buttons both do it), which
   * is where the underline below comes from — on this palette the colour move
   * alone is too quiet to be an affordance.
   */
  --bs-link-color: var(--ink-soft);
  --bs-link-hover-color: var(--brand-600);
  --bs-link-decoration: none;
  --bs-link-color-rgb: 67, 73, 102;
  --bs-link-hover-color-rgb: 63, 56, 84;
  letter-spacing: .01em;
  --bs-link-hover-color-rgb: 78, 50, 204;

  --bs-focus-ring-color: rgba(63, 56, 84, .18);

  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* --------------------------------------------------------------------------
   3. Button variants — pair with .btn
   -------------------------------------------------------------------------- */

/* The template's medium button: 16px bold, 5px radius, and tall enough to sit
   with a 52px field (padding 18/26/15 there, evened out here because these
   buttons are full width and their label is centred). */
.btn-brand,
.btn-neutral {
  --bs-btn-font-family: var(--bs-body-font-family);
  --bs-btn-font-size: 1rem;
  --bs-btn-font-weight: 700;
  --bs-btn-line-height: 1.25;
  --bs-btn-padding-y: .9375rem;
  --bs-btn-padding-x: 1.625rem;
  --bs-btn-border-radius: 5px;
  --bs-btn-focus-shadow-rgb: 63, 56, 84;
  letter-spacing: -.01em;
}

/*
 * Hover matches the front end: `.tj-btn-primary:hover` does not change hue, it
 * lifts the same primary to 80% opacity (--tj-color-theme-primary-hover), so
 * the button lightens against the page rather than turning violet. Pressing it
 * goes the other way, to the heading ink, which is where the template's own
 * dark controls land.
 *
 * No drop shadow either: the template's primary button is flat, and a coloured
 * shadow was the loudest thing separating these pages from the rest of the site.
 */
.btn-brand {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--brand-600);
  --bs-btn-border-color: var(--brand-600);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: rgba(63, 56, 84, .8);
  --bs-btn-hover-border-color: rgba(63, 56, 84, .8);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--ink);
  --bs-btn-active-border-color: var(--ink);
  --bs-btn-disabled-color: #fff;
  --bs-btn-disabled-bg: var(--brand-300);
  --bs-btn-disabled-border-color: var(--brand-300);
  transition: background-color .3s ease-in-out, border-color .3s ease-in-out;
}

.btn-neutral {
  --bs-btn-color: var(--ink);
  --bs-btn-bg: var(--surface);
  --bs-btn-border-color: var(--line);
  --bs-btn-hover-color: var(--ink);
  --bs-btn-hover-bg: var(--surface-2);
  /* The template's outline button keeps its own colour on hover and moves only
     its border, so this does the same rather than tinting the label. */
  --bs-btn-hover-border-color: var(--brand-600);
  --bs-btn-active-color: var(--ink);
  --bs-btn-active-bg: var(--surface-3);
  --bs-btn-active-border-color: var(--brand-200);
}

/* Link-styled button — the "Resend" trigger */
.btn-inline {
  --bs-btn-color: var(--brand-600);
  --bs-btn-hover-color: var(--brand-700);
  --bs-btn-active-color: var(--brand-700);
  --bs-btn-disabled-color: var(--muted);
  --bs-btn-bg: transparent;
  --bs-btn-border-color: transparent;
  --bs-btn-hover-bg: transparent;
  --bs-btn-hover-border-color: transparent;
  --bs-btn-active-bg: transparent;
  --bs-btn-active-border-color: transparent;
  --bs-btn-font-weight: 600;
  --bs-btn-padding-y: 0;
  --bs-btn-padding-x: 0;
  --bs-btn-focus-shadow-rgb: 63, 56, 84;
}

/* Eye toggle sitting inside a password field */
.btn-reveal {
  --bs-btn-color: var(--muted-2);
  --bs-btn-hover-color: var(--brand-600);
  --bs-btn-active-color: var(--brand-600);
  --bs-btn-bg: transparent;
  --bs-btn-border-color: transparent;
  --bs-btn-hover-bg: transparent;
  --bs-btn-hover-border-color: transparent;
  --bs-btn-active-bg: transparent;
  --bs-btn-active-border-color: transparent;
  --bs-btn-padding-y: .25rem;
  --bs-btn-padding-x: .5rem;
  --bs-btn-focus-shadow-rgb: 63, 56, 84;
  z-index: 4;
}

/* Password currently visible */
.btn-reveal[aria-pressed="true"] { --bs-btn-color: var(--brand-600); }

/* Inline links, the way the front end draws them: body-coloured, no underline
   at rest, moving to the theme primary when hovered — with a rule appearing
   under the label, which is how the template's own footer and text links
   answer a pointer. Bootstrap 5.3's reboot hardcodes `text-decoration:
   underline` on <a>, so the resting state has to be turned off here rather than
   through --bs-link-decoration. Buttons are excluded: they already say what
   they are. */
.auth-form a:not(.btn),
.auth-aside a:not(.btn) {
  text-decoration: none;
}

.auth-form a:not(.btn):hover,
.auth-form a:not(.btn):focus-visible,
.auth-aside a:not(.btn):hover,
.auth-aside a:not(.btn):focus-visible {
  color: var(--brand-600);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

/* --------------------------------------------------------------------------
   4. Form controls — pair with .form-label / .form-control / .form-check-*
   -------------------------------------------------------------------------- */

/* Labels as the template writes them (.cf-label): 16px, semibold, heading ink,
   10px clear of the field. */
.field-label {
  display: block;
  margin-bottom: .625rem;
  font-size: 1rem;
  line-height: 1.4;
  font-weight: 600;
  color: var(--ink);
}

/*
 * The field itself, to the template's spec: 52px tall, 16px text in heading
 * ink, a tinted rather than white ground, a hairline border, 5px radius and no
 * resting shadow.
 */
.field-input {
  min-height: 52px;
  padding: .625rem 1.25rem;
  font-size: 1rem;
  color: var(--ink);
  background-color: var(--surface-2);
  border-color: var(--line-soft);
  border-radius: 5px;
  box-shadow: none;
  transition: border-color .3s ease, box-shadow .3s ease;
}

.field-input::placeholder {
  color: var(--muted);
  opacity: 1;
  transition: color .3s ease;
}

/*
 * Focus moves the border to the primary, as the template does. The ring is
 * ours: the template leaves focus to the border alone, which is a 1.4:1 change
 * and not a focus indicator anyone can rely on.
 */
.field-input:focus {
  background-color: var(--surface);
  border-color: var(--brand-600);
  box-shadow: 0 0 0 .1875rem rgba(63, 56, 84, .12);
}

.field-check {
  border-color: var(--line);
  border-radius: 4px;
}
.field-check:checked {
  background-color: var(--brand-600);
  border-color: var(--brand-600);
}
.field-check:focus {
  border-color: var(--brand-600);
  box-shadow: 0 0 0 .1875rem rgba(63, 56, 84, .12);
}

.field-check-label { font-size: .9375rem; color: var(--ink-soft); }

.field-hint { font-size: .875rem; color: var(--muted); }

/* --------------------------------------------------------------------------
   5. Validation — our own, in place of .was-validated / .invalid-feedback
   Errors only: a green tick on every field the user simply filled in is noise
   on a form this short. On submit, app.js adds .form-validated to the <form>
   and toggles .is-shown / aria-invalid per field, so nothing is flagged before
   the user has tried and the state is driven by one explicit mechanism rather
   than by selector structure.
   -------------------------------------------------------------------------- */

.field-error {
  display: none;
  margin-top: .375rem;
  font-size: .875rem;
  color: var(--danger);
}
.field-error.is-shown { display: block; }

.field-input[aria-invalid="true"],
.field-check[aria-invalid="true"],
.field-input.has-error { border-color: var(--danger); }

.field-input[aria-invalid="true"]:focus,
.field-input.has-error:focus {
  border-color: var(--danger);
  box-shadow: 0 0 0 .1875rem var(--danger-ring);
}

/* --------------------------------------------------------------------------
   6. Bespoke pieces Bootstrap has no component for
   -------------------------------------------------------------------------- */

/* Password strength meter. Colours come from data-score so JS sets one
   attribute instead of painting each tick inline. */
.strength { display: flex; gap: .5rem; }

.strength-tick {
  height: 4px;
  flex: 1 1 0;
  border-radius: 999px;
  background: var(--line);
  transition: background-color .15s ease;
}

.strength[data-score="1"] .strength-tick:nth-child(-n+1),
.strength[data-score="2"] .strength-tick:nth-child(-n+2),
.strength[data-score="3"] .strength-tick:nth-child(-n+3),
.strength[data-score="4"] .strength-tick:nth-child(-n+4) { background: var(--strength-colour); }

.strength[data-score="1"] { --strength-colour: #C2185B; }
.strength[data-score="2"] { --strength-colour: #A15C07; }
.strength[data-score="3"] { --strength-colour: #0B6E99; }
.strength[data-score="4"] { --strength-colour: #12703A; }

.strength-label { font-size: .71875rem; color: var(--muted); }
.strength-label[data-score="1"] { color: #C2185B; }
.strength-label[data-score="2"] { color: #A15C07; }
.strength-label[data-score="3"] { color: #0B6E99; }
.strength-label[data-score="4"] { color: #12703A; }

/* 6-digit verification code */
.code-group { display: flex; gap: .625rem; }

.code-input {
  min-width: 0;
  height: 3rem;
  padding-left: 0;
  padding-right: 0;
  text-align: center;
  font-size: 1.125rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 400px) {
  .code-group { gap: .375rem; }
  .code-input { height: 2.75rem; font-size: 1rem; }
}

/* --------------------------------------------------------------------------
   7. Auth layout
   -------------------------------------------------------------------------- */

.auth-page {
  min-height: 100vh;
  min-height: 100dvh;   /* dodges mobile browser chrome; vh is the fallback */
  display: grid;
  place-items: center;
  padding: 1.75rem;
  /* The template's hero wash (gradient-1), softened at the corners the way the
     course header carries it. */
  background:
    radial-gradient(60% 60% at 15% 20%, rgba(255, 229, 199, .85) 0%, transparent 60%),
    radial-gradient(60% 60% at 85% 85%, rgba(236, 224, 255, .9) 0%, transparent 60%),
    var(--canvas);
}

.auth-card {
  width: min(980px, 100%);
  border: 0;
  border-radius: var(--bs-border-radius-xl);
  box-shadow: 0 18px 40px rgba(43, 22, 96, .1);
  overflow: hidden;
}

.auth-aside {
  background: linear-gradient(150deg, #ffe5c7 0%, #ece0ff 100%);
  padding: 2.75rem 2.375rem;
}

.auth-form { padding: 2.875rem; }

/* Illustration sizes. Kept as classes rather than inline styles so the pages
   need no 'unsafe-inline' in style-src. */
.auth-figure    { width: 100%; max-width: 230px; height: auto; }
.auth-figure-sm { max-width: 200px; }
.auth-figure-lg { max-width: 250px; }

@media (max-width: 767.98px) {
  .auth-page { padding: 0; }
  .auth-card { border-radius: 0; min-height: 100vh; min-height: 100dvh; }
  .auth-aside { padding: 2rem; }
  .auth-form  { padding: 2rem 1.5rem 2.5rem; }
  /* Keep the illustration from pushing the form below the fold. */
  .auth-figure { max-width: 150px; }
}

@media (max-width: 575.98px) {
  .auth-aside { padding: 1.5rem 1.5rem 1.25rem; }
  .auth-figure { max-width: 116px; }
}

/* The mark carries the brand on its own — no wordmark beside it. */
.brand { display: inline-flex; }

.brand-logo {
  width: 64px;
  height: 64px;
  object-fit: contain;
  flex: 0 0 auto;
}

/* The template's heading scale, one step down for a card this size: h4 for the
   page title, h6 for the lead, both semibold with its -0.02em tracking. */
.auth-title {
  font-family: var(--bs-heading-font-family);
  font-size: 1.75rem;
  line-height: 1.16;
  font-weight: 600;
  letter-spacing: -.02em;
  color: var(--ink);
}

.auth-lead {
  font-family: var(--bs-heading-font-family);
  font-size: 1.125rem;
  line-height: 1.4;
  font-weight: 600;
  letter-spacing: -.015em;
  color: var(--ink);
}

/* Sentence case, body weight, quiet: it names the screen, it is not a label
   shouting above the heading. */
.auth-eyebrow {
  font-size: .875rem;
  font-weight: 500;
  color: var(--muted);
}

.auth-note { color: var(--brand-800); max-width: 250px; font-size: .875rem; }

.auth-divider { font-size: .875rem; color: var(--muted); }

.auth-prose { max-width: 24rem; }

/* --------------------------------------------------------------------------
   8. Motion
   -------------------------------------------------------------------------- */

@keyframes rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
.rise { animation: rise .45s cubic-bezier(.22, 1, .36, 1) both; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --------------------------------------------------------------------------
   9. Forced-colors / high-contrast mode
   -------------------------------------------------------------------------- */

@media (forced-colors: active) {
  .auth-card { border: 1px solid CanvasText; }
  .field-input:focus,
  .field-check:focus { outline: 2px solid Highlight; outline-offset: 1px; }
  .strength-tick { background: CanvasText; }
}
