* { box-sizing: border-box; margin: 0; }

/* ---------- the font, the app's own ----------
   Fredoka lived at Google and was fetched at runtime, and that killed it three
   separate times: a cache deleted under it, an address changed under it, and,
   the one that kept coming back, the browser gives an optional font a tenth of
   a second to appear and a phone's service worker takes longer than that just
   to wake up, so a cold open lost the race and the whole session ran in the
   system font. The files are in the repo now, preloaded by the page and
   precached by the worker, so there is no race, no Google, and it works on a
   phone that has never been online. One variable file carries every weight.
   From the Fontsource build of Google's own files, v5.3.0. */
@font-face {
  font-family: "Fredoka";
  font-style: normal;
  font-display: swap;
  font-weight: 300 700;
  src: url(fonts/fredoka-latin.woff2) format("woff2-variations");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: "Fredoka";
  font-style: normal;
  font-display: swap;
  font-weight: 300 700;
  src: url(fonts/fredoka-latin-ext.woff2) format("woff2-variations");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

/* A phone paints a translucent blue box over whatever you just tapped. That is a
   browser telling you it registered the tap, and in an app it reads as something
   the app did. Every button here already says it has been pressed by changing,
   so the box is turned off.

   Not the focus ring: that is how somebody using a keyboard knows where they
   are, and it only shows for a keyboard, never for a tap. */
/* The page is a light page, said in CSS as well as in the head. The meta tag
   alone was not enough: Chrome's own dark theme reads this property when it
   decides whether to darken a site, and darkening is where the strip under
   the status bar came from. */
html { color-scheme: light; background: var(--bg); }

html { -webkit-tap-highlight-color: transparent; }
button, a, .chip, .pill, .card, .foodpick, label { -webkit-tap-highlight-color: transparent; }

/* ---------- themes ---------- */
/* Each theme is only a set of variables. Adding one means adding a block here
   and a button in Settings, nothing else changes. */

/* The off white is #F6F6F8, the same as Clean, and the same as the one colour the
   phone paints behind the clock on an installed app. That colour is fixed when
   the app is installed and cannot follow a theme picked afterwards, so any theme
   that does not match it shows a thin line across the top. Sage keeps its green,
   it just gives up five shades of white to lose the line. */
html[data-theme="scandi"] {
  --bg: #F6F6F8; --ink: #23312B; --muted: #7C8A82; --card: #FFFFFF; --line: #E4EBE6;
  --head-bg: #F6F6F8; --head-ink: #23312B; --accent: #6FA98C; --accent-ink: #FFFFFF;
  --water: #9CC4DE;
  --price-bg: #EDF5F0; --price-ink: #3E6B54; --soft: #EDF5F0;
  --g-bg: #E3F2E8; --g-ink: #2F6E4C; --b-bg: #E7EEF6; --b-ink: #48688C;
  --a-bg: #F7EEDC; --a-ink: #8A6B2E; --r-bg: #F6E4E0; --r-ink: #A05244;
  --n-bg: #EFF2EF; --n-ink: #7C8A82;
  --warn-bg: #F7EEDC; --warn-ink: #7A5C22;
  --radius: 16px; --radius-sm: 12px;
  --nav-bg: #FFFFFF; --shadow: 0 1px 2px rgba(40,60,50,.05);
}

html[data-theme="midnight"] {
  --bg: #101014; --ink: #F2F2F5; --muted: #9A9AA6; --card: #1C1C22; --line: #2A2A33;
  --head-bg: #101014; --head-ink: #FF8A3D; --accent: #FF8A3D; --accent-ink: #141414;
  --water: #6FAFD9;
  --price-bg: #FF8A3D; --price-ink: #141414; --soft: #1C1C22;
  --g-bg: #17351D; --g-ink: #7FDB90; --b-bg: #14293D; --b-ink: #7FB8EA;
  --a-bg: #3A2B10; --a-ink: #F0B95A; --r-bg: #3D1714; --r-ink: #F09088;
  --n-bg: #26262E; --n-ink: #9A9AA6;
  --warn-bg: #3A2B10; --warn-ink: #F0B95A;
  --radius: 16px; --radius-sm: 12px;
  --nav-bg: #16161B; --shadow: none;
}

html[data-theme="minimal"] {
  --bg: #F6F6F8; --ink: #1C1C1E; --muted: #84848B; --card: #FFFFFF; --line: #E8E8EC;
  --head-bg: #F6F6F8; --head-ink: #1C1C1E; --accent: #FF8A3D; --accent-ink: #141414;
  --water: #9CC4DE;
  --price-bg: #F2F2F6; --price-ink: #3C3C43; --soft: #ECECF1;
  --g-bg: #E7F5EB; --g-ink: #1F7A38; --b-bg: #E9F1FC; --b-ink: #1D63B8;
  --a-bg: #FCF2DF; --a-ink: #8F6A10; --r-bg: #FBE9E7; --r-ink: #C0392B;
  --n-bg: #EFEFF4; --n-ink: #84848B;
  --warn-bg: #FCF2DF; --warn-ink: #8F6A10;
  --radius: 14px; --radius-sm: 10px;
  --nav-bg: #FFFFFF; --shadow: 0 1px 2px rgba(0,0,0,.04);
}

/* Dragging down from the top of a browser tab reloads the page. In an app
   that is never what you meant, and a reload has to start everything up
   again, so it is switched off. Scrolling inside the app is untouched. */
html, body { height: 100%; overscroll-behavior-y: none; }

body {
  /* Everything. It started as headings only, on the argument that the phone's own
     font is the one people read fastest. John, 8 Aug: the font is clear to read
     and using two of them looks mismatched. He is right, and one font used at
     four weights is a cleaner rule than two fonts used by category. */
  --head-font: Fredoka, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-family: var(--head-font);
  background: var(--bg);
  color: var(--ink);
  -webkit-text-size-adjust: 100%;
}

/* a form control does not inherit the page's font unless it is told to */
input, select, textarea, button { font-family: inherit; }

.hidden { display: none !important; }
.muted { color: var(--muted); }
.small { font-size: .85rem; }

/* ---------- screens ---------- */
.screen { display: none; min-height: 100vh; flex-direction: column; }
/* dvh is the height actually on screen, which shrinks and grows as the phone
   browser's own bars come and go. vh does not, and overshoots. */
@supports (min-height: 100dvh) { .screen { min-height: 100dvh; } }
.screen.active { display: flex; }

/* Fredoka, picked by John on 7 Aug 2026 from eight rendered at renders/fonts.html.
   Served from the app itself rather than from Google, because the app has to work
   with no signal and a heading in a fallback font on a phone with no bars is not
   a heading anybody chose. */
/* One font, four weights, and a rule for which goes where.

   700  the title of a screen, and the two words that are the home screen's title
   600  a section heading, a button, the name of a food or a cat
   500  a chip, a pill, a tag, a small capitalised label
   400  anything explaining something: a hint, the wording under a question, the
        line under a card

   Fredoka stops at 700. Twenty three rules in here asked for 800, which the
   browser cannot supply, so it thickened 700 itself and the result was a slightly
   smeared version of the real thing. They all say 700 now.

   Everything is in it now, set on the body, so this list is only about which
   things get which weight. */
h1, h2, h3, .fieldname, .fp-title, .cardbody .name, .big, .pill,
.asktitle, .askbody, .alert, .sheetbtn,
.pbtn, .widebtn, .danger, .linkbtn, .rowbtn, .offertoggle, .stockbought,
.stockcount span:first-child, .stocklabel, .foodpick .nm, .themecard,
.hint, .nocats, .empty, .worksout, .cardbody .brand, .eachnote, .brandsaid,
.catrow .nm, .cv-name, .req-name, .req-sub, .fp-set {
  font-family: var(--head-font);
  letter-spacing: -0.005em;
}


.topbar {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  /* the same padding above and below on every bar. The home bar needs twenty
     underneath for the version hanging below the logo, and if the others keep
     eight then their titles sit six lower than the home one even though both
     bars are the same height. */
  padding: calc(env(safe-area-inset-top, 0px) + 10px) 16px 20px;
  background: var(--head-bg); color: var(--head-ink);
  position: sticky; top: 0; z-index: 5;
}

/* The home screen's bar sizes itself against its own width rather than the
   window's, so the same rule works whatever it is put inside.

   The version sits beside the logo, on its baseline, not under it. Under it, it
   added a whole line the bar did not otherwise need, which made the bar tall
   enough that the two words looked stranded at the top of it. */
/* Every other bar matches the home one, so a title does not move as you go from
   screen to screen. The home bar sets that height and never receives it: giving
   it a floor made of its own measured height plus the safe area meant it grew a
   little every single time it was measured, and the words sank with it. */
.topbar:not(.homebar) { min-height: var(--barh, 64px); }
.homebar { container-type: inline-size; gap: clamp(6px, 2.5cqw, 16px); align-items: center; }
/* The version sits under the logo and takes up no height while doing it, so the
   logo alone sets the line that Cats, Cupboard, the paw and the door centre on.
   Counting the version towards the height made that block taller than the logo,
   and everything else centred on the block, which put it all above the logo's
   middle. */
.homebar .brand { position: relative; align-items: center; gap: 0; }
.homebar .version {
  position: absolute; top: 100%; left: 0; margin-top: 2px;
  pointer-events: none; white-space: nowrap;
}
.homebar .logo {
  width: clamp(40px, 13cqw, 56px); height: clamp(40px, 13cqw, 56px); max-width: none;
}
/* only the owner's logo is a way in. For everybody else it is a picture. */
.homebar #btn-settings.owner { cursor: pointer; }
/* the version is the last thing that needs the room, so below about 300 it goes.
   It is on the sign in screen and in Admin as well. */
.homebar .version { font-size: clamp(.56rem, 1.9cqw, .66rem); line-height: 1; }

/* every one of the three is centred on the same line, whatever height it is */
.homebar > * { align-self: center; }
/* icons tighter, the other half of option B */
.homebar .cornerrow { gap: 0; flex-shrink: 0; }
.homebar .cornerrow .iconbtn { width: clamp(1.5rem, 5.6cqw, 1.7rem); }
.homebar .iconbtn { width: 1.9rem; height: 1.9rem; }
.doorout { width: 21px; height: 21px; display: block; margin: 0 auto; }
.brand { display: flex; align-items: center; gap: 8px; min-width: 0; }

/* The logo is a full colour drawing now, so it is a picture rather than a one
   colour trace filled with the text colour. It is wider than it is tall, and it
   is used in boxes that are square, so it is fitted inside rather than
   stretched. */
.logo {
  width: 118px; height: 118px; max-width: 38vw; flex-shrink: 0; display: block;
  background: url(logo.webp) center / contain no-repeat;
}
/* On Midnight the cat is black on nearly black, so the logo wears the same thin
   white edge the cat faces wear. The word is white already and reads either way. */
html[data-theme="midnight"] .logo {
  background-image: url(logo-dark.webp);
}
/* Not the header colour. On Midnight that is the orange, and small orange
   text on black is hard to read. Same grey as the cat names in the panel. */
.version { font-size: .68rem; font-weight: 400; color: var(--muted); }

/* Nothing in the app capped its width, so on a tablet a food card became a very
   long thin strip with the photo at one end and the price at the other. The app
   is the same shape at any size now, centred, with the extra width left alone. */
.topbar, .scrollarea, #tab-cats, #tab-cupboard {
  width: 100%; max-width: 560px; margin-inline: auto;
}
/* clear of the round plus button and the phone's own bar at the bottom */
#tab-cats, #tab-cupboard {
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 92px);
}

.iconbtn {
  background: none; border: none; font-size: 1.35rem; width: 2.1rem; height: 2.1rem;
  cursor: pointer; color: inherit; flex-shrink: 0; padding: 0;
}

.scrollarea { padding: 16px 16px 40px; flex: 1; overflow-y: auto; }
.scrollarea h3 { margin: 22px 0 8px; font-size: 1rem; }
/* A faint line between each part of a long settings page, so it reads as
   separate blocks rather than one run of headings. Not before the first one,
   which has nothing above it to be separated from. */
.sections h3:not(:first-child) {
  border-top: 1px solid var(--line);
  margin-top: 30px; padding-top: 26px;
}

/* ---------- cat chips ---------- */
/* Wraps rather than scrolling sideways. Scrolling meant the last cat was cut
   in half at the right edge while the first sat neatly 16px from the left,
   which is what it looked like: uneven. Wrapped, both edges match and every
   cat is on screen. */
