/* chasemahony.com styles: Design batch B1 "Gallery" (Concept A, picked by Chase 2026-10-06).
   Replaces site/styles.css wholesale. Owner: Design (design/batches/). Selectors: no ids/testids/labels renamed. */

/* ---------- 1. Tokens (light, then dark) ---------- */
:root {
  color-scheme: light dark;
  --bg: #f6f3ee; --fg: #1b1a17; --muted: #5f5a52; --card: #fffdf9; --line: #e3ddd2; --line-strong: #c9bfae;
  --control-border: #8a8174;   /* CRD-B1 MUST: form-control edges (search, selects, buttons, chips) >= 3:1 (3.47:1 on --bg, 3.78:1 on --card) */
  --accent: #c2410c;           /* links, focus ring, Alpha/Beta badge, Pause pressed: 5.1:1 on --card */
  --ok: #1f7a50;               /* Live badge: CRD-6, was #2f9e6a (3.3:1) */
  --m1: #efe9df; --m2: #fffdf9; --m3: #e3ddd2; --m4: #c9bfae;   /* mock/placeholder surfaces */
  --tick: #2f9e6a;             /* decorative only (mock ticks/buttons), never text */
  --shadow: 0 14px 30px -18px rgba(60, 40, 10, .45);
  --radius: 18px; --radius-s: 12px;
  --font-body: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-display: ui-serif, Georgia, "Times New Roman", serif;
  --ease: cubic-bezier(.2, .7, .2, 1); --t-fast: .15s;
  --wrap: 1180px; --gutter: 16px;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #171512; --fg: #f3eee6; --muted: #b0a796; --card: #211e1a; --line: #36312a; --line-strong: #6b6153;
    --control-border: #857a6b;   /* CRD-B1: 4.33:1 on --bg, 3.95:1 on --card */
    --accent: #fb8a4c; --ok: #4cc08a;
    --m1: #2a2621; --m2: #332e28; --m3: #463f36; --m4: #6b6153; --tick: #3fae7c;
    --shadow: 0 14px 30px -18px rgba(0, 0, 0, .8);
  }
}

/* ---------- 2. Base + layout ---------- */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body { margin: 0; background: var(--bg); color: var(--fg); font: 16px/1.55 var(--font-body); }
.site-header, main, .site-footer { max-width: var(--wrap); margin: 0 auto; padding: 0 var(--gutter); }
.site-header { padding-top: 56px; padding-bottom: 28px; }
.site-header h1 { margin: 0; font: 600 clamp(2.2rem, 6vw, 3.6rem)/1.05 var(--font-display); letter-spacing: -.01em; }
.tagline { color: var(--muted); font-size: 1.15rem; margin: 10px 0 0; }
a { color: var(--accent); text-underline-offset: .15em; }
:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

/* ---------- 3. Controls bar ---------- */
.controls { display: flex; flex-wrap: wrap; gap: 14px 18px; align-items: end; padding: 18px 0;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.control { display: flex; flex-direction: column; gap: 6px; min-width: 0; margin: 0; padding: 0; border: 0;
  font-size: .85rem; color: var(--muted); }
.control legend { padding: 0; margin-bottom: 6px; }
.control-search { flex: 1 1 100%; }                 /* row 1: search */
.control-category { flex: 1 1 100%; }               /* row 2: chips; row 3: selects, Clear, Pause motion */
.control input, .control select, .controls button {
  font: inherit; font-size: .95rem; color: var(--fg); background: var(--card);
  border: 1px solid var(--control-border); border-radius: 999px; padding: 9px 16px; min-height: 44px;
  transition: border-color var(--t-fast), background-color var(--t-fast), color var(--t-fast);
}
.control input { width: 100%; max-width: 560px; }
.control select { padding-right: 12px; max-width: 100%; }
.controls button { cursor: pointer; display: inline-flex; align-items: center; gap: 8px; }
.control input:hover, .control select:hover, .controls button:hover { border-color: var(--fg); }   /* CRD-B1: --line stays for decorative tile/card edges */

/* Category chips (BOARD #9). Container keeps id/testid "category"; one button per option, aria-pressed. */
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chips .chip { padding: 8px 14px; font-size: .92rem; }
.chips .chip[aria-pressed="true"] { background: var(--fg); color: var(--bg); border-color: var(--fg); }

/* Pause motion toggle (TILE-MOTION-SPEC §5): last item, pushed right on the selects row. */
#motion-toggle { margin-left: auto; }
#motion-toggle svg { width: 14px; height: 14px; flex: none; }
#motion-toggle .icon-play { display: none; }
#motion-toggle[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); }
#motion-toggle[aria-pressed="true"] .icon-pause { display: none; }
#motion-toggle[aria-pressed="true"] .icon-play { display: inline; }

#result-count { color: var(--muted); font-size: .9rem; margin: 18px 0; }
#empty { color: var(--muted); padding: 32px 0 64px; }

/* ---------- 4. Grid + tiles ---------- */
.grid { list-style: none; margin: 0 0 64px; padding: 0; display: grid; gap: 28px;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 330px), 1fr)); }
.tile-item { min-width: 0; }
.tile { display: flex; flex-direction: column; height: 100%; color: inherit; text-decoration: none;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
  transition: transform var(--t-fast) ease-out, box-shadow var(--t-fast) ease-out, border-color var(--t-fast); }
