/* TM6 Chef — the plandrop app skin (admin.css), not the plan look. Token names
   keep plan.css's architecture (bg/panel/panel2/line/text/muted/accent plus the
   ok/info/warn/crit triples) so every component rule below stays palette-
   agnostic, but the values are the plandrop dashboard's: flat zinc surfaces,
   indigo accent, dark only — no light mode, no glow, no pill buttons. */

:root{
  --bg:#09090b; --panel:#18181b; --panel2:#1f1f23; --panel3:#27272a;
  --side:#111114; --well:#0c0c0e; --line:#27272a;
  --text:#fafafa; --muted:#a1a1aa; --subtle:#71717a;
  --accent:#6366f1; --on-accent:#fafafa; --hi:0 0 #0000;
  --ok-bg:#0f2418; --ok-fg:#4ade80; --ok-line:#1f5136;
  --info-bg:#1e1b4b; --info-fg:#a5b4fc; --info-line:#3730a3;
  --warn-bg:#2a1f0e; --warn-fg:#f5b64a; --warn-line:#5a4318;
  --crit-bg:#2a1315; --crit-fg:#f87171; --crit-line:#5a2327;
  --yellow:#f5c518;
}

/* ---------------------------------------------------------------------------
   base
--------------------------------------------------------------------------- */

*{box-sizing:border-box}
html{
  -webkit-text-size-adjust:100%;
  color-scheme:dark;
  background:var(--bg);
  height:100%;
}
body{
  margin:0; background:transparent; color:var(--text);
  font:14px/1.5 ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  min-height:100%;
}
h1{font-size:22px;line-height:1.2;margin:0 0 4px;letter-spacing:-.02em;font-weight:600}
h2{font-size:15px;letter-spacing:-.01em;color:var(--text);margin:26px 0 10px;font-weight:600}
h3{font-size:15px;line-height:1.3;margin:0 0 8px;font-weight:600;letter-spacing:-.01em}
p{margin:.7em 0}
a{color:var(--accent);text-underline-offset:2px}
strong,b{color:var(--text)}
ul,ol{margin:.7em 0;padding-left:1.4em}
li{margin:.3em 0}
code{background:var(--well);border:1px solid var(--line);border-radius:6px;overflow-wrap:anywhere;
     padding:1px 6px;font-size:.86em;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
hr{border:none;border-top:1px solid var(--line);margin:24px 0}
[hidden]{display:none !important}

/* Two quick taps on a control — skipping cook steps to reach step 4, a burst
   of shopping-list ticks — are a double-tap zoom gesture on iOS unless the
   element opts out. `manipulation` drops double-tap on controls only: panning
   and pinch to zoom anywhere on the page are untouched, so the recipe photo
   and the small print can still be enlarged. */
button,a,label,summary,input,select,textarea,[role=button]{touch-action:manipulation}

input[type=text],input[type=search],input[type=number],input[type=password],input[type=email],textarea,select{
  width:100%; background:var(--bg); color:var(--text);
  border:1px solid var(--line); border-radius:8px;
  padding:9px 12px; font:inherit; font-size:13.5px;
}
input:focus-visible,textarea:focus-visible,select:focus-visible,button:focus-visible,a:focus-visible{
  outline:2px solid color-mix(in srgb,var(--accent) 33%,transparent); outline-offset:1px;
}
::placeholder{color:var(--muted);opacity:.8}
textarea{resize:vertical}
label{font-size:12.5px;font-weight:600;color:var(--text)}
.field{display:block;margin:0 0 12px}
.field .lbl{display:block;margin:0 0 5px}
.hint{color:var(--muted);font-size:12px;margin:5px 0 0}
.err{color:var(--crit-fg);font-size:13px;margin:6px 0 0}
.row2{display:flex;gap:12px}
.row2>*{flex:1}

/* buttons */
button{font:inherit;cursor:pointer}
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  background:var(--panel);color:var(--text);border:1px solid var(--line);
  border-radius:8px;padding:7px 14px;font-weight:500;font-size:13px;
  text-decoration:none;
}
.btn:hover{background:var(--panel2)}
.btn.pr{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.btn.pr:hover{background:#4f46e5;border-color:#4f46e5;color:var(--on-accent)}
.btn.danger{color:var(--crit-fg);border-color:transparent;background:transparent}
.btn.danger:hover{background:var(--crit-bg);border-color:var(--crit-line)}
.btn:disabled{opacity:.55;cursor:default;pointer-events:none}
.btn.wide{display:flex;width:100%}
.link-btn{background:none;border:none;padding:0;color:var(--accent);font-weight:600;
          font-size:13px;text-decoration:underline;text-underline-offset:2px}
.link-btn:hover{filter:brightness(1.1)}

/* inline loading spinner — TM6.busy/TM6.wait (shell.js) drop this 1em ring,
   drawn in currentColor, into buttons and status lines while a request runs */
.spin{display:inline-block;width:1em;height:1em;flex:none;border-radius:50%;
      vertical-align:-.125em;margin-right:.45em;
      border:2px solid color-mix(in srgb,currentColor 25%,transparent);
      border-top-color:currentColor;animation:spin .7s linear infinite}
.btn .spin{margin-right:0} /* .btn's own gap already separates it */

/* ---------------------------------------------------------------------------
   plan.css components (verbatim shapes, app-sized)
--------------------------------------------------------------------------- */

.badges{display:flex;gap:10px;flex-wrap:wrap;margin:0 0 18px}
.badge{padding:5px 13px;border-radius:999px;font-weight:600;font-size:13px;border:1px solid transparent}
.b-ok{background:var(--ok-bg);color:var(--ok-fg);border-color:var(--ok-line)}
.b-info{background:var(--info-bg);color:var(--info-fg);border-color:var(--info-line)}
.b-warn{background:var(--warn-bg);color:var(--warn-fg);border-color:var(--warn-line)}
.b-crit{background:var(--crit-bg);color:var(--crit-fg);border-color:var(--crit-line)}

.ribbon{display:inline-flex;align-items:center;gap:.5em;font-weight:700;font-size:14px;
        padding:.4em .95em;border-radius:999px;box-shadow:var(--hi);
        background:var(--ok-bg);border:1px solid var(--ok-line);color:var(--ok-fg)}
.ribbon.warn{background:var(--warn-bg);border-color:var(--warn-line);color:var(--warn-fg)}
.ribbon.crit{background:var(--crit-bg);border-color:var(--crit-line);color:var(--crit-fg)}

.sgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(96px,1fr));gap:10px;margin:14px 0}
.stile{border:1px solid var(--line);border-radius:10px;padding:13px 12px;text-align:center;
       background:var(--panel)}
.stile .n{font-size:1.7em;font-weight:800;line-height:1;font-variant-numeric:tabular-nums}
.stile .l{font-size:.72em;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin-top:6px}
.stile.crit .n{color:var(--crit-fg)}
.stile.warn .n{color:var(--warn-fg)}
.stile.good .n{color:var(--ok-fg)}

.finding{background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--yellow);
         border-radius:12px;padding:12px 16px;margin:0 0 12px;box-shadow:var(--hi)}
.finding.crit{border-left-color:var(--crit-fg)}
.finding.warn{border-left-color:var(--warn-fg)}
.finding.info{border-left-color:var(--info-fg)}
.finding.good{border-left-color:var(--ok-fg)}
.finding .ft{font-weight:600;margin:0 0 4px}
.finding p{margin:.45em 0;color:var(--muted);font-size:14px}
.finding ul{margin:.45em 0}
.finding li{color:var(--muted);font-size:14px}
.finding b,.finding strong{color:var(--text)}
.finding>:first-child{margin-top:0}
.finding>:last-child{margin-bottom:0}

.card{background:var(--panel);border:1px solid var(--line);border-radius:10px;
      padding:16px 18px;margin:0 0 14px}
