/* ============================================================
   v18-additions.css — Playtypus: new home-layout options and pinned
   category navigation, added alongside LayoutStyleManifest on the
   Playtyper side (see /mnt/skills or the Playtyper repo for the
   editor/prompt-generator half of this change).

   Load after ui-variants.css (same convention as v14-additions.css) —
   MUST be added to BOTH Playtypus.App/wwwroot/index.html and
   Playtypus.Web/wwwroot/index.html, and to Playtyper's
   preview-bridge.js asset list, or it silently never loads. All three
   are already updated as part of this same change; if you copy this
   file into a different host project, remember the fourth reference.
   ============================================================ */

/* ══════════════════════════════════════════════════════════════
   PINNED CATEGORY TABS  (Ui.CategoryNavPosition = "pinned")
   Reuses .category-tabs/.category-tab/.category-tab--active exactly as
   defined in ui.css for the FilterDrawer — this is only a positioning
   wrapper, not a new visual style, so the two stay visually consistent
   automatically instead of needing to be kept in sync by hand.
   ══════════════════════════════════════════════════════════════ */

.category-tabs-pinned {
  padding: var(--spacing-sm, 8px) var(--spacing-md, 16px) 0;
  margin-bottom: var(--spacing-sm, 8px);
}

.category-tabs-pinned .category-tabs {
  padding-bottom: var(--spacing-sm, 8px);
  border-bottom: 1px solid var(--color-border);
}

/* An "All" pseudo-tab so users can get back to the unfiltered feed
   without opening the drawer — the drawer's own list has no such
   affordance because clearing filters there already has a dedicated
   "Clear filters" button (see AppShell's empty-state). */
.category-tab--all-pseudo {
  font-weight: var(--font-weight-heading, 600);
}

/* ══════════════════════════════════════════════════════════════
   MAP HOME  (Ui.HomeLayout = "map")
   Plots activities that carry a "map" content block via the existing
   playtypusMap JS module (see playtypus-map.js — initMulti, added
   alongside this file). Activities without coordinates are listed
   below, grouped by category, so nothing in the pack becomes
   unreachable just because it lacks a pin.
   ══════════════════════════════════════════════════════════════ */

.map-home__canvas {
  width: 100%;
  height: 46vh; /* dvh fallback for browsers/webviews that don't support it */
  height: 46dvh;
  min-height: 260px;
  max-height: 420px;
  border-radius: var(--border-radius-lg, 18px);
  overflow: hidden;
  background: var(--color-surface-alt, var(--color-surface));
  margin-bottom: var(--spacing-md, 16px);
  /* premium-home.css polish (2026-07-26): subtle inset shadow so the
     canvas reads as "embedded in a card" like the rest of the app,
     rather than a flat rectangle. */
  box-shadow: inset var(--card-shadow, 0 1px 3px rgba(0,0,0,0.12));
}

/* premium-home.css polish (2026-07-26): warm gradient CTA (same technique
   as .card-visual--map) instead of a dashed "form field to fill in" look —
   white text/icon on color instead of grey on transparent. */
.map-home__consent {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--spacing-sm, 8px);
  width: 100%;
  height: 100%;
  border: none;
  border-radius: var(--border-radius-lg, 18px);
  background: linear-gradient(135deg, var(--color-primary-light, #6B65F0), var(--color-primary, #453FE9));
  cursor: pointer;
  color: rgba(255, 255, 255, 0.95);
  font: inherit;
  text-align: center;
  padding: var(--spacing-md, 16px);
  transition: filter 150ms ease;
}

.map-home__consent:hover { filter: brightness(1.08); }

.map-home__consent-icon {
  width: 28px;
  height: 28px;
  color: #fff;
}

.map-home__consent-title {
  color: #fff;
  font-weight: var(--font-weight-heading, 600);
  margin: 0;
}

.map-home__consent-notice { margin: 0; font-size: var(--font-size-sm, 0.875rem); opacity: 0.9; }

/* premium-home.css polish (2026-07-26): matches today-home__empty's
   icon+text+CTA warmth instead of a single line of grey text. */
.map-home__no-pins {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--spacing-sm, 8px);
  height: 100%;
  color: var(--color-text-muted);
  font-size: var(--font-size-sm, 0.875rem);
  text-align: center;
  padding: var(--spacing-md, 16px);
}

.map-home__no-pins-icon { font-size: 2.25rem; }

