/**
 * theme.css — the Orangelo design system. SINGLE SOURCE OF TRUTH.
 * ---------------------------------------------------------------------------
 * Plain CSS on purpose. Every rule here works identically whether Tailwind's
 * utilities arrive from the compiled build or the Play CDN fallback, so the
 * app can never change appearance depending on whether `npm run build` has
 * been run. Nothing in here uses @apply.
 *
 * Do NOT redefine .card / .btn-* / .field / .pill / .eyebrow anywhere else —
 * not in head.php, not in resources/css/app.css, not in a template <style>.
 * This file is the only place they exist.
 *
 * Loaded unconditionally by templates/partials/head.php.
 */

/* ── Design tokens ───────────────────────────────────────────────────────── */
:root {
  --safe-top: env(safe-area-inset-top);
  --page-bg: #FAF8F6;            /* matches body; used by sticky bars */
  --safe-bottom: env(safe-area-inset-bottom);
  --ease: cubic-bezier(.22, 1, .36, 1);

  --glass-bg: rgba(255, 255, 255, .55);
  --glass-border: rgba(0, 0, 0, .07);
  --glass-hover: rgba(0, 0, 0, .04);
  --glass-blur: 16px;
  --glass-shadow: 0 1px 3px rgba(0, 0, 0, .04), 0 8px 24px -12px rgba(0, 0, 0, .08);

  --surface-primary: #fff;
  --surface-secondary: #F4F0EC;
  --text-primary: #1E1E1E;
  --text-secondary: rgba(0, 0, 0, .5);
  --divider: rgba(0, 0, 0, .06);

  --brand: #FF6B00;
  --brand-ink: #E85F00;
}

html.dark {
  --glass-bg: rgba(255, 255, 255, .04);
  --glass-border: rgba(255, 255, 255, .08);
  --glass-hover: rgba(255, 255, 255, .06);
  --glass-shadow: 0 1px 3px rgba(0, 0, 0, .2), 0 8px 24px -12px rgba(0, 0, 0, .5);

  --surface-primary: #1E1E1E;
  --surface-secondary: #161616;
  --page-bg: #0C0C0C;
  --text-primary: #f0f0f0;
  --text-secondary: rgba(255, 255, 255, .45);
  --divider: rgba(255, 255, 255, .07);
}

/* ── Base ────────────────────────────────────────────────────────────────── */
html,
body {
  overscroll-behavior-y: none;          /* no rubber-band bounce in the webview */
}

body {
  -webkit-tap-highlight-color: transparent;
  background-color: #FAF8F6;            /* warmer ground than pure white */
  letter-spacing: -0.011em;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

html.dark body {
  background-color: #0C0C0C;
}

h1,
h2,
.font-display {
  letter-spacing: -0.028em;
  font-optical-sizing: auto;
}

::selection {
  background: #FFE8D6;
  color: #1E1E1E;
}

html.dark ::selection {
  background: rgba(255, 107, 0, .32);
  color: #fff;
}

*:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: rgba(0, 0, 0, .13);
  border-radius: 99px;
}

html.dark ::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, .13);
}

[x-cloak] {
  display: none !important;
}

/* ── Surfaces ────────────────────────────────────────────────────────────── */
.card {
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: 1rem;
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  box-shadow: var(--glass-shadow);
  transition: background .2s var(--ease), border-color .2s var(--ease),
              transform .25s var(--ease), box-shadow .25s var(--ease);
}

.card:hover {
  border-color: rgba(255, 107, 0, .18);
  transform: translateY(-1px);
  box-shadow: 0 4px 20px -8px rgba(0, 0, 0, .12);
}

html.dark .card:hover {
  box-shadow: 0 4px 20px -8px rgba(0, 0, 0, .4);
}

.card-flat {
  background: var(--surface-secondary);
  border-radius: 1rem;
}

/* Selected option cards (study mode, sign-up role, payment method, …).
   Keyed off the native :checked state so the highlight shows with or without
   Alpine, and regardless of how the utility CSS was produced. Scoped to
   .card labels so plain agree/remember checkboxes are unaffected. */
