/* Dashboard home: desktop corrections + the phone dashboard.
 *
 * app/Views/dashboard/index.php has always linked this file, but the file never
 * existed, so the request 404'd on live and staging. It is the right home for
 * these rules because it loads AFTER the purged CSS bundles: library.css and
 * dashboard-page.css are compiled into public/css/build/*.purged.css, so edits
 * there do not reach production until somebody regenerates the bundles.
 * Declarations here win by load order instead.
 *
 * Below md the four desktop cards are replaced wholesale by
 * app/Views/dashboard/phone_dashboard.php. They could not be restyled into the
 * phone designs - the fundraiser carries a full meter with a needle, callout and
 * tick scale, and the hero art is landscape - so the phone gets purpose-built
 * markup and the desktop cards are hidden. Three layouts share that markup and
 * are selected by data-phone-layout on <html>:
 *
 *   rows   - iOS inset grouped lists, every destination a uniform row
 *   tiles  - iOS widget stack, the photography survives as 2-up widgets
 *   stats  - Health/Fitness summary, the numbers lead
 */

/* ==========================================================================
   View toggle: below the library grid, at every width
   --------------------------------------------------------------------------
   The toggle used to sit in its own full-width row between the dashboard cards
   and the library grid, where .filters-container (library.css) renders it as a
   padded white panel with a shadow. That cost a whole row of vertical space for
   one small control, on desktop as much as on mobile. The markup now sits under
   #gridViewContainer, where the app view has always put it, so all that is left
   is to drop the panel chrome.
   ========================================================================== */

body.dashboard-page .filters-container.dash-view-toggle-bottom {
  padding: 0.25rem 0 0;
  background-color: transparent !important;
  border-radius: 0;
  box-shadow: none;
}

/* theme.css gives every panel inside a sidebar layout a surface background and a
   drop shadow via html[data-theme="dark"] body.has-v1-sidebar .content-wrapper
   .filters-container, which scores (0,4,2) with !important on both the
   background shorthand and the shadow. This scores (0,5,2) to clear it. */
html[data-theme="dark"] body.dashboard-page .content-wrapper .filters-container.dash-view-toggle-bottom {
  background: transparent !important;
  background-color: transparent !important;
  box-shadow: none !important;
}

/* ==========================================================================
   Phone layout picker
   --------------------------------------------------------------------------
   An iOS segmented control, below the grid with the view toggle. The markup is
   d-md-none, so this only ever renders on a phone.
   ========================================================================== */

.phone-layout-picker {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.2rem 0 0;
}

.phone-layout-picker__label {
  color: var(--thf-text-2);
  font-size: 0.8125rem;
  font-weight: 500;
}

.phone-layout-picker__segments {
  display: flex;
  padding: 2px;
  border-radius: 9px;
  background: var(--thf-surface-3);
}

.phone-layout-picker__btn {
  padding: 0.3rem 0.72rem;
  border: 0;
  border-radius: 7px;
  background: none;
  color: var(--thf-text-2);
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.2;
}

.phone-layout-picker__btn.is-active {
  background: var(--thf-surface);
  color: var(--thf-heading);
  box-shadow: 0 1px 2px var(--thf-shadow);
  font-weight: 600;
}

/* ==========================================================================
   Desktop: all four dashboard cards share one width
   ========================================================================== */

@media (min-width: 768px) {
  /* The phone-only blocks deliberately do NOT use Bootstrap's .d-md-none.
     mobile-header.css forces body.dashboard-page .d-md-none to
     display:flex !important below 1100px so the navbar hamburger survives, and
     that rule hits every .d-md-none element on the page - it would have shown
     the whole phone dashboard on tablets, on top of the desktop cards. Hiding
     them from md up here keeps that hack out of it. */
  body.dashboard-page .phone-dash,
  body.dashboard-page .phone-hdr,
  body.dashboard-page .phone-only {
    display: none !important;
  }
}

/* The installed dashboard already reserves its fixed header (including the
   safe area) in shared-head-chrome.css on .wrapper. The generic mobile body
   padding and iOS html padding must not reserve it a second and third time.
   Keep both early-html and late-body detection paths for login/PWA navigation. */
@media (max-width: 1100px) {
  html.is-pwa-standalone:has(body.dashboard-page),
  html:has(body.dashboard-page.is-pwa-standalone) {
    padding-top: 0 !important;
  }

  body.dashboard-page.is-pwa-standalone,
  html.is-pwa-standalone body.dashboard-page {
    padding-top: 0 !important;
  }
}

/* ==========================================================================
   Phone dashboard: shared primitives
   ========================================================================== */