.card>:first-child{margin-top:0}
.card>:last-child{margin-bottom:0}
.note{background:var(--panel2);border:1px solid var(--line);border-radius:10px;
      padding:10px 14px;font-size:13px;color:var(--muted)}

/* info tooltip: a small ⓘ that reveals a bubble on hover, or on tap via .open
   (toggled in shell.js — Safari does not focus buttons on tap) */
.tip{position:relative;display:inline-flex;vertical-align:-2px;margin-left:5px}
.tip-btn{width:16px;height:16px;padding:0;border:1px solid var(--line);border-radius:50%;
         background:var(--panel2);color:var(--muted);font-size:10px;font-weight:700;
         font-style:normal;line-height:1;display:inline-flex;align-items:center;
         justify-content:center;font-family:Georgia,serif}
.tip-btn:hover{color:var(--accent);border-color:var(--accent)}
.tip-pop{position:absolute;bottom:calc(100% + 8px);left:50%;transform:translateX(-50%);
         width:max-content;max-width:min(280px,78vw);background:var(--panel);
         border:1px solid var(--line);border-radius:10px;padding:8px 11px;
         box-shadow:0 10px 28px -8px rgba(0,0,0,.3),var(--hi);
         font-size:12px;font-weight:400;line-height:1.5;color:var(--muted);
         text-align:left;text-transform:none;letter-spacing:normal;z-index:80;display:none}
.tip:hover .tip-pop,.tip.open .tip-pop{display:block}
.tip.start .tip-pop{left:-9px;transform:none}

/* accordion: a styled <details> for explanations that are optional reading */
details.fold{border:1px solid var(--line);border-radius:10px;background:var(--panel2);
             margin:10px 0}
.fold>summary{list-style:none;cursor:pointer;padding:9px 13px;font-size:13px;
              font-weight:600;color:var(--text);display:flex;align-items:center;
              gap:9px;user-select:none;-webkit-user-select:none}
.fold>summary::-webkit-details-marker{display:none}
.fold>summary::before{content:"";width:6px;height:6px;flex:none;margin-top:-2px;
              border-right:1.7px solid var(--muted);border-bottom:1.7px solid var(--muted);
              transform:rotate(-45deg);transition:transform .16s ease}
.fold[open]>summary::before{transform:rotate(45deg);margin-top:-4px}
.fold-body{padding:0 13px 12px}
.fold-body>:first-child{margin-top:0}
.fold-body>:last-child{margin-bottom:0}
.fold-body .hint{font-size:12.5px}
.fold-body input{margin:6px 0 8px}

/* compact numbered instructions, inside or outside a fold */
.mini-ol{margin:.4em 0 .7em;padding-left:1.35em;font-size:12.5px;color:var(--muted)}
.mini-ol li{margin:.35em 0}

/* ---------------------------------------------------------------------------
   app shell: sidebar + master–detail
--------------------------------------------------------------------------- */

.shell{display:grid;grid-template-columns:200px 320px 1fr;height:100vh;height:100dvh;overflow:hidden}
/* pages without a master list (settings) drop the middle column */
.shell.two{grid-template-columns:200px 1fr}

.side{background:var(--side);border-right:1px solid var(--line);
      padding:14px 12px;display:flex;flex-direction:column;gap:4px;min-width:0}
.side-logo{display:flex;align-items:center;gap:8px;font-weight:600;font-size:14.5px;
           margin:0 4px 14px;color:var(--text);text-decoration:none;white-space:nowrap}
