/* Catdex: warm cream pages, white cards, sky blue for the brand, deep blue for actions, ink for words, peach for small rewards.
   One reading column (max 600px). The cat from the app icon (Ming) is the only decoration that repeats. */
:root{
  /* surfaces: cream page, white cards, a slightly deeper cream for quiet fills */
  --bg:#fff9f0; --card:#ffffff; --surface:#f7efe3; --tint:#e6f3fe; --photo-empty:#f3eadd;
  /* text */
  --text:#263247; --text-2:#5b6476;
  /* brand and action: sky is the brand colour, deep blue fills buttons, a darker deep blue carries blue text */
  --action:#2270bb; --action-fill:#2879c7; --action-hover:#1f69b0; --on-action:#ffffff; --sky:#67b7f7; --selected:#e6f3fe; --reward:#ffb39b; --reward-bg:#ffede6; --on-reward:#263247;
  /* lines */
  --divider:#efe5d6; --control:#8c8f98; --focus:#2270bb; --grid-line:rgb(103 183 247 / .11);
  /* status */
  --ok:#25704a; --ok-bg:#e6f4eb; --warn:#80540a; --warn-bg:#fff3dd; --err:#b4361f; --err-bg:#fdeae5; --on-err:#ffffff; --swatch-edge:rgb(0 0 0 / .2); --img-edge:rgb(0 0 0 / .1); --shadow-chip:0 1px 2px rgb(38 50 71 / .12); --shadow-fab:0 1px 3px rgb(38 50 71 / .2),0 4px 8px 3px rgb(38 50 71 / .12);
  /* the tab bar is a solid white pill, not glass */
  --bar:#ffffff; --bar-edge:0 0 0 1px #efe5d6;
  /* fur pastels, behind the drawn cats */
  --peach:#ffe9dc; --lilac:#eeeaf6; --skyt:#e3f1fd; --butter:#fff0d0; --mint:#e2f3e8; --blush:#fde9ed;
  /* map */
  --map-bg:#fffdf8; --map-zone:#f6eee2; --map-bldg:#ffffff; --map-water:#cfe6fa; --map-label:#5b6476; --map-walk:#e7d6bd; --map-walk-line:#b89a72;
  --scrim:rgb(38 50 71 / .36); --lift:0 1px 2px rgb(38 50 71 / .06),0 10px 24px -14px rgb(38 50 71 / .28);
  --font:-apple-system,BlinkMacSystemFont,"SF Pro Text",system-ui,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --display:"Gabarito",ui-rounded,-apple-system,system-ui,sans-serif;
  --r-sm:10px; --r-md:16px; --r-lg:24px; --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px; --s7:48px;
  --ease-out:cubic-bezier(.23,1,.32,1); --ease-in-out:cubic-bezier(.77,0,.175,1); --ease-drawer:cubic-bezier(.32,.72,0,1);
  /* the only curve that overshoots: for rare reward moments (card deal, cat meet, guardian card, done check). Never on Ming. */
  --ease-pop:cubic-bezier(.3,1.35,.6,1);
  --ease:var(--ease-out);
  /* guardian card */
  --card-shadow:drop-shadow(0 1px 2px rgb(38 50 71 / .06)) drop-shadow(0 12px 24px rgb(38 50 71 / .08));
}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
  --bg:#141b26; --card:#1c2533; --surface:#222c3b; --tint:#1a3350; --photo-empty:#222c3b;
  --text:#f3eee6; --text-2:#a9b3c2;
  --action:#67b7f7; --action-fill:#67b7f7; --action-hover:#86c6f9; --on-action:#0e2238; --sky:#67b7f7; --selected:#1a3350; --reward:#ffb39b; --reward-bg:#3a2721; --on-reward:#263247;
  --divider:#2a3546; --control:#6e7b8d; --focus:#67b7f7; --grid-line:rgb(103 183 247 / .07);
  --ok:#7cc89a; --ok-bg:#16301f; --warn:#f0c070; --warn-bg:#2a2414; --err:#ff8f78; --err-bg:#331b17; --on-err:#1f0d0a; --swatch-edge:rgb(255 255 255 / .25); --img-edge:rgb(255 255 255 / .1); --shadow-chip:0 1px 2px rgb(0 0 0 / .4); --shadow-fab:0 1px 3px rgb(0 0 0 / .5),0 4px 8px 3px rgb(0 0 0 / .3);
  --bar:#1c2533; --bar-edge:0 0 0 1px #2a3546; --peach:#3a2a20; --lilac:#2a2638; --skyt:#1a2d40; --butter:#352d1a; --mint:#1a3326; --blush:#3a2229;
  --map-bg:#18202c; --map-zone:#1e2734; --map-bldg:#263142; --map-water:#1d3a52; --map-label:#a9b3c2; --map-walk:#3a3328; --map-walk-line:#8a7458;
  --scrim:rgb(0 0 0 / .55); --lift:0 1px 2px rgb(0 0 0 / .4),0 12px 28px -14px rgb(0 0 0 / .7); --card-shadow:drop-shadow(0 16px 32px rgb(0 0 0 / .35)); color-scheme:dark}}

/* type scale: 28 page title / 32 cat name / 18 section / 16 body, controls, card names / 14 metadata / 12 map labels */
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
/* 17px body like iOS; on iPhone the root follows the Text Size setting (Dynamic Type) and every rem scales with it */
html{font-size:106.25%;-webkit-text-size-adjust:100%;overscroll-behavior:none;scroll-padding-block-end:calc(110px + env(safe-area-inset-bottom,0px))}
body{overscroll-behavior:none}
@supports (font:-apple-system-body){html{font:-apple-system-body}}
html,body{background:var(--bg);overflow-x:clip}
body{color:var(--text);font:400 1rem/1.5 var(--font);-webkit-font-smoothing:antialiased}
button,input,select,textarea{font:inherit;color:inherit}
h1,h2,h3{margin:0;font-family:var(--display);font-weight:600;line-height:1.15;letter-spacing:-.005em;text-wrap:balance}
.t-page{font-size:1.765rem}
.t-cat{font-size:2.118rem;font-weight:700}
.t-sec{font-size:1.176rem}
p{margin:0;text-wrap:pretty}
a{color:var(--action)}
:focus-visible{outline:2px solid var(--focus);outline-offset:2px;border-radius:4px}
main:focus,h1:focus,h2:focus{outline:none}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.skip{position:fixed;left:16px;top:calc(8px + env(safe-area-inset-top,0px));z-index:70;padding:8px 16px;border-radius:var(--r-sm);background:var(--text);color:var(--bg);transform:translateY(-200%);text-decoration:none;font-weight:600}
.skip:focus{transform:none}
.meta{font-size:0.824rem;color:var(--text-2);line-height:1.45}
.count{font-variant-numeric:tabular-nums}


/* page frame */
.app{max-width:600px;margin:0 auto;padding-left:max(20px,env(safe-area-inset-left,0px));padding-right:max(20px,env(safe-area-inset-right,0px));padding-block:0 120px}
.top{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);min-height:64px;margin-bottom:var(--s4)}
.brand{display:flex;align-items:center;gap:8px;white-space:nowrap;min-height:44px;background:none;border:0;padding:0;cursor:pointer;text-align:left}
.brand img{width:34px;height:34px;flex:none;border-radius:10px}
.brand b{display:block;font-size:1rem;font-weight:600;line-height:1.1}
.brand span{display:block;font-size:0.765rem;color:var(--text-2);line-height:1.2}
.view{display:flex;flex-direction:column;gap:var(--s7)}
@keyframes fade{from{opacity:0}}
.sec{display:flex;flex-direction:column;gap:var(--s4)}
.sec-h{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s3)}
.link{display:inline-flex;align-items:center;gap:4px;min-height:44px;background:none;border:0;padding:0;color:var(--action);font-weight:500;cursor:pointer;text-decoration:underline;text-decoration-color:transparent;text-underline-offset:3px;transition:text-decoration-color .15s}
.link.quiet{color:var(--text-2)}