a.tile { color: inherit; }
a.tile:hover, a.tile:focus-visible { transform: translateY(-3px); box-shadow: var(--shadow); border-color: var(--line-strong); }
.tile-nolink:hover, .tile-nolink:focus-visible { border-color: var(--line-strong); }   /* not a link: no lift */
.tile-media { display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: cover; background: var(--m1);
  border-bottom: 1px solid var(--line); }
.tile-text { display: flex; flex-direction: column; gap: 8px; padding: 16px 18px 18px; flex: 1; }
.tile-name { margin: 0; font: 600 1.3rem/1.2 var(--font-display); overflow-wrap: anywhere; }
.tile-tagline { margin: 0; color: var(--muted); min-height: 3.1em; }   /* 2 lines of a <=60-char one-liner */
.tile-meta { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; font-size: .78rem; }
.tile-category { color: var(--muted); }
.tile-status, .tile-draft { padding: 2px 10px; border-radius: 999px; border: 1px solid currentColor; white-space: nowrap; color: var(--muted); }
/* Status badges (Marketing #2). Dev adds class tile-status--<status id> (B1 README step 3). */
.tile-status--live { color: var(--ok); }
.tile-status--alpha, .tile-status--beta { color: var(--accent); }
.tile-status--in-development, .tile-status--private { color: var(--muted); }
.tile-draft { border-style: dashed; color: var(--accent); }   /* "Unconfirmed", dev server only */
.tile-tags { margin: 0; display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: .8rem; color: var(--muted); }
.tile-tag::before { content: '#'; }
.tile-credit { margin: 0; font-size: .78rem; color: var(--muted); }
.tile-soon { margin: 0 18px 18px; font-size: .82rem; color: var(--muted); }

/* ---------- 5. Footer + privacy page ---------- */
.site-footer { color: var(--muted); font-size: .85rem; padding-top: 8px; padding-bottom: 40px; }
.site-footer a { color: inherit; }
.prose { max-width: 680px; padding-bottom: 48px; }
.prose h1 { font: 600 clamp(1.9rem, 5vw, 2.6rem)/1.1 var(--font-display); margin: 8px 0 12px; }
.prose h2 { font: 600 1.25rem/1.3 var(--font-display); margin: 32px 0 8px; }