.side-mark{width:26px;height:26px;flex:none;border-radius:7px;color:var(--on-accent);
           background:linear-gradient(135deg,var(--accent),color-mix(in srgb,var(--accent) 55%,#8b5cf6));
           display:inline-flex;align-items:center;justify-content:center;font-size:13px}
.side-mark svg{width:78%;height:78%;display:block}
.ver-badge{font-size:10px;color:#a5b4fc;background:rgba(99,102,241,.12);
           border:1px solid rgba(99,102,241,.28);border-radius:999px;padding:2px 7px;
           font-weight:600;white-space:nowrap;font-variant-numeric:tabular-nums;
           letter-spacing:.02em;line-height:1}
.side-nav{display:block;width:100%;padding:7px 9px;border-radius:8px;color:var(--muted);
          text-decoration:none;font-weight:500;font-size:13.5px;
          background:none;border:0;text-align:left;font-family:inherit;line-height:inherit}
.side-nav:hover{color:var(--text)}
.side-nav.on{background:var(--panel3);color:var(--text);font-weight:600}
.side-foot{margin-top:auto;display:flex;flex-direction:column;gap:8px}
.side-links{font-size:11.5px;color:var(--muted);margin:0 4px}
.side-links a{color:var(--muted)}

/* the hamburger: plandrop's .nav-toggle grammar, opens the drop-card menu */
.menu-toggle{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;
             flex:none;padding:0;border-radius:8px;background:transparent;
             border:1px solid var(--line);color:var(--muted);cursor:pointer}
.menu-toggle:hover{background:var(--panel2);color:var(--text)}
.menu-toggle svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.8;
                 stroke-linecap:round;stroke-linejoin:round}

/* account row + popover */
.acct{position:relative;margin:0}
.acct-btn{display:flex;align-items:center;gap:7px;width:100%;background:none;border:none;
          padding:6px 8px;border-radius:8px;color:var(--muted);font-size:12.5px;text-align:left}
.acct-btn:hover{background:var(--panel2);color:var(--text)}
.acct-avatar{width:20px;height:20px;flex:none;border-radius:50%;
             background:linear-gradient(135deg,#f59e0b,#ef4444)}
.acct-email{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.acct-pop{position:absolute;bottom:calc(100% + 6px);left:0;right:0;z-index:30;
          background:var(--panel);border:1px solid var(--line);border-radius:10px;
          box-shadow:0 8px 28px -8px rgba(0,0,0,.25),var(--hi);padding:6px}
.acct-pop button,.acct-pop a{display:block;width:100%;text-align:left;background:none;border:none;
          padding:7px 10px;border-radius:7px;color:var(--text);font-size:13px;text-decoration:none}
.acct-pop button:hover,.acct-pop a:hover{background:var(--panel2)}

/* the recipes list (chat page right pane) */
.list-tools{display:flex;gap:6px;padding:12px 12px 8px}
.list-tools input[type=search]{flex:1;min-width:0;background:var(--panel)}
.star-filter{flex:none;width:38px;border:1px solid var(--line);border-radius:8px;
             background:var(--panel);color:var(--muted);font-size:15px}
.star-filter[aria-pressed="true"]{color:var(--yellow);border-color:var(--yellow)}
.list-scroll{flex:1;overflow-y:auto;padding-bottom:8px}
.band{font-size:10.5px;text-transform:uppercase;letter-spacing:.1em;color:var(--muted);
      padding:10px 14px 4px;border-left:3px solid var(--accent);margin-top:4px;font-weight:700}
.thread{display:flex;align-items:stretch;cursor:pointer}
.thread:hover{background:var(--panel2)}
.thread.sel{background:var(--panel);box-shadow:inset 3px 0 var(--accent)}
.thread-main{flex:1;min-width:0;background:none;border:none;text-align:left;
             padding:8px 4px 8px 14px;color:inherit;font:inherit;cursor:pointer}
.thread-name{display:block;font-weight:600;font-size:13.5px;
             overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* the meta line carries the badges: it is short by construction, so nothing
   here is ever the thing an ellipsis eats */
.thread-meta{display:flex;align-items:center;gap:6px;flex-wrap:wrap;
             font-size:11.5px;color:var(--muted)}
.thread-meta .tag{font-size:10px;padding:0 5px}
/* the dish photo: a small square that turns the list into something you scan
   by eye. The row becomes a grid so the picture spans both text lines, and the
   square is sized in CSS rather than by the image — it reserves its space from
   the first paint, so nothing jumps when a photo that was still generating
   turns up on a later load. Chat rows keep the plain block layout: a
   conversation is not a dish and has no picture. */
.thread:not(.chat-thread) .thread-main{display:grid;grid-template-columns:auto 1fr;
             column-gap:10px;align-items:center}
.thread-shot{grid-column:1;grid-row:1 / span 2;width:38px;height:38px;
             border-radius:7px;object-fit:cover;background:var(--panel2)}
.thread-name,.thread-meta{grid-column:2}
.thread-acts{display:flex;align-items:center;padding-right:8px;gap:2px}
.icon-btn{background:none;border:none;color:var(--muted);font-size:14px;padding:4px 6px;
          border-radius:6px;line-height:1}
.icon-btn:hover{color:var(--text);background:var(--panel2)}
.icon-btn.fav-on{color:var(--yellow)}
.list-empty{color:var(--muted);font-size:13px;padding:16px 14px}

/* detail pane (settings) */
.detail{position:relative;overflow:hidden;background:var(--bg);
        display:flex;flex-direction:column;min-width:0}
.detail-scroll{flex:1;overflow-y:auto;padding:18px 20px}

@keyframes spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.spin{animation-duration:1.6s}}

/* banners */
.banner{background:var(--warn-bg);color:var(--warn-fg);border:1px solid var(--warn-line);
        border-radius:10px;padding:10px 14px;font-size:13px;margin:0 0 12px}
.banner.crit{background:var(--crit-bg);color:var(--crit-fg);border-color:var(--crit-line)}

/* segmented tabs — the base shape; .top-tabs and .mode-seg override it, so
   it must come before the duo section in the cascade */
.seg{display:flex;background:var(--well);border:1px solid var(--line);border-radius:9px;
     padding:3px;gap:3px;margin:0 0 14px}
.seg-btn{flex:1;border:0;border-radius:6px;padding:7px 0;font:inherit;font-size:12.5px;
         font-weight:500;color:var(--muted);background:transparent}
.seg-btn.on{background:var(--panel3);color:var(--text);font-weight:600;
            box-shadow:0 1px 2px rgba(0,0,0,.3)}

/* ---------------------------------------------------------------------------
   chat-first duo: topbar over a chat pane + recipes column
--------------------------------------------------------------------------- */

.duo{display:flex;flex-direction:column;height:100vh;height:100dvh;overflow:hidden}
.topbar{display:flex;align-items:center;gap:14px;padding:8px 16px;flex:none;
        border-bottom:1px solid var(--line);background:var(--side)}
.topbar .side-logo{margin:0}
.top-tabs{display:none;margin:0;width:auto}
.top-tabs .seg-btn{flex:none;padding:6px 16px}
.topbar .menu-toggle{margin-left:auto}

.duo-body{flex:1;display:grid;grid-template-columns:1fr 340px;overflow:hidden;min-height:0}
.pane-chat{overflow:hidden;display:flex;min-width:0}
.chat-inner{width:100%;max-width:680px;margin:0 auto;display:flex;flex-direction:column;
            min-height:0;padding:0 16px}
.chat-head{display:flex;align-items:center;gap:10px;padding:10px 0 6px;flex:none}
.chat-head .btn{padding:6px 13px;font-size:12.5px}
.chat-title-wrap{position:relative;flex:1;min-width:0}
.chat-title{display:flex;align-items:center;gap:6px;max-width:100%;background:none;
            border:none;padding:6px 8px;border-radius:8px;font:inherit;font-weight:650;
            color:var(--text);font-size:15px}
.chat-title:hover{background:var(--panel2)}
.chat-title-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chat-title-caret{color:var(--muted);font-size:11px;flex:none}
.chat-pop{position:absolute;top:calc(100% + 4px);left:0;z-index:30;min-width:260px;
          max-width:min(340px,80vw);background:var(--panel);border:1px solid var(--line);
          border-radius:10px;box-shadow:0 10px 32px -10px rgba(0,0,0,.3),var(--hi);
          padding:5px;max-height:300px;overflow-y:auto}
.chat-pop-row{display:flex;align-items:center;gap:4px;border-radius:7px}
.chat-pop-row:hover{background:var(--panel2)}
.chat-pop-open{flex:1;min-width:0;text-align:left;background:none;border:none;
               padding:7px 10px;font:inherit;font-size:13px;color:var(--text);
               overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chat-pop-row.on .chat-pop-open{color:var(--accent);font-weight:600}
.chat-pop-del{flex:none;background:none;border:none;color:var(--muted);padding:6px 8px;
              border-radius:6px;font-size:13px;line-height:1}
.chat-pop-del:hover{color:var(--crit-fg);background:var(--crit-bg)}
.chat-pop-empty{padding:8px 10px;color:var(--muted);font-size:13px}

.chat-log{flex:1;overflow-y:auto;padding:6px 0 14px;display:flex;flex-direction:column;
          gap:10px;min-height:0}
.chat-empty{text-align:center;padding:8px}
.chat-empty h1{font-size:24px;margin:0}
/* the fresh page groups greeting + composer in the centre, t3-style */
.chat-inner.fresh{justify-content:center}
.chat-inner.fresh .chat-log{flex:0 0 auto;overflow:visible;padding:0 0 8px}
.chat-inner.fresh .composer2{padding-top:0}
.chat-msg{display:flex;flex:none}
.chat-msg.user{justify-content:flex-end}
.bubble{background:var(--accent);color:var(--on-accent);border-radius:16px 16px 4px 16px;
        padding:8px 14px;max-width:85%;font-size:14px;white-space:pre-wrap;
        overflow-wrap:anywhere}
.chat-msg.assistant .bubble{background:var(--panel);color:var(--text);
        border:1px solid var(--line);border-radius:16px 16px 16px 4px}
.chat-card{background:var(--panel);border:1px solid var(--line);border-radius:10px;
           padding:12px 14px;flex:1;min-width:0;max-width:560px}
.rc-name{margin:0}
.rc-name a{color:var(--text);text-decoration:none}
.rc-name a:hover{color:var(--accent)}
.rc-meta{color:var(--muted);font-size:12.5px;margin:2px 0 10px}
/* the recipe card's photo: a banner across the top of the card, cropped to a
   consistent strip so a column of cards keeps its rhythm whatever shape the
   model returned. Bleeds to the card's edges by cancelling its padding. */
.rc-shot{display:block;position:relative;margin:-12px -14px 10px;border-radius:9px 9px 0 0;
         overflow:hidden}
.rc-shot img{display:block;width:100%;height:150px;object-fit:cover;
             background:var(--panel2)}
.rc-acts{display:flex;gap:6px;flex-wrap:wrap}
/* The newest card is the conversation's answer: its ready bar takes the full
   width and the other verbs share the row underneath. Older cards are drafts
   that were superseded — same buttons, flat row, no bar. */
.rc.latest .rc-keep{flex:1 0 100%;padding:9px 14px;font-size:13.5px}
/* The three that follow share the row underneath and wrap as a row rather
   than wrapping their labels — "Envoyer vers Cookidoo" is a long verb. */
.rc.latest .rc-acts .btn:not(.rc-keep){flex:1 1 auto;white-space:nowrap}
.rc:not(.latest) .rc-keep:not(.on){background:var(--panel);border-color:var(--line);
                                   color:var(--text)}
.rc:not(.latest) .rc-keep:not(.on):hover{background:var(--panel2)}
.btn .ck{width:15px;height:15px;flex:none;fill:none;stroke:currentColor;stroke-width:2.4;
         stroke-linecap:round;stroke-linejoin:round}
/* Ready reads as a settled green state, not an invitation to press again. */
.rc-keep.on{background:var(--ok-bg);border-color:var(--ok-line);color:var(--ok-fg)}
.rc-keep.on:hover{background:var(--ok-bg)}
.rc.done{border-color:var(--ok-line)}
.rc.done .rc-shot::after{content:"✓";position:absolute;top:8px;right:8px;
        width:24px;height:24px;border-radius:50%;display:flex;align-items:center;
        justify-content:center;font-size:13px;font-weight:700;
        background:var(--ok-bg);border:1px solid var(--ok-line);color:var(--ok-fg)}
.idea-row{display:flex;gap:12px;align-items:flex-start;padding:9px 0;
          border-bottom:1px solid var(--line)}
.idea-row:last-of-type{border-bottom:none}
.idea-main{flex:1;min-width:0}
.idea-name{font-weight:650;margin:0;font-size:14px}
.idea-min{color:var(--muted);font-weight:500;font-size:12px;margin-left:6px;white-space:nowrap}
.idea-one{color:var(--muted);font-size:13px;margin:2px 0 0}
.idea-side{flex:none;display:flex;flex-direction:column;align-items:flex-end;gap:4px}
.idea-status{font-size:12px;margin:0;text-align:right}
.ic-foot{padding-top:8px}

/* The found-on-Cookidoo strip: a compact stack of outbound links between the
   assistant's reply and the recipe card. Rows echo the ideas card's rhythm;
   the thumbnails stay small — this is a citation, not a menu. */
.ckc-head{display:flex;align-items:center;gap:7px;margin:0 0 4px;
          color:var(--muted);font-size:12.5px;font-weight:650}
.ckc-head svg{width:15px;height:15px;flex:none;fill:none;stroke:currentColor;
              stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.ckc-row{display:flex;gap:10px;align-items:center;padding:8px 0;
         border-bottom:1px solid var(--line)}
.ckc-row:last-of-type{border-bottom:none;padding-bottom:2px}
.ckc-link{display:flex;gap:10px;align-items:center;flex:1;min-width:0;
          text-decoration:none;color:var(--text)}
.ckc-link:hover .ckc-name{color:var(--accent)}
.ckc-save{flex:none}
.ckc-shot{flex:none;width:52px;height:40px;object-fit:cover;border-radius:7px;
          background:var(--panel2)}
.ckc-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.ckc-name{font-weight:650;font-size:13.5px;overflow:hidden;text-overflow:ellipsis;
          white-space:nowrap}
.ckc-meta{color:var(--muted);font-size:12px}

.composer2{flex:none;padding:6px 0 14px;background:var(--bg)}
.composer-box{border:1px solid var(--line);border-radius:14px;background:var(--panel);
              padding:12px 12px 10px}
.composer-box:focus-within{border-color:color-mix(in srgb,var(--accent) 55%,var(--line))}
.composer-box textarea{border:none;background:transparent;border-radius:0;resize:none;
                       padding:2px 4px 8px;font-size:15px;display:block;
                       min-height:52px;max-height:150px;overflow-y:auto}
.composer-box textarea:focus-visible{outline:none}
.send-btn{width:34px;height:34px;flex:none;border:none;border-radius:9px;
          background:var(--accent);color:var(--on-accent);
          display:inline-flex;align-items:center;justify-content:center}
.send-btn svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:2.2;
              stroke-linecap:round;stroke-linejoin:round}
.send-btn:hover{filter:brightness(1.06)}
.send-btn:disabled{opacity:.5;cursor:default}
.send-btn .spin{margin-right:0}
.refine-badge{display:inline-flex;align-items:center;gap:7px;background:var(--info-bg);
              color:var(--info-fg);border:1px solid var(--info-line);border-radius:999px;
              padding:3px 11px;font-size:12px;font-weight:600;margin:0 0 8px;max-width:100%}
.refine-badge span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.refine-badge button{background:none;border:none;color:inherit;padding:0 2px;font-size:14px;
                     line-height:1;flex:none}
.composer2-row{display:flex;gap:8px;margin-top:2px;align-items:center;
               justify-content:space-between}
/* the mode picker sits quietly in the box: plain words, the active one lit */
.mode-seg{margin:0;width:auto;padding:0;gap:2px;background:transparent;border:none}
.mode-seg .seg-btn{flex:none;padding:5px 10px;font-size:13px;border-radius:9px}
.mode-seg .seg-btn.on{background:var(--panel3);box-shadow:none}

.pane-list{border-left:1px solid var(--line);display:flex;flex-direction:column;
           overflow:hidden;background:var(--bg);min-width:0}
/* the pane hosts two lists; data-list on the pane picks which one shows */
.list-seg{flex:none;margin:12px 12px 0}
.list-view{flex:1;min-height:0;display:none;flex-direction:column}
.pane-list[data-list="threads"] .list-view[data-view="threads"]{display:flex}
.pane-list[data-list="recipes"] .list-view[data-view="recipes"]{display:flex}
.pane-list[data-list="lists"] .list-view[data-view="lists"]{display:flex}
.thread-main{text-decoration:none;display:block}
/* thread rows have no meta line; centre the title on the row */
.chat-thread .thread-main{padding-top:10px;padding-bottom:10px}

@media (max-width: 900px){
  .duo-body{grid-template-columns:1fr}
  .top-tabs{display:flex;margin:0 auto}
  .top-tabs .seg-btn{padding:6px 12px}
  .pane-list{display:none;border-left:none}
  /* the topbar tabs already choose the list; the pane's own switcher goes */
  .list-seg{display:none}
  .duo-body[data-tab="threads"] .pane-list,
  .duo-body[data-tab="recipes"] .pane-list,
  .duo-body[data-tab="lists"] .pane-list{display:flex}
  .duo-body[data-tab="threads"] .pane-chat,
  .duo-body[data-tab="recipes"] .pane-chat,
  .duo-body[data-tab="lists"] .pane-chat{display:none}
  /* four tabs on a phone: the labels are short, the padding gives way */
  .top-tabs .seg-btn{padding:6px 8px;font-size:12px}
  /* the mark alone is the logo on phones; the tabs take the true centre —
     margin-left:auto on the hamburger would steal a share of the space */
  .topbar .side-logo>span:not(.side-mark){display:none}
  .topbar .menu-toggle{margin-left:0}
}
@media (max-width: 640px){
  .nc-lbl{display:none}
  /* 16px inputs, or iOS Safari zooms the whole page on focus */
  input[type=text],input[type=search],input[type=number],input[type=password],input[type=email],
  textarea,select,.composer-box textarea{font-size:16px}
}

/* ---------------------------------------------------------------------------
   streaming draft (shared by the chat and the document's feedback card)
--------------------------------------------------------------------------- */

.tagline{color:var(--muted);margin:0 0 14px;font-size:14px}

/* streaming draft: the ring spins steadily, only the label pulses */
.stream-status{color:var(--muted);font-size:13px}
.stream-status .stream-label{animation:pulse 1.6s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.45}}
.stream-cursor::after{content:"▊";color:var(--accent);animation:pulse 1s step-end infinite;
                      margin-left:2px;font-weight:400}
.draft-ing{color:var(--muted);font-size:14px}
.draft-steps{font-size:14px}
/* the assistant talking: the sentence as it is written, sized like the bubble
   that replaces it when the turn ends */
.stream-reply{font-size:14px;margin:6px 0 0;white-space:pre-wrap;overflow-wrap:anywhere}

/* ---------------------------------------------------------------------------
   recipe document page
--------------------------------------------------------------------------- */

.doc{max-width:720px;margin:0 auto;padding:26px 18px 110px}
/* no header bar on the document: the hamburger floats at the page's top right
   (anchored to the body, not the centred column, so it matches the other pages) */
.doc .menu-toggle{position:absolute;top:14px;right:14px}
.doc .doc-back{display:inline-block;margin-bottom:12px;text-decoration:none}
.doc .doc-back:hover{text-decoration:underline;text-underline-offset:2px}
.doc>h1{padding-right:44px}
/* the dish photo heads the document — the picture of the thing you are about
   to cook, so it gets room. 4:3 rather than 16:9: the photos are generated
   square at the cheapest size tier, and a widescreen crop would throw away
   nearly half the height and then stretch what was left across a desktop
   column. 4:3 keeps it sharp while still leaving the ingredients on screen. */
.doc-shot-wrap{position:relative;margin:0 0 14px}
.doc-shot{display:block;width:100%;aspect-ratio:4/3;object-fit:cover;
          border-radius:12px;background:var(--panel2);margin:0}
/* redraw sits on the photo itself — the eye judging the picture is already
   there, and the pill below is full */
.doc-redraw{position:absolute;right:10px;bottom:10px;width:34px;height:34px;border-radius:50%;
  border:none;background:rgba(0,0,0,.5);color:#fff;display:inline-flex;align-items:center;
  justify-content:center;cursor:pointer;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}
.doc-redraw:hover{background:rgba(0,0,0,.7)}
.doc-redraw:disabled{opacity:.5;cursor:default}
.doc-redraw svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round}
.doc-desc{margin:2px 0 8px;color:var(--muted);font-size:14.5px}
/* the photo's credit: the library asks that its photographers be named, and
   this is the quietest place on the page that still counts as naming them */
.doc-credit{margin:0 0 10px;color:var(--subtle);font-size:11.5px}
/* the shared copy: no hamburger to dodge, and a quiet line saying whose page
   the reader has landed on */
.doc-public>h1{padding-right:0}
.doc-shared{margin:0 0 10px;font-size:12.5px;font-weight:600;
            letter-spacing:.04em;text-transform:uppercase;color:var(--muted)}
.made-with{display:flex;gap:12px;align-items:center;justify-content:space-between;
           flex-wrap:wrap}
.made-with p{margin:0;color:var(--muted);font-size:13.5px}
.doc-src{margin:0 0 14px;font-size:12.5px;color:var(--muted)}
.doc-src a{color:var(--accent);font-weight:600}
.draft-note{background:var(--panel2);border:1px solid var(--line);border-radius:10px;
            padding:9px 13px;font-size:12.5px;color:var(--muted);margin:12px 0}

/* the overview line under the title: verdict dot + label, servings, times */
.doc-meta{display:flex;align-items:center;gap:7px;flex-wrap:wrap;
          color:var(--muted);font-size:13px;font-weight:500;margin:0 0 14px}

/* "More" pane rows: versions and scale pills share one quiet row shape */
.more-row{display:flex;gap:10px;margin:0 0 10px;flex-wrap:wrap;align-items:center}
.more-lbl{color:var(--muted);font-size:13px;font-weight:600}

.ing-row{display:flex;gap:12px;padding:7px 0;font-size:14px;align-items:flex-start;cursor:pointer}
/* Centered on the row's first text line (line box ≈ 21.7px, box 17px), so it
   tracks the ingredient name even when a note wraps underneath. */
.ing-chk{width:17px;height:17px;flex:none;margin:2px 0 0;accent-color:var(--accent);
         cursor:pointer}
.ing-row:has(.ing-chk:checked){opacity:.55}
.ing-row:has(.ing-chk:checked) .ing-name{text-decoration:line-through;
         text-decoration-color:var(--muted);text-decoration-thickness:1px}
.ing-qty{min-width:70px;flex:none;color:var(--muted);font-variant-numeric:tabular-nums}
.ing-name{flex:1}
.ing-prep{color:var(--muted)}
.ing-note{display:block;color:var(--muted);font-size:12px}
.tag{display:inline-block;font-size:10.5px;border:1px solid var(--line);border-radius:5px;
     padding:0 5px;color:var(--muted);margin-left:6px;vertical-align:middle;white-space:nowrap}
.tag.buy{color:var(--warn-fg);border-color:color-mix(in srgb,var(--warn-fg) 35%,transparent)}
.tag.ok{color:var(--ok-fg);border-color:color-mix(in srgb,var(--ok-fg) 35%,transparent)}

.step{display:flex;gap:11px;background:var(--panel);border:1px solid var(--line);
      border-radius:10px;padding:11px 13px;margin:0 0 8px;font-size:14px;box-shadow:var(--hi)}
.step-n{width:22px;height:22px;flex:none;border-radius:50%;background:var(--panel2);
        color:var(--muted);display:inline-flex;align-items:center;justify-content:center;
        font-size:11.5px;font-weight:700;margin-top:1px}
.step-body{flex:1;min-width:0}
.step-body p{margin:0}
.step-meta{margin-top:6px;display:flex;gap:6px;flex-wrap:wrap}
.step-adds{margin-top:6px;display:flex;gap:6px;flex-wrap:wrap}
.add-pill{background:var(--panel2);border:1px solid var(--line);border-radius:6px;
          padding:2px 8px;font-size:12px;color:var(--muted)}
.add-pill b{color:var(--text);font-variant-numeric:tabular-nums;margin-right:2px}
.set-pill{background:color-mix(in srgb,var(--ok-fg) 13%,transparent);color:var(--ok-fg);
          border:1px solid color-mix(in srgb,var(--ok-fg) 32%,transparent);border-radius:6px;
          padding:2px 8px;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums}
.man-pill{background:var(--panel2);color:var(--muted);border:1px solid var(--line);
          border-radius:6px;padding:2px 8px;font-size:12px}

/* the floating action pill — plandrop's plan-view .detail-actions grammar:
   a blurred translucent pill of round buttons, icon-only on phones, labeled
   from 640px up. position:fixed pins it to the iframe viewport when framed. */
.pill-bar{position:fixed;left:0;right:0;bottom:0;z-index:20;display:flex;justify-content:center;
          pointer-events:none;padding:0 14px max(16px,env(safe-area-inset-bottom))}
.pill{display:flex;gap:4px;pointer-events:auto;
      background:color-mix(in srgb,var(--panel) 86%,transparent);
      border:1px solid var(--line);border-radius:999px;padding:5px;
      box-shadow:0 12px 32px rgba(0,0,0,.28),0 2px 8px rgba(0,0,0,.14);
      backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px)}
.pill-btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;
          height:40px;min-width:40px;padding:0;border:0;border-radius:999px;
          background:transparent;color:var(--text);font:inherit;font-weight:600;
          font-size:13px;text-decoration:none;cursor:pointer}
.pill-btn:hover{background:var(--panel2);color:var(--text)}
.pill-btn:active{background:var(--panel2)}
.pill-btn svg{width:17px;height:17px;flex:none;fill:none;stroke:currentColor;
              stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
.pill-btn.pr{background:var(--accent);color:var(--on-accent)}
.pill-btn.pr:hover{filter:brightness(1.06);background:var(--accent);color:var(--on-accent)}
/* the Cookidoo button wears the bowl and its blade, which has finer detail in
   it than the other glyphs — a hair thinner keeps them apart at 17px */
.pill-btn.ck svg{width:18px;height:18px;stroke-width:1.6}
/* the button carries both bowls — plain and checked — and wears whichever the
   recipe's state calls for, so a push answers without reloading the page */
.pill-btn.ck .ckg-done{display:none}
.pill-btn.ck.ck-on .ckg-done{display:block}
.pill-btn.ck.ck-on .ckg:not(.ckg-done){display:none}
/* and it stops wearing the accent once the copy exists: a recipe already over
   there is a settled state, not the pill's primary invitation. Green on green
   is what "done" says everywhere else on this page (the ready card, the row
   badge), and the swapped fill is visible from further away than a swapped
   glyph is. It still pushes — a re-push replaces the copy. */
.pill-btn.ck.ck-on,.pill-btn.ck.ck-on:hover{background:var(--ok-bg);
       color:var(--ok-fg);box-shadow:inset 0 0 0 1.5px var(--ok-fg);filter:none}
/* the pin is a state, not a destination: off it is one more quiet verb, on it
   wears the accent as an outline rather than a fill, so it reads as "held"
   next to the Cookidoo button's own filled "done" */
.pill-btn.pin.on{color:var(--accent);box-shadow:inset 0 0 0 1.5px var(--accent)}
.pill-btn .lbl{display:none}
@media (min-width: 640px){
  .pill-btn{padding:0 14px}
  .pill-btn .lbl{display:inline}
}

/* the shelf line in the Upload sheet: what the push will cost, said before it
   is made */
.shelf-line{font-variant-numeric:tabular-nums}

/* bottom sheets behind the pill's Edit and Upload buttons */
.sheet{position:fixed;left:0;right:0;bottom:0;z-index:60;background:var(--panel);
       border:1px solid var(--line);border-bottom:none;border-radius:18px 18px 0 0;
       box-shadow:0 -12px 34px rgba(0,0,0,.3);
       padding:16px 16px max(18px,env(safe-area-inset-bottom));
       max-height:80vh;max-height:80dvh;overflow-y:auto}
@media (min-width: 640px){
  .sheet{left:50%;right:auto;bottom:24px;transform:translateX(-50%);width:520px;
         max-width:calc(100vw - 48px);border-bottom:1px solid var(--line);border-radius:16px}
}
.sheet-head{display:flex;align-items:center;gap:8px;margin:0 0 10px}
.sheet-head h3{flex:1;margin:0}
.sheet-x{background:none;border:none;color:var(--muted);font-size:15px;
         padding:5px 9px;border-radius:8px;line-height:1}
.sheet-x:hover{background:var(--panel2);color:var(--text)}

.scale-pills{display:inline-flex;gap:5px}
.scale-pills a{border:1px solid var(--line);border-radius:999px;padding:4px 12px;font-size:13px;
               color:var(--muted);text-decoration:none;font-weight:600}
.scale-pills a:hover{color:var(--accent);border-color:var(--accent)}
.scale-pills a.on{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}

/* rating stars */
.stars{display:inline-flex;gap:2px}
.star{background:none;border:none;font-size:22px;color:var(--line);padding:2px}
.star.on{color:var(--yellow)}
.star:hover{color:var(--yellow)}

/* export tabs */
.tabs{display:flex;gap:4px;border-bottom:1px solid var(--line);margin:0 0 12px;flex-wrap:wrap}
.tab{background:none;border:none;border-bottom:2px solid transparent;color:var(--muted);
     padding:7px 12px;font-weight:600;font-size:13px;margin-bottom:-1px}
.tab:hover{color:var(--text)}
.tab.on{color:var(--accent);border-bottom-color:var(--accent)}
.export-text{width:100%;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
             font-size:12px;background:var(--well);min-height:200px}
.transfer-steps{font-size:13.5px;color:var(--muted)}
.split{display:flex;gap:8px;flex-wrap:wrap;margin:10px 0}

/* the share sheet's link row: the URL takes the space, Copy keeps its size */
.share-row{display:flex;gap:8px;align-items:center;margin:10px 0}
.share-row input{flex:1;min-width:0;font-size:13px}
.share-row .btn{flex:none}

/* transient toasts (TM6.toast) — the pill grammar again, stacked into the
   bottom-right corner, above every sheet and scrim, gone on its own. Newest
   sits closest to the corner, older ones ride up. When a page carries the
   floating action pill, the stack clears it. */
.toasts{position:fixed;bottom:calc(14px + env(safe-area-inset-bottom));right:0;z-index:70;
        display:flex;flex-direction:column;align-items:flex-end;gap:8px;
        max-width:min(420px,100vw);pointer-events:none;padding:0 14px}
body:has(.pill-bar) .toasts{bottom:calc(78px + env(safe-area-inset-bottom))}
.toast{pointer-events:auto;display:flex;align-items:center;gap:12px;max-width:100%;
       background:color-mix(in srgb,var(--panel) 92%,transparent);
       border:1px solid var(--line);border-radius:999px;padding:9px 16px;
       font-size:13.5px;font-weight:600;color:var(--text);
       box-shadow:0 12px 32px rgba(0,0,0,.28),0 2px 8px rgba(0,0,0,.14);
       backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
       opacity:0;transform:translateY(8px);transition:opacity .18s ease,transform .18s ease}
.toast.in{opacity:1;transform:none}
.toast.ok{border-color:var(--ok-line);color:var(--ok-fg)}
.toast.err{border-color:var(--crit-line);color:var(--crit-fg)}
.toast a{color:inherit;font-weight:700;flex:none}
/* under 900px the chat pane is the full width, so the composer owns the
   bottom-right corner — the stack rides above it (--composer-h from shell.js)
   rather than swallowing taps meant for Send */
@media (max-width: 900px){
  .toasts{bottom:calc(14px + var(--composer-h,0px) + env(safe-area-inset-bottom))}
}

/* pull to refresh (pull.js) — one indicator, borrowed by whichever scroller
   is being pulled: the same circular arrow the rebuild button carries, on a
   chip that grows in below the scroller's own top edge and comes down with
   the pull. --ptr-d is how far the pull has travelled, --ptr-t how much of
   the way to armed that is; the glyph turns with the pull and spins once the
   refresh is running. It rides over the list rather than pushing it down: a
   transform on the content would make every fixed thing inside it — the
   floating pill above all — position against the moved box instead of the
   viewport. The ring of page background is what keeps it legible over the
   first row. The attribute on <html> is set by pull.js only where it wired
   something up, so a page it left alone keeps the browser's own gesture. */
html[data-ptr]{overscroll-behavior-y:contain}
.ptr{position:fixed;top:var(--ptr-top,0px);left:var(--ptr-x,50%);z-index:35;
     width:34px;height:34px;margin-left:-17px;display:none;
     align-items:center;justify-content:center;border-radius:50%;
     background:var(--panel);border:1px solid var(--line);color:var(--muted);
     box-shadow:0 8px 22px -8px rgba(0,0,0,.6),0 0 0 5px var(--bg);
     pointer-events:none;
     transform:translateY(calc(6px + var(--ptr-d,0px) * .5))
               scale(clamp(.55,var(--ptr-t,0),1));
     opacity:clamp(0,var(--ptr-t,0),1)}
.ptr.on{display:flex}
.ptr.ease{transition:transform .24s ease,opacity .24s ease}
.ptr svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:2;
         stroke-linecap:round;stroke-linejoin:round;
         transform:rotate(calc(var(--ptr-t,0) * 200deg))}
.ptr.armed{color:var(--accent);border-color:color-mix(in srgb,var(--accent) 45%,var(--line))}
.ptr.run{color:var(--accent)}
.ptr.run svg{transform:none;animation:spin .9s linear infinite}

/* combobox (model picker) */
.combo{position:relative}
.combo-list{position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:20;
            background:var(--panel);border:1px solid var(--line);border-radius:9px;
            box-shadow:0 10px 32px -10px rgba(0,0,0,.3),var(--hi);
            max-height:260px;overflow-y:auto;margin:0;padding:5px;list-style:none}
.combo-option{padding:7px 10px;border-radius:7px;font-size:13.5px;cursor:pointer;margin:0}
.combo-option:hover,.combo-option.combo-active{background:var(--panel2)}
.combo-option.combo-current{color:var(--accent);font-weight:600}
.combo-empty{padding:7px 10px;color:var(--muted);font-size:13px}

/* ---------------------------------------------------------------------------
   settings: one centred column of cards, each opened by an icon-chip header
--------------------------------------------------------------------------- */

.set-col{max-width:620px;margin:0 auto;padding:8px 0 48px}
.set-hero{margin:10px 0 20px}
.set-hero .tagline{margin:3px 0 0}
.set-col .card{margin:0 0 16px;padding:18px}
.set-head{display:flex;align-items:center;gap:12px;margin:0 0 14px}
.set-head-main{min-width:0}
.set-head h3{margin:0}
.set-head .hint{margin:2px 0 0}
.set-ico{width:34px;height:34px;flex:none;border-radius:10px;
         background:rgba(99,102,241,.12);border:1px solid rgba(99,102,241,.26);
         color:#a5b4fc;display:inline-flex;align-items:center;justify-content:center}
.set-ico svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.7;
             stroke-linecap:round;stroke-linejoin:round}
/* single compact controls (the language select) stop at a hand's width;
   text inputs and the model combo stay full-bleed */
.set-ctl{max-width:380px}
/* A one-line preference: box and sentence on the same baseline. */
.check{display:flex;align-items:flex-start;gap:9px;cursor:pointer;max-width:480px}
.check input{flex:none;width:16px;height:16px;margin-top:2px;accent-color:var(--accent)}
.check span{font-size:13.5px}
.set-state{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:0 0 12px}
.badge.sm{padding:2px 9px;font-size:11px}
.set-col .btn.danger{border-color:var(--crit-line)}

/* devices */
.devices{list-style:none;padding:0;margin:0 0 12px}
.devices li{border-bottom:1px solid var(--line);padding:8px 0;margin:0}
.devices li:last-child{border-bottom:none}
.devices .ua{font-size:13px;word-break:break-all;margin:0}
.devices .ua .badge{margin-left:6px;vertical-align:1px;white-space:nowrap}
.devices .sub{font-size:12px;color:var(--muted);margin:2px 0 0}

/* ---------------------------------------------------------------------------
   cooking mode
--------------------------------------------------------------------------- */

.cook{display:flex;flex-direction:column;height:100vh;height:100dvh;max-width:760px;
      margin:0 auto;padding:0 18px}
.cook-head{display:flex;justify-content:space-between;align-items:center;padding:14px 0 10px}
.cook-progress{font-size:13px;color:var(--muted);font-weight:600;font-variant-numeric:tabular-nums}
.cook-bar{height:4px;background:var(--panel2);border-radius:2px;overflow:hidden;flex:none}
.cook-bar-fill{height:100%;background:var(--accent);border-radius:2px;width:0;
               transition:width .25s ease}
.cook-body{flex:1;overflow-y:auto;padding:22px 0}
.cook-step{display:none}
.cook-step.on{display:block}
.cook-adds{background:var(--panel);border:1px solid var(--line);border-radius:12px;
           padding:14px 18px;margin:0 0 18px;box-shadow:var(--hi)}
.cook-adds h3{font-size:12px;text-transform:uppercase;letter-spacing:.1em;color:var(--muted)}
.cook-adds ul{margin:8px 0 0;padding:0;list-style:none}
.cook-adds li{font-size:16px;margin:.35em 0}
.cook-instruction{font-size:22px;line-height:1.4;margin:0 0 14px}
.cook-manual{color:var(--muted);font-size:16px}
.cook-settings{display:inline-block;background:color-mix(in srgb,var(--ok-fg) 13%,transparent);
               color:var(--ok-fg);border:1px solid color-mix(in srgb,var(--ok-fg) 32%,transparent);
               border-radius:10px;padding:8px 16px;font-size:18px;font-weight:700;
               font-variant-numeric:tabular-nums}
.cook-nav{display:flex;gap:10px;padding:12px 0 18px;flex:none}
.cook-nav .btn{flex:1;padding:13px}

/* ---------------------------------------------------------------------------
   gate + static pages
--------------------------------------------------------------------------- */

.gate{min-height:100vh;min-height:100dvh;display:flex;align-items:center;justify-content:center;
      padding:20px}
.gate-card{max-width:400px;width:100%;text-align:center;padding:28px 26px}
.gate-card .side-mark{width:40px;height:40px;font-size:19px;border-radius:11px;margin:0 auto 14px}
.gate-card .tagline{margin-bottom:20px}
.fine{color:var(--muted);font-size:12px}
.fine a{color:var(--muted)}

/* the household card's client-rendered share list */
#household-card input{margin:4px 0 8px}

.page{max-width:720px;margin:0 auto;padding:32px 18px 64px}
.page .foot{color:var(--muted);font-size:13px;margin-top:34px;text-align:center}

/* ---------------------------------------------------------------------------
   mobile: hamburger drop-card, fullscreen sheet
--------------------------------------------------------------------------- */

.scrim{position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:40;border:none;padding:0}
.drop-card{position:fixed;top:10px;left:10px;right:10px;z-index:50;background:var(--panel);
           border:1px solid var(--line);border-radius:14px;padding:10px;
           box-shadow:0 18px 48px -12px rgba(0,0,0,.35),var(--hi);
           transform:translateY(-8px) scale(.98);opacity:0;
           transition:transform .18s cubic-bezier(.2,1.4,.4,1),opacity .15s}
.drop-card.open{transform:none;opacity:1}
.drop-card .side-nav{padding:11px 12px;font-size:15px}
/* wider screens: the card drops from the hamburger's corner instead of
   spanning the viewport */
@media (min-width: 641px){
  .drop-card{left:auto;right:16px;top:54px;width:280px}
}

@media (max-width: 900px){
  .shell{grid-template-columns:1fr}
  .side{display:none}
  .list-tools{padding-top:8px}
  .list-head{display:flex;align-items:center;gap:10px;padding:12px 12px 0}
  .list-head .side-logo{margin:0;flex:1}

  .shell.two{grid-template-columns:1fr}
}
@media (min-width: 901px){
  .list-head{display:none}
}
@media (max-width: 640px){
  .doc{padding:20px 12px 104px}
  .stile .n{font-size:1.45em}
  .cook-instruction{font-size:19px}
}


/* ---------------------------------------------------------------------------
   shopping lists
   --------------------------------------------------------------------------- */

/* Selection mode in the recipes pane. The checkbox is on every row and only
   claims space once the pane is selecting, so turning the mode on never
   re-renders the list. */
.thread-pick{display:none;flex:none;align-self:center;margin-left:12px;
             width:17px;height:17px;accent-color:var(--accent)}
.pane-list.selecting .thread-pick{display:block}
.pane-list.selecting .thread-acts{display:none}
.pane-list.selecting .thread{cursor:pointer}
.select-bar{flex:none;display:flex;align-items:center;justify-content:space-between;
            gap:10px;padding:10px 12px;border-top:1px solid var(--line);
            background:var(--panel);font-size:12.5px;color:var(--muted)}

/* The list page reuses the recipe document's frame; only the list itself is
   its own shape. */
.shop .band{margin:18px 0 6px}
.shop .sl-aisle:first-of-type .band{margin-top:10px}
.sl-from{margin:-2px 0 10px;font-size:12.5px;color:var(--muted)}
.sl-from a{color:var(--muted)}
.sl-row .ing-qty{min-width:74px}
.sl-row .ing-note{display:block;font-size:11.5px;color:var(--muted)}
.ing-row:has(.sl-chk:checked){opacity:.55}
.ing-row:has(.sl-chk:checked) .ing-name{text-decoration:line-through}
/* Halfway down an aisle, what is left to buy is the only interesting half, so
   the list can be told to keep only that. A row ticked while the filter is on
   lingers for a moment before it goes, so a mis-tick is still there to undo,
   and an aisle goes with its last visible row. */
.sl-hide{font-size:13px;font-weight:500;color:var(--muted)}
.sl-hide[aria-pressed="true"]{color:var(--accent)}
.shop.hide-done .sl-row.done{display:none}
.shop.hide-done .sl-row.done.grace{display:flex;opacity:.3}
.shop.hide-done .sl-aisle:not(:has(.sl-row:not(.done))):not(:has(.grace)){display:none}
/* When the filter has hidden the last aisle, the basket card stands where the
   aisles stood — same conditions as the aisle rule above, inverted. */
.sl-basket{display:none}
.shop.hide-done:not(:has(.sl-row:not(.done))):not(:has(.grace)) .sl-basket{
  display:flex;flex-direction:column;align-items:center;gap:8px;
  padding:44px 20px;text-align:center;animation:basket-in .35s ease}
.sl-basket svg{width:46px;height:46px;fill:none;stroke:var(--ok-fg);stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round}
.sl-basket p{margin:2px 0 0;font-size:15px;font-weight:600}
.sl-basket .link-btn{font-size:13px;font-weight:500;color:var(--muted)}
@keyframes basket-in{from{opacity:0;transform:translateY(8px)}}
/* Everything no recipe asked for — milk, bread, batteries — typed at the foot
   of the list. The rows it makes are the only ones that can be taken off
   again: a line the cook invented is a line the cook can be wrong about,
   while an ingredient a recipe wants is answered with the tick, not the bin.
   The bin lives inside the row's label, where a click on it never reaches the
   checkbox. */
/* scroll-margin so that whatever scrolls this into view — a tap on the field
   with a keyboard coming up, the browser's own focus scroll — leaves the
   floating pill's height clear underneath, instead of parking the field
   behind it. */
.sl-add{display:flex;gap:8px;align-items:center;margin:22px 0 0;scroll-margin-bottom:96px}
.sl-add input{flex:1}
.sl-add .btn{flex:none}
.sl-add .btn svg{width:15px;height:15px;flex:none;fill:none;stroke:currentColor;
  stroke-width:2;stroke-linecap:round}
.sl-add-hint{margin:6px 0 0}
.sl-rm{flex:none;background:none;border:none;padding:1px 0 1px 8px;line-height:0;
       color:var(--muted)}
.sl-rm svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round}
.sl-rm:hover{color:var(--crit-fg)}
.sl-rm:disabled{opacity:.4;cursor:default}
/* A line still in the air. It stands between the list and the field it was
   typed into — dashed, because it is not part of the list yet — and it is the
   only place a failed add can live: the field has moved on to the next thing
   by then. Empty at rest, and its own label goes with it. */