/* buttons */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:48px;padding:0 20px;border-radius:14px;border:1px solid transparent;font-weight:600;cursor:pointer;transition:background-color .15s,border-color .15s}
.btn-primary{background:var(--action-fill);color:var(--on-action)}
.btn-secondary{background:var(--card);border-color:var(--control);color:var(--text)}
.btn-text{background:none;color:var(--action);padding:0 8px;min-height:44px}
.btn-danger{background:none;color:var(--err);padding:0 8px;min-height:44px}
.btn[disabled]{opacity:.5;cursor:not-allowed;transform:none}
.btn-block{width:100%}
.btn svg{width:18px;height:18px}

/* photos and placeholders */
.photo{position:relative;overflow:hidden;background:var(--photo-empty);border-radius:var(--r-md)}
.photo img{display:block;width:100%;height:100%;object-fit:cover;transition:opacity .2s var(--ease-out)}
.js .photo img:not(.loaded){opacity:0}
.photo:has(img)::after{content:"";position:absolute;inset:0;border-radius:inherit;box-shadow:inset 0 0 0 1px var(--img-edge);pointer-events:none}
.photo .none{position:absolute;inset:0;display:grid;place-items:center;align-content:center;gap:8px;color:var(--text-2);font-size:0.765rem}
.photo .none svg{width:30%;max-width:56px;height:auto;opacity:.75}
.photo .fur{position:absolute;left:10px;bottom:10px;width:14px;height:14px;border-radius:50%;box-shadow:0 0 0 2px var(--bg)}


/* notices */
.notice{display:flex;gap:var(--s3);align-items:flex-start;padding:var(--s3) var(--s4);border-radius:var(--r-sm);background:var(--tint);font-size:0.882rem}
.notice.warn{background:var(--warn-bg);color:var(--warn)}
.notice .grow{flex:1;min-width:0}
.err{display:flex;gap:8px;align-items:flex-start;color:var(--err);font-size:0.882rem;font-weight:500}
.err svg{flex:none;width:18px;height:18px;margin-top:2px}


/* home */
.intro{display:flex;flex-direction:column;gap:var(--s4)}
.intro p{color:var(--text-2);max-width:40ch}
.intro .row-btns{display:flex;flex-wrap:wrap;gap:var(--s3);align-items:center}
@media (min-width:640px){.strip{grid-auto-flow:row!important;grid-template-columns:repeat(4,minmax(0,1fr));overflow:visible!important;margin-inline:0!important;padding-inline:0!important}.strip>:nth-child(n+5){display:none}}
.strip{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(150px,42%);gap:var(--s3);overflow-x:auto;margin-inline:-20px;padding-inline:20px;scroll-padding-inline:20px;scroll-snap-type:x mandatory;scrollbar-width:thin}
.tile{display:flex;flex-direction:column;gap:var(--s2);background:none;border:0;padding:0;text-align:left;cursor:pointer;scroll-snap-align:start;min-width:0}
.tile .photo{aspect-ratio:4/5}
.tile b{font-weight:600;line-height:1.3}
.empty{display:flex;flex-direction:column;gap:var(--s3);align-items:flex-start;padding:var(--s5);border-radius:var(--r-lg);background:var(--card);border:1px solid var(--divider)}
.empty h2{font-size:1.059rem}
.empty .ming-small{width:64px;height:64px}
.empty p{color:var(--text-2);max-width:42ch}
.skeleton{background:var(--surface);border-radius:var(--r-md);animation:pulse 1.4s ease-in-out infinite}
@keyframes pulse{50%{opacity:.55}}

/* directory grid */
.searchbar{display:flex;flex-direction:column;gap:var(--s3)}
.field{width:100%;min-height:48px;padding:12px 16px;border-radius:var(--r-sm);border:1px solid var(--control);background:var(--card);transition:border-color .15s,box-shadow .15s}
.field:focus{outline:none;border-color:var(--action);box-shadow:0 0 0 3px var(--tint)}
.field[aria-invalid="true"]{border-color:var(--err)}
textarea.field{min-height:92px;resize:vertical}
.search-wrap{position:relative}
.search-wrap svg{position:absolute;left:16px;top:50%;width:18px;height:18px;margin-top:-9px;color:var(--text-2);pointer-events:none}
.search-wrap .field{padding-left:44px}
.toggles{display:flex;gap:var(--s2);overflow-x:auto;margin-inline:-20px;padding:2px 20px 4px;scrollbar-width:none}
.toggles::-webkit-scrollbar{display:none}
.toggles.wrap{flex-wrap:wrap;overflow:visible;margin-inline:0;padding-inline:0}
.tog{display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:0 16px;border-radius:999px;border:1px solid var(--control);background:var(--card);cursor:pointer;white-space:nowrap;font-size:0.882rem;transition:background-color .15s,border-color .15s,color .15s}
.tog[aria-pressed="true"]{background:var(--selected);border-color:var(--action);color:var(--action);font-weight:500}
.toggles[aria-invalid="true"] .tog{border-color:var(--err)}
.sw{width:12px;height:12px;border-radius:50%;box-shadow:inset 0 0 0 1px var(--swatch-edge)}
.grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s5) var(--s4)}
@media (min-width:560px){.grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
.card{display:flex;flex-direction:column;gap:var(--s2);background:none;border:0;padding:0;text-align:left;cursor:pointer;min-width:0;color:inherit}
.card .photo{aspect-ratio:4/5}
.card b{font-weight:600;line-height:1.3}
.card .meta{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}

/* profile */
.crumb{align-self:flex-start;margin-bottom:calc(-1 * var(--s5))}
.prof{display:flex;flex-direction:column;gap:var(--s5)}
.prof .photo.hero{aspect-ratio:4/3}
.prof-head{display:flex;flex-direction:column;gap:var(--s2)}
.vcheck{width:.62em;height:.62em;margin-left:.22em;vertical-align:-.04em;color:var(--ok)}
.prof-head .seen{margin:var(--s1) 0 0;font-size:1.02rem}
.prof-head .seen .link{min-height:0;display:inline;padding:0;text-decoration:underline;text-decoration-color:color-mix(in srgb,currentColor 35%,transparent)}
.actions{display:flex;gap:var(--s3);flex-wrap:wrap}
.actions .btn{flex:1 1 180px}
.prose ul{margin:0;padding-left:20px;display:flex;flex-direction:column;gap:var(--s2)}
.prose h2{margin-top:var(--s3)}
.foot-links{display:flex;flex-wrap:wrap;justify-content:center;gap:0 var(--s4)}
.foot-links .link{font-size:.765rem}
.sec-note{font-size:0.824rem;color:var(--text-2);margin-top:calc(-1 * var(--s2))}
.kv{display:grid;grid-template-columns:120px minmax(0,1fr);gap:var(--s3) var(--s4);margin:0}
.kv dt{color:var(--text-2)}
.kv dd{margin:0}
.notes{display:flex;flex-direction:column;gap:var(--s3);margin:0;padding:0}
.notes li{list-style:none;padding-left:var(--s4);border-left:2px solid var(--divider)}
.gallery{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
.gallery .photo{aspect-ratio:1;border-radius:var(--r-sm)}
.pbtn{display:block;width:100%;padding:0;border:0;background:none;cursor:pointer;border-radius:var(--r-sm);min-width:0}
/* a screen redrawn because new data arrived doesn't replay entrances */
#view[data-bg] :is(.gcard-art svg,.place,.confirm,.report,.meet,.done .mark,.ming .m-all,.ming .m-eyes){animation:none}
.timeline{margin:0;padding:0;display:flex;flex-direction:column}
.timeline li{list-style:none;display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--s3);padding-block:var(--s3);border-top:1px solid var(--divider)}
.timeline li:first-child{border-top:0;padding-top:0}
.timeline .when{font-size:0.824rem;color:var(--text-2);font-variant-numeric:tabular-nums;min-width:76px}
.timeline .where{font-weight:500}
.mod-cat{display:flex;flex-direction:column;gap:var(--s4);padding-top:var(--s4);border-top:1px solid var(--divider)}
.mod-row{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--s2)}
.mod-row .lbl{flex:1 1 220px}
.confirm{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s1) var(--s2);animation:enter-in .16s var(--ease-out) both;transform-origin:0 50%}
.report{display:flex;flex-direction:column;gap:var(--s3);padding:var(--s4);border-radius:var(--r-md);border:1px solid var(--divider);background:var(--card);animation:enter-in .2s var(--ease-out) both;transform-origin:0 0}

