/* ============================================================
   Learner App v2 — shared chrome (topbar / bottom-tab nav / footer)
   Loaded by templates/learner_base.html ONLY (never base.html).
   Consumes static/tokens.css design tokens; hardcodes no brand hex
   except the decorative smoke-page samples.
   ============================================================ */

/* --- Account depth is APIIS-blue-led in the authenticated app chrome ---
   tokens.css now leads the account depth with azure itself, so this block is
   a same-value pin rather than a divergence. Kept because the learner chrome
   should not silently inherit a future depth retune.

   Rebrand 2026-08-10: --lead moves --ap-blue -> --ap-blue-deep. --lead feeds
   .btn-primary's gradient under white text, and #0082CB is 4.16:1 there — an
   AA failure. #0568A2 is 5.97:1. Do NOT put the brand azure back here. */
html[data-depth="account"]{
  --lead:var(--ap-blue-deep); --lead-2:var(--ap-navy);
  --lead-soft:var(--ap-sky); --focus:var(--ap-blue-deep);
}

.zh{ font-family:"Noto Sans SC",var(--sans); }

/* --- Skip link (first focusable element; mirrors base.html) --- */
.skip-link{
  position:absolute; left:8px; top:-48px; z-index:60;
  background:var(--surface); color:var(--ink); border:1px solid var(--outline-strong);
  border-radius:var(--r-sm); padding:10px 16px; font-weight:600; font-size:14px;
  transition:top .16s ease;
}
.skip-link:focus{ top:8px; }

/* --- Topbar: sticky, flat cream, brand left / nav / actions right --- */
.lx-topbar{
  position:sticky; top:0; z-index:30; background:#F6F2EC;
  border-bottom:1px solid var(--outline);
}
.lx-topbar .lx-row{
  max-width:1180px; margin:0 auto; padding:0 28px; height:68px;
  display:flex; align-items:center; gap:22px;
}
.lx-brand{ display:inline-flex; align-items:center; gap:11px; }
.lx-brand .coin{ width:34px; height:34px; }
.lx-brand .lx-name{ font-family:var(--serif); font-weight:600; font-size:20px; letter-spacing:-0.025em; color:var(--ink); }
.lx-brand .lx-name .u{ color:var(--su-bronze); }
.lx-brand .lx-by{
  font-size:9.5px; color:var(--muted);
  border-left:1px solid var(--outline-strong); padding-left:9px; line-height:1.25;
}

/* Desktop primary nav */
.lx-nav{ display:flex; align-items:center; gap:4px; margin-left:14px; }
.lx-nav a{
  font-size:14px; font-weight:500; color:var(--muted);
  padding:8px 13px; border-radius:var(--r-pill); white-space:nowrap;
}
.lx-nav a[aria-current="page"]{ color:var(--ap-blue-deep); background:var(--ap-sky); font-weight:600; }
.lx-nav a:hover:not([aria-current="page"]){ color:var(--ink); }

.lx-right{ margin-left:auto; display:flex; align-items:center; gap:14px; }
/* 44px minimum touch targets (DESIGN.md); the visible disc stays 38px via an
   inner element, but the hit area is the full 44px button. */
.lx-iconbtn{
  width:44px; height:44px; border-radius:50%; border:0; background:transparent;
  display:flex; align-items:center; justify-content:center; color:var(--muted); cursor:pointer;
}
.lx-iconbtn svg{ width:18px; height:18px; }
.lx-iconbtn:hover{ color:var(--ink); }
/* Announcements epic: live bell. The badge uses the bronze accent (DESIGN.md
   tertiary — milestone/emphasis moments), not danger red: an announcement is
   news, not an error. */
.lx-bell{ position:relative; }
.lx-badge{
  position:absolute; top:4px; right:2px; min-width:16px; height:16px; padding:0 4px;
  border-radius:var(--r-pill, 9999px); background:var(--su-bronze); color:#fff;
  font-size:10px; font-weight:700; line-height:16px; text-align:center;
}
.lx-avatar{
  width:44px; height:44px; border-radius:50%;
  /* R28 (2026-08-10): a gradient carrying white text may not start or end at
     --ap-blue. These are serif initials at 15px, so white on the near end was
     4.15:1. Azure-deep -> navy is 5.97 at the near end, 11.76 at the far. */
  background:linear-gradient(135deg,var(--ap-blue-deep),var(--ap-navy)); color:#fff;
  display:flex; align-items:center; justify-content:center;
  font-family:var(--serif); font-weight:600; font-size:15px; flex:none;
}