.sl-pend{margin:20px 0 0;display:flex;flex-direction:column;gap:4px}
.sl-pend:empty{display:none}
.sl-pend::before{content:attr(data-label);font-size:10.5px;text-transform:uppercase;
  letter-spacing:.13em;color:var(--muted);font-weight:700;margin-bottom:2px}
/* Nothing left in the air, only failures: the heading says so rather than
   going on promising. CSS-only, off the same kind of :has state as the
   basket card. */
.sl-pend:has(.sl-pending.err):not(:has(.sl-pending:not(.err)))::before{
  content:attr(data-label-failed);color:var(--crit-fg)}
.sl-pending{background:var(--panel);border:1px dashed var(--line);border-radius:9px;
  padding:7px 12px;font-size:14px;cursor:default}
.sl-pending .ing-name{font-style:italic;color:var(--muted)}
.sl-pending .spin{margin:3px .45em 0 0}
.sl-pending.err{border-color:var(--crit-line);border-style:solid;background:var(--crit-bg)}
.sl-pending.err .ing-name{font-style:normal;color:var(--text)}
.sl-pending.err .ing-note{color:var(--crit-fg)}
.sl-pend-mark{flex:none;width:17px;margin:1px 0 0;text-align:center;font-weight:700;
  color:var(--crit-fg)}