@media (max-width: 767.98px) {

  body.dashboard-page {
    /* Real San Francisco on iOS, and the platform UI font everywhere else. This
       is most of what makes the screen read as native rather than as a web page
       with rounded corners. */
    --ios-sf: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  }

  /* The desktop cards are replaced, not restyled (welcome card, photo wall,
     fundraiser: .dh-desk-only, see DASHBOARD TOP CARDS). */
  body.dashboard-page .dh-desk-only {
    display: none !important;
  }

  /* iOS grouped lists put the page BEHIND the cards, so the canvas has to be
     the darker of the two surfaces. Light mode only: in dark mode --thf-bg is
     already darker than --thf-surface, which is the relationship we want.
     !important is required because the bundles set
     .content-wrapper { background-color: var(--body-bg) !important }, which
     resolves to white here and would otherwise flatten the cards. */
  html:not([data-theme='dark']) body.dashboard-page .content-wrapper {
    background-color: var(--thf-surface-2) !important;
  }

  /* .wrapper's 85px reservation is 8px taller than the navbar, so the body
     showed as a thin white line between the dark header and the grey canvas.
     Carrying the canvas colour onto the body removes any chance of a white
     band, whatever the navbar's exact height turns out to be. */
  html:not([data-theme='dark']) body.dashboard-page {
    background-color: var(--thf-surface-2) !important;
  }

  /* Reclaim the dead band above the first card. mobile-header.css makes the
     navbar position:fixed, then reserves room for it TWICE: body gets
     padding-top:45px and .wrapper gets padding-top:85px ("70px navbar + 15px
     breathing room"). A fixed element is out of flow, so body padding reserves
     nothing for it - those 45px were pure empty page, and content started at
     45+85+16 = 146px under a navbar that is 77px tall (1rem padding either side
     of a logo capped at max-height:45px). Dropping the body padding leaves the
     wrapper's 85px doing the job it was written for.

     Browser only. The installed dashboard has its own reset above; its
     wrapper reservation includes the safe area. */
  /* The flag now lands on <html> before the first paint (head.php) and on
     <body> at DOMContentLoaded, so require BOTH to be absent; :where keeps the
     specificity identical to the old body-only form. */
  :where(html:not(.is-pwa-standalone)) body.dashboard-page:not(.is-pwa-standalone) {
    padding-top: 0 !important;
  }

  /* .content-wrapper carries p-4 (24px) and every .container-fluid inside it
     adds 15px, so the cards started 39px in from each edge and measured only
     315px on a 393px phone - narrow enough that "Welcome back, Daniel" and its
     subtitle both truncated. Dropping the outer 24px leaves the iOS-standard
     ~16px inset. The container's own 15px has to stay: Bootstrap's .row uses
     -15px side margins and would otherwise overflow the viewport. */
  body.dashboard-page .content-wrapper.p-4 {
    padding-right: 0 !important;
    padding-left: 0 !important;
  }

  .phone-dash {
    display: flex;
    flex-direction: column;
    font-family: var(--ios-sf);
  }

  /* --- Bible plan sliver ------------------------------------------------- */

  /* The full-width banner is the desktop presentation of the same plan. On a
     phone it would cost a two-line card above the fold for information that
     fits on one line, so the sliver replaces it here. */
  body.dashboard-page .biay-dash-banner {
    display: none !important;
  }

  .phone-sliver {
    position: relative;
    display: flex;
    overflow: hidden;
    align-items: center;
    gap: 0.55rem;
    margin: 0 0 0.85rem;
    padding: 0.5rem 0.85rem 0.55rem;
    /* The gold edge is what marks this as the Bible plan. Literal rather than
       --thf-accent-2, which is #FACE68 and nearly invisible on a light surface;
       #C9A227 is the gold the desktop banner already uses for this same
       feature, and it holds up on both themes. */
    border-left: 3px solid #C9A227;
    border-radius: 10px;
    background: var(--thf-surface);
    box-shadow: 0 1px 2px var(--thf-shadow);
    color: var(--thf-text);
    text-decoration: none !important;
  }

  /* .phone-sliver sets display:flex, which would defeat the hidden attribute
     the markup ships with and flash an empty sliver before the plan state
     arrives - or permanently, for people with no plan. */
  .phone-sliver[hidden] {
    display: none;
  }

  .phone-sliver__icon {
    flex: 0 0 auto;
    color: #C9A227;
    font-size: 0.9rem;
  }

  .phone-sliver__text {
    overflow: hidden;
    min-width: 0;
    flex: 1 1 auto;
    color: var(--thf-text-2);
    font-size: 0.8125rem;
    font-variant-numeric: tabular-nums;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .phone-sliver__text strong {
    color: var(--thf-heading);
    font-weight: 700;
  }

  .phone-sliver__badge {
    display: flex;
    min-width: 18px;
    height: 18px;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    padding: 0 5px;
    border-radius: 999px;
    /* Self-contained alert band, correct in both themes. A shade darker than
       the desktop banner's #d64545, which scores only 4.38:1 against white and
       misses AA at this size. */
    background: #c53030;
    color: #fff;
    font-size: 0.68rem;
    font-weight: 700;
    line-height: 1;
  }

  .phone-sliver__badge[hidden] {
    display: none;
  }

  .phone-sliver__go {
    display: flex;
    width: 22px;
    height: 22px;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--thf-accent);
    color: var(--encounter-ink, #17202b);
    font-size: 0.5rem;
  }

  /* Progress reads as a hairline along the bottom edge rather than a track,
     which is what keeps this a sliver. */
  .phone-sliver__bar {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    height: 2px;
    background: var(--thf-surface-3);
  }

  .phone-sliver__bar > span {
    display: block;
    height: 100%;
    background: #C9A227;
  }

  .phone-sliver.is-done {
    border-left-color: #4c9a50;
  }

  .phone-sliver.is-done .phone-sliver__icon {
    color: #4c9a50;
  }

  .phone-sliver.is-done .phone-sliver__bar > span {
    background: #4c9a50;
  }

  /* --- group headers ----------------------------------------------------- */

  .phone-hdr {
    padding: 0.85rem 0.2rem 0.4rem;
    /* --thf-text-muted is only 3.5:1 on --thf-surface-2, which fails AA at this
       size. --thf-text-2 clears it. */
    color: var(--thf-text-2);
    font-family: var(--ios-sf);
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.045em;
    text-transform: uppercase;
  }

  /* --- inset grouped card ------------------------------------------------ */

  .phone-group {
    overflow: hidden;
    border-radius: 12px;
    background: var(--thf-surface);
    box-shadow: 0 1px 2px var(--thf-shadow);
  }

  .phone-group + .phone-group {
    margin-top: 0.85rem;
  }

  /* --- row -------------------------------------------------------------- */

  .phone-row {
    position: relative;
    display: flex;
    min-height: 56px;
    align-items: center;
    gap: 0.7rem;
    padding: 0.6rem 2.1rem 0.6rem 0.85rem;
    color: var(--thf-text);
    text-decoration: none !important;
  }

  /* Hairline between rows, inset past the artwork the way Settings.app does it
     rather than running the full card width. */
  .phone-row + .phone-row::before {
    position: absolute;
    top: 0;
    right: 0;
    left: 3.9rem;
    height: 1px;
    background: var(--thf-border);
    content: '';
  }

  .phone-row__art {
    display: flex;
    overflow: hidden;
    width: 38px;
    height: 38px;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    border-radius: 9px;
    background: var(--thf-surface-3);
    color: var(--thf-text-2);
  }

  .phone-row__art img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .phone-row__art--avatar {
    border-radius: 50%;
  }

  .phone-row__art--lesson {
    /* The resume row has no artwork of its own - $lastLesson carries only a
       title and a URL - so it gets the brand bronze and a glyph. */
    background: var(--thf-accent);
    color: var(--encounter-ink, #17202b);
    font-size: 0.95rem;
  }

  .phone-row__text {
    display: flex;
    min-width: 0;
    flex: 1 1 auto;
    flex-direction: column;
  }

  .phone-row__eyebrow {
    color: var(--thf-link);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  .phone-row__title {
    overflow: hidden;
    color: var(--thf-heading);
    font-size: 0.95rem;
    font-weight: 600;
    letter-spacing: -0.012em;
    line-height: 1.3;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .phone-row__sub {
    overflow: hidden;
    color: var(--thf-text-2);
    font-size: 0.8125rem;
    line-height: 1.3;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .phone-row__bar {
    display: block;
    overflow: hidden;
    max-width: 11rem;
    height: 4px;
    margin: 0.4rem 0 0.15rem;
    border-radius: 2px;
    background: var(--thf-surface-3);
  }

  .phone-row__bar > span {
    display: block;
    height: 100%;
    border-radius: 2px;
    background: var(--thf-accent);
  }

  .phone-row__chevron {
    position: absolute;
    top: 50%;
    right: 1rem;
    width: 0.46rem;
    height: 0.46rem;
    margin-top: -0.27rem;
    border-top: 2px solid var(--thf-text-muted);
    border-right: 2px solid var(--thf-text-muted);
    border-radius: 1px;
    transform: rotate(45deg);
  }

  .phone-pill {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 0.22rem;
    padding: 0.24rem 0.6rem;
    border-radius: 999px;
    /* A self-contained dark band, correct in both themes, matching the points
       pill on the desktop card. */
    background: #343a40;
    color: #fff;
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
  }

  .phone-pill i {
    color: var(--thf-accent-2, #C9A227);
    font-size: 0.7rem;
  }

  .phone-play {
    display: flex;
    width: 26px;
    height: 26px;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--thf-accent);
    color: var(--encounter-ink, #17202b);
    font-size: 0.6rem;
  }

  /* --- stat pair --------------------------------------------------------- */

  .phone-stats {
    display: flex;
    gap: 0.7rem;
  }

  .phone-stat {
    display: flex;
    min-width: 0;
    flex: 1 1 0;
    flex-direction: column;
    padding: 0.7rem 0.8rem 0.75rem;
    border-radius: 12px;
    background: var(--thf-surface);
    box-shadow: 0 1px 2px var(--thf-shadow);
    color: var(--thf-text);
    text-decoration: none !important;
  }

  .phone-stat__label {
    overflow: hidden;
    color: var(--thf-text-2);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-overflow: ellipsis;
    text-transform: uppercase;
    white-space: nowrap;
  }

  .phone-stat__value {
    margin: 0.15rem 0 0;
    color: var(--thf-heading);
    font-size: 1.65rem;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    letter-spacing: -0.028em;
    line-height: 1.1;
  }

  .phone-stat__sub {
    color: var(--thf-text-2);
    font-size: 0.75rem;
  }

  /* --- fundraiser ------------------------------------------------------- */

  .phone-fund {
    margin-top: 0.85rem;
    padding: 0.85rem 0.9rem 0.9rem;
    /* Same parchment band, border and ink as .encounter-fundraiser-card in
       encounter-campaign.css, so the phone card is the same object as the
       desktop one. The dark counterpart is below. */
    border: 1px solid rgba(209, 170, 58, 0.42);
    border-radius: 16px;
    background: linear-gradient(145deg, #fffdf9 0%, #f8f1e5 57%, #efe1cd 100%);
    color: var(--encounter-ink, #17202b);
  }

  .phone-fund__top {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
  }

  .phone-fund__eyebrow {
    color: var(--encounter-red-dark, #9f2630);
    font-size: 0.6875rem;
    font-weight: 800;
    letter-spacing: 0.12em;
    text-transform: uppercase;
  }

  .phone-fund__funded {
    color: #5f6267;
    font-size: 0.6875rem;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }

  .phone-fund__headline {
    margin: 0.3rem 0 0.35rem;
    color: #122a47;
    font-family: 'Playfair Display', Georgia, serif;
    font-size: 1.15rem;
    font-weight: 700;
    line-height: 1.18;
  }

  .phone-fund__amount {
    display: flex;
    align-items: baseline;
    gap: 0.35rem;
    margin: 0.15rem 0 0.5rem;
  }

  .phone-fund__amount strong {
    color: #122a47;
    font-family: 'Playfair Display', Georgia, serif;
    font-size: 1.65rem;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    line-height: 1;
  }

  .phone-fund__of {
    color: #4a4d52;
    font-size: 0.8125rem;
    font-variant-numeric: tabular-nums;
  }

  .phone-fund__track {
    overflow: hidden;
    height: 5px;
    border-radius: 999px;
    background: rgba(23, 32, 43, 0.14);
  }

  .phone-fund__track > span {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: var(--thf-accent);
  }

  .phone-fund__match {
    margin: 0.5rem 0 0.7rem;
    color: #4a4d52;
    font-size: 0.75rem;
    line-height: 1.35;
  }

  .phone-fund__match strong {
    color: var(--encounter-ink, #17202b);
    font-weight: 700;
  }

  .phone-fund__btn {
    display: block;
    padding: 0.7rem 1rem;
    border-radius: 999px;
    /* Bronze fill with dark ink is the established pattern on this site (the
       photo wall's Open Photo Wall button). White on bronze would be 2.8:1. */
    background: var(--thf-accent);
    color: var(--encounter-ink, #17202b) !important;
    font-size: 0.9rem;
    font-weight: 800;
    text-align: center;
    text-decoration: none !important;
  }

  /* Dark mode for the fundraiser. This card MUST flip with the theme rather
     than stay a light band: theme.css forces every h2, strong and p inside
     .content-wrapper to light ink in dark mode with
     html[data-theme="dark"] body.has-v1-sidebar .content-wrapper h2 (0,3,1)
     plus !important, so a cream card loses its headline, its amount and its
     match figure to light-on-light. The values match
     .encounter-fundraiser-card's own dark treatment in encounter-campaign.css
     so both cards read as the same object. */
  html[data-theme='dark'] .phone-fund {
    border-color: rgba(209, 170, 58, 0.34);
    background: linear-gradient(145deg, #25211f 0%, #201c1a 58%, #2b211e 100%);
    color: #eee7df;
  }

  html[data-theme='dark'] .phone-fund__eyebrow {
    color: #ffd2d5;
  }

  html[data-theme='dark'] .phone-fund__funded,
  html[data-theme='dark'] .phone-fund__of {
    color: #c9c0b7;
  }

  html[data-theme='dark'] .phone-fund__track {
    background: rgba(255, 255, 255, 0.16);
  }

  /* --- what each layout shows ------------------------------------------- */

  /* Everything optional is hidden here and switched back on per layout, so a
     layout can never inherit a stray piece from another. */
  .phone-row__title--welcome,
  .phone-stats,
  .phone-hdr--pickup,
  .phone-hdr--communitystudy,
  .phone-row__sub--pathtiles,
  .phone-row__bar,
  .phone-fund__match--short,
  .phone-fund__match--dated,
  .phone-group--community .phone-row__eyebrow {
    display: none;
  }
}

/* ==========================================================================
   Phone layout: rows - iOS inset grouped lists
   --------------------------------------------------------------------------
   The default, and the fallback when no layout has been chosen. Everything the
   shared block sets up is already what this layout wants, so there is nothing
   to add.
   ========================================================================== */

/* ==========================================================================
   Phone layout: tiles - iOS widget stack
   ========================================================================== */

@media (max-width: 767.98px) {

  /* This layout drops the section headers; the widgets label themselves. */
  html[data-phone-layout='tiles'] .phone-hdr {
    display: none;
  }

  /* The other two layouts get their gap from the LIBRARY header that follows.
     With the headers gone the library artwork butted straight up against the
     resume row, which read as the tiles covering it. */
  html[data-phone-layout='tiles'] .phone-dash {
    margin-bottom: 0.9rem;
  }

  /* The profile row is a greeting on one line here, not a profile entry. */
  html[data-phone-layout='tiles'] .phone-row__sub--profile,
  html[data-phone-layout='tiles'] .phone-row__title--name {
    display: none;
  }

  html[data-phone-layout='tiles'] .phone-row__title--welcome {
    display: block;
  }

  /* "Welcome back, <name>" wants 156px and the row leaves 149px next to the
     avatar, the points pill and the chevron on a 393px phone. A slightly
     smaller greeting plus trimming the chevron gutter to what the chevron
     actually needs buys ~14px, so ordinary first names fit on one line;
     unusually long ones still ellipsize rather than wrap. */
  html[data-phone-layout='tiles'] .phone-group--profile .phone-row {
    padding-right: 1.75rem;
  }

  html[data-phone-layout='tiles'] .phone-row__title--welcome {
    font-size: 0.9rem;
  }

  /* The amount is the headline in this layout, so the sentence goes. */
  html[data-phone-layout='tiles'] .phone-fund__headline {
    display: none;
  }

  html[data-phone-layout='tiles'] .phone-fund__amount strong {
    font-size: 2rem;
  }

  html[data-phone-layout='tiles'] .phone-fund__goal-word {
    display: none;
  }

  html[data-phone-layout='tiles'] .phone-fund__match--long {
    display: none;
  }

  html[data-phone-layout='tiles'] .phone-fund__match--short {
    display: block;
  }

  /* The widgets carry the artwork, so the resume row follows them. Visual order
     only; the DOM keeps the reading order the other two layouts use. */
  html[data-phone-layout='tiles'] .phone-group--community {
    order: 5;
    margin-top: 0.85rem;
  }

  html[data-phone-layout='tiles'] .phone-group--resume {
    order: 6;
  }

  /* --- the two widgets --------------------------------------------------- */

  html[data-phone-layout='tiles'] .phone-group--community {
    display: flex;
    overflow: visible;
    column-gap: 0.7rem;
    border-radius: 0;
    background: none;
    box-shadow: none;
  }

  html[data-phone-layout='tiles'] .phone-group--community .phone-row {
    overflow: hidden;
    flex: 1 1 0;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-end;
    min-width: 0;
    aspect-ratio: 1;
    padding: 0.8rem;
    border-radius: 16px;
    /* Dark backstop for the case where the artwork does not load, since the
       text on these widgets is light. */
    background: var(--thf-footer-bg);
    box-shadow: 0 1px 2px var(--thf-shadow);
  }

  html[data-phone-layout='tiles'] .phone-group--community .phone-row + .phone-row::before {
    display: none;
    content: none;
  }

  /* The artwork becomes the widget's background. */
  html[data-phone-layout='tiles'] .phone-group--community .phone-row__art {
    position: absolute;
    z-index: 0;
    width: 100%;
    height: 100%;
    inset: 0;
    border-radius: 0;
  }

  html[data-phone-layout='tiles'] .phone-group--community .phone-row__art::after {
    position: absolute;
    inset: 0;
    background: linear-gradient(0deg, rgba(0, 0, 0, 0.84) 0%, rgba(0, 0, 0, 0.36) 48%, rgba(0, 0, 0, 0.06) 100%);
    content: '';
  }

  html[data-phone-layout='tiles'] .phone-group--community .phone-row__text {
    position: relative;
    z-index: 1;
    flex: 0 0 auto;
    width: 100%;
  }

  html[data-phone-layout='tiles'] .phone-group--community .phone-row__eyebrow {
    display: block;
    overflow: hidden;
    color: var(--thf-accent-2, #C9A227);
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  html[data-phone-layout='tiles'] .phone-group--community .phone-row__title {
    color: #fff;
    font-size: 1rem;
    /* Two lines are expected at widget width. */
    white-space: normal;
  }

  html[data-phone-layout='tiles'] .phone-group--community .phone-row__sub {
    color: #ddd3c2;
    font-size: 0.72rem;
  }

  html[data-phone-layout='tiles'] .phone-row__sub--pathway {
    display: none;
  }

  html[data-phone-layout='tiles'] .phone-row__sub--pathtiles {
    display: block;
  }

  html[data-phone-layout='tiles'] .phone-group--community .phone-row__chevron {
    display: none;
  }
}

/* ==========================================================================
   Phone layout: stats - Health/Fitness summary
   ========================================================================== */

@media (max-width: 767.98px) {

  /* The stat pair replaces the profile row: the avatar has moved to the
     header and both numbers are now first-class. */
  html[data-phone-layout='stats'] .phone-group--profile {
    display: none;
  }

  html[data-phone-layout='stats'] .phone-stats {
    display: flex;
  }

  html[data-phone-layout='stats'] .phone-hdr--continue,
  html[data-phone-layout='stats'] .phone-hdr--community {
    display: none;
  }

  html[data-phone-layout='stats'] .phone-hdr--pickup,
  html[data-phone-layout='stats'] .phone-hdr--communitystudy {
    display: block;
  }

  html[data-phone-layout='stats'] .phone-fund__match--long {
    display: none;
  }

  html[data-phone-layout='stats'] .phone-fund__match--dated {
    display: block;
  }

  /* The pathway row shows a bar rather than a sentence, since the figure is
     already at the top of the screen. */
  html[data-phone-layout='stats'] .phone-row__sub--pathway {
    display: none;
  }

  html[data-phone-layout='stats'] .phone-row__bar {
    display: block;
  }
}

/* ==========================================================================
   Library cards: two across on a phone

   One card per row made ten cards a five-screen scroll (4,525px), and at full
   width the 16:9 art plus a three-line subtitle plus a button said less than
   the art and the title do at half width. Two across cuts the page to 1,637px
   and reads like a shelf. Card View only, every phone layout - the layout
   picker restyles the dashboard block above, not the library.

   Every rule here is gated on :not([data-card-size="full"]), which is the View
   control's third option. Opting out rather than undoing means "Large Cards"
   gets the original card CSS untouched, instead of a second set of overrides
   trying to restore it property by property. Absent attribute counts as two-up,
   so this survives a page where the inline script has not run.
   ========================================================================== */

@media (max-width: 767.98px) {

  /* Tighter than Bootstrap's 15px gutters, so the art keeps some of the width
     the second column costs it. */
  html:not([data-card-size="full"]) body.dashboard-page .library-cards-container[data-view="grid"] {
    margin-left: -0.3rem;
    margin-right: -0.3rem;
  }

  html:not([data-card-size="full"]) body.dashboard-page .library-cards-container[data-view="grid"] .library-item {
    flex: 0 0 50%;
    max-width: 50%;
    padding-left: 0.3rem;
    padding-right: 0.3rem;
    margin-bottom: 0.6rem !important;
  }

  /* The 400px cap and auto margins exist to centre a full-width card; at half
     width they would pull the card off its column edge. */
  html:not([data-card-size="full"]) body.dashboard-page .library-cards-container[data-view="grid"] .library-card {
    max-width: none;
    margin: 0;
    border-radius: 12px;
  }

  html:not([data-card-size="full"]) body.dashboard-page .library-cards-container[data-view="grid"] .library-card-body {
    padding: 0.55rem 0.6rem 0.65rem;
  }

  /* Two lines of title, no bottom margin because the subtitle and button below
     it are gone. font-size needs !important purely because the mobile block of
     the purged bundles forces .content-wrapper h3 to 1rem with !important,
     which no amount of specificity can outrank. */
  html:not([data-card-size="full"]) body.dashboard-page .library-cards-container[data-view="grid"] .library-title {
    font-size: 0.9rem !important;
    line-height: 1.25;
    margin: 0;
    -webkit-line-clamp: 2;
  }

  /* No room for body copy at ~170px, and the whole card is already a link, so
     the button is decoration costing a third of the card's height. */
  html:not([data-card-size="full"]) body.dashboard-page .library-cards-container[data-view="grid"] .library-subtitle,
  html:not([data-card-size="full"]) body.dashboard-page .library-cards-container[data-view="grid"] .library-button-container {
    display: none;
  }

  /* Half-width art needs the Coming Soon badge to shrink with it. */
  html:not([data-card-size="full"]) body.dashboard-page .library-cards-container[data-view="grid"] .coming-soon-banner {
    font-size: 0.6rem;
    padding: 0.2rem 0.3rem;
  }

  html:not([data-card-size="full"]) body.dashboard-page .library-cards-container[data-view="grid"] .coming-soon-logo {
    width: 22px;
    height: 22px;
  }
}

/* ==========================================================================
   App View tiles: two across on a phone, shaped to the artwork

   The tiles were 85px squares three across, which read as a phone home screen
   but wasted most of the width. Two across lets each tile fill its column.

   The tile is 16:9 rather than square because every image behind it is: the ten
   dashboard cards run 1.50-1.78, not one is square. A square container can only
   crop that art (which ate ~40% of the width and cut "ANTE-NICENE" down to
   "TE-NICE") or letterbox it (bands above and below, and a white block floating
   on a dark tile). Matching the container to the art means the picture fills it
   edge to edge and looks the way it does on the cards, where it looks right.
   ========================================================================== */

@media (max-width: 767.98px) {

  body.dashboard-page .ios-app-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 1.15rem 0.6rem;
    /* The 3-up grid centred each fixed-width icon in its column; these stretch
       to fill it instead. */
    justify-items: stretch;
  }

  body.dashboard-page .ios-app-grid .ios-app-item,
  body.dashboard-page .ios-app-grid .ios-app-link {
    width: 100%;
  }

  /* aspect-ratio rather than a matched width/height pair, so the tile keeps the
     artwork's shape at any column width without another breakpoint. */
  body.dashboard-page .ios-app-grid .ios-app-icon {
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
    border-radius: 16px;
  }

  /* 11px under an 85px icon was proportionate; under a 164px tile it is not,
     and there is now room for the full name. */
  body.dashboard-page .ios-app-grid .ios-app-label {
    font-size: 0.95rem;
    max-width: 100%;
    margin-top: 0.45rem;
  }

  /* The per-app scale() nudges were tuned to hide the square crop; against a
     tile that already matches the art they only crop it again. Left alone for
     admin-made icons, whose fit and scale were chosen in the crop modal.
     !important is unavoidable: index.php writes transform as an inline style
     attribute, which outranks any selector. */
  body.dashboard-page .ios-app-grid .ios-app-item[data-has-custom-icon="0"] .ios-app-icon img {
    transform: none !important;
  }

  body.dashboard-page .ios-app-grid .ios-app-badge {
    font-size: 0.68rem;
    letter-spacing: 0.4px;
  }
}

/* --------------------------------------------------------------------------
   Dark mode for the app tiles - restoring overrides the bundle dropped

   library.css darkens .ios-app-label and .ios-app-icon for dark mode, but it is
   only linked when $ASSETS_OPTIMIZED is false. The purged bundles that ship
   carry .ios-app-label{color:#1a1a1a} with no dark counterpart, so the labels
   were near-invisible on a dark page. Restated here because this file is linked
   unconditionally and loads after the bundles.
   -------------------------------------------------------------------------- */

html[data-theme="dark"] .ios-app-label {
  color: var(--thf-text-2);
}

html[data-theme="dark"] .ios-app-icon,
html[data-theme="dark"] .ios-app-icon img {
  background-color: var(--thf-surface-2);
}

/* =============================================================================
   DASHBOARD TOP CARDS — design 9 ("Mix: Big and Clear"), picked by Daniel
   2026-09-28 (task folder dashboard-cards-redesign-2026-09-28).

   Markup: dashboard/index.php (.dh) + welcome_card.php,
   encounter_photo_wall_card.php, group_studies_card.php. One look for all of
   them: surface card, 16px corners, soft shadow, serif titles, a small
   uppercase eyebrow, copper buttons with dark text, a picture tile per card.

   Two arrangements, chosen by index.php:
   - .dh--split (Encounter fundraiser on): welcome card over the photo wall on
     the left, the UNCHANGED fundraiser on the right, tops and bottoms level.
   - otherwise: welcome card full width, then the photo wall and Cell Group
     Studies as a matched pair (or the photo wall as a full-width row).
   Every church course under that (Cell Group Studies, baptism class, Four
   Foundations) is a full-width row of its own, all on the same 1.5rem gap.

   Sizes follow the width of .dh (container queries), not the screen, because
   the left sidebar can be open or closed at any screen width.

   Phones never see the welcome card, photo wall or fundraiser here
   (.dh-desk-only): phone_dashboard.php replaces them below 768px. The course
   rows do show on phones.

   Colours: theme tokens plus the brand literals already used on this page
   (#BD926F, #C9A227, #3a5331, #343a40, #1a1a1a). Correct in both themes
   because every surface and text colour is a token; the only literals sit on
   the dark picture tiles and the copper buttons, which look the same in both.
   ============================================================================= */
.dh {
  --dh-radius: 16px;
  --dh-pad: 1.9rem;
  --dh-copper: #BD926F;
  --dh-gold: #C9A227;
  --dh-ink: #1a1a1a;
  --dh-serif: 'Playfair Display', Georgia, serif;
  --dh-shadow: 0 1px 2px rgba(20, 23, 26, .06), 0 6px 18px rgba(20, 23, 26, .06);
  container: dh / inline-size;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
.dh--split { --dh-pad: 1.6rem; }
html[data-theme="dark"] .dh {
  --dh-shadow: 0 1px 2px rgba(0, 0, 0, .35), 0 8px 22px rgba(0, 0, 0, .28);
}

@media (min-width: 768px) {
  /* reach the same edge as the library cards below (rows there pull out 12px) */
  .dh {
    margin-left: -12px;
    margin-right: -12px;
  }
  #dashHomeCards { padding-top: 4px; }
}

@media (max-width: 767.98px) {
  /* on a phone only the course rows are left in here (the rest is
     .dh-desk-only, hidden in "Phone dashboard: shared primitives") */
  #dashHomeCards:has(> :not(.dh-desk-only)) { margin-top: 2rem; }
}

/* ---------- shared ---------- */
.dh .dh-eyebrow {
  display: block;
  font-size: .8rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--thf-text-2);
  line-height: 1.25;
}
.dh .dh-eyebrow--accent { color: var(--thf-link); }

.dh .dh-panel,
.dh .dh-card {
  background: var(--thf-surface);
  border: 1px solid var(--thf-border);
  border-radius: var(--dh-radius);
  box-shadow: var(--dh-shadow);
  color: var(--thf-text);
}

.dh .dh-go { font-size: .8rem; color: var(--thf-text-2); transition: transform .15s ease, color .15s ease; }

.dh .dh-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6rem;
  min-height: 50px;
  padding: .6rem 1.5rem;
  border-radius: 999px;
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.2;
  text-decoration: none;
  white-space: nowrap;
  border: 2px solid transparent;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.dh .dh-btn i { font-size: .85em; }
.dh .dh-btn--lg { min-height: 56px; padding: .7rem 1.8rem; font-size: 1.12rem; }
.dh .dh-btn--primary {
  background: var(--dh-copper);
  border-color: var(--dh-copper);
  color: var(--dh-ink);
}
.dh a.dh-btn--primary:hover,
.dh .dh-card--link:hover .dh-btn--primary,
.dh .dh-resume:hover .dh-btn--primary {
  background: var(--dh-gold);
  border-color: var(--dh-gold);
  color: var(--dh-ink);
  text-decoration: none;
}
.dh .dh-btn--ghost {
  background: var(--thf-surface);
  border-color: var(--thf-border-strong, var(--thf-border));
  color: var(--thf-heading);
}
.dh .dh-btn--ghost i { color: var(--thf-link); }
.dh .dh-btn--ghost:hover { border-color: var(--dh-copper); color: var(--thf-heading); text-decoration: none; }
.dh .dh-btn:focus-visible,
.dh .dh-link:focus-visible,
.dh .dh-points:focus-visible,
.dh .dh-resume:focus-visible,
.dh .dh-card--link:focus-visible,
.dh .dh-photo:focus-visible { outline: 3px solid var(--dh-copper); outline-offset: 3px; }

/* ---------- 1. welcome card ---------- */
.dh .dh-panel { overflow: hidden; }

.dh .dh-head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) minmax(250px, 300px);
  grid-template-areas: "photo greet links";
  align-items: center;
  gap: 1.9rem;
  padding: var(--dh-pad);
}
.dh .dh-photo-cell { grid-area: photo; }
.dh .dh-greet { grid-area: greet; min-width: 0; }
.dh .dh-links { grid-area: links; }

.dh .dh-photo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .45rem;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  border-radius: 20px;
}
.dh .dh-photo-img {
  width: 120px;
  height: 120px;
  object-fit: cover;
  display: block;
  border-radius: 20px;
  box-shadow: 0 0 0 1px var(--thf-border), 0 4px 12px rgba(0, 0, 0, .14);
}
.dh .dh-photo-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--thf-surface-2);
  color: var(--thf-text-2);
  font-size: 3rem;
}
.dh .dh-photo-edit {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .25rem .8rem;
  border: 1px solid var(--thf-border);
  border-radius: 999px;
  background: var(--thf-surface-2);
  color: var(--thf-text);
  font-size: .88rem;
  font-weight: 600;
  line-height: 1.3;
}
.dh .dh-photo-edit i { color: var(--thf-link); font-size: .8rem; }
.dh .dh-photo:hover .dh-photo-edit { border-color: var(--dh-copper); }

.dh .dh-title {
  font-family: var(--dh-serif);
  font-weight: 700;
  font-size: 2.35rem;
  line-height: 1.15;
  color: var(--thf-heading);
  margin: .4rem 0 .85rem;
  font-variant-numeric: lining-nums;
}

.dh .dh-points {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  min-height: 48px;
  padding: .35rem 1.1rem .35rem 1rem;
  border: 1px solid var(--thf-border-strong, var(--thf-border));
  border-radius: 999px;
  background: var(--thf-surface-2);
  color: var(--thf-heading);
  text-decoration: none;
  transition: border-color .15s ease;
}
.dh .dh-points:hover { border-color: var(--dh-gold); color: var(--thf-heading); text-decoration: none; }
.dh .dh-points #points-star { color: var(--dh-gold); font-size: 1.15rem; }
.dh .dh-points-num { font-size: 1.35rem; font-weight: 700; font-variant-numeric: tabular-nums lining-nums; line-height: 1; }
.dh .dh-points-word { font-size: 1rem; font-weight: 600; color: var(--thf-text); }
.dh .dh-points .dh-go { margin-left: .15rem; }

.dh .dh-links { display: flex; flex-direction: column; gap: .75rem; }
.dh .dh-link {
  display: flex;
  align-items: center;
  gap: .8rem;
  min-height: 56px;
  padding: .5rem 1.1rem .5rem .6rem;
  border: 1px solid var(--thf-border-strong, var(--thf-border));
  border-radius: 12px;
  background: var(--thf-surface);
  color: var(--thf-heading);
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.2;
  text-decoration: none;
  transition: border-color .15s ease;
}
.dh .dh-link-icon {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: var(--thf-surface-2);
  color: var(--thf-link);
  font-size: 1rem;
}
.dh .dh-link-text { flex: 1 1 auto; min-width: 0; white-space: nowrap; }
.dh .dh-link:hover { border-color: var(--dh-copper); color: var(--thf-heading); text-decoration: none; }
.dh .dh-link:hover .dh-go,
.dh .dh-points:hover .dh-go { transform: translateX(3px); color: var(--thf-link); }

/* resume row — the one big "do this next" */
.dh .dh-resume {
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr) minmax(250px, 300px);  /* same columns as the row above */
  align-items: center;
  gap: 1.9rem;
  padding: 1.35rem var(--dh-pad);
  border-top: 1px solid var(--thf-border);
  background: var(--thf-surface-2);
  color: var(--thf-text);
  text-decoration: none;
}
.dh .dh-resume:hover { color: var(--thf-text); text-decoration: none; }
.dh .dh-play {
  justify-self: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--dh-copper);
  color: var(--dh-ink);
  font-size: 1.35rem;
  box-shadow: 0 0 0 7px rgba(189, 146, 111, .18), 0 4px 12px rgba(0, 0, 0, .16);
  transition: transform .18s ease, background-color .18s ease;
}
.dh .dh-play i { margin-left: 4px; }
.dh .dh-resume:hover .dh-play { transform: scale(1.04); background: var(--dh-gold); }
.dh .dh-resume-text { display: flex; flex-direction: column; gap: .3rem; min-width: 0; }
.dh .dh-resume-title {
  font-family: var(--dh-serif);
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--thf-heading);
  line-height: 1.2;
  font-variant-numeric: lining-nums;
  overflow-wrap: anywhere;
}
.dh .dh-resume .dh-btn { width: 100%; }

/* signed-out welcome (index.php only renders these cards for a signed-in
   member, but the partial keeps the guest branch) */
.dh .dh-guest { padding: var(--dh-pad); text-align: center; }
.dh .dh-guest .dh-title { margin: .4rem 0 1rem; }
.dh .dh-guest-text {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: .75rem;
  margin: 0;
  font-size: 1.05rem;
  color: var(--thf-text);
}

/* ---------- 2 + 3. the cards: photo wall, Cell Group Studies ----------
   One markup each, laid out on a grid so the same pieces can form a full-width
   row (default), a half-width card (.dh-pair) or the photo wall beside the
   fundraiser (.dh-left). Areas: tile, head (eyebrow + title), desc, meta
   (dates / chips), act (buttons). */
.dh .dh-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-rows: auto auto auto 1fr;
  grid-template-areas:
    "tile head act"
    "tile desc act"
    "tile meta act"
    "tile .    act";
  column-gap: 1.1rem;
  align-items: start;
  padding: var(--dh-pad);
  text-decoration: none;
  transition: border-color .15s ease, transform .15s ease;
}
.dh .dh-card--link { cursor: pointer; }
.dh .dh-card--link:hover { color: var(--thf-text); border-color: var(--dh-copper); text-decoration: none; transform: translateY(-2px); }

.dh .dh-tile {
  grid-area: tile;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 58px;
  height: 58px;
  border-radius: 14px;
  font-size: 1.45rem;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .06);
}
.dh .dh-tile--photos { background: linear-gradient(145deg, #3a5331 0%, #1a1a1a 100%); color: #BD926F; }
.dh .dh-tile--study  { background: linear-gradient(145deg, #343a40 0%, #1a1a1a 100%); color: #C9A227; }

.dh .dh-card-head { grid-area: head; display: flex; flex-direction: column; min-width: 0; }
.dh .dh-card-title {
  display: block;
  font-family: var(--dh-serif);
  font-weight: 700;
  font-size: 1.7rem;
  line-height: 1.2;
  color: var(--thf-heading);
  margin: .35rem 0 .6rem;
}

.dh .dh-desc {
  grid-area: desc;
  display: block;
  font-size: 1.05rem;
  line-height: 1.6;
  color: var(--thf-text);
  margin: 0 0 .75rem;
  max-width: 40em;
}

.dh .dh-meta,
.dh .dh-date { grid-area: meta; display: flex; flex-wrap: wrap; align-items: center; gap: .45rem 1.4rem; }
.dh .dh-meta-item {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--thf-heading);
  line-height: 1.35;
}
.dh .dh-meta-item i { color: var(--thf-link); font-size: .95rem; }

/* buttons in a column on the right, behind a hairline */
.dh .dh-actions {
  grid-area: act;
  align-self: stretch;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: .75rem;
  min-width: 230px;
  margin-left: .5rem;
  padding: .25rem 0 .25rem 1.6rem;
  border-left: 1px solid var(--thf-border);
}

/* --- the matched pair (no fundraiser, Cell Group Studies present) --- */
.dh .dh-pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.5rem;
  align-items: stretch;
}
.dh .dh-pair > .dh-card {
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: auto auto 1fr auto;
  grid-template-areas:
    "tile head"
    "meta meta"
    "desc desc"
    "act  act";
}
.dh .dh-pair > .dh-card .dh-tile { width: 64px; height: 64px; font-size: 1.6rem; margin-bottom: 1rem; }
.dh .dh-pair > .dh-card .dh-card-head { align-self: center; gap: .35rem; margin-bottom: 1rem; }
.dh .dh-pair > .dh-card .dh-card-title { margin: 0; }
.dh .dh-pair > .dh-card .dh-meta,
.dh .dh-pair > .dh-card .dh-date { margin-bottom: .75rem; }
.dh .dh-pair > .dh-card .dh-desc { margin-bottom: 1.4rem; }
.dh .dh-pair > .dh-card .dh-actions {
  align-self: end;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  min-width: 0;
  margin: 0;
  padding: 1.25rem 0 0;
  border-left: 0;
  border-top: 1px solid var(--thf-border);
}

/* ======================= split: beside the Encounter fundraiser ======================= */
.dh .dh-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(400px, 40%, 460px);
  gap: 1.5rem;
  align-items: stretch;
}
.dh .dh-left {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  min-width: 0;
}
.dh .dh-left > .dh-panel { flex: none; }
.dh .dh-left > .dh-card { flex: 1 1 auto; }

/* the fundraiser column: ONLY its box is set here; its look is encounter-campaign.css */
.dh .dh-top > #encounterFundraiserCard {
  flex: none;
  width: auto;
  max-width: none;
  min-width: 0;
  padding: 0;
  margin: 0 !important;
  display: flex;
}
.dh .dh-top > #encounterFundraiserCard > .encounter-fundraiser-card { flex: 1 1 auto; height: auto; }

/* welcome card: photo on the left; eyebrow + points, the greeting, then the two shortcut buttons beside it */
.dh--split .dh-head {
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas: "photo greet" "photo links";
  align-items: start;
  gap: 1rem 1.5rem;
  padding: var(--dh-pad) var(--dh-pad) 1.35rem;
}
.dh--split .dh-photo-img { width: 108px; height: 108px; }
.dh--split .dh-greet {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "eye pts" "title title";
  align-items: center;
  column-gap: 1rem;
}
.dh--split .dh-greet .dh-eyebrow { grid-area: eye; }
.dh--split .dh-points { grid-area: pts; min-height: 44px; }
.dh--split .dh-title { grid-area: title; font-size: 1.95rem; margin: .2rem 0 0; }
.dh--split .dh-links { display: grid; grid-template-columns: 1fr 1fr; gap: .75rem; }
.dh--split .dh-link { min-height: 52px; }

.dh--split .dh-resume {
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 1.1rem;
  padding: 1.05rem var(--dh-pad);
}
.dh--split .dh-play {
  justify-self: start;
  width: 58px;
  height: 58px;
  font-size: 1.15rem;
  box-shadow: 0 0 0 6px rgba(189, 146, 111, .18), 0 4px 12px rgba(0, 0, 0, .16);
}
.dh--split .dh-resume-title { font-size: 1.15rem; text-wrap: balance; }
.dh--split .dh-resume .dh-btn { width: auto; min-height: 52px; padding: .6rem 1.25rem; font-size: 1.05rem; }

/* photo wall under the welcome card: the dates share the button row */
.dh .dh-left > .dh-photos {
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "tile head head"
    "desc desc desc"
    "meta meta act";
  column-gap: 0;
  padding: 1.3rem var(--dh-pad);
}
.dh .dh-left > .dh-photos .dh-tile { margin: 0 1.1rem .85rem 0; }
.dh .dh-left > .dh-photos .dh-card-head { align-self: center; gap: .35rem; margin-bottom: .85rem; }
.dh .dh-left > .dh-photos .dh-card-title { margin: 0; }
.dh .dh-left > .dh-photos .dh-desc { margin-bottom: 1rem; }
.dh .dh-left > .dh-photos .dh-date,
.dh .dh-left > .dh-photos .dh-actions {
  align-self: stretch;
  padding-top: 1rem;
  border-top: 1px solid var(--thf-border);
}
.dh .dh-left > .dh-photos .dh-actions {
  flex-direction: row;
  justify-content: flex-end;
  align-items: center;
  min-width: 0;
  margin: 0;
  padding-left: 1rem;
  padding-right: 0;
  padding-bottom: 0;
  border-left: 0;
}

/* ======================= narrower widths (measured on .dh) ======================= */

/* no fundraiser: tighten the three-column welcome card */
@container dh (max-width: 1000px) {
  .dh:not(.dh--split) .dh-head { grid-template-columns: auto minmax(0, 1fr) 250px; }
  .dh:not(.dh--split) .dh-resume { grid-template-columns: 120px minmax(0, 1fr) 250px; }
  .dh:not(.dh--split) .dh-resume-title { font-size: 1.45rem; }
}
/* no fundraiser, narrower: shortcut buttons go under the greeting; the pair
   stops being a pair and both cards become full-width rows */
@container dh (max-width: 940px) {
  .dh:not(.dh--split) .dh-head {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas: "photo greet" "links links";
    gap: 1.4rem 1.6rem;
  }
  .dh:not(.dh--split) .dh-links { display: grid; grid-template-columns: 1fr 1fr; }
  .dh:not(.dh--split) .dh-title { font-size: 2.1rem; }
  .dh:not(.dh--split) .dh-resume { grid-template-columns: 120px minmax(0, 1fr) auto; gap: 1.6rem; }
  .dh .dh-pair { display: flex; flex-direction: column; }
  .dh .dh-pair > .dh-card {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-rows: auto auto auto 1fr;
    grid-template-areas:
      "tile head act"
      "tile desc act"
      "tile meta act"
      "tile .    act";
  }
  .dh .dh-pair > .dh-card .dh-tile { width: 58px; height: 58px; font-size: 1.45rem; margin-bottom: 0; }
  .dh .dh-pair > .dh-card .dh-card-head { align-self: start; gap: 0; margin-bottom: 0; }
  .dh .dh-pair > .dh-card .dh-card-title { margin: .35rem 0 .6rem; }
  .dh .dh-pair > .dh-card .dh-meta,
  .dh .dh-pair > .dh-card .dh-date { margin-bottom: 0; }
  .dh .dh-pair > .dh-card .dh-desc { margin-bottom: .75rem; }
  .dh .dh-pair > .dh-card .dh-actions {
    align-self: stretch;
    flex-direction: column;
    justify-content: center;
    min-width: 230px;
    margin-left: .5rem;
    padding: .25rem 0 .25rem 1.6rem;
    border-top: 0;
    border-left: 1px solid var(--thf-border);
  }
}

/* split, narrower content (tablet, or sidebar open): same arrangement, tighter welcome card */
@container dh (max-width: 1180px) {
  .dh--split .dh-photo-img { width: 96px; height: 96px; }
  .dh--split .dh-head { gap: .9rem 1.25rem; }
  .dh--split .dh-title { font-size: 1.8rem; }
  .dh--split .dh-link { gap: .6rem; padding: .45rem .8rem .45rem .5rem; }
  .dh--split .dh-link-icon { width: 34px; height: 34px; }
  .dh--split .dh-link .dh-go { display: none; }
  .dh--split .dh-resume .dh-btn { padding: .6rem 1rem; }
}
/* split, sidebar open on a ~1200px screen: shortcut buttons move under the photo so they keep one line */
@container dh (max-width: 920px) {
  .dh--split .dh-top { grid-template-columns: minmax(0, 1fr) 380px; }
  .dh--split .dh-head { grid-template-areas: "photo greet" "links links"; }
  .dh--split .dh-greet { align-self: center; }
  .dh--split .dh-resume-title { font-size: 1.1rem; }
  .dh--split .dh-resume .dh-btn { padding: .6rem 1rem; }
}
/* too narrow for two columns (about 768-820px): stack everything, the
   fundraiser after the photo wall; rows put their buttons underneath */
@container dh (max-width: 820px) {
  .dh--split .dh-head { grid-template-areas: "photo greet" "photo links"; }
  .dh--split .dh-greet { align-self: start; }
  .dh--split .dh-resume-title { font-size: 1.15rem; }
  .dh--split .dh-resume .dh-btn { padding: .6rem 1.25rem; }
  .dh--split .dh-top { grid-template-columns: minmax(0, 1fr); }
  .dh--split .dh-link .dh-go { display: inline-block; }

  .dh .dh-card:not(.dh-left > .dh-card),
  .dh .dh-pair > .dh-card {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-rows: auto;
    grid-template-areas: "tile head" "tile desc" "tile meta" ".    act";
  }
  .dh .dh-card:not(.dh-left > .dh-card) .dh-actions,
  .dh .dh-pair > .dh-card .dh-actions {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: flex-start;
    min-width: 0;
    margin: 1.1rem 0 0;
    padding: 1rem 0 0;
    border-left: 0;
    border-top: 1px solid var(--thf-border);
  }
  .dh:not(.dh--split) .dh-photo-img { width: 100px; height: 100px; }
  .dh:not(.dh--split) .dh-title { font-size: 1.85rem; }
  .dh:not(.dh--split) .dh-resume { grid-template-columns: 100px minmax(0, 1fr); gap: 1rem 1.6rem; }
  .dh:not(.dh--split) .dh-resume .dh-btn { grid-column: 1 / -1; }
}
/* phone width: the course rows become simple cards with the buttons full width */
@container dh (max-width: 560px) {
  .dh .dh-card:not(.dh-left > .dh-card),
  .dh .dh-pair > .dh-card {
    padding: 1.25rem;
    grid-template-areas: "tile head" "desc desc" "meta meta" "act act";
  }
  .dh .dh-card .dh-card-head { align-self: center; }
  .dh .dh-card .dh-desc { margin-top: .85rem; }
  .dh .dh-card:not(.dh-left > .dh-card) .dh-actions,
  .dh .dh-pair > .dh-card .dh-actions { flex-direction: column; align-items: stretch; }
}

/* the phone block of the purged bundle forces .content-wrapper h3 to 1rem with
   a tiny margin (!important); give the study title its size back there */
@media (max-width: 767.98px) {
  .dh .dh-card-title { font-size: 1.45rem !important; margin: .3rem 0 0 !important; }
  .dh .dh-card .dh-eyebrow { font-size: .75rem; }
  .dh .dh-desc { font-size: 1rem; }
}

/* --- church course rows: baptism class and Four Foundations keep their own
   look; they just run full width, one row each --- */
.dh .dh-course > [class*="col-"] {
  flex: none;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  padding-left: 0;
  padding-right: 0;
  margin: 0 !important;
}

/* =============================================================================
   CHURCH DOCUMENTS ROW, under the top cards.

   The top cards and church courses space themselves (.dh, DASHBOARD TOP
   CARDS). This row, which only a few accounts see, makes its own space above
   instead of relying on a margin that is not there.
   ============================================================================= */
.thf-course-row { margin-top: 2rem; }

/* Desktop: the same width as every card above them.

   .top-cards-row (library.css) drops Bootstrap's 12px column padding in favour
   of a 1.5rem gap, so its two cards reach both edges of the row. The rows that
   only some accounts ever see (now just Church Documents) kept the default
   padding, so measured on the deployed page every
   one of their cards started 12px to the right of the card above it and stopped
   12px short on the other side. Same treatment here, but sized rather than
   flexed: these rows can carry a third card, and that card has to wrap onto a
   second line instead of squeezing three across. */
@media (min-width: 768px) {
  .thf-course-row { column-gap: 1.5rem; }

  .thf-course-row > .col-md-6 {
    flex: 0 0 calc(50% - .75rem);
    /* Defeats flexbox's automatic minimum size, the same way the pathway card
       needs it. */
    min-width: 0;
    max-width: calc(50% - .75rem);
    padding-right: 0;
    padding-left: 0;
  }
}

/* =============================================================================
   COMPLETED CHURCH COURSES — the section at the foot.

   A finished course is a record, not a call to action, so it drops out of the
   top of the dashboard and collects down here past every other card. Only the
   few accounts with one of these ever see the section at all.
   ============================================================================= */
.thf-completed-courses {
  margin-top: 2.5rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--thf-border, #e2e3e5);
}
.thf-completed-courses__head { margin-bottom: 1rem; }
.thf-completed-courses__heading {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin: 0 0 .2rem;
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 1.35rem;
  color: var(--thf-heading, #2f2d2c);
}
.thf-completed-courses__heading i { font-size: 1.05rem; color: #3a5331; }
.thf-completed-courses__note {
  margin: 0;
  font-size: .92rem;
  color: var(--thf-text-2, #6a6764);
}
/* its rows are the same full-width .dh-course rows as the courses at the top */

/* =============================================================================
   THE CARD GRID — one height for all twelve, not three.

   The grid was a wrapping flex row, so each line of four stretched to its own
   tallest card and the three rows disagreed: measured 407px, 402px and 374px
   down the page. That step is what read as "not symmetrical".

   A real grid with `grid-auto-rows: 1fr` gives every card in the grid the same
   height, and reserving two lines for every title means the description — and
   the button under it — start at the same place on every card. The button was
   already pinned with margin-top:auto; it just had nothing consistent to sit
   under.

   Columns match the Bootstrap classes the markup already carries
   (col-xl-3 / col-lg-4 / col-md-6 / col-sm-12) so nothing moves at any width.
   Scoped to the default grid view; the App and Large Card views are untouched.
   ============================================================================= */
@media (min-width: 768px) {
  .library-cards-container[data-view="grid"] {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-rows: 1fr;
    gap: 24px;
  }
  /* the items keep their Bootstrap column classes; the gap does the spacing now */
  .library-cards-container[data-view="grid"] > .library-item {
    flex: none;
    width: auto;
    max-width: none;
    padding-left: 0;
    padding-right: 0;
    margin-bottom: 0;
  }
  .library-cards-container[data-view="grid"] > .library-item > .library-card-link { height: 100%; }
  .library-cards-container[data-view="grid"] .library-card { height: 100%; }

  /* one title treatment, with two lines of room reserved whether the title
     needs them or not - that is what lines the descriptions up */
  .library-cards-container[data-view="grid"] .library-title,
  .library-cards-container[data-view="grid"] .library-title-emphasis {
    font-size: 1.25rem;
    font-weight: 700;
    min-height: 2.8em;   /* 2 lines at line-height 1.4 */
  }
}
@media (min-width: 992px) {
  .library-cards-container[data-view="grid"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width: 1200px) {
  .library-cards-container[data-view="grid"] { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* =============================================================================
   RAISE THE CARD PICTURES OFF THE TEXT.

   The card is pure white and six of the twelve pictures have edges measured at
   239-255 luminance - Questions Answered 255, Blog 254, Forums 252, Donate 248,
   ANF Library 247 - so the bottom of the picture and the top of the text ran
   together with nothing between them.

   The picture stays FULL BLEED across the top of the card, exactly as it was:
   no mat, no inset, no change to its size or ratio. All that changes is its
   bottom edge, which now has a hairline and a downward shadow, so the picture
   reads as a raised plate with the text recessed under it.

   The card is overflow:hidden with an 8px radius, so the shadow falls inside
   the card onto the body, and the picture's top corners stay rounded with it.
   ============================================================================= */
@media (min-width: 768px) {
  .library-cards-container[data-view="grid"] .library-image-container {
    position: relative;
    z-index: 1;                    /* the shadow has to land on the body below */
    border-radius: 8px 8px 0 0;    /* follow the card's own corners */
    box-shadow:
      0 1px 0 rgba(28,26,24,.12),          /* the edge itself */
      0 7px 12px -5px rgba(28,26,24,.34);  /* the lift under it */
    transition: box-shadow .22s ease;
  }
  /* the card already lifts 4px on hover; the picture lifts further off the text
     by deepening its own shadow rather than moving again */
  @media (hover: hover) and (pointer: fine) {
    .library-card-link:hover .library-image-container {
      box-shadow:
        0 1px 0 rgba(28,26,24,.16),
        0 11px 18px -6px rgba(28,26,24,.42);
    }
  }
  /* black barely reads on a dark surface, so it goes deeper there */
  html[data-theme="dark"] .library-cards-container[data-view="grid"] .library-image-container {
    box-shadow: 0 1px 0 rgba(0,0,0,.6), 0 8px 14px -5px rgba(0,0,0,.7);
  }
  @media (hover: hover) and (pointer: fine) {
    html[data-theme="dark"] .library-card-link:hover .library-image-container {
      box-shadow: 0 1px 0 rgba(0,0,0,.65), 0 12px 20px -6px rgba(0,0,0,.78);
    }
  }
  @media (prefers-reduced-motion: reduce) {
    .library-cards-container[data-view="grid"] .library-image-container { transition: none; }
  }
}

/* =============================================================================
   ONE SHADOW FOR THE BIG CARDS TOO.

   The library cards below sit on `0 4px 12px rgba(0,0,0,.2)`. Every large card
   above them was on half that: `rgba(0,0,0,.1)` twice over for the welcome
   card, the photo wall and the fundraiser, and a single .1 for the Four
   Foundations bar. The Bible in a Year banner had no shadow at all. That is why
   the lower half of the dashboard looked lifted and the top half looked flat.

   They all use the library card's value now, so the whole page sits at one
   depth. Dark mode goes to the deeper black theme.css already gives the welcome
   card and photo wall there - which also fixes the Four Foundations bar, whose
   --thf-shadow token does not darken for dark mode and left it with almost no
   shadow at all.

   Since design 9 (2026-09-28) the welcome card, photo wall and Cell Group
   Studies carry that design's own softer shadow (DASHBOARD TOP CARDS); the
   fundraiser and Four Foundations keep this one.
   ============================================================================= */
.dh-top .encounter-fundraiser-card,
.dh-course .ff-dashboard-card,
.biay-dash-banner-link {
  box-shadow: 0 4px 12px rgba(0, 0, 0, .2);
}

html[data-theme="dark"] .dh-top .encounter-fundraiser-card,
html[data-theme="dark"] .dh-course .ff-dashboard-card,
html[data-theme="dark"] .biay-dash-banner-link {
  box-shadow: 0 8px 24px rgba(0, 0, 0, .55);
}

/* Subtle brand tints and clearer edges in light mode. Keep Four Foundations'
   artwork and every dark-mode surface unchanged. */
html:not([data-theme="dark"]) .dh {
  --dh-shadow: 0 3px 6px var(--thf-shadow),
    0 12px 28px color-mix(in srgb, var(--thf-heading) 16%, transparent);
}

html:not([data-theme="dark"]) .dh .dh-welcome {
  background: color-mix(in srgb, var(--thf-accent) 4%, var(--thf-surface));
}

/* Restore the original textured card identities inside the new layouts.
   Local text tokens keep all headings, metadata, dividers and controls legible.
   These historical brand colors apply only in light mode. */
html:not([data-theme="dark"]) .dh :is(.dh-photos, .dh-study) {
  --thf-heading: #ffffff;
  --thf-text: #E7D9C4;
  --thf-text-2: #C9A227;
  --thf-link: #BD926F;
  --thf-border: rgba(231, 217, 196, .25);
  --thf-border-strong: rgba(231, 217, 196, .45);
  --thf-surface: transparent;
  /* Keep the shadow dark despite this card's light heading token. */
  --dh-shadow: 0 3px 6px var(--thf-shadow), 0 12px 28px rgba(47, 45, 44, .16);
}

html:not([data-theme="dark"]) .dh .dh-photos {
  background:
    radial-gradient(circle at calc(100% - 30px) calc(100% - 30px), rgba(201, 162, 39, .15) 0 60px, transparent 61px),
    radial-gradient(circle at 20px 20px, rgba(74, 103, 65, .2) 0 40px, transparent 41px),
    radial-gradient(circle, rgba(189, 146, 111, .15) 0 1.5px, transparent 1.6px) 0 0 / 20px 20px,
    linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 50%, #3a5331 100%);
}

html:not([data-theme="dark"]) .dh .dh-study {
  background:
    radial-gradient(circle at calc(100% - 55px) 35px, rgba(201, 162, 39, .28), transparent 130px),
    repeating-linear-gradient(180deg, rgba(201, 162, 39, .088) 0 1px, transparent 1px 14px),
    linear-gradient(135deg, #14100c 0%, #2b2118 55%, #4a3722 100%);
}

html:not([data-theme="dark"]) .dh .encounter-fundraiser-card {
  background: linear-gradient(145deg,
    color-mix(in srgb, var(--thf-accent-2) 10%, var(--thf-surface)),
    color-mix(in srgb, var(--thf-accent-2) 22%, var(--thf-surface)));
}

html:not([data-theme="dark"]) .dh .encounter-fundraiser-card,
html:not([data-theme="dark"]) body.dashboard-page .ff-dashboard-card {
  box-shadow: 0 3px 6px var(--thf-shadow),
    0 12px 28px color-mix(in srgb, var(--thf-heading) 16%, transparent);
}

/* =============================================================================
   THE BIBLE-IN-A-YEAR BANNER REACHES THE SAME EDGE AS THE CARDS.

   .library-grid-container pads its contents by 20px, and every .row inside it
   pulls back out by 12px on each side. The top cards and the twelve library
   cards then zero their own column padding, so all of them paint 12px PAST the
   container padding. The Bible-in-a-Year banner is a plain block, not a .row,
   so it never gets the -12px pull and sat 12px inside every card above and
   below it, which is the uneven left and right edge the owner saw. Give it the
   cards' reach (.dh does the same for the top cards and course rows). Phones
   are untouched: the banner is display:none below 768px (the .phone-sliver
   replaces it).
   ============================================================================= */
@media (min-width: 768px) {
  body.dashboard-page .biay-dash-banner {
    margin-right: -12px;
    margin-left: -12px;
  }
}

/* Profile dialogs must follow the active theme, including the legacy
   dashboard-page.css white surface override. */
#profileChoiceModal .modal-content,
#profileUpdateModal .modal-content {
  background: var(--thf-surface) !important;
  color: var(--thf-text);
}
#profileChoiceModal .close,
#profileUpdateModal .close {
  color: var(--thf-text);
  text-shadow: none;
  min-width: 44px;
  min-height: 44px;
}

#profileChoiceModal .modal-body .btn {
  min-height: 48px;
  white-space: normal;
}

/* Keep account settings easy to find from signed-in tablet Home. */
.dh .dh-link-account { grid-column: 1 / -1; min-height: 52px; }

/* Selected Catacomb Light artwork, with real accessible text and one link.
   This photographic surface stays dark in both themes; the existing primary
   button text token supplies its light lettering. */
.early-christian-chat-card {
  display: flex;
  align-items: center;
  min-height: 340px;
  margin-bottom: 1.25rem;
  padding: clamp(28px, 4vw, 58px);
  position: relative;
  overflow: hidden;
  isolation: isolate;
  border: 1px solid var(--thf-accent);
  border-radius: 22px;
  background: var(--thf-footer-bg) url('../images/dashboard/early-christian-chat-catacomb.webp') center / cover no-repeat;
  color: var(--primary-btn-text);
  text-decoration: none;
  box-shadow: 0 10px 30px var(--thf-shadow);
}
.early-christian-chat-card::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(90deg, color-mix(in srgb, var(--thf-footer-bg) 36%, transparent), transparent 72%);
}
.early-christian-chat-card__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 65%;
}
.early-christian-chat-card__eyebrow {
  color: var(--thf-accent-2);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .22em;
  line-height: 1.5;
  text-transform: uppercase;
}
.early-christian-chat-card__title {
  margin-top: 20px;
  color: color-mix(in srgb, var(--primary-btn-text) 94%, var(--thf-accent-2));
  font-family: 'Crimson Pro', Georgia, serif;
  font-size: clamp(30px, 3.7vw, 54px);
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: -.02em;
}
.early-christian-chat-card__divider {
  display: block;
  width: min(280px, 76%);
  height: 1px;
  margin: 22px 0;
  position: relative;
  background: linear-gradient(90deg, var(--thf-accent), var(--thf-accent-2), transparent);
}
.early-christian-chat-card__divider::after {
  content: '';
  position: absolute;
  top: -3px;
  left: 54%;
  width: 7px;
  height: 7px;
  background: var(--thf-accent-2);
  transform: rotate(45deg);
}
.early-christian-chat-card__description {
  color: var(--primary-btn-text);
  font-family: 'Crimson Pro', Georgia, serif;
  font-size: clamp(18px, 1.8vw, 24px);
  line-height: 1.4;
}
.early-christian-chat-card__action {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 28px;
  min-height: 48px;
  max-width: 100%;
  margin-top: 28px;
  padding: 12px 22px;
  border: 1px solid var(--thf-accent-2);
  border-radius: 10px;
  background: linear-gradient(120deg, var(--thf-accent-2), var(--thf-accent));
  color: var(--thf-text);
  font-family: 'Crimson Pro', Georgia, serif;
  font-size: 21px;
  font-weight: 600;
  line-height: 1.25;
}
html[data-theme="dark"] .early-christian-chat-card__action { color: var(--tooltip-text); }
.early-christian-chat-card__action > span { font-family: Georgia, serif; font-size: 26px; }
.early-christian-chat-card:hover,
.early-christian-chat-card:focus-visible { color: var(--primary-btn-text); text-decoration: none; border-color: var(--thf-accent-2); }
.early-christian-chat-card:hover .early-christian-chat-card__action { background: var(--thf-accent-2); }
.early-christian-chat-card:focus-visible { outline: 3px solid var(--thf-accent-2); outline-offset: 4px; }
@media (min-width: 768px) {
  .early-christian-chat-card { margin-right: -12px; margin-left: -12px; }
}
@media (max-width: 767.98px) {
  .early-christian-chat-card { min-height: 300px; padding: 26px 24px; border-radius: 18px; background-position: 62% center; }
  .early-christian-chat-card::before { background: linear-gradient(90deg, color-mix(in srgb, var(--thf-footer-bg) 88%, transparent), color-mix(in srgb, var(--thf-footer-bg) 68%, transparent) 70%, color-mix(in srgb, var(--thf-footer-bg) 24%, transparent)); }
  .early-christian-chat-card__copy { width: 100%; }
  .early-christian-chat-card__eyebrow { font-size: 10px; letter-spacing: .17em; }
  .early-christian-chat-card__title { font-size: clamp(28px, 7.7vw, 42px); margin-top: 16px; }
  .early-christian-chat-card__divider { margin: 18px 0; }
  .early-christian-chat-card__description { max-width: 290px; font-size: 19px; }
  .early-christian-chat-card__action { margin-top: 22px; font-size: 19px; padding: 12px 18px; gap: 20px; }
}

/* Daniel's quiet personal shortcut beside his profile. */
.dh-calendar-shortcut { display: block; width: fit-content; padding: 4px 6px; color: var(--thf-text-2); font-size: 12px; line-height: 1.4; text-decoration: none; }
.dh .dh-calendar-shortcut { margin: 6px auto 0; }
.phone-dash .dh-calendar-shortcut { margin: -10px 0 12px auto; }
.dh-calendar-shortcut:hover { color: var(--thf-link); text-decoration: underline; }
.dh-calendar-shortcut:focus-visible { outline: 2px solid var(--thf-link); outline-offset: 2px; border-radius: 3px; }