/* ── Pins-list (activities without coordinates) ──────────────────────────
   premium-home.css polish (2026-07-26): previously bare dashboard-tile
   buttons with no wrapper of their own — reused desktop-grid sizing
   verbatim and had no visual separation from the map above. This wrapper
   gives it its own single-column identity and a clear "more activities"
   heading before the per-category groups start. */
.map-home__pins-list {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-sm, 8px);
}

.map-home__pins-heading {
  font-size: var(--font-size-sm, 0.875rem);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
  margin: var(--spacing-sm, 8px) 0 0;
  padding-top: var(--spacing-md, 16px);
  border-top: 1px solid var(--color-border);
}

.map-home__pin-tile {
  flex-direction: row;
  justify-content: flex-start;
  text-align: left;
  min-height: 56px;
  width: 100%;
}
.map-home__pin-tile .dashboard-tile__icon { font-size: 1.5rem; }

.map-home__section-title {
  font-size: var(--font-size-sm, 0.875rem);
  font-weight: var(--font-weight-heading, 600);
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  margin: var(--spacing-md, 16px) 0 var(--spacing-sm, 8px);
}

/* premium-home.css polish (2026-07-26): Leaflet injects its own attribution
   control markup at runtime — this can only be styled globally by class,
   not from Razor. Same frosted-glass treatment as premium.css's B3
   (.detail-close-btn) instead of leaving Leaflet's own default styling.
   !important is load-order, not specificity, insurance: leaflet.css is
   fetched and appended to <head> by playtypus-map.js at runtime, so it
   always lands after this stylesheet and would otherwise win the cascade
   at equal specificity regardless of file order in index.html. */
.leaflet-control-attribution {
  background: rgba(0, 0, 0, 0.55) !important;
  color: rgba(255, 255, 255, 0.85) !important;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: var(--radius-sm, 6px);
  padding: 2px 6px !important;
}
.leaflet-control-attribution a { color: rgba(255, 255, 255, 0.95) !important; }

/* ══════════════════════════════════════════════════════════════
   TODAY HOME  (Ui.HomeLayout = "today")
   ══════════════════════════════════════════════════════════════ */

/* premium-home.css polish (2026-07-26): thin eyebrow above the heading,
   same uppercase/letter-spacing pattern as sections-home__row-title/
   dashboard-home__section-title — gives a sense of *which* day this is
   instead of the heading reading as static boilerplate. */
.today-home__date-eyebrow {
  font-size: var(--font-size-xs, 0.75rem);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
  margin: 0 0 var(--spacing-xs, 4px);
}

.today-home__heading {
  font-size: var(--font-size-lg, 1.125rem);
  font-weight: var(--font-weight-heading, 700);
  margin: 0 0 var(--spacing-xs, 4px);
}

.today-home__subheading {
  color: var(--color-text-muted);
  margin: 0 0 var(--spacing-md, 16px);
  font-size: var(--font-size-sm, 0.875rem);
}

.today-home__empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--spacing-sm, 8px);
  padding: var(--spacing-xl, 40px) var(--spacing-md, 16px);
  color: var(--color-text-muted);
  border-radius: var(--border-radius-lg, 18px);
}

.today-home__empty-icon { font-size: 2.25rem; }

/* premium-home.css polish (2026-07-26): the "all done" state previously
   shared the same neutral grey box as "not configured" — same color-mix
   technique as .btn-done so the two empty states read as visibly
   different (one is a good outcome, the other is a config gap). */