/* --- Main + footer --- */
.lx-main{ max-width:1080px; margin:0 auto; padding:52px 28px 70px; min-height:50vh; }
.lx-footer{
  border-top:1px solid var(--outline); background:var(--surface-2);
  color:var(--muted); font-size:13px;
}
.lx-footer .lx-frow{ max-width:1180px; margin:0 auto; padding:22px 28px; display:flex; gap:14px; flex-wrap:wrap; align-items:center; }
.lx-footer a{ color:var(--muted); text-decoration:underline; text-underline-offset:2px; }
.lx-footer a:hover{ color:var(--ink); }

/* --- Bottom-tab nav: mobile only (<=640px) --- */
.lx-bottomnav{ display:none; }

@media (max-width:640px){
  /* Topbar sheds the primary nav; keeps brand + avatar only. */
  .lx-topbar .lx-row{ padding:0 16px; height:60px; gap:12px; }
  .lx-nav{ display:none; }
  .lx-brand .lx-by{ display:none; }
  .lx-main{ padding:28px 16px calc(64px + env(safe-area-inset-bottom,0px)); }

  .lx-bottomnav{
    display:flex; position:fixed; left:0; right:0; bottom:0; z-index:40;
    background:#F6F2EC; border-top:1px solid var(--outline);
    padding-bottom:env(safe-area-inset-bottom,0px);
  }
  .lx-bottomnav a{
    flex:1; min-height:56px; display:flex; flex-direction:column;
    align-items:center; justify-content:center; gap:3px;
    color:var(--muted); font-size:11px; font-weight:600;
  }
  .lx-bottomnav a svg{ width:22px; height:22px; }
  .lx-bottomnav a[aria-current="page"]{ color:var(--ap-blue-deep); }
  .lx-footer{ margin-bottom:64px; }
}

/* --- Smoke-page sample block (dev canary only) --- */
.lx-smoke-grid{ display:grid; gap:16px; grid-template-columns:repeat(auto-fill,minmax(220px,1fr)); margin-top:22px; }

/* ===================================================================
   Lane B §4 — the auth brand panel, behind BRAND_MARK_V2.
   `logo-integration.md` §4. Scoped to `.auth-brand-v2` on <body>, which
   only the four auth templates set and only when the flag is on, so the
   flag-off render of these pages is byte-identical to today.

   Lives here rather than in each template's <style> because login,
   register, forgot_password and reset_password carry BYTE-IDENTICAL
   copies of the .aside/.abrand rules — four copies of this block would
   be four places to drift.

   Every colour below is measured on --ap-navy #043B5C:
     white           11.76    quote
     on-dark-muted    8.04    footer line
     ap-gold          8.16    seed label + rule
     apiis-lock-green 4.91    the IIS half of the footer lockup (AA pass)
   --su-bronze is 1.90 on navy, which is why the seed moves to gold
   rather than staying bronze: the two-family rule sends warm emphasis
   to gold on any dark ground (Lane C --lp-on-dark-warm).
   =================================================================== */

/* The panel ground. Navy base with an azure/bronze atmosphere at the
   same weights the cream version used. No stop is --ap-blue itself, so
   R28 (no white-text gradient starts or ends at the brand azure) holds. */
.auth-brand-v2 .aside{
  background:
    radial-gradient(820px 440px at 112% -8%, color-mix(in srgb,var(--ap-blue) 20%,transparent), transparent 70%),
    radial-gradient(620px 420px at -10% 108%, color-mix(in srgb,var(--su-bronze-2) 14%,transparent), transparent 66%),
    linear-gradient(168deg, color-mix(in srgb,var(--ap-navy) 92%,var(--ap-sky)), var(--ap-navy));
}
/* The ruled overlay was `multiply` on cream — invisible on navy. Flip to
   a light hairline at normal blend. */