.sl-pend-act{flex:none;background:none;border:none;padding:0 0 0 10px;font-size:15px;
  line-height:1.2;color:var(--muted)}
.sl-pend-act:hover{color:var(--text)}
/* Where it went. A row the server has just written is lit for a moment, so an
   add that landed in an aisle you cannot see still shows itself when you get
   there — and a line that merged into one already on the list is not mistaken
   for nothing having happened. */
.sl-row.arrive{animation:sl-arrive 1.5s ease-out}
@keyframes sl-arrive{
  0%{background:color-mix(in srgb,var(--accent) 24%,transparent)}
  100%{background:transparent}
}
.sl-add-hint.err{color:var(--crit-fg)}
/* the list sheet's choices: one list per row, stacked */
#list-choices{display:flex;flex-direction:column;gap:6px;margin:10px 0}
#list-choices .list-choice{justify-content:flex-start}
/* whose recipe this is, when a household shares a library */
.doc-owner{margin:0 0 4px;font-size:12.5px;color:var(--muted)}
/* The transcription credit under the description: quiet, but a real link. */
.doc-source{margin:0 0 4px;font-size:12.5px;color:var(--muted)}
.doc-source a{color:var(--accent);text-decoration:none}
.doc-source a:hover{text-decoration:underline}
.doc-source-meta{margin-left:6px}
/* deleting a finished list: red enough to notice, quiet enough not to be
   the first thing a thumb finds on the pill */
