:root{
  --green-900:#1b3a2b;
  /* Added for the two cards under the homepage search, which needed a green
     dark enough to carry white text and lighter than the 900 the header ink
     uses, so the cards read as a surface rather than as a second header. */
  --green-800:#1f5a3c;
  --green-700:#2f6b45;
  --green-500:#4c9a63;
  --green-300:#a8d5b5;
  --green-100:#eef7ef;
  --earth:#8a6d4b;
  --cream:#faf8f2;
  --text:#233329;
  /* Secondary text: captions, latin names, "no results", meta lines. One
     token, because the two greys it replaces (#7b8a80 and #6a7a6f) were
     three percent of luminance apart and both failed AA - 3.63:1 and
     4.15:1. This is 5.12:1 at worst, on white, cream or green-100. */
  --muted:#5d6b62;
  /* The warning amber, dark enough to read: 6.53:1 at worst, where
     #8a6d1f was 4.47:1. */
  --warn-ink:#6b5518;
  --radius:14px;
  --shadow:0 4px 16px rgba(27,58,43,0.12);
  /* Height of the sticky site header. A sensible default for the first paint;
     assets/header.js measures the real bar and overwrites it, since the header
     is taller on narrow screens and when the nav wraps. */
  --header-h:61px;
  /* One width for the whole page. The header used to be 1400, .container 1100
     and the plant article 840, so on any screen wider than 1400 the logo sat
     150px left of the breadcrumb and the breadcrumb 130px left of the card: a
     three-step staircase down the left edge, constant at every width above
     that. Raised from 1100 at the same time, because an 840px article stranded
     in the middle of a 1920 screen left most of it empty. */
  --page-max:1240px;
  /* Where the hero artwork is centred when a hero does not say otherwise.
     .hero-media img reads these, so the visible crop can be nudged per hero
     without re-exporting the picture. See assets/hero/README.md. */
  --hero-focus-x:50%;
  --hero-focus-y:52%;
}
/* Keeps anchor jumps and scrollIntoView from parking their target underneath
   the sticky header. */
html{scroll-padding-top:calc(var(--header-h) + 12px);}
*{box-sizing:border-box;}
body{
  margin:0;
  font-family:'Segoe UI',system-ui,-apple-system,sans-serif;
  color:var(--text);
  background:var(--cream);
}
/* width:100% is not redundant. body is a column flex container (so the footer
   can be pushed down on a short page), which makes every direct child a flex
   item, and an item with auto margins on the cross axis stops stretching and
   sizes to its own content instead. A container holding a wide grid still
   filled the page, so most of the site looked unaffected; a container holding
   only a breadcrumb shrank to the width of the words and the auto margins then
   centred it. An explicit width gives the item a base size to stretch from,
   and the auto margins go back to centring the leftover. */
.container{width:100%;max-width:var(--page-max);margin:0 auto;padding:0 20px;}
a{text-decoration:none;color:inherit;}

/* Sticky, so the nav and the language switcher stay reachable on the long
   pages. z-index sits above everything on the page (the tallest was #site-nav
   at 60, and Leaflet's own controls at 800) but below the listing modal at
   1000, which is meant to cover the header along with the rest. */
.site-header{
  background:#fff;color:var(--text);position:sticky;top:0;z-index:900;
  border-bottom:1px solid var(--green-100);
}
/* Added by assets/header.js once the page has scrolled, so the bar lifts off
   the content instead of carrying a shadow while it is still at rest. */
.site-header.is-stuck{box-shadow:0 4px 16px rgba(27,58,43,.09);}
.header-inner{display:flex;align-items:center;max-width:var(--page-max);margin:0 auto;padding:14px 20px;gap:16px;}
.header-left{display:flex;align-items:center;gap:12px;flex:none;}
/* The logo is a 4:1 horizontal lockup. Height is set and width left auto, so
   the aspect ratio is the file's own and can never be squashed; display:flex
   removes the inline descender gap under the image. */
.brand{display:flex;align-items:center;flex:none;}
.brand img{display:block;height:38px;width:auto;}
.site-header nav a{margin-left:24px;color:var(--green-700);font-weight:500;}
.site-header nav a.active,.site-header nav a:hover{color:var(--green-900);}
#lang-select{background:var(--green-700);color:#fff;border:1px solid var(--green-500);border-radius:6px;padding:4px 8px;font-weight:600;cursor:pointer;flex:none;}

.menu-toggle{display:flex;flex-direction:column;justify-content:center;gap:5px;width:36px;height:36px;padding:8px;border:none;background:none;cursor:pointer;flex:none;}
.menu-toggle span{display:block;width:100%;height:2px;background:var(--green-900);border-radius:2px;}
.menu-toggle:hover span{background:var(--green-500);}