.catrow {
  display: flex; flex-wrap: wrap; gap: 8px; padding: 12px 16px 2px;
}
.catchip {
  display: flex; align-items: center; gap: 7px; flex-shrink: 0;
  padding: 5px 13px 5px 5px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  font-size: .87rem; font-weight: 600; cursor: pointer;
}
.catchip.plain { padding: 6px 13px; justify-content: center; }
.catchip.on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.avatar {
  width: 25px; height: 25px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: .72rem; font-weight: 700; background: var(--soft); color: var(--ink);
  background-size: cover; background-position: center;
}
/* A drawn face has no background behind it and is not clipped to a circle:
   the ears are part of the drawing and cutting them off makes it a blob. */
.avatar.drawn { background: none; border-radius: 0; overflow: visible; }
.catface { display: block; width: 100%; height: auto; }
/* No outline on the picture. It was drawn when the face was a circle inside a
   circle. Round a square picture of a cat it reads as a box somebody forgot to
   remove, and the chip already goes solid to say it is picked. */

/* ---------- choosing a cat's face ----------
   Shades and eyes are round swatches, markings are the face itself wearing
   that marking, because a word like "tortie" tells you nothing and the
   drawing tells you everything. Both rows scroll sideways so the block stays
   the same height however many options there are. */
.facepick {
  margin: 14px 0 4px; padding: 12px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius);
}
.fp-top { display: flex; align-items: center; gap: 12px; }
.fp-top > div { min-width: 0; }
.fp-preview { display: block; width: 76px; flex-shrink: 0; }
.fp-preview .catface { width: 100%; }
.fp-title { display: block; font-weight: 700; }
.fp-sofar {
  display: block; color: var(--muted); font-size: .78rem;
  line-height: 1.3; overflow-wrap: anywhere;
}
.fp-lab {
  display: block; margin: 14px 0 6px;
  font-size: .64rem; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--muted);
}
.fp-swatches, .fp-marks {
  display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none;
  padding-bottom: 2px;
}
.fp-swatches::-webkit-scrollbar, .fp-marks::-webkit-scrollbar { display: none; }
.fp-swatches .sw {
  width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0; padding: 0;
  border: 2px solid var(--line); cursor: pointer;
}
.fp-swatches .sw.on { border-color: var(--accent); box-shadow: 0 0 0 2px var(--card) inset; }
.fp-marks .mk {
  flex: 0 0 56px; padding: 5px 3px 4px; cursor: pointer; color: inherit;
  border: 1px solid var(--line); border-radius: 12px; background: var(--card);
  display: flex; flex-direction: column; align-items: center; gap: 1px;
}
.fp-marks .mk.on { border-color: var(--accent); }
.fp-marks .mk .f { display: block; width: 40px; }
.fp-marks .mk .f .catface { width: 100%; }
.fp-marks .mk .t { display: block; font-size: .56rem; color: var(--muted); line-height: 1.2; }

/* The faces to pick from. Four across, because five leaves each one too small
   to tell apart on a 320 wide phone. */
.fp-pics { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 12px; }
.fp-pics .pic {
  padding: 6px; cursor: pointer; color: inherit;
  border: 1px solid var(--line); border-radius: 12px; background: var(--card);
}
.fp-pics .pic.on { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.fp-pics .pic .catface { width: 100%; }

/* Their face, or their photo, is the way in to editing. A pencil on its own in
   the corner of the bar was somewhere nobody looks. */
.catbigbtn {
  position: relative; flex-shrink: 0; padding: 0; border: none;
  background: none; color: inherit; cursor: pointer; line-height: 0;
}
.catbig.drawn { background: none; }
.catbig.drawn .catface { width: 100%; height: auto; }
.catpen {
  position: absolute; right: 2px; bottom: 2px;
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--card); border: 1px solid var(--line); color: var(--muted);
  font-size: 1rem; line-height: 28px; text-align: center;
}

/* Admin used to send you to another screen to see your cats. They are here now. */
.catrows { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.catrow {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 9px 12px; cursor: pointer; color: inherit; text-align: left;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
}
.catrow .avatar { width: 40px; height: 40px; }
.catrow .nm { font-weight: 700; flex: 1; min-width: 0; overflow-wrap: anywhere; }
.catrow .chev { color: var(--muted); font-size: 1.3rem; flex-shrink: 0; }
/* how many foods carry this brand, or where it has been sent */
.brandsaid { color: var(--muted); font-size: .78rem; flex-shrink: 0; text-align: right; }

/* ---------- search and filters ---------- */
.searchrow { padding: 12px 16px 0; }
.searchrow input {
  width: 100%; padding: 11px 14px; font-size: 1rem; color: inherit;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--card);
}
.chips { display: flex; gap: 7px; padding: 10px 16px; overflow-x: auto; scrollbar-width: none; }

/* Cats or the cupboard. The two words are the title of the screen: the one you
   are on is in the ink colour and the other is grey. They were a pair of orange
   pills on their own line, which was a whole line spent saying what the screen
   already is. */
/* The size is set in code, by measuring the gap the logo and the icons leave and
   filling it. See fitHomeTabs. Nothing here fixes a size, because no fixed size
   can fill a gap that is a different width on every phone. */
/* Not drawn until it has been measured. One frame of the words at the size they
   inherit, followed by them jumping to the size they should be, is the app
   rearranging itself in front of you. */
.hometabs:not(.fitted) { visibility: hidden; }
.hometabs {
  display: flex; align-items: center; justify-content: center;
  flex: 1 1 auto; min-width: 0; gap: .45em;
  /* clear space either side, so the words never sit against the logo or a paw.
     fitHomeTabs takes this off the room it has to fill, so the words hold their
     size rather than growing into the gap it just made. */
  padding-inline: clamp(10px, 4cqw, 22px);
}
.hometab {
  padding: 0; border: none; background: none; cursor: pointer;
  font-family: var(--head-font); font-weight: 700; white-space: nowrap;
  /* 1, so the box round the words is the words. Anything looser and the block
     centres on empty space above and below them rather than on the letters,
     which is what put them off the logo's line. */
  font-size: 1em; color: var(--muted); line-height: 1;
}
.hometab.on { color: var(--ink); }
.doneline { display: flex; gap: 8px; margin-top: 14px; }
.doneline .chip { flex: 1; text-align: center; }

/* One panel holding everything the one filter can do. Cats, foods and order,
   each with a word over it, so nothing is hidden behind a second tap. */
.filterpanel {
  margin: 0 16px 4px; padding: 4px 12px 12px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
}
/* In the filter panel the heading is the way in and out of its group, so it is a
   button the full width of the panel with a little arrow on the end, and it says
   in plain words what is set inside it while it is shut. */
.filterpanel .fp-lab {
  margin: 4px 0 0; width: 100%; text-align: left; cursor: pointer;
  border: none; border-top: 1px solid var(--line); background: none;
  padding: 12px 2px; display: flex; align-items: center; gap: 8px;
}
.filterpanel .fp-lab:first-of-type { border-top: none; }
.filterpanel .fp-lab::after {
  content: "\25be"; margin-left: auto; font-size: .8rem;
  color: var(--muted); transition: transform .12s;
}
.filterpanel .fp-lab.open::after { transform: rotate(180deg); }
.filterpanel .fp-lab .fp-set {
  font-size: .68rem; font-weight: 600; letter-spacing: 0; text-transform: none;
  color: var(--accent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.filterpanel .fp-group { padding-bottom: 8px; }
.filterpanel .chips, .filterpanel .catrow { padding-left: 0; padding-right: 0; }
.pill.open::after { transform: rotate(180deg); display: inline-block; }
.chips::-webkit-scrollbar { display: none; }
/* Every row of chips in the app is a set of choices about the screen you are on,
   the same job the title above them does, so they are set in the heading font a
   size down from it. That covers the filter panel, the order, which food, the
   Admin tabs, the categories and the rest, in one place. */
.chip {
  flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  padding: 6px 13px; border-radius: 999px; cursor: pointer;
  font-family: var(--head-font); font-weight: 600; font-size: .82rem;
  white-space: nowrap; line-height: 1.25; text-align: center;
}
.chip.on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }

/* ---------- cards ---------- */
.cards { padding: 4px 16px; display: flex; flex-direction: column; gap: 10px; }

/* The way in and out of the archived food. A row rather than a card, because it
   is not a food, and under the list rather than over it, because the cupboard is
   what you came for. */
.archiverow {
  width: 100%; padding: 12px; border-radius: var(--radius-sm); cursor: pointer;
  border: 1px dashed var(--line); background: transparent; color: var(--muted);
  font-family: var(--head-font); font-weight: 600; font-size: .84rem; text-align: center;
}
#screen-list .cards { padding-bottom: 110px; }
#screen-list #pending { padding: 14px 16px 0; }
#screen-list #pending h3 { margin: 0 0 6px; font-size: 1rem; }

/* ---------- the cat panel ---------- */
/* Tapping a cat opens them here rather than taking you somewhere else, so the
   cupboard underneath stays filtered to that cat at the same time. All cats
   gives the whole house, which is what used to sit at the bottom of the home
   screen as "Recent feeds". */
.catpanel {
  /* space under the card, not inside it, so there is background between the
     bottom of the card and the bottom of the screen */
  margin: 10px 16px 16px; padding: 4px 12px 8px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius);
}
.catpanel .facts:empty { display: none; }
.catpanel .fact {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 5px 0; font-size: .84rem;
}
.catpanel .fact .k { font-weight: 700; }
.catpanel .fact .v { color: var(--muted); text-align: right; }
/* Their last few bowls in a row. One look instead of a paragraph. */
.strip { display: flex; gap: 6px; overflow-x: auto; padding: 8px 0 4px; scrollbar-width: none; }
.strip::-webkit-scrollbar { display: none; }
.strip .s {
  flex: 0 0 62px; border: 1px solid var(--line); border-radius: 10px;
  padding: 5px 4px; text-align: center;
}
.strip .s .w {
  display: block; font-size: .58rem; font-weight: 700; color: var(--muted);
  margin-top: 1px;
}
/* With All cats picked it is the cats themselves, one face each, with a
   small bowl on the corner saying how their last feed went. */
.strip.faces .s {
  border: none; background: none; padding: 2px 2px 4px; cursor: pointer;
  flex: 0 0 64px; color: inherit;
}
.strip.faces .face { position: relative; display: block; }
.strip.faces .face .badge {
  position: absolute; right: -6px; bottom: -4px; width: 30px; display: block;
}
.strip.faces .s .w {
  display: block; font-size: .68rem; font-weight: 700; color: var(--ink);
  margin-top: 2px; overflow-wrap: anywhere;
}
.strip.faces .s .ago { display: block; font-size: .58rem; color: var(--muted); }

/* A feed, read as when, what came back, who, and what they had. The times
   run down the left with a thread through the bowls, so the column is an
   order of events rather than a wall of sentences. */
.catpanel .history li {
  display: grid; grid-template-columns: 50px 40px 1fr 22px;
  align-items: center; column-gap: 8px; padding: 2px 0; border-bottom: none;
}
.catpanel .history .when {
  min-width: 0; text-align: right; font-size: .72rem; color: var(--muted);
}
.catpanel .history .spine {
  position: relative; display: block; padding: 4px 0;
}
.catpanel .history .spine::before {
  content: ""; position: absolute; left: 50%; top: -8px; bottom: -8px; width: 1px;
  background: var(--line); transform: translateX(-50%);
}
.catpanel .history li:first-child .spine::before { top: 50%; }
.catpanel .history li:last-child .spine::before { bottom: 50%; }
.catpanel .history .spine .b {
  position: relative; display: block; width: 40px; background: var(--card);
}
.catpanel .history li > span:nth-child(3) { font-size: .84rem; min-width: 0; }
.catpanel .history .restask { grid-column: 3 / -1; margin: 0 0 8px; }
.catpanel .history li { padding: 8px 0; }

.card {
  display: flex; gap: 12px; align-items: center; cursor: pointer;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 11px; box-shadow: var(--shadow);
}
/* Portrait and contained, not a square crop. The flavour is usually printed at
   the top of a pack and a square crop of the middle threw it away. */
.thumb {
  width: 54px; height: 72px; border-radius: var(--radius-sm); flex-shrink: 0;
  background: var(--soft) no-repeat center/contain;
  display: flex; align-items: center; justify-content: center; font-size: 1.5rem;
}
/* A cat is square, a pack of food is portrait. They share the card, not the
   shape of the picture on it. */