/* map */
.map-frame{border:1px solid var(--divider);border-radius:var(--r-md);overflow:hidden;background:var(--map-bg)}
.map-frame svg{display:block;width:100%;height:auto}
.lm{cursor:pointer}
/* paws answer a press, and lift a little under a mouse */
.lm .pawmark{transform-box:fill-box;transform-origin:50% 75%;transition:transform 160ms var(--ease-out)}
.lm:active .pawmark{transform:scale(.9)}
@media (hover:hover) and (pointer:fine){.lm:hover .pawmark{transform:translateY(-2px)}}
.lm:focus,.lm:focus-visible{outline:none}
.lm:focus-visible .ring{stroke:var(--focus);stroke-width:3;opacity:1}
.place{display:flex;flex-direction:column;gap:var(--s2);padding:var(--s4);border-radius:var(--r-md);border:1px solid var(--divider);background:var(--card);animation:enter-in .2s var(--ease-out) both;transform-origin:50% 0}
.lines{display:flex;flex-direction:column}
.line{display:grid;grid-template-columns:48px minmax(0,1fr) auto;gap:var(--s3);align-items:center;padding-block:var(--s3);border:0;border-top:1px solid var(--divider);background:none;text-align:left;cursor:pointer;width:100%;color:inherit}
.line:first-child{border-top:0}
.line.no-img{grid-template-columns:minmax(0,1fr) auto}
.line .photo{width:48px;height:48px;border-radius:var(--r-sm)}
.line b{font-weight:500}
.line .meta{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.line .side{font-size:0.824rem;color:var(--text-2);text-align:right;font-variant-numeric:tabular-nums}

/* community photos */

/* review queue (owner only) */
.review{display:flex;flex-direction:column;padding:var(--s4);border:1px solid var(--divider);border-radius:var(--r-md);background:var(--card)}
.review h2{margin-bottom:var(--s2)}
.review-item{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:4px var(--s3);align-items:center;padding-block:var(--s2);border-top:1px solid var(--divider)}
.review h2+.review-item{border-top:0}
.review-name{grid-column:1/-1}
.review-item.has-photo{grid-template-columns:64px minmax(0,1fr) auto}
.review-photo{display:block;width:64px;height:64px;border-radius:var(--r-sm);overflow:hidden;background:var(--photo-empty)}
.review-photo img{width:100%;height:100%;object-fit:cover;display:block}
.consent{margin-top:calc(-1 * var(--s2))}


/* ---------- Cats: the Catdex index. One row per cat, who at a glance ---------- */
.dexlist{display:flex;flex-direction:column;gap:2px;margin-inline:calc(var(--s3) * -1)}
.dexrow{display:grid;grid-template-columns:56px minmax(0,1fr) auto;align-items:center;gap:var(--s3);width:100%;min-height:72px;padding:var(--s2) var(--s3);border:0;border-radius:var(--r-md);background:transparent;color:inherit;text-align:left;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background-color 150ms var(--ease-out)}
.dexrow:active{background:var(--surface)}
.dexrow .photo.av{width:56px;height:56px;border-radius:50%}
.dexrow .photo.av img{outline:1px solid var(--img-edge);outline-offset:-1px;border-radius:50%}
.dexrow .photo.av .art{width:100%;height:100%;display:grid;place-items:center}
.dr-txt{display:flex;flex-direction:column;gap:2px;min-width:0}
.dr-txt b{display:flex;align-items:center;gap:6px;font-weight:600;line-height:1.3;min-width:0}
.dr-met{display:inline-flex;color:var(--reward)}
.dr-met svg{width:14px;height:14px;fill:currentColor}
.dr-txt .meta{display:flex;align-items:center;gap:6px;min-width:0}
.dr-where{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dr-no{font-size:.824rem;font-weight:600;color:var(--text-2);font-variant-numeric:tabular-nums;padding-left:var(--s2)}
@media (hover:hover) and (pointer:fine){.dexrow:hover{background:var(--surface)}}

/* ---------- Photos: a wall of pictures. No text, the photo is the button ---------- */
.wall{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:3px;margin-inline:calc(max(20px,env(safe-area-inset-left,0px)) * -1)}
.wtile{position:relative;display:block;padding:0;border:0;background:var(--photo-empty);cursor:pointer;-webkit-tap-highlight-color:transparent}
.wtile .photo{display:block;aspect-ratio:1;border-radius:0}
.wtile .photo img{transition:opacity 150ms var(--ease-out)}
.wtile:active .photo img{opacity:.8}
.wtile:focus-visible{outline:3px solid var(--focus);outline-offset:-3px;z-index:1}
.wpend{position:absolute;left:6px;bottom:6px;padding:2px 8px;border-radius:999px;font-size:.706rem;font-weight:600;background:var(--warn-bg);color:var(--warn)}
/* wider screens: the wall sits inside the page, each photo with soft corners so a half row still looks finished */
@media (min-width:640px){.wall{margin-inline:0;gap:6px}.wtile,.wtile .photo{border-radius:10px;overflow:hidden}}
@media (min-width:900px){.wall{grid-template-columns:repeat(4,minmax(0,1fr))}}

/* ---------- moderator: rename a cat by tapping its name ---------- */
.name-edit{display:inline-flex;align-items:center;gap:6px;max-width:100%;margin:0 -4px;padding:2px 4px;border:0;border-radius:var(--r-sm);background:transparent;font:inherit;color:inherit;text-align:left;cursor:text;-webkit-tap-highlight-color:transparent;transition:background-color 150ms var(--ease-out)}
.name-edit svg{flex:none;width:.5em;height:.5em;color:var(--text-2)}
.name-edit:active{background:var(--surface)}
@media (hover:hover) and (pointer:fine){.name-edit:hover{background:var(--surface)}}
.name-form{display:inline-block;width:100%;max-width:24ch}
.name-input{width:100%;padding:2px 0;border:0;border-bottom:2px solid var(--action);border-radius:0;background:transparent;font:inherit;color:inherit;outline:none}
.name-input::placeholder{color:var(--text-2)}
.cands .add-named{grid-column:1/-1}
/* keep the verified check beside the name while it is tappable or being edited */
.t-cat:has(.name-edit),.t-cat:has(.name-form){display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px}
.t-cat .name-form{flex:1 1 12ch}

/* hold to merge: a fill sweeps across while held (2 s, steady), and snaps back on early release */
.hold{position:relative;overflow:hidden;isolation:isolate}
.hold-fill{position:absolute;inset:0;z-index:-1;background:var(--tint);clip-path:inset(0 100% 0 0);transition:clip-path 200ms var(--ease-out)}
.hold.holding .hold-fill{clip-path:inset(0 0 0 0);transition:clip-path 2s linear}

/* bottom navigation */
.nav{position:fixed;left:0;right:0;bottom:0;z-index:20;pointer-events:none;padding:0 max(16px,env(safe-area-inset-right,0px)) calc(12px + env(safe-area-inset-bottom,0px)) max(16px,env(safe-area-inset-left,0px))}
/* scroll edge effect: content fades under the floating bar instead of colliding with it */
.nav::before{content:"";position:absolute;left:0;right:0;bottom:0;height:calc(110px + env(safe-area-inset-bottom,0px));background:linear-gradient(to top,var(--bg) 30%,color-mix(in srgb,var(--bg) 0%,transparent));z-index:-1}
.nav-in{pointer-events:auto;position:relative;max-width:480px;margin:0 auto;display:flex;align-items:center;gap:12px}
.tabbar{flex:1;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:2px;padding:4px;border-radius:999px;background:var(--bar);box-shadow:var(--bar-edge),var(--lift)}
.nav-btn{min-width:0;white-space:nowrap;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;min-height:54px;border-radius:999px;background:none;border:0;cursor:pointer;font-size:min(0.706rem,16px);font-weight:500;color:var(--text-2);transition:color .15s}
/* tab labels stop growing at 16px, like iOS tab bars, so all four tabs and the Log button fit with large text */
.nav-btn svg{width:22px;height:22px}
.nav-btn[aria-current="page"]{color:var(--action);background:var(--selected)}
.nav-btn .on,.nav-btn[aria-current="page"] .off{display:none}
.nav-btn[aria-current="page"] .on{display:block}
.nav-log{position:relative;flex:none;width:62px;height:62px;border-radius:50%;border:0;cursor:pointer;display:grid;place-items:center;background:var(--action-fill);color:var(--on-action);box-shadow:var(--lift);transition:background-color .15s,transform .2s var(--ease)}
.nav-log svg{width:26px;height:26px}


/* sheet (logging flow) */
.sheet{position:fixed;inset:0;z-index:40;display:flex;align-items:flex-end;justify-content:center}
.scrim{position:absolute;inset:0;background:var(--scrim);opacity:0;transition:opacity .25s var(--ease)}
.panel{position:relative;width:100%;max-width:600px;height:calc(100% - 16px - env(safe-area-inset-top,0px));background:var(--bg);border-radius:16px 16px 0 0;display:flex;flex-direction:column;transform:translateY(100%);transition:transform .32s var(--ease);box-shadow:var(--lift)}
.sheet.open .scrim{opacity:1}
.sheet.open .panel{transform:none}
.grabber{width:38px;height:5px;border-radius:3px;background:var(--control);opacity:.55;margin:8px auto 0;flex:none}
.sheet-bar{touch-action:none;display:grid;grid-template-columns:44px 1fr 44px;align-items:center;gap:var(--s3);padding:var(--s1) max(16px,env(safe-area-inset-right,0px)) var(--s3) max(16px,env(safe-area-inset-left,0px));border-bottom:1px solid var(--divider)}
.icon-btn{width:44px;height:44px;border-radius:var(--r-sm);border:0;background:none;cursor:pointer;display:grid;place-items:center;color:var(--text)}
.icon-btn[hidden]{display:block!important;visibility:hidden}
.progress{display:flex;flex-direction:column;align-items:center;gap:8px}
.progress span{font-size:0.765rem;color:var(--text-2)}
.progress .bar{width:100%;max-width:160px;height:4px;border-radius:2px;background:var(--divider);overflow:hidden}
.progress .bar i{display:block;height:100%;width:100%;background:var(--action-fill);transform-origin:left;transform:scaleX(0);transition:transform .3s var(--ease-out)}
.sheet-body{flex:1;overflow-y:auto;overscroll-behavior:contain;padding:var(--s5) max(20px,env(safe-area-inset-right,0px)) var(--s5) max(20px,env(safe-area-inset-left,0px))}
.step{display:flex;flex-direction:column;gap:var(--s5)}
.step.fwd{animation:slideIn .22s var(--ease)}
.step.back{animation:slideBack .22s var(--ease)}
@keyframes slideIn{from{opacity:0;transform:translateX(12px)}}
@keyframes slideBack{from{opacity:0;transform:translateX(-12px)}}
.step h2{font-size:1.412rem}
.step .lead{color:var(--text-2);margin-top:calc(-1 * var(--s3))}
.sheet-foot{padding:var(--s3) max(20px,env(safe-area-inset-right,0px)) calc(var(--s3) + env(safe-area-inset-bottom,0px)) max(20px,env(safe-area-inset-left,0px));display:flex;flex-direction:column;gap:var(--s1);border-top:1px solid var(--divider);background:var(--bg)}
.sheet-foot:empty{display:none}
.panel.dragging{transition:none}
.discard{position:absolute;inset:0;z-index:2;display:flex;align-items:flex-end;background:var(--scrim);border-radius:16px 16px 0 0;padding:var(--s3) max(12px,env(safe-area-inset-right,0px)) calc(var(--s3) + env(safe-area-inset-bottom,0px)) max(12px,env(safe-area-inset-left,0px));animation:fade .18s var(--ease)}
.discard-card{width:100%;display:flex;flex-direction:column;gap:var(--s2);padding:var(--s5) var(--s4) var(--s4);border-radius:var(--r-lg);background:var(--card);box-shadow:var(--lift);text-align:center;animation:slideUp .25s var(--ease)}
.discard-card h2{font-size:1.176rem}
.discard-card p{color:var(--text-2);margin-bottom:var(--s2)}
@keyframes slideUp{from{transform:translateY(24px);opacity:0}}
.btn-danger-fill{background:var(--err);color:var(--on-err)}
.drop{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--s2);aspect-ratio:4/3;width:100%;border-radius:var(--r-md);border:1.5px dashed var(--control);background:var(--surface);cursor:pointer;text-align:center;padding:var(--s5);position:relative;overflow:hidden;transition:border-color .15s,background-color .15s}
.drop svg{width:32px;height:32px;color:var(--action)}
.drop b{font-weight:600}
.pick:focus-within{outline:2px solid var(--focus);outline-offset:2px}
.drop img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.yours{display:grid;grid-template-columns:72px minmax(0,1fr);gap:var(--s3);align-items:center}
.yours .photo{width:72px;height:72px;border-radius:var(--r-sm)}
.cands{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s3)}
.cand{position:relative;display:flex;flex-direction:column;gap:8px;padding:8px 8px 12px;border-radius:var(--r-md);border:1px solid var(--divider);background:var(--card);cursor:pointer;text-align:left;min-width:0;transition:border-color .15s,background-color .15s}
.cand[aria-pressed="true"]{border-color:var(--action);background:var(--selected);box-shadow:0 0 0 1px var(--action)}
.cand .photo{aspect-ratio:1;border-radius:var(--r-sm)}
.cand .t{padding-inline:4px;display:flex;flex-direction:column;gap:2px}
.cand b{font-weight:600;line-height:1.3}
.cand .meta{font-size:0.765rem}
.cand .check{position:absolute;right:12px;top:12px;width:26px;height:26px;border-radius:50%;background:var(--action);color:var(--on-action);display:grid;place-items:center;transition:opacity .15s,transform .15s;background:var(--action-fill)}
.js .cand:not([aria-pressed="true"]) .check{opacity:0;transform:scale(.8)}
.lbl{display:flex;flex-direction:column;gap:var(--s2)}
.lbl>span,.lbl>legend{font-size:0.882rem;font-weight:600;padding:0}
.lbl .hint{font-size:0.824rem;color:var(--text-2);font-weight:400}
fieldset.lbl{border:0;margin:0;padding:0;min-width:0}
.choice{display:flex;flex-direction:column;gap:var(--s2)}
.opt{display:grid;grid-template-columns:20px minmax(0,1fr);gap:var(--s3);align-items:start;padding:var(--s3) var(--s4);border:1px solid var(--control);border-radius:var(--r-sm);background:var(--card);cursor:pointer;transition:border-color .15s,background-color .15s}
.opt:has(input:checked){border-color:var(--action);background:var(--selected);box-shadow:0 0 0 1px var(--action)}
.opt:has(input:focus-visible){outline:2px solid var(--focus);outline-offset:2px}
.opt input{margin:3px 0 0;width:18px;height:18px;accent-color:var(--action)}
.opt b{display:block;font-weight:600}
.opt span{font-size:0.824rem;color:var(--text-2)}
.reveal{display:grid;grid-template-rows:0fr;transition:grid-template-rows .22s var(--ease)}
.reveal.open{grid-template-rows:1fr}
.reveal>div{overflow:hidden;min-height:0;display:flex;flex-direction:column;gap:var(--s3);transition:padding-top .22s var(--ease),visibility 0s .22s}
.reveal.open>div{transition:padding-top .22s var(--ease),visibility 0s}
.reveal.open>div{padding-top:var(--s3)}
.js .reveal:not(.open)>div{visibility:hidden}
.pick-map{border:1px solid var(--divider);border-radius:var(--r-md);overflow:hidden;background:var(--map-bg)}
.pick-map svg{display:block;width:100%;height:auto}
.preview{display:grid;grid-template-columns:48px minmax(0,1fr);gap:var(--s3);align-items:center;padding:var(--s3);border-radius:var(--r-sm);background:var(--card);border:1px solid var(--divider)}
.preview .photo{width:48px;height:48px;border-radius:6px}
.preview.no-img{grid-template-columns:minmax(0,1fr)}
.stranded{display:flex;flex-direction:column;align-items:flex-start;gap:var(--s3);padding:var(--s4);border:1px solid var(--divider);border-radius:var(--r-md);background:var(--card)}
.stranded .gallery{width:100%}
/* cats nobody has photographed yet: plain text cards, no drawn stand-in */
.strip:has(.no-img),.grid:has(.no-img){align-items:start}
.tile.no-img,.card.no-img{padding:var(--s4);border:1px solid var(--divider);border-radius:var(--r-md);background:var(--card)}
.card.no-img .metmark{position:static;align-self:flex-start;box-shadow:none}
.mycat.no-img{width:auto;padding:8px 16px;border:1px solid var(--divider);background:var(--card);border-radius:999px;font-size:.824rem}
.cand.no-img{padding:var(--s3) 44px var(--s3) var(--s3)}
.cand.no-img .check{top:50%;margin-top:-13px}
.preview .t{display:flex;flex-direction:column;min-width:0;font-size:0.882rem}
.done{display:flex;flex-direction:column;align-items:center;text-align:center;gap:var(--s3);padding-top:10vh}
.done .wait{display:flex;gap:var(--s3);align-items:flex-start;text-align:left;max-width:36ch;padding:var(--s3) var(--s4);border-radius:var(--r-sm);background:var(--surface)}
.done .wait svg{flex:none;width:20px;height:20px;margin-top:2px;fill:none;stroke:var(--action);stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.done .wait p{margin:0;font-size:.882rem}
.done .wait b{display:block;color:var(--text)}
.step.fwd .done .wait{animation:rise .3s var(--ease-out) .15s both}
.done h2{font-size:1.412rem}
.done p{color:var(--text-2);max-width:34ch}

.toast{position:fixed;left:50%;bottom:calc(92px + env(safe-area-inset-bottom,0px));z-index:60;background:var(--text);color:var(--bg);padding:12px 16px;border-radius:var(--r-sm);font-size:0.882rem;max-width:calc(100% - 40px);transform:translate(-50%,0);transition:transform .25s var(--ease),opacity .2s}
.toast.off{opacity:0;transform:translate(-50%,8px);pointer-events:none;transition-duration:.15s}


/* ---- personality ---- */
.brand b{font-family:var(--display);font-size:1.118rem}
.hello{position:relative;isolation:isolate;margin-top:64px;padding:var(--s5);border-radius:var(--r-lg);background-color:var(--tint)}
/* AdU's front in blue ASCII, on the right. It fades out before the text, and takes its colour from the theme. Still on purpose: Home is opened often. */
.hello .adu{position:absolute;inset:0;z-index:-1;border-radius:inherit;overflow:hidden;pointer-events:none;-webkit-mask-image:linear-gradient(90deg,transparent 15%,#000 75%);mask-image:linear-gradient(90deg,transparent 15%,#000 75%)}
/* phone: the building stands in the bottom-right corner, sized by width, faint, so the text above stays easy to read */
.hello .adu i{position:absolute;right:-12px;bottom:-6px;width:min(88%,420px);aspect-ratio:1040/804;background:var(--action);opacity:.4;-webkit-mask:url(img/adu-ascii.png) center/contain no-repeat;mask:url(img/adu-ascii.png) center/contain no-repeat}
/* laptop: the text keeps the left half, the building takes the right half */
@media (min-width:720px){.hello .adu{-webkit-mask-image:linear-gradient(90deg,transparent 40%,#000 70%);mask-image:linear-gradient(90deg,transparent 40%,#000 70%)}.hello .adu i{width:auto;height:118%;opacity:.75}}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .hello .adu i{opacity:.3}}
@media (prefers-color-scheme:dark) and (min-width:720px){:root:not([data-theme="light"]) .hello .adu i{opacity:.5}}
.hello .perch{position:absolute;right:20px;top:-72px;width:92px;height:92px;pointer-events:none}
.hello .perch svg{width:100%;height:100%;overflow:visible}
.hello .perch .blink{transform-origin:50px 57px;animation:blink 5s infinite}
@keyframes blink{0%,95%,100%{transform:scaleY(1)}97%{transform:scaleY(.1)}}
.photo .art{position:absolute;inset:0;display:flex;align-items:flex-end;justify-content:center}
.photo .art svg{width:70%;height:auto;margin-bottom:-3%;transition:transform .25s var(--ease)}
.photo .art .cap{position:absolute;left:12px;top:12px;font-size:0.765rem;color:var(--text-2);background:color-mix(in srgb,var(--bg) 70%,transparent);padding:4px 8px;border-radius:6px}
.photo{border-radius:var(--r-md)}
/* the Log button has ears; they tilt when it's hovered or focused */
.nav-log::before,.nav-log::after{content:"";position:absolute;top:-5px;width:18px;height:15px;background:inherit;clip-path:polygon(50% 0,100% 100%,0 100%);transform-origin:50% 100%;transition:transform .25s var(--ease)}
.nav-log::before{left:9px;transform:rotate(-16deg)}
.nav-log::after{right:9px;transform:rotate(16deg)}
@keyframes float{0%,100%{transform:translateY(0);opacity:.9}50%{transform:translateY(-4px);opacity:.4}}
.done .mark{width:76px;height:76px;border-radius:50%;display:grid;place-items:center;background:var(--tint);color:var(--action);animation:hop .5s var(--ease-pop) both}
.done .mark svg{width:38px;height:38px}
@keyframes hop{0%{transform:translateY(10px) scale(.8);opacity:0}100%{transform:none;opacity:1}}
.paw{fill:var(--action)}

/* ---- Ming: Catdex's own cat ----
   Sky blue on purpose, so nobody mistakes the mascot for a real campus cat.
   One drawing, four states, each tied to something real: idle, happy (you did something),
   hmm (nothing matched, or a save failed), sleepy (nothing logged yet, or late at night). */
.ming{display:block;overflow:visible}
.ming .m-all,.ming .m-body{transform-origin:50px 92px}
.ming .m-tail{transform-origin:80px 88px}
.ming .m-eyes,.ming .m-open{transform-origin:50px 57px}
.ming .m-happy,.ming .m-shut,.ming .m-zz{display:none}
/* Ming only breathes and sways where Ming is the focus: the Home hero, empty states and the intro. Blinking runs everywhere. */
:is(.hello,.empty,.ob-ming) .ming .m-body{animation:m-breathe 4.2s ease-in-out infinite}
:is(.hello,.empty,.ob-ming) .ming .m-tail{animation:m-sway 3.4s ease-in-out .3s infinite}
.ming .m-open{animation:blink 5s 1.2s infinite}
@keyframes m-breathe{50%{transform:scale(.993,1.012)}}
@keyframes m-sway{50%{transform:rotate(6deg)}}
/* happy: one calm hop (no overshoot, small squash), squeezed eyes, two tail swishes, then back to idle */
.ming.m-is-happy .m-open{display:none}
.ming.m-is-happy .m-happy{display:inline}
.ming.m-is-happy .m-all{animation:m-hop .6s var(--ease-in-out) both}
.ming.m-is-happy .m-tail{animation:m-swish .45s ease-in-out 2}
@keyframes m-hop{0%{transform:none}40%{transform:translateY(-5px) scale(.985,1.02)}75%{transform:translateY(0) scale(1.02,.985)}100%{transform:none}}
@keyframes m-swish{50%{transform:rotate(10deg)}}
/* hmm: a look to the side, never a frown. No tilt: Ming has no separate head (see MOTION.md) */
.ming.m-is-hmm .m-eyes{animation:m-glance 2.2s var(--ease-out) both}
@keyframes m-glance{18%,70%{transform:translate(1.6px,-.4px)}}
.ming.m-still .m-all,.ming.m-still .m-eyes{animation:none}
/* sleepy: eyes shut, slower breath, two z's */
.ming.m-is-sleepy .m-open{display:none}
.ming.m-is-sleepy .m-shut,.ming.m-is-sleepy .m-zz{display:inline}
.ming.m-is-sleepy .m-body{animation-duration:5.6s}
.ming.m-is-sleepy .m-tail{animation:none}
.ming .m-zz text{animation:float 3s ease-in-out infinite}
.ming .m-zz text+text{animation-delay:1.2s}
/* placements */
.hello .perch.ming-btn{pointer-events:auto;padding:0;border:0;background:none;cursor:pointer;border-radius:50% 50% 12px 12px;touch-action:manipulation;-webkit-user-select:none;user-select:none}
.ming-btn:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
.ming-badge{width:56px;height:56px;flex:none;border-radius:50%;background:var(--tint);display:flex;align-items:flex-end;justify-content:center;overflow:hidden}
.ming-badge .ming{width:82%;height:auto;margin-bottom:-2px}
/* The guardian card's avatar: a small piece of the card itself. A glossy sky orb, AdU in ASCII, Ming in front.
   Fixed colours, like the card, so it looks the same in light and dark mode. */
.ming-badge.aero{position:relative;isolation:isolate;background:radial-gradient(circle at 50% 35%,#f4fbff,#bfe5fa 68%,#7cc8f2);box-shadow:inset 0 -6px 12px rgb(0 60 120 / .3),0 0 0 2px #fff,0 4px 10px -4px rgb(0 60 120 / .55)}
.ming-badge.aero .ab-adu{position:absolute;left:-45%;right:-45%;bottom:6%;height:100%;z-index:-1;background:#1d6fc4;opacity:.75;-webkit-mask:url(img/adu-ascii.png) center bottom/contain no-repeat;mask:url(img/adu-ascii.png) center bottom/contain no-repeat}
.ming-badge.aero .ming{width:70%}
.ming-badge.aero::after{content:"";position:absolute;left:16%;right:16%;top:5%;height:38%;border-radius:50%;background:linear-gradient(rgb(255 255 255 / .85),rgb(255 255 255 / 0));pointer-events:none}
.ming-nap{width:104px;height:104px}
.ming-nap>svg:not(.ming){display:block;width:100%;height:100%;overflow:visible}
/* Ming sits on the Mochi card's top edge, left of the stamp. It is part of the card, so it tilts with it and is dealt in with it. */
.ob-ming{position:absolute;z-index:2;left:16px;top:-55px;width:62px;height:62px}
.ob-preview:has(.ob-ming){margin-top:28px}
.ob-react{display:grid;grid-template-columns:56px minmax(0,1fr);gap:var(--s3);align-items:center;min-height:56px}
.ming-err{display:grid;grid-template-columns:56px minmax(0,1fr);gap:var(--s3);align-items:center}
.done .meet .ming{width:78%;height:auto;margin-bottom:-2px}


/* ---- first-run intro: questionnaire, spotter card ---- */
.opt b{color:var(--text)}
.ob{position:fixed;inset:0;z-index:50;background:var(--bg);display:flex;flex-direction:column;padding-top:env(safe-area-inset-top,0px);transition:opacity .2s var(--ease)}
.ob.leaving{opacity:0}
.ob-bar{display:grid;grid-template-columns:44px minmax(0,1fr) 64px;align-items:center;gap:var(--s3);width:100%;max-width:520px;margin:0 auto;padding:var(--s2) max(16px,env(safe-area-inset-right,0px)) var(--s2) max(16px,env(safe-area-inset-left,0px))}
.ob-bar .btn-text{justify-self:end;padding:0 4px}
.ob-progress{height:6px;border-radius:3px;background:var(--divider);overflow:hidden}
.ob-progress i{display:block;height:100%;width:100%;background:var(--action-fill);transform-origin:left;transition:transform .3s var(--ease-out)}
.ob-body{flex:1;overflow-y:auto;overscroll-behavior:contain}
.ob-body>.step{max-width:520px;margin:0 auto;padding:var(--s4) max(20px,env(safe-area-inset-right,0px)) var(--s6) max(20px,env(safe-area-inset-left,0px))}
.ob h1{font-size:1.765rem}
.ob .lead{color:var(--text-2);margin-top:calc(-1 * var(--s3))}
.ob-foot{width:100%;max-width:520px;margin:0 auto;display:flex;flex-direction:column;gap:var(--s1);padding:var(--s3) max(20px,env(safe-area-inset-right,0px)) calc(var(--s3) + env(safe-area-inset-bottom,0px)) max(20px,env(safe-area-inset-left,0px))}
fieldset.choice{border:0;margin:0;padding:0;min-width:0}
.ob-opt{grid-template-columns:20px 40px minmax(0,1fr);align-items:center}
.ob-opt input{margin:0}
.ob-ava{width:40px;height:40px;border-radius:50%;overflow:hidden;display:flex;align-items:flex-end;justify-content:center}
.ob-ava svg{width:80%;height:auto;margin-bottom:-2px}
.ob-preview{position:relative;height:236px}
.ob-pcard{position:absolute;top:8px;width:150px;padding:8px 8px 12px;border-radius:24px;background:var(--card);box-shadow:var(--lift),0 0 0 1px var(--divider);display:flex;flex-direction:column;gap:4px;font-size:.824rem}
.ob-pcard .photo{aspect-ratio:1}
.ob-pcard b{font-family:var(--display);font-size:1rem;padding:4px 4px 0}
.ob-pcard span{color:var(--text-2);padding-inline:4px}
.ob-p0{left:max(14px,calc(50% - 150px));--r:-6deg;transform:rotate(var(--r));animation:deal .6s var(--ease-pop) both}
.ob-p1{left:calc(50% - 8px);top:26px;--r:5deg;transform:rotate(var(--r));animation:deal .6s .1s var(--ease-pop) both}
@keyframes deal{from{transform:translateY(28px) rotate(0);opacity:0}}
/* The welcome's one action: a paw stamp presses onto each card just after it lands, the way a sighting
   gets logged, and Ming's tail swishes once as the second stamp lands. Then only the idle loops run. */
.ob-pcard .stamp{position:absolute;right:12px;top:12px;z-index:1;width:34px;height:34px;border-radius:50%;display:grid;place-items:center;background:var(--action-fill);color:var(--on-action);box-shadow:var(--shadow-chip);--tilt:-12deg;transform:rotate(var(--tilt));animation:stamp .28s var(--ease-out) .72s both}
.ob-pcard .stamp svg{width:18px;height:18px}
.ob-p1 .stamp{--tilt:9deg;animation-delay:.9s}
@keyframes stamp{from{opacity:0;transform:scale(1.2) rotate(var(--tilt))}}
.ob-preview .ob-ming .ming .m-tail{animation:m-swish .45s ease-in-out 1s 2,m-sway 3.4s ease-in-out 2s infinite}
.ob-fixes{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--s5)}
.ob-fixes li{display:grid;grid-template-columns:40px minmax(0,1fr);gap:var(--s3);align-items:start}
.ob-ic{width:40px;height:40px;border-radius:12px;background:var(--tint);color:var(--action);display:grid;place-items:center}
.ob-ic svg{width:20px;height:20px}
.ob-fixes .meta{display:block;margin-bottom:2px}
.ob-fixes b{display:block;font-weight:600}
.ob-clue{display:grid;grid-template-columns:72px minmax(0,1fr);gap:var(--s3);align-items:center;padding:var(--s3);border-radius:var(--r-md);background:var(--surface)}
.ob-q{position:relative;width:72px;height:72px}
.ob-q .ob-ava{width:72px;height:72px}
.ob-q i{position:absolute;right:-4px;top:-4px;width:26px;height:26px;border-radius:50%;background:var(--action-fill);color:var(--on-action);font-style:normal;font-weight:700;font-size:.882rem;display:grid;place-items:center;box-shadow:0 0 0 3px var(--surface)}
.ob-clue p{font-weight:500}
.cands.c3{grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s2)}
.cand.no{opacity:.45}
.cand[aria-disabled="true"]{cursor:default}
.cand.shake{animation:shake .3s}
@keyframes shake{25%{transform:translateX(-4px)}75%{transform:translateX(4px)}}
.ob-feedback{min-height:1.6em;font-weight:500}
.ob-feedback.ok{color:var(--ok)}
@keyframes cardIn{from{transform:translateY(16px) rotate(-3deg) scale(.96);opacity:0}}

/* "Already have cat photos?": three photos dealt in a fan, the middle one stamped */
.ob-roll{position:relative;height:190px;margin-top:var(--s4)}
.ob-shot{position:absolute;top:20px;left:50%;width:132px;margin-left:-66px;padding:6px;border-radius:20px;background:var(--card);box-shadow:var(--lift),0 0 0 1px var(--divider);transform:translateX(var(--x)) rotate(var(--r));animation:deal .5s var(--ease-out) both}
.ob-shot .photo{aspect-ratio:1;border-radius:14px;overflow:hidden}
.ob-shot .photo img{display:block;width:100%;height:100%;object-fit:cover}
.ob-s0{--x:-92px;--r:-8deg}
.ob-s1{--x:0px;--r:2deg;z-index:1;top:6px;animation-delay:60ms}
.ob-s2{--x:92px;--r:9deg;animation-delay:120ms}
.ob-shot .stamp{position:absolute;right:-8px;top:-8px;width:34px;height:34px;border-radius:50%;display:grid;place-items:center;background:var(--action-fill);color:var(--on-action);box-shadow:var(--shadow-chip);--tilt:9deg;transform:rotate(var(--tilt));animation:stamp .28s var(--ease-out) .6s both}
.ob-shot .stamp svg{width:18px;height:18px}

/* ---- guardian card: the card is always its own cobalt object, in both themes ---- */
.gcard-art{width:100%;max-width:520px;align-self:center;aspect-ratio:700/470;filter:var(--card-shadow)}
.gcard-art svg{display:block;width:100%;height:auto}
.gcard-art.enter svg{animation:cardIn .5s var(--ease-pop) both}
.ob .gcard-art{max-width:480px;margin-inline:auto}
.gc-actions{display:flex;flex-wrap:wrap;gap:var(--s3)}
.gc-actions .btn{flex:1 1 160px}
.gc-actions.mini{gap:var(--s2);justify-content:center}
.prose a{overflow-wrap:anywhere}
.gc-actions.mini .btn{flex:0 0 auto}
/* small peach pills: noticeable next to the card, quieter than the blue button below */
.chip-btn{display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:0 16px 0 14px;border-radius:999px;border:1px solid color-mix(in srgb,var(--reward) 55%,transparent);background:var(--reward-bg);color:var(--text);font-size:.824rem;font-weight:600;box-shadow:inset 0 1px 0 rgb(255 255 255 / .6),0 1px 2px rgb(38 50 71 / .08);transition:transform .16s var(--ease-out),background-color .16s var(--ease-out)}
.chip-btn svg{width:16px;height:16px;flex:none}
.chip-btn:active{transform:scale(.96)}
@media (hover:hover) and (pointer:fine){.chip-btn:hover{background:color-mix(in srgb,var(--reward-bg) 75%,var(--reward))}}
.gcard .link,.ob .step>.link{align-self:flex-start}
.gcard textarea,.ob #gc-copytext{min-height:110px}
.gentry{display:grid;grid-template-columns:56px minmax(0,1fr);gap:var(--s4);align-items:center;width:100%;padding:var(--s3) var(--s4);border-radius:var(--r-md);border:1px solid var(--divider);background:var(--card);text-align:left;cursor:pointer;color:inherit}
.gentry b{font-weight:600}
.gentry .meta{display:block}
.gentry-art{width:72px;aspect-ratio:700/470;display:block}
.gentry-art svg{display:block;width:100%;height:auto}


/* ================= life: field notes, your cats, discovery moments ================= */
.greet .obs-line{color:var(--text);font-weight:500;max-width:36ch}
.mycats{display:flex;gap:var(--s3);overflow-x:auto;margin-inline:-20px;padding:2px 20px 4px;scrollbar-width:none;scroll-snap-type:x mandatory;scroll-padding-inline:20px;overscroll-behavior-x:contain}
.mycats::-webkit-scrollbar{display:none}
.mycat{flex:none;scroll-snap-align:start;display:flex;flex-direction:column;align-items:center;gap:8px;width:68px;background:none;border:0;padding:0;cursor:pointer;color:inherit;font-size:.765rem;text-align:center}
.mycat .photo{width:60px;height:60px;border-radius:50%}
.mycat span{width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.metmark{position:absolute;left:8px;top:8px;display:inline-flex;align-items:center;gap:4px;padding:4px 8px 4px 4px;border-radius:999px;background:var(--reward);color:var(--on-reward);font-size:.706rem;font-weight:600;box-shadow:var(--shadow-chip)}
.metmark svg{width:12px;height:12px;fill:currentColor}
.metmark .paw{fill:currentColor}
.metline{display:flex;align-items:flex-start;gap:8px;color:var(--text-2);font-size:.882rem}
.metline svg{width:16px;height:16px;color:var(--action);flex:none;margin-top:2px}
.fieldnote{font-size:1.059rem;line-height:1.6;max-width:38ch}
.fieldnote .link{min-height:0;display:inline;padding:0;text-decoration:underline;text-decoration-color:color-mix(in srgb,currentColor 35%,transparent)}
.fieldnote p+p{margin-top:var(--s2)}
.place .about{color:var(--text)}
.pet{all:unset;position:absolute;inset:0;cursor:pointer;border-radius:inherit}
.pet:focus-visible{outline:2px solid var(--focus);outline-offset:-4px}
.petted .art svg{animation:squish .5s var(--ease-out);transform-origin:50% 100%}
.petted .blink{animation:none!important;transform:scaleY(.12);transition:transform .1s ease}
@keyframes squish{30%{transform:scale(1.05,.93)}65%{transform:scale(.98,1.02)}}
.meet{width:132px;height:132px;border-radius:50%;display:flex;align-items:flex-end;justify-content:center;overflow:hidden;animation:meet .55s var(--ease-pop) both}
.meet svg{width:78%;height:auto;margin-bottom:-2px}
@keyframes meet{from{transform:translateY(24px) scale(.9);opacity:0}}


/* ================= Android: Material 3 conventions, same Catdex identity ================= */
[data-os="android"]{--font:Roboto,"Google Sans Text",system-ui,"Segoe UI",sans-serif;--nav-h:80px;scroll-padding-block-end:calc(160px + env(safe-area-inset-bottom,0px))}
[data-os="android"] .app{padding-bottom:180px}
[data-os="android"] .nav{padding:0}
[data-os="android"] .nav::before{display:none}
[data-os="android"] .nav-in{max-width:none;display:block}
[data-os="android"] .tabbar{border-radius:0;gap:0;background:var(--bar);box-shadow:0 -1px 0 var(--divider);padding:12px max(8px,env(safe-area-inset-right,0px)) calc(16px + env(safe-area-inset-bottom,0px)) max(8px,env(safe-area-inset-left,0px))}
[data-os="android"] .nav-btn{border-radius:0;background:none!important;gap:4px;min-height:56px;font-size:min(.706rem,16px);font-weight:500;color:var(--text-2)}
[data-os="android"] .nav-btn svg{box-sizing:content-box;width:24px;height:24px;padding:4px 20px;border-radius:16px;transition:background-color .2s ease}
[data-os="android"] .nav-btn[aria-current="page"]{color:var(--text);font-weight:600}
[data-os="android"] .nav-btn[aria-current="page"] svg{background:var(--selected);color:var(--action)}
[data-os="android"] .nav-log{position:fixed;right:max(16px,env(safe-area-inset-right,0px));bottom:calc(var(--nav-h) + 16px + env(safe-area-inset-bottom,0px));width:56px;height:56px;border-radius:16px;box-shadow:var(--shadow-fab)}
[data-os="android"] .nav-log::before{left:7px}
[data-os="android"] .nav-log::after{right:7px}
[data-os="android"] .btn{border-radius:999px}
[data-os="android"] .panel{border-radius:28px 28px 0 0}
[data-os="android"] .grabber{width:32px;height:4px;border-radius:2px;margin-top:16px;opacity:.4}
[data-os="android"] .discard{align-items:center;justify-content:center;padding:24px;border-radius:28px 28px 0 0}
[data-os="android"] .discard-card{max-width:320px;border-radius:28px;padding:24px 24px 16px;text-align:left;flex-direction:row;flex-wrap:wrap;justify-content:flex-end;gap:4px 8px}
[data-os="android"] .discard-card h2,[data-os="android"] .discard-card p{width:100%}
[data-os="android"] .discard-card h2{font-size:1.412rem}
[data-os="android"] .discard-card .btn{width:auto;min-height:40px;padding:0 12px;background:none;border:0;box-shadow:none;color:var(--action)}
[data-os="android"] .discard-card .btn-danger-fill{order:2;color:var(--err)}
[data-os="android"] .toast{left:max(12px,env(safe-area-inset-left,0px));right:max(12px,env(safe-area-inset-right,0px));bottom:calc(var(--nav-h) + 12px + env(safe-area-inset-bottom,0px));max-width:560px;margin:0 auto;transform:none;border-radius:4px;padding:12px 16px;text-align:left}
[data-os="android"] .toast.off{transform:translateY(8px)}
[data-os="android"] :is(.btn,.card,.tile,.line,.tog,.opt,.cand,.nav-btn,.icon-btn,.nav-log,.drop):active{transform:none}
[data-os="android"] :is(.btn,.tile,.line,.tog,.opt,.cand,.nav-btn,.icon-btn,.drop){position:relative;overflow:hidden}
[data-os="android"] .tog{flex:none}
/* the FAB keeps its ears outside its edge, so it shows a pressed state layer instead of a clipped ripple */
[data-os="android"] .nav-log:active{filter:brightness(.9)}
.ripple{position:absolute;border-radius:50%;background:currentColor;pointer-events:none;opacity:0}
/* Reduce Transparency: opaque bar. Increase Contrast: stronger text, lines and edges */
@media (prefers-contrast:more){
  :root{--text-2:#3d4659;--control:#5d616b;--divider:#c9bba6;--bar-edge:0 0 0 2px var(--text)}
  .tog,.field,.btn-secondary,.opt{border-width:2px}
}
@media (prefers-contrast:more) and (prefers-color-scheme:dark){:root:not([data-theme="light"]){--text-2:#c4d1dd;--control:#8ea2b6;--divider:#3d5163}}


/* ---- motion pass (Emil Kowalski's standards) ---- */
/* press feedback on everything pressable: 0.96, 160ms, strong ease-out */
.btn,.tile,.card,.line,.tog,.opt,.cand,.nav-btn,.icon-btn,.drop,.gentry,.pbtn{transition-property:transform,background-color,border-color,color,box-shadow,opacity;transition-duration:160ms;transition-timing-function:var(--ease-out)}
.btn:active,.tile:active,.card:active,.gentry:active,.pbtn:active,.line:active,.tog:active,.opt:active,.cand:active,.nav-btn:active,.drop:active{transform:scale(.96)}
.icon-btn:active,.nav-log:active{transform:scale(.96)}
.btn[disabled]:active,.cand[aria-disabled="true"]:active{transform:none}
/* sheet: iOS drawer curve going in, quicker on the way out */
.panel{transition:transform .2s var(--ease-out)}
.sheet.open .panel{transition:transform .42s var(--ease-drawer)}
.sheet.open .panel.dragging,.panel.dragging{transition:none}
/* let go of the sheet without closing it: it returns quickly, so it never looks like it is arguing */
.sheet.open .panel.snap{transition:transform .2s var(--ease-out)}
/* rare first-run moments get a short stagger */
@keyframes rise{from{opacity:0;transform:translateY(8px)}}
.ob .step.fwd .choice .opt,.ob .step.fwd .ob-fixes li{animation:rise .3s var(--ease-out) both}
.ob .step.fwd .choice .opt:nth-of-type(2),.ob .step.fwd .ob-fixes li:nth-child(2){animation-delay:40ms}
.ob .step.fwd .choice .opt:nth-of-type(3),.ob .step.fwd .ob-fixes li:nth-child(3){animation-delay:80ms}
.ob .step.fwd .choice .opt:nth-of-type(4),.ob .step.fwd .ob-fixes li:nth-child(4){animation-delay:120ms}
.ob .step.fwd .choice .opt:nth-of-type(5),.ob .step.fwd .ob-fixes li:nth-child(5){animation-delay:160ms}
.ob .step.fwd .choice .opt:nth-of-type(6){animation-delay:200ms}
/* hover only where there's a real pointer */
@media (hover:hover) and (pointer:fine){
  .link:hover{text-decoration-color:currentColor}
  .btn-primary:hover{background:var(--action-hover)}
  .btn-secondary:hover{background:var(--surface)}
  .tile:hover b{color:var(--action)}
  .tog:hover{background:var(--surface)}
  .card:hover b,.gentry:hover b{color:var(--action)}
  .gentry:hover{border-color:var(--control)}
  .line:hover b{color:var(--action)}
  .nav-log:hover{background:var(--action-hover)}
  .icon-btn:hover{background:var(--surface)}
  .btn-danger-fill:hover{filter:brightness(.95)}
  .drop:hover,.drop:focus-within{border-color:var(--action);background:var(--tint)}
  .cand:hover{border-color:var(--control)}
  .opt:hover{background:var(--surface)}
  .card:hover .art svg,.tile:hover .art svg,.cand:hover .art svg{transform:translateY(-4px)}
  .nav-log:hover::before,.nav-log:focus-visible::before{transform:rotate(-30deg)}
  .nav-log:hover::after,.nav-log:focus-visible::after{transform:rotate(30deg)}
}
/* small surfaces grow from where they were triggered; nothing appears from nothing */
@keyframes enter-in{from{opacity:0;transform:scale(.97)}}
.ob:not([hidden]){animation:fade .2s var(--ease-out)}
/* keyboard-initiated closes are instant */
.sheet.instant .panel,.sheet.instant .scrim,.discard.instant,.discard.instant .discard-card{transition:none!important;animation:none!important}
/* text links and the logo also answer a press */
.link,.brand{transition:text-decoration-color .15s ease,transform 160ms var(--ease-out)}
.link:active,.brand:active{transform:scale(.96)}
/* unseen details: no double-tap zoom on controls, no accidental text selection on long-press */
button,a,label,.lm{touch-action:manipulation}
button,label.opt,label.drop,.lm,.brand{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
/* focus styles stay on for keyboards everywhere */
.drop:focus-within{border-color:var(--action);background:var(--tint)}
.nav-log:focus-visible::before{transform:rotate(-30deg)}
.nav-log:focus-visible::after{transform:rotate(30deg)}
/* reduced motion: fewer and gentler, not zero. Movement goes, fades stay */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.2s!important;animation-iteration-count:1!important;animation-delay:0s!important;transition-property:opacity,color,background-color,border-color,box-shadow!important}
  .step.fwd,.step.back,.place,.confirm,.report,.meet,.discard-card,.ob-pcard,.ob-pcard .stamp,.ob-shot,.ob-shot .stamp,.gcard-art svg,.done .mark,.ob .choice .opt,.ob-fixes li,.discard{animation-name:fade!important}
  .blink,.cand.shake,.skeleton,.petted .art svg,.ming *{animation:none!important}
  .sheet:not(.open) .panel{transform:none!important;opacity:0}
  .panel{transition:opacity .2s!important}
  *:active{transform:none!important}
  .reveal:not(.open)>div{opacity:0}
  .reveal>div{transition:opacity .15s,visibility 0s .15s!important}
  .reveal.open>div{transition:opacity .15s,visibility 0s!important}
  .done .wait{animation-name:fade!important}
  .hold-fill{transition-property:clip-path!important}
  :is(.btn,.tile,.card,.line,.tog,.opt,.cand,.nav-btn,.icon-btn,.nav-log,.drop,.gentry,.pbtn,.link,.brand,.mycat,.dexrow,.wtile):not([disabled]):active{opacity:.85}
}

/* desktop: a wider column and denser grids, same single reading flow */
@media (min-width:900px){.app{max-width:720px}.grid{grid-template-columns:repeat(4,minmax(0,1fr))}.cands{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:360px){.kv{grid-template-columns:1fr;gap:2px}.kv dd{margin-bottom:var(--s2)}}