.pill-btn.danger{color:var(--crit-fg)}
.pill-btn.danger:hover{background:var(--crit-bg)}

/* Calling a recipe ready: the document's one decision, asked out loud under
   the title while it is pending and shrunk to a green line once answered. The
   pane's ⌫ is the same verb undone from the list side. */
.ready-card{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin:14px 0 0;
            padding:12px 14px;border:1px solid var(--line);border-radius:12px;
            background:var(--panel);box-shadow:var(--hi)}
.ready-copy{flex:1;min-width:190px}
.ready-h{margin:0;font-size:14px;font-weight:650;color:var(--text)}
.ready-p{margin:3px 0 0;font-size:12.5px;line-height:1.5;color:var(--muted)}
.ready-go{flex:none}
.ready-card.on{background:var(--ok-bg);border-color:var(--ok-line);padding:9px 14px}
.ready-card.on .ready-h{color:var(--ok-fg)}
.ready-card.on .ready-h::before{content:"✓ "}
.ready-card.on .ready-p{font-size:12px}
.ready-card.on .ready-go{background:transparent;border-color:transparent;color:var(--muted);
                         padding-left:8px;padding-right:8px}
.ready-card.on .ready-go:hover{color:var(--text);background:transparent}
.ready-card.on .ready-go .ck{display:none}
@media (max-width:560px){.ready-go{width:100%;justify-content:center}}
.thread-acts .keep-off{font-size:13px}