.auth-brand-v2 .aside::after{
  background-image:linear-gradient(to bottom, transparent calc(100% - 1px), color-mix(in srgb,#fff 12%,transparent) 100%);
  mix-blend-mode:normal; opacity:.6;
}

.auth-wordmark{ display:block; width:216px; height:auto; }
.auth-brand-v2 .abrand{ gap:0; }

.auth-brand-v2 .aside .seed .dash{ background:var(--ap-gold); }
.auth-brand-v2 .aside .seed span{ color:var(--ap-gold); }
.auth-brand-v2 .aside .quote{ color:var(--color-on-dark,#fff); }
.auth-brand-v2 .aside-foot{ border-top-color:color-mix(in srgb,var(--ap-gold) 22%,transparent); }
.auth-brand-v2 .aside-foot .ft{ color:var(--color-on-dark-muted,#C7D8E3); }

/* §4 a11y: the focus ring inside the navy panel is the on-dark sky glow.
   --focus is azure-deep, which is 1.97 on navy and would be a ring you
   cannot see on the one focusable element the panel has. Sky is 10.55. */
.auth-brand-v2 .aside a:focus-visible{
  outline:2px solid var(--ap-sky); outline-offset:3px;
  box-shadow:0 0 0 5px color-mix(in srgb,var(--ap-sky) 28%,transparent);
}

/* Mobile: the aside is display:none below 860px, so the mark reappears
   in the form pane on the warm surface — full-colour, not knockout. */
.auth-mobile-wordmark{ display:block; width:190px; height:auto; }

/* --- Lane B §3 — the wordmark into the learner v2 chrome, behind
   BRAND_MARK_V2. Warm surface, so the FULL-COLOUR mark.

   The nav already sheds at 640px (above), which is the spec's "collapses the
   nav instead" — so the only thing §3 adds below that is the mark stepping to
   the 132px floor at 420px. It never goes under: below 132px the APIIS
   endorsement line stops resolving and this is a wordmark-only system. --- */
.lx-wordmark{ display:block; width:172px; height:auto; }
@media (max-width:420px){
  .lx-wordmark{ width:132px; }
}
@media (max-width:360px){
  /* 320px budget: padding + brand + row gap + three 44px targets in
     .lx-right must fit. The 44px hit areas are non-negotiable (DESIGN.md)
     and the wordmark holds its 132px floor (see above), so only padding
     and gaps give way: 24 + 132 + 8 + (3*44 + 2*4) = 304px.
     Was 5px of horizontal scroll at exactly 320 (QA 2026-08-22). */
  .lx-topbar .lx-row{ padding:0 12px; gap:8px; }
  .lx-right{ gap:4px; }
  .lx-brand{ gap:8px; }
  .lx-brand .coin{ width:30px; height:30px; }
  .lx-brand .lx-name{ font-size:18px; }
}

/* ═══════════ Touch-target pass, auth screens — coarse pointers only ═══════════
   Measured at 390px, coarse pointer: `.mode a` 35px (the Sign in / Create
   account tabs) and `.field-actions a` 26px ("Resend verification", "Forgot
   password?"). Lives here rather than in each template's <style> for the same
   reason §4's panel block does — all four auth templates carry byte-identical
   copies of these rules.

   NOT swept, deliberately: `.help a` ("Need help? Contact us"), `.form-foot a`
   ("New to SeminaryU? Create a free account") and `.legal a`. Each sits inside
   a sentence, which WCAG 2.5.8 exempts precisely because growing it to 44px
   forces the line box apart and collides with the surrounding copy. They
   measure 14-15px and that is the correct call, not an oversight — recorded so
   the next audit does not "fix" them.
   ══════════════════════════════════════════════════════════════════════════ */
@media (any-pointer: coarse){
  .mode a,
  .field-actions a{
    min-height:var(--touch-min); display:inline-flex; align-items:center;
  }
  .field-actions{ gap:var(--touch-gap); }
}

/* ===================================================================
   Course cover art (catalogue imagery Block 2, design A1–A3).
   One box, four sizes. The gradient + texture + glyph always sit under
   the <img>, so a slow or failed load shows the fallback art. Any text on
   the art sits on the navy plate rgba(4,59,92,.72) (DESIGN.md plate rule).
   The gradient values are the single copy for the learner app: the admin
   picker in admin-studio.css mirrors them (keep in sync with
   db.COURSE_COVER_THEMES).
   =================================================================== */
/* Every rule is scoped to .cover.fb, the box the cover() macro emits, so the
   flag-off .enroll .cover sidebar strip and the .thumb / .lthumb boxes are
   untouched when CATALOG_COVER_IMAGES is off. */
/* No background here on purpose: the gradient comes from the .t-* / .cover-theme-*
   class on the same element, which this (0,2,0) rule would otherwise outrank. */
.cover.fb{ position:relative; aspect-ratio:16/9; overflow:hidden; }
.cover.fb::before{ content:""; position:absolute; inset:0; background:repeating-linear-gradient(135deg,rgba(255,255,255,.07) 0 1px,transparent 1px 9px); pointer-events:none; }
.cover.fb .wmk{ position:absolute; right:-10px; bottom:-14px; width:46%; height:auto; aspect-ratio:1; color:#fff; opacity:.16; pointer-events:none; }
.cover.fb img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; display:block; transition:transform .22s cubic-bezier(.16,1,.3,1); }
.cover.fb .plate{ position:absolute; left:12px; bottom:12px; z-index:2; display:inline-flex; align-items:center; gap:6px; font-family:var(--mono); font-size:10px; letter-spacing:.08em; text-transform:uppercase; color:#fff; background:rgba(4,59,92,.72); padding:5px 10px; border-radius:var(--r-pill); }
/* Category tints (six, cycled by a stable hash for admin-added categories). */
.t-blue{ background:linear-gradient(135deg,#0568A2,#043B5C); } .t-bronze{ background:linear-gradient(135deg,#8B5421,#A66E36); } .t-sage{ background:linear-gradient(135deg,#3E6B3A,#5C8A57); }
.t-navy{ background:linear-gradient(135deg,#063450,#0568A2); } .t-clay{ background:linear-gradient(135deg,#9A4B2E,#B86A45); } .t-plum{ background:linear-gradient(135deg,#5B3A52,#7C5270); }
/* Admin-chosen cover themes (courses.cover_theme). */
.cover-theme-dawn{ background:linear-gradient(135deg,#F6C39A,#E8809B); } .cover-theme-sage{ background:linear-gradient(135deg,#A7C7A0,#5E9E7E); } .cover-theme-bronze{ background:linear-gradient(135deg,#C79A5B,#8B5421); }
.cover-theme-slate{ background:linear-gradient(135deg,#7FA8C9,#0568A2); } .cover-theme-plum{ background:linear-gradient(135deg,#B79AD1,#6E4A8E); } .cover-theme-sky{ background:linear-gradient(135deg,#9AD0F6,#0082CB); }
/* Sizes. */
.cover-row{ width:112px; border-radius:var(--r-md); flex:none; }
.cover-strip{ width:72px; border-radius:var(--r-sm); flex:none; }
.cover.fb.cover-hero{ position:absolute; inset:0; aspect-ratio:auto; }
/* Course hero: the cover fills the box; a scrim adds atmosphere only, the
   plates are what pass 4.5:1. The title plate clones onto every wrapped line. */
/* The hero is a grid with the plate in flow: the aspect ratio is the minimum
   height, and a long wrapped title on a phone grows the box instead of being
   clipped at the top. */
.chero{ position:relative; display:grid; width:100%; aspect-ratio:21/9; border-radius:var(--r-xl); overflow:hidden; margin-bottom:22px; background:var(--surface-2); }
.chero .scrim{ position:absolute; inset:0; background:linear-gradient(180deg,rgba(4,59,92,0) 35%,rgba(4,59,92,.62) 100%); pointer-events:none; }
.chero .hplate{ position:relative; z-index:1; grid-area:1 / 1; align-self:end; padding:22px 24px; color:#fff; display:flex; flex-direction:column; gap:8px; align-items:flex-start; }
.chero .hplate .k{ display:inline-flex; gap:8px; font-family:var(--mono); font-size:10px; letter-spacing:.12em; text-transform:uppercase; background:rgba(4,59,92,.72); padding:5px 10px; border-radius:var(--r-pill); }
/* The plate sits on an inline span (not the blockified h1) so each wrapped
   line carries its own plate via box-decoration-break: clone. */
.chero .hplate h1{ font-family:var(--serif); font-weight:600; font-size:clamp(22px,3vw,34px); letter-spacing:-0.02em; line-height:1.45; margin:0; color:#fff; }
.chero .hplate h1 span{ background:rgba(4,59,92,.72); padding:6px 14px; border-radius:var(--r-md); box-decoration-break:clone; -webkit-box-decoration-break:clone; }
.zh .chero .hplate h1, .chero .hplate h1.zh{ font-family:"Noto Sans SC",var(--sans); letter-spacing:0; }
@media (max-width:640px){
  .chero{ aspect-ratio:16/9; border-radius:var(--r-lg); }
  .chero .hplate{ padding:14px 16px; }
  .cover-row{ width:100%; aspect-ratio:21/9; }
}