label.card:has(input[type="radio"]:checked),
label.card:has(input[type="checkbox"]:checked) {
  border-color: var(--brand) !important;
  box-shadow: 0 0 0 2px var(--brand);
  background-color: rgba(255, 107, 0, .06);
}

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.btn-primary {
  position: relative;
  overflow: hidden;
  background-image: linear-gradient(135deg, #FF8A33 0%, #FF6B00 55%, #E85F00 100%);
  background-color: #FF6B00;            /* if gradients are unsupported */
  color: #fff;
  font-weight: 600;
  box-shadow: 0 4px 16px -4px rgba(255, 107, 0, .5);
  transition: transform .18s var(--ease), box-shadow .18s var(--ease), filter .18s var(--ease);
}

.btn-primary:hover {
  filter: brightness(1.04);
  box-shadow: 0 8px 22px -6px rgba(255, 107, 0, .6);
  transform: translateY(-1px);
}

.btn-primary:active {
  transform: scale(.98);
}

.btn-primary::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(255, 255, 255, .14), rgba(255, 255, 255, 0));
}

.btn-ghost {
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  font-weight: 600;
  transition: background .2s var(--ease), border-color .2s var(--ease), transform .18s var(--ease);
}

.btn-ghost:hover {
  background: var(--glass-hover);
  border-color: rgba(255, 107, 0, .2);
  transform: translateY(-1px);
}

.btn-ghost:active {
  transform: scale(.98);
}

/* ── Form fields ─────────────────────────────────────────────────────────── */
.field {
  width: 100%;
  border-radius: .75rem;
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  padding: .875rem 1rem;
  outline: none;
  transition: background .18s var(--ease), border-color .18s var(--ease), box-shadow .18s var(--ease);
  font-size: 16px;                      /* keeps iOS from zooming on focus */
  color: inherit;
}

.field:focus {
  background: var(--surface-primary);
  border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(255, 107, 0, .16);
}

.field::placeholder {
  color: var(--text-secondary);
}

.label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  margin-bottom: .375rem;
  color: var(--text-primary);
  opacity: .75;
}

/* ── Small type ──────────────────────────────────────────────────────────── */
.eyebrow {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .12em;
  color: #A79C93;
}

.pill {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  padding: .25rem .625rem;
  border-radius: 999px;
  line-height: 1.4;
}

/* ── Gradient / colour helpers ───────────────────────────────────────────────
   These mirror Tailwind theme extensions. Defined here in plain CSS so they
   render correctly under the CDN fallback, which never reads tailwind.config.js
   and would otherwise leave hero cards white-on-white in light mode. */