.thumb.catthumb { width: 56px; height: 56px; }
.thumb.catthumb.drawn { background: none; padding: 2px; }
.thumb.catthumb .catface { display: block; width: 100%; height: auto; }
.cardbody { flex: 1; min-width: 0; }
.cardbody .name { font-weight: 700; font-size: .97rem; overflow-wrap: anywhere; }
.cardbody .brand { color: var(--muted); font-size: .82rem; margin-top: 1px; }
/* what kind of food it is, quiet enough not to compete with the name */
/* What each cat thinks, on the card. The cat, and their fishbone directly under
   them. Fixed width columns so the fishbones line up in a row rather than
   hanging off whichever face happens to be widest. */
.whothinks { display: flex; gap: 10px; margin-top: 8px; flex-wrap: wrap; }
/* four cats have to fit across a 320 wide phone without wrapping */
@media (max-width: 380px) {
  .whothinks { gap: 7px; }
  .wt { width: 26px; }
  .wt .avatar { width: 24px; height: 24px; }
  .wt-em { width: 22px; }
}
.wt {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  width: 30px; line-height: 0;
}
.wt .avatar { width: 28px; height: 28px; }
.wt-em { width: 26px; }
.cardbody .kind {
  display: inline-block; margin-top: 5px; padding: 2px 8px;
  border-radius: 999px; background: var(--n-bg); color: var(--n-ink);
  font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
}
.cardmeta { display: flex; align-items: center; gap: 7px; margin-top: 6px; flex-wrap: wrap; }
.cardright {
  display: flex; flex-direction: column; align-items: flex-end; gap: 5px;
  flex-shrink: 0; max-width: 42%;
}

.stamp {
  font-size: .66rem; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  padding: 4px 9px; border-radius: 999px; line-height: 1.2; text-align: center;
  overflow-wrap: anywhere;
}
.stamp.favourite { background: var(--g-bg); color: var(--g-ink); }
.stamp.eats      { background: var(--b-bg); color: var(--b-ink); }
.stamp.fussy     { background: var(--a-bg); color: var(--a-ink); }
.stamp.refused   { background: var(--r-bg); color: var(--r-ink); }
.stamp.none      { background: var(--n-bg); color: var(--n-ink); }

.who { font-size: .7rem; color: var(--muted); text-align: right; overflow-wrap: anywhere; }

.pricetag {
  background: var(--price-bg); color: var(--price-ink);
  font-size: .74rem; font-weight: 700; padding: 3px 8px; border-radius: 6px;
  overflow-wrap: anywhere;
}
.pricetag .store { font-weight: 400; }

.empty { text-align: center; color: var(--muted); padding: 34px 24px; }

/* ---------- household banner ---------- */
.banner {
  padding: 11px 14px; border-radius: var(--radius-sm); font-size: .88rem;
  margin: 14px 0 4px; line-height: 1.45;
}
.banner.good { background: var(--g-bg); color: var(--g-ink); font-weight: 600; }
.banner.bad  { background: var(--r-bg); color: var(--r-ink); font-weight: 600; }
.banner.warn { background: var(--warn-bg); color: var(--warn-ink); }
.banner strong { display: block; }

.mini {
  font-size: .64rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
  padding: 3px 7px; border-radius: 5px;
}
.mini.good { background: var(--g-bg); color: var(--g-ink); }
.mini.ok   { background: var(--b-bg); color: var(--b-ink); }
.mini.meh  { background: var(--a-bg); color: var(--a-ink); }
.mini.bad  { background: var(--r-bg); color: var(--r-ink); }

/* ---------- per cat verdict rows ---------- */
.catverdicts { display: flex; flex-direction: column; gap: 10px; }
.cv {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 10px 11px;
}
.cv-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.cv-name { font-weight: 700; font-size: .92rem; overflow-wrap: anywhere; min-width: 0; }
.cv-opts { display: flex; gap: 6px; flex-wrap: wrap; }
.cv-opts button {
  flex: 1 1 auto; min-width: 62px; padding: 8px 6px; border-radius: 9px;
  border: 1px solid var(--line); background: var(--bg); color: var(--ink);
  font-size: .76rem; font-weight: 600; cursor: pointer;
}
.cv-opts button.on[data-v="favourite"] { background: var(--g-bg); color: var(--g-ink); border-color: var(--g-ink); }
.cv-opts button.on[data-v="eats"]      { background: var(--b-bg); color: var(--b-ink); border-color: var(--b-ink); }
.cv-opts button.on[data-v="fussy"]     { background: var(--a-bg); color: var(--a-ink); border-color: var(--a-ink); }
.cv-opts button.on[data-v="refused"]   { background: var(--r-bg); color: var(--r-ink); border-color: var(--r-ink); }

.nocats { color: var(--muted); font-size: .88rem; padding: 6px 2px; }

/* the name as printed on a foreign pack, kept quiet under the English one */
.original {
  color: var(--muted); font-size: .82rem; margin: 4px 0 12px;
  overflow-wrap: anywhere;
}

/* ---------- detail ---------- */
/* contain, not cover. Cover crops to fill, which on a tall pouch means a
   rectangle out of the middle of the packet: no name, no brand, no use to
   anybody standing in a shop. Tapping it opens the whole thing full size. */
.bigphoto {
  width: 100%; height: 230px; border-radius: var(--radius);
  background: var(--soft) no-repeat center/contain;
  display: flex; align-items: center; justify-content: center; font-size: 2.2rem;
  border: 1px solid var(--line); padding: 0; color: inherit; cursor: pointer;
}

/* The app asking, rather than the browser asking on the app's behalf. */
.ask {
  position: fixed; inset: 0; z-index: 70; background: rgba(0,0,0,.6);
  display: flex; align-items: flex-end; justify-content: center;
  padding: 16px 16px calc(env(safe-area-inset-bottom, 0px) + 16px);
}
/* A question with two answers fits anywhere. A question with twenty, which is
   what picking a brand out of a full cupboard is, ran off the bottom of the
   screen and the last few could not be reached at all. It is as tall as it needs
   to be up to the height of the screen, and scrolls inside itself after that. */
.askbox {
  width: 100%; max-width: 420px; background: var(--card);
  border: 1px solid var(--line); border-radius: var(--radius); padding: 18px;
  display: flex; flex-direction: column; gap: 10px;
  max-height: calc(100dvh - 32px - env(safe-area-inset-bottom, 0px));
  overflow-y: auto; overscroll-behavior: contain;
}
/* nothing in here shrinks to make room. A button squashed to fit is a button
   nobody can read */
.askbox > * { flex-shrink: 0; }
.asktitle { font-size: 1.02rem; font-weight: 700; }
.askbody { color: var(--muted); font-size: .88rem; line-height: 1.45; }
.askbody:empty { display: none; }

.photofull {
  position: fixed; inset: 0; z-index: 60; background: rgba(0,0,0,.92);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; padding: 16px;
}
.photofull img { max-width: 100%; max-height: 82vh; object-fit: contain; border-radius: 8px; }
.photofull-hint { color: #BBB; font-size: .8rem; }
.detail-head { margin: 14px 0 2px; }
.detail-head h2 { font-size: 1.3rem; overflow-wrap: anywhere; }

.pricerow { display: flex; gap: 8px; }
.pricerow input {
  flex: 1; min-width: 0; padding: 10px 12px; font-size: 1rem; color: inherit;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--card);
}
.pricerow button {
  padding: 10px 16px; border: none; border-radius: var(--radius-sm);
  background: var(--accent); color: var(--accent-ink); font-weight: 700; cursor: pointer;
}

/* "that bought [12]  £0.38 each". The per item cost is the number worth
   comparing in a shop, so it is worked out while you type rather than only
   after saving. */
.forrow { display: flex; align-items: center; gap: 10px; margin-top: 8px; flex-wrap: wrap; }
.forlabel {
  display: flex; align-items: center; gap: 7px;
  font-size: .84rem; color: var(--muted); font-weight: 600;
}
.forlabel input {
  width: 68px; padding: 7px 9px; font-size: .95rem; color: inherit; text-align: center;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--card);
}
.eachnote { font-size: .84rem; font-weight: 700; color: var(--accent); }

/* Three real columns rather than a flex row, so the dates and the remove
   buttons line up down the list instead of sitting wherever the text on
   their left happens to end. The date column is right aligned and wide
   enough for the longest date any locale will produce. */
.history { list-style: none; margin-top: 2px; padding-left: 0; }
.history li {
  display: grid; grid-template-columns: 1fr auto 26px; align-items: center;
  column-gap: 10px;
  padding: 10px 2px; border-bottom: 1px solid var(--line); font-size: .93rem;
}
.history li span:first-child { min-width: 0; overflow-wrap: anywhere; }
/* Asking what became of the part that was put away. It sits under the feed it
   belongs to and spans the whole row. */
.restask {
  grid-column: 1 / -1; display: flex; align-items: center; flex-wrap: wrap;
  gap: 8px; margin-top: 8px;
}
.restask span { color: var(--muted); font-size: .8rem; }
.restask .chip { font-size: .78rem; padding: 5px 11px; }
/* a feed on a cat's own screen: the flavour, then the brand and what kind of
   food it is under it, a weight up from the flavour the way the feed log does */
.hist-what { display: block; }
.hist-brand {
  display: block; color: var(--muted); font-size: .74rem; font-weight: 500;
  line-height: 1.25; margin-top: 1px;
}
/* What somebody wrote down about a cat being sick, under the line saying what
   it followed. Their own words, so it is set apart from the app's. */
.sicknote {
  display: block; color: var(--ink); font-size: .76rem; font-weight: 500;
  line-height: 1.3; margin-top: 3px; padding-left: 8px;
  border-left: 2px solid var(--line); overflow-wrap: anywhere;
}

/* The line that starts a sitting in the day's feed list.

   It keeps the same columns as the feeds under it rather than being its own
   flex row, so the paw sits over the middle of the times and the sitting's
   name over the middle of the bowls. Laid out by hand it drifted a column to
   the left of both. */
.sitting {
  grid-column: 1 / -1; align-items: center;
  border-bottom: none; background: var(--bg);
  margin: 8px 0 0; padding: 8px 0; border-radius: 10px;
  display: grid; grid-template-columns: inherit; column-gap: inherit;
}
/* Centred on the time itself, not on the time's column. The times are left
   aligned in a column wider than they are, so the column's middle is about
   eleven pixels right of where a time actually reads. A time starts at the
   column's left edge and runs 23 to 28 pixels wide, so its middle is about
   twelve in, which is where the paw's middle goes. */
.sitting-paw {
  grid-column: 1; justify-self: start; margin-left: 7px;
  width: 15px; height: 15px; background-color: var(--accent);
  -webkit-mask: url(paw.svg) center / contain no-repeat;
          mask: url(paw.svg) center / contain no-repeat;
}
/* centred on the bowls, and allowed out of its column so a longer name stays
   centred rather than wrapping inside 42px */
.sitting-name {
  grid-column: 2; justify-self: center; white-space: nowrap; overflow: visible;
  font-size: .78rem; font-weight: 700; color: var(--ink);
}
.sitting-count {
  /* padding rather than a margin on the band: shifting the band would shift
     its columns with it, and the paw would come off the times */
  grid-column: 4; justify-self: end; padding-right: 8px;
  font-size: .72rem; color: var(--muted); white-space: nowrap;
}

.history .when {
  color: var(--muted); font-size: .78rem;
  min-width: 78px; text-align: right; white-space: nowrap;
}
.history .rm {
  background: none; border: none; color: var(--r-ink); font-size: 1.1rem;
  cursor: pointer; padding: 0; width: 26px; text-align: center;
}

/* ---------- forms ---------- */
label { display: block; margin-top: 14px; font-weight: 600; font-size: .9rem; }
label input, .barcoderow input {
  width: 100%; margin-top: 6px; padding: 11px 12px; font-size: 1rem; font-weight: 400;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--card); color: inherit;
}
.fieldname { margin-top: 20px; margin-bottom: 8px; font-weight: 600; font-size: .9rem; }
/* A box on its own under a fieldname, rather than inside a label. Same box as
   every other one in the app, it just has its heading above it already. */
.widein {
  width: 100%; padding: 11px 12px; font-size: 1rem; font-weight: 400;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--card); color: inherit;
}
.widein + .hint { margin-top: 8px; }