/* in Cookidoo: the machine's own glyph, on the row and as a filter beside the
   favourites star — a wordy tag ate the width a recipe name needs */
/* the row badge is a chip, not a glyph dropped into the meta line: a green
   ring and fill of its own, or it reads as one more grey word among dates */
.ck-mark{display:inline-flex;align-items:center;justify-content:center;
         vertical-align:-4px;width:19px;height:19px;border-radius:999px;
         background:var(--ok-bg);border:1px solid var(--ok-line);color:var(--ok-fg)}
.ck-mark svg{width:13px;height:13px;fill:none;stroke:currentColor;stroke-width:1.6;
             stroke-linecap:round;stroke-linejoin:round}
/* the check is the whole point of the mark at 13px — draw it heavier than the
   bowl it sits in so it survives the size */
.ckg-done path:last-child{stroke-width:2.4}
.ck-filter{display:inline-flex;align-items:center;justify-content:center}
.ck-filter svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.6;
               stroke-linecap:round;stroke-linejoin:round}
.ck-filter.on{color:var(--ok-fg);border-color:var(--ok-line)}
/* the shelf meter: how many Cookidoo slots this app's copies are using out of
   the budget it is allowed. It sits with the filters because it is about the
   same thing they are — what is over there — and it stays quiet (muted, no
   fill) until the last slot, when it turns the colour of a limit being met */
.ck-meter{flex:none;display:inline-flex;align-items:center;padding:0 8px;
          border:1px solid var(--line);border-radius:8px;background:var(--panel);
          color:var(--muted);font-size:11.5px;font-weight:700;white-space:nowrap;
          font-variant-numeric:tabular-nums}
.ck-meter.full{color:var(--warn-fg);border-color:var(--warn-line)}
/* a pinned row wears the pin next to the bowl: the bowl says it is over there,
   the pin says rotation will not take it */
.pin-mark{display:inline-flex;align-items:center;justify-content:center;
          margin-left:4px;color:var(--accent)}
.pin-mark svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:1.7;
              stroke-linecap:round;stroke-linejoin:round}