.bg-ember {
  background-image: linear-gradient(135deg, #FF8A33 0%, #FF6B00 55%, #E85F00 100%);
  background-color: #FF6B00;
}

.bg-sheen {
  background-image: linear-gradient(180deg, rgba(255, 255, 255, .10), rgba(255, 255, 255, 0));
}

.shadow-glow {
  box-shadow: 0 8px 28px -8px rgba(255, 107, 0, .55);
}

.shadow-glow-sm {
  box-shadow: 0 3px 12px -3px rgba(255, 107, 0, .45);
}

.shadow-card {
  box-shadow: 0 1px 2px rgba(16, 12, 8, .04), 0 8px 24px -12px rgba(16, 12, 8, .12);
}

.shadow-lift {
  box-shadow: 0 2px 4px rgba(16, 12, 8, .04), 0 16px 40px -16px rgba(16, 12, 8, .20);
}

.bg-sand-100 { background-color: #F4F0EC; }
.bg-sand-200 { background-color: #E9E2DB; }
html.dark .bg-sand-100 { background-color: #1E1E1E; }
html.dark .bg-sand-200 { background-color: #2A2A2A; }

/* ── Loading placeholder ─────────────────────────────────────────────────── */
.skeleton {
  position: relative;
  overflow: hidden;
  background: #E9E2DB;
  border-radius: .5rem;
}

html.dark .skeleton {
  background: #2A2A2A;
}

.skeleton::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background-image: linear-gradient(90deg, transparent, rgba(255, 255, 255, .35), transparent);
  animation: shimmer 1.4s infinite;
}

@keyframes shimmer {
  100% { transform: translateX(100%); }
}

/* ── Entry motion ────────────────────────────────────────────────────────── */
@keyframes rise {
  from { opacity: 0; transform: translateY(9px); }
  to   { opacity: 1; transform: none; }
}

.stagger > * { animation: rise .38s var(--ease) both; }
.stagger > *:nth-child(1) { animation-delay: .02s; }
.stagger > *:nth-child(2) { animation-delay: .06s; }
.stagger > *:nth-child(3) { animation-delay: .10s; }
.stagger > *:nth-child(4) { animation-delay: .14s; }
.stagger > *:nth-child(5) { animation-delay: .18s; }
.stagger > *:nth-child(6) { animation-delay: .22s; }

main > * { animation: rise .4s var(--ease) both; }

.tap {
  transition: transform .18s var(--ease);
}

.tap:active {
  transform: scale(.98);
}

/* ── Module reading content ──────────────────────────────────────────────────
   Admin-authored HTML pulled from the database. Previously written with @apply
   in resources/css/app.css, which meant it only had any effect once Tailwind
   had been compiled — so on the live CDN fallback every course module rendered
   as unstyled running text. Plain CSS here, so it always applies. */
.prose-orangelo p          { margin-bottom: .75rem; line-height: 1.625; }
.prose-orangelo ul,
.prose-orangelo ol         { padding-left: 1.25rem; margin-bottom: .75rem; }
.prose-orangelo ul         { list-style: disc; }
.prose-orangelo ol         { list-style: decimal; }
.prose-orangelo li + li    { margin-top: .25rem; }
.prose-orangelo h2 {
  font-family: 'Fraunces', ui-serif, Georgia, serif;
  font-size: 1.125rem;
  font-weight: 600;
  margin: 1.25rem 0 .5rem;
}
.prose-orangelo h3         { font-weight: 600; margin: 1rem 0 .375rem; }
.prose-orangelo strong     { font-weight: 600; }
.prose-orangelo a          { color: var(--brand); text-decoration: underline; }
.prose-orangelo img        { border-radius: .75rem; margin: .75rem 0; width: 100%; }

/* ── Safe-area helpers ───────────────────────────────────────────────────── */
.pt-safe { padding-top: env(safe-area-inset-top); }
.pb-safe { padding-bottom: env(safe-area-inset-bottom); }

/* ── App chrome ──────────────────────────────────────────────────────────── */
.appbar {
  background: var(--glass-bg);
  backdrop-filter: saturate(1.5) blur(20px);
  -webkit-backdrop-filter: saturate(1.5) blur(20px);
  border-bottom: 1px solid var(--glass-border);
}

.navbar {
  background: var(--glass-bg);
  backdrop-filter: saturate(1.6) blur(20px);
  -webkit-backdrop-filter: saturate(1.6) blur(20px);
  border-top: 1px solid var(--glass-border);
}

.nav-dot {
  position: absolute;
  top: -1px;
  left: 50%;
  transform: translateX(-50%);
  width: 20px;
  height: 3px;
  border-radius: 99px;
  background: linear-gradient(90deg, #FF8A33, #E85F00);
  box-shadow: 0 0 12px 1px rgba(255, 107, 0, .65);
}

/* Drawer rows — replaces the inline onmouseover handlers, which never fired
   on touch devices and would break under a Content-Security-Policy. */
.drawer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-radius: .75rem;
  padding: .625rem 1rem;
  transition: background .15s var(--ease), color .15s var(--ease);
}

.drawer-row:hover,
.drawer-row:focus-visible {
  background: var(--glass-hover);
}

.drawer-row:active {
  background: var(--glass-hover);
}

/* Pinned promotional row at the top of the drawer. */
.drawer-row--accent {
  color: var(--brand);
  font-weight: 600;
  background: rgba(255, 107, 0, .08);
}

.drawer-row--accent:hover,
.drawer-row--accent:focus-visible {
  background: rgba(255, 107, 0, .14);
}

/* ── Admin navigation ─────────────────────────────────────────────────────
   Three things were wrong with this bar and all three made it hard to use:

   1. It was painted with --glass-bg, which is 55% white in light mode and 4%
      white in dark. That only reads as a solid bar while backdrop-filter is
      working; where it is unsupported or switched off (older Firefox, some
      Android webviews, "reduce transparency"), page text showed straight
      THROUGH the nav. It is an opaque surface now, and the blur is decoration.

   2. It scrolled away with the page, so on a long orders or products list the
      only way back to the nav was scrolling to the top. It is sticky now,
      parked under the app header.

   3. The quick-link strip was a flex item with the default min-width:auto, so
      its overflow-x never engaged — instead the strip refused to shrink and
      shoved the search and Exit buttons off the right edge. Fixed by giving
      the scroller min-width:0, which is what actually lets it scroll.
   ------------------------------------------------------------------------ */

/* Full-bleed sticky ground. Without this, page content scrolls through the
   16px gutters either side of the rounded bar. */
.adminbar-wrap {
  position: sticky;
  top: calc(3.5rem + var(--safe-top, 0px));   /* the app header is h-14 + notch */
  z-index: 20;                                /* under the header (30), over content */
  margin: -0.25rem -1rem 1.25rem;
  padding: .25rem 1rem .5rem;
  background: var(--page-bg);
}

.adminbar {
  background: var(--surface-primary);
  border: 1px solid var(--glass-border);
  border-radius: .875rem;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 4px 16px rgba(0, 0, 0, .05);
}

html.dark .adminbar {
  box-shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 4px 16px rgba(0, 0, 0, .3);
}

/* The scrolling strip of frequent links. */
.admin-scroll-wrap {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;            /* the whole fix: lets the scroller shrink */
}

.admin-scroll {
  display: flex;
  align-items: center;
  gap: .25rem;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none;           /* Firefox */
  -ms-overflow-style: none;        /* old Edge */
}

.admin-scroll::-webkit-scrollbar {
  display: none;
}

/* The phone row sits on the page ground, not on the card, so its fade has to
   blend into a different colour. */
.admin-scroll-wrap--onpage::after {
  background: linear-gradient(to right, transparent, var(--page-bg));
}

/* Tells you there is more to the right, without a scrollbar sitting in the bar. */
.admin-scroll-wrap::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 28px;
  pointer-events: none;
  background: linear-gradient(to right, transparent, var(--surface-primary));
}

/* NOTE: theme.css is loaded AFTER the compiled Tailwind build, so a `display`
   declared here beats utilities like `hidden` / `sm:block` at equal
   specificity. Put responsive visibility on a WRAPPER element, never directly
   on an .admin-quick link. */
.admin-quick {
  display: inline-flex;
  align-items: center;
  min-height: 40px;                /* was ~30px — too small to hit on a phone */
  border-radius: 999px;
  padding: .375rem .875rem;
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
  scroll-snap-align: start;
  color: var(--text-secondary);
  transition: background .15s var(--ease), color .15s var(--ease);
}

.admin-quick:hover {
  background: var(--glass-hover);
  color: var(--text-primary);
}

.admin-quick:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

.admin-quick[aria-current="page"] {
  background: var(--brand);
  color: #fff;
}

/* Command palette */
.palette-row {
  display: flex;
  align-items: center;
  gap: .75rem;
  width: 100%;
  text-align: left;
  border-radius: .625rem;
  padding: .5rem .75rem;
  font-size: 14px;
  transition: background .12s var(--ease);
}

.palette-row:hover,
.palette-row.is-cursor {
  background: rgba(255, 107, 0, .1);
  color: var(--brand);
}

.palette-row[aria-current="page"] {
  font-weight: 600;
  color: var(--brand);
}

/* ── Motion preference ───────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition: none !important;
    animation: none !important;
  }
}