.barcoderow { display: flex; gap: 8px; }
.barcoderow button {
  margin-top: 6px; width: 46px; flex-shrink: 0; border: 1px solid var(--line);
  border-radius: var(--radius-sm); background: var(--card); color: inherit;
  font-size: 1.15rem; cursor: pointer;
}

.photopick {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-height: 132px; border: 2px dashed var(--line); border-radius: var(--radius);
  background: var(--card); cursor: pointer; text-align: center; padding: 10px;
  color: var(--muted); font-weight: 400; margin-top: 0; overflow: hidden;
}
.photopick img { max-width: 100%; max-height: 230px; border-radius: var(--radius-sm); }

.photobtns { display: flex; gap: 9px; margin-top: 10px; }
.pbtn {
  flex: 1; margin-top: 0; text-align: center; cursor: pointer;
  padding: 12px 8px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  font-size: .92rem; font-weight: 700;
}

/* A note under something needs air above it as well as below, or it reads as
   part of the control it is explaining rather than a note about it. */
.hint {
  color: var(--muted); font-size: .85rem; line-height: 1.45;
  margin-top: 8px; margin-bottom: 12px;
}
/* except straight after its own heading, where the heading's own spacing is
   already doing the job */
h3 + .hint, .fieldname + .hint { margin-top: 0; }

.editmark { color: var(--muted); font-size: 1.15rem; flex-shrink: 0; padding-left: 4px; }

.big {
  display: block; width: 100%; margin-top: 16px; padding: 14px;
  font-size: .95rem; font-weight: 700; border-radius: var(--radius-sm); border: none;
  background: var(--accent); color: var(--accent-ink); cursor: pointer; text-align: center;
}
.big.secondary { background: var(--card); color: var(--ink); border: 1px solid var(--line); }
.filelabel { font-weight: 700; }

/* The same shape as Delete, in the ordinary colours. Archiving is not a warning,
   so it should not be sat there in red, but the two belong together at the foot
   of the screen so they line up. */
.widebtn {
  margin-top: 22px; width: 100%; padding: 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  font-size: .95rem; font-weight: 600; cursor: pointer;
}
.danger + .widebtn, .widebtn + .danger { margin-top: 10px; }

.danger {
  margin-top: 26px; width: 100%; padding: 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--r-ink); background: var(--r-bg); color: var(--r-ink);
  font-size: .95rem; font-weight: 600; cursor: pointer;
}

/* ---------- add to home screen ---------- */
/* Sits along the bottom, on top of everything, and everything fixed to the
   bottom moves up out of its way while it is there. Its height is measured into
   --installh in code, because it is two lines on a narrow phone and one on a
   wide one and nothing here can know which. */
.installbar {
  position: fixed; z-index: 8; left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px calc(env(safe-area-inset-bottom, 0px) + 12px);
  background: var(--card); border-top: 1px solid var(--line);
  box-shadow: 0 -6px 20px rgba(0,0,0,.10);
}
.installmark {
  width: 42px; height: 42px; flex-shrink: 0; display: block;
  background: url(logo.webp) center / contain no-repeat;
}
html[data-theme="midnight"] .installmark { background-image: url(logo-dark.webp); }
.installwords { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.installwords strong {
  font-family: var(--head-font); font-size: .92rem; font-weight: 700;
  line-height: 1.2; color: var(--ink);
}
.installwords span { font-size: .76rem; color: var(--muted); line-height: 1.3; }
.installgo {
  flex-shrink: 0; margin-left: auto; padding: 10px 16px; border: none;
  border-radius: 999px; background: var(--accent); color: var(--accent-ink);
  font-family: var(--head-font); font-weight: 700; font-size: .9rem; cursor: pointer;
}
.installx {
  flex-shrink: 0; width: 30px; height: 30px; padding: 0; line-height: 1;
  border: none; background: none; color: var(--muted); font-size: .95rem; cursor: pointer;
}
/* the round plus button and the bottom of every list clear the bar */
html.hasinstall .fab { bottom: calc(env(safe-area-inset-bottom, 0px) + 18px + var(--installh, 0px)); }
html.hasinstall #tab-cats, html.hasinstall #tab-cupboard {
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 92px + var(--installh, 0px));
}
html.hasinstall .signin { padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px) + var(--installh, 0px)); }