/* ---------- 6. Phones ---------- */
@media (max-width: 600px) {
  .site-header { padding-top: 36px; }
  /* CRD-B1 SHOULD: 6px room on every side for the 3px+2px focus ring (scroll box clips overflow);
     15% end padding > 12% fade, so the last chip scrolls fully clear of the fade, and on wide phones nothing sits under it. */
  .chips { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
    padding: 6px 15% 6px 6px; margin: -6px 0 -6px -6px; scroll-padding-inline: 6px 15%;
    -webkit-mask: linear-gradient(90deg, #000 88%, transparent); mask: linear-gradient(90deg, #000 88%, transparent); }
  .chips::-webkit-scrollbar { display: none; }
  .chips .chip { flex: none; }
  .control:has(select) { flex: 1 1 140px; }
  .control select { width: 100%; }
  #motion-toggle { margin-left: 0; }
  .grid { gap: 20px; }
}

/* ---------- 7. Tile motion: placeholders + per-product CSS mocks ----------
   Rules (TILE-MOTION-SPEC §1-4, CRD-1, CRD-7):
   - animate transform/opacity only; no width/top/left in keyframes.
   - every animation starts at a negative delay (--t0 per mock, --d per element) so frame 0 is mid-action:
     paused-from-load (reduced motion or Pause motion) shows a meaningful still, no blank frame. */
.placeholder { position: relative; overflow: hidden; }

/* 7a. Generic fallbacks (products with no clip and no mock) */
.placeholder-bars, .placeholder-scroll, .placeholder-pulse { background: var(--m1); }
.placeholder > span { position: absolute; left: 10%; height: 10%; border-radius: 4px; background: var(--m4); }
.placeholder-bars span { bottom: 12%; width: 12%; height: 30%; transform-origin: bottom; background: var(--accent); opacity: .75; animation: ph-bar 1.4s ease-in-out infinite; }
.placeholder-bars span:nth-child(2) { left: 30%; --d: -.3s; }
.placeholder-bars span:nth-child(3) { left: 50%; --d: -.6s; }
.placeholder-bars span:nth-child(4) { left: 70%; --d: -.9s; }
@keyframes ph-bar { 0%, 100% { transform: scaleY(.3); } 50% { transform: scaleY(1.6); } }
.placeholder-scroll span { top: 105%; width: 80%; animation: ph-scroll 3s linear infinite; }
.placeholder-scroll span:nth-child(2) { width: 60%; --d: -.75s; }
.placeholder-scroll span:nth-child(3) { width: 70%; --d: -1.5s; }
.placeholder-scroll span:nth-child(4) { width: 50%; --d: -2.25s; }
@keyframes ph-scroll { from { transform: none; } to { transform: translateY(-1200%); } }   /* was top:105%→-15% (layout) */
.placeholder-pulse span { top: 40%; left: 40%; width: 20%; height: 20%; border-radius: 50%; border: 3px solid var(--accent); background: transparent; animation: ph-pulse 2s ease-out infinite; }
.placeholder-pulse span:nth-child(2) { --d: -.5s; }
.placeholder-pulse span:nth-child(3) { --d: -1s; }
.placeholder-pulse span:nth-child(4) { --d: -1.5s; }
@keyframes ph-pulse { from { transform: scale(.2); opacity: 1; } to { transform: scale(3); opacity: 0; } }

/* 7b. Per-product mocks (CLIP-PLAN method B). Markup: design/batches/B1-gallery/mocks.md. Fake data only (L-006). */
.mock * { position: absolute; }
/* heatseeker: playlist URL typed, cart rows tick in */
.mock-heatseeker { background: var(--m1); --t0: 3.6s; }
.mock-heatseeker .bar { left: 8%; top: 10%; width: 84%; height: 12%; border-radius: 6px; background: var(--m3); }
.mock-heatseeker .bar::after { content: ""; position: absolute; left: 4%; top: 35%; height: 30%; width: 60%; border-radius: 3px; background: var(--m4);
  transform-origin: left; animation: mk-type 6s steps(12) infinite; animation-delay: calc(0s - var(--t0)); }
.mock-heatseeker .row { left: 8%; width: 84%; height: 11%; border-radius: 5px; background: var(--m2); animation: mk-rowin 6s infinite; animation-delay: calc(var(--d, 0s) - var(--t0)); }
.mock-heatseeker .row::before { content: ""; position: absolute; left: 3%; top: 25%; width: 8%; height: 50%; border-radius: 3px; background: var(--m4); }
.mock-heatseeker .row::after { content: ""; position: absolute; right: 4%; top: 30%; width: 6%; height: 40%; border-radius: 50%; background: var(--tick);
  animation: mk-tick 6s infinite; animation-delay: calc(var(--d, 0s) - var(--t0)); }
.mock-heatseeker .r1 { top: 30%; } .mock-heatseeker .r2 { top: 45%; --d: .35s; } .mock-heatseeker .r3 { top: 60%; --d: .7s; } .mock-heatseeker .r4 { top: 75%; --d: 1.05s; }
@keyframes mk-type { 0% { transform: scaleX(0); } 25%, 100% { transform: scaleX(1); } }
@keyframes mk-rowin { 0%, 28% { opacity: 0; transform: translateX(-8%); } 36%, 92% { opacity: 1; transform: none; } 100% { opacity: 0; } }
@keyframes mk-tick { 0%, 45% { transform: scale(0); } 52%, 92% { transform: scale(1); } 100% { transform: scale(0); } }
/* dead-sun: artist site scrolls, waveform pulses (fixed night palette in both themes) */
.mock-dead-sun { background: linear-gradient(160deg, #160f1f, #3a1430); --t0: 1s; }
.mock-dead-sun .page { left: 10%; top: 0; width: 80%; height: 220%; animation: mk-page 7s ease-in-out infinite; }
.mock-dead-sun .hero { left: 0; top: 4%; width: 100%; height: 22%; border-radius: 6px; background: radial-gradient(circle at 70% 40%, #ff7a3d, #7a1d4a 60%, transparent 61%), #24142c; }
.mock-dead-sun .wave { left: 0; top: 30%; width: 100%; height: 10%; display: flex; gap: 3%; align-items: center; }
.mock-dead-sun .wave i { position: relative; flex: 1; height: 100%; border-radius: 2px; background: #ff9e5e; animation: mk-wave 1.1s ease-in-out infinite; }
.mock-dead-sun .wave i:nth-child(2n) { --d: -.4s; } .mock-dead-sun .wave i:nth-child(3n) { --d: -.7s; }
.mock-dead-sun .card { width: 30%; height: 16%; top: 46%; border-radius: 5px; background: #3b2440; }
.mock-dead-sun .c1 { left: 0; } .mock-dead-sun .c2 { left: 35%; } .mock-dead-sun .c3 { left: 70%; } .mock-dead-sun .card.b { top: 66%; }
@keyframes mk-page { 0%, 15% { transform: none; } 50%, 65% { transform: translateY(-40%); } 100% { transform: none; } }
@keyframes mk-wave { 0%, 100% { transform: scaleY(.25); } 50% { transform: scaleY(1); } }
/* kawaiicatattack: a cat walks across a phone home screen */
.mock-kawaiicatattack { background: linear-gradient(135deg, #bfe3ff, #ffd6e8); --t0: 2.5s; }
.mock-kawaiicatattack .ph { left: 36%; top: 6%; width: 28%; height: 88%; border-radius: 14px; background: #1d2433; box-shadow: 0 0 0 3px #0f131c; overflow: hidden; }
.mock-kawaiicatattack .ic { width: 22%; height: 12%; border-radius: 4px; background: #5d7bd6; }
.mock-kawaiicatattack .ic:nth-child(1) { left: 12%; top: 12%; } .mock-kawaiicatattack .ic:nth-child(2) { left: 39%; top: 12%; background: #e8735b; }
.mock-kawaiicatattack .ic:nth-child(3) { left: 66%; top: 12%; background: #55b685; } .mock-kawaiicatattack .ic:nth-child(4) { left: 12%; top: 30%; background: #d8b84a; }
.mock-kawaiicatattack .ic:nth-child(5) { left: 39%; top: 30%; background: #a46ad8; } .mock-kawaiicatattack .ic:nth-child(6) { left: 66%; top: 30%; background: #4fb3c8; }
.mock-kawaiicatattack .cat { left: -30%; top: 58%; width: 30%; height: 14%; animation: mk-walk 6s ease-in-out infinite; }
.mock-kawaiicatattack .cat b { left: 0; top: 30%; width: 70%; height: 60%; border-radius: 40% 40% 30% 30%; background: #f2a65a; }
.mock-kawaiicatattack .cat s { left: 58%; top: 0; width: 38%; height: 62%; border-radius: 50%; background: #f2a65a; }
.mock-kawaiicatattack .cat s::before, .mock-kawaiicatattack .cat s::after { content: ""; position: absolute; top: -22%; width: 30%; height: 45%; background: #f2a65a; clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.mock-kawaiicatattack .cat s::before { left: 8%; } .mock-kawaiicatattack .cat s::after { right: 8%; }
.mock-kawaiicatattack .cat u { left: -18%; top: 20%; width: 24%; height: 14%; border-radius: 4px; background: #f2a65a; transform-origin: right; animation: mk-tail .6s ease-in-out infinite alternate; }
@keyframes mk-walk { 0% { transform: none; } 55%, 85% { transform: translateX(250%); } 100% { transform: translateX(420%); } }
@keyframes mk-tail { to { transform: rotate(-30deg); } }
/* applyamend: a broken job application gets fixed. Each field starts flagged (red ring, entry jumbled),
   then its entry snaps into place and the flag clears, one field after another; Submit lights up once all are fixed.
   Still frame (--t0 2s): first fields fixed, last one still broken. --bad is decorative only, never text. */
.mock-applyamend { background: var(--m1); --t0: 2s; --bad: #d0453a; }
.mock-applyamend .f { left: 14%; width: 72%; height: 11%; border-radius: 5px; background: var(--m2); border: 1px solid var(--m3); }
.mock-applyamend .f::before { content: ""; position: absolute; inset: -2px; border: 2px solid var(--bad); border-radius: 6px;
  animation: mk-flag 6s infinite; animation-delay: calc(var(--d, 0s) - var(--t0)); }
.mock-applyamend .f::after { content: ""; position: absolute; left: 3%; top: 35%; height: 30%; width: 55%; border-radius: 3px; background: var(--m4);
  transform-origin: left; animation: mk-fix 6s infinite; animation-delay: calc(var(--d, 0s) - var(--t0)); }
.mock-applyamend .f1 { top: 10%; } .mock-applyamend .f2 { top: 26%; --d: .5s; } .mock-applyamend .f3 { top: 42%; --d: 1s; } .mock-applyamend .f4 { top: 58%; --d: 1.5s; }
.mock-applyamend .go { left: 14%; top: 76%; width: 28%; height: 13%; border-radius: 6px; background: var(--tick); animation: mk-glow 6s infinite; }
@keyframes mk-fix { 0%, 15% { transform: translate(28%, 55%) rotate(-8deg) scaleX(.6); } 25%, 92% { transform: none; } 100% { transform: translate(28%, 55%) rotate(-8deg) scaleX(.6); } }
@keyframes mk-flag { 0%, 15% { opacity: 1; } 25%, 92% { opacity: 0; } 100% { opacity: 1; } }
@keyframes mk-glow { 0%, 55% { opacity: .35; transform: none; } 65%, 90% { opacity: 1; transform: scale(1.06); } 100% { opacity: .35; } }
/* ai-team-playbook: task cards move across a three-column board */
.mock-ai-team-playbook { background: var(--m1); --t0: 1s; }
.mock-ai-team-playbook .col { top: 8%; width: 28%; height: 84%; border-radius: 6px; background: var(--m2); }
.mock-ai-team-playbook .k1 { left: 4%; } .mock-ai-team-playbook .k2 { left: 36%; } .mock-ai-team-playbook .k3 { left: 68%; }
.mock-ai-team-playbook .lamp { left: 8%; top: 5%; width: 12%; height: 7%; border-radius: 50%; background: #e0a03a; }
.mock-ai-team-playbook .k3 .lamp { background: var(--tick); }
.mock-ai-team-playbook .card { left: 7%; width: 22%; height: 16%; border-radius: 4px; background: var(--m4); animation: mk-move 6s ease-in-out infinite; }
.mock-ai-team-playbook .q1 { top: 24%; } .mock-ai-team-playbook .q2 { top: 44%; --d: -2s; } .mock-ai-team-playbook .q3 { top: 64%; --d: -4s; }
@keyframes mk-move { 0%, 20% { transform: none; } 35%, 55% { transform: translateX(145%); } 70%, 90% { transform: translateX(290%); } 100% { transform: translateX(290%); opacity: 0; } }

/* 7c. Start every loop mid-action (beats the animation shorthands above; doubled class = higher specificity). */
.tile-media.placeholder.placeholder *, .tile-media.placeholder.placeholder *::before, .tile-media.placeholder.placeholder *::after {
  animation-delay: calc(var(--d, 0s) - var(--t0, 0s)); }

/* ---------- 8. Pause motion + reduced motion (TILE-MOTION-SPEC §3-5) ----------
   Placeholders/mocks: paused (on their mid-action still) when the site toggle is on (html.motion-off),
   when the OS asks for reduced motion, or when app.js marks them off-screen (.is-paused, optional).
   Hover or keyboard focus on the tile plays them (explicit intent), matching the spec table rows 4 and 6. */
.motion-off .placeholder *, .motion-off .placeholder *::before, .motion-off .placeholder *::after,
.placeholder.is-paused *, .placeholder.is-paused *::before, .placeholder.is-paused *::after { animation-play-state: paused !important; }
@media (prefers-reduced-motion: reduce) {
  .tile, .controls button, .control input, .control select { transition: none; }
  a.tile:hover, a.tile:focus-visible { transform: none; }
  .placeholder *, .placeholder *::before, .placeholder *::after { animation-play-state: paused !important; }
}
.tile:hover .placeholder *, .tile:hover .placeholder *::before, .tile:hover .placeholder *::after,
.tile:focus-visible .placeholder *, .tile:focus-visible .placeholder *::before, .tile:focus-visible .placeholder *::after { animation-play-state: running !important; }

/* ---------- 9. Utilities ---------- */
/* Screen-reader-only text (Dev 0.1.2, BOARD #16 / CR-1 S9: tile name " (opens <host>)"). Carried in B1 so site/styles.css stays a verbatim copy. */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