.login-btn{background:var(--green-700);color:#fff !important;padding:9px 20px;border-radius:999px;font-weight:700;font-size:0.9rem;white-space:nowrap;flex:none;}
.login-btn:hover{background:var(--green-700);color:#fff !important;}

#account-extras{margin-left:auto;display:flex;align-items:center;gap:14px;flex:none;}
.account-icon-btn{background:none;border:none;cursor:pointer;padding:4px;position:relative;line-height:1;display:flex;align-items:center;color:var(--green-700);}
.account-icon-btn svg{width:24px;height:24px;}
.account-icon-btn:hover{color:var(--green-900);}
.account-icon-btn .badge-dot{position:absolute;top:0;right:0;width:8px;height:8px;border-radius:50%;background:#d9534f;border:1.5px solid #fff;}

#site-nav{position:absolute;top:100%;left:0;background:#fff;border-top:1px solid var(--green-100);border-right:1px solid var(--green-100);border-bottom-right-radius:14px;box-shadow:var(--shadow);display:flex;flex-direction:column;width:max-content;max-width:calc(100vw - 64px);padding:18px 32px 22px 22px;gap:16px;z-index:60;}
#site-nav[hidden]{display:none;}
#site-nav a{margin-left:0;color:var(--green-900);font-weight:600;font-size:1.05rem;}
#site-nav a:hover{color:var(--green-500);}
/* Desktop: full nav bar inline in the header, no hamburger. The hamburger
   dropdown above is for narrow/mobile screens only. */
@media(min-width:701px){
  .menu-toggle{display:none;}
  #site-nav{position:static;flex-direction:row;flex-wrap:wrap;align-items:center;border:none;box-shadow:none;width:auto;max-width:none;padding:0;gap:20px;margin:0;}
  #site-nav[hidden]{display:flex;}
  #site-nav a{font-size:0.95rem;}
}

/* No ad network is wired in yet, so the placeholder boxes stay hidden.
   Remove this rule once real ads are plugged into these slots. */
.ad-slot{display:none;background:var(--green-100);border:1px dashed var(--green-300);border-radius:10px;align-items:center;justify-content:center;color:#8aa392;font-size:0.85rem;position:relative;min-height:90px;margin:20px auto;}
.ad-leaderboard{max-width:728px;min-height:90px;}
.ad-inline{min-height:100px;margin:30px auto;}
.ad-label{position:absolute;top:6px;left:10px;font-size:0.65rem;text-transform:uppercase;letter-spacing:0.05em;color:#a3b5aa;}

.hero{background:linear-gradient(180deg,var(--green-100),var(--cream));padding:60px 0 40px;text-align:center;}
.hero h1{font-size:2.2rem;color:var(--green-900);margin-bottom:10px;}
.hero p{color:var(--green-700);max-width:600px;margin:0 auto 30px;font-size:1.05rem;}








.search-panel{max-width:700px;margin:0 auto;background:#fff;border-radius:var(--radius);box-shadow:var(--shadow);padding:20px;}
/* Centred, like every other .search-panel on the site. It was briefly
   left-aligned to sit over the breadcrumb and the photo; centred is how it
   read before the container regression and is what it goes back to. The auto
   margins only do anything above 700px, so on a phone it still fills the
   content width. */
.plant-page-search{margin:16px auto 20px;padding:12px 16px;}
.plant-page-search .search-tabs{margin-bottom:8px;gap:8px;}
.plant-page-search .tab-btn{padding:7px;font-size:0.85rem;}
/* The field inside the card. A tint rather than a border: the card is already
   a white box, and a second bordered box inside it is the thing being removed
   everywhere else on the site. */
.plant-page-search .wp-search{
  background:var(--green-100);border-radius:999px;padding:4px 16px;
}
.plant-page-search .wp-search input{padding:8px 0;font-size:0.95rem;}
.plant-page-search .photo-drop{min-height:0;padding:14px;gap:10px;}

/* .related-plants-grid / .related-plant-card lived here: a square photo with
   a name under it, used by the category, related-plants and bonsai lists. It
   was the second of two plant cards on the site, and the reason the category
   pages never looked like the homepage. Everything now renders the one card
   (.plant-grid / .plant-card below), so both classes are gone. */
.search-tabs{display:flex;gap:10px;margin-bottom:16px;}
.tab-btn{flex:1;padding:10px;border:none;border-radius:10px;background:var(--green-100);color:var(--green-700);font-weight:600;cursor:pointer;font-size:0.95rem;transition:.2s;}
.tab-btn.active{background:var(--green-500);color:#fff;}
.tab-panel{display:none;text-align:left;}
.tab-panel.active{display:block;}

/* "#plant-search-input{border:1px solid ...}" used to live here. It was the
   plant page's field, but the same id is on the homepage search and on the
   404, where the markup asks for a flat input inside a pill. An id scores
   1-0-0 and ".home-search-input{border:none}" scores 0-1-0, so the border
   won on all three: a rounded box sat inside the rounded pill, which is the
   box-in-a-box this change is undoing. The field is styled by .wp-search at
   the end of this file now, by class, so no page has to out-weigh an id. */

.search-results{margin-top:14px;display:flex;flex-direction:column;gap:8px;max-height:280px;overflow-y:auto;}
/* The message a search with nothing to show puts there. The colour was an
   inline #6a7a6f, which is below 4.5:1 on the white card; --muted is the
   token the rest of the site's secondary text uses. */
.search-empty{margin:0;padding:8px;color:var(--muted);}
.search-empty a{color:var(--green-700);text-decoration:underline;}

/* The address and its Copy button, on a wide screen with a mouse only.
   Hidden by default, so a phone gets exactly the markup it had before and
   nothing has to be measured for the common case to be right.

   Three conditions, and all three are needed:
     min-width  - there is room for an address on the line;
     hover:hover - the device has a pointer that can rest on something, which
                   rules out a tablet in portrait with a stylus-less finger;
     pointer:fine - that pointer is accurate, i.e. a mouse or a trackpad and
                   not a fingertip.
   A narrow desktop window therefore keeps the mailto alone, which is right:
   the test is "is there room and is this a mouse", not "is this a big phone".

   display:none and not visibility or opacity: hidden this way the button is
   out of the accessibility tree and out of the tab order too, so a phone
   reader is never offered a Copy button it cannot usefully press. */
.search-empty-desk{display:none;}
@media (min-width:900px) and (hover:hover) and (pointer:fine){
  /* A wrapping flex row, which is what gets "one line if it fits, two clean
     ones if not" without deciding in advance which it will be. The sentence
     and the address are the two items; column-gap separates them on one line,
     row-gap on two, and because both items are flex children the second line
     starts at the paragraph's own left edge instead of under wherever the
     first line happened to end. That is the alignment an inline span with a
     margin-left cannot give. */
  .search-empty{display:flex;flex-wrap:wrap;column-gap:14px;row-gap:3px;}
  .search-empty-desk{display:inline-flex;align-items:baseline;gap:7px;}
}
/* The site's own font, like the sentence it sits under. It was monospace, on
   the argument that an address is read character by character - true of a
   licence key, overdone for an address somebody is about to copy with the
   button next to it, and it read as a code sample rather than as text. */
.search-empty-addr{color:inherit;}
/* A text link, not a control with a box. No border, no background, and the
   colour of the sentence around it; the underline on hover and the focus ring
   are what say it can be pressed. */
.search-empty-copy{
  display:inline-flex;align-items:center;gap:5px;
  font:inherit;font-size:.92em;line-height:inherit;
  padding:0;border:0;background:none;color:inherit;cursor:pointer;
  text-decoration:underline;text-decoration-color:transparent;
  text-underline-offset:2px;transition:text-decoration-color .15s,color .15s;
}
.search-empty-copy:hover{color:var(--green-700);text-decoration-color:currentColor;}
.search-empty-copy:focus-visible{
  outline:2px solid var(--green-500);outline-offset:3px;border-radius:4px;
}
.search-empty-copy-icon{width:15px;height:15px;flex:none;}
/* Done: the word changes and the icon goes green, which is the whole signal.
   Nothing moves, because the icon keeps its box and the two words are close
   enough in length ("Copier"/"Copié", "Kopieren"/"Kopiert") that the line
   does not reflow. */
.search-empty-copy.is-done{color:var(--green-700);}
.result-item{display:flex;align-items:center;gap:12px;padding:8px;border-radius:10px;cursor:pointer;transition:.15s;}
.result-item:hover{background:var(--green-100);}
.result-item img{width:48px;height:48px;object-fit:cover;border-radius:8px;}
.result-item .rname{font-weight:600;color:var(--green-900);}
.result-item .rlatin{font-size:0.8rem;color:var(--muted);font-style:italic;}

.photo-drop{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;min-height:140px;border:2px dashed var(--green-300);border-radius:10px;color:var(--green-700);text-align:center;padding:20px;font-weight:500;background:var(--green-100);transition:.15s;}
.photo-drop.drag-active{border-color:var(--green-500);background:var(--green-300);}
.photo-choice-buttons{display:flex;gap:12px;flex-wrap:wrap;justify-content:center;}
.photo-choice-btn{display:inline-flex;align-items:center;justify-content:center;padding:10px 18px;border-radius:8px;background:var(--green-700);color:#fff;font-weight:600;font-size:0.95rem;cursor:pointer;transition:.15s;}
.photo-choice-btn:hover{background:var(--green-500);}
#photo-preview{max-width:100%;max-height:220px;border-radius:10px;margin-top:14px;display:block;}
.photo-result{margin-top:14px;}

.breadcrumb{font-size:0.85rem;color:var(--green-700);margin:14px 0 0;}
.breadcrumb a{color:var(--green-700);}
.breadcrumb a:hover{color:var(--green-500);text-decoration:underline;}
.breadcrumb-sep{margin:0 8px;color:var(--green-300);}
.breadcrumb [aria-current="page"]{color:var(--green-900);font-weight:600;}

.tools-columns{display:grid;grid-template-columns:1fr 1fr;gap:24px;margin:16px 0 40px;}
.tools-column h2{color:var(--green-900);font-size:1.05rem;margin:0 0 12px;}
.tool-item{background:var(--green-100);padding:12px 14px;border-radius:10px;margin-bottom:10px;}
.tool-item b{display:block;color:var(--green-900);margin-bottom:4px;}
.tool-item p{margin:0;font-size:0.9rem;color:var(--text);line-height:1.5;}

.section-title{color:var(--green-900);margin:50px 0 20px;font-size:1.5rem;}











/* A short page used to leave a band of cream below the footer: on a 410 at
   1280x900 the footer ended at 514px and 386px of background showed under it.
   The body is a column that fills the viewport and the footer takes the slack,
   so it sits on the bottom edge when there is not enough content to push it
   there, and behaves normally when there is.
   The cookie banner, its dim and the scripts are all out of flow, so the
   footer is the last thing in the column either way. */
body{min-height:100vh;display:flex;flex-direction:column;}
.site-footer{margin-top:auto;}
/* The publish flow has no footer and sets its own full-height background. */
.pub-body{display:block;}
.site-footer{background:var(--green-900);color:var(--green-300);text-align:center;padding:20px;font-size:0.9rem;}
/* Growing calendar ---------------------------------------------------------
   Fixed design: the same card, the same three colours, for every plant that
   has calendar data. Only the segment positions change, so these values are
   deliberately literal rather than themed. */
/* Same pale green and radius as .info-item and .placement, so this reads as
   one of the page's cards rather than an insert pasted over them. */
.gcal{
  background:var(--green-100);border-radius:12px;
  padding:18px 20px 14px;margin:0 0 18px;
}
/* Titles the card, rather than repeating the h1 sitting just above it.
   Same treatment as the Meilleur emplacement heading it sits beside. */
.gcal-head{margin:0 0 10px;font-size:0.85rem;font-weight:700;letter-spacing:0.04em;
  text-transform:uppercase;color:var(--green-700);}
.gcal-badge{
  display:inline-flex;align-items:center;gap:6px;margin:0 0 16px;
  padding:5px 12px;border-radius:999px;
  background:#E7F0E5;color:#2F5D3A;font-size:0.85rem;font-weight:600;
}
.gcal-leaf{width:15px;height:15px;flex:none;}

/* The track is the whole year. Segments are positioned on it, so months with
   no activity stay empty instead of being stretched to fill the bar. */
/* White for the empty months now the card itself is green, so the months with
   nothing happening still read as empty rather than as a fourth phase. */
/* One row per phase, because real windows overlap: basil is still being sown
   in June and July while the first sowings are already being picked. A single
   bar would have to pick a winner and invent a sequence. */
.gcal-rows{position:relative;display:grid;gap:8px;}
.gcal-row{display:grid;grid-template-columns:74px 1fr;align-items:center;gap:10px;}
.gcal-row-label{font-size:0.78rem;font-weight:600;color:#1B3A2B;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.gcal-track{position:relative;height:28px;border-radius:7px;background:#fff;}
/* Marker label sits once under the whole stack rather than on every row. */
.gcal-today-label{
  position:absolute;top:calc(100% + 4px);transform:translateX(-50%);margin:0;
  font-size:0.72rem;font-weight:700;color:#1B3A2B;white-space:nowrap;
}
.gcal-seg{
  position:absolute;top:0;bottom:0;display:flex;align-items:center;justify-content:center;
  padding:0 6px;font-size:0.8rem;font-weight:600;overflow:hidden;
}
.gcal-seg span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.gcal-seg-sow{background:#D9E8D2;color:#3E6B3E;border-radius:7px 0 0 7px;}
.gcal-seg-growth{background:#9FCB8E;color:#1F4D22;}
.gcal-seg-harvest{background:#E8A93C;color:#5C3D0A;border-radius:7px;}
.gcal-seg-sow{border-radius:7px;}
/* The source gave a season, not months, so the edges are deliberately soft:
   the bar has to occupy months to line up with the axis, but it should not
   read as a boundary the source never stated. */
.gcal-seg-approx{
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 14%,#000 86%,transparent 100%);
  mask-image:linear-gradient(90deg,transparent 0,#000 14%,#000 86%,transparent 100%);
}

/* Marker sits above the bar and carries its own label below it. translateX
   keeps it centred on the date rather than starting at it. */
.gcal-today{position:absolute;top:-4px;bottom:-4px;width:2px;background:#1B3A2B;transform:translateX(-1px);}
.gcal-today span{
  position:absolute;top:calc(100% + 5px);left:50%;transform:translateX(-50%);
  font-size:0.72rem;font-weight:700;color:#1B3A2B;white-space:nowrap;
}
/* Offset by the row-label column (74px) plus its gap (10px), so the month
   ticks line up with the start of the tracks rather than the card edge. */
.gcal-months{
  display:grid;grid-template-columns:repeat(12,1fr);
  margin:26px 0 0 84px;padding:0;list-style:none;
}
.gcal-months li{text-align:center;font-size:0.72rem;color:#8a9a90;}
/* Says what this card answers, so it does not read as a rival to the
   Care by Season tab, which answers the other question. */
.gcal-note{margin:12px 0 0;font-size:0.75rem;line-height:1.45;color:#7a8a80;}
.gcal-source{margin:4px 0 0;font-size:0.72rem;color:#8a9a90;}
.gcal-source a{color:inherit;}

/* Desktop keeps the labels inside the bar, as designed, so the legend is for
   phones only. */
.gcal-legend{display:none;}

@media(max-width:640px){
  .gcal{padding:16px 14px 12px;}
  .gcal-badge{font-size:0.8rem;padding:5px 10px;}
  .gcal-track{height:24px;}
  .gcal-row{grid-template-columns:62px 1fr;gap:8px;}
  .gcal-row-label{font-size:0.72rem;}
  .gcal-months{margin-left:70px;}
  .gcal-months li{font-size:0.68rem;}
  /* A two-month phase is about 50px wide on a phone, which is not enough for
     "Croissance" at any readable size. Rather than ship a truncated word, the
     bar goes colour-only here and the names move to a legend underneath. The
     colours, proportions and marker are unchanged. */
  .gcal-seg{font-size:0.66rem;}
  .gcal-legend{
    display:flex;flex-wrap:wrap;gap:6px 14px;
    margin:12px 0 0;padding:0;list-style:none;
  }
  .gcal-legend li{
    display:flex;align-items:center;gap:6px;
    font-size:0.76rem;font-weight:600;color:#1B3A2B;
  }
  .gcal-legend li span{font-weight:500;color:#7a8a80;}
  .gcal-legend i{width:11px;height:11px;border-radius:3px;flex:none;}
  .gcal-key-sow i{background:#D9E8D2;}
  .gcal-key-growth i{background:#9FCB8E;}
  .gcal-key-harvest i{background:#E8A93C;}
}
@media(max-width:400px){
  .gcal-months li{font-size:0.62rem;letter-spacing:-0.02em;}
  .gcal-legend{gap:5px 10px;}
  .gcal-legend li{font-size:0.72rem;}
}

.footer-links{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:8px 20px;margin-top:8px;
}
.footer-links a{
  display:inline-flex;align-items:center;gap:6px;
  color:var(--green-300);opacity:0.75;font-size:0.8rem;text-decoration:underline;
}
.footer-links a:hover{opacity:1;}
/* The text is only 17px tall, which is a poor tap target. Keyed to a coarse
   pointer rather than a width, so phones and tablets get the 44px hit area
   and a mouse-driven desktop keeps the tighter row. */
@media(pointer:coarse){
  .footer-links{gap:0 20px;}
  .footer-links a{min-height:44px;}
}
/* This icon carries a viewBox and no width/height, so with no rule of its own
   it took the replaced-element default and stretched to fill the footer: a
   1060px camera. Every other inline icon on the site is sized in CSS; this one
   was simply missed. */
.footer-icon{width:14px;height:14px;flex:none;}


/* inline-flex, not flex: as a block-level flex box this stretched the full
   width of the summary column with its label stranded at the left end. */
.bonsai-example{display:inline-flex;align-items:center;gap:8px;margin-top:8px;background:var(--green-100);padding:6px 12px 6px 6px;border-radius:20px;text-decoration:none;cursor:pointer;transition:.15s;}
.bonsai-example:hover{background:var(--green-300);}
.bonsai-example img{width:32px;height:32px;object-fit:cover;border-radius:50%;}
.bonsai-example span{font-size:0.75rem;font-weight:600;color:var(--green-700);}
.bonsai-steps{padding-left:20px;margin:0 0 16px;color:var(--text);font-size:1.05rem;}
.bonsai-steps li{margin-bottom:18px;line-height:1.7;}
.bonsai-diagram{background:#fff;border-radius:var(--radius);box-shadow:var(--shadow);padding:12px;margin:0 0 16px;max-width:380px;}
.bonsai-diagram img{width:100%;display:block;}
.plant-detail-content{max-width:var(--page-max);margin:0 auto;}
.plant-top{display:flex;gap:24px;align-items:flex-start;margin-bottom:18px;}
.plant-media{flex:0 0 260px;}
.plant-hero-figure{margin:0;}
/* A frame of one shape, whatever shape the photograph is.
   It was height:auto with object-fit:contain, which meant the box took the
   proportions of whichever photo was showing: a portrait one sat in it with
   white down the side, and switching between a portrait and a landscape one
   resized the frame and pushed the text below it up or down. The same 4/3 and
   cover the plant cards use, so one photo looks like the next and nothing
   moves when they are swapped.
   cover crops rather than shrinks, which also keeps the picture at a usable
   size: contain scaled a 1000x1333 photo down until the copyright mark in its
   corner was too small to read. */
.plant-hero-figure img{
  /* height:auto is load-bearing: the width and height ATTRIBUTES on the img
     are a presentational hint of height:750px, which beats aspect-ratio when
     height is left unset, and max-height then clamped the box to 400 and gave
     a 320x400 frame instead of a 320x240 one. */
  width:100%;height:auto;aspect-ratio:4/3;max-height:400px;object-fit:cover;
  background:var(--green-100);
  border-radius:var(--radius);box-shadow:var(--shadow);display:block;
}
.plant-gallery-thumbs{display:flex;gap:8px;overflow-x:auto;padding-bottom:6px;margin-top:8px;}
.gthumb-btn{flex:0 0 auto;padding:0;border:2px solid transparent;border-radius:10px;background:none;cursor:pointer;line-height:0;}
.gthumb-btn img{width:56px;height:56px;object-fit:cover;border-radius:8px;display:block;}
.gthumb-btn:hover{border-color:var(--green-300);}
.gthumb-btn.active{border-color:var(--green-500);}
.plant-summary{flex:1;min-width:0;}
.plant-summary h1{margin:0 0 4px;color:var(--green-900);font-size:1.6rem;}
.plant-summary .latin{font-style:italic;color:var(--muted);}
.diff-badge{display:inline-block;margin-top:8px;background:var(--green-100);color:var(--green-700);padding:4px 10px;border-radius:20px;font-size:0.8rem;font-weight:600;}

.variation-section{margin-bottom:20px;}
.variation-label{display:block;font-size:0.8rem;color:var(--green-700);text-transform:uppercase;letter-spacing:0.03em;margin-bottom:8px;}
.variation-list{display:flex;flex-wrap:wrap;gap:8px;}
.variation-chip{background:var(--green-100);color:var(--green-700);padding:6px 12px;border-radius:20px;font-size:0.85rem;}

.detail-tabs{display:flex;gap:8px;margin:24px 0 16px;flex-wrap:wrap;}
.dtab-btn{background:#fff;border:1px solid var(--green-300);padding:9px 15px;border-radius:20px;font-weight:600;color:var(--green-700);cursor:pointer;transition:.2s;}
.dtab-btn:hover{border-color:var(--green-500);}
.dtab-btn.active{background:var(--green-100);border-color:var(--green-500);color:var(--green-900);}
.dtab-panel{display:none;}
.dtab-panel.active{display:block;}

.info-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;}
.info-item{background:var(--green-100);padding:12px;border-radius:10px;}
.info-item h3{display:block;color:var(--green-900);margin:0 0 4px;font-size:0.85rem;font-weight:700;}
/* Only the facts that carry a citation get one, so it is set quietly and does
   not compete with the care text around it. */
.info-source{display:block;margin-top:4px;font-size:0.72rem;color:#8a9a90;}
.info-source a{color:inherit;}

.season-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;}
.season-item{background:var(--cream);border-left:4px solid var(--green-500);padding:12px 14px;border-radius:8px;}
.season-item h3{display:block;color:var(--green-900);margin:0 0 4px;font-size:1rem;font-weight:700;text-transform:capitalize;}
/* Growing & Maintenance reuses the season cards, but its headings are phrases
   ("Soil and pot", "Erde und Topf"), which capitalize would turn into titles. */
.grow-grid .season-item h3{text-transform:none;}

.pest-item{background:#fff5f0;border-left:4px solid #d97b5f;padding:12px 14px;border-radius:8px;margin-bottom:10px;}
.pest-item h3{color:#a8452a;margin:0;font-size:1rem;font-weight:700;}
.pest-item .signs{font-size:0.85rem;color:#7a5a4e;margin:4px 0;}

/* Common problems, above the pests in the same tab. Amber rather than the
   pests' red: these are care mistakes to correct, not something to treat. */
.problems-title{color:var(--green-900);font-size:1.05rem;font-weight:700;margin:18px 0 10px;}
.problems-title:first-of-type{margin-top:0;}
.problem-list{display:grid;gap:10px;margin-bottom:6px;}
.problem-item{background:#fdf6e3;border-left:4px solid #e0b84b;padding:12px 14px;border-radius:8px;}
.problem-item h4{color:var(--warn-ink);margin:0;font-size:1rem;font-weight:700;}
.problem-item .cause{font-size:0.9rem;color:#6b5518;margin:4px 0;}
@media(min-width:900px){
  .problem-list{grid-template-columns:1fr 1fr;gap:12px;}
}

.plant-intro{margin:16px 0 0;color:var(--text);font-size:1.08rem;line-height:1.7;}
/* Had a bottom margin only, so it sat flush against whatever card was above. */
.highlight-box{background:#fdf6e3;border-left:4px solid #e0b84b;border-radius:8px;padding:14px 18px;margin:20px 0;}
.highlight-box h3{display:block;color:var(--warn-ink);margin:0 0 4px;font-size:1rem;font-weight:700;}
.highlight-box p{margin:0;color:#6b5518;font-size:1.02rem;line-height:1.6;}
/* Cards, like every other tab, and two columns on desktop so the panel is not
   half empty. The columns also hold each answer at a readable measure without
   a max-width that would strand the right-hand side. */
.faq-grid{display:grid;gap:12px;}
.faq-item{background:var(--green-100);border-radius:10px;padding:14px 16px;margin:0;}
.faq-item h3{display:block;color:var(--green-900);margin:0 0 6px;font-size:1rem;font-weight:700;}
.faq-item p{margin:0;color:var(--text);font-size:0.97rem;line-height:1.6;}
@media(min-width:900px){
  .faq-grid{grid-template-columns:1fr 1fr;gap:14px;}
}

/* Widening the article to the page width lets the two-column grids use the
   space, but running prose has to stay at a readable measure, or a line of FAQ
   answer runs to roughly 150 characters at 1920. Scoped to wide screens, so
   nothing at or below 900px is touched. */
@media(min-width:900px){
  .plant-intro{max-width:70ch;}
  /* The card fills the panel like every other card; it is the text inside it
     that needs the measure. Capping the card itself stopped the pest panel at
     58% of the container while Informations and Entretien filled it. */
  .pest-item > div{max-width:72ch;}
  /* A 260px photo beside a 900px text column read as an afterthought once the
     article got wider. */
  .plant-media{flex:0 0 320px;}
}

.verdict-box{flex:2;min-width:260px;border-radius:10px;padding:14px 18px;font-weight:600;line-height:1.5;}
.verdict-good{background:#e3f5e9;color:var(--green-900);border:1px solid var(--green-300);}
.verdict-bad{background:#fff5f0;color:#a8452a;border:1px solid #f0c4b0;}

/* Shared with Plant Sitters. The marketplace's own listing/search/map styles
   moved to the .mk-* block at the end of this file. */
.listing-location{font-size:0.85rem;color:var(--muted);margin:0 0 6px;}
.listing-contact{display:inline-block;background:var(--green-500);color:#fff;text-decoration:none;padding:8px 16px;border-radius:8px;font-weight:600;font-size:0.9rem;border:1px solid transparent;cursor:pointer;}
.listing-contact:hover{background:var(--green-700);}
.listing-contact.message-toggle{background:transparent;color:var(--green-700);border-color:var(--green-500);}
.listing-contact.message-toggle:hover{background:var(--green-100);}
.no-results{text-align:center;color:var(--muted);padding:30px 0;}
.market-post-cta{background:var(--green-100);border-radius:var(--radius);padding:30px;text-align:center;margin:30px 0;}
.market-post-cta h2{color:var(--green-900);margin:0 0 8px;}
.market-post-cta p{color:var(--green-700);margin:0 0 16px;}
.sitters-wrap{padding-bottom:60px;}
.sitters-gate{background:#fff;border-radius:var(--radius);box-shadow:var(--shadow);padding:30px;text-align:center;}
.sitters-gate p{color:var(--green-700);margin-bottom:16px;}
.sitters-coming-soon{font-size:0.85rem;color:#8aa392;margin-top:14px;margin-bottom:0;}
.auth-form{display:flex;flex-direction:column;gap:10px;max-width:360px;margin:0 auto;text-align:left;}
.auth-form label{font-size:0.85rem;font-weight:600;color:var(--green-700);}
.auth-form input{padding:10px 12px;border:1px solid var(--green-300);border-radius:8px;font-size:1rem;}
.auth-form button[type="submit"]{margin-top:6px;padding:12px;border:none;border-radius:8px;cursor:pointer;}
.auth-toggle-link{background:none;border:none;color:var(--green-700);text-decoration:underline;cursor:pointer;font-size:0.9rem;padding:4px;}
.auth-message{margin-top:14px;color:var(--green-700);font-weight:600;}
.oauth-btn{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;max-width:360px;margin:0 auto 12px;padding:12px;border:1px solid var(--green-300);border-radius:8px;background:#fff;color:var(--text);font-weight:600;font-size:0.95rem;cursor:pointer;}
.oauth-btn:hover{border-color:var(--green-500);background:var(--green-100);}
.oauth-btn-apple{background:#000;color:#fff;border-color:#000;}
.oauth-btn-apple:hover{background:#222;border-color:#222;}
.oauth-divider{max-width:360px;margin:0 auto 12px;text-align:center;color:#8aa392;font-size:0.85rem;}
.oauth-switch{margin-top:16px;font-size:0.9rem;color:var(--green-700);}
.oauth-switch a{color:var(--green-700);font-weight:700;text-decoration:underline;}
#auth-back{display:block;margin-bottom:14px;}
.sitters-account-bar{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;color:var(--green-900);font-weight:600;}
.link-btn{background:none;border:none;color:var(--green-700);text-decoration:underline;cursor:pointer;}
.sitters-post-panel{background:#fff;border-radius:var(--radius);box-shadow:var(--shadow);padding:24px;margin-bottom:30px;}
.sitters-post-panel h2{margin:0 0 14px;color:var(--green-900);}
.dashboard-info-row{display:flex;justify-content:space-between;padding:8px 0;border-bottom:1px solid var(--green-100);}
.dashboard-info-row:last-of-type{border-bottom:none;}
#dashboard-signout{margin-top:14px;}
.dashboard-message-card,.dashboard-listing-card{background:var(--green-100);border-radius:10px;padding:14px 16px;margin-bottom:10px;}
.dashboard-message-card .meta,.dashboard-listing-card .meta{font-size:0.8rem;color:var(--green-700);font-weight:600;margin-bottom:4px;}
.dashboard-source-tag{font-weight:400;font-style:italic;opacity:0.8;}
.listing-form{display:flex;flex-direction:column;gap:10px;}
.listing-form-row{display:flex;gap:14px;flex-wrap:wrap;}
.listing-form-row[hidden]{display:none;}
.sitters-role-intro{max-width:640px;margin:0 0 24px;color:var(--green-700);}

.form-select-label{font-size:0.85rem;font-weight:700;color:var(--green-700);margin:0 0 4px;}
.care-type-row{margin-top:10px;padding-top:14px;border-top:1px dashed var(--green-300);}
#care-type-row[hidden]{display:none;}
#compensation-row[hidden]{display:none;}

.role-options{display:grid;grid-template-columns:1fr 1fr;gap:14px;}
.role-option{position:relative;display:flex;flex-direction:column;gap:4px;padding:14px 16px;border:1px solid var(--green-300);border-radius:10px;cursor:pointer;background:#fff;font-weight:500;}
.role-option input{position:absolute;opacity:0;pointer-events:none;}
.role-option:hover{border-color:var(--green-500);}
.role-option:has(input:checked){border-color:var(--green-500);background:var(--green-100);}
.role-option-label{color:var(--green-900);}
.role-option-desc{font-size:0.8rem;color:var(--text);opacity:0.75;font-weight:400;}

#always-available-row{margin-top:10px;}
#always-available-row[hidden]{display:none;}

#dates-section{margin-top:10px;padding-top:14px;border-top:1px dashed var(--green-300);display:flex;flex-direction:column;gap:14px;}
#dates-section[hidden]{display:none;}
.date-field{display:flex;flex-direction:column;gap:4px;flex:1;min-width:140px;}
.date-field label{font-size:0.85rem;font-weight:600;color:var(--green-700);}
#listing-photo-row{display:flex;flex-direction:column;gap:6px;}
#listing-photo-row[hidden]{display:none;}
#listing-photo-row label{font-size:0.85rem;font-weight:600;color:var(--green-700);}
.sitter-listing-photo{width:100%;max-height:220px;object-fit:cover;border-radius:10px;margin-bottom:10px;}
.listing-form-row label{display:flex;align-items:center;gap:6px;font-weight:500;}
.listing-form input,.listing-form textarea{padding:10px 12px;border:1px solid var(--green-300);border-radius:8px;font-size:1rem;flex:1;min-width:140px;}
.listing-form textarea{min-height:80px;resize:vertical;}
.form-safety-note{font-size:0.8rem;color:#a8452a;margin:4px 0 0;}
.autocomplete-field{position:relative;flex:1;min-width:140px;}
.autocomplete-field input{width:100%;}
.autocomplete-suggestions{position:absolute;top:100%;left:0;right:0;background:#fff;border:1px solid var(--green-300);border-radius:8px;box-shadow:var(--shadow);max-height:220px;overflow-y:auto;z-index:20;margin-top:4px;}
.autocomplete-suggestions[hidden]{display:none;}
.autocomplete-option{padding:8px 12px;cursor:pointer;font-size:0.95rem;}
.autocomplete-option:hover,.autocomplete-option.active{background:var(--green-100);}
.location-note{font-size:0.8rem;color:#a8452a;margin:-4px 0 0;}
.listing-form button[type="submit"]{align-self:flex-start;padding:10px 20px;border:none;border-radius:8px;cursor:pointer;margin-top:6px;}
.sitter-listing-card{background:#fff;border-radius:var(--radius);box-shadow:var(--shadow);padding:20px;margin-bottom:16px;}
.sitter-listing-meta{font-size:0.75rem;font-weight:700;color:var(--green-700);text-transform:uppercase;letter-spacing:0.03em;margin-bottom:6px;}
.sitter-listing-card h3{margin:0 0 6px;color:var(--green-900);}
.sitter-poster{font-size:0.85rem;color:var(--muted);font-style:italic;}
.message-box{margin-top:10px;display:flex;flex-direction:column;gap:8px;}
.message-box textarea{padding:10px;border:1px solid var(--green-300);border-radius:8px;min-height:60px;}
.message-box button{align-self:flex-start;padding:8px 16px;border:none;border-radius:8px;cursor:pointer;}

@media(max-width:480px){
  .header-inner{gap:8px;padding:12px 14px;}
  /* 4:1, so 28px tall is 112px wide, close to what the old wordmark took. */
  .brand img{height:28px;}
  .login-btn{padding:8px 14px;font-size:0.85rem;}
  #lang-select{padding:4px 6px;font-size:0.85rem;}
}
/* Very narrow phones. The German header was already 5px over at this width
   with the old text wordmark, and the logo is wider than that text was, so
   the row is tightened here rather than only giving back what the logo took. */
@media(max-width:400px){
  .header-inner{gap:6px;padding:10px 10px;}
  .brand img{height:24px;}
  .login-btn{padding:7px 11px;font-size:0.8rem;}
}

@media(max-width:600px){
  .info-grid,.season-grid,.tools-columns{grid-template-columns:1fr;}
  .hero h1{font-size:1.6rem;}
  .search-tabs{flex-direction:column;}
  .plant-top{flex-direction:column;gap:12px;}
  .plant-media{flex:0 0 auto;width:100%;}
  .plant-hero-figure img{max-height:240px;}
  .role-options{grid-template-columns:1fr;}
}

.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;}

/* --- Homepage -------------------------------------------------------------
   Three bands: a calm hero that leads with the search, three feature cards,
   then the library. The old page opened with an ad slot and a pale gradient
   headline; this leads with the sentence that says what the site is for. */

.home-hero{
  /* --hero-focus-* now default in :root, shared with the other two heroes.
     The phone override further down still belongs to this one. */
  position:relative;isolation:isolate;overflow:hidden;
  background:
    radial-gradient(1100px 420px at 50% -120px, rgba(76,154,99,.16), transparent 70%),
    linear-gradient(180deg,var(--green-100),var(--cream) 78%);
  /* The bottom padding is the landing strip for the feature cards, which sit
     half over the hero. Content centres inside the padding box, so it ends up
     above the cards rather than behind them.

     140px here, with the cards pulled back 54, left 144px of empty hero
     between the search box and the first card. The cards are rows now rather
     than tall tiles, so the strip they need is the overlap plus a normal
     gap: 82 - 54 = 28px of padding below the content, which measures 38px of
     air between the search box and the first card. */
  padding:52px 20px 82px;text-align:center;
}
/* Without a minimum the hero is only as tall as its text, and object-fit:cover
   then crops a 16:9 photograph to a thin mid-band, losing the doorway and the
   view through it. Capped so the hero never eats the fold. */
.home-hero.has-media{
  /* Scales with WIDTH, not just viewport height. object-fit:cover scales the
     photo to the hero's width, so on a 2000px screen a fixed 460px hero showed
     only 41% of the image height: a thin slice through the palest part of the
     frame, with the foliage cropped away above and below. Tying the floor to
     vw keeps roughly half the picture visible as the screen grows, and the vh
     term stops it eating a short viewport. */
  /* Raised again: at 30vw the cards had eaten the lower third and the box was
     only as tall as its own text, so object-fit:cover cropped the photograph
     to a thin pale band and the plants at top and bottom were lost. The vw
     term keeps roughly half the frame visible as the screen grows; the vh term
     stops it swallowing a short viewport. */
  /* Tightened again, and this is the half of the gap the padding did not
     explain. A floor above what the content actually needs is slack, and with
     the column pinned to the top every pixel of it fell into the gap below
     the search box: 515px of floor against 409px of content was 106px of
     empty hero nobody asked for. The floor now sits under the content at the
     sizes that matter, so it only does its original job, which is keeping the
     photograph from being cropped to a band on a screen whose text happens to
     be short. The cap is what a very wide screen gets, and there the gap grows
     again by whatever the cap exceeds the content. */
  min-height:clamp(340px, min(26vw, 48vh), 420px);
  /* Aligned to the top, not centred. Centring split all the slack between the
     header and the cards, so the taller the hero got the further the headline
     fell: 127px of gap at 1440px wide and over 200px at 1920px. The gap is now
     just the top padding, at any hero height, and the extra height goes to the
     photograph below the search box where it was wanted. */
  display:flex;align-items:flex-start;
}

/* The picture is absent until artwork is dropped into assets/hero/, and the
   gradient above is the hero on its own until then. */
/* Positive z-index, not negative: .home-hero sets isolation:isolate, and a
   negative-index child of a stacking context paints behind that element own
   background, which hid the photo under the fallback gradient. */
/* The one rule that puts hero artwork behind a hero. The homepage, the
   marketplace and Plant Sitting all carry it; what differs between them is
   where the crop is centred and whether the image is lifted, and that stays
   with each hero below. It was two near-identical copies before Plant Sitting
   needed a third. */
.hero-media{position:absolute;inset:0;z-index:0;display:block;}
/* The crop and the lift are part of the artwork, not of one page's layout, so
   they live with the picture and every hero gets the same ones. The focus
   point is a pair of variables (defaults in :root) so a hero can nudge its
   crop without re-exporting anything; the homepage does, on phones.
   The saturation and contrast were the homepage's alone, which is most of why
   the marketplace hero looked bleached beside it: same photograph, served
   flat. */
.hero-media img{
  width:100%;height:100%;object-fit:cover;display:block;
  object-position:var(--hero-focus-x) var(--hero-focus-y);
  filter:saturate(1.22) contrast(1.06);
}

/* Readability scrim. Veils the CENTRE only, not the whole frame: the bright
   sea-and-sky band through the middle is where the headline and search sit and
   carries little detail, while the interior plants on the left and the terrace
   on the right are the point of the picture and stay clear. Veiling toward
   cream rather than black keeps the dark-green type legible without restyling
   it. An even wash strong enough for the dark foliage at the column edges
   washed the whole photograph out. */
.home-hero.has-media::after{
  content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    /* Measured in px from the centre, not in percentages. The text column is a
       fixed 760px, so a percentage band tracks the viewport instead of the
       text: at 2000px it veiled 74% of the width to protect a column occupying
       38% of it, bleaching the Monstera and the terrace at the edges. Anchored
       to the column, the veil stays the same real width at every screen size
       and the planted edges stay clear. */
    /* A soft halo for the space labels, which sit on bare photograph with no
       panel behind them. It is a wash with no edge, not a container. */
    radial-gradient(ellipse 320px 210px at calc(50% + 530px) 44%,
      rgba(250,248,242,.92), rgba(250,248,242,.55) 52%, rgba(250,248,242,0) 100%),
    /* Lightened from .88/.62: that veil was tuned for a shorter hero where the
       photograph was a backdrop. With the taller frame it bleached the picture
       to near-white. The headline is #1b3a2b, dark enough to carry a thinner
       scrim; the sweep behind these numbers is in the commit message. */
    /* Falls off to nothing at ±570 rather than ±640, so the monstera on the
       left and the terrace on the right sit on clear photograph instead of
       the tail of the veil. The centre is unchanged. */
    linear-gradient(90deg,
      rgba(250,248,242,0)   calc(50% - 570px),
      rgba(250,248,242,.54) calc(50% - 470px),
      rgba(250,248,242,.82) calc(50% - 400px),
      rgba(250,248,242,.82) calc(50% + 400px),
      rgba(250,248,242,.54) calc(50% + 470px),
      rgba(250,248,242,0)   calc(50% + 570px)),
    linear-gradient(180deg,
      rgba(250,248,242,.16) 0%, rgba(250,248,242,.04) 40%,
      rgba(250,248,242,.22) 72%, rgba(250,248,242,.62) 88%,
      rgba(250,248,242,.95) 99%, rgba(250,248,242,1) 100%);
}

/* The headline column stays centred on the hero. It was briefly a two-column
   grid, which pushed the text 132px left of centre and out from under the
   scrim, dropping the headline to 2.4:1 over the dark monstera. The space
   labels float beside the column instead, so they cost the text nothing. */
.home-hero-inner{position:relative;z-index:2;max-width:760px;margin:0 auto;}
.home-hero-main{min-width:0;}

/* Space labels ------------------------------------------------------------- */
/* Deliberately not links. There are no balcony or garden destination pages, so
   these say what the site covers rather than promising a page that is not
   there. See the comment on the markup in scripts/build.js. */
.home-hero-title{
  margin:0 0 14px;color:var(--green-900);font-size:clamp(2rem,4.6vw,3rem);
  line-height:1.1;letter-spacing:-0.02em;font-weight:800;
}
.home-hero-sub{
  margin:0 auto 30px;max-width:60ch;color:#4d5f55;
  font-size:clamp(1rem,1.7vw,1.13rem);line-height:1.6;
}

/* Search sits on white against the tinted hero, so it reads as the one thing
   to do here rather than as another band of colour. */
.home-search{
  display:flex;align-items:center;gap:12px;max-width:560px;margin:0 auto;
  background:#fff;border:1px solid #e3eae5;border-radius:999px;padding:6px 8px 6px 20px;
  box-shadow:0 10px 30px rgba(27,58,43,.10);
}
/* The ring itself comes from .wp-focus-ring at the end of the file, so that
   every search on the site shows the same one. This only tints the border. */
.home-search:focus-within{border-color:var(--green-500);}
/* ".home-search-icon{color:#8b9991}" was here. The icon is .wp-search-icon
   now, in the site green, like the pin and the calendar on the other cards. */
.home-search-input{padding:14px 0;font-size:1rem;}
.home-search-results{max-width:560px;margin:10px auto 0;text-align:left;}
.home-search-results:not(:empty){
  background:#fff;border:1px solid #e3eae5;border-radius:16px;padding:8px;
  box-shadow:0 10px 30px rgba(27,58,43,.10);
}

/* Feature cards ------------------------------------------------------------ */
/* The cards straddle the bottom edge of the hero, roughly half over the
   photograph and half on the cream below it, so the two read as one
   composition instead of a band and then a separate section. The hero's
   bottom padding is what keeps its own content clear of them. */
/* Two cards, not three. Stretching the pair across the full 1240px container
   left each one wide and empty, so they keep roughly the width they had as a
   trio and sit centred under the hero instead. */
/* Two cards, side by side from 768px and stacked below it. They used to be
   tall centred tiles: a 76px icon, centred copy and a call-to-action pill,
   which came to 260px of height for two sentences. They are rows now, icon
   left and text right, and the pill is gone because the whole card was
   already the link to the same place. */
.home-features{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;
  /* Wider than the 840px the tall cards used. A row gives the text about
     260px at that width, which is three lines of the German marketplace
     sentence; 920 brings it to two without touching the type size. */
  max-width:920px;margin:-54px auto 0;position:relative;z-index:2;
}
/* Dark green, not white. These two cards are the only route from the homepage
   to the marketplace and the sitting board, and as white cards on a page of
   white cards they read as two more plant tiles. Green makes them the one
   thing under the hero that is not the library.

   The colour is --green-800, which this pair is what added to the palette: it
   sits between the 900 the header ink uses and the 700 of the buttons. White
   on it measures 8.1:1, and the paragraph at 88% white 6.5:1, both well over
   the 4.5:1 the text has to clear. */
.home-feature{
  display:flex;align-items:center;text-align:left;gap:14px;min-height:44px;
  background:var(--green-800);border:1px solid rgba(255,255,255,.14);
  border-radius:16px;padding:20px;
  box-shadow:0 14px 32px rgba(27,58,43,.22);transition:.18s;
}
.home-feature:hover{
  transform:translateY(-2px);box-shadow:0 18px 40px rgba(27,58,43,.3);
  border-color:rgba(255,255,255,.28);
}
/* White, not --green-500: the focus ring has to be visible against the card
   it sits on, and a mid green on a dark green is the one pair that fails. */
.home-feature:focus-visible{outline:3px solid #fff;outline-offset:3px;}
/* The tile, and the line icon centred in it.
   White at 16% rather than the pale --green-100 the rest of the page uses for
   icons, because on this card that pale tile would be the brightest thing on
   it. 48px, with the icon at 28 inside it: the icon used to be a bitmap that
   filled the tile edge to edge, and a line drawing at that size reads as a
   diagram rather than an icon. The padding the tile had is the gap now, so
   centring does the work instead of a fixed inset. */
.home-feature-tile{
  flex:none;width:48px;height:48px;border-radius:13px;
  background:rgba(255,255,255,.16);
  display:flex;align-items:center;justify-content:center;
}
/* currentColor on the svg, so this one rule sets the stroke. */
.home-feature-icon{flex:none;width:28px;height:28px;color:#fff;}
.home-feature-text{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1;}
.home-feature h2{margin:0;font-size:1.02rem;font-weight:800;color:#fff;letter-spacing:-0.01em;}
.home-feature p{margin:0;font-size:0.84rem;line-height:1.45;color:rgba(255,255,255,.88);max-width:none;}
/* The chevron points down everywhere else on the site; here it is the "go"
   affordance left over from the pill, so it is turned to point along the
   reading direction and nudges on hover. */
.home-feature-go{
  flex:none;width:17px;height:17px;color:#fff;
  transform:rotate(-90deg);transition:transform .18s;
}
.home-feature:hover .home-feature-go{transform:translateX(3px) rotate(-90deg);}

/* Library ------------------------------------------------------------------ */
.home-library{margin-top:44px;padding-bottom:64px;}
/* The category hero carries the same search box as the homepage. .hero gives
   its <p> a 30px bottom margin, which is the gap above the field. */
.category-search{margin-top:4px;}
/* A listing page has no "Browse the library" heading above the chips: the
   <h1> in the hero directly above already names what is being listed. */
.category-hero + .home-library{margin-top:30px;}
/* The chip row and the count sit on one line, the count pushed to the right,
   wrapping under on a narrow screen rather than squeezing the chips. */
.listing-head{display:flex;align-items:baseline;gap:16px;flex-wrap:wrap;}
.listing-head .category-chips{flex:1;min-width:0;}
.listing-count{flex:none;margin:0 0 26px;font-size:.9rem;color:var(--muted);white-space:nowrap;}
.home-library-more{margin:26px 0 0;text-align:center;}
.home-library-head{display:flex;align-items:baseline;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:18px;}
.home-library-head .section-title{margin:0;}
.home-library-count{margin:0;font-size:0.9rem;color:var(--muted);}

.category-chips{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:26px;}
/* The chip for the page you are on. Filled rather than outlined, so the row
   says where you are without needing to read every label. */
.category-chip.is-active{
  background:var(--green-700);border-color:var(--green-700);color:#fff;
}
.category-chip.is-active .chip-icon{color:#fff;}
.category-chip.is-active:hover{background:var(--green-900);border-color:var(--green-900);color:#fff;}
.category-chip.is-active:hover .chip-icon{color:#fff;}
.category-chip{
  display:inline-flex;align-items:center;gap:8px;
  background:#fff;border:1px solid #e3eae5;color:#46564c;border-radius:999px;
  padding:9px 16px 9px 13px;font-size:0.9rem;font-weight:600;transition:.15s;
}
.category-chip:hover{border-color:var(--green-500);color:var(--green-900);background:#f4faf6;}
.category-chip:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.chip-icon{width:18px;height:18px;flex:none;color:var(--green-500);}
.category-chip:hover .chip-icon{color:var(--green-700);}

/* The phone category picker -------------------------------------------------
   Below 700px the chip row is replaced by a compact bar that opens a bottom
   sheet. Both the bar and the swap are gated on .cat-picker-ready, which
   assets/category-picker.js sets at parse time: with scripting off the chips
   stay exactly as they are and the bar never appears. */
.cat-picker-bar{display:none;}
@media(max-width:699px){
  html.cat-picker-ready .cat-picker-bar{
    display:flex;align-items:center;gap:12px;margin-bottom:18px;
  }
  html.cat-picker-ready .category-chips{display:none;}
  /* The bar carries the count on a phone, so the one in the section heading
     above it, and the one beside the chip row, would say it twice more. */
  html.cat-picker-ready .home-library-count,
  html.cat-picker-ready .listing-count{display:none;}
}
.cat-picker-btn{
  flex:1;min-width:0;display:flex;align-items:center;gap:10px;min-height:52px;
  padding:8px 14px;border:1px solid var(--green-300);border-radius:999px;
  background:#fff;color:var(--green-900);font:inherit;text-align:left;cursor:pointer;
}
.cat-picker-btn:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.cat-picker-grid{width:20px;height:20px;flex:none;color:var(--green-700);}
.cat-picker-chevron{width:18px;height:18px;flex:none;color:var(--green-700);}
.cat-picker-text{flex:1;min-width:0;display:flex;flex-direction:column;line-height:1.25;}
.cat-picker-label{font-size:.72rem;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);}
.cat-picker-current{
  font-weight:700;font-size:.95rem;color:var(--green-900);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.cat-picker-count{flex:none;font-size:.82rem;color:var(--muted);white-space:nowrap;}

.cat-sheet-backdrop{
  position:fixed;inset:0;z-index:90;background:rgba(27,58,43,.45);
  opacity:0;transition:opacity .24s ease;
}
.cat-sheet-backdrop.is-open{opacity:1;}
.cat-sheet-backdrop[hidden]{display:none;}
.cat-sheet{
  position:fixed;left:0;right:0;bottom:0;z-index:91;
  display:flex;flex-direction:column;max-height:82vh;max-height:82svh;
  background:var(--cream);border-radius:22px 22px 0 0;
  box-shadow:0 -12px 40px rgba(27,58,43,.24);
  transform:translateY(100%);transition:transform .26s cubic-bezier(.22,.9,.3,1);
  padding-bottom:env(safe-area-inset-bottom);
}
.cat-sheet.is-open{transform:translateY(0);}
.cat-sheet[hidden]{display:none;}
.cat-sheet-handle{
  width:44px;height:5px;border-radius:999px;background:var(--green-300);
  margin:10px auto 2px;flex:none;
}
.cat-sheet-head{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:6px 18px 10px;flex:none;
}
.cat-sheet-head h2{margin:0;font-size:1.05rem;color:var(--green-900);}
.cat-sheet-close{
  flex:none;width:44px;height:44px;display:flex;align-items:center;justify-content:center;
  border:0;border-radius:50%;background:var(--green-100);color:var(--green-700);cursor:pointer;
}
.cat-sheet-close:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.cat-sheet-grid{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;
  padding:4px 18px 20px;overflow-y:auto;flex:1;min-height:0;
  overscroll-behavior:contain;
  /* The grid has a definite height (flex:1 inside the sheet), and grid's
     default align-content:stretch then divides that height between the rows
     rather than letting each row size to its content. A two-line name like
     "Succulentes & Cactus" needed 95px and got 86, so its plant count was
     clipped off the bottom of the tile. start lets the rows grow, and the
     grid scrolls once they total more than the sheet. */
  align-content:start;
  /* Every tile is the same height by construction (see .cat-tile b below), so
     the rows only need a floor. Comfortably over the 44px minimum. */
  grid-auto-rows:minmax(96px,auto);
}
.cat-tile{
  display:flex;flex-direction:column;gap:3px;
  padding:12px;border:1px solid #e7ece8;border-radius:14px;background:#fff;
  color:var(--green-900);text-decoration:none;
}
/* Two lines for the name, always, whether it needs them or not.
   Letting the tile grow to fit a wrapped name did not work: inside a grid that
   is itself a flex child with its own scrolling, the row would not grow past
   86px however the track sizing was expressed, and the plant count was cut off
   "Succulentes & Cactus", "Lianes & retombantes" and "Herbes aromatiques".
   Giving the name an exact two-line box makes every tile identical by
   construction, which is what a picker grid should look like anyway, and a
   longer name than that is clamped. flex:none so nothing is squashed. */
.cat-tile b{
  flex:none;font-size:.92rem;font-weight:700;line-height:1.25;
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;
  height:2.5em;
  /* German compounds do not break at a space because they have none:
     "Aquarienpflanzen" is wider than a tile at 320px and was clipped
     mid-word by the overflow above. */
  overflow-wrap:anywhere;
}
.cat-tile-count{flex:none;font-size:.78rem;color:var(--muted);}
.cat-tile-icon{flex:none;display:block;width:22px;height:22px;color:var(--green-700);margin-bottom:2px;}
.cat-tile-icon svg{width:22px;height:22px;display:block;}
.cat-tile.is-active{background:var(--green-700);border-color:var(--green-700);color:#fff;}
.cat-tile.is-active .cat-tile-count{color:rgba(255,255,255,.82);}
.cat-tile.is-active .cat-tile-icon{color:#fff;}
.cat-tile:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
@media(prefers-reduced-motion:reduce){
  .cat-sheet,.cat-sheet-backdrop{transition:none;}
}

.plant-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:20px;}
.plant-card{
  display:flex;flex-direction:column;background:#fff;border:1px solid #e7ece8;
  border-radius:16px;overflow:hidden;transition:.18s;
}
.plant-card:hover{transform:translateY(-3px);box-shadow:0 12px 26px rgba(27,58,43,.13);border-color:#d7e4da;}
/* The card used to be the <a> itself and carried the focus ring. It is a
   wrapper now, with the link and the heart as siblings inside it, because a
   button nested in an anchor is invalid and behaves differently in every
   browser. The ring follows the link, which is the thing that still takes
   focus; :focus-within keeps the lift so the card still reacts as one piece.
   position:relative is what the heart is positioned against. */
.plant-card{position:relative;}
.plant-card:focus-within{transform:translateY(-3px);box-shadow:0 12px 26px rgba(27,58,43,.13);border-color:#d7e4da;}
.plant-card-link{display:flex;flex-direction:column;text-decoration:none;color:inherit;}
.plant-card-link:focus-visible{outline:3px solid var(--green-500);outline-offset:-3px;border-radius:15px;}
/* A fixed 4:3 frame is what makes the grid read as one set: the source photos
   are a mix of portrait and landscape, and without it every row has a
   different height. */
.plant-card-media{display:block;position:relative;aspect-ratio:4/3;background:var(--green-100);overflow:hidden;}
.plant-card-media img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .35s ease;}
.plant-card:hover .plant-card-media img{transform:scale(1.05);}
.plant-card .pinfo{display:flex;flex-direction:column;gap:3px;padding:13px 15px 15px;}
/* Two lines are reserved whether the name needs them or not, and a longer one
   is clamped to two. Without this a single wrapping name ("Buisson des
   éléphants") made its whole grid row 20px taller than every other row, which
   is what the uneven gaps between rows were. */
.plant-card .pinfo b{
  color:var(--green-900);font-size:0.97rem;font-weight:700;line-height:1.3;
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;
  min-height:2.6em;
}
/* One line, always. On a 320px screen the card is 131px wide and a binomial
   like "Hibiscus rosa-sinensis" wraps, which made that row 17px taller than
   its neighbours. Above 320 these fit on one line, so the ellipsis never
   shows; the full name is on the plant's own page either way. */
.plant-card .pinfo i{
  color:var(--muted);font-size:0.82rem;font-style:italic;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* Below 768 the pair stacks. The row itself does not change shape: it is
   already a row, so only the sizes come down. Stacked cards no longer
   straddle an edge, so the overlap goes back to the small lift it was. */
@media(max-width:767px){
  /* The landing strip, measured from the search field now that the spaces
     row is gone. 56px was chosen to leave 30px of air under that row; with
     nothing between the search and the cards it left a 94px strip of bare
     photograph. 18px restores the same 30px of air. Set here rather than in
     the 640px block so the band between 641 and 767, where the cards have
     already stacked, does not keep the desktop strip with it. */
  .home-hero{padding-bottom:18px;}
  .home-features{grid-template-columns:1fr;margin:-26px auto 0;gap:12px;}
  .home-feature{padding:16px;gap:12px;border-radius:14px;}
  .home-feature-tile{width:40px;height:40px;border-radius:11px;}
  .home-feature-icon{width:25px;height:25px;}
  .home-feature h2{font-size:0.98rem;}
  .home-feature p{font-size:0.82rem;}
}
@media(max-width:640px){
  /* Bottom matches the 767 rule above: the spaces row it was leaving
     room for is gone, and this shorthand would otherwise put the 56px
     back at the width where it shows most. */
  .home-hero{padding:36px 16px 18px;}
  /* The desktop scrim veils only the middle, because there the text sits in a
     760px column inside a much wider frame. On a phone the text runs the full
     width, so the side falloff left it over dark foliage: measured 1.46:1 on
     the subtitle. Here the veil is even across the width and varies only
     vertically, leaving a clear strip of photograph above the headline. */
  .home-hero.has-media::after{
    /* Strong through the band the text actually occupies. The hero centres its
       content in a 560px box, so that band measured at roughly 30% to 75% of
       the height, not the top third as first assumed: a veil sized for the top
       left the subtitle at 2.6:1. A clear strip of photograph is kept above
       the headline. */
    /* Ramp pulled up from 20% to 14%: dropping the "coming soon" line shortened
       the centred block, and with the image filter on, the headline's worst
       pixel fell to 3.29:1 while still sitting in the thin part of the veil.
       A clear strip of photograph is kept above it. */
    background:linear-gradient(180deg,
      rgba(250,248,242,.20) 0%, rgba(250,248,242,.44) 6%,
      rgba(250,248,242,.88) 14%, rgba(250,248,242,.88) 84%,
      rgba(250,248,242,.94) 100%);
  }
  /* Phones get the narrow crop, framed slightly higher so a subject near the
     top of the composition survives the taller viewport. The tall band is
     scoped to .has-media: without artwork it would just be empty gradient. */
  .home-hero.has-media{
    --hero-focus-y:46%;
    /* Was clamp(420px,72vh,560px), which on a 360x800 phone meant a 560px
       floor under 490px of content: 70px of slack, split by the centring into
       35 above and 35 below, and the lower half landed in the gap. German,
       whose hero text is 60px taller, had almost none of it, which is why the
       same page measured 65px of gap in English and 35 in German. The floor
       is now under the content on an ordinary phone, so both languages get
       the same 30px and the gap stops depending on how long the sentence is.
       The cap is 430 rather than 470 because at 390x844 a 470 floor was still
       21px above the English content, and all of that came back as gap.
       object-fit:cover still fills the box; a shorter box simply crops less. */
    min-height:clamp(380px,52vh,430px);
    display:flex;align-items:center;
  }
  .home-hero.has-media .home-hero-inner{width:100%;}
  .home-search{padding:5px 6px 5px 16px;gap:10px;}
  .home-search-input{padding:12px 0;font-size:0.95rem;}
  .home-library{margin-top:32px;padding-bottom:44px;}
  /* Two columns, stated rather than inferred. auto-fill with a 150px minimum
     gave one column at 320px, because the content box there is only 280px. */
  .plant-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;}
  .plant-card .pinfo{padding:11px 12px 13px;}
  /* A phone card is narrow enough that a binomial wraps: at 320px, 21 of the
     38 names on /category/de/flowering/ do. Truncating them all to keep the
     rows even traded away more than it bought, so the second line is reserved
     instead. Cards stay identical and no name is cut. */
  .plant-card .pinfo i{
    white-space:normal;
    display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;
    /* height, not min-height, and a line-height stated here rather than
       inherited: two lines has to be an exact number or the cards land 3px
       apart and the rows go ragged again. */
    line-height:1.35;height:2.7em;
  }
  /* One row that scrolls sideways. The scrollbar is hidden because it sits
     across the chips on the platforms that draw one; assets/category-page.js
     scrolls the current chip into view so the row still says where you are. */
  .category-chips{
    flex-wrap:nowrap;overflow-x:auto;margin-bottom:20px;
    scrollbar-width:none;-ms-overflow-style:none;
    -webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;
  }
  .category-chips::-webkit-scrollbar{display:none;}
  .category-chip{flex:none;min-height:44px;}
}
@media(prefers-reduced-motion:reduce){
  .home-feature,.plant-card,.plant-card-media img,.category-chip,.home-feature-go{transition:none;}
  .home-feature:hover,.plant-card:hover,.plant-card:focus-within{transform:none;}
  /* The chevron keeps its rotation; only the nudge goes. */
  .home-feature:hover .home-feature-go{transform:rotate(-90deg);}
  .plant-card:hover .plant-card-media img{transform:none;}
}

/* The placement caret animates, so it honours reduced motion. It sits apart
   from the placement block below because it used to be grouped with other
   animated controls that have since gone; keep the two together if you move it. */
@media(prefers-reduced-motion:reduce){
  .placement-caret{transition:none;}
}

/* --- Plant page placement guidance ------------------------------------- */
.placement{background:var(--green-100);border-radius:12px;padding:16px 18px;margin:20px 0 0;}
.placement h3{margin:0 0 10px;font-size:0.85rem;font-weight:700;letter-spacing:0.04em;
  text-transform:uppercase;color:var(--green-700);}
.placement-list{list-style:none;margin:0;padding:0;display:grid;gap:8px;}
.placement-list li{display:flex;flex-wrap:wrap;gap:4px 10px;align-items:baseline;}
.placement-list b{color:var(--green-900);font-size:1.02rem;}
.placement-list span{color:var(--green-700);font-size:0.95rem;}
.placement-warn{margin:12px 0 0;font-size:0.9rem;color:var(--warn-ink);}
.placement-details{margin-top:12px;}
.placement-details summary{cursor:pointer;font-size:0.9rem;font-weight:600;color:var(--green-700);
  padding:6px 0;min-height:36px;display:flex;align-items:center;gap:8px;list-style:none;}
.placement-details summary::-webkit-details-marker{display:none;}
.placement-caret{width:0;height:0;border-left:5px solid currentColor;
  border-top:4px solid transparent;border-bottom:4px solid transparent;
  transition:transform .15s;flex:none;}
.placement-details[open] .placement-caret{transform:rotate(90deg);}
.placement-details summary:hover{text-decoration:underline;}
.placement-summary-open{display:none;}
.placement-details[open] .placement-summary-open{display:inline;}
.placement-details[open] .placement-summary-closed{display:none;}
.placement-details summary:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;border-radius:6px;}
.placement-table-wrap{overflow-x:auto;}
.placement-table{border-collapse:collapse;margin:8px 0 0;font-size:0.82rem;width:100%;}
.placement-table th{font-weight:600;color:var(--green-700);text-align:left;padding:6px 8px;white-space:nowrap;}
.placement-table thead th{font-size:0.75rem;}
.placement-table td{padding:6px 8px;text-align:center;}
.pg-mark{display:inline-block;font-size:1.05rem;line-height:1;font-weight:700;}
/* Darkened from the first pass: on the pale green panel the amber and grey sat
   under the 3:1 contrast minimum for a non-text indicator. */
.pg-ok .pg-mark{color:var(--green-700);}
.pg-mid .pg-mark{color:#96690a;}
.pg-dark .pg-mark{color:#5f6b7a;}
.pg-sun .pg-mark{color:#b35f14;}
.placement-legend{margin:10px 0 0;font-size:0.8rem;color:var(--muted);display:flex;flex-wrap:wrap;gap:6px 14px;align-items:center;}
.pg-item{display:inline-flex;align-items:center;gap:5px;}
.placement-approx{margin:12px 0 0;font-size:0.8rem;color:var(--muted);line-height:1.5;}
.photo-soon{background:var(--green-100);border-radius:10px;padding:18px;text-align:center;}
.photo-soon b{display:block;color:var(--green-900);margin-bottom:6px;}
.photo-soon p{margin:0;font-size:0.9rem;color:var(--green-700);line-height:1.6;}

/* --- Plant page pet safety ---------------------------------------------- */
.petsafety{border-radius:12px;padding:14px 16px;margin:12px 0 0;border-left:4px solid;}
.petsafety h3{margin:0 0 6px;font-size:0.85rem;font-weight:700;letter-spacing:0.04em;
  text-transform:uppercase;display:flex;align-items:center;gap:8px;}
.petsafety p{margin:0 0 6px;font-size:0.95rem;line-height:1.55;}
.petsafety p:last-child{margin-bottom:0;}
.pet-icon{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;
  border-radius:50%;font-size:0.75rem;font-weight:700;color:#fff;flex:none;}
.pet-verdict{font-weight:600;}
.petsafety-toxic{background:#fff5f0;border-color:#c2410c;}
.petsafety-toxic h3{color:#9a3412;}
.petsafety-toxic .pet-icon{background:#c2410c;}
.petsafety-safe{background:var(--green-100);border-color:var(--green-500);}
.petsafety-safe h3{color:var(--green-700);}
.petsafety-safe .pet-icon{background:var(--green-500);}
.petsafety-unknown{background:#f4f5f3;border-color:#8a93a0;}
.petsafety-unknown h3{color:#4a5560;}
.petsafety-unknown .pet-icon{background:#6b7480;}
.pet-vet,.pet-source{font-size:0.82rem;color:var(--muted);}
/* The EU invasive-species notice: the pet safety box, near the top of the page. */
.eu-invasive{margin:14px 0 16px;}
.eu-invasive h2{margin:0 0 6px;font-size:0.85rem;font-weight:700;letter-spacing:0.04em;
  text-transform:uppercase;display:flex;align-items:center;gap:8px;color:#9a3412;}
.eu-invasive .pet-source a{color:inherit;text-decoration:underline;}

/* --- Marketplace ---------------------------------------------------------
   Same vocabulary as the homepage: white cards on cream, 1px #e7ece8 borders,
   18px radii, green-100 icon tiles, 999px pills. No emoji anywhere: every
   glyph on this page comes from the shared stroke icon set. ------------- */

/* Buttons ------------------------------------------------------------------ */
/* 46px min height across the set, so every control clears a finger. */
.mk-btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  min-height:46px;padding:11px 22px;border-radius:999px;border:1px solid transparent;
  font-family:inherit;font-size:0.97rem;font-weight:700;line-height:1.2;
  cursor:pointer;transition:.16s;text-align:center;
}
.mk-btn-icon{width:19px;height:19px;flex:none;}
.mk-btn-primary{background:var(--green-500);color:#fff;}
.mk-btn-primary:hover{background:var(--green-700);}
.mk-btn-ghost{background:#fff;color:var(--green-700);border-color:#d7e4da;}
.mk-btn-ghost:hover{background:var(--green-100);border-color:var(--green-300);}
.mk-btn-soft{background:var(--green-100);color:var(--green-700);}
.mk-btn-soft:hover{background:var(--green-300);color:var(--green-900);}
.mk-btn:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
/* display:inline-flex above outranks the UA's [hidden]{display:none}, so the
   sign-in link and the reveal button would both show at once without this. */
.mk-btn[hidden]{display:none;}

/* Hero --------------------------------------------------------------------- */
.mk-hero{
  background:linear-gradient(180deg,var(--green-100) 0%,rgba(238,247,239,.35) 62%,var(--cream) 100%);
  padding:56px 0 44px;text-align:center;
}
.mk-hero .container{max-width:820px;}
.mk-hero-title{
  margin:0 0 14px;color:var(--green-900);font-size:clamp(1.85rem,4.2vw,2.75rem);
  line-height:1.12;letter-spacing:-0.02em;font-weight:800;
}
.mk-hero-sub{margin:0 auto 28px;max-width:56ch;color:#4d5f55;font-size:clamp(1rem,1.6vw,1.1rem);line-height:1.6;}

/* The search is the page's main action, so it gets the one white panel in
   the band rather than sitting inline with the secondary buttons. */
.mk-search{
  display:flex;flex-wrap:wrap;align-items:flex-end;gap:14px;text-align:left;
  background:#fff;border:1px solid #e3eae5;border-radius:18px;padding:16px;
  box-shadow:0 10px 30px rgba(27,58,43,.10);
}
.mk-search:focus-within{border-color:var(--green-500);}
/* position:relative so the place suggestions anchor to the field, the same
   way .sit-search-field does on the Plant Sitters board. Without it the list
   is absolute against whatever is positioned further up and lands away from
   the box entirely, which is what it did on the publish form.
   Set on both copies of this rule: .mk-search and .mk-search-field are each
   declared twice in this file, which is not mine to untangle here, and the
   suggestions must not depend on which copy wins. */
.mk-search-field{display:flex;flex-direction:column;gap:5px;min-width:0;position:relative;}
.mk-search-grow{flex:1 1 180px;}
.mk-search-field label{font-size:0.8rem;font-weight:700;color:var(--green-700);}
/* The controls themselves, and their focus outline, were declared here and
   again 300 lines down. Both are gone: the panel is the box, and what the
   field inside it looks like is settled once, at the end of this file. */
.mk-search-submit{flex:0 0 auto;}

.mk-hero-actions{display:flex;flex-wrap:wrap;justify-content:center;gap:12px;margin-top:20px;}
.mk-error{color:#a8452a;margin:12px 0 0;font-size:0.92rem;font-weight:600;}
.mk-error[hidden]{display:none;}
.mk-hint{
  margin:0 0 16px;padding:12px 16px;border-radius:12px;
  background:var(--green-100);color:var(--green-900);font-size:0.92rem;
}
.mk-hint[hidden]{display:none;}

/* Listings ----------------------------------------------------------------- */
/* The shorthand here zeroes .container's side gutter, which on wide screens
   pushed these sections 20px outside every other block on the page. The
   gutter is restored for desktop only: on phones this section has always run
   edge to edge, and that is left exactly as it was. */
.mk-section{padding:44px 0 0;}
@media(min-width:900px){.mk-section{padding-left:20px;padding-right:20px;}}
.mk-h2{margin:0;color:var(--green-900);font-size:clamp(1.35rem,2.4vw,1.75rem);letter-spacing:-0.01em;}
.mk-h2-center{text-align:center;margin-bottom:26px;}
.mk-listings-head{display:flex;align-items:flex-end;justify-content:space-between;gap:18px;flex-wrap:wrap;margin-bottom:20px;}
.mk-count{margin:6px 0 0;font-size:0.9rem;color:var(--muted);}
.mk-count[hidden]{display:none;}
.mk-filter{display:flex;align-items:center;gap:9px;font-size:0.9rem;font-weight:700;color:var(--green-700);}
.mk-filter select{
  min-height:44px;padding:10px 12px;border:1px solid var(--green-300);border-radius:10px;
  font-family:inherit;font-size:0.95rem;background:#fff;color:var(--text);
}
.mk-map{height:380px;border-radius:18px;margin:0 0 24px;box-shadow:var(--shadow);}
.mk-map[hidden]{display:none;}
.mk-empty{
  /* 10 rather than 18: with one sentence here the gap only ever separated
     the line from the button. Now there are two lines, and a title sitting
     18px off its own text reads as two unrelated statements. The button
     takes the wider gap back for itself below. */
  display:flex;flex-direction:column;align-items:center;gap:10px;
  margin:0;padding:44px 24px;text-align:center;color:var(--muted);
  background:#fff;border:1px dashed #d7e4da;border-radius:18px;
}
.mk-empty .mk-post-cta-btn{margin-top:10px;}
.mk-empty p{margin:0;}
.mk-empty[hidden]{display:none;}
/* The same two weights the Plant Sitting board's empty state uses, so the two
   pages say "there is nothing here yet" in the same voice. The flex column
   above already spaces them, so neither carries a margin; max-width keeps the
   German text, which is the longest by half a line, off a single wide line. */
.mk-empty-title{font-size:1.12rem;font-weight:700;color:var(--green-900);max-width:34ch;}
.mk-empty-text{max-width:46ch;line-height:1.5;}

/* Listing-type chips. Hidden until the listing_type column exists, so the page
   never offers a filter that cannot mean anything. */
.mk-chips{display:flex;flex-wrap:wrap;gap:9px;margin:0 0 20px;}
.mk-chips[hidden]{display:none;}
.mk-chip{
  min-height:44px;padding:10px 18px;border-radius:999px;
  border:1px solid #d7e4da;background:#fff;color:var(--green-700);
  font-family:inherit;font-size:0.92rem;font-weight:700;cursor:pointer;transition:.15s;
}
.mk-chip:hover{background:var(--green-100);border-color:var(--green-300);}
.mk-chip.is-active{background:var(--green-700);border-color:var(--green-700);color:#fff;}
.mk-chip:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}

/* Low inventory: a prompt in the spare grid cell, deliberately not shaped like
   a listing card. An area with nothing in it should look like one. */
.mk-prompt{
  display:flex;flex-direction:column;align-items:flex-start;gap:9px;align-self:start;
  background:var(--green-100);border:1px dashed var(--green-300);border-radius:18px;padding:24px;
}
.mk-prompt-icon{
  display:flex;align-items:center;justify-content:center;width:44px;height:44px;
  border-radius:14px;background:#fff;color:var(--green-700);
}
.mk-prompt-icon svg{width:22px;height:22px;}
.mk-prompt h3{margin:4px 0 0;font-size:1.02rem;color:var(--green-900);line-height:1.35;}
.mk-prompt p{margin:0;font-size:0.9rem;line-height:1.5;color:var(--green-700);}

/* auto-fill, not auto-fit: one listing should keep a card's width rather than
   stretching across the whole row. */
.mk-grid{
  display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,300px),1fr));
  gap:24px;padding-bottom:4px;
}
.mk-card{
  display:flex;flex-direction:column;background:#fff;border:1px solid #e7ece8;
  border-radius:18px;overflow:hidden;box-shadow:0 2px 10px rgba(27,58,43,.06);transition:.18s;
}
.mk-card:hover{transform:translateY(-3px);box-shadow:0 12px 28px rgba(27,58,43,.12);border-color:#d7e4da;}
.mk-card-media{position:relative;aspect-ratio:4/3;background:var(--green-100);}
.mk-card-media img{width:100%;height:100%;object-fit:cover;display:block;}
/* Branded plant mark rather than a photo. Faint on purpose: it marks a gap in
   the listing, it does not compete with the cards that do have a photograph. */
.mk-card-noimg{
  display:flex;align-items:center;justify-content:center;width:100%;height:100%;
  color:var(--green-300);
  background:radial-gradient(circle at 50% 46%, #fff 0%, rgba(255,255,255,0) 62%);
}
.mk-card-placeholder{width:84px;height:84px;}

.mk-card-type{
  position:absolute;top:12px;left:12px;display:inline-flex;align-items:center;gap:6px;
  background:rgba(255,255,255,.95);color:var(--green-900);border-radius:999px;
  padding:6px 13px;font-size:0.8rem;font-weight:700;box-shadow:0 2px 8px rgba(27,58,43,.16);
}
.mk-type-gift{background:var(--green-500);color:#fff;}
.mk-type-swap{background:var(--earth);color:#fff;}
.mk-chip-icon{width:15px;height:15px;flex:none;}

.mk-card-body{display:flex;flex-direction:column;gap:9px;padding:18px;flex:1;}
.mk-card-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;}
.mk-card-title{margin:0;color:var(--green-900);font-size:1.08rem;line-height:1.3;}
.mk-price{
  flex:none;background:var(--green-100);color:var(--green-900);border-radius:999px;
  padding:6px 13px;font-size:0.9rem;font-weight:800;white-space:nowrap;
}
.mk-price-free{background:var(--green-500);color:#fff;}
.mk-card-loc{display:flex;align-items:center;gap:6px;margin:0;font-size:0.87rem;color:var(--muted);}
.mk-card-dist{color:var(--green-700);font-weight:700;}
.mk-card-desc{
  margin:0;font-size:0.92rem;line-height:1.55;color:#5c6b62;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
}
.mk-card-foot{
  display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;
  margin-top:auto;padding-top:12px;border-top:1px solid #f0f4f1;
}
.mk-card-poster{font-size:0.83rem;color:var(--muted);}
.mk-card-foot .mk-btn{min-height:44px;padding:9px 18px;font-size:0.9rem;}
.mk-msgbox{flex:1 0 100%;display:flex;flex-direction:column;gap:10px;}
.mk-msgbox[hidden]{display:none;}
.mk-msgbox textarea{
  padding:11px 13px;border:1px solid var(--green-300);border-radius:10px;
  font-family:inherit;font-size:0.95rem;resize:vertical;
}
/* Plant Sitters' `.message-box button` rule also matches the send button here,
   and outranks .mk-btn. This wins the pill shape back. */
.mk-msgbox .mk-btn{border-radius:999px;padding:11px 22px;align-self:flex-start;}

/* How it works ------------------------------------------------------------- */
.mk-steps{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;list-style:none;margin:0;padding:0;}
.mk-step{
  display:flex;flex-direction:column;align-items:center;text-align:center;gap:10px;
  background:#fff;border:1px solid #e7ece8;border-radius:18px;padding:28px 24px;
  box-shadow:0 2px 10px rgba(27,58,43,.06);
}
.mk-step-icon{
  position:relative;display:flex;align-items:center;justify-content:center;
  width:56px;height:56px;border-radius:16px;background:var(--green-100);color:var(--green-700);
}
.mk-step-icon svg{width:28px;height:28px;}
.mk-step-num{
  position:absolute;top:-7px;right:-7px;display:flex;align-items:center;justify-content:center;
  width:24px;height:24px;border-radius:50%;background:var(--green-700);color:#fff;
  font-size:0.78rem;font-weight:800;
}
.mk-step h3{margin:0;font-size:1.08rem;color:var(--green-900);}
.mk-step p{margin:0;font-size:0.92rem;line-height:1.55;color:#5c6b62;max-width:32ch;}

/* Publish a listing -------------------------------------------------------- */
/* Publishing is one of the two things people come here to do, so its button
   sits in the hero with the search. The form itself stays collapsed, and its
   wrapper collapses with it, so browsing is never pushed down the page. */
/* Spacing lives on the panel, not the wrapper, so a closed form leaves no gap
   without needing :has(). */
.mk-post-panel{
  margin-top:24px;background:var(--green-100);border:1px solid #d7e4da;
  border-radius:20px;padding:28px;
}
.mk-post-panel[hidden]{display:none;}
.mk-post-title{margin:0 0 5px;color:var(--green-900);font-size:1.3rem;}
.mk-post-note{margin:0;color:var(--green-700);font-size:0.95rem;line-height:1.5;}
/* The "no database configured" notice replaces this container's contents. */
.mk-post-wrap > p{margin:24px 0 0;padding:16px 20px;border-radius:14px;background:#fff5f0;color:#a8452a;}

.mk-form{
  display:grid;grid-template-columns:repeat(2,1fr);gap:16px;
  margin-top:24px;padding-top:24px;border-top:1px solid #d7e4da;
}
.mk-form[hidden]{display:none;}
.mk-field{display:flex;flex-direction:column;gap:5px;min-width:0;}
.mk-field[hidden]{display:none;}
.mk-field-wide{grid-column:1/-1;}
.mk-field label{font-size:0.82rem;font-weight:700;color:var(--green-700);}
.mk-field input,.mk-field textarea,.mk-field select{
  width:100%;min-height:46px;padding:11px 13px;border:1px solid var(--green-300);
  border-radius:10px;font-family:inherit;font-size:1rem;color:var(--text);background:#fff;
}
.mk-field textarea{min-height:96px;resize:vertical;}
.mk-field input[type="file"]{padding:9px 12px;}
.mk-field .autocomplete-field{width:100%;}

/* Safety ------------------------------------------------------------------- */
.mk-safety{
  display:flex;align-items:flex-start;gap:18px;
  background:#fff5f0;border:1px solid #f0c4b0;border-radius:18px;padding:22px 24px;
}
.mk-safety-icon{
  display:flex;align-items:center;justify-content:center;width:46px;height:46px;flex:none;
  border-radius:14px;background:#fff;color:#a8452a;
}
.mk-safety-icon svg{width:24px;height:24px;}
.mk-safety h2{margin:0 0 5px;color:#8f3822;font-size:1.08rem;}
.mk-safety p{margin:0;color:#8f3822;font-size:0.93rem;line-height:1.55;}

/* FAQ ---------------------------------------------------------------------- */
/* Accordions, so four answers no longer outweigh the listings above them. The
   text stays in the markup, which is what the FAQ structured data needs. */
.mk-faq-section{padding-bottom:64px;}
.mk-faq{display:flex;flex-direction:column;gap:12px;}
.mk-faq-item{background:#fff;border:1px solid #e7ece8;border-radius:16px;overflow:hidden;}
.mk-faq-item[open]{border-color:#d7e4da;box-shadow:0 2px 10px rgba(27,58,43,.06);}
.mk-faq-q{
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  min-height:44px;padding:16px 20px;cursor:pointer;list-style:none;
}
.mk-faq-q::-webkit-details-marker{display:none;}
.mk-faq-q:hover{background:var(--green-100);}
.mk-faq-q:focus-visible{outline:3px solid var(--green-500);outline-offset:-3px;}
.mk-faq-q h3{margin:0;font-size:1.02rem;font-weight:700;color:var(--green-900);line-height:1.4;}
.mk-faq-chevron{width:20px;height:20px;flex:none;color:var(--green-700);transition:transform .18s;}
.mk-faq-item[open] .mk-faq-chevron{transform:rotate(180deg);}
.mk-faq-a{padding:0 20px 18px;}
.mk-faq-a p{margin:0;color:var(--text);font-size:0.97rem;line-height:1.65;}

/* Narrower screens --------------------------------------------------------- */
/* The steps switch to icon-beside-text, the same grid the homepage feature
   cards use at this width. */
@media (max-width:860px){
  .mk-steps{grid-template-columns:1fr;}
  .mk-step{
    display:grid;grid-template-columns:auto 1fr;grid-template-areas:"icon title" "icon text";
    column-gap:16px;row-gap:5px;align-items:start;text-align:left;padding:20px;
  }
  .mk-step-icon{grid-area:icon;width:48px;height:48px;}
  .mk-step-icon svg{width:24px;height:24px;}
  .mk-step h3{grid-area:title;}
  .mk-step p{grid-area:text;max-width:none;}
}
@media (max-width:640px){
  .mk-hero{padding:38px 0 32px;}
  .mk-search{padding:14px;gap:12px;}
  .mk-search-field{flex:1 1 100%;}
  .mk-search-submit{width:100%;}
  /* The label alone fills a full-width button in the longer languages, and the
     icon then hangs off to the left of two centred lines. */
  .mk-search-submit .mk-btn-icon{display:none;}
  .mk-hero-actions .mk-btn{flex:1 1 100%;}
  .mk-section{padding-top:34px;}
  .mk-listings-head{align-items:flex-start;}
  .mk-map{height:300px;}
  .mk-post{padding:22px 18px;}
  .mk-post-actions,.mk-post-actions .mk-btn{width:100%;}
  .mk-form{grid-template-columns:1fr;}
  .mk-card-foot .mk-btn{width:100%;}
}

/* --- Marketplace, visual pass -------------------------------------------
   Hero with artwork behind it, a trust strip, and the listings sitting beside
   the map rather than above it. ---------------------------------------- */

/* Hero --------------------------------------------------------------------- */
/* 40px under the header, and the height is whatever the content needs. It used
   to be a flex box with a min-height and align-items:center, which made the
   hero a fixed room the text was centred inside: a one-line Spanish headline
   started 21px lower than a three-line German one, the card beside it moved
   with the text, and everything below inherited the difference - 113px between
   the Spanish and German "Plants near you". A heading that starts in a
   different place in every language is not a design, it is an accident of how
   long the sentence is. */
.mk-hero{position:relative;isolation:isolate;overflow:hidden;padding:40px 0 44px;text-align:left;}
/* The same floor the homepage hero carries, and for the same reason its own
   comment gives: without a minimum the hero is only as tall as its text, and
   object-fit:cover then crops a 16:9 photograph to a thin mid-band. This one
   was the worst case on the site - 342px against 1265 wide showed 48% of the
   frame's height, the pale middle, where the homepage shows 58% and Plant
   Sitting 73%. The veil was only the second reason this hero looked washed.
   Nothing moves: .container is a block, so the headline, the search panel and
   the post card stay exactly where they were and the extra height falls below
   them, as photograph. The phone keeps min-height:0 further down, where the
   cards already fill the hero and a floor would only add empty space. */
/* 33vw, not the homepage's 26: that one is a floor under a hero whose own
   content already makes it 414px, so copying the number changed nothing here
   (26vw is 333px at 1280, under the 342 this hero already was). The fraction
   of the frame on screen is height / (720/1280 * width), so holding it at the
   homepage's 58% means tying the height to 0.58 * 0.5625 = 32.6% of the
   width. 33vw gives 422px at 1280, which measures 59%. The vh term and the
   cap are the homepage's, for the same reasons its comment gives. */
.mk-hero.has-media{min-height:clamp(340px, min(33vw, 48vh), 440px);}
/* Was pinned to 1180 to out-widen the old 1100px container; now it just
   narrowed the hero by 30px against everything else on the page. */
.mk-hero .container{max-width:var(--page-max);width:100%;}
/* No override here any more. This hero used to pin the crop at 50% 58% and
   take the picture unfiltered, which is two of the three ways it differed
   from the homepage; it now takes the shared 50% 52% and the shared
   saturate/contrast from .hero-media. */
/* The full-width veil is gone. A 90deg wash from .80 at the left was the
   third and largest way this hero differed from the homepage: it covered the
   photograph everywhere, not only where words sit, so the picture was pale
   across its whole left half whatever was written on it.
   What is left is the homepage's vertical gradient, copied stop for stop. It
   is not readability, it is the landing: without it the photograph meets the
   cream page below on a hard edge. The homepage's other two layers do not
   come across - its centre band protects centred text, which this hero does
   not have, and its radial halo belongs to the space labels, which this hero
   does not carry. The headline and subtitle get .mk-hero-copy instead, a soft
   backing the size of the words. */
.mk-hero.has-media::after{
  content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    linear-gradient(180deg,
      rgba(250,248,242,.16) 0%, rgba(250,248,242,.04) 40%,
      rgba(250,248,242,.22) 72%, rgba(250,248,242,.62) 88%,
      rgba(250,248,242,.95) 99%, rgba(250,248,242,1) 100%);
}
/* The readability backing, the size of the words instead of the size of the
   hero. A blurred ellipse behind the headline and subtitle, strongest where
   the first line starts and gone well before the edge of the column, so the
   photograph beside and below the text is untouched and in full colour.
   z-index:-1 puts it behind the two blocks but still inside .mk-hero-inner,
   which is a stacking context at z-index 2, so it stays above the picture.
   blur() costs nothing in layout: the element is absolutely positioned, and
   what the blur spills is clipped by the hero's own overflow:hidden.
   The inset is asymmetric on purpose. It reaches further left and up than
   right and down because the text is left-aligned and ragged-right: the last
   line of a subtitle can end halfway across, and a backing that squared off
   around the whole column would be the full-width veil again, smaller. */
.mk-hero-copy{position:relative;}
.mk-hero-copy::before{
  content:'';position:absolute;z-index:-1;pointer-events:none;
  inset:-30px -56px -24px -40px;
  background:radial-gradient(118% 128% at 26% 46%,
    rgba(250,248,242,.95) 0%, rgba(250,248,242,.92) 38%,
    rgba(250,248,242,.74) 62%, rgba(250,248,242,.34) 82%,
    rgba(250,248,242,0) 100%);
  filter:blur(14px);
}
.mk-hero:not(.has-media){
  background:linear-gradient(180deg,var(--green-100) 0%,rgba(238,247,239,.35) 62%,var(--cream) 100%);
}
/* Without artwork there is nothing to be readable against. */
.mk-hero:not(.has-media) .mk-hero-copy::before{display:none;}
.mk-hero-inner{
  position:relative;z-index:2;
  display:grid;grid-template-columns:minmax(0,1.35fr) minmax(280px,.65fr);
  /* start, not center: the card is pinned to the top of its row, so its top
     edge is the title's top edge in every language. Centred, it floated
     against whatever height the text happened to have and sat 57px lower in
     German than in English. */
  gap:30px;align-items:start;
}
.mk-hero-title{
  margin:0 0 20px;color:var(--green-900);font-size:clamp(1.9rem,3.5vw,2.75rem);
  /* The whole column, which is the grid's 1.35fr share. The 30px grid gap is
     the clearance to the card and no width set here can eat into it, so the
     headline can fill the space it has been given.

     pretty, not balance. balance evens the lines out by making them all as
     short as the last one needs, which on a long sentence meant three narrow
     lines in a column wide enough for two. pretty only looks after the last
     line, so the first lines fill. */
  line-height:1.08;letter-spacing:-0.02em;font-weight:800;
  max-width:100%;text-wrap:pretty;
}
/* Set by the build when the title runs past 55 characters, which today is
   French, Dutch and German. 0.85 of the large size, so a sentence listing four
   verbs sets on two lines in the same column where the English one does,
   instead of three. English and Spanish keep the full size. */
.mk-hero-title.is-long{font-size:clamp(1.7rem,3vw,2.35rem);}
.mk-hero-sub{
  /* 660px rather than 46ch, for the same reason the title no longer uses ch:
     a measure in ch shrinks with the type. pretty keeps a single word off the
     last line, which is what "cerca de ti." alone under the Spanish subtitle
     was. */
  margin:0 0 38px;max-width:660px;text-wrap:pretty;
  color:#42544a;font-size:clamp(0.98rem,1.4vw,1.06rem);line-height:1.55;
}

/* Search panel, now with the pin that anchors it as a location control. */
.mk-search{
  display:flex;flex-wrap:wrap;align-items:flex-end;gap:14px;
  background:#fff;border:1px solid #e3eae5;border-radius:18px;padding:14px 16px;
  box-shadow:0 14px 36px rgba(27,58,43,.13);
}
.mk-search:focus-within{border-color:var(--green-500);}
.mk-search-pin{
  display:flex;align-items:center;justify-content:center;width:38px;height:38px;flex:none;
  border-radius:12px;background:var(--green-100);color:var(--green-700);margin-bottom:3px;
}
.mk-search-pin svg{width:20px;height:20px;}
/* position:relative so the place suggestions anchor to the field, the same
   way .sit-search-field does on the Plant Sitters board. Without it the list
   is absolute against whatever is positioned further up and lands away from
   the box entirely, which is what it did on the publish form.
   Set on both copies of this rule: .mk-search and .mk-search-field are each
   declared twice in this file, which is not mine to untangle here, and the
   suggestions must not depend on which copy wins. */
.mk-search-field{display:flex;flex-direction:column;gap:5px;min-width:0;position:relative;}
/* The country has to stay wide enough to read the country in: as a plain
   flex item with min-width:0 it was the first thing squeezed when the German
   button asked for 323px, and it ended up 46px wide - a chevron with the name
   clipped away entirely. It keeps its own width and the postcode, which only
   ever holds five or six characters, gives up the room instead. */
/* A fixed basis, and the select told to fill it. Left alone a <select> is as
   wide as its longest option, so the German one asked for 221px because
   "Vereinigtes Königreich" is in the list - width the row did not have, and
   width that says nothing, since only the chosen country is ever on screen.
   150px shows every one of the six whole. */
.mk-search-field-country{flex:0 0 150px;min-width:0;}
.mk-search-field-country select{width:100%;}
.mk-search-grow{flex:1 1 120px;min-width:110px;}
.mk-search-field label{font-size:0.78rem;font-weight:700;color:var(--muted);}
/* The control's own box lived here. See the shared search block at the end of
   the file: a bordered select and a bordered input inside a bordered panel
   were three boxes where the page needs one. */
/* The submit is the longest label in German ("Pflanzen in meiner Nähe
   anzeigen"), so it is what pushes the row onto two lines. Tightening its own
   padding rather than any of the labels keeps the row together to 1100px and
   below without a word being changed. */
.mk-search-submit{flex:0 1 auto;min-width:0;}
.mk-search-submit span{overflow:hidden;text-overflow:ellipsis;}
/* Between 1000 and 1300 the left column is around 700px and the German submit
   alone takes 315px of it, which put the row on two lines all the way up to
   1240. The row is tightened rather than any label shortened: 10px between the
   fields instead of 14, and 18px of button padding instead of 22. That is 20px
   back, and with the country select no longer sizing itself to its longest
   option the row holds together from 1100 up. Below that it wraps, which is
   where it was asked to. */
@media (min-width:1001px) and (max-width:1300px){
  .mk-search{gap:10px;padding:14px;}
  .mk-search-submit{padding-left:18px;padding-right:18px;}
}
.mk-search-field select:focus,.mk-search-field input:focus{outline:2px solid var(--green-500);outline-offset:-1px;}
.mk-search-submit{flex:0 0 auto;}

/* Publishing card: its own surface, so it reads as the second thing to do
   here rather than as one more button under the search. */
.mk-hero-post{
  background:rgba(238,247,239,.96);border:1px solid #cfe0d5;border-radius:20px;
  padding:22px;box-shadow:0 14px 36px rgba(27,58,43,.13);backdrop-filter:blur(3px);
}
.mk-hero-post-icon{
  display:flex;align-items:center;justify-content:center;width:44px;height:44px;
  border-radius:13px;background:#fff;color:var(--green-700);margin-bottom:11px;
}
.mk-hero-post-icon svg{width:24px;height:24px;}
.mk-hero-post h2{margin:0 0 6px;color:var(--green-900);font-size:1.12rem;line-height:1.28;}
.mk-hero-post p{margin:0 0 15px;color:#42544a;font-size:0.92rem;line-height:1.5;}
.mk-hero-post .mk-btn{width:100%;}

/* Trust strip -------------------------------------------------------------- */
.mk-trust{background:#fff;border-bottom:1px solid #eef2ef;}
.mk-trust-inner{
  display:grid;grid-template-columns:repeat(4,1fr);gap:22px;
  padding-top:15px;padding-bottom:15px;
}
.mk-trust-item{display:flex;align-items:center;gap:13px;}
.mk-trust-icon{
  display:flex;align-items:center;justify-content:center;width:42px;height:42px;flex:none;
  border-radius:13px;background:var(--green-100);color:var(--green-700);
}
.mk-trust-icon svg{width:21px;height:21px;}
.mk-trust-item b{display:block;color:var(--green-900);font-size:0.95rem;line-height:1.3;}
/* "div span" and not "span": the icon tile is a span too, and a direct child
   of the item, so the bare selector reached it and outranked .mk-trust-icon
   (0-1-1 against 0-1-0). It took four declarations off the tile - display
   went from flex to block, which stopped align-items/justify-content from
   doing anything and left the 21px icon in the top-left corner of its own
   42px box; the colour went from green to the caption grey, since the SVGs
   stroke with currentColor; and margin-top:2px pushed the whole tile a
   pixel below the centre of the text, which is what was visible. */
.mk-trust-item div span{display:block;color:var(--muted);font-size:0.85rem;line-height:1.4;margin-top:2px;}

/* Marketplace: filters above, listings left, map right --------------------- */
.mk-market{padding-top:48px;}
.mk-listings-head{align-items:flex-end;margin-bottom:18px;}
.mk-h2{font-size:clamp(1.45rem,2.6vw,1.9rem);}
.mk-controls{display:flex;flex-wrap:wrap;align-items:center;gap:12px;}
.mk-filter{
  display:flex;align-items:center;gap:8px;padding:5px 14px 5px 12px;
  background:#fff;border:1px solid #e3eae5;border-radius:999px;
  font-size:0.87rem;font-weight:700;color:var(--muted);
}
.mk-filter[hidden]{display:none;}
.mk-filter-icon{width:17px;height:17px;flex:none;color:var(--green-700);}
.mk-filter select{
  min-height:44px;padding:9px 4px;border:none;background:none;
  font-family:inherit;font-size:0.92rem;font-weight:700;color:var(--green-900);cursor:pointer;
}
.mk-filter select:focus-visible{outline:2px solid var(--green-500);border-radius:6px;}

.mk-chip{display:inline-flex;align-items:center;gap:6px;}
.mk-chip-count{font-weight:700;opacity:.62;}

/* Two columns from 1000px up: the map is a peer of the listings, not a block
   parked above them. It sticks while the listings scroll past it. */
/* Below 1000px the map keeps working, it just moves under the listings in
   normal document order instead of sitting beside them. */
.mk-market-split{display:grid;grid-template-columns:minmax(0,1fr);gap:24px;}
@media (min-width:1000px){
  /* 1.35fr leaves the listings two comfortable columns while giving the map a
     landscape frame rather than a sliver. */
  .mk-market-split{grid-template-columns:minmax(0,1.35fr) minmax(360px,1fr);align-items:start;}
  /* Clears the sticky header rather than sliding under it. */
  .mk-market-map{position:sticky;top:calc(var(--header-h) + 20px);}
  .mk-grid{grid-template-columns:repeat(auto-fill,minmax(min(100%,268px),1fr));}
}
/* Landscape rather than a tall sidebar, and near enough the height of one card
   row that it reads as part of the marketplace instead of a panel bolted on. */
.mk-map{
  height:clamp(340px,33vw,470px);margin:0;border-radius:20px;overflow:hidden;
  border:1px solid #e7ece8;box-shadow:0 6px 18px rgba(27,58,43,.10);
}
/* Leaflet paints its own panes; round them with the container. */
.mk-map .leaflet-container{border-radius:20px;}
/* Controls in the site's own vocabulary: white, rounded, soft shadow, and
   large enough to hit without becoming the loudest thing on the map. */
.mk-map .leaflet-control-zoom{border:none;border-radius:12px;overflow:hidden;box-shadow:0 2px 10px rgba(27,58,43,.18);}
/* Leaflet's own sheet loads after this one and its `.leaflet-touch .leaflet-bar a`
   rule ties on specificity, so these carry the control class to outrank it. */
.mk-map .leaflet-bar a.leaflet-control-zoom-in,
.mk-map .leaflet-bar a.leaflet-control-zoom-out{
  width:38px;height:38px;line-height:38px;border:none;
  background:#fff;color:var(--green-900);font-size:1.15rem;font-weight:700;
}
.mk-map .leaflet-bar a.leaflet-control-zoom-in:hover,
.mk-map .leaflet-bar a.leaflet-control-zoom-out:hover{background:var(--green-100);color:var(--green-700);}
.mk-map .leaflet-bar a.leaflet-control-zoom-in{border-bottom:1px solid #eef2ef;}
.mk-map .leaflet-control-attribution{
  background:rgba(255,255,255,.84);font-size:0.67rem;padding:2px 8px;border-radius:8px 0 0 0;
}

/* Cards -------------------------------------------------------------------- */
.mk-card-media{aspect-ratio:5/4;}
.mk-card-body{gap:8px;padding:16px 18px 18px;}
.mk-card-poster{display:flex;align-items:center;gap:9px;}
/* Cards are narrower now that the map shares the row, so the contact control
   takes its own line rather than wrapping to two inside a squeezed pill. */
.mk-card-foot{flex-direction:column;align-items:stretch;gap:12px;}
.mk-card-foot .mk-btn{width:100%;}
.mk-avatar{
  display:flex;align-items:center;justify-content:center;width:28px;height:28px;flex:none;
  border-radius:50%;background:var(--green-100);color:var(--green-700);
  font-size:0.72rem;font-weight:800;letter-spacing:.02em;
}

/* Low inventory, styled as a deliberate invitation ------------------------- */
.mk-prompt{
  display:flex;flex-direction:column;align-items:center;text-align:center;gap:10px;align-self:stretch;
  justify-content:center;background:var(--green-100);border:1px dashed var(--green-300);
  border-radius:18px;padding:30px 24px;
}
.mk-prompt-icon{
  display:flex;align-items:center;justify-content:center;width:78px;height:78px;
  border-radius:50%;background:rgba(255,255,255,.75);color:var(--green-500);margin-bottom:2px;
}
.mk-prompt-icon svg{width:42px;height:42px;}
.mk-prompt h3{margin:0;font-size:1.04rem;color:var(--green-900);line-height:1.35;}
.mk-prompt p{margin:0;font-size:0.9rem;line-height:1.5;color:#5c7365;max-width:30ch;}
.mk-prompt .mk-btn{margin-top:6px;}

/* How it works ------------------------------------------------------------- */
.mk-steps{
  display:grid;grid-template-columns:1fr auto 1fr auto 1fr;gap:0 14px;align-items:stretch;
}
.mk-step{
  align-items:flex-start;text-align:left;gap:12px;padding:28px 26px;border-radius:20px;
}
.mk-step-num{
  position:static;display:flex;align-items:center;justify-content:center;
  width:34px;height:34px;border-radius:50%;background:var(--green-100);
  color:var(--green-700);font-size:0.92rem;font-weight:800;
}
.mk-step-icon{
  position:absolute;top:26px;right:26px;width:46px;height:46px;border-radius:14px;
  background:var(--green-100);color:var(--green-700);
}
.mk-step{position:relative;}
.mk-step-icon svg{width:24px;height:24px;}
.mk-step h3{margin-top:4px;}
.mk-step-arrow{
  display:flex;align-items:center;justify-content:center;color:var(--green-300);
  list-style:none;
}
.mk-step-arrow svg{width:26px;height:26px;}

/* Safety ------------------------------------------------------------------- */
/* Green, not warning-coloured: this is reassurance about how the marketplace
   works, not an alert about the listing you are looking at. */
.mk-safety{
  align-items:center;gap:20px;background:var(--green-100);
  border:1px solid #cfe0d5;border-radius:20px;padding:24px 28px;
}
.mk-safety-icon{width:48px;height:48px;border-radius:15px;background:#fff;color:var(--green-700);}
.mk-safety-icon svg{width:25px;height:25px;}
.mk-safety-copy h2{margin:0 0 4px;color:var(--green-900);font-size:1.1rem;}
.mk-safety-copy p{margin:0;color:#42544a;font-size:0.94rem;line-height:1.55;}

/* FAQ ---------------------------------------------------------------------- */
.mk-faq{gap:10px;}
.mk-faq-item{border-radius:18px;}
.mk-faq-q{padding:18px 22px;}
.mk-faq-a{padding:0 22px 20px;}

/* Narrower screens --------------------------------------------------------- */
@media (max-width:1000px){
  /* One column, so the headline has the whole width and the cap goes with it
     rather than holding the text to a measure meant for the two-column hero. */
  .mk-hero-inner{grid-template-columns:minmax(0,1fr);gap:26px;}
  .mk-hero-title{max-width:none;}
  .mk-trust-inner{grid-template-columns:repeat(2,1fr);gap:18px;}
}
@media (max-width:860px){
  /* The arrows are a desktop-only progression cue; stacked cards read in
     order on their own. */
  .mk-steps{grid-template-columns:1fr;gap:16px;}
  .mk-step-arrow{display:none;}
  .mk-step{
    display:grid;grid-template-columns:auto 1fr;grid-template-areas:"num title" "num text";
    column-gap:15px;row-gap:5px;padding:22px 20px;
  }
  .mk-step-num{grid-area:num;}
  .mk-step h3{grid-area:title;margin-top:5px;}
  .mk-step p{grid-area:text;max-width:none;}
  .mk-step-icon{top:20px;right:20px;width:40px;height:40px;}
  .mk-step-icon svg{width:21px;height:21px;}
}
@media (max-width:640px){
  .mk-hero{padding:24px 0 20px;}
  /* The phone used to get its own full-width scrim, even heavier than the
     desktop one (.56 to .90 down the frame), because the text runs the full
     width here. It is gone with the desktop one: .mk-hero-copy follows the
     words at any width, and it is the whole width on a phone because the
     words are. */
  .mk-hero.has-media{min-height:0;}
  /* Wider and softer at this size: the column is the screen, so the backing
     has to reach both gutters, and there is no photograph to either side of
     the text left to protect. */
  .mk-hero-copy::before{inset:-22px -28px -18px -28px;}
  /* Shorter again on a phone: the map is a companion to the list here, and a
     tall one would push the listings off the screen entirely. */
  .mk-map{height:clamp(260px,38vh,330px);}
  .mk-hero-title{max-width:none;}
  .mk-hero-inner{gap:16px;}
  .mk-search{padding:14px;}
  .mk-search-pin{display:none;}
  /* Icon beside the heading rather than stacked above it: the hero already
     carries a headline, a subtitle and a search panel before this card. */
  .mk-hero-post{
    padding:20px;display:grid;grid-template-columns:auto 1fr;
    grid-template-areas:"icon title" "text text" "btn btn";column-gap:13px;
  }
  .mk-hero-post-icon{grid-area:icon;width:40px;height:40px;margin:0;}
  .mk-hero-post-icon svg{width:22px;height:22px;}
  .mk-hero-post h2{grid-area:title;align-self:center;margin:0;font-size:1.06rem;}
  .mk-hero-post p{grid-area:text;margin:10px 0 16px;}
  .mk-hero-post .mk-btn{grid-area:btn;}
  .mk-trust-inner{grid-template-columns:repeat(2,1fr);gap:14px 12px;padding-top:14px;padding-bottom:14px;}
  .mk-trust-item b{font-size:0.9rem;}
  /* Scoped for the same reason as the desktop rule above: a bare "span"
     here also sets the icon tile's font-size, which is not a caption. */
  .mk-trust-item div span{font-size:0.8rem;}
  .mk-listings-head{flex-direction:column;align-items:stretch;}
  .mk-controls{width:100%;}
  .mk-filter{flex:1 1 auto;justify-content:space-between;}
  .mk-safety{flex-direction:column;align-items:flex-start;gap:14px;padding:22px 20px;}
  .mk-faq-q{padding:16px 18px;}
  .mk-faq-a{padding:0 18px 18px;}
}

/* --- Marketplace: fixed cards, pagination, detail modal ------------------
   A card's height is now the same whatever the listing says. Every text slot
   is both clamped and floored, so a two-word title and a three-paragraph
   description occupy the same box and rows never go ragged. -------------- */

/* Cards -------------------------------------------------------------------- */
.mk-card{cursor:pointer;}
.mk-card:focus-visible{outline:3px solid var(--green-500);outline-offset:3px;}
/* aspect-ratio only sizes a box whose in-flow content is not taller. The image
   had height:100% against an auto-height parent, which resolves to auto, so it
   rendered at its intrinsic height and grew the box past 4:3. Taking it out of
   flow makes the ratio authoritative for every listing. */
.mk-card-media{aspect-ratio:4/3;overflow:hidden;}
.mk-card-media > img,
.mk-card-media > .mk-card-noimg{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
}

/* Photo count, opposite the type badge. Only drawn above one photo. */
.mk-card-photos{
  position:absolute;top:12px;right:12px;display:inline-flex;align-items:center;gap:5px;
  background:rgba(27,58,43,.78);color:#fff;border-radius:999px;
  padding:5px 11px;font-size:0.78rem;font-weight:700;
}

.mk-card-body{display:flex;flex-direction:column;gap:8px;padding:16px 18px 18px;flex:1;}
.mk-card-head{align-items:flex-start;}
/* Clamped AND floored: the clamp stops long text, the min-height stops short
   text from making this card shorter than its neighbour. */
.mk-card-title{
  font-size:1.05rem;line-height:1.3;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  min-height:calc(2 * 1.3 * 1.05rem);
}
.mk-card-loc{
  display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  line-height:1.4;min-height:calc(1.4 * 0.87rem);
}
/* The pin is inline here rather than a flex child, so the ellipsis applies to
   the whole line including the place name. */
.mk-card-loc .mk-chip-icon{display:inline-block;vertical-align:-3px;margin-right:5px;}
.mk-card-desc{
  -webkit-line-clamp:2;line-height:1.5;
  min-height:calc(2 * 1.5 * 0.92rem);
}
.mk-card-foot{margin-top:auto;padding-top:12px;flex-direction:row;align-items:center;}

/* Two columns beside the map, not auto-fill: the listing area is a grid of its
   own and should not reflow into three narrow cards on a wide screen. */
@media (min-width:1000px){
  .mk-grid{grid-template-columns:repeat(2,minmax(0,1fr));}
}

/* Pagination --------------------------------------------------------------- */
.mk-pagination{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:8px;
  margin-top:26px;
}
.mk-pagination[hidden]{display:none;}
.mk-page-btn,.mk-page-num{
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  min-width:44px;min-height:44px;padding:10px 15px;border-radius:12px;
  border:1px solid #d7e4da;background:#fff;color:var(--green-700);
  font-family:inherit;font-size:0.92rem;font-weight:700;cursor:pointer;transition:.15s;
}
.mk-page-btn:hover:not(:disabled),.mk-page-num:hover{background:var(--green-100);border-color:var(--green-300);}
.mk-page-btn:disabled{opacity:.42;cursor:default;}
.mk-page-num.is-active{background:var(--green-700);border-color:var(--green-700);color:#fff;}
.mk-page-btn:focus-visible,.mk-page-num:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.mk-page-gap{color:#9aa79f;padding:0 2px;}
.mk-page-of{flex-basis:100%;text-align:center;color:var(--muted);font-size:0.85rem;margin-top:4px;}

/* Photo picker ------------------------------------------------------------- */
.mk-field-hint{margin:2px 0 0;font-size:0.8rem;color:var(--muted);}
/* The "42/60" under the listing title. Right-aligned and tabular, so the
   number does not shift the slash about as it counts up. */
.mk-count{
  margin:2px 0 0;align-self:flex-end;font-size:0.78rem;color:var(--muted);
  font-variant-numeric:tabular-nums;
}
/* At the limit, because maxlength refuses the next keystroke in silence. */
.mk-count.is-full{color:var(--warn-ink);font-weight:700;}
.mk-photo-preview{display:flex;flex-wrap:wrap;gap:10px;margin-top:10px;}
.mk-photo-preview[hidden]{display:none;}
.mk-photo-thumb{
  position:relative;display:block;width:72px;height:72px;border-radius:12px;
  overflow:hidden;border:1px solid #d7e4da;background:#fff;
}
.mk-photo-thumb img{width:100%;height:100%;object-fit:cover;display:block;}
/* The first file is the cover, which is worth saying on the thumbnail itself. */
.mk-photo-thumb.is-cover{border-color:var(--green-500);box-shadow:0 0 0 2px rgba(76,154,99,.28);}

/* Detail modal ------------------------------------------------------------- */
body.mk-modal-open{overflow:hidden;}
.mk-modal{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;padding:24px;}
.mk-modal[hidden]{display:none;}
.mk-modal-backdrop{position:absolute;inset:0;background:rgba(19,37,27,.58);backdrop-filter:blur(2px);}
.mk-modal-panel{
  position:relative;display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);
  width:min(960px,100%);max-height:min(680px,90vh);
  background:#fff;border-radius:22px;overflow:hidden;box-shadow:0 24px 60px rgba(19,37,27,.34);
}
.mk-modal-close{
  position:absolute;top:12px;right:12px;z-index:3;
  display:flex;align-items:center;justify-content:center;width:44px;height:44px;
  border:none;border-radius:50%;background:rgba(255,255,255,.94);color:var(--green-900);
  cursor:pointer;box-shadow:0 2px 10px rgba(19,37,27,.22);
}
.mk-modal-close:hover{background:var(--green-100);}
.mk-modal-close svg{width:20px;height:20px;}
.mk-modal-close:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}

.mk-modal-gallery{display:flex;flex-direction:column;background:var(--green-100);min-width:0;}
.mk-gallery-frame{position:relative;flex:1;min-height:260px;overflow:hidden;background:var(--green-100);}
/* Out of flow for the same reason as the card media: an in-flow image would
   size the frame to its own height instead of filling it. The placeholder is
   excluded from display:block, which would undo the flex centring it needs. */
.mk-gallery-frame > img,
.mk-gallery-frame > .mk-card-noimg{
  position:absolute;inset:0;width:100%;height:100%;
}
.mk-gallery-frame > img{object-fit:cover;display:block;}
.mk-gallery-nav{
  position:absolute;top:50%;transform:translateY(-50%);
  display:flex;align-items:center;justify-content:center;width:44px;height:44px;
  border:none;border-radius:50%;background:rgba(255,255,255,.94);color:var(--green-900);
  cursor:pointer;box-shadow:0 2px 10px rgba(19,37,27,.22);
}
.mk-gallery-nav:hover{background:#fff;}
.mk-gallery-nav[hidden]{display:none;}
.mk-gallery-nav svg{width:21px;height:21px;}
.mk-gallery-prev{left:12px;}
.mk-gallery-next{right:12px;}
.mk-gallery-thumbs{display:flex;gap:8px;padding:12px;overflow-x:auto;background:#fff;}
.mk-gallery-thumbs[hidden]{display:none;}
.mk-thumb{
  flex:none;width:56px;height:56px;padding:0;border-radius:10px;overflow:hidden;
  border:2px solid transparent;background:none;cursor:pointer;
}
.mk-thumb img{width:100%;height:100%;object-fit:cover;display:block;}
.mk-thumb.is-active{border-color:var(--green-500);}
.mk-thumb:focus-visible{outline:3px solid var(--green-500);outline-offset:1px;}

.mk-modal-body{display:flex;flex-direction:column;gap:12px;padding:28px;overflow-y:auto;}
/* The close button floats over this row, so the price keeps clear of it. */
.mk-modal-head{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;padding-right:52px;}
.mk-modal-head h2{margin:0;color:var(--green-900);font-size:1.4rem;line-height:1.25;}
.mk-modal-type{position:static;align-self:flex-start;box-shadow:none;}
.mk-modal-type[hidden]{display:none;}
/* The full text lives here, which is the point of the modal. */
.mk-modal-desc{margin:0;color:#42544a;font-size:0.97rem;line-height:1.65;white-space:pre-line;}
.mk-modal-contact{display:flex;flex-direction:column;gap:10px;margin-top:auto;padding-top:8px;}
.mk-modal-contact .mk-btn{align-self:flex-start;}
.mk-modal-contact .mk-msgbox{flex:1 0 auto;width:100%;}

@media (max-width:820px){
  .mk-modal{padding:0;align-items:stretch;}
  .mk-modal-panel{
    grid-template-columns:minmax(0,1fr);grid-template-rows:auto 1fr;
    width:100%;max-height:100vh;border-radius:0;
  }
  .mk-gallery-frame{min-height:0;aspect-ratio:4/3;flex:none;}
  .mk-modal-body{padding:20px;}
  .mk-modal-head h2{font-size:1.22rem;}
}
@media (max-width:640px){
  .mk-pagination{gap:6px;}
  .mk-page-btn{padding:10px 12px;}
  /* The word labels drop; the arrows still say which way each button goes. */
  .mk-page-btn span{display:none;}
}

/* --- Owner-only listing controls -----------------------------------------
   Rendered only when the signed-in user's id matches the listing's user_id,
   in the grid card, the detail modal and the map popup. Anyone else, signed
   in or not, sees the ordinary public listing and none of this. */
.mk-owner{margin-top:12px;padding-top:12px;border-top:1px solid #e7ece8;}
.mk-owner-note{
  margin:0 0 8px;font-size:0.76rem;line-height:1.45;color:#7a8a80;
}
.mk-owner-btns{display:flex;flex-wrap:wrap;gap:8px;}
.mk-owner-btn{
  flex:1 1 auto;min-height:40px;padding:8px 12px;
  background:#fff;border:1px solid #d7e4da;border-radius:10px;
  font-size:0.82rem;font-weight:600;color:var(--green-700);
  cursor:pointer;transition:.15s;
}
.mk-owner-btn:hover{border-color:var(--green-500);background:var(--green-100);}
.mk-owner-btn:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.mk-owner-btn[disabled]{opacity:.55;cursor:default;}
/* Permanent and unrecoverable, so it does not look like the other two. */
.mk-owner-danger{color:#a8452a;border-color:#f0c4b0;}
.mk-owner-danger:hover{background:#fff5f0;border-color:#d97b5f;}

/* A paused listing is still in the owner's own grid, dimmed and labelled, so
   there is somewhere to click to bring it back. Nobody else receives it. */
.mk-card-paused .mk-card-media{opacity:.55;}
.mk-card-paused-badge{
  position:absolute;left:10px;bottom:10px;
  background:rgba(27,58,43,.88);color:#fff;
  padding:4px 10px;border-radius:999px;
  font-size:0.72rem;font-weight:700;letter-spacing:.02em;
}
/* Leaflet sizes popups to their content, which a three-button row would blow
   out; this keeps the popup narrow and lets the buttons wrap. */
.leaflet-popup-content .mk-owner{min-width:190px;}
.leaflet-popup-content .mk-owner-btn{flex:1 1 100%;}

@media(pointer:coarse){
  .mk-owner-btn{min-height:44px;}
}

/* --- 404 -------------------------------------------------------------------
   The art carries intrinsic width/height on the <img> and a CSS aspect-ratio
   here, so the box is the right shape before the SVG arrives and the headline
   below it never jumps. width:min(352px,72vw) is what scales it on a phone;
   height:auto lets the ratio drive the rest. */
.error-page{
  max-width:620px;margin:0 auto;padding:56px 20px 80px;text-align:center;
}
.error-art{
  display:block;width:min(352px,72vw);height:auto;aspect-ratio:352/284;
  margin:0 auto 26px;
}
.error-page h1{
  font-size:clamp(1.6rem,4.2vw,2.3rem);line-height:1.15;margin:0 0 12px;
  color:var(--green-dark);
}
.error-text{
  margin:0 auto 30px;max-width:46ch;color:var(--text-muted);line-height:1.6;
}
/* The results list is absolutely positioned under the field, so an empty one
   takes no space and a full one never pushes the button down the page. */
.error-search{position:relative;margin:0 auto 26px;max-width:460px;text-align:left;}
.error-search .home-search-input{width:100%;}
.error-search .search-results{
  position:absolute;left:0;right:0;top:calc(100% + 6px);z-index:20;
  background:#fff;border-radius:14px;overflow:hidden;
  box-shadow:0 10px 30px rgba(16,40,26,.14);
}
.error-search .search-results:empty{display:none;}
.error-home{display:inline-flex;}

@media(max-width:600px){
  .error-page{padding:34px 20px 60px;}
  .error-art{margin-bottom:20px;}
}

/* The About page's "Why WikiPlant" row, and the bonsai hub's four cards.
   Both were an unstyled div, so the cards stacked in one column at every
   width and looked nothing like the FAQ cards below them on the same page.

   auto-fit rather than repeat(3, 1fr), because this same strip carries three
   cards on About and four on the bonsai hub: the tracks that fit are filled
   and the empty ones collapse, so three cards share the row in thirds and
   four share it in quarters without either layout being written down. Below
   about 520px only one track fits and they become a single column. */
.features-strip{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));}
/* The FAQ card look, from .faq-item, so the two blocks on the About page read
   as one page. A card that is a link keeps its own text colour rather than
   taking the browser's blue. */
.feature-card{
  background:var(--green-100);border-radius:10px;padding:14px 16px;margin:0;
  color:var(--text);text-decoration:none;
}
.feature-card p{margin:0;color:var(--text);font-size:0.97rem;line-height:1.6;}
.feature-icon{display:block;color:var(--green-700);}
.feature-icon-svg{width:28px;height:28px;display:block;}

/* The icons that replaced the emoji elsewhere. Each is sized in its own
   context and takes its colour from the text it sits with, so none of them
   needs a colour of its own except where the heading is green already. */
.info-item h3{display:flex;align-items:center;gap:8px;}
.info-icon{width:20px;height:20px;flex:0 0 auto;color:var(--green-700);}
.dtab-btn{display:inline-flex;align-items:center;gap:7px;}
.dtab-icon{width:18px;height:18px;flex:0 0 auto;}
.oauth-icon{width:20px;height:20px;flex:0 0 auto;}
.report-icon{width:16px;height:16px;vertical-align:-3px;}
.footer-icon{width:16px;height:16px;vertical-align:-3px;}

/* .feature-card headings were relying on the browser's default h3 size. The
   bonsai hub's cards are its top-level sections so they are h2 now, while the
   About page's sit under a section title and stay h3; pinning the size here
   keeps the two looking identical and stops the tag choice from being a
   visual decision. */
.feature-card h2,.feature-card h3{
  /* Was 18px above and below, from when the card had an emoji on its own line
     and nothing else to set the rhythm. The icon now sits directly above, so
     the gap is the FAQ card's 6px under the heading and a smaller step over
     it. */
  font-size:1.17rem;font-weight:700;margin:10px 0 6px;color:var(--green-900);
}

/* --- Cookie consent banner -------------------------------------------------
   Ported from the design reference. The demo carried its own palette; these
   map onto the site's tokens, which resolve to the same colours. The amber
   --focus is kept literal: it is the one accent that has to stay visible
   against both the white card and the green buttons.

   Fixed position, so it reserves no space in the flow and contributes nothing
   to CLS. bottom uses safe-area-inset so it clears an iPhone's home bar. */
/* A light wash over the page so the card is noticed, and nothing more than
   that: pointer-events:none means every link, button and scroll underneath
   keeps working, so this is not a modal and must not behave like one. It
   fades rather than disappears, and goes the moment an answer is given. */
.cb-dim{
  position:fixed;inset:0;z-index:999;
  background:rgba(27,58,43,.12);
  pointer-events:none;
  opacity:0;transition:opacity .35s ease;
}
.cb-dim.is-on{opacity:1;}
.cb-dim[hidden]{display:none;}

/* Phones: a sheet along the bottom, within thumb reach, 12px clear of each
   edge. The safe-area inset is padding inside the card rather than a bigger
   offset, so on a phone without a home bar the card does not float. */
#cookie-banner{
  position:fixed;left:12px;right:12px;bottom:12px;z-index:1000;
  background:#fff;border:1px solid #dce5d8;border-radius:16px;
  box-shadow:0 10px 34px rgba(27,58,43,.20);
  padding:14px 16px;
  padding-bottom:calc(14px + env(safe-area-inset-bottom,0px));
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  animation:cb-rise .45s ease-out;
}
#cookie-banner[hidden]{display:none;}
@keyframes cb-rise{
  from{opacity:0;transform:translateY(16px);}
  to{opacity:1;transform:translateY(0);}
}

/* 768px and up: a card under the header rather than along the bottom edge.
   Top, because a notice at the bottom of a long page is read last if at all,
   and 16px below the header rather than over it: the bar is sticky at z-index
   900, this is 1000, so without the offset it would cover the language menu
   the moment the page is scrolled. --cb-top is the measured header height,
   written by assets/cookie-consent.js; the fallback is what it measures on a
   desktop today, so the card still lands correctly if the script cannot. */
@media(min-width:768px){
  #cookie-banner{
    left:50%;right:auto;bottom:auto;
    top:calc(var(--cb-top,67px) + 16px);
    transform:translateX(-50%);
    width:min(560px,calc(100% - 32px));
    border-radius:18px;
    box-shadow:0 18px 48px rgba(27,58,43,.22);
    padding:18px 20px;
    animation:cb-drop .45s ease-out;
  }
  @keyframes cb-drop{
    from{opacity:0;transform:translate(-50%,-16px);}
    to{opacity:1;transform:translate(-50%,0);}
  }
}
.cb-plant{width:88px;height:88px;flex:none;}
.cb-text{flex:1;min-width:220px;}
.cb-title{margin:0 0 4px;font-weight:600;font-size:16px;color:var(--green-900);}
.cb-sub{margin:0;font-size:14px;color:#566b5e;}
.cb-sub a{color:var(--green-900);text-decoration:underline;}
.cb-sub a:focus-visible{outline:3px solid #e8a93c;outline-offset:2px;}

/* The card is 560px at most, so the buttons never fit beside the mascot and
   the text; they always take a row of their own and share it equally. */
.cb-btns{display:grid;grid-template-columns:1fr 1fr;gap:10px;width:100%;}
/* The class sets display:grid, which would otherwise beat the user agent's
   [hidden]{display:none} and leave the buttons on screen after a choice. */
.cb-btns[hidden]{display:none;}

/* Refuse and accept are the same size, the same shape, the same weight and
   the same row, and each is one click. Accept is filled and refuse outlined,
   which is as far apart as they are allowed to get: making refusal smaller,
   greyer, lighter or an extra click is the usual way a banner fails the
   CNIL's test. The outline is the full green at full weight, not a hairline
   in grey. */
.cb-btn{
  background:var(--green-700);color:#fff;border:2px solid var(--green-700);
  border-radius:10px;padding:10px 20px;min-width:128px;min-height:44px;
  font:inherit;font-weight:600;font-size:15px;cursor:pointer;
}
.cb-btn:hover{background:#256b42;border-color:#256b42;}
.cb-btn:focus-visible{outline:3px solid #e8a93c;outline-offset:2px;}
.cb-btn-ghost{background:#fff;color:var(--green-900);border-color:var(--green-700);}
.cb-btn-ghost:hover{background:var(--green-100);border-color:var(--green-900);color:var(--green-900);}

/* The plant reacts to the answer: it flowers and grows on yes, sprouts two
   extra leaves and hops on no. */
.cb-o{stroke:#1b3a2b;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;}
.cb-ln{fill:none;stroke-linecap:round;}
#cp-flower{transform-box:fill-box;transform-origin:center;transform:scale(0);transition:transform .5s cubic-bezier(.34,1.56,.64,1);}
.is-yes #cp-flower{transform:scale(1);}
#cp-ext{stroke-dasharray:16;stroke-dashoffset:16;transition:stroke-dashoffset .4s;}
.is-yes #cp-ext{stroke-dashoffset:0;}
#cp-extra{opacity:0;transition:opacity .3s .3s;}
.is-no #cp-extra{opacity:1;}
#cp-plant{transform-box:fill-box;transform-origin:50% 100%;}
.is-no #cp-plant{animation:cb-hop .6s ease-out 2;}
@keyframes cb-hop{0%,100%{transform:translateY(0);}40%{transform:translateY(-8px);}}

/* A footer item that reopens the banner. It is a button, not a link, because
   it performs an action rather than navigating; these rules strip the button
   chrome so it reads as the links beside it. */
.footer-linkbtn{
  font:inherit;color:inherit;background:none;border:0;padding:0;
  text-decoration:underline;cursor:pointer;
}
.footer-linkbtn:hover{color:#fff;}
.footer-linkbtn:focus-visible{outline:3px solid #e8a93c;outline-offset:2px;}

@media(max-width:560px){
  #cookie-banner{padding:12px 14px;padding-bottom:calc(12px + env(safe-area-inset-bottom,0px));gap:10px;}
  .cb-plant{width:64px;height:64px;}
  .cb-text{min-width:0;flex:1 1 calc(100% - 80px);}
  .cb-btn{min-width:0;}
}
@media(prefers-reduced-motion:reduce){
  #cookie-banner{animation:none;}
  .cb-dim{transition:none;}
  #cp-flower,#cp-ext,#cp-extra{transition:none;}
  .is-no #cp-plant{animation:none;}
}

/* --- Cookie / legal information pages -------------------------------------- */
.legal-page{max-width:760px;padding-bottom:70px;}
.legal-page h1{font-size:clamp(1.7rem,4vw,2.2rem);margin:14px 0 10px;color:var(--green-900);}
.legal-page h2{font-size:1.15rem;margin:30px 0 8px;color:var(--green-900);}
.legal-page p{line-height:1.7;margin:0 0 12px;}
.legal-intro{font-size:1.05rem;color:var(--green-700);}
/* The table scrolls rather than squeezing three columns onto a phone. */
.legal-tablewrap{overflow-x:auto;margin:0 0 12px;}
.legal-table{border-collapse:collapse;width:100%;min-width:420px;font-size:.95rem;}
.legal-table th,.legal-table td{
  text-align:left;padding:10px 12px;border-bottom:1px solid var(--green-100);vertical-align:top;
}
.legal-table th{background:var(--green-100);color:var(--green-900);font-weight:700;}
.legal-table code{background:var(--green-100);padding:2px 6px;border-radius:5px;font-size:.9em;}

/* --- Report a listing ------------------------------------------------------
   A quiet link-weight button: reporting should be findable but must not
   compete with "contact" or the owner's own controls. */
.listing-report-btn{
  display:inline-flex;align-items:center;gap:5px;
  margin-top:10px;padding:6px 2px;
  font:inherit;font-size:.82rem;color:var(--text-muted,#566b5e);
  background:none;border:0;text-decoration:underline;cursor:pointer;
}
.listing-report-btn:hover{color:#a1442f;}
.listing-report-btn:focus-visible{outline:3px solid #e8a93c;outline-offset:2px;}
@media(pointer:coarse){
  .listing-report-btn{min-height:44px;padding:11px 2px;}
}

.report-overlay{
  position:fixed;inset:0;z-index:1200;
  background:rgba(15,32,22,.45);
  display:flex;align-items:center;justify-content:center;padding:20px;
}
.report-overlay[hidden]{display:none;}
.report-modal{
  background:#fff;border-radius:16px;padding:22px 24px;
  width:min(460px,100%);max-height:90vh;overflow-y:auto;
  box-shadow:0 18px 50px rgba(16,40,26,.3);
}
.report-modal h2{margin:0 0 6px;font-size:1.2rem;color:var(--green-900);}
.report-intro{margin:0 0 16px;font-size:.92rem;color:var(--text-muted,#566b5e);line-height:1.55;}
.report-reasons{border:0;padding:0;margin:0 0 16px;}
.report-reasons legend{padding:0;margin:0 0 8px;font-weight:700;font-size:.9rem;color:var(--green-900);}
.report-reason{display:flex;align-items:center;gap:9px;padding:7px 0;cursor:pointer;font-size:.93rem;}
.report-reason input{width:17px;height:17px;accent-color:var(--green-700);flex:none;}
.report-details-label{display:block;margin:0 0 6px;font-weight:700;font-size:.9rem;color:var(--green-900);}
.report-modal textarea{
  width:100%;padding:10px 12px;border:1px solid var(--green-100);border-radius:10px;
  font:inherit;font-size:.93rem;resize:vertical;
}
.report-modal textarea:focus-visible{outline:3px solid #e8a93c;outline-offset:1px;}
.report-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:18px;}
.report-actions button{min-height:44px;}
.report-status{margin:14px 0 0;padding:11px 13px;border-radius:10px;font-size:.92rem;line-height:1.5;}
.report-status.is-ok{background:var(--green-100);color:var(--green-900);}
.report-status.is-error{background:#fbe9e5;color:#8d2f1a;}

@media(max-width:560px){
  .report-modal{padding:18px;}
  .report-actions{flex-direction:column-reverse;}
  .report-actions button{width:100%;}
}

/* --- Legal pages ----------------------------------------------------------- */
.legal-updated{margin:0 0 26px;font-size:.85rem;color:var(--text-muted,#566b5e);}
.legal-list{margin:0 0 14px;padding-left:22px;line-height:1.7;}
.legal-list li{margin-bottom:5px;}

/* --- Profile / username field ---------------------------------------------
   The hint under the username input. It explains that this one field is the
   only thing other people see, so it sits with the input rather than in a
   tooltip. */
/* p.field-hint, not .field-hint: these sit inside .sitters-gate and .hero,
   whose `.sitters-gate p` and `.hero p` rules are specificity 0,1,1 and so beat
   a bare class. The hint was rendering at 16.8px in --green-700, the size and
   colour of a hero paragraph, instead of as a quiet note under its field.
   Matching their specificity is enough, since this rule comes later. */
p.field-hint{
  margin:-4px 0 6px;font-size:.84rem;line-height:1.45;
  color:var(--text-muted,#566b5e);
  text-align:left;
}
/* The shared .auth-message is styled for errors; a successful save needs to
   read as a success rather than as another failure. */
.auth-message.is-ok{color:var(--green-700);}

/* The required marker. aria-hidden in the markup, because the input's own
   `required` attribute is what a screen reader announces; this is the visual
   half of the same fact. */
.auth-form .req{
  margin-left:3px;color:#a1442f;font-weight:700;
}

/* --- Message thread -------------------------------------------------------
   Opened from a Reply button on My Account. Sits above the two message lists
   rather than replacing them: those still show everything, newest first. */
.thread-panel{scroll-margin-top:calc(var(--header-h) + 16px);}
.thread-back{margin-bottom:6px;}
.thread-with{margin:0 0 14px;color:var(--text-muted,#566b5e);font-size:.92rem;}

/* The listing this conversation is about. Rendered from the snapshot stored on
   the message, so it survives the listing being paused or deleted. */
.thread-listing{
  display:flex;align-items:center;gap:12px;
  padding:10px 12px;margin:0 0 16px;
  background:var(--green-100);border-radius:12px;
}
.thread-listing img{
  width:64px;height:64px;flex:none;object-fit:cover;border-radius:8px;
}

/* Oldest first, so the newest sits next to the reply box. Capped and scrolled
   so a long thread does not push the box off the screen. */
.thread-messages{
  display:flex;flex-direction:column;gap:10px;
  max-height:46vh;overflow-y:auto;padding:2px;margin:0 0 14px;
}
.thread-msg{
  align-self:flex-start;max-width:min(80%,520px);
  padding:9px 13px;border-radius:14px 14px 14px 4px;
  background:#f1f5f0;border:1px solid var(--green-100);
}
.thread-msg.is-mine{
  align-self:flex-end;border-radius:14px 14px 4px 14px;
  background:var(--green-100);border-color:var(--green-300);
}
.thread-msg-meta{
  font-size:.76rem;color:var(--text-muted,#566b5e);margin-bottom:3px;
}
.thread-msg p{margin:0;line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere;}

.thread-reply textarea{
  width:100%;padding:10px 12px;border:1px solid var(--green-300);
  border-radius:8px;font:inherit;font-size:1rem;resize:vertical;
}
.thread-reply textarea:focus-visible{outline:3px solid #e8a93c;outline-offset:1px;}

.msg-reply-btn{margin-top:8px;font-size:.88rem;}
@media(pointer:coarse){
  .msg-reply-btn{min-height:44px;}
}

/* --- My plants -------------------------------------------------------------
   The header holds two icons comfortably at 375px and overflows with three,
   pushing the language select past the right edge. So the icon is a desktop
   thing and the account menu carries it on a phone; exactly one of the two is
   visible at any width. 701px is the same breakpoint the nav already uses to
   switch between the dropdown and the inline bar. */
#nav-my-plants-btn{display:none;}
.nav-my-plants{
  font:inherit;text-align:left;background:none;border:0;padding:0;cursor:pointer;
  color:var(--green-900);font-weight:600;font-size:1.05rem;
}
.nav-my-plants:hover{color:var(--green-500);}
.nav-my-plants:focus-visible{outline:3px solid #e8a93c;outline-offset:2px;}

@media(min-width:701px){
  #nav-my-plants-btn{display:flex;}
  .nav-my-plants{display:none;}
}

/* --- My plants ------------------------------------------------------------- */
.mp-page{max-width:820px;padding-bottom:70px;}
.mp-title{display:flex;align-items:center;gap:12px;font-size:clamp(1.7rem,4vw,2.2rem);margin:14px 0 12px;color:var(--green-900);}
.mp-title-icon{display:inline-flex;color:var(--green-700);flex:none;}
.mp-pitch{font-size:1.05rem;line-height:1.7;color:var(--text);max-width:56ch;margin:0 0 20px;}

/* What the library is and what it costs, above both halves of the page. */
.mp-benefits{
  margin:4px 0 26px;padding:18px 20px;max-width:620px;
  background:var(--green-100);border:1px solid var(--green-300);border-radius:16px;
}
.mp-benefits-title{margin:0 0 10px;font-size:1.05rem;color:var(--green-900);}
.mp-benefits-list{
  list-style:none;margin:0 0 14px;padding:0;
  display:flex;flex-direction:column;gap:7px;
}
.mp-benefits-list li{
  position:relative;padding-left:24px;color:var(--text);font-size:.95rem;line-height:1.5;
}
/* A drawn tick rather than a character, so it cannot arrive as an emoji on
   one platform and a box on another. */
.mp-benefits-list li::before{
  content:"";position:absolute;left:3px;top:.42em;width:11px;height:6px;
  border-left:2px solid var(--green-700);border-bottom:2px solid var(--green-700);
  transform:rotate(-45deg);
}
.mp-benefits-browse{
  display:inline-flex;align-items:center;min-height:40px;
  color:var(--green-700);font-weight:700;font-size:.93rem;text-decoration:underline;
}
.mp-benefits-browse:hover{color:var(--green-900);}

/* The empty library's way out, as a button. */
.mp-empty-btn{
  display:inline-flex;align-items:center;gap:9px;margin-top:6px;
  min-height:44px;padding:0 20px;border-radius:999px;
  background:var(--green-700);color:#fff;text-decoration:none;
  font-size:.95rem;font-weight:700;transition:background .16s;
}
.mp-empty-btn:hover{background:var(--green-900);color:#fff;}
.mp-empty-btn:focus-visible{outline:3px solid var(--green-700);outline-offset:3px;}

@media(max-width:560px){
  .mp-benefits{padding:16px;}
  .mp-empty-btn,.mp-benefits-browse{width:100%;justify-content:center;}
}
.mp-actions{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin:0 0 34px;}
.mp-preview-label{font-size:1rem;color:var(--text-muted,#566b5e);margin:0 0 12px;font-weight:600;}

.mp-list{list-style:none;margin:0 0 24px;padding:0;display:grid;gap:10px;}
.mp-card{
  position:relative;
  display:flex;align-items:center;gap:14px;
  padding:10px 14px;background:#fff;
  border:1px solid var(--green-100);border-radius:12px;
}
.mp-card:has(.mp-card-link):hover{border-color:var(--green-300);}
.mp-card-photo{width:64px;height:64px;flex:none;object-fit:cover;border-radius:8px;}
/* The three lines stack with real space between them. They used to sit in a
   2px-gap column, so the name and the nickname read as one run of text
   ("ficus-retusaIndoor") to anything reading the card out. */
.mp-card-body{flex:1;min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:4px;}
.mp-card-link{
  font-weight:700;color:var(--green-900);text-decoration:none;
  /* Stretched over the card so the whole row is clickable, while the link text
     stays just the plant name. The Remove button lifts itself above this. */
}
.mp-card-link::after{content:'';position:absolute;inset:0;border-radius:12px;}
.mp-card-link:hover{color:var(--green-500);text-decoration:underline;}
.mp-card-link:focus-visible{outline:3px solid #e8a93c;outline-offset:3px;}
.mp-card-name{font-weight:700;color:var(--text-muted,#566b5e);}
.mp-card-latin{font-size:.86rem;font-style:italic;color:var(--text-muted,#566b5e);}
.mp-card.is-gone{opacity:.8;background:var(--green-100);}
.mp-nickname{
  font-size:.84rem;color:var(--green-700);
  background:var(--green-100);border-radius:6px;padding:2px 7px;
}
/* The gone-card already uses green-100 as its background, so the chip needs a
   different one to stay a chip. */
.mp-card.is-gone .mp-nickname{background:#fff;}
/* The preview on the signed-out page is decoration, not a list to act on. */
/* The example library.
   It used to be opacity:.75 over the whole list with pointer-events:none -
   decorative, unreachable, and the fade applied to the text as much as to
   the photographs, which is where the contrast went. The fade now sits on
   the photographs alone, so the cards still read as an example while the
   names keep their full colour, and the cards are real links. */
.mp-preview{opacity:1;}
.mp-preview .mp-card-photo{opacity:.72;}
.mp-card-link{
  display:flex;align-items:center;gap:14px;width:100%;
  color:inherit;text-decoration:none;border-radius:12px;
}
.mp-card-link:hover .mp-card-name{text-decoration:underline;}
.mp-card-link:hover .mp-card-photo{opacity:1;}
.mp-card-link:focus-visible{outline:3px solid var(--green-700);outline-offset:2px;}
.mp-card-link:focus-visible .mp-card-photo{opacity:1;}
/* Two lines, in the order they matter: which plant, then where it lives.
   The name takes the body colour so it leads; the room is smaller and in
   the muted token, which is 5.12:1 at worst - quieter, still readable.
   Scoped to the preview, so a real library entry is untouched. */
.mp-card-preview .mp-card-name{color:var(--text);}
.mp-card-nick{
  display:inline-flex;align-items:center;gap:5px;
  font-size:.86rem;color:var(--muted);
}
.mp-card-pin{flex:none;}
.mp-card-preview .mp-card-body{gap:2px;}
/* Above the stretched link, so a click on Remove removes rather than
   navigating to the plant. */
.mp-remove{position:relative;z-index:1;flex:none;font-size:.86rem;color:#a1442f;}
@media(pointer:coarse){ .mp-remove{min-height:44px;} }

.mp-count{font-size:.88rem;color:var(--text-muted,#566b5e);margin:0 0 10px;}
.mp-empty{text-align:center;padding:34px 20px;background:var(--green-100);border-radius:14px;margin:0 0 24px;}
.mp-empty h2{margin:0 0 8px;font-size:1.15rem;color:var(--green-900);}
.mp-empty p{margin:0 0 18px;color:var(--green-700);}

.mp-share{margin-top:10px;}
.mp-toggle{display:flex;align-items:center;gap:10px;cursor:pointer;font-weight:600;color:var(--green-900);margin:0 0 12px;}
.mp-toggle input{width:20px;height:20px;accent-color:var(--green-700);flex:none;}
#mp-share-link-row{display:flex;gap:10px;align-items:center;flex-wrap:wrap;}
#mp-share-link{
  flex:1;min-width:0;padding:9px 12px;font:inherit;font-size:.9rem;
  border:1px solid var(--green-300);border-radius:8px;background:var(--green-100);color:var(--green-900);
}

/* The link on a plant page. */
/* "I have this plant".
   It was an underlined link below the description, which read as a footnote
   to the text above it rather than as the one thing to do on the page. It is
   the primary action here, so it looks like one: filled, white on green at
   6.34:1, with a 44px target. */
.mp-add-btn{
  display:inline-flex;align-items:center;gap:9px;margin-top:18px;
  min-height:44px;padding:0 20px;border:none;border-radius:999px;
  background:var(--green-700);color:#fff;text-decoration:none;
  font-size:.95rem;font-weight:700;cursor:pointer;transition:background .16s;
}
.mp-add-btn:hover{background:var(--green-900);color:#fff;}
.mp-add-btn:focus-visible{outline:3px solid var(--green-700);outline-offset:3px;}
.mp-add-icon{flex:none;}
/* Already in the library: still green so it does not read as disabled, but
   quieter, and it stops responding to the pointer. */
.mp-add-btn.is-added{
  background:var(--green-100);color:var(--green-900);cursor:default;
  box-shadow:inset 0 0 0 1px var(--green-300);
}
.mp-add-btn.is-added:hover{background:var(--green-100);color:var(--green-900);}
.mp-add-btn[aria-disabled="true"]{opacity:.6;pointer-events:none;}

/* What a signed-out visitor gets when they press it. */
.mp-gate{
  margin:12px 0 0;padding:14px 16px;max-width:460px;
  background:var(--green-100);border:1px solid var(--green-300);border-radius:14px;
}
.mp-gate[hidden]{display:none;}
.mp-gate-text{margin:0 0 12px;color:var(--text);font-size:.95rem;line-height:1.5;}
.mp-gate-actions{display:flex;flex-wrap:wrap;align-items:center;gap:10px 16px;margin:0;}
.mp-gate-signin{
  display:inline-flex;align-items:center;min-height:40px;padding:0 18px;
  border-radius:999px;background:var(--green-700);color:#fff;
  text-decoration:none;font-weight:700;font-size:.9rem;
}
.mp-gate-signin:hover{background:var(--green-900);color:#fff;}
.mp-gate-signup{
  display:inline-flex;align-items:center;min-height:40px;
  color:var(--green-700);font-weight:600;font-size:.9rem;text-decoration:underline;
}
.mp-gate-signup:hover{color:var(--green-900);}

@media(max-width:560px){
  .mp-card{gap:10px;padding:9px 11px;}
  .mp-card img{width:52px;height:52px;}
}

/* --- Plant picker (combobox) ----------------------------------------------
   Replaces a <datalist>, which cannot show a photo beside an option, cannot be
   styled, and opens inconsistently across browsers. */
.mp-combo{position:relative;}
.mp-options{
  position:absolute;left:0;right:0;top:calc(100% + 4px);z-index:40;
  margin:0;padding:4px;list-style:none;
  max-height:min(340px,52vh);overflow-y:auto;
  background:#fff;border:1px solid var(--green-300);border-radius:10px;
  box-shadow:0 10px 30px rgba(16,40,26,.14);
}
.mp-options[hidden]{display:none;}
.mp-option{
  display:flex;align-items:center;gap:10px;
  padding:7px 9px;border-radius:8px;cursor:pointer;
  font-size:.93rem;line-height:1.3;
}
.mp-option img{width:36px;height:36px;flex:none;object-fit:cover;border-radius:6px;}
.mp-option-name{font-weight:600;color:var(--green-900);}
.mp-option-latin{
  font-style:italic;font-size:.84rem;color:var(--text-muted,#566b5e);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;
}
.mp-option-added{
  flex:none;font-size:.76rem;font-weight:600;color:var(--green-700);
  background:var(--green-100);border-radius:6px;padding:2px 7px;
}
/* Hover and the keyboard cursor look the same, so arrowing down and moving the
   mouse read as one selection rather than two competing ones. */
.mp-option:hover,.mp-option.is-active{background:var(--green-100);}
.mp-option.is-added{opacity:.72;}
.mp-option.is-empty{
  cursor:default;color:var(--text-muted,#566b5e);justify-content:center;padding:14px 9px;
}
.mp-option.is-empty:hover{background:none;}
@media(pointer:coarse){
  .mp-option{padding:11px 9px;}
  .mp-option img{width:40px;height:40px;}
}

/* --- Mobile header ---------------------------------------------------------
   Measured at 320px before this: signed out the row was 4px over, signed in
   49px over, and with a 27-character name 182px over, with the language button
   pushed off the right edge in all three. The name pill alone was 199px.

   Below 560px the pill becomes a round button showing the first letter. The
   full name stays as the button's accessible name, so only the pixels change.
   Desktop is untouched: .login-initial never shows above this width. */
.login-initial{display:none;}

@media(max-width:560px){
  .login-btn .login-name{display:none;}
  .login-btn .login-initial{
    display:flex;align-items:center;justify-content:center;
    width:100%;height:100%;font-size:1rem;line-height:1;
  }
  /* Only the signed-in pill becomes a circle. The signed-out one keeps its
     words, because "Log in" is a call to action and a lone "L" is not. */
  .login-btn[aria-label]{
    width:44px;height:44px;min-width:44px;padding:0;border-radius:50%;
    display:flex;align-items:center;justify-content:center;flex:none;
  }

  /* 44px for everything tappable in the row. These were 32 (bell, heart),
     27 (language) and 36 (menu). The visual size of each is unchanged; the
     target around it grows. */
  .account-icon-btn{min-width:44px;min-height:44px;justify-content:center;}
  #account-extras{gap:2px;}
  .menu-toggle{width:44px;height:44px;padding:10px 4px;}
  #lang-select{min-height:44px;padding:4px 6px;}

  /* The language button is the last thing in the row and was sitting flush
     against the edge. Both sides are set here, not just the right: setting one
     alone left 14px on the left against 10px on the right, so the row looked
     pushed over. The menu button and the language button now sit the same
     distance from their own edge. */
  .header-inner{padding-left:10px;padding-right:10px;gap:4px;}
}

/* Very narrow phones: the brand shrinks before anything tappable does. */
@media(max-width:380px){
  .header-inner{padding-left:8px;padding-right:8px;gap:2px;}
  .brand img{height:22px;}
  #lang-select{font-size:0.8rem;padding:4px 4px;}
}

/* At 320px the signed-in row needs 326px before padding: menu 44, brand 88,
   bell 44, heart 44, initial 44, language 48. Five 44px tap targets plus a
   legible wordmark do not fit, and something has to give.

   The bell and the heart go. They are placeholders, labelled "coming soon",
   and they do nothing when tapped; letting them push a working language
   selector off the screen would be the wrong trade. Everything that does
   something keeps its full target. They come back at 401px, where there is
   room for them at 44px. */
@media(max-width:400px){
  #account-extras .account-icon-btn[data-i18n-aria="nav_notifications_soon"],
  .nav-favorites-btn{
    display:none;
  }
}
/* The word in the nav takes over wherever the icon is not shown, so the
   entry is never simply absent. Mirrors #nav-my-plants-btn / .nav-my-plants. */
.nav-favorites{
  font:inherit;text-align:left;background:none;border:0;padding:0;cursor:pointer;
  color:var(--green-900);font-weight:600;font-size:1.05rem;
}
.nav-favorites:hover{color:var(--green-500);}
.nav-favorites:focus-visible{outline:3px solid #e8a93c;outline-offset:2px;}
@media(min-width:401px){ .nav-favorites{display:none;} }

/* ===========================================================================
   Favorites: the heart, and the page behind it (assets/favorites.js)
   =========================================================================== */

/* On a card the heart sits over the top right of the photo. It is hidden
   until the card is hovered or something inside it has focus: :focus-within
   is not decoration here, it is the only thing that makes the control
   reachable with a keyboard, since a Tab into the card is not a hover.
   Where there is no hover at all, which is every touch screen, it is simply
   always there, smaller and lighter so it does not shout over the photo. */
.fav-heart{
  position:absolute;top:8px;right:8px;z-index:2;
  width:44px;height:44px;display:flex;align-items:center;justify-content:center;
  border:0;border-radius:50%;background:rgba(255,255,255,.92);
  color:var(--green-900);cursor:pointer;padding:0;
  box-shadow:0 2px 8px rgba(27,58,43,.18);
  opacity:0;transition:opacity .15s ease,transform .15s ease,color .15s ease;
}
.fav-heart svg{width:20px;height:20px;}
.plant-card:hover .fav-heart,
.plant-card:focus-within .fav-heart,
.mk-card:hover .fav-heart,
.mk-card:focus-within .fav-heart,
.sit-card:hover .fav-heart,
.sit-card:focus-within .fav-heart,
.fav-card:hover .fav-heart,
.fav-card:focus-within .fav-heart,
.fav-heart:focus-visible{opacity:1;}
.fav-heart:hover{transform:scale(1.06);}
.fav-heart:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
/* Saved is not a hover state: a filled heart has to be visible whatever the
   pointer is doing, or the card cannot be told apart from an unsaved one. */
.fav-heart.is-on{opacity:1;color:var(--green-700);}
.fav-heart.is-on svg{fill:currentColor;}
/* No hover anywhere means no way to reveal it, so on a touch screen it is
   always there. Lighter and visually smaller, but the button keeps its full
   44px: the circle shrinks by insetting the background with a shadow spread
   rather than by making the control itself smaller, because a 38px target is
   a 38px target however light it looks. */
@media(hover:none){
  .fav-heart{
    opacity:1;background:none;box-shadow:none;
  }
  .fav-heart::before{
    content:'';position:absolute;top:3px;right:3px;bottom:3px;left:3px;
    border-radius:50%;background:rgba(255,255,255,.78);
    box-shadow:0 1px 5px rgba(27,58,43,.14);
  }
  .fav-heart svg{position:relative;width:18px;height:18px;}
  .fav-heart.is-on::before{background:rgba(255,255,255,.95);}
}

/* On the plant page it is not on the photo at all: it sits at the end of the
   title row, on the same line as the name. */
.plant-title-row{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;}
.plant-title-row h1{margin:0;min-width:0;}
.fav-heart-inline{
  /* relative, not static. The @media(hover:none) rule above gives every heart
     a ::before that is position:absolute, inset 3px on all four sides, to draw
     the pale circle behind the glyph. An absolutely positioned box resolves
     against its nearest positioned ancestor, and for a card heart that is the
     button itself, which is position:absolute. This one leaves the corner of a
     photo to sit in the title row's flow, and as static it was no longer an
     ancestor anything could resolve against: the circle went looking up the
     tree, found the page, and drew itself at 384x838 with a 50% radius - a
     white ellipse at 78% opacity across the breadcrumb, the search box, the
     photo and the title, on every touch screen and nowhere else, since no
     ::before exists where there is hover.

     relative lays the button out exactly as static does and makes it the
     containing block again. top and right are reset because the base rule sets
     them for the absolute case, where they place the heart in a photo corner;
     on a relative box they would shift it 8px down and 8px left instead. */
  position:relative;top:auto;right:auto;
  flex:none;opacity:1;background:#fff;
  border:1px solid var(--green-100);
}
.fav-heart-inline.is-on{border-color:var(--green-700);}

/* The one-time invitation to sign in, and the line that says a save failed.
   Both sit above the page and neither blocks it. */
/* Both sit above everything, including the cookie banner at z-index 1000: a
   toast behind the banner is a toast nobody reads. The bottom offset is set
   by assets/favorites.js, which measures whatever is already down there. */
.fav-nudge,.fav-toast{
  position:fixed;left:50%;bottom:24px;transform:translate(-50%,10px);z-index:1100;
  display:flex;align-items:center;gap:12px;max-width:min(460px,calc(100% - 24px));
  padding:12px 14px 12px 18px;border-radius:999px;
  background:var(--green-900);color:#fff;font-size:.92rem;line-height:1.35;
  box-shadow:0 10px 30px rgba(27,58,43,.28);
  opacity:0;transition:opacity .2s ease,transform .2s ease;
}
.fav-nudge.is-on,.fav-toast.is-on{opacity:1;transform:translate(-50%,0);}
.fav-nudge a{color:#fff;font-weight:700;text-decoration:underline;flex:none;}
.fav-nudge-x{
  flex:none;width:28px;height:28px;display:flex;align-items:center;justify-content:center;
  border:0;border-radius:50%;background:rgba(255,255,255,.14);color:#fff;cursor:pointer;padding:0;
}
.fav-nudge-x:hover{background:rgba(255,255,255,.26);}
.fav-nudge-x:focus-visible,.fav-nudge a:focus-visible{outline:3px solid #e8a93c;outline-offset:2px;}
.fav-toast{padding:12px 20px;}

/* Standing on the Favorites page while signed out, and not dismissible: where
   the list is kept is not a one-off announcement. Quiet, because it is a fact
   about the page rather than a warning about it. */
.fav-device-only{
  display:flex;align-items:center;gap:9px;flex-wrap:wrap;
  margin:0 0 20px;padding:11px 15px;
  background:var(--green-100);border-radius:12px;
  color:#44584c;font-size:.92rem;line-height:1.45;
}
.fav-device-only svg{flex:none;color:var(--green-700);}
.fav-device-only a{color:var(--green-700);font-weight:700;text-decoration:underline;}
.fav-device-only a:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;border-radius:4px;}
#fav-device-notice[hidden]{display:none;}

/* --- the page ------------------------------------------------------------ */
.fav-page{max-width:980px;padding-bottom:70px;}
.fav-h1{margin:10px 0 6px;color:var(--green-900);}
.fav-intro{margin:0 0 22px;color:#6c7c72;}
.fav-tabs{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:22px;}
.fav-tab{
  min-height:44px;padding:0 18px;border:1px solid var(--sit-border);border-radius:999px;
  background:#fff;color:var(--green-900);font:inherit;font-weight:700;cursor:pointer;
}
.fav-tab:hover{background:var(--green-100);}
.fav-tab:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.fav-tab.is-on{background:var(--green-700);border-color:var(--green-700);color:#fff;}
.fav-panel[hidden]{display:none;}
.fav-loading{color:#8b9991;}
.fav-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:18px;}
.fav-grid[hidden]{display:none;}
.fav-card{
  position:relative;background:#fff;border:1px solid #e7ece8;border-radius:16px;
  overflow:hidden;display:flex;flex-direction:column;
}
.fav-card-link{display:flex;flex-direction:column;text-decoration:none;color:inherit;}
.fav-card-media{display:block;aspect-ratio:4/3;background:var(--green-100);overflow:hidden;}
.fav-card-media img{width:100%;height:100%;object-fit:cover;display:block;}
.fav-card-blank{display:block;width:100%;height:100%;}
.fav-card-body{display:flex;flex-direction:column;gap:2px;padding:12px 14px;}
.fav-card-body b{color:var(--green-900);font-size:.98rem;}
.fav-card-body i{color:var(--muted);font-size:.84rem;font-style:italic;}
.fav-have{
  margin:0 14px 14px;min-height:44px;border:1px solid var(--green-700);border-radius:10px;
  background:#fff;color:var(--green-900);font:inherit;font-weight:700;cursor:pointer;
}
.fav-have:hover{background:var(--green-100);}
.fav-have:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.fav-card-gone{padding:16px;gap:12px;align-items:flex-start;}
.fav-card-gone .fav-card-body b{color:#8b9991;font-weight:600;}
.fav-gone-remove{
  min-height:44px;padding:0 16px;border:1px solid var(--sit-border);border-radius:10px;
  background:#fff;color:var(--green-900);font:inherit;font-weight:700;cursor:pointer;
}
.fav-gone-remove:hover{background:var(--green-100);}
.fav-gone-remove:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.fav-empty{text-align:center;padding:40px 16px;}
.fav-empty[hidden]{display:none;}
.fav-empty-title{margin:0 0 6px;font-weight:700;color:var(--green-900);font-size:1.1rem;}
.fav-empty-text{margin:0 0 18px;color:#6c7c72;}
@media(prefers-reduced-motion:reduce){
  .fav-heart,.fav-nudge,.fav-toast{transition:none;}
  .fav-heart:hover{transform:none;}
}

/* 1. The picker input sat inside .mp-combo, which stretched to the form width
   while the input kept the browser's default size: 221px against 232px for the
   nickname field and the button beside it. The wrapper is the one that
   stretches, so the input has to fill it. The dropdown is positioned to the
   wrapper's edges and so matches automatically. */
.mp-combo{width:100%;}
.mp-combo input{width:100%;}

/* 4. The share link is around 100 characters. Beside a Copy button it had
   132px to show them in, which is not a readable link. Below 560px the two
   stack, so the field gets the full width and the button sits under it. The
   row never overflowed the page, but it was unusable. */
@media(max-width:560px){
  #mp-share-link-row{flex-direction:column;align-items:stretch;gap:8px;}
  #mp-share-link{width:100%;}
  #mp-share-copy{align-self:flex-start;min-height:44px;}
}

/* --- Messages --------------------------------------------------------------
   Three columns on a desktop, one at a time on a phone. Same markup both ways:
   .is-thread-open on the shell says which pane a phone is showing. */
.msg-page{
  max-width:var(--page-max);margin:0 auto;padding:0 20px 16px;
  height:calc(100svh - var(--header-h));
  display:flex;flex-direction:column;
}
/* The inbox owns the viewport: the panels scroll, the document does not. */
body:has(#msg-page){overflow:hidden;}
.msg-signin{padding:40px 0;font-size:1.05rem;}
.msg-shell{
  display:grid;grid-template-columns:320px minmax(0,1fr) 260px;gap:16px;
  /* Grows into whatever the flex column leaves, so the page itself never
     scrolls: each panel scrolls inside its own box and the reply box stays put
     at the bottom of the thread. min-height:0 is what lets a grid item shrink
     below its content and hand the overflow to the panels. */
  flex:1;min-height:0;margin-top:16px;
}
.msg-shell[hidden]{display:none;}
.msg-list-pane,.msg-thread-pane,.msg-side-pane{
  background:#fff;border:1px solid var(--green-100);border-radius:14px;
  display:flex;flex-direction:column;min-height:0;overflow:hidden;
}
.msg-side-pane{background:none;border:0;gap:12px;overflow-y:auto;}

/* Tabs */
.msg-tabs{display:flex;gap:2px;padding:8px;border-bottom:1px solid var(--green-100);flex:none;}
.msg-tab{
  flex:none;padding:7px 11px;border:0;border-radius:999px;background:none;cursor:pointer;
  font:inherit;font-size:.86rem;font-weight:600;color:var(--text-muted,#566b5e);white-space:nowrap;
}
.msg-tab:hover{background:var(--green-100);}
.msg-tab.is-active{background:var(--green-700);color:#fff;}
.msg-tab:focus-visible{outline:3px solid #e8a93c;outline-offset:2px;}

/* Conversation rows */
.msg-list{list-style:none;margin:0;padding:6px;overflow-y:auto;flex:1;min-height:0;}
.msg-row{
  width:100%;display:flex;align-items:center;gap:10px;
  padding:10px;border:0;border-radius:10px;background:none;cursor:pointer;
  font:inherit;text-align:left;
}
.msg-row:hover{background:var(--green-100);}
.msg-row.is-open{background:var(--green-100);box-shadow:inset 3px 0 0 var(--green-700);}
.msg-row:focus-visible{outline:3px solid #e8a93c;outline-offset:-2px;}
.msg-row-photo{width:48px;height:48px;flex:none;object-fit:cover;border-radius:8px;}
/* No photo on the listing snapshot: a plant mark in the site green on the
   pale green, rather than an empty square that reads as a failed image.
   .is-brand is the same treatment for the built-in welcome, whose picture is
   the leaf-book mark rather than any listing's photo. */
.msg-row-photo.is-blank,.msg-row-photo.is-brand{
  background:var(--green-100);border-radius:8px;color:var(--green-700);
  display:flex;align-items:center;justify-content:center;
}
.msg-row-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;}
.msg-row-top{display:flex;align-items:baseline;gap:8px;}
.msg-row-title{flex:1;min-width:0;color:var(--green-900);font-size:.92rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.msg-row-date{flex:none;font-size:.74rem;color:var(--text-muted,#566b5e);}
.msg-row-name{font-size:.8rem;color:var(--green-700);}
.msg-row-preview{
  font-size:.82rem;color:var(--text-muted,#566b5e);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.msg-row.is-unread .msg-row-title,.msg-row.is-unread .msg-row-preview{font-weight:700;color:var(--green-900);}
.msg-dot{flex:none;width:9px;height:9px;border-radius:50%;background:var(--green-700);}
.msg-empty{padding:28px 16px;text-align:center;color:var(--text-muted,#566b5e);}

/* Thread */
.msg-back{display:none;margin:10px 12px 0;align-self:flex-start;}
.msg-thread-head{display:none;}
.msg-thread{flex:1;min-height:0;overflow-y:auto;padding:14px;display:flex;flex-direction:column;gap:8px;}
.msg-placeholder{margin:auto;padding:20px;color:var(--text-muted,#566b5e);text-align:center;}
.msg-day{display:flex;align-items:center;gap:10px;margin:10px 0 4px;color:var(--text-muted,#566b5e);font-size:.76rem;}
.msg-day::before,.msg-day::after{content:'';flex:1;height:1px;background:var(--green-100);}
.msg-bubble{
  align-self:flex-start;max-width:min(78%,520px);
  padding:8px 12px;border-radius:14px 14px 14px 4px;
  background:#f1f5f0;border:1px solid var(--green-100);
}
.msg-bubble.is-mine{align-self:flex-end;border-radius:14px 14px 4px 14px;background:var(--green-100);border-color:var(--green-300);}
.msg-bubble p{margin:0;line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere;}
.msg-bubble time{display:block;margin-top:3px;font-size:.7rem;color:var(--text-muted,#566b5e);text-align:right;}

/* The built-in welcome: one bubble, but a short letter rather than a line of
   chat, so it gets the paragraph spacing and the real list that a chat bubble
   deliberately suppresses. Cream on the site green, to read as the site
   talking rather than as another person. */
.msg-bubble.is-welcome{
  align-self:stretch;max-width:min(94%,560px);
  background:var(--cream);border-color:var(--green-300);border-radius:14px;
  padding:14px 16px;
}
.msg-bubble.is-welcome p+p,.msg-bubble.is-welcome ul+p{margin-top:9px;}
.msg-welcome-title{font-weight:700;font-size:1.04rem;color:var(--green-900);}
.msg-welcome-list{
  margin:8px 0 0;padding-left:20px;
  display:flex;flex-direction:column;gap:5px;line-height:1.5;
}
.msg-bubble.is-welcome a{color:var(--green-700);font-weight:600;overflow-wrap:anywhere;}
/* The side card's avatar holds the leaf-book mark instead of an initial, so
   it drops the letter sizing and lets the SVG inherit the white. */
.msg-avatar.is-brand{font-size:0;}
.msg-reply{display:flex;gap:8px;padding:10px;border-top:1px solid var(--green-100);flex:none;}
/* display:flex here beats the browser's own [hidden]{display:none}, so the
   form stayed on screen whenever the script hid it: before any conversation
   was opened, and on the welcome, which has nobody to reply to. */
.msg-reply[hidden]{display:none;}
.msg-reply textarea{
  flex:1;min-width:0;padding:9px 12px;border:1px solid var(--green-300);
  border-radius:10px;font:inherit;font-size:.95rem;resize:none;
}
.msg-reply textarea:focus-visible{outline:3px solid #e8a93c;outline-offset:1px;}
.msg-reply button{flex:none;}

/* Right panel */
.msg-side-card{background:#fff;border:1px solid var(--green-100);border-radius:14px;padding:14px;display:flex;flex-direction:column;gap:6px;align-items:flex-start;}
.msg-side-card h2{margin:0 0 4px;font-size:.84rem;text-transform:uppercase;letter-spacing:.04em;color:var(--text-muted,#566b5e);}
.msg-side-card img{width:100%;height:auto;border-radius:10px;}
.msg-side-card b{color:var(--green-900);}
.msg-avatar{
  width:44px;height:44px;border-radius:50%;background:var(--green-700);color:#fff;
  display:flex;align-items:center;justify-content:center;font-weight:700;font-size:1.1rem;
}
.msg-since{font-size:.82rem;color:var(--text-muted,#566b5e);}

/* The bell */
.msg-bell-wrap{position:relative;display:flex;}
.msg-badge{
  position:absolute;top:0;right:0;min-width:17px;height:17px;padding:0 4px;
  border-radius:999px;background:#a1442f;color:#fff;border:2px solid #fff;
  font-size:.64rem;font-weight:700;line-height:13px;text-align:center;
}
.msg-badge[hidden]{display:none;}
.msg-bell-menu{
  position:absolute;top:calc(100% + 8px);right:0;z-index:70;width:min(320px,calc(100vw - 24px));
  background:#fff;border:1px solid var(--green-100);border-radius:14px;
  box-shadow:0 12px 34px rgba(16,40,26,.16);overflow:hidden;
}
/* Narrow screens: the bell sits near the middle of the row, so anchoring the
   menu to it put the left edge at -80px. Pinned to the viewport instead, with
   the same 8px margin the header uses. */
@media(max-width:560px){
  .msg-bell-menu{
    position:fixed;top:calc(var(--header-h) + 6px);left:8px;right:8px;width:auto;
    max-height:calc(100vh - var(--header-h) - 20px);overflow-y:auto;
  }
}
.msg-bell-menu[hidden]{display:none;}
.msg-bell-head{
  display:flex;flex-direction:column;align-items:flex-start;gap:4px;
  padding:11px 14px;border-bottom:1px solid var(--green-100);
}
.msg-bell-head b{font-size:.92rem;color:var(--green-900);}
.msg-bell-head .link-btn{font-size:.84rem;padding:0;min-height:0;}
.msg-bell-item{display:flex;flex-direction:column;gap:2px;padding:10px 14px;border-bottom:1px solid var(--green-100);text-decoration:none;}
.msg-bell-item:hover{background:var(--green-100);}
.msg-bell-item b{color:var(--green-900);font-size:.9rem;}
.msg-bell-listing{font-size:.78rem;color:var(--green-700);}
.msg-bell-preview{font-size:.8rem;color:var(--text-muted,#566b5e);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.msg-bell-none{margin:0;padding:18px 14px;text-align:center;color:var(--text-muted,#566b5e);font-size:.9rem;}
.msg-bell-all{display:block;padding:11px 14px;text-align:center;font-weight:600;color:var(--green-700);text-decoration:none;}
.msg-bell-all:hover{background:var(--green-100);}

/* Phone: one pane at a time. */
@media(max-width:880px){
  .msg-page{padding:0 12px 30px;}
  .msg-shell{grid-template-columns:1fr;height:calc(100vh - var(--header-h) - 30px);}
  .msg-thread-pane,.msg-side-pane{display:none;}
  .msg-shell.is-thread-open .msg-list-pane{display:none;}
  .msg-shell.is-thread-open .msg-thread-pane{display:flex;}
  .msg-back{display:inline-flex;min-height:44px;align-items:center;}
  /* The right panel becomes a strip above the thread rather than vanishing. */
  .msg-shell.is-thread-open .msg-thread-head{
    display:flex;flex-direction:column;gap:2px;
    padding:8px 14px 10px;border-bottom:1px solid var(--green-100);
  }
  .msg-thread-head b{color:var(--green-900);font-size:.95rem;}
  .msg-thread-head span{font-size:.82rem;color:var(--green-700);}
  .msg-tab{min-height:44px;}
  .msg-row{min-height:44px;}
}

/* ===========================================================================
   Plant Sitters: the board and the four-step publish flow.

   Tokens only, no new colours: --green-900 for ink, --green-700 for primary
   buttons, --green-100 for the tint, --cream for the page, and one border
   colour the design uses on cards and inputs.
   =========================================================================== */
:root{ --sit-border:#e0e9de; }
.sit-body{background:var(--cream);}

/* --- hero ---------------------------------------------------------------- */
/* The same photograph as the homepage and the marketplace, through the same
   .hero-media rule and the same renderHeroMedia() in scripts/build.js. There
   is no sitters-hero-*.jpg in assets/hero/ and there should not be: the
   helper falls back to the home artwork, which is how the marketplace has
   been getting it all along.
   Deliberately NOT overflow:hidden, unlike the other two. The place
   suggestions and the calendar open out of the search card and would be
   clipped at the hero's bottom edge; the picture is inset:0 with
   object-fit:cover, so it has nothing to overflow with anyway.
   Deliberately NOT isolation:isolate either: that would trap those same
   popovers in the hero's stacking context, under the results below. */
.sit-hero{padding:54px 0 46px;text-align:center;}
.sit-hero:not(.has-media){background:var(--green-100);}
.sit-hero.has-media{position:relative;}
.sit-hero.has-media > .container{position:relative;z-index:2;}
/* The marketplace's framing, because it is the same frame at a similar
   height. */
.sit-hero-media img{object-position:50% 58%;}
/* The marketplace scrim: the same two gradients, peaking at the same .93,
   with the horizontal one mirrored about the centre because this hero's text
   is centred rather than left-aligned. A left-weighted veil would have left
   the right half of a centred headline on bare photograph.
   Anchored in px from the centre, not in percentages, so the veil stays the
   width of the text column instead of tracking the viewport and bleaching the
   planted edges on a wide screen. The vertical gradient is copied unchanged:
   it is what lands the hero on the cream page below without a seam.
   Measured against the marketplace at 1280 in German, worst pixel behind each
   element: title 10.3:1 here against 9.0:1 there. The subtitle reads 5.4:1
   against the marketplace's 6.0:1, and that gap is the type colour, not the
   scrim: --green-700 on flat cream with no photograph at all tops out at
   6.04:1, so the photograph is costing this subtitle 0.7 where it costs the
   marketplace's darker #42544a a full 1.6. Both clear AA. */
.sit-hero.has-media::after{
  content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    linear-gradient(90deg,
      rgba(250,248,242,0)   calc(50% - 600px),
      rgba(250,248,242,.55) calc(50% - 500px),
      rgba(250,248,242,.93) calc(50% - 380px),
      rgba(250,248,242,.93) calc(50% + 380px),
      rgba(250,248,242,.55) calc(50% + 500px),
      rgba(250,248,242,0)   calc(50% + 600px)),
    linear-gradient(180deg, rgba(250,248,242,.10) 0%, rgba(250,248,242,0) 28%,
      rgba(250,248,242,.28) 82%, rgba(250,248,242,.84) 96%, rgba(250,248,242,1) 100%);
}
.sit-hero-title{
  /* 24ch breaks the French title after "mains", which is the two-line shape
     the design shows. 17ch gave four lines. */
  margin:0 auto;max-width:24ch;
  font-size:clamp(2rem,4.4vw,3.2rem);line-height:1.12;color:var(--green-900);
  /* This rule never said either of these, so the h1 defaults applied: weight
     700 against the 800 the other two hero titles carry, and letter-spacing
     normal against their -0.02em. Same family throughout, so what read as a
     different typeface was a lighter weight set 0.96px looser. */
  font-weight:800;letter-spacing:-0.02em;
}
.sit-hero-sub{
  margin:18px auto 0;max-width:62ch;
  color:var(--green-700);font-size:clamp(1rem,1.6vw,1.12rem);line-height:1.55;
}

/* One toggle, two sides. A pill inside a pill, the active half filled. */
.sit-modes{
  display:inline-flex;gap:4px;margin:26px auto 0;padding:5px;
  background:#fff;border:1px solid var(--sit-border);border-radius:999px;
  max-width:100%;
}
.sit-mode{
  flex:0 1 auto;min-height:44px;padding:9px 20px;border:0;border-radius:999px;
  background:none;color:var(--green-900);font:inherit;font-weight:700;font-size:.95rem;
  cursor:pointer;white-space:nowrap;transition:background .16s,color .16s;
}
.sit-mode:hover{background:var(--green-100);}
.sit-mode.is-active{background:var(--green-900);color:#fff;}
.sit-mode:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.sit-mode-short{display:none;}

/* Search card */
.sit-search{
  display:flex;align-items:center;gap:8px;margin:22px auto 0;max-width:940px;
  background:#fff;border:1px solid var(--sit-border);border-radius:999px;
  padding:8px 8px 8px 20px;box-shadow:0 10px 30px rgba(27,58,43,.08);
  text-align:left;
}
.sit-search-field{display:flex;align-items:center;gap:12px;flex:1;min-width:0;position:relative;}
.sit-search .sit-ico{flex:none;color:var(--green-700);}
.sit-search-text{display:flex;flex-direction:column;min-width:0;flex:1;}
.sit-search-text label,.sit-search-label{
  font-size:.74rem;font-weight:700;color:var(--green-900);line-height:1.2;
}
.sit-search-text input{
  border:0;background:none;padding:2px 0 0;font:inherit;font-size:.98rem;color:var(--text);
  min-width:0;width:100%;
}
.sit-search-text input:focus{outline:none;}
.sit-search-text input::placeholder{color:#8b9991;}
.sit-when-btn{
  border:0;background:none;padding:2px 0 0;font:inherit;font-size:.98rem;
  color:#8b9991;text-align:left;cursor:pointer;
}
.sit-when-btn:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;border-radius:6px;}
.sit-search-sep{width:1px;align-self:stretch;margin:4px 0;background:var(--sit-border);flex:none;}
.sit-search-btn{
  flex:none;display:inline-flex;align-items:center;gap:8px;min-height:48px;
  padding:0 22px;border:0;border-radius:999px;
  background:var(--green-700);color:#fff;font:inherit;font-weight:700;cursor:pointer;
}
.sit-search-btn:hover{background:var(--green-900);}
.sit-search-btn:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.sit-cal-pop{
  position:absolute;top:calc(100% + 14px);left:-12px;z-index:60;
  background:#fff;border:1px solid var(--sit-border);border-radius:16px;
  box-shadow:0 16px 40px rgba(27,58,43,.16);padding:10px;min-width:300px;
}
.sit-cal-pop[hidden]{display:none;}
.sit-cal-foot{display:flex;justify-content:flex-end;padding:4px 6px 2px;}

/* --- results ------------------------------------------------------------- */
.sit-results{padding-top:34px;}
.sit-results-head{
  display:flex;align-items:flex-start;justify-content:space-between;gap:20px;flex-wrap:wrap;
}
.sit-results-title{margin:0;font-size:clamp(1.5rem,2.6vw,2rem);color:var(--green-900);}
.sit-results-count{margin:5px 0 0;color:var(--muted);font-size:.92rem;}
.sit-publish-btn{
  display:inline-flex;align-items:center;gap:8px;min-height:48px;padding:0 22px;
  border-radius:999px;background:var(--green-700);color:#fff;border:0;
  font:inherit;font-weight:700;text-decoration:none;cursor:pointer;
}
.sit-publish-btn:hover{background:var(--green-900);color:#fff;}
.sit-publish-btn:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}

.sit-filters{display:flex;align-items:center;gap:10px;margin:22px 0 18px;flex-wrap:wrap;}
.sit-filter{
  position:relative;display:inline-flex;align-items:center;gap:6px;min-height:44px;
  padding:0 16px;border:1px solid var(--sit-border);border-radius:999px;background:#fff;
  color:var(--green-900);font:inherit;font-size:.92rem;font-weight:600;cursor:pointer;
}
.sit-filter:hover{border-color:var(--green-500);}
.sit-filter:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.sit-filter.is-on{background:var(--green-100);border-color:var(--green-300);}
.sit-filter .sit-ico{width:16px;height:16px;}
.sit-filter-group{position:relative;}
.sit-filter-menu{
  position:absolute;top:calc(100% + 6px);left:0;z-index:50;min-width:210px;
  background:#fff;border:1px solid var(--sit-border);border-radius:14px;padding:6px;
  box-shadow:0 14px 34px rgba(27,58,43,.14);display:flex;flex-direction:column;
}
.sit-filter-menu[hidden]{display:none;}
.sit-filter-opt{
  min-height:44px;padding:0 12px;border:0;border-radius:9px;background:none;
  color:var(--green-900);font:inherit;font-size:.93rem;text-align:left;cursor:pointer;
}
.sit-filter-opt:hover{background:var(--green-100);}
.sit-filter-opt.is-on{background:var(--green-700);color:#fff;}
.sit-filter-sheet-btn{display:none;}
.sit-sort{
  margin-left:auto;display:inline-flex;align-items:center;gap:6px;
  color:var(--green-900);font-size:.92rem;font-weight:600;
}
.sit-sort .sit-ico{width:16px;height:16px;}

/* Cards */
.sit-grid{
  list-style:none;margin:0;padding:0;display:grid;gap:22px;
  grid-template-columns:repeat(auto-fill,minmax(300px,1fr));
}
.sit-grid[hidden]{display:none;}
/* No overflow:hidden here. It used to be, to round the photo's top corners,
   and it clipped the 3-dots menu to the card. The photo rounds its own two
   corners instead, so nothing above the card has to be cut off. */
.sit-card{
  position:relative;
  display:flex;flex-direction:column;background:#fff;
  border:1px solid var(--sit-border);border-radius:16px;
}
.sit-card-photo{
  display:block;width:100%;aspect-ratio:16/10;object-fit:cover;background:var(--green-100);
  border-radius:15px 15px 0 0;
}
/* No photograph: the illustration fills the same tile a real photo would,
   so the card keeps one shape either way and the title stays where the eye
   expects it. The source is 1200x755, within a hair of 16/10, so cover
   crops almost nothing - and what it does crop is the empty margin, not
   the plant, the dividing line or the logo, which is what centring is for. */
.sit-card-photo.is-placeholder{object-position:center;}
.sit-card-body{display:flex;flex-direction:column;gap:10px;padding:16px 18px 14px;flex:1;}
.sit-card-title{margin:0;font-size:1.04rem;line-height:1.3;color:var(--green-900);}
.sit-card-meta{
  display:flex;flex-wrap:wrap;gap:6px 16px;margin:0;
  color:#6c7c72;font-size:.88rem;
}
.sit-card-meta span{display:inline-flex;align-items:center;gap:5px;}
.sit-card-chips{display:flex;flex-wrap:wrap;gap:8px;margin:0;}
.sit-chip{
  display:inline-block;padding:5px 12px;border-radius:999px;
  background:var(--green-100);color:var(--green-700);font-size:.82rem;font-weight:600;
}
.sit-card-foot{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  margin-top:auto;padding-top:13px;border-top:1px solid var(--sit-border);
}
.sit-card-who{display:flex;align-items:center;gap:10px;min-width:0;}
.sit-avatar{
  flex:none;width:36px;height:36px;border-radius:50%;background:var(--green-700);color:#fff;
  display:flex;align-items:center;justify-content:center;font-weight:700;font-size:.95rem;
}
.sit-who-text{display:flex;flex-direction:column;min-width:0;}
.sit-who-text b{color:var(--green-900);font-size:.92rem;}
.sit-since{color:var(--muted);font-size:.78rem;line-height:1.25;}
.sit-card-actions{display:flex;align-items:center;gap:4px;flex:none;}
.sit-contact{
  display:inline-flex;align-items:center;gap:7px;min-height:44px;padding:0 16px;
  border:1.5px solid var(--green-700);border-radius:999px;background:#fff;
  color:var(--green-700);font:inherit;font-size:.9rem;font-weight:700;cursor:pointer;
}
.sit-contact:hover{background:var(--green-100);}
.sit-contact:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.sit-kebab-wrap{position:relative;}
.sit-kebab{
  width:44px;height:44px;display:flex;align-items:center;justify-content:center;
  border:0;border-radius:50%;background:none;color:var(--muted);cursor:pointer;
}
.sit-kebab:hover{background:var(--green-100);color:var(--green-900);}
.sit-kebab:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
/* One menu, moved to the end of <body> and positioned against the viewport,
   so it is never a child of the card and cannot be clipped by it. It flips
   above the button when there is not room below. */
.sit-menu{
  position:fixed;z-index:95;min-width:210px;
  background:#fff;border:1px solid var(--sit-border);border-radius:12px;padding:6px;
  box-shadow:0 16px 40px rgba(27,58,43,.18);
}
.sit-menu[hidden]{display:none;}
.sit-menu button,.sit-menu .listing-report-btn{
  display:flex;align-items:center;gap:9px;width:100%;min-height:44px;
  padding:0 12px;border:0;border-radius:9px;background:none;
  color:var(--green-900);font:inherit;font-size:.94rem;text-align:left;cursor:pointer;
}
.sit-menu button:hover,.sit-menu .listing-report-btn:hover{background:var(--green-100);}
.sit-menu button:focus-visible,.sit-menu .listing-report-btn:focus-visible{
  outline:3px solid var(--green-500);outline-offset:-2px;
}
/* On a phone the same menu becomes a bottom sheet. */
.sit-menu.is-sheet{
  left:0;right:0;bottom:0;top:auto;width:auto;min-width:0;
  border-radius:20px 20px 0 0;padding:8px 12px calc(14px + env(safe-area-inset-bottom));
  box-shadow:0 -12px 40px rgba(27,58,43,.24);
}
.sit-menu.is-sheet::before{
  content:'';display:block;width:44px;height:5px;border-radius:999px;
  background:var(--green-300);margin:4px auto 10px;
}
.sit-menu-backdrop{position:fixed;inset:0;z-index:94;background:rgba(27,58,43,.35);}
.sit-menu-backdrop[hidden]{display:none;}

.sit-status{margin:24px 0;color:#8a5a2b;text-align:center;}
.sit-empty{
  margin:10px 0 0;padding:46px 24px;text-align:center;
  background:#fff;border:1px solid var(--sit-border);border-radius:16px;
}
.sit-empty[hidden]{display:none;}
/* Capped and centred. The copy used to be short enough that the full width
   of the card did not matter; the longer wording set the German text as one
   1150px line at 1280, which is a line nobody reads to the end of. Same caps
   as the marketplace's empty state, so the two read alike. */
.sit-empty-title{
  margin:0 auto;max-width:34ch;
  font-size:1.12rem;font-weight:700;color:var(--green-900);
}
.sit-empty-text{margin:8px auto 20px;max-width:52ch;color:#6c7c72;line-height:1.5;}
.sit-more-wrap{display:flex;justify-content:center;margin:30px 0 8px;}
.sit-more,.sit-more-link{
  min-height:48px;padding:0 26px;display:inline-flex;align-items:center;
  border:1px solid var(--sit-border);border-radius:999px;background:#fff;
  color:var(--green-900);font:inherit;font-weight:700;cursor:pointer;text-decoration:none;
}
.sit-more:hover,.sit-more-link:hover{border-color:var(--green-500);}
.sit-more:focus-visible,.sit-more-link:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.sit-more[hidden],.sit-more-link[hidden]{display:none;}

/* --- safety --------------------------------------------------------------- */
.sit-safe{
  display:grid;grid-template-columns:minmax(220px,1fr) 2.2fr;gap:34px;
  margin:46px 0 0;padding:34px 36px;background:#fff;
  border:1px solid var(--sit-border);border-radius:20px;
}
.sit-safe-icon{
  display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;
  border-radius:12px;background:var(--green-100);color:var(--green-700);margin-bottom:14px;
}
.sit-safe-intro h2{margin:0 0 10px;font-size:1.5rem;color:var(--green-900);line-height:1.2;}
.sit-safe-intro p{margin:0;color:#6c7c72;line-height:1.6;}
.sit-safe-items{display:grid;grid-template-columns:repeat(3,1fr);gap:26px;}
.sit-safe-item h3{margin:0 0 7px;font-size:.98rem;color:var(--green-900);}
.sit-safe-item p{margin:0;color:#6c7c72;font-size:.92rem;line-height:1.55;}

/* --- closing call to action ----------------------------------------------- */
.sit-cta{
  display:flex;align-items:center;justify-content:space-between;gap:30px;flex-wrap:wrap;
  margin:26px 0 56px;padding:40px 44px;border-radius:20px;background:var(--green-900);
}
.sit-cta-text h2{margin:0 0 10px;color:#fff;font-size:clamp(1.4rem,2.5vw,1.95rem);line-height:1.2;max-width:22ch;}
.sit-cta-text p{margin:0;color:rgba(255,255,255,.84);line-height:1.6;max-width:60ch;}
.sit-cta-btn{
  flex:none;min-height:50px;padding:0 28px;display:inline-flex;align-items:center;
  border-radius:999px;background:#fff;color:var(--green-900);
  font-weight:700;text-decoration:none;
}
.sit-cta-btn:hover{background:var(--green-100);color:var(--green-900);}
.sit-cta-btn:focus-visible{outline:3px solid #fff;outline-offset:3px;}

/* --- phone bottom bar and filter sheet ------------------------------------ */
.sit-bottombar{display:none;}
.sit-sheet-backdrop{position:fixed;inset:0;z-index:90;background:rgba(27,58,43,.45);}
.sit-sheet-backdrop[hidden]{display:none;}
.sit-sheet{
  position:fixed;left:0;right:0;bottom:0;z-index:91;max-height:80svh;
  display:flex;flex-direction:column;background:var(--cream);
  border-radius:22px 22px 0 0;box-shadow:0 -12px 40px rgba(27,58,43,.24);
  padding-bottom:env(safe-area-inset-bottom);
}
.sit-sheet[hidden]{display:none;}
.sit-sheet-handle{width:44px;height:5px;border-radius:999px;background:var(--green-300);margin:10px auto 2px;flex:none;}
.sit-sheet-head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:6px 18px 10px;}
.sit-sheet-head h2{margin:0;font-size:1.05rem;color:var(--green-900);}
.sit-sheet-close{
  width:44px;height:44px;flex:none;display:flex;align-items:center;justify-content:center;
  border:0;border-radius:50%;background:var(--green-100);color:var(--green-700);cursor:pointer;
}
.sit-sheet-close:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.sit-sheet-body{padding:4px 18px 10px;overflow-y:auto;flex:1;min-height:0;}
.sit-sheet-group h3{margin:12px 0 10px;font-size:.92rem;color:var(--green-900);}
.sit-sheet-opts{display:flex;flex-wrap:wrap;gap:8px;}
.sit-sheet-opt{
  min-height:44px;padding:0 16px;border:1px solid var(--sit-border);border-radius:999px;
  background:#fff;color:var(--green-900);font:inherit;font-size:.92rem;cursor:pointer;
}
.sit-sheet-opt.is-on{background:var(--green-700);border-color:var(--green-700);color:#fff;}
.sit-sheet-foot{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:12px 18px 16px;border-top:1px solid var(--sit-border);flex:none;
}
.sit-sheet-apply{
  min-height:48px;padding:0 24px;border:0;border-radius:999px;
  background:var(--green-700);color:#fff;font:inherit;font-weight:700;cursor:pointer;
}

@media(max-width:900px){
  .sit-safe{grid-template-columns:1fr;gap:24px;padding:26px 22px;}
  .sit-safe-items{grid-template-columns:1fr;gap:18px;}
}
@media(max-width:760px){
  .sit-hero{padding:34px 0 30px;}
  /* The desktop scrim veils a band 760px wide about the centre, because there
     the text sits in a column inside a much wider frame. On a phone that band
     is wider than the screen, so every pixel of the hero sat at .93 and the
     photograph was washed out to almost nothing: the picture was there and
     could not be seen. The same answer the homepage reached at this width, in
     the same shape: no horizontal term at all, strong through the band the
     text occupies, a clear strip of photograph above the headline, and the
     picture coming back below the search card before the hero lands on the
     cream page. */
  .sit-hero.has-media::after{
    background:linear-gradient(180deg,
      rgba(250,248,242,.20) 0%,  rgba(250,248,242,.46) 5%,
      rgba(250,248,242,.90) 11%, rgba(250,248,242,.90) 50%,
      rgba(250,248,242,.44) 68%, rgba(250,248,242,.30) 84%,
      rgba(250,248,242,.86) 96%, rgba(250,248,242,1) 100%);
  }
  .sit-modes{width:100%;display:flex;}
  /* white-space:normal, overriding the nowrap the desktop pill sets. These
     two labels are shared with the publish form's step 1 cards, which have a
     whole card to set them in; here they are two buttons sharing 335px. At
     the longest, French, they asked for 368px on one line and the row ran off
     the screen. Wrapping is what a button that cannot be narrower should do,
     and line-height keeps two lines inside the pill. */
  .sit-mode{
    flex:1 1 0;padding:9px 10px;font-size:.9rem;
    white-space:normal;line-height:1.25;
  }
  .sit-mode-long{display:none;}
  .sit-mode-short{display:inline;}
  .sit-search{
    flex-direction:column;align-items:stretch;gap:0;border-radius:20px;padding:6px 16px 14px;
  }
  .sit-search-field{padding:12px 0;}
  .sit-search-sep{width:auto;height:1px;align-self:stretch;margin:0;}
  .sit-search-btn{width:100%;justify-content:center;margin-top:10px;}
  .sit-cal-pop{left:0;right:0;min-width:0;}
  .sit-results-head .sit-publish-btn{display:none;}
  .sit-filter-group{display:none;}
  .sit-filter-sheet-btn{display:inline-flex;}
  .sit-grid{grid-template-columns:1fr;gap:16px;}
  .sit-cta{padding:28px 22px;margin-bottom:96px;}
  .sit-bottombar{
    display:block;position:fixed;left:0;right:0;bottom:0;z-index:70;
    padding:10px 16px calc(10px + env(safe-area-inset-bottom));
    background:#fff;border-top:1px solid var(--sit-border);
  }
  .sit-bottombar .sit-publish-btn{width:100%;justify-content:center;}
}

/* ===========================================================================
   The localized calendar (assets/wp-calendar.js)
   =========================================================================== */
.wpcal-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:6px 4px 10px;}
.wpcal-title{font-weight:700;color:var(--green-900);font-size:.98rem;}
.wpcal-nav{
  width:36px;height:36px;flex:none;display:flex;align-items:center;justify-content:center;
  border:0;border-radius:50%;background:var(--green-100);color:var(--green-700);cursor:pointer;
}
.wpcal-nav:hover{background:var(--green-300);}
.wpcal-nav:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.wpcal-week{
  display:grid;grid-template-columns:repeat(7,1fr);gap:2px;
  padding:0 0 6px;text-align:center;color:#8b9991;font-size:.78rem;font-weight:700;
}
.wpcal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;}
.wpcal-pad{display:block;}
/* 44px so a day is a comfortable target with a thumb, which it was not at 38.
   The cells stretch with the grid, so on a wide card a day is a wide pill
   rather than a small circle; the range highlight is unchanged. */
.wpcal-day{
  position:relative;min-height:44px;border:0;background:none;border-radius:999px;
  color:var(--green-900);font:inherit;font-size:.92rem;font-weight:600;cursor:pointer;
}
.wpcal-day:hover{background:var(--green-100);}
.wpcal-day:focus-visible{outline:3px solid var(--green-500);outline-offset:-2px;}
.wpcal-day.is-today{text-decoration:underline;text-underline-offset:3px;}
.wpcal-day.is-mid{background:var(--green-100);border-radius:0;}
.wpcal-day.is-start,.wpcal-day.is-end{background:var(--green-900);color:#fff;}
.wpcal-day.is-start{border-radius:999px 0 0 999px;}
.wpcal-day.is-end{border-radius:0 999px 999px 0;}
.wpcal-day.is-start.is-end{border-radius:999px;}

/* ===========================================================================
   The publish flow (assets/sitters-publish.js)
   =========================================================================== */
.pub-body{background:var(--cream);min-height:100vh;}
/* The bar itself still spans the window, because a white strip that stops
   short of the edges looks like a mistake on a cream page. What is inside it
   lines up with the form column, so "Quitter" sits above the content rather
   than out in the margin. */
.pub-topbar{
  background:#fff;border-bottom:1px solid var(--sit-border);
  position:sticky;top:0;z-index:40;
}
.pub-topbar-inner{
  max-width:1180px;margin:0 auto;padding:10px 26px;
  display:flex;align-items:center;gap:16px;
}
.pub-close{
  min-height:44px;flex:none;display:inline-flex;align-items:center;gap:8px;
  padding:0 16px 0 13px;border:1px solid var(--sit-border);border-radius:999px;
  color:var(--green-900);text-decoration:none;font-weight:700;font-size:.94rem;
}
.pub-close:hover{background:var(--green-100);color:var(--green-900);}
.pub-close:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.pub-close svg{flex:none;}
.pub-topbar-title{margin:0;font-size:1.08rem;color:var(--green-900);}

/* "Draft saved", after leaving. Sits above everything and says itself. */
.pub-toast{
  position:fixed;left:50%;bottom:26px;transform:translate(-50%,10px);z-index:80;
  display:inline-flex;align-items:center;gap:9px;
  padding:12px 20px;border-radius:999px;
  background:var(--green-900);color:#fff;font-weight:700;font-size:.94rem;
  box-shadow:0 10px 30px rgba(27,58,43,.28);
  opacity:0;transition:opacity .18s ease,transform .18s ease;
}
.pub-toast.is-on{opacity:1;transform:translate(-50%,0);}
.pub-toast[hidden]{display:none;}

/* Same container as .pub-topbar-inner and .pub-main, so the bar starts where
   "Quitter" and the heading do. It used to centre a 1180px list inside a
   padded wrapper, which left it 26px to the left of everything else. */
.pub-steps{max-width:1180px;margin:0 auto;padding:22px 26px 6px;}
.pub-steps ol{
  list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(4,1fr);gap:18px;
}
/* A finished step is a real button and says so on hover and focus. One not
   yet reached is disabled, and loses the pointer and the hover with it. */
.pub-step-btn{
  display:block;width:100%;border:0;background:none;padding:0 0 4px;
  font:inherit;text-align:left;cursor:pointer;border-radius:8px;
}
.pub-step-btn[disabled]{cursor:default;}
.pub-step-btn:not([disabled]):hover .pub-step-name{text-decoration:underline;}
.pub-step-btn:not([disabled]):hover .pub-step-dot{background:var(--green-900);}
.pub-step-btn:focus-visible{outline:3px solid var(--green-500);outline-offset:3px;}
.pub-step-bar{display:block;height:4px;border-radius:999px;background:var(--green-100);}
.pub-step.is-done .pub-step-bar,.pub-step.is-current .pub-step-bar{background:var(--green-700);}
.pub-step-row{display:flex;align-items:center;gap:9px;padding-top:10px;}
.pub-step-dot{
  width:26px;height:26px;flex:none;display:flex;align-items:center;justify-content:center;
  border-radius:50%;background:var(--green-100);color:var(--muted);font-size:.82rem;font-weight:700;
}
.pub-step.is-current .pub-step-dot{background:var(--green-900);color:#fff;}
.pub-step.is-done .pub-step-dot{background:var(--green-700);color:#fff;}
.pub-step-name{font-size:.92rem;font-weight:700;color:var(--muted);}
.pub-step.is-current .pub-step-name,.pub-step.is-done .pub-step-name{color:var(--green-900);}

.pub-main{max-width:1180px;margin:0 auto;padding:18px 26px 80px;}
.pub-panel[hidden]{display:none;}
.pub-panel-split{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(300px,.65fr);gap:46px;align-items:start;}
.pub-col{min-width:0;}
.pub-h2{margin:14px 0 8px;font-size:clamp(1.7rem,3.4vw,2.5rem);color:var(--green-900);line-height:1.15;}
.pub-h3{margin:26px 0 12px;font-size:1.05rem;color:var(--green-900);}
.pub-sub{margin:0 0 26px;color:#6c7c72;font-size:1.02rem;line-height:1.55;}

/* Two cards of equal width, side by side from 900px up. A grid rather than a
   flex row because 1fr 1fr is the equal-width part: with flex the German
   card, whose text is longest, would have taken the room the other one
   needed.
   One column is the default and the two columns are asked for, rather than
   the other way round: the breakpoint that matters is where there is room
   for two cards, which is not the same as the phone breakpoint the rest of
   this form uses (700px). Between those two it was side by side with 180px
   of card, which is narrower than the German title. */
/* No max-width. It was 860px, which made step 1 narrower than step 2's
   choices (1128px at 1280) and moved the content edge as you went from one
   step to the next. The column is the width; both steps use all of it. */
.pub-big-choices{display:grid;grid-template-columns:1fr;gap:16px;}
@media(min-width:900px){
  .pub-big-choices{grid-template-columns:1fr 1fr;}
}
.pub-big,.pub-choice{
  display:flex;align-items:center;gap:18px;width:100%;text-align:left;
  padding:20px 22px;border:1.5px solid var(--sit-border);border-radius:16px;background:#fff;
  font:inherit;cursor:pointer;transition:border-color .16s,background .16s;
}
/* Step 1's two cards read top to bottom: picture, title, then the line that
   explains it. Everything else about .pub-big is unchanged, which is what
   keeps the selected state, the tick and the focus ring working. */
.pub-big-choices .pub-big{
  flex-direction:column;align-items:center;text-align:center;gap:12px;
  padding:26px 22px 22px;position:relative;
}
/* A fixed square, the same for both, with the drawing centred inside it. The
   two files are normalised to the same visual area before they get here
   (see the note in the commit): contain alone scales to the longest side,
   which made the tall suitcase read smaller than the wide watering can in
   boxes of identical size. */
.pub-big-art{
  display:block;width:80px;height:80px;flex:none;
  object-fit:contain;object-position:center;
}
.pub-big-choices .pub-choice-text{align-items:center;flex:0 1 auto;}
/* The tick moves to the corner: in a centred column it would otherwise sit
   under the text as a third row and pull the two cards out of step whenever
   one language's description ran to a different number of lines. */
.pub-big-choices .pub-choice-mark{position:absolute;top:14px;right:14px;}
.pub-big:hover,.pub-choice:hover{border-color:var(--green-500);}
.pub-big:focus-visible,.pub-choice:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.pub-big.is-on,.pub-choice.is-on{border-color:var(--green-700);background:var(--green-100);}
/* ".pub-big-icon", a 52px tinted square holding a stroke glyph, lived here.
   Step 1 was the only thing that used it and it shows the illustrations now;
   .pub-choice in the later steps never had an icon. */
.pub-choice-text{display:flex;flex-direction:column;gap:5px;flex:1;min-width:0;}
.pub-choice-text b{color:var(--green-900);font-size:1.06rem;}
.pub-choice-text span{color:#6c7c72;font-size:.94rem;line-height:1.45;}
.pub-choice-mark{
  flex:none;width:26px;height:26px;border-radius:50%;
  border:2px solid var(--sit-border);background:#fff;
}
.pub-big.is-on .pub-choice-mark,.pub-choice.is-on .pub-choice-mark{
  border-color:var(--green-700);background:var(--green-700);
}
.pub-big.is-on .pub-choice-mark::after,.pub-choice.is-on .pub-choice-mark::after{
  content:'';display:block;width:100%;height:100%;
  background:no-repeat center/15px 15px;
  -webkit-mask:no-repeat center/15px 15px;
}
.pub-choices{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;}
.pub-choices .pub-choice{align-items:flex-start;padding:18px;}
.pub-choices .pub-choice-text b{font-size:1rem;}
/* The tick inside a chosen radio. Drawn with a border rather than an image so
   there is no encoded SVG in the stylesheet. */
.pub-choice-mark{position:relative;}
.pub-big.is-on .pub-choice-mark::before,.pub-choice.is-on .pub-choice-mark::before{
  content:'';position:absolute;left:7px;top:3px;width:6px;height:11px;
  border:solid #fff;border-width:0 2.5px 2.5px 0;transform:rotate(45deg);
}

.pub-form-card{
  background:#fff;border:1px solid var(--sit-border);border-radius:18px;
  padding:24px 26px;display:flex;flex-direction:column;gap:22px;
}
.pub-field{display:flex;flex-direction:column;gap:8px;}
.pub-field label,.pub-label{font-weight:700;color:var(--green-900);font-size:.96rem;}
.pub-optional{font-weight:400;color:#8b9991;}
.pub-field input[type=text],.pub-field textarea{
  width:100%;padding:13px 15px;border:1.5px solid var(--sit-border);border-radius:11px;
  font:inherit;font-size:1rem;color:var(--text);background:#fff;
}
.pub-field input[type=text]:focus,.pub-field textarea:focus{
  outline:none;border-color:var(--green-700);box-shadow:0 0 0 3px rgba(47,107,69,.12);
}
.pub-field textarea{resize:vertical;min-height:110px;line-height:1.55;}
/* flex, not block, so the wrapper's height IS the field's height.
   As a block it held an inline formatting context, and the newlines in the
   markup between the icon, the input and the list became anonymous inline
   boxes: a whole empty line of them, 22px tall, on top of the input. That is
   what put the pin 11px below the middle of the field - top:50% was
   centring on a box half a line taller than the one you can see - and what
   opened the suggestions 30px under the field instead of 8px.
   A flex container discards whitespace-only children outright, which is the
   whole fix; the icon and the list are position:absolute and out of flow,
   so the input is the only item left and its height is the wrapper's. */
.pub-input-icon{position:relative;display:flex;}
.pub-input-icon input[type=text]{flex:1;min-width:0;}
.pub-input-icon .sit-ico{position:absolute;left:14px;top:50%;transform:translateY(-50%);color:var(--green-700);}
/* Written to out-weigh ".pub-field input[type=text]" above, which sets
   padding:13px 15px. That selector scores 0-2-1 because of the attribute
   test, and the old ".pub-input-icon input" scored 0-1-1, so the 44px never
   applied and the text ran straight under the pin. */
.pub-field .pub-input-icon input[type=text]{padding-left:46px;}
.pub-field-foot{display:flex;justify-content:space-between;gap:14px;}
.pub-hint,.pub-counter{color:#8b9991;font-size:.84rem;}
.pub-note{display:flex;align-items:center;gap:7px;color:#6c7c72;font-size:.86rem;}
.pub-note svg{flex:none;color:var(--green-700);}
.pub-field-head{display:flex;align-items:baseline;justify-content:space-between;gap:14px;flex-wrap:wrap;}
.pub-range{color:var(--green-700);font-weight:700;font-size:.92rem;}
/* Full width of the card. It used to stop at 420px inside a card about 640px
   wide, which left a bare third of the row empty next to it. */
.pub-cal{
  border:1px solid var(--sit-border);border-radius:14px;padding:12px;background:#fff;
}

.pub-drop{
  border:2px dashed var(--green-300);border-radius:16px;background:var(--green-100);
  padding:38px 22px;text-align:center;display:flex;flex-direction:column;align-items:center;gap:8px;
}
.pub-drop.is-over{border-color:var(--green-700);background:#e3f1e6;}
.pub-drop-icon{
  width:54px;height:54px;display:flex;align-items:center;justify-content:center;
  border-radius:50%;background:#fff;color:var(--green-700);margin-bottom:6px;
}
.pub-drop-title{color:var(--green-900);font-size:1.06rem;}
.pub-drop-or{color:#6c7c72;font-size:.95rem;}
.pub-drop-choose{
  border:0;background:none;padding:0;font:inherit;font-weight:700;color:var(--green-700);
  text-decoration:underline;cursor:pointer;
}
.pub-drop-choose:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.pub-drop-formats{color:#8b9991;font-size:.86rem;}
.pub-drop-chosen{margin-top:14px;display:flex;flex-direction:column;align-items:center;gap:8px;}
.pub-drop-chosen[hidden]{display:none;}
.pub-drop-chosen img{max-width:220px;max-height:150px;border-radius:12px;object-fit:cover;}
.pub-tip{
  display:flex;align-items:flex-start;gap:10px;margin:0;padding:14px 16px;
  background:var(--green-100);border-radius:12px;color:#44584c;font-size:.92rem;line-height:1.5;
}
.pub-tip svg{flex:none;color:var(--green-700);margin-top:1px;}
.pub-terms{margin:18px 0 0;color:#6c7c72;font-size:.92rem;line-height:1.55;}
.pub-terms a{color:var(--green-700);font-weight:700;}

.pub-error{
  margin:16px 0 0;padding:12px 16px;border-radius:12px;
  background:#fdf4ec;border:1px solid #f0ddc9;color:#8a5a2b;font-size:.93rem;
}
.pub-error[hidden]{display:none;}

.pub-actions{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-top:30px;}
.pub-actions-end{display:flex;align-items:center;gap:16px;min-width:0;}
/* Step 1 has no Back button and holds its place with an empty span. Left in
   the flow it still collects a gap, which pushed the only button 12px off
   centre in the phone bar. */
.pub-actions > span:empty{display:none;}
/* Step 1's footer is step 2's footer with the Back button taken out: the
   saved-draft note and Continue together at the right edge of the column.
   flex-end rather than space-between, because with the empty span hidden
   .pub-actions-end is the only child left and space-between would park it at
   the start. Nothing else about the row changes, so the two steps line up
   their buttons on the same edge and the page does not shift between them. */
[data-panel="1"] .pub-actions{justify-content:flex-end;}

/* The autosave indicator, beside the button that moves the flow on rather
   than in the far corner of the header where nobody was looking. Two states:
   a green tick and "Enregistré" for about two seconds after a real save, then
   it settles to a quiet "Brouillon enregistré" with no tick. */
.pub-savedmark{
  display:inline-flex;align-items:center;gap:6px;min-width:0;
  font-size:.88rem;font-weight:700;color:#8b9991;
  opacity:0;transition:opacity .25s ease,color .25s ease;
}
.pub-savedmark.is-visible{opacity:1;}
.pub-savedmark.is-saved{color:var(--green-700);}
.pub-savedmark-tick{flex:none;opacity:0;transition:opacity .25s ease;}
.pub-savedmark.is-saved .pub-savedmark-tick{opacity:1;}
.pub-savedmark span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.pub-next,.pub-submit{
  display:inline-flex;align-items:center;gap:9px;min-height:50px;padding:0 30px;
  border:0;border-radius:12px;background:var(--green-700);color:#fff;
  font:inherit;font-weight:700;font-size:1rem;cursor:pointer;text-decoration:none;
}
.pub-next:hover,.pub-submit:hover{background:var(--green-900);color:#fff;}
.pub-next:focus-visible,.pub-submit:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.pub-submit[disabled]{opacity:.6;cursor:default;}
.pub-prev{
  border:0;background:none;padding:10px 2px;font:inherit;font-weight:700;
  color:var(--green-900);text-decoration:underline;cursor:pointer;min-height:44px;
}
.pub-prev:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}

.pub-preview{position:sticky;top:96px;}
.pub-preview-head{
  display:flex;align-items:center;gap:8px;margin:14px 0 12px;
  color:#6c7c72;font-size:.82rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
}
.pub-preview-card{
  background:#fff;border:1px solid var(--sit-border);border-radius:18px;overflow:hidden;
}
.pub-preview-photo{
  position:relative;aspect-ratio:16/10;background:var(--green-100);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;
  color:var(--green-700);
}
.pub-preview-photo img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;}
.pub-preview-photo.has-photo .pub-preview-leaf,
.pub-preview-photo.has-photo .pub-preview-photo-note{display:none;}
.pub-preview-photo-note{font-size:.88rem;}
.pub-preview-badge{
  position:absolute;top:12px;left:12px;z-index:2;padding:5px 12px;border-radius:999px;
  background:#fdeccd;color:#8a5a2b;font-size:.8rem;font-weight:700;
}
.pub-preview-badge[hidden]{display:none;}
.pub-preview-body{padding:16px 18px;display:flex;flex-direction:column;gap:10px;}
.pub-preview-title{color:var(--green-900);font-size:1.04rem;line-height:1.3;}
.pub-preview-meta{display:flex;flex-wrap:wrap;gap:6px 14px;margin:0;color:#6c7c72;font-size:.88rem;}
.pub-preview-meta>span{display:inline-flex;align-items:center;gap:5px;}
.pub-preview-meta .sit-ico{width:15px;height:15px;}
.pub-preview-meta>span[hidden]{display:none;}
.pub-preview-chips{display:flex;flex-wrap:wrap;gap:8px;margin:0;}
.pub-preview-who{display:flex;align-items:center;gap:10px;padding-top:12px;border-top:1px solid var(--sit-border);}
.pub-preview-avatar{
  flex:none;width:36px;height:36px;border-radius:50%;background:var(--green-700);color:#fff;
  display:flex;align-items:center;justify-content:center;font-weight:700;
}
.pub-preview-who b{display:block;color:var(--green-900);font-size:.93rem;}
.pub-preview-username{color:var(--muted);font-size:.8rem;}
.pub-preview-note{margin:12px 2px 0;color:var(--muted);font-size:.86rem;line-height:1.5;}
.pub-signin .pub-next{margin-top:10px;}

@media(max-width:980px){
  .pub-panel-split{grid-template-columns:1fr;gap:28px;}
  .pub-preview{position:static;}
  .pub-choices{grid-template-columns:1fr;}
}
@media(max-width:700px){
  .pub-topbar-inner{padding:8px 16px;gap:10px;}
  .pub-close{padding:0 14px 0 11px;font-size:.9rem;}
  .pub-steps{padding:14px 16px 2px;}
  .pub-steps ol{gap:8px;}
  .pub-step-name{display:none;}
  .pub-step-row{justify-content:center;}
  .pub-form-card{padding:18px 16px;}
  .pub-big,.pub-choice{padding:16px;gap:14px;}
  /* The single column is the default now, set above; this block only tightens
     the card itself for a phone. */
  .pub-big-choices .pub-big{padding:20px 16px 18px;gap:10px;}
  .pub-big-art{width:72px;height:72px;}
  .pub-cal{padding:10px 6px;}

  /* The step's buttons become a bar fixed to the bottom of the screen, so
     "Continuer" is under the thumb instead of at the end of a long scroll.
     Only one panel is in the layout at a time, the rest being hidden, so
     there is never more than one of these. */
  .pub-actions{
    position:fixed;left:0;right:0;bottom:0;z-index:50;margin:0;gap:12px;
    padding:10px 16px;
    padding-bottom:calc(10px + env(safe-area-inset-bottom, 0px));
    background:#fff;border-top:1px solid var(--sit-border);
    box-shadow:0 -4px 18px rgba(27,58,43,.08);
  }
  .pub-next,.pub-submit{padding:0 20px;flex:1;justify-content:center;}
  .pub-actions-end{flex:1;gap:10px;}
  .pub-prev{flex:none;}
  /* The indicator would push the button off a 320px screen. It is a comfort,
     not a control, so it gives up its place first. */
  .pub-savedmark{display:none;}
  /* Enough room under the form that the bar never covers the last field, and
     the toast clears the bar rather than sitting behind it. */
  .pub-main{padding:14px 16px calc(96px + env(safe-area-inset-bottom, 0px));}
  .pub-toast{bottom:calc(86px + env(safe-area-inset-bottom, 0px));}
}
@media(prefers-reduced-motion:reduce){
  .pub-big,.pub-choice,.pub-savedmark,.pub-savedmark-tick,.pub-toast{transition:none;}
}

/* The photo is a link to the listing page now, so it needs to be a block. */
.sit-card-media{display:block;line-height:0;}
.sit-card-title a{color:inherit;text-decoration:none;}
.sit-card-title a:hover{text-decoration:underline;}
.sit-card-title a:focus-visible{outline:3px solid var(--green-500);outline-offset:3px;border-radius:4px;}

/* ===========================================================================
   Round 2: place suggestions, the radius, one listing's page, "Mes annonces"
   =========================================================================== */

/* Place suggestions, shared by the publish form and the "Où" box. */
.sit-places{
  position:absolute;top:calc(100% + 8px);left:0;right:0;z-index:70;
  background:#fff;border:1px solid var(--sit-border);border-radius:14px;padding:6px;
  box-shadow:0 16px 40px rgba(27,58,43,.16);max-height:300px;overflow-y:auto;
}
.sit-places[hidden]{display:none;}
.sit-place{
  display:flex;flex-direction:column;gap:2px;width:100%;min-height:44px;
  padding:7px 12px;border:0;border-radius:9px;background:none;
  font:inherit;text-align:left;cursor:pointer;color:var(--green-900);
}
.sit-place:hover,.sit-place.is-active{background:var(--green-100);}
.sit-place b{font-size:.95rem;}
.sit-place span{color:var(--muted);font-size:.8rem;}
.sit-places-none{margin:0;padding:12px;color:var(--muted);font-size:.9rem;}
/* A failed lookup, which used to be indistinguishable from an unknown town. */
.sit-places-err{
  margin:0;padding:12px;color:#8a3b2f;font-size:.9rem;font-weight:600;line-height:1.45;
}
/* The list is a child of .pub-input-icon, which is already position:relative
   and whose box is exactly the field's, so left:0;right:0;top:100% puts it
   directly under the field at the field's own width. It is absolute and not
   fixed, so it scrolls with the page.

   .pub-field stays positioned for the sitters board's "Où" box, which has a
   different structure. */
.pub-field{position:relative;}

/* On a phone the keyboard takes the lower half of the screen, so 300px of
   suggestions cannot be shown under a field that is itself halfway down. Four
   rows is what fits above a keyboard on a 375x667 phone, and the picker
   scrolls the field up when even that does not fit. dvh, not vh: vh on iOS
   Safari is the height WITHOUT the browser chrome, which is the one number
   that is never what is on screen. */
@media(max-width:600px){
  .sit-places{max-height:min(46dvh,232px);}
}

/* The country selector beside a place field. One country is searched at a
   time, so which one it is has to be visible without opening anything. */
.sit-ctry,.pub-ctry{
  /* Shrinkable, not fixed: on a narrow phone the country name gives up its
     room to the town being typed and ellipsises instead of pushing the
     field off the screen. */
  flex:0 1 auto;display:inline-flex;align-items:center;gap:4px;min-width:0;
  border:1px solid var(--sit-border);border-radius:999px;background:var(--green-100);
  color:var(--green-900);font:inherit;font-weight:600;cursor:pointer;
}
.sit-ctry [data-ctry-value],.pub-ctry [data-ctry-value]{
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;
}
.sit-ctry .sit-ico,.pub-ctry .sit-ico{flex:none;width:16px;height:16px;color:var(--green-700);}
.sit-ctry:hover,.pub-ctry:hover{background:var(--sit-border);}
.sit-ctry:focus-visible,.pub-ctry:focus-visible{
  outline:3px solid var(--green-500);outline-offset:2px;
}
/* The country gets the same small label above it that the field beside it
   has. Without one the button was the only control on the card whose heading
   was its own current value, so "France" had to be read as both the answer and
   the question. The label is aria-hidden because the button's aria-label
   already reads "Pays : France"; a screen reader hearing the word twice is
   worse than not seeing it at all. */
.sit-ctry-field{display:flex;flex-direction:column;gap:2px;min-width:0;flex:none;}
.pub-ctry-field{display:flex;flex-direction:column;gap:4px;min-width:0;flex:none;}
.pub-ctry-label{
  font-size:0.78rem;font-weight:600;color:var(--green-700);letter-spacing:.01em;
  white-space:nowrap;
}
/* Inside the round white search card, where height is at a premium. */
.sit-ctry{min-height:38px;padding:0 10px 0 12px;font-size:.86rem;max-width:170px;}
/* On the publish form it sits next to a full-height text input. */
.pub-place-row{display:flex;align-items:stretch;gap:10px;}
.pub-place-row .pub-input-icon{flex:1;min-width:0;}
.pub-ctry{min-height:48px;padding:0 12px 0 15px;font-size:.92rem;max-width:200px;}
/* Narrow phones have to share one line between the town and the country, so
   the country gives up room first and ellipsises. This block has to come
   after the two rules above, not up with the other phone rules, which are
   earlier in the file and would lose to them on source order alone. */
@media(max-width:760px){
  .pub-ctry{max-width:130px;padding:0 10px 0 12px;font-size:.86rem;}
  /* Sharing one line left 70px to type a town in at 320px, with "Vereinigtes
     Königreich" taking the rest. The country goes underneath instead, lined
     up with the label past the pin: the text block is given the whole first
     line (the pin is 20px and the gap 12px), which is what pushes the
     button down to the second. */
  .sit-search-field{flex-wrap:wrap;}
  .sit-search-text{flex:1 1 calc(100% - 32px);}
  /* The margin is on the wrapper now, so the label goes down to the second
     line with the button it belongs to instead of staying beside the town. */
  .sit-ctry-field{margin:10px 0 0 32px;max-width:calc(100% - 32px);}
  .sit-ctry{max-width:100%;font-size:.84rem;min-height:44px;}
  /* Before a country is chosen the pill says "Choose a country", which is an
     instruction rather than a label: cut to "Choose a cou…" at 130px it stops
     being one. In that one state the publish form's pill takes the width its
     text needs and the field drops to the next line, which is the answer the
     board's own field already gives above. A country once chosen goes back to
     sharing the line and ellipsising, because "Vereinigtes Königreich" cut
     short is still recognisable and the town being typed matters more. */
  .pub-place-row:has(.pub-ctry.is-empty){flex-wrap:wrap;}
  .pub-place-row:has(.pub-ctry.is-empty) .pub-input-icon{flex:1 1 100%;}
  .pub-ctry.is-empty{max-width:calc(100% - 2px);}
}

.sit-radius{display:inline-flex;align-items:center;gap:8px;font-size:.92rem;font-weight:600;color:var(--green-900);}
.sit-radius select{
  min-height:44px;padding:0 10px;border:1px solid var(--sit-border);border-radius:999px;
  background:#fff;font:inherit;font-size:.92rem;color:var(--green-900);cursor:pointer;
}
.sit-radius select:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.sit-dist{color:var(--green-700);font-weight:600;}

/* --- one listing's page --------------------------------------------------- */
.sit-detail{
  display:grid;grid-template-columns:minmax(0,1.6fr) minmax(280px,.6fr);
  gap:40px;align-items:start;padding-top:10px;padding-bottom:60px;
}
.sit-detail-photo{
  display:block;width:100%;aspect-ratio:16/10;object-fit:cover;
  border-radius:18px;background:var(--green-100);
}
/* The illustration stands in for a photograph, and takes less room than
   one: a fixed 280px rather than the 560px a 16/10 crop of this column
   would give, because the same picture on every such listing has earned
   less of the first screen than somebody's own photo. aspect-ratio is
   cleared or it would fight the height. */
.sit-detail-photo.is-placeholder{
  height:280px;aspect-ratio:auto;object-fit:cover;object-position:center;
}
.sit-detail-title{margin:22px 0 10px;font-size:clamp(1.6rem,3.2vw,2.3rem);color:var(--green-900);line-height:1.18;}
.sit-detail-meta{display:flex;flex-wrap:wrap;gap:8px 20px;margin:0 0 14px;color:#6c7c72;font-size:.95rem;}
.sit-detail-meta span{display:inline-flex;align-items:center;gap:6px;}
.sit-detail-h2{margin:26px 0 8px;font-size:1.1rem;color:var(--green-900);}
.sit-detail-desc{margin:0;color:var(--text);line-height:1.65;white-space:pre-wrap;overflow-wrap:anywhere;}
.sit-detail-side{position:sticky;top:96px;display:flex;flex-direction:column;gap:14px;}
.sit-detail-card{
  background:#fff;border:1px solid var(--sit-border);border-radius:18px;padding:20px;
  display:flex;flex-direction:column;gap:16px;
}
.sit-detail-contact{width:100%;justify-content:center;}
/* align-items:center, not the default stretch: the row holds one button with
   a word in it and two with only an icon, and stretching made Share 54px tall
   against their 44 and pushed it off their baseline. One height for all
   three, set rather than inherited from the tallest. */
.sit-detail-tools{display:flex;align-items:center;gap:8px;}
.sit-tool{
  flex:1;display:inline-flex;align-items:center;justify-content:center;gap:7px;
  height:44px;min-height:44px;padding:0 12px;border:1px solid var(--sit-border);border-radius:999px;
  background:#fff;color:var(--green-900);font:inherit;font-size:.9rem;font-weight:600;cursor:pointer;
}
.sit-tool:hover{border-color:var(--green-500);}
.sit-tool:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
/* Save and report carry their name in an aria-label rather than beside the
   icon, so the row reads as one labelled action with two smaller ones either
   side instead of three competing words. Square, so they are the same 44px
   high as Share and do not stretch with it. */
.sit-tool-icon{flex:none;width:44px;padding:0;}
/* .listing-report-btn is shared with the card menus, where it is a stacked
   item and carries margin-top:10px. In this row that pushed it 5px below the
   two beside it. */
.sit-detail-tools .listing-report-btn{margin:0;}
.sit-tool-icon .sit-ico{width:17px;height:17px;}
/* The heart is a .fav-heart, which is normally a floating circle over a photo.
   Here it is one of the tools, so the positioning and the reveal-on-hover are
   undone and it sits in the row like the others. */
.fav-heart-tool{
  position:static;opacity:1;box-shadow:none;background:#fff;
  border:1px solid var(--sit-border);border-radius:999px;
  height:44px;top:auto;right:auto;
}
.fav-heart-tool::before{content:none;}
.fav-heart-tool.is-on{color:var(--green-700);border-color:var(--green-700);}
.fav-heart-tool.is-on .sit-ico{fill:currentColor;}
.fav-heart-tool:hover{transform:none;border-color:var(--green-500);}
.sit-share-done{margin:0;color:var(--green-700);font-size:.88rem;font-weight:600;text-align:center;}
.sit-share-done[hidden]{display:none;}
.sit-detail-back{color:var(--green-700);font-weight:600;text-align:center;}
/* Three more of the same kind, under the listing. Same cards as the board, so
   there is nothing new to look at and nothing new to maintain. */
.sit-nearby{padding:10px 0 50px;}
.sit-nearby-title{margin:0 0 18px;font-size:1.25rem;color:var(--green-900);}
.sit-nearby .sit-grid{margin:0;}

.sit-gone{padding:70px 0 90px;text-align:center;}
.sit-gone h1{margin:0 0 12px;font-size:clamp(1.5rem,3vw,2rem);color:var(--green-900);}
.sit-gone p{margin:0 0 24px;color:#6c7c72;}

@media(max-width:900px){
  .sit-detail{grid-template-columns:1fr;gap:24px;}
  .sit-detail-side{position:static;}
}
/* Shorter again on a phone, where 280px would be most of the screen and
   the description is what the reader came for. */
@media(max-width:640px){
  .sit-detail-photo.is-placeholder{height:200px;}
}

/* --- "Mes annonces" -------------------------------------------------------- */
.my-listings{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:12px;}
.my-listing{
  display:flex;align-items:center;gap:14px;padding:12px;
  background:#fff;border:1px solid var(--sit-border);border-radius:14px;
}
.my-listing-photo{
  flex:none;width:92px;height:66px;object-fit:cover;border-radius:10px;background:var(--green-100);
}
.my-listing-photo.is-blank{display:flex;align-items:center;justify-content:center;color:var(--green-700);}
.my-listing-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px;}
.my-listing-title{color:var(--green-900);font-size:.98rem;overflow:hidden;text-overflow:ellipsis;}
.my-listing-meta{color:var(--muted);font-size:.84rem;}
.my-status{
  align-self:flex-start;padding:3px 10px;border-radius:999px;
  font-size:.74rem;font-weight:700;text-transform:uppercase;letter-spacing:.04em;
}
.my-status.is-active{background:var(--green-100);color:var(--green-700);}
.my-status.is-paused{background:#fdeccd;color:#8a5a2b;}
.my-status.is-expired{background:#eceff0;color:#6c7c72;}
.my-listing-actions{display:flex;flex-wrap:wrap;gap:6px;flex:none;}
.my-action{
  min-height:44px;padding:0 14px;display:inline-flex;align-items:center;
  border:1px solid var(--sit-border);border-radius:999px;background:#fff;
  color:var(--green-900);font:inherit;font-size:.88rem;font-weight:600;
  text-decoration:none;cursor:pointer;
}
.my-action:hover{border-color:var(--green-500);color:var(--green-900);}
.my-action:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.my-action.is-danger{color:#8a3d2b;}
.my-action.is-danger:hover{border-color:#c98a76;}

.my-del-backdrop{position:fixed;inset:0;z-index:98;background:rgba(27,58,43,.45);}
.my-del-backdrop[hidden]{display:none;}
.my-del-dialog{
  position:fixed;z-index:99;left:50%;top:50%;transform:translate(-50%,-50%);
  width:min(440px,calc(100vw - 32px));background:#fff;border-radius:18px;padding:24px;
  box-shadow:0 24px 60px rgba(27,58,43,.3);
}
.my-del-dialog[hidden]{display:none;}
.my-del-dialog h2{margin:0 0 10px;font-size:1.15rem;color:var(--green-900);}
.my-del-dialog p{margin:0 0 8px;color:#6c7c72;line-height:1.55;}
.my-del-name{font-weight:700;color:var(--green-900);}
.my-del-actions{display:flex;align-items:center;justify-content:flex-end;gap:14px;margin-top:20px;}
.my-del-go{
  min-height:48px;padding:0 22px;border:0;border-radius:12px;
  background:#8a3d2b;color:#fff;font:inherit;font-weight:700;cursor:pointer;
}
.my-del-go:hover{background:#6f3023;}
.my-del-go:focus-visible{outline:3px solid var(--green-500);outline-offset:2px;}
.my-del-go[disabled]{opacity:.6;cursor:default;}

@media(max-width:640px){
  .my-listing{flex-wrap:wrap;}
  .my-listing-actions{width:100%;}
  .my-action{flex:1;justify-content:center;}
}

/* Options inside the shared menu (sort, radius, and the two filters). The
   kebab's single report button and these rows are the same component, so
   they get the same 44px target and the same focus ring. */
.sit-menu-opt{
  display:flex;align-items:center;gap:9px;width:100%;min-height:44px;
  padding:0 12px;border:0;border-radius:9px;background:none;
  color:var(--green-900);font:inherit;font-size:.94rem;text-align:left;cursor:pointer;
}
.sit-menu-opt:hover{background:var(--green-100);}
.sit-menu-opt:focus-visible{outline:3px solid var(--green-500);outline-offset:-2px;}
.sit-menu-opt.is-on{background:var(--green-700);color:#fff;}
.sit-menu-opt.is-on:hover{background:var(--green-900);}

/* A pill with a choice made is filled, so the row shows at a glance which
   filters are narrowing the list. */
.sit-filter.is-on{
  background:var(--green-700);border-color:var(--green-700);color:#fff;
}
.sit-filter.is-on .sit-ico{color:#fff;}
.sit-filter.is-on:hover{background:var(--green-900);border-color:var(--green-900);}
.sit-filter-group[hidden]{display:none;}
/* Sort sits at the far end of the row, where the inert label used to be. */
.sit-sort-group{margin-left:auto;}
@media(max-width:760px){
  .sit-sort-group{margin-left:auto;}
  .sit-sort-group,.sit-sort-group .sit-filter{display:inline-flex;}
}

/* GeoNames asks to be credited where its data is used. Quiet, under the
   footer links, on every page. */
.footer-attribution{margin:10px 0 0;font-size:.78rem;opacity:.72;}
.footer-attribution a{color:inherit;text-decoration:none;}
.footer-attribution a:hover{text-decoration:underline;}
/* Two sources now, named one after the other on the same line. */
.footer-attribution a + a::before{content:"·";margin:0 .45em;text-decoration:none;}

/* ==========================================================================
   Search fields, shared
   --------------------------------------------------------------------------
   Nine search-like controls had grown nine different answers to the same
   three questions. The homepage pill held an input that still drew a border
   from "#plant-search-input", so a rounded box sat inside the rounded pill.
   The marketplace panel did it twice over: a bordered select and a bordered
   input inside a bordered card. The 404 had the border but no pill and no
   icon at all, and the plant page had neither icon nor focus ring. The
   magnifier was grey on the homepage while the pin and the calendar on the
   two other cards were already green.

   One box, one icon colour, one ring, set here and only here.

   This block is last in the file deliberately. ".wp-search input" scores
   0-2-0, the same as ".mk-field input" and ".auth-form input" scores 0-1-0,
   so for the ones it ties with, position decides. The id rule it could never
   have out-weighed (#plant-search-input, 1-0-0) was deleted rather than
   fought; see the note where it used to live.
   ========================================================================== */

/* A search container: icon, then the field, on one line. */
.wp-search{display:flex;align-items:center;gap:12px;min-width:0;}

/* No box inside a box. The container draws the border, the field sits flat
   in it. background:none and not transparent, so an autofilled field does
   not paint its own yellow box back in. */
.wp-search input,.wp-search select{
  flex:1;min-width:0;width:100%;
  border:0;background:none;border-radius:0;box-shadow:none;
  font:inherit;color:var(--text);
}
.wp-search input:focus,.wp-search select:focus{outline:none;box-shadow:none;}
/* The placeholder stays grey: it is the hint, not the signal. */
.wp-search input::placeholder{color:#8b9991;}

/* The magnifier, in the site green, at the size and position the pin and the
   calendar on the Plant Sitting card already use. */
.wp-search-icon{width:20px;height:20px;flex:none;color:var(--green-700);}

/* One ring for every search on the site, on the whole container rather than
   on the control inside it, so a panel holding two fields lights up as one
   thing. An outline rather than a box-shadow: most of these containers
   already carry a shadow, and an outline follows the container's own
   border-radius without having to be told it. Low opacity, 3px, and it is
   :focus-within rather than :focus-visible on purpose, so it is there for
   anyone arriving by keyboard. */
.wp-focus-ring:focus-within{outline:3px solid rgba(47,107,69,.28);outline-offset:1px;}

/* The marketplace hero panel. Its two controls lose their own boxes and sit
   on the panel the way the Plant Sitting card's fields sit on theirs, with a
   hairline between them instead of a border around each. */
.mk-search .mk-search-field select,.mk-search .mk-search-field input{
  width:100%;min-width:0;min-height:0;padding:2px 0 0;
  border:0;background:none;border-radius:0;
  font-family:inherit;font-size:0.98rem;color:var(--text);
}
.mk-search .mk-search-field select:focus,.mk-search .mk-search-field input:focus{
  outline:none;
}
.mk-search .mk-search-field input::placeholder{color:#8b9991;}
/* A select with no border still reserves room for its arrow, and left-aligns
   its text with a few pixels of its own. -2px pulls the country name back
   flush with its label. */
.mk-search .mk-search-field select{margin-left:-2px;}
/* Flat fields are shorter than the bordered ones were, so the row centres on
   the pin instead of hanging off the bottom of it. */
.mk-search{align-items:center;}
.mk-search-pin{margin-bottom:0;}
.mk-search .mk-search-field + .mk-search-field{
  border-left:1px solid #e9efea;padding-left:14px;
}
/* An absolutely positioned child is laid out against the padding box, so the
   suggestion list in the postcode field started 14px to the left of the input
   it belongs to: the gutter above is inside the field. Inset by the same
   amount, and kept directly under the rule that creates it so the two cannot
   drift apart. */
.mk-search .mk-search-field + .mk-search-field > .sit-places{left:14px;}

/* On a phone the two fields stack instead of sharing one narrow row.
   There is a rule 2800 lines up that already says this - inside
   @media(max-width:600px) - but .mk-search-field-country scores 0-2-0 with
   its flex:0 0 150px and is declared after it, so the country field stayed
   150px wide and the postcode field was left with 141px of a 375px screen.
   Nobody noticed while the field was only a box to type in; a suggestion
   list 126px wide breaks "Aulnay-sous-Bois" across three lines, which is
   what made it worth fixing rather than noting. Written here, at the end of
   the file and specific enough to beat both, so neither ordering nor
   specificity decides it. */
@media(max-width:600px){
  .mk-search .mk-search-field,
  .mk-search .mk-search-field-country{flex:1 1 100%;}
  /* Stacked, the divider between them belongs on top rather than at the
     side, and the list goes back to the field's own left edge. */
  .mk-search .mk-search-field + .mk-search-field{
    border-left:0;padding-left:0;border-top:1px solid #e9efea;padding-top:12px;
  }
  .mk-search .mk-search-field + .mk-search-field > .sit-places{left:0;}
}

/* The two list filters are pills with a flat select already. They only
   needed the ring. */
.mk-filter:focus-within{border-color:var(--green-500);}

/* The publish forms. The place field is its own box there, with the pin drawn
   over it, so the ring goes on the input: .pub-input-icon around it is a
   positioning shell stretched to the height of the country button beside it,
   and a ring on that would have floated 22px below the field. Same ring, and
   the softer shadow the field drew for itself stands down rather than
   doubling up. */
.pub-input-icon input[type=text]:focus{
  outline:3px solid rgba(47,107,69,.28);outline-offset:1px;box-shadow:none;
}
/* The same grey as every other placeholder on the site. */
.pub-input-icon input[type=text]::placeholder{color:#8b9991;}
/* The pin needs the text pushed clear of it. The old rule asked for a
   ".pub-field" ancestor, which the marketplace publish form does not have:
   its place field is a ".mk-field", so there the text ran under the pin. */
.pub-input-icon input[type=text]{padding-left:46px;}

/* My plants: the picker is a search, so it looks like one. The box moves off
   the input and onto the wrapper, matching the nickname field beside it
   exactly - same border, same 8px corner, same 40px - with the magnifier
   inside it rather than a second box around anything. */
.mp-combo{
  display:flex;align-items:center;gap:10px;
  padding:0 12px;background:#fff;
  border:1px solid var(--green-300);border-radius:8px;
}
.mp-combo input{padding:9px 0;}

/* The one red thing on My Account. Outline rather than a filled button: a
   destructive action should look deliberate to reach, not inviting to press,
   and a solid red block beside the green ones reads as the primary action on
   the page, which it very much is not. */
.danger-panel{border:1px solid #e6c4bb;}
.danger-panel h2{color:#9c3d24;}
.danger-text{color:#6c7c72;line-height:1.55;margin:0 0 16px;}
.danger-btn{
  min-height:44px;padding:0 20px;border-radius:999px;
  border:1.5px solid #c2543a;background:#fff;color:#9c3d24;
  font:inherit;font-weight:700;cursor:pointer;transition:background .16s,color .16s;
}
.danger-btn:hover{background:#9c3d24;color:#fff;}
.danger-btn:focus-visible{outline:3px solid #c2543a;outline-offset:2px;}
.danger-btn:disabled{opacity:.6;cursor:default;}
.danger-btn:disabled:hover{background:#fff;color:#9c3d24;}
#del-confirm{margin-top:20px;padding-top:20px;border-top:1px solid #e6c4bb;}
#del-confirm h3{margin:0 0 10px;color:#9c3d24;font-size:1.05rem;}
.danger-actions{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin-top:8px;}
.auth-message.is-error{color:#9c3d24;}
@media(max-width:600px){
  .danger-actions{flex-direction:column-reverse;align-items:stretch;}
  .danger-actions .danger-btn{width:100%;}
}
/* .auth-form is a centred 360px column, which is right for a sign-in card and
   wrong inside a left-aligned panel: the fields floated to the middle away
   from the heading explaining them. And the password pair is wrapped in a div
   so it can be hidden for a Google account, which made it one flex item
   rather than two, losing the gap between its label and its field.
   display:contents hands the children back to the form's own column. */
#del-form{margin:0;max-width:420px;}
#del-password-wrap{display:contents;}
#del-password-wrap[hidden]{display:none;}
#del-reauth{margin-bottom:18px;}
/* .auth-form button[type="submit"] is 0-2-1 and strips the border off every
   submit button in a form, which left the last button on the page - the one
   that actually deletes the account - looking like a line of bold text. */
.auth-form button[type="submit"].danger-btn{
  border:1.5px solid #c2543a;border-radius:999px;padding:0 20px;margin-top:0;
}

/* Secondary button: the way out of a long list, where a bare underlined
   link reads as a footnote to the thing above it. Outlined rather than
   filled, so it cannot compete with a real primary action on the same
   screen; green-700 on cream is 5.97:1 for the text and the border is the
   same colour, so the outline is visible without a fill. */
.btn-secondary{
  display:inline-flex;align-items:center;gap:10px;
  min-height:44px;padding:0 22px;
  border:1.5px solid var(--green-700);border-radius:999px;
  background:transparent;color:var(--green-700);
  font-size:.95rem;font-weight:700;text-decoration:none;cursor:pointer;
  transition:background .16s,color .16s;
}
.btn-secondary:hover{background:var(--green-700);color:#fff;}
.btn-secondary:focus-visible{outline:3px solid var(--green-700);outline-offset:3px;}
/* The arrow nudges on hover, which is the whole animation budget here. */
.btn-secondary-arrow{flex:none;transition:transform .16s;}
.btn-secondary:hover .btn-secondary-arrow{transform:translateX(2px);}
@media(prefers-reduced-motion:reduce){
  .btn-secondary-arrow{transition:none;}
  .btn-secondary:hover .btn-secondary-arrow{transform:none;}
}
.allplants-cta{margin-top:6px;}