/* ---------- themes picker ---------- */
.themes { display: flex; gap: 9px; }
.themecard {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 7px;
  padding: 11px 6px; border-radius: var(--radius-sm);
  border: 2px solid var(--line); background: var(--card); color: var(--ink);
  font-size: .8rem; font-weight: 600; cursor: pointer;
}
.themecard.on { border-color: var(--accent); }
.sw { width: 100%; height: 30px; border-radius: 8px; display: block; }
.sw-scandi   { background: linear-gradient(120deg, #F6F6F8 0 50%, #6FA98C 50% 100%); border: 1px solid #E4EBE6; }
.sw-midnight { background: linear-gradient(120deg, #1C1C22 0 50%, #FF8A3D 50% 100%); border: 1px solid #2A2A33; }
.sw-minimal  { background: linear-gradient(120deg, #FFFFFF 0 50%, #FF8A3D 50% 100%); border: 1px solid #E8E8EC; }

/* ---------- the round button ---------- */
/* No bar behind it any more. It floats where the bar used to be, so the list
   carries on underneath instead of being cut off by a strip of chrome. */
.fab {
  position: fixed; z-index: 6;
  left: 50%; transform: translateX(-50%);
  bottom: calc(env(safe-area-inset-bottom, 0px) + 18px);
  width: 58px; height: 58px; padding: 0;
  border-radius: 50%; border: none; font-size: 0;
  background: var(--accent); color: var(--accent-ink);
  cursor: pointer; box-shadow: 0 6px 18px rgba(0,0,0,.22);
}
.fab::before, .fab::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  background: currentColor; border-radius: 2px;
}
.fab::before { width: 22px; height: 3px; transform: translate(-50%, -50%); }
.fab::after  { width: 3px; height: 22px; transform: translate(-50%, -50%); }
.fab .plus { position: absolute; width: 1px; height: 1px; overflow: hidden; opacity: 0; }

/* ---------- scanner ---------- */
#scanner {
  position: fixed; inset: 0; background: #000; z-index: 50;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
#scan-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.scan-guide {
  width: 78%; max-width: 420px; height: 158px; border: 3px solid var(--accent);
  border-radius: 14px; z-index: 51; box-shadow: 0 0 0 2000px rgba(0,0,0,.35);
}
#scan-hint { color: #fff; z-index: 51; margin-top: 16px; text-align: center; padding: 0 24px; }
#btn-scan-close {
  z-index: 51; margin-top: 20px; padding: 12px 28px; border-radius: 999px; border: none;
  background: var(--accent); color: var(--accent-ink); font-weight: 700; cursor: pointer;
}


/* ---------- today panel in the header ---------- */
/* Two columns need about 130px each. On the narrowest phones there is not
   room, and a long name starts breaking in the middle of itself, so below
   that they go back to one under the other. */
/* ---------- what needs doing ---------- */
/* The first thing on the home screen. Bordered in the accent colour because
   it is the one thing on the screen asking you to do something. */
.feedcard {
  margin: 10px 16px 0; padding: 12px;
  border: 1px solid var(--accent); border-radius: var(--radius);
  background: var(--card);
}
.feedhead { font-size: .84rem; font-weight: 700; margin-bottom: 8px; line-height: 1.35; }
.feedrow {
  display: flex; align-items: center; gap: 10px; padding: 5px 0;
  cursor: pointer; background: none; border: none; width: 100%; text-align: left;
  color: inherit;
}
.feedrow .avatar { width: 26px; height: 26px; font-size: .72rem; }
.feedname { flex: 1; min-width: 0; font-weight: 600; font-size: .92rem; overflow-wrap: anywhere; }
.feedbtn {
  border: none; border-radius: 999px; background: var(--accent); color: var(--accent-ink);
  font-weight: 700; font-size: .8rem; padding: 7px 16px; cursor: pointer; flex-shrink: 0;
}
.donebtn {
  border: 1px solid var(--line); border-radius: 999px; background: transparent;
  color: var(--muted); font-weight: 700; font-size: .78rem; padding: 6px 13px;
  cursor: pointer; flex-shrink: 0; white-space: nowrap;
}

/* Worth knowing, not worth interrupting for. */
.alerts { display: flex; flex-wrap: wrap; gap: 8px; padding: 10px 16px 0; }
.alerts:empty { display: none; }
.alert {
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  border-radius: 999px; padding: 7px 13px; font-size: .8rem; font-weight: 600;
  cursor: pointer; text-align: left; max-width: 100%; overflow-wrap: anywhere;
}

/* One word each until tapped. */
.rowpad { display: flex; flex-wrap: wrap; gap: 8px; padding: 10px 16px 0; }
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  border-radius: 999px; padding: 7px 14px; font-size: .84rem; font-weight: 600;
  cursor: pointer;
}
.pill.set { border-color: var(--accent); color: var(--accent); }
.pill::after { content: " \25be"; color: var(--muted); }
/* Option D, John's pick, 10 Aug: the two pills each own a full line, so the
   long wording never leaves a stranded gap beside the first pill. The feeding
   pill presses rather than opens, so it carries no arrow. */
#filter-row { flex-direction: column; align-items: stretch; }
#filter-row .pill { width: 100%; justify-content: center; }
#pill-feeding::after { content: none; }

/* ---------- what the plus button offers ---------- */
.sheetwrap { position: fixed; inset: 0; z-index: 45; }
.sheetdim { position: absolute; inset: 0; background: rgba(0,0,0,.55); }
.sheet {
  position: absolute; left: 0; right: 0; bottom: 0; background: var(--card);
  border-top: 1px solid var(--line); border-radius: 18px 18px 0 0;
  padding: 10px 16px calc(env(safe-area-inset-bottom, 0px) + 20px);
}
.sheet .grab { width: 40px; height: 4px; border-radius: 2px; background: var(--line); margin: 0 auto 14px; }
.sheetbtn {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  padding: 14px; margin-bottom: 8px; border-radius: 14px;
  border: 1px solid var(--line); background: var(--bg); color: var(--ink);
  font-size: 1rem; font-weight: 700; cursor: pointer;
}
.sheetbtn .ic { font-size: 1.3rem; width: 28px; text-align: center; flex-shrink: 0; }
.sheetbtn .sub { display: block; font-weight: 500; font-size: .8rem; color: var(--muted); margin-top: 2px; }
.sheetbtn .fishicon, .sheetbtn .barcodeicon { width: 28px; height: 22px; flex-shrink: 0; }

/* a barcode, drawn rather than fetched, so there is no extra file to load */
.barcodeicon {
  display: inline-block; width: 26px; height: 20px; background-color: currentColor;
  -webkit-mask: repeating-linear-gradient(90deg, #000 0 2px, transparent 2px 4px,
                #000 4px 7px, transparent 7px 9px, #000 9px 10px, transparent 10px 13px,
                #000 13px 16px, transparent 16px 17px, #000 17px 19px, transparent 19px 22px,
                #000 22px 24px, transparent 24px 26px);
          mask: repeating-linear-gradient(90deg, #000 0 2px, transparent 2px 4px,
                #000 4px 7px, transparent 7px 9px, #000 9px 10px, transparent 10px 13px,
                #000 13px 16px, transparent 16px 17px, #000 17px 19px, transparent 19px 22px,
                #000 22px 24px, transparent 24px 26px);
}

/* ---------- logging a feed ---------- */
.whocard {
  border: 1px solid var(--line); border-radius: 14px; background: var(--card); padding: 6px 10px;
}
.whorow {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 4px;
  background: none; border: none; color: inherit; text-align: left; cursor: pointer;
  border-bottom: 1px solid var(--line);
}
.whorow:last-child { border-bottom: none; }
.whorow .box {
  width: 26px; height: 26px; border-radius: 8px; border: 2px solid var(--line);
  flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  font-weight: 900; font-size: .9rem;
}
.whorow.on .box { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.whorow .nm { flex: 1; min-width: 0; font-weight: 700; font-size: .95rem; overflow-wrap: anywhere; }
.whorow .st { font-size: .78rem; color: var(--muted); flex-shrink: 0; }

.foodpick {
  display: flex; gap: 10px; align-items: center; width: 100%; text-align: left;
  padding: 10px; border-radius: 14px; border: 2px solid var(--line);
  background: var(--card); color: var(--ink); margin-bottom: 10px; cursor: pointer;
}
.foodpick.on { border-color: var(--accent); background: var(--soft); }
.foodpick .shot {
  width: 50px; height: 66px; border-radius: 10px; flex-shrink: 0;
  background: var(--soft) no-repeat center/contain;
  display: flex; align-items: center; justify-content: center; font-size: 1.5rem;
}
.foodpick .words { flex: 1; min-width: 0; }
.foodpick .nm { display: block; font-weight: 700; font-size: .97rem; overflow-wrap: anywhere; }
.foodpick .sb { display: block; font-size: .8rem; color: var(--muted); margin-top: 2px; overflow-wrap: anywhere; }
.foodpick .tick {
  width: 26px; height: 26px; border-radius: 50%; border: 2px solid var(--line);
  flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  font-weight: 900; font-size: .9rem;
}
.foodpick.on .tick { border-color: var(--accent); background: var(--accent); color: var(--accent-ink); }

/* The day and the clock, side by side. Only shown when a feed already exists,
   because a new one is being logged as it happens. */
.whenpair { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.whenpair input {
  font: inherit; font-size: .95rem; padding: 11px 12px; min-width: 0;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--card); color: var(--ink);
}

.amtbig { display: flex; gap: 8px; }
.amtbig button {
  flex: 1; padding: 15px 4px; border-radius: 14px; border: 2px solid var(--line);
  background: var(--card); color: var(--ink); font-size: 1.15rem; font-weight: 700;
  cursor: pointer;
}
.amtbig button.on { border-color: var(--accent); background: var(--accent); color: var(--accent-ink); }
.amtbig .lbl { display: block; font-size: .62rem; font-weight: 700; color: var(--muted); margin-top: 3px; }
.amtbig button.on .lbl { color: inherit; opacity: .8; }
.amtbig button.on .lbl { color: var(--accent-ink); }

/* How much they ate: a row each, with a bowl showing the amount. Seven words
   side by side were seven guesses at what they meant. */
/* Each answer is its own rounded button rather than a row in one long box. The
   ring that says chosen then follows the corners, which it could not do when the
   rows were square and the box around them was doing the rounding. */
.ate { display: flex; flex-direction: column; gap: 8px; }
.ate button {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 6px 12px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--card); color: var(--ink); text-align: left; cursor: pointer;
}
/* Chosen is a ring in the accent colour, not a grey wash. A wash reads as the
   row being switched off rather than picked. */
.ate button.on { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
/* Not sure yet is one of the answers, drawn the same way, in a box of its own so
   the seven amounts still read as one run from full to empty. */
.ate.notsure { margin-bottom: 8px; }
.ate .ic { width: 58px; flex-shrink: 0; }
.ate .tx { min-width: 0; }
.ate .w { display: block; font-weight: 700; font-size: .9rem; }
.ate .d { display: block; color: var(--muted); font-size: .74rem; margin-top: 1px; }

/* The bowl itself. The fishbone is the app's own file laid over the drawing
   as a mask, so it is the same fishbone as the rest of the app rather than a
   worse copy of it, and it takes whatever colour it is given. */
.bowlwrap { position: relative; display: block; }
/* A treat sits where a bowl would, so the column still lines up. */
.bowl.treat { color: var(--accent); }
.bowl { display: block; width: 100%; height: auto; }
.bowlwrap .fishbadge {
  position: absolute; left: 50%; top: 68%; width: 23%;
  transform: translate(-50%, -50%); aspect-ratio: 1252 / 592;
  display: block; pointer-events: none; opacity: .55;
  background-color: var(--muted);
  -webkit-mask: url(fishbone.svg) center / contain no-repeat;
          mask: url(fishbone.svg) center / contain no-repeat;
}
.later {
  width: 100%; margin: 0 0 8px; padding: 12px; border-radius: 12px;
  border: 1px dashed var(--line); background: transparent; color: var(--muted);
  font-weight: 700; font-size: .86rem; cursor: pointer;
}
/* Chosen is the same ring the amounts get, so the eight answers all agree. */
.later.on {
  border-style: solid; border-width: 2px; border-color: var(--accent);
  background: transparent; color: var(--ink); padding: 11px;
}

.pendrow {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 4px; border-bottom: 1px solid var(--line);
}
.pendrow:last-child { border-bottom: none; }
/* A leftover waiting to be accounted for. The question and its answers sit under
   the line rather than beside it, because three answers will not fit next to a
   name on a 320 wide phone. */
.pendrow.restrow { align-items: flex-start; }
.pendrow.restrow .nm { flex: 1 1 100%; }
.pendrow .restq { flex: 1 1 100%; color: var(--muted); font-size: .78rem; }
.pendrow .restask { flex: 1 1 100%; margin-top: 2px; }
.pendrow .nm { flex: 1; min-width: 0; font-weight: 600; font-size: .9rem; overflow-wrap: anywhere; }
.pendrow .askamt {
  border: 1px solid var(--accent); background: transparent; color: var(--accent);
  border-radius: 999px; padding: 7px 13px; font-weight: 700; font-size: .78rem;
  cursor: pointer; flex-shrink: 0;
}
.pendrow .ate { width: 100%; margin-top: 8px; }

/* ---------- one cat's own screen ---------- */
/* A cat's own screen leads with the cat. Their face or their photo, twice the size
   it was, with the name under it rather than beside it. */
.cathead { display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; }
.catbig {
  width: 132px; height: 132px; flex-shrink: 0; border-radius: 50%;
  background: var(--soft); background-size: cover; background-position: center;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 2.6rem; color: var(--muted);
}
.catwho { min-width: 0; max-width: 100%; }
.catwho h2 { font-size: 1.25rem; overflow-wrap: anywhere; }
#screen-cat .cards { padding: 0; }
#screen-cat #cat-alerts { padding: 12px 0 0; }
/* A cat found by searching. Marked out from the food cards so it does not
   read as something you can put in the cupboard. */
.catcard { border-style: dashed; }

/* ---------- how big one of something is ---------- */
.sizerow { display: flex; gap: 8px; align-items: stretch; margin-top: 6px; }
.sizerow input { flex: 1; min-width: 0; margin-top: 0; }
.unitseg {
  display: flex; border: 1px solid var(--line); border-radius: var(--radius-sm);
  overflow: hidden; background: var(--card); flex-shrink: 0;
}
.unitseg button {
  border: none; background: none; color: var(--muted); font-weight: 700;
  font-size: .88rem; padding: 0 12px; cursor: pointer; border-right: 1px solid var(--line);
}
.unitseg button:last-child { border-right: none; }
.unitseg button.on { background: var(--accent); color: var(--accent-ink); }
/* What it works out at per 100. The whole reason for asking. */
.worksout {
  margin-top: 10px; padding: 9px 12px; border-radius: var(--radius-sm);
  background: var(--price-bg); color: var(--price-ink);
  font-size: .82rem; font-weight: 700;
}

/* ---------- what each cat thinks ---------- */
.vseg { display: flex; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; }
.vseg button {
  flex: 1; padding: 11px 3px; border: none; background: var(--bg); color: var(--muted);
  font-size: .74rem; font-weight: 700; border-right: 1px solid var(--line); cursor: pointer;
}
.vseg button:last-child { border-right: none; }
.vseg .em { display: block; margin: 0 auto 5px; width: 30px; }

/* The mark that says what a cat thinks: the app's own fishbone, in colour. The
   real file is laid on as a mask, so there is one copy of that artwork in the
   app rather than one per icon and it takes whatever colour it is given. */
.vmark {
  display: block; flex-shrink: 0;
  aspect-ratio: 1252 / 592;
  background-color: var(--muted);
  -webkit-mask: url(fishbone.svg) center / contain no-repeat;
          mask: url(fishbone.svg) center / contain no-repeat;
}
.vmark.none { background-color: var(--line); }
.vseg button.on { background: var(--accent); color: var(--accent-ink); }
.vseg button.on[data-tone="good"] { background: var(--g-bg); color: var(--g-ink); }
.vseg button.on[data-tone="ok"]   { background: var(--b-bg); color: var(--b-ink); }
.vseg button.on[data-tone="meh"]  { background: var(--a-bg); color: var(--a-ink); }
.vseg button.on[data-tone="bad"]  { background: var(--r-bg); color: var(--r-ink); }

/* ---------- scanning ---------- */
.scanbtn {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; margin-top: 10px; padding: 14px; border-radius: 14px;
  border: 2px solid var(--accent); background: transparent; color: var(--accent);
  font-weight: 700; font-size: .95rem; cursor: pointer;
}

/* the one place the cupboard count changes */
/* a number in the middle of a sentence, in Admin */
.onesetting { display: flex; align-items: center; gap: 8px; font-size: .92rem; }
.onesetting input {
  width: 76px; padding: 9px 11px; font-size: 1rem; color: inherit;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--card);
}

.stockpanel {
  margin-top: 10px; padding: 12px;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--card);
}
.stockpanel .fieldname { margin-top: 0; }
.buyrow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.buyrow input {
  width: 96px; padding: 10px 12px; font-size: 1rem; color: inherit;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg);
}
.buyrow .chips { padding: 0; }
.stockpanel .pricerow { margin-bottom: 10px; }
.fixes { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; margin-top: 14px; }

.sectionrow {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; padding: 18px 16px 6px;
}
.sectitle {
  font-size: .72rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted);
}

/* Back to a plus, drawn by the stylesheet as it always was. */
.fab .plus { position: absolute; width: 1px; height: 1px; overflow: hidden; opacity: 0; }

/* Sign out sits in the corner with the paw under it. */
.cornerbtns {
  display: flex; flex-direction: column; align-items: flex-end; gap: 6px;
  flex-shrink: 0;
}
.homebar .adminbtn { gap: 0; }
.cornerrow { display: flex; align-items: center; gap: 6px; }
.adminbtn { display: flex; align-items: center; gap: 6px; }
.adminbtn .pawicon { width: 17px; height: 17px; }
/* The same paw drawn as a line rather than a solid shape. One is the shared
   Admin screen, the other is the owner's own section, and at this size they
   have to be telling apart without reading anything. */
.pawoutline {
  width: 21px; height: 21px; display: block; background-color: currentColor;
  -webkit-mask: url(paw-outline.svg) center / contain no-repeat;
          mask: url(paw-outline.svg) center / contain no-repeat;
}
/* Centred, so the name sits level with the middle of its initial. Left to
   itself flex puts the text at the top of the row and it reads as crooked. */
/* Wraps rather than being cut short, because a cut off cat name is no use to
   anybody. The header grows by a line instead. */
/* Wraps rather than being cut short, because a cut off cat name is no use to
   anybody. Two lines instead of one is the price. */
/* Spacing found by tests/spacing.py, where blocks were touching with no gap
   at all. Each of these read as one lump rather than two things. */
#feed-stocknote { margin-top: 10px; }
#stock-binned { margin-top: 6px; }
#screen-settings .pane > .fullonly { margin-top: 26px; }

/* Guides on the Help tab: a stack of quiet folds. The chevron turns when one
   is open, the body is plain prose, and nothing in here is interactive beyond
   opening and closing. */
.guidefold { border-bottom: 1px solid var(--line); }
.guidefold:first-child { border-top: 1px solid var(--line); }
.guidehead {
  width: 100%; display: flex; justify-content: space-between; align-items: center;
  background: none; border: 0; padding: 13px 2px; font: inherit; font-weight: 700;
  color: var(--ink); text-align: left; cursor: pointer;
}
.guidehead .chev { color: var(--muted); font-size: 20px; transition: transform .15s; }
.guidehead[aria-expanded="true"] .chev { transform: rotate(90deg); }
.guidebody { padding: 0 2px 14px; }
.guidebody p { margin: 0 0 10px; color: var(--muted); font-size: 14px; line-height: 1.5; }
.guidebody p:last-child { margin-bottom: 0; }

/* The group labels between guides: quiet, and clearly not folds themselves. */
.guidegroup {
  margin: 22px 0 6px; font-size: 12px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--muted);
}
.guidegroup:first-child { margin-top: 4px; }

/* The green strip under Top it up and Log it. Slides in, says what
   happened with the amount, and slides away. John picked this from
   renders/confirm.html on 10 Aug 2026. */
.savetoast {
  margin-top: 10px; padding: 10px 12px; border-radius: 10px;
  background: var(--g-bg); color: var(--g-ink);
  font-size: .85rem; font-weight: 700;
  display: flex; align-items: center; gap: 8px;
  animation: toastin .25s ease-out;
  transition: opacity .3s;
}
@keyframes toastin {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}