.today-home__empty--success {
  color: color-mix(in srgb, var(--color-done, #22c55e) 70%, #000);
  background: color-mix(in srgb, var(--color-done, #22c55e) 10%, transparent);
}

/* premium-home.css polish (2026-07-26): thin colored top border so
   "due today" tiles read as visually distinct from the generic dashboard
   grid they share a base class with. */
.today-home__tile {
  border-top: 3px solid var(--color-primary);
}

/* ══════════════════════════════════════════════════════════════
   MAGAZINE HOME  (Ui.HomeLayout = "magazine")
   ══════════════════════════════════════════════════════════════ */

.magazine-home__hero {
  position: relative;
  display: block;
  width: 100%;
  min-height: 260px;
  border-radius: var(--border-radius-xl, 28px);
  overflow: hidden;
  /* premium-home.css polish (2026-07-26): more breathing room before the
     "More" grid, proportionate to how much the hero dominates the view. */
  margin-bottom: var(--spacing-xl, 32px);
  background: var(--color-primary);
  border: none;
  padding: 0;
  cursor: pointer;
  text-align: left;
  /* premium-home.css polish (2026-07-26): same spring entrance as the
     other five views, via the shared keyframe in premium-home.css. */
  animation: premiumHomeEntrance 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.magazine-home__hero-media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* premium-home.css polish (2026-07-26): stronger scrim (was 0.65 at the
   base, now 0.75) plus a subtle radial corner vignette layered on top for
   filmic depth — text legibility over bright photos was the original
   goal, this pushes it from "adequate" to "considered". */
.magazine-home__hero-scrim {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 90% at 100% 0%, rgba(0,0,0,0.25) 0%, transparent 55%),
    linear-gradient(180deg, rgba(0,0,0,0.08) 0%, rgba(0,0,0,0.75) 100%);
}

.magazine-home__hero-body {
  position: relative;
  padding: var(--spacing-lg, 24px);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 260px;
  color: #fff;
}

/* premium-home.css polish (2026-07-26): a frosted chip background (same
   values as premium.css's B3) instead of relying on text-shadow alone for
   legibility — reads as a deliberate label rather than text floating on
   the photo. */
.magazine-home__hero-eyebrow {
  display: inline-block;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: var(--font-size-xs, 0.75rem);
  margin: 0 0 var(--spacing-sm, 8px);
  padding: 3px 10px;
  border-radius: var(--border-radius-pill, 999px);
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.magazine-home__hero-title {
  font-size: var(--font-size-xl, 1.375rem);
  font-weight: 700;
  margin: 0 0 var(--spacing-xs, 4px);
  text-shadow: 0 1px 4px rgba(0,0,0,0.4);
}

.magazine-home__hero-desc {
  margin: 0;
  font-size: var(--font-size-sm, 0.875rem);
  opacity: 0.92;
  max-width: 60ch;
}

.magazine-home__rest-title {
  font-size: var(--font-size-sm, 0.875rem);
  font-weight: var(--font-weight-heading, 600);
  color: var(--color-text-muted);
  margin: 0 0 var(--spacing-sm, 8px);
  /* premium-home.css polish (2026-07-26): the hero's own margin-bottom
     already grew (see above) — this adds a touch more on this side of
     the seam too, so the hero doesn't feel like it's crowding the grid
     below it. */
  padding-top: var(--spacing-xs, 4px);
}

/* ══════════════════════════════════════════════════════════════
   SEARCH HOME  (Ui.HomeLayout = "search")
   ══════════════════════════════════════════════════════════════ */

.search-home__field-wrap {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm, 8px);
  padding: var(--spacing-sm, 8px) var(--spacing-md, 16px);
  border: 1.5px solid var(--color-border);
  border-radius: var(--border-radius-lg, 18px);
  background: var(--color-surface);
  margin-bottom: var(--spacing-md, 16px);
}

.search-home__field-wrap {
  transition: box-shadow 180ms ease, border-color 180ms ease;
}
.search-home__field-wrap:focus-within {
  border-color: var(--color-primary);
  /* premium-home.css polish (2026-07-26): a soft lift on focus, not just
     a border-color swap — matches how focus/hover reads everywhere else
     in the app. */
  box-shadow: var(--card-shadow-hover);
}

.search-home__field {
  flex: 1;
  border: none;
  outline: none;
  background: none;
  font: inherit;
  color: var(--color-text);
  min-width: 0;
}

.search-home__icon { color: var(--color-text-muted); flex-shrink: 0; }

.search-home__shortcuts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-xs, 6px);
  margin-bottom: var(--spacing-lg, 24px);
}

.search-home__shortcut {
  padding: var(--spacing-xs, 6px) var(--spacing-sm, 10px);
  border-radius: var(--border-radius-pill, 999px);
  border: 1px solid var(--color-border);
  background: var(--color-surface-alt, var(--color-surface));
  font-size: var(--font-size-sm, 0.875rem);
  cursor: pointer;
  color: var(--color-text);
}

/* premium-home.css polish (2026-07-26): lift/press physics come from the
   shared .premium-hover-lift class (see SearchHomeView.razor markup) —
   only the border-color swap is specific enough to this element to stay
   here. */
.search-home__shortcut:hover { border-color: var(--color-primary); }

.search-home__hint {
  color: var(--color-text-muted);
  font-size: var(--font-size-sm, 0.875rem);
  text-align: center;
  padding: var(--spacing-lg, 24px) 0;
}

/* premium-home.css polish (2026-07-26): the activity count reads as
   boilerplate grey text otherwise — bolding just the number (not the
   whole sentence) needed its own wrapping span, see SearchHomeView.razor. */
.search-home__hint-count {
  font-weight: 800;
  color: var(--color-text);
}

/* ══════════════════════════════════════════════════════════════
   SECTIONED HOME  (Ui.HomeLayout = "sections")
   One horizontally-scrolling row per category, "shelf" style.
   ══════════════════════════════════════════════════════════════ */

.sections-home__row { margin-bottom: var(--spacing-lg, 24px); }

.sections-home__row-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 0 var(--spacing-md, 16px);
  margin-bottom: var(--spacing-sm, 8px);
}

.sections-home__row-title {
  font-size: var(--font-size-md, 1rem);
  font-weight: var(--font-weight-heading, 700);
  margin: 0;
  display: flex;
  align-items: center;
  gap: var(--spacing-xs, 6px);
}

/* premium-home.css polish (2026-07-26): the catch-all "Other" row (no
   emoji, no real category identity) previously looked like just another
   category — a muted heading reads it correctly as a fallback bucket. */
.sections-home__row-title--muted {
  color: var(--color-text-muted);
}

.sections-home__row-more {
  font-size: var(--font-size-sm, 0.875rem);
  color: var(--color-primary);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  font: inherit;
}

/* premium-home.css polish (2026-07-26): the count reads as metadata
   rather than filler when it carries a bit more visual weight than the
   "See all" label around it. */
.sections-home__row-more-count {
  font-weight: 800;
}

.sections-home__row-scroll {
  overflow-x: auto;
  padding: 0 var(--spacing-md, 16px) var(--spacing-xs, 4px);
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  /* premium-home.css polish (2026-07-26): matches the row's own side
     padding so scroll-snap never leaves the first card half-clipped
     against the viewport edge. */
  scroll-padding-left: var(--spacing-md, 16px);
}

.sections-home__row-scroll::-webkit-scrollbar { display: none; }

/* SectionedHomeView reuses ActivityListRenderer's normal "card" output
   (.activity-grid full of .activity-card) unchanged — this turns that one
   grid into a horizontal shelf purely in CSS, so every card variant
   (locked/quiz/favourite/wall/etc.) keeps working with zero duplicated
   Razor logic. */
.sections-home__row-scroll .activity-grid {
  display: flex;
  gap: var(--spacing-sm, 8px);
}

.sections-home__row-scroll .activity-card {
  flex: 0 0 auto;
  width: 220px;
  scroll-snap-align: start;
}

@media (min-width: 640px) {
  .sections-home__row-scroll .activity-card { width: 260px; }
}

/* ══════════════════════════════════════════════════════════════
   REDUCED-MOTION / SMALL-SCREEN SAFETY
   ══════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  .sections-home__row-scroll { scroll-behavior: auto; }
  /* premium-home.css polish (2026-07-26): magazine-home__hero applies the
     shared entrance keyframe directly (not via the .premium-home-entrance
     utility class), so it needs its own opt-out here too. */
  .magazine-home__hero { animation: none; }
}

@media (max-width: 480px) {
  .magazine-home__hero,
  .magazine-home__hero-body { min-height: 200px; }
}

/* ══════════════════════════════════════════════════════════════
   SMALL-PHONE BREAKPOINT (2026-07-26, premium-home.css strategy §4)
   dashboard-home__grid/dashboard-tile (shared with today-home via the
   same classes) already got their <380px pass in v14-additions.css.
   This covers the three views here that had no dedicated mobile
   breakpoint at all before now: map, search, sections.
   ══════════════════════════════════════════════════════════════ */

@media (max-width: 380px) {
  .map-home__consent-icon { width: 22px; height: 22px; }
  .map-home__consent-title { font-size: var(--font-size-sm, 0.875rem); }
  .map-home__pin-tile { min-height: 64px; } /* larger tap target than the 56px baseline */

  .search-home__field-wrap { padding: var(--spacing-xs, 6px) var(--spacing-sm, 10px); }
  .search-home__shortcuts { gap: var(--spacing-xs, 4px); }

  .sections-home__row-scroll .activity-card { width: 168px; }
}