.filelabel + .muted, p.muted + p.muted { margin-top: 6px; }

/* ---------- stock ---------- */
.mini.stock { background: var(--n-bg); color: var(--n-ink); }
.mini.stock.low { background: var(--a-bg); color: var(--a-ink); }

.stockrow {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 10px 12px;
}
.stockrow.low { border-color: var(--a-ink); }
.stockbtn {
  width: 42px; height: 42px; flex-shrink: 0; border-radius: 50%;
  border: 1px solid var(--line); background: var(--bg); color: var(--ink);
  font-size: 1.3rem; cursor: pointer; line-height: 1;
}
.stockcount { display: flex; flex-direction: column; align-items: center; min-width: 54px; }
.stockcount span:first-child { font-size: 1.35rem; font-weight: 700; line-height: 1.1; }
.stocklabel { font-size: .66rem; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.stockbought {
  flex: 1; min-width: 110px; padding: 11px 12px; border-radius: var(--radius-sm);
  border: none; background: var(--accent); color: var(--accent-ink);
  font-weight: 700; font-size: .84rem; cursor: pointer;
}

/* ---------- feeding ---------- */
.history.tight { margin: 4px 0 10px; }
/* the feeds under a cat have no remove button, so they only need two columns */
.history.tight li { grid-template-columns: 1fr auto; padding: 6px 2px; font-size: .85rem; }
.history.tight .when { min-width: 52px; }

.picklist { display: flex; flex-direction: column; gap: 8px; }
.pick {
  display: flex; flex-direction: column; gap: 2px; text-align: left;
  padding: 11px 13px; border-radius: var(--radius-sm); cursor: pointer;
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
}
.pick.on { border-color: var(--accent); background: var(--soft); }
.pick-name { font-weight: 700; font-size: .95rem; overflow-wrap: anywhere; }
.pick-sub { font-size: .78rem; color: var(--muted); overflow-wrap: anywhere; }

.amounts { display: flex; gap: 7px; flex-wrap: wrap; }
.amounts .amt {
  flex: 1 1 auto; min-width: 74px; padding: 11px 8px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  font-size: .84rem; font-weight: 700; cursor: pointer;
}
.amounts .amt.on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
/* how much went in the bowl: fewer, wider targets than the food list */
.amounts.served .amt { flex: 1 1 0; min-width: 0; font-size: 1rem; }

/* how much of it they ate */
.eatcard {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 14px 15px 11px;
}
.eatvalue { font-size: 1.02rem; font-weight: 700; color: var(--ink); margin-bottom: 12px; }
.eatslider { -webkit-appearance: none; appearance: none; width: 100%; height: 26px; background: none; }
.eatslider::-webkit-slider-runnable-track {
  height: 8px; border-radius: 99px; background: var(--n-bg);
}
.eatslider::-moz-range-track { height: 8px; border-radius: 99px; background: var(--n-bg); }
.eatslider::-webkit-slider-thumb {
  -webkit-appearance: none; width: 26px; height: 26px; margin-top: -9px; border-radius: 50%;
  background: var(--accent); border: 3px solid var(--card); box-shadow: 0 0 0 1px var(--accent);
}
.eatslider::-moz-range-thumb {
  width: 26px; height: 26px; border-radius: 50%; border: 3px solid var(--card);
  background: var(--accent); box-shadow: 0 0 0 1px var(--accent);
}
.eatends { display: flex; justify-content: space-between; font-size: .72rem; color: var(--muted); margin-top: 2px; }

/* ---------- the moment before we know who you are ---------- */
/* Belt and braces: the screens are hidden AND the splash covers them. Either
   alone would do, but this is the one thing that must never fail, because
   failing means showing one person's cats to another. */
html.booting .screen { display: none !important; }
/* Deliberately the same off white as the manifest's splash, the app icon and
   the strip behind the clock, rather than the theme's own background. The phone
   shows its splash first and this one second, so if they differ you get a flash
   between them. */
.boot {
  position: fixed; inset: 0; z-index: 60; display: none;
  align-items: center; justify-content: center; background: #F6F6F8;
}
html.booting .boot { display: flex; }
/* Sized and placed so the logo does not jump when the phone hands over to the
   app. The phone paints its own splash first, drawn from the app icon, and the
   app paints this one second. Measured off a screen recording of a real start
   up: this one was drawn about a tenth too big, and it sat 15px lower than the
   phone had it. Both numbers below come from that measurement, so if the icon
   or the logo file ever changes, measure again rather than adjusting by eye. */
.bootmark {
  width: 170px; height: 170px; max-width: 62vw; display: block;
  background: url(logo.webp) center / contain no-repeat;
  transform: translateY(-15px);
}

/* ---------- sign in ---------- */
/* Always dark, whatever theme is saved. Before anyone signs in the app has no
   idea which theme they use, so following the theme means the first thing a
   person sees is whichever one happens to be the default. It also has to
   agree with the icon and the phone's splash, both of which are black. So
   these colours are fixed here rather than taken from the theme. */
#screen-signin { background: #F6F6F8; color: #1C1C1E; }
/* The page itself, not just the screen sitting on it. When the keyboard opens
   the page is made shorter, and for a moment the strip it uncovers is whatever
   colour the body is. That was the theme's near white, which flashed. */
html.signedout, html.signedout body { background: #F6F6F8; }
#screen-signin .logo { background-image: url(logo.webp); }
#screen-signin .signin-label { color: #1C1C1E; }
/* the register interest link is an anchor, so it needs the button's shape */
.aslink {
  display: block; text-align: center; text-decoration: none; padding: 14px 16px;
  border-radius: var(--radius-sm); font-weight: 700; font-size: 1rem;
}
#screen-signin .aslink { background: none; color: #84848B; border: 1px solid #E8E8EC; }
#screen-signin .signin-label input {
  background: #FFFFFF; border-color: #E8E8EC; color: #1C1C1E;
}
#screen-signin .signin-label input::placeholder { color: #A0A0A8; }
#screen-signin button.big { background: #FF8A3D; color: #141414; border: none; }
#screen-signin .hint,
#screen-signin .signin-foot,
#screen-signin .signin-version { color: #84848B; }

/* When the keyboard opens it takes half the screen. Centred content with no
   way to scroll would leave the box and the button underneath it. So: it
   scrolls, and it only centres itself while there is room to. */
.signin {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 14px; overflow-y: auto;
  padding: 24px 22px calc(24px + env(safe-area-inset-bottom, 0px)); text-align: center;
}
@media (max-height: 720px) {
  .signin { gap: 10px; }
  .signin .logo.big { width: 128px; height: 128px; }
}
@media (max-height: 600px) {
  .signin { justify-content: flex-start; gap: 8px; }
  .signin .logo.big { width: 92px; height: 92px; }
}
/* The sign in and waiting screens carry the logo as an h1 with the class `big`,
   and `big` is also the button shape, which paints an accent background and
   throws away a picture's sizing. Harmless while the logo was a mask. Now that
   it is a picture it has to be said again, after `big`. */
.logo.big {
  width: 190px; height: 190px; max-width: 62vw; margin-bottom: 4px;
  background-color: transparent;
  background-size: contain; background-position: center; background-repeat: no-repeat;
}
.signin-lead { color: var(--ink); font-size: 1rem; max-width: 22rem; line-height: 1.45; }
.signin-label {
  display: flex; flex-direction: column; gap: 6px; width: 100%; max-width: 22rem;
  text-align: left; font-weight: 700; font-size: .9rem;
}
.signin-label input {
  padding: 12px 14px; font-size: 1rem; color: inherit;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--card);
}
.signin .big { width: 100%; max-width: 22rem; }
.signin-foot { color: var(--muted); font-size: .82rem; max-width: 22rem; line-height: 1.45; }
.signin .hint { max-width: 22rem; }
/* Sits with the rest of the content, NOT pinned to the bottom of the screen.
   Pinning it used 100vh, which on a phone is taller than what you can
   actually see, so the line ended up below the fold and John could not find
   it at all. */
.signin-version { padding-top: 10px; color: var(--muted); font-size: .72rem; }

/* ---------- the waiting screen, and John's list of who asked ---------- */
#screen-waiting { background: #F6F6F8; color: #1C1C1E; }
#screen-waiting .logo { background-image: url(logo.webp); }
#screen-waiting .signin-lead { color: #1C1C1E; }
#screen-waiting .signin-foot, #screen-waiting .signin-version { color: #84848B; }
#screen-waiting button.big.secondary {
  background: none; color: #84848B; border: 1px solid #E8E8EC;
}

/* Whose list this is. Only on screen when it is somebody else's, so it never
   becomes wallpaper you stop reading. */
/* The home header used to be laid out here, with the version stacked under the
   logo and everything pinned to the top of the bar. It is all in .homebar now,
   near the top of this file, and these were still winning because of the id in
   front of them. That is what pushed the version under the logo and left the two
   words and the icons centred against a block taller than the logo itself. */

.textbtn {
  border: 1px solid var(--line); background: var(--card); color: var(--muted);
  border-radius: 999px; padding: 5px 9px; font-size: .72rem; font-weight: 600;
  white-space: nowrap; flex-shrink: 0;
}

.listbanner {
  margin: 0 16px 8px; padding: 9px 12px;
  border: 1px solid var(--accent); border-radius: var(--radius-sm);
  background: var(--card); color: var(--ink);
  font-size: .86rem; font-weight: 600;
}

/* Admin, one part at a time */
/* The tabs sit centred under the Admin title and are set in the heading font a
   size down, so they read as part of the header rather than as five buttons
   pushed against the left edge. */
.admintabs { padding: 8px 16px 0; margin: 0; justify-content: center; }
.chips.wrap.admintabs .chip { letter-spacing: .1px; }
.pane { display: none; }
.pane.on { display: block; }
.pane h3:first-child { margin-top: 8px; }

.invform { margin-top: 18px; }
.invform h4 { margin: 0 0 10px; font-size: .95rem; }
.linkbox {
  margin: 10px 0; padding: 10px 12px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--bg); color: var(--muted);
  font-size: .78rem; overflow-wrap: anywhere;
}

.sharerow {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 12px; margin-bottom: 8px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--card); font-size: .93rem; overflow-wrap: anywhere;
}
.reqcard {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 12px 13px; margin-bottom: 10px;
}
.reqcard.done { opacity: .55; }
.req-name { font-weight: 700; font-size: .97rem; }
.req-sub { color: var(--muted); font-size: .82rem; margin: 2px 0 10px; overflow-wrap: anywhere; }
.req-done {
  display: inline-block; padding: 3px 9px; border-radius: 999px;
  background: var(--g-bg); color: var(--g-ink);
  font-size: .7rem; font-weight: 700; text-transform: uppercase;
}

/* the worth watching banner on the home screen */

/* ---------- admin rows ---------- */
.rowbtn {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; padding: 13px 14px; border-radius: var(--radius-sm); cursor: pointer;
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  font-size: .93rem; font-weight: 600; text-align: left;
}
.rowbtn .chev { color: var(--muted); font-size: 1.3rem; flex-shrink: 0; }

/* ---------- toggles ---------- */
.offertoggle {
  display: flex; align-items: center; gap: 9px; width: 100%; margin-top: 10px;
  padding: 11px 13px; border-radius: var(--radius-sm); cursor: pointer;
  border: 1px solid var(--line); background: var(--card); color: var(--muted);
  font-size: .88rem; font-weight: 600; text-align: left;
}
.offertoggle .tick {
  width: 22px; height: 22px; flex-shrink: 0; border-radius: 6px;
  border: 2px solid var(--muted); background: var(--bg);
  display: flex; align-items: center; justify-content: center;
  font-size: .8rem; color: transparent;
}
.offertoggle.on { color: var(--ink); border-color: var(--accent); }
.offertoggle.on .tick { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

.linkbtn {
  display: block; margin-top: 9px; padding: 4px 0; background: none; border: none;
  color: var(--muted); font-size: .82rem; text-decoration: underline; cursor: pointer;
}

.offertag { margin-left: 6px; }
.pricetag.wasoffer { outline: 2px solid var(--g-ink); outline-offset: 1px; }

/* ---------- meal times ---------- */
.meals { display: flex; flex-direction: column; gap: 8px; }
.meal {
  display: flex; align-items: center; gap: 8px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 8px 10px;
}
.meal-name {
  flex: 1; min-width: 0; padding: 9px 10px; font-size: .95rem; color: inherit;
  border: 1px solid var(--line); border-radius: 9px; background: var(--bg);
}
.meal-time {
  flex-shrink: 0; padding: 9px 8px; font-size: .95rem; color: inherit;
  border: 1px solid var(--line); border-radius: 9px; background: var(--bg);
}

/* ---------- nav icons ---------- */
.pawicon {
  width: 21px; height: 21px; display: block; background-color: currentColor;
  -webkit-mask: url(paw.svg) center / contain no-repeat;
          mask: url(paw.svg) center / contain no-repeat;
}

/* ---------- filters that all fit ---------- */
/* Wrapping beats a scrolling row: every option is visible without swiping,
   and two tight rows cost less height than one row plus a scrollbar. */
.chips.wrap { flex-wrap: wrap; overflow: visible; gap: 6px; padding: 10px 16px 8px; }
.chips.wrap .chip { padding: 5px 11px; font-size: .78rem; }

/* ---------- traced brand icons ---------- */
/* fishbone.svg and paw.svg are traced from John's own reference artwork.
   Both are masks filled with currentColor, so they follow the theme and the
   active state without needing a second copy of each file. */
.fishicon {
  width: 26px; height: 21px; display: block; background-color: currentColor;
  -webkit-mask: url(fishbone.svg) center / contain no-repeat;
          mask: url(fishbone.svg) center / contain no-repeat;
}
#btn-settings { display: flex; align-items: center; justify-content: center; }
#btn-settings .pawicon { width: 23px; height: 23px; }

/* ---------- v0.0.67 ---------- */

/* The panel rows are a four column grid. A line with only one thing in it
   lands in the first column, which is 50px, and the words wrap inside it.
   Anything on its own has to be told to cross the whole row. */
.catpanel .history .wide { grid-column: 1 / -1; text-align: left; }

/* The time is plain text. The whole line is the way in to changing a feed. */

/* Changing when a feed happened. Sits under its own line and crosses the
   whole row, because a date box and a clock box will not fit in a column. */
.whenedit {
  grid-column: 1 / -1; display: grid; grid-template-columns: 1fr 1fr;
  align-items: center; gap: 6px; margin: 6px 0 2px;
}
/* The two boxes take a line of their own and the buttons drop under them.
   Left to flow, the date and the clock fill the row and Cancel is orphaned
   on the next line on its own, which reads as though it belongs to something
   else. Checked at 390, 360 and 320. */
.whenedit input {
  font: inherit; font-size: .8rem; padding: 6px 8px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--card); color: var(--ink); min-width: 0;
}
.whenedit .chip { text-align: center; }
.whenedit .chip { font-size: .78rem; padding: 5px 11px; }
.whenedit select {
  grid-column: 1 / -1; font: inherit; font-size: .8rem; padding: 6px 8px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--card); color: var(--ink); min-width: 0;
}
/* The line itself opens the feed now, so it has to look like it does something. */
.history li.tapme { cursor: pointer; }
.history li.tapme:active { background: var(--soft); }

/* Going back a step, rather than answering. Quieter than the answers beside it. */
.chip.ghost { border-style: dashed; color: var(--muted); }

/* An alert you have read. The cross is part of the pill, on the end of its own
   sentence, not a loose mark sitting next to it. */
.alert.hasx { display: inline-flex; align-items: center; gap: 8px; padding-right: 7px; }
.alert.hasx .words { min-width: 0; overflow-wrap: anywhere; }
.alertx {
  flex-shrink: 0; width: 20px; height: 20px; border-radius: 50%;
  background: var(--soft); color: var(--muted);
  font-size: .78rem; line-height: 20px; text-align: center; font-weight: 700;
}

/* The three treat sizes are words, not fractions, so they need the room. */
.amtbig.treatsizes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.amtbig.treatsizes .amt { font-size: .92rem; height: auto; padding: 10px 6px; }
.amtbig.treatsizes .amt .lbl { display: block; font-size: .66rem; font-weight: 600; margin-top: 2px; }

/* ---------- v0.0.70, a week strip and columns ---------- */

/* The top of the home screen. The faces are the buttons: a row of cats you
   tap, rather than a row each with a pill on the end. */
.feedhead .feedcount { font-weight: 700; font-size: .78rem; color: var(--muted); }
/* iPhones paint button text in Apple's blue unless told otherwise, which is
   why cat names and day numbers went blue on a sharer's phone while looking
   right everywhere else. Buttons wear the app's own ink unless a rule says
   different. */
button { color: inherit; }

.feedfaces {
  display: flex; justify-content: center; flex-wrap: wrap; gap: 12px; margin-top: 8px;
}
.ff {
  width: 62px; background: none; border: none; padding: 0; cursor: pointer; text-align: center;
}
.ff .catface { display: block; width: 100%; height: auto; }
.ffwrap { position: relative; display: block; }
.ff.done .catface { opacity: .32; }
.fftick {
  position: absolute; right: 1px; bottom: 15px; width: 18px; height: 18px;
  border-radius: 50%; background: var(--accent); color: var(--accent-ink);
  font-size: .64rem; line-height: 18px; font-weight: 700;
}
.ffname { display: block; font-weight: 700; font-size: .74rem; margin-top: 1px; }
.ffwhen { display: block; color: var(--muted); font-size: .64rem; }
.ff.done .ffwhen { color: var(--accent); }

/* The week. A dot means something was logged that day, so an empty day is
   obvious before you open it, and any day is one tap rather than five. */
.dayarea { margin-top: 8px; touch-action: pan-y; }
.week { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; margin-bottom: 6px; }
.wd {
  background: none; border: none; padding: 5px 0 4px; border-radius: 10px; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
}
.wd .l { font-size: .6rem; color: var(--muted); font-weight: 700; text-transform: uppercase; }
.wd .d { font-size: .86rem; font-weight: 700; }
.wd .dot { width: 4px; height: 4px; border-radius: 50%; background: var(--accent); }
.wd .dot.off { background: transparent; }
.wd.on { background: var(--accent); }
.wd.on .l, .wd.on .d { color: var(--accent-ink); }
.wd.on .dot { background: var(--accent-ink); }
.wd.later { opacity: .3; cursor: default; }

/* A feed line is columns, so the times line up and the names line up, and how
   much came back is pulled out to the right instead of trailing off a
   sentence. Held to a minimum height so the list does not jump about when a
   day is empty. */
.catpanel .history { min-height: 132px; }
.catpanel .history li {
  /* the tag gets a column of its own rather than taking whatever it wants.
     Left on auto it sized itself to the longest phrase and squeezed the name
     until it broke in the middle of itself on a small phone */
  /* The same left and right edges as the row of days above, so the time lines up
     under the S and the tag ends under the last S. minmax(0, 1fr) is what stops
     the middle column refusing to shrink and pushing the tag off the card. */
  display: grid; grid-template-columns: 46px 42px minmax(0, 1fr) auto;
  column-gap: 8px; align-items: center; padding: 9px 0;
  border-bottom: 1px solid var(--line);
}
.catpanel .history li:last-child { border-bottom: none; }
.catpanel .history li.dayhead {
  display: block; padding: 12px 0 2px; border-bottom: none;
  font-weight: 700; font-size: .78rem; color: var(--muted);
}
.catpanel .history .when {
  /* left, so it starts on the same line as the first day above it */
  min-width: 0; text-align: left; font-size: .74rem; color: var(--muted);
}
.catpanel .history .spine { position: static; }
.catpanel .history .spine::before { display: none; }
.catpanel .history .spine .b { display: block; width: 42px; background: none; }
.fl-who { display: block; font-weight: 700; font-size: .88rem; line-height: 1.2; }
.fl-what { display: block; color: var(--muted); font-size: .74rem; }
.fl-what:empty { display: none; }
/* the brand behind the food's own name, a shade quieter again */
/* its own line under the flavour. One step heavier than it, 500 against the
   400 everything else on the line sits at, so the brand reads as its own thing
   without shouting. The font is variable from 300 to 700, so 500 is a real
   weight in it rather than the browser faking one. */
.fl-brand {
  display: block; color: var(--muted); font-size: .72rem; font-weight: 500;
  opacity: .8; line-height: 1.25;
}

/* A portion the cupboard cannot cover. Still readable, clearly not for
   tapping, and it says why underneath rather than leaving you guessing. */
.amtbig .amt.nomore {
  opacity: .45; cursor: not-allowed;
  background: var(--n-bg); color: var(--n-ink); border-color: var(--line);
}
.amtbig .amt.nomore .lbl { font-weight: 600; }

/* The tag keeps its place in the row at every width and wraps onto a second
   line instead. Moving it below the name on a narrow phone changed the shape
   of the row, so the same list looked like two different designs depending on
   the handset. Capped so it can never crowd the name out. */
/* The pill is only as wide as the words in it. Given a column of its own it
   sat there at full width with two short words rattling around inside. */
.fl-tag {
  justify-self: end; border-radius: 999px; padding: 3px 9px; font-size: .66rem;
  font-weight: 700; text-align: center; line-height: 1.25;
  /* One line. What stopped it running off the card is the name column beside it
     being allowed to shrink, not this breaking up. Left to wrap it broke a word
     a letter at a time, which is worse than what it replaced. */
  white-space: nowrap;
}
.fl-tag.clean { background: var(--soft); color: var(--accent); }
.fl-tag.leftover { background: #F6EAD8; color: #9A6B1E; }
.fl-tag.pending { background: var(--soft); color: var(--muted); }
.catpanel .history .wide { grid-column: 1 / -1; text-align: left; }
.catpanel .history .restask { grid-column: 3 / -1; margin: 0 0 8px; }
.whenedit { grid-column: 1 / -1; }

/* The cats above the box, centred. Four of them sat over to the left looked
   like the row had failed to fill. */
.catpanel .strip { justify-content: center; }

/* The leftovers question, above the days. */

/* A name must never break in the middle of itself. The column can be tight on
   a narrow phone, so it wraps between words only. */
.fl-who, .fl-what, .fl-brand { overflow-wrap: normal; word-break: normal; min-width: 0; }
.catpanel .history li > span { min-width: 0; }


/* On a narrow phone the columns get tighter, but the arrangement does not
   change: time, bowl, cat, tag, remove, the same as on a wide one. The tag
   wraps onto a second line rather than moving somewhere else, so the list
   does not look like two different designs depending on the handset. */
@media (max-width: 372px) {
  /* the same four things in the same order, just tighter and pulled left */
  .catpanel { margin: 10px 10px 0; padding: 4px 8px 8px; }
  .consumecard { margin: 10px 10px 16px; padding: 2px 8px; }
  .catpanel .history li { grid-template-columns: 46px 34px 1fr auto; column-gap: 6px; }
  .catpanel .history .spine .b { width: 34px; }
  .catpanel .history .when { font-size: .68rem; }
  .fl-who { font-size: .84rem; }
  .fl-tag { font-size: .6rem; padding: 3px 7px; }
}

/* Removing a feed, in Admin under Feeding. */
.feedbin { margin-top: 6px; }
/* One change per line. It is a trail meant to be read and copied, so the type
   is small and every line wraps in full rather than being cut off. Selectable,
   because a phone that blocks the copy button leaves press and hold. */
.logline { margin: 0 0 6px; font-size: .72rem; line-height: 1.35; color: var(--muted);
           overflow-wrap: anywhere; user-select: text; -webkit-user-select: text; }
/* a grid rather than flex, so the button can never take the whole row and
   squeeze the words into one letter per line */
.binrow {
  display: grid; grid-template-columns: 34px 1fr 84px; align-items: center;
  gap: 10px; padding: 10px 2px; border-bottom: 1px solid var(--line);
  font-size: .86rem;
}
.binrow .avatar { width: 34px; height: auto; }
.binrow:last-child { border-bottom: none; }
.binrow > span { min-width: 0; }
.binwhen { color: var(--muted); font-size: .72rem; }
.binrm {
  padding: 7px 10px; border-radius: 999px; background: transparent;
  border: 1px solid var(--r-ink); color: var(--r-ink);
  font-weight: 700; font-size: .74rem; cursor: pointer; white-space: nowrap;
}



/* ---------- the home screen's going-through header ---------- */

.consumecard { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
               padding: 2px 12px; margin: 10px 16px 16px; box-shadow: var(--shadow); }
.consumehead { width: 100%; display: flex; align-items: center; justify-content: space-between;
               gap: 10px; background: none; border: none; padding: 10px 0; cursor: pointer;
               color: var(--ink); text-align: left; }
.consumehead h3 { margin: 0; }
.consumehead .chev { color: var(--muted); font-size: .95rem; flex-shrink: 0; }
#consume-body { padding-bottom: 12px; }
/* The being sick drawer under it. Same card, same head, and the list inside it
   is the same list the cat's own screen uses. */
#sickcard-body { padding-bottom: 12px; }
#sickcard-body .hint { margin-top: 2px; }
#sickcard-body .history { margin-top: 8px; }
/* A face on the front of every line, so four entries in a column are told
   apart at a glance rather than read. The cat's own screen does not get one:
   there is only ever one cat on it. */
.history.sicklist li { grid-template-columns: 28px 1fr auto; column-gap: 10px; }
#sickcard-body .history li:last-child { border-bottom: none; }
#sickcard-body .widebtn { margin-top: 10px; }
/* Which seven days are showing, with an arrow either side. The arrows are
   44 across and tall so they are a real target on a phone, and the label in
   the middle takes what is left so it never pushes them off at 320 wide. */
.weeknav { display: flex; align-items: center; justify-content: space-between; gap: 6px;
           margin: 2px 0 4px; }
.wnav { flex: 0 0 44px; height: 36px; display: flex; align-items: center; justify-content: center;
        background: none; border: 1px solid var(--line); border-radius: 12px; cursor: pointer;
        color: var(--ink); font-size: 1.1rem; line-height: 1; padding: 0; }
.wnav:disabled { opacity: .35; cursor: default; }
.wnavlab { flex: 1 1 auto; min-width: 0; text-align: center; color: var(--muted);
           font-size: .78rem; font-weight: 600; }
.trendrow { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 10px; }
.trendrow .trendname { margin: 0; }
.trendname { font-weight: 700; font-size: .85rem; margin: 10px 0 0; }
.trendname.sub { font-weight: 600; font-size: .78rem; color: var(--muted); }
.trendname .subbrand { color: var(--muted); font-weight: 400; font-size: .75rem; }

/* an empty food in the feed list: faded, with none left on it, still there
   as the subtle reminder John asked for. The badge keeps full strength so
   the reason for the fade is readable. */
.foodpick.out .shot, .foodpick.out .words { opacity: .45; }
.fp-none {
  flex-shrink: 0; background: var(--warn-bg); color: var(--warn-ink);
  font-weight: 700; font-size: .64rem; letter-spacing: .04em; text-transform: uppercase;
  padding: 4px 8px; border-radius: 8px; align-self: center;
}

/* ---------- multipacks in Admin ---------- */

.mprow { display: flex; align-items: center; justify-content: space-between; gap: 10px;
         padding: 10px 0; border-bottom: 1px solid var(--line); }
.mprow:last-child { border-bottom: none; }
.mprow .nm { font-weight: 700; font-size: .9rem; }
.stepper { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.stepper button { width: 34px; height: 34px; border-radius: 10px; border: 1px solid var(--line);
                  background: var(--card); color: var(--ink); font-weight: 700; font-size: 1rem; }
.stepper .n { font-weight: 700; min-width: 18px; text-align: center; }

/* ---------- water: the last seven days ---------- */

.weekrow { display: flex; gap: 6px; align-items: flex-end; margin-top: 10px; }
.weekcol { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; }
.weekcol .bar { width: 100%; max-width: 34px; border-radius: 6px 6px 2px 2px; background: var(--accent); opacity: .8; }
/* water is blue wherever it is drawn, so a glance says food or water */
.waterbars .bar, #water-week .bar { background: var(--water); }
.weekcol .val { font-size: .6rem; color: var(--muted); white-space: nowrap; min-height: .9rem; }
.weekcol .wlab { display: flex; flex-direction: column; align-items: center; gap: 1px;
                 padding: 4px 6px; border-radius: 10px; }
.weekcol .wlab .l { font-size: .6rem; color: var(--muted); font-weight: 700; text-transform: uppercase; }
.weekcol .wlab .d { font-size: .86rem; font-weight: 700; }
.weekcol .wlab.on { background: var(--accent); }
.weekcol .wlab.on .l, .weekcol .wlab.on .d { color: var(--accent-ink); }

/* ---------- the weights, last ----------
   Said once, at the end, because a weight set beside a colour halfway up this
   file wins on order alone and the ladder stops being a ladder. Anything that
   wants to break the rule has to say so after this. */
h1 { font-weight: 700; }
h2, h3, .fieldname, .fp-title { font-weight: 600; }
.big, .pbtn, .widebtn, .danger, .rowbtn, .sheetbtn, .stockbought, .themecard,
.cardbody .name, .catrow .nm, .cv-name, .req-name { font-weight: 600; }
.chip, .pill, .alert, .linkbtn, .offertoggle, .archiverow, .stocklabel { font-weight: 500; }
.hint, .askbody, .nocats, .empty, .worksout, .cardbody .brand, .req-sub,
.brandsaid, .fp-set { font-weight: 400; }
/* the two words that are the home screen's title, and the chip standing for the
   pane you are on, are the exceptions and say so here */
.hometab { font-weight: 700; }
.chip.on, .chips.wrap.admintabs .chip { font-weight: 600; }

/* ---------- the first time set up ----------
   After the weight ladder on purpose: the wizard's own headings pick their own
   weights, and everything borrowed from the app keeps the app's. */
.wizstep { padding-bottom: 8px; }
.wiztop { padding: 10px 0 4px; }
.wizh { font-family: var(--head-font); font-weight: 700; font-size: 1.3rem; margin: 0 0 6px; }
.wizp { color: var(--muted); font-size: .9rem; font-weight: 400; line-height: 1.5; margin: 0 0 10px; }
.wizdots { display: flex; gap: 6px; padding: 0 0 12px; }
.wizdots i { width: 8px; height: 8px; border-radius: 50%; background: var(--line); }
.wizdots i.on { background: var(--accent); }
.wizlist { list-style: none; display: flex; flex-direction: column; gap: 12px; padding: 6px 0; margin: 0; }
.wizlist li { display: flex; gap: 12px; align-items: center; background: var(--card);
              border: 1px solid var(--line); border-radius: var(--radius); padding: 12px; }
.wizlist .n { width: 30px; height: 30px; border-radius: 50%; background: var(--soft);
              color: var(--accent); font-family: var(--head-font); font-weight: 700;
              display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.wizlist .w { font-size: .9rem; font-weight: 500; }
.wizfoot { padding: 18px 0 6px; }
.wizskip, .wizback { display: block; width: 100%; text-align: center; padding: 12px; background: none;
           border: none; color: var(--muted); font-family: var(--head-font); font-weight: 500;
           font-size: .84rem; cursor: pointer; }
.wizbar { position: static; padding-left: 0; padding-right: 0; }
.say {
  margin: 10px 0; padding: 11px 13px; border-radius: var(--radius-sm);
  background: var(--soft); color: var(--ink); font-size: .84rem; font-weight: 400;
  line-height: 1.45; border: 1px solid var(--line);
}
.say b { font-weight: 600; }
.wizcard { border: 1px solid var(--line); border-radius: var(--radius);
           padding: 10px 12px; background: var(--card); }
.wizbowls { display: flex; gap: 6px; align-items: center; justify-content: center; flex-wrap: wrap; }
.wizbowls span { width: 44px; display: inline-block; }
.finger {
  position: absolute; width: 34px; height: 34px; border-radius: 50%;
  background: rgba(255,138,61,.28); border: 2px solid var(--accent);
  pointer-events: none; z-index: 8; transform: translate(-50%, -50%);
}
.finger.pulse { animation: wizpulse 1.6s ease-in-out infinite; }
@keyframes wizpulse { 0%,100% { transform: translate(-50%,-50%) scale(1); opacity: 1; }
                      50% { transform: translate(-50%,-50%) scale(1.35); opacity: .55; } }
.wizring { outline: 3px solid var(--accent); outline-offset: 3px; border-radius: 12px;
           animation: wizringpulse 1.6s ease-in-out infinite; }
@keyframes wizringpulse { 0%,100% { outline-offset: 3px; } 50% { outline-offset: 7px; } }
.typein::after { content: ""; border-right: 2px solid var(--accent); margin-left: 1px;
                 animation: wizcaret 1s step-end infinite; }
@keyframes wizcaret { 50% { border-color: transparent; } }

/* who is on the account: their name, their address under it, their access */
.sharerow { flex-wrap: wrap; }
.sharewho { display: flex; flex-direction: column; min-width: 0; flex: 1 1 100%; }
.sharewho .nm { font-weight: 600; overflow-wrap: anywhere; }
.shareemail { color: var(--muted); font-size: .76rem; font-weight: 400; overflow-wrap: anywhere; }

/* ---------- marking many foods at once ---------- */
.sectionrow { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.tickbox {
  width: 26px; height: 26px; border-radius: 8px; border: 2px solid var(--line);
  background: var(--bg); flex-shrink: 0; align-self: center;
  display: flex; align-items: center; justify-content: center;
  font-size: .9rem; color: var(--accent-ink);
}
.tickbox.on { background: var(--accent); border-color: var(--accent); }
.bulkbar {
  position: fixed; z-index: 7; left: 0; right: 0; bottom: 0;
  display: flex; gap: 8px; margin: 0 auto; max-width: 560px;
  padding: 10px 16px calc(env(safe-area-inset-bottom, 0px) + 12px);
  background: var(--card); border-top: 1px solid var(--line);
}
.bulkbar .big { margin-top: 0; flex: 1; font-size: .84rem; padding: 12px 6px; }
.bulkbar .secondary.on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }

/* the cat's name in Waiting on you wears the theme's soft colour, so whose
   bowl it was is the first thing the eye lands on. Nothing else moved. */
.catmark {
  background: var(--soft); color: var(--accent);
  border-radius: 7px; padding: 1px 7px;
  font-family: var(--head-font); font-weight: 700;
}

/* ---------- Ask about your cats ----------
   Owner only, in Admin. The question box is a plain field the width of the
   pane, and the answer sits in a card under it so a long one reads as one
   block rather than running into the rest of the screen. */
.askbox {
  width: 100%; margin-top: 12px; padding: 11px 12px;
  font-size: 1rem; font-weight: 400; line-height: 1.4;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--card); color: inherit; resize: vertical;
}
#ask-examples { margin-top: 10px; }
/* the two tabs on the hidden screen behave the same as Admin's */
.apane { display: none; }
.apane.on { display: block; }
.apane h3:first-child { margin-top: 8px; }
#ask-examples .chip { font-size: .78rem; }
#ask-note { margin-top: 10px; }
.askanswer {
  margin-top: 12px; padding: 13px 14px;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--card); font-size: .93rem; line-height: 1.5;
  overflow-wrap: anywhere;
}
/* the first line is the answer itself, so it carries a little more weight
   than the working underneath it */
.askanswer > p { margin: 0 0 10px; }
/* the first line is the answer, the bullets under it are the working */
.askanswer > p:first-child { font-weight: 600; margin-bottom: 12px; }
/* a later line on its own is a heading, standing over its own bullets, with a
   clear gap above it so each cat reads as its own block */
.askanswer > p:not(:first-child) {
  font-weight: 600; font-size: .9rem; margin: 18px 0 6px;
}
.askanswer > p.askcat {
  display: flex; align-items: center; gap: 8px;
  padding-top: 14px; border-top: 1px solid var(--line);
}
.askanswer .askcat .catface { width: 30px; height: 30px; flex-shrink: 0; }
.askanswer > p:last-child { margin-bottom: 0; }
/* paw prints instead of dots. paw.svg is the app's own artwork, masked and
   filled with the accent, so it follows the theme like every other use of it */
.asklist { margin: 0 0 10px; padding-left: 0; list-style: none; }
.asklist:last-child { margin-bottom: 0; }
/* the paw sits in the middle of the line's height, so on a line that wraps to
   two rows it is level with the middle of both rather than up against the top */
.asklist li {
  margin: 5px 0; padding-left: 24px; position: relative;
  min-height: 16px;
}
.asklist li::before {
  content: ""; position: absolute; left: 0; top: 50%;
  transform: translateY(-50%);
  width: 14px; height: 14px; background-color: var(--accent);
  -webkit-mask: url(paw.svg) center / contain no-repeat;
          mask: url(paw.svg) center / contain no-repeat;
}

}
.askanswer.bad { border-color: var(--r-ink); color: var(--r-ink); }
