
  /* Pretendard Variable, bundled (app\fonts, OFL): the app makes no request to another host. */
  @font-face{font-family:"Pretendard Variable";src:url("fonts/PretendardVariable.woff2") format("woff2-variations"),
    url("fonts/PretendardVariable.woff2") format("woff2");font-weight:45 920;font-style:normal;font-display:swap}
  /* "몽글몽글한 아이같은" - the direction the first memo asked for.
     Soft, warm, rounded; nothing sharp. Two hard floors that are graded by
     test/rubric.js and must not drift: no text under 12px (a tired parent
     reads this one-handed at 6am) and every tappable thing at least 44px. */
  :root {
    /* V1 look (2026-10-04), values from work\develop_20261003\visual\v1.css. --sub,
       --faint and --accent-2 are darker than V1 so no text loses contrast against
       the green system it replaces (work\develop_20261003\build\v1\RESULT.md).
       Var names are kept exactly as they were: 식단/장보기 CSS reads --bg, --card,
       --accent, --sub and the D2 aliases, and a renamed token is a silent blank. */
    --bg:#F6F5F1; --card:#FFFFFF; --ink:#141414; --sub:#717171;
    --accent:#17785A; --accent-soft:#EAF4EF; --line:#E8E7E2;
    --ok:#17785A; --warn:#A3552F; --warn-soft:#F7E7DF;
    --well:#F1F0EB; --peach:#E9C3B7; --pink:#D9A99B;
    /* design-up "surface" (work\design_up_20261007 DU1): a warm floor, every block a white surface with a hairline
       ring and one of two shadows - --shadow-s for rows and pills, --shadow-m for the next meal and its CTA (DU4 7) */
    --hair:rgba(20,20,20,.07);
    --ring:0 0 0 1px rgba(20,20,20,.06) inset;
    --shadow-s:0 1px 2px rgba(20,20,20,.04), 0 6px 18px -8px rgba(20,20,20,.12);
    --shadow-m:0 2px 4px rgba(20,20,20,.04), 0 12px 28px -10px rgba(20,20,20,.16);
    /* an empty checkbox and an empty track: grey enough to be seen, never
       dark enough to read as "off is wrong" */
    --box:#C1C1C1; --track:#EBEBEB;
    --r:24px; --r-sm:16px;
    --shadow:var(--ring),var(--shadow-s);
    --tap:44px;
    /* D2 design system tokens */
    --surface:#FFFFFF; --muted:#717171; --sel:#17785A; --sel-soft:#EAF4EF;
    --hero-bg:#FFFFFF; --hero-ink:#141414; --hero-muted:#717171;
    --avatar-bg:#141414; --pill-bg:#F4F4F2; --pill-ink:#141414;
    --food-bg:#EAF4EF; --dock-bg:#F4F4F2; --dock-ink:#141414;
    --tab-bg:rgba(255,255,255,.96);
    --lift:var(--ring),var(--shadow-m); --tile-shadow:var(--ring),var(--shadow-s);
    --r-lg:24px; --r-md:18px; --r-cta:999px;
    --cta-bg:#17785A; --cta-ink:#FFFFFF; --cta-shadow:none;
    --display:"Pretendard Variable",Pretendard,-apple-system,"Apple SD Gothic Neo",system-ui,sans-serif;
    --display-w:700;
    --body:"Pretendard Variable",Pretendard,-apple-system,"Apple SD Gothic Neo","Malgun Gothic",system-ui,sans-serif;
    --dot-on:#17785A;
    --carb:#D9B26A; --prot:#C97C6A; --fat:#7FA9A3;
    /* recipe drawings (D4/D7 mockup fills). One set only: this sheet carries no
       prefers-color-scheme rules anywhere, so a dark value for these four would
       make the recipe block the one thing that flips on a light page. */
    --rec-grain:#F3E6D8; --rec-grain-line:#C9B49A; --rec-water:#D6E8F5;
    --rec-veg:#BFE0C7; --rec-veg-lite:#CFE6D4; --rec-meat:#E9C3B7;
    --rec-range:#7FA9A3;
  }
  svg.i { width:20px; height:20px; flex:none; }
  /* the mockup's heading badge: a round inset well with the icon inside */
  .ico { width:34px; height:34px; border-radius:50%; background:var(--well);
    box-shadow:inset 0 1px 3px rgba(120,90,60,.10); display:inline-flex;
    align-items:center; justify-content:center; color:var(--accent); flex:none; }
  .ico svg { width:18px; height:18px; }
  /* Long explanations fold behind a ⓘ. The sources still have to BE on the
     screen - this app does not show a number it cannot attribute - but a parent
     holding a baby at 6am should not have to read a paragraph to see a gauge. */
  details.fold { }
  /* min-, not a fixed box: a summary that carries TEXT (.gfold, .shop-fold) is
     the same element, and 44px of WIDTH folds its line into a letter column. */
  details.fold > summary { list-style:none; cursor:pointer; position:absolute; top:5px; right:5px;
    min-width:var(--tap); min-height:var(--tap); display:flex; align-items:center; justify-content:center;
    padding:4px; color:var(--sub); line-height:1; white-space:nowrap; }
  details.fold > summary::-webkit-details-marker { display:none; }
  details.fold > summary::marker { content:""; }
  details.fold[open] > summary { color:var(--accent); }
  details.fold > summary svg { width:18px; height:18px; }
  details.fold > *:not(summary) { margin-top:8px; }
  * { margin:0; padding:0; box-sizing:border-box; -webkit-tap-highlight-color:transparent; }
  html { touch-action:pan-x pan-y; }
  body { font-family:var(--body);
    background:radial-gradient(900px 420px at 50% -120px, rgba(23,120,90,.07), transparent 70%) no-repeat, var(--bg); color:var(--ink); max-width:520px; margin:0 auto;
    padding:16px var(--gutter) 90px; line-height:1.6; -webkit-font-smoothing:antialiased; }
  .notice { color:var(--sub); font-size:12px; margin-bottom:14px; line-height:1.6; }
  h1 { font-size:22px; font-weight:700; letter-spacing:-.02em; line-height:1.2; margin:0; }
  .sub { color:var(--sub); font-size:14px; margin-bottom:22px; }
  .card { background:var(--card); border-radius:var(--r); padding:22px 20px;
    margin-bottom:16px; box-shadow:var(--shadow); position:relative; }
  .card h2 { font-size:17px; letter-spacing:-.01em; margin-bottom:14px;
    display:flex; align-items:center; gap:10px; min-width:0; }
  label { font-size:13px; color:var(--sub); display:block; margin-bottom:6px; }
  input[type=date], input[type=text] { width:100%; min-height:var(--tap); padding:12px 14px;
    border:1.5px solid var(--line); border-radius:var(--r-sm); font-size:16px;
    margin-bottom:14px; background:var(--bg); color:var(--ink); font-family:inherit;
    transition:border-color .18s ease; }
  input[type=date]:focus, input[type=text]:focus { outline:none; border-color:var(--accent); }
  .chips { display:flex; flex-wrap:wrap; gap:8px; }
  .chip { min-height:var(--tap); display:inline-flex; align-items:center; padding:0 16px;
    border:1.5px solid var(--line); border-radius:999px; font-size:14px; background:var(--card);
    cursor:pointer; user-select:none; }
  .chip.on { background:var(--warn-soft); border-color:var(--warn); color:var(--warn); font-weight:600; }
  button.primary { width:100%; min-height:52px; padding:15px; background:var(--accent);
    color:#fff; border:none; border-radius:999px; font-size:17px; font-weight:700;
    font-family:inherit; cursor:pointer; margin-top:10px;
    box-shadow:0 4px 14px rgba(239,139,82,.28); }
  button.btn-sec { background:none; border:1.5px solid var(--accent); color:var(--accent);
    border-radius:999px; font-size:13px; font-family:inherit; padding:6px 14px;
    cursor:pointer; white-space:nowrap; }
  .wk-kv, .wk-refuse2 .td-kv { display:flex; justify-content:space-between; gap:10px; font-size:14px; padding:6px 0; white-space:nowrap; }
  .wk-kv b { font-weight:700; }
  #week .day { background:var(--card); border-radius:var(--r-lg); box-shadow:var(--shadow);
    padding:4px 14px; margin-bottom:12px; }
  /* V1 rows: badge + foods / base · tags · state, the text button at the end. */
  :is(#week,#pp-plan) .wk-row { display:flex; align-items:center; gap:8px; width:100%; padding:10px 0; border:0;
    border-bottom:1px solid var(--line); background:none; font-family:inherit; text-align:left; color:var(--ink); }
  :is(#week,#pp-plan) .wk-row:last-child { border-bottom:0; }
  :is(#week,#pp-plan) .wk-open { flex:1; min-width:0; display:flex; align-items:center; gap:10px; cursor:pointer; }
  :is(#week,#pp-plan) .wk-row .td-th { width:52px; height:52px; border-radius:8px; object-fit:cover; flex:none; }
  :is(#week,#pp-plan) .wk-row .td-tx { flex:1; min-width:0; }
  :is(#week,#pp-plan) .wk-row .td-tx b { display:block; font-size:15px; font-weight:700; line-height:1.7;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  :is(#week,#pp-plan) .wk-row .td-tx em { display:block; font-style:normal; color:#7A8480; font-size:12px; line-height:1.3;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  :is(#week,#pp-plan) .wk-row .td-tx em :is(u,i) { text-decoration:none; font-style:normal; color:var(--accent); font-weight:700; }
  :is(#week,#pp-plan) .wk-row .td-tx em s { text-decoration:none; color:#A3321D; font-weight:700; }
  :is(#week,#pp-plan) .m-name { margin:0; }
  :is(#week,#pp-plan) .m-name .new { display:inline-block; background:var(--accent-soft); color:var(--accent);
    font-size:12px; font-weight:700; margin-left:6px; padding:0 8px; border-radius:999px; line-height:1.6; }
  :is(#week,#pp-plan) .wk-sw { flex:none; width:auto; height:auto; min-height:36px; padding:0 12px; border:1px solid var(--line); border-radius:999px;
    background:var(--card); font-family:inherit; font-size:13px; font-weight:700; color:var(--accent);
    white-space:nowrap; cursor:pointer; }
  #week .pocket { cursor:pointer; }
  #week .pocket .td-tx b { color:var(--accent); }
  #week .day-h { display:flex; align-items:center; justify-content:space-between; padding:8px 0 0; }
  #week .day-h #empty-chip { font-size:12px; color:var(--sub); }
  /* §6 요일 띠: the days, then 다음 주 ›. Days before the week's first are dim, a skipped day struck. */
  #week .wk-days { gap:4px; }
  #week .wk-days > * { min-width:0; }
  #week .wk-dim { flex:1; min-height:52px; display:flex; flex-direction:column; align-items:center; justify-content:center;
    font-size:14px; color:var(--sub); opacity:.45; }
  #week .wk-skip { text-decoration:line-through; color:var(--sub); }
  #week .wk-nextd { flex:1; min-height:52px; border:1px solid var(--accent); border-radius:16px; background:var(--card);
    color:var(--accent); font-family:inherit; font-size:13px; font-weight:700; display:flex; flex-direction:column;
    align-items:center; justify-content:center; white-space:nowrap; cursor:pointer; }
  #week .wk-nextd small { color:var(--accent); font-weight:700; }
  .wk-link { display:block; width:100%; min-height:var(--tap); border:0; background:none; font-family:inherit;
    font-size:14px; font-weight:700; color:var(--accent); cursor:pointer; margin-bottom:4px; white-space:nowrap; }
  .wk-foot { text-align:center; font-size:12px; color:var(--sub); margin:0 0 12px; white-space:nowrap;
    overflow:hidden; text-overflow:ellipsis; }
  .wk-skipgo { display:flex; flex-direction:column; align-items:center; gap:2px; width:100%; margin-top:12px;
    padding:12px; border:1.5px solid var(--accent); border-radius:var(--r-cta); background:var(--card);
    color:var(--accent); font-family:inherit; cursor:pointer; }
  .wk-skipgo b { font-size:16px; font-weight:800; }
  .wk-skipgo small { font-size:12px; color:var(--sub); }
  /* §6 생성 거부: a red-edged card, the emptied group's foods with why and 되돌리기. */
  .wk-refuse { border-left:4px solid #A3321D; padding:14px; margin-bottom:12px; }
  .wk-refuse .wk-rt { display:block; font-size:16px; font-weight:800; color:#A3321D; }
  .wk-refuse > small { display:block; font-size:13px; color:var(--sub); margin:4px 0 8px; }
  .wk-lbl { font-size:12px; font-weight:600; color:var(--sub); margin:10px 0 4px; }
  .wk-opt { display:flex; align-items:center; gap:8px; padding:8px 0; border-bottom:1px solid var(--line); }
  .wk-opt small { display:block; font-size:12px; color:var(--sub); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .wk-opt .td-sp { flex:1; min-width:0; }
  .wk-refuse2 { padding:8px 14px; margin-bottom:12px; }
  .react-btn { min-height:var(--tap); font-size:13px; font-weight:600; color:var(--accent);
    border:1.5px solid var(--accent); background:var(--card); border-radius:999px; padding:0 14px;
    cursor:pointer; font-family:inherit; white-space:nowrap; flex:none; }
  .cart-detail { padding-top:4px; }
  a.buy { min-height:var(--tap); display:inline-flex; align-items:center; padding:0 16px;
    font-size:13px; color:#fff; background:var(--accent); text-decoration:none;
    font-weight:700; white-space:nowrap; border-radius:999px; }
  .cart-detail.nopick a.buy { float:right; }
  .note { font-size:14px; color:var(--sub); line-height:1.7; margin-top:12px; }
  .excluded { background:var(--warn-soft); border-radius:var(--r-sm); padding:11px 15px;
    font-size:13px; color:var(--warn); margin-bottom:8px; font-weight:600; }
  #banned { margin-bottom:8px; }
  .sh-cat-h { font-size:17px; font-weight:700; padding:0 0 12px; display:flex;
    align-items:center; gap:8px; flex-wrap:wrap; line-height:1.3; }
  /* The UA's [hidden] rule loses to ANY author display rule, so .chips or an
     inline display:block left 간식 설정 on screen at 완료기 while the script
     had set hidden = true. Author origin + !important is what actually wins. */
  [hidden] { display:none !important; }
  .hidden { display:none; }
  .privacy { font-size:12px; color:var(--sub); margin:6px 0 14px; }
  .privacy-detail summary { list-style:none; cursor:pointer; display:inline;
    color:var(--sub); text-decoration:underline; }
  .privacy-detail summary::-webkit-details-marker { display:none; }
  .privacy span { display:block; font-size:12px; color:var(--ink); margin-top:6px; }
  .data-row { display:flex; gap:8px; margin-top:6px; }
  .data-row button { flex:1; min-height:var(--tap); padding:0 8px; font-size:13px;
    border:1.5px solid var(--line); background:var(--card); border-radius:999px;
    cursor:pointer; color:var(--ink); font-family:inherit; }
  .data-row button.danger { color:var(--warn); border-color:var(--warn-soft); }
  .why { font-size:14px; color:var(--sub); margin-top:3px; line-height:1.6; }
  .highrisk { margin-top:16px; padding-top:16px; border-top:1.5px solid var(--line); }
  .hr-line { display:flex; align-items:center; gap:10px; min-height:var(--tap);
    margin-bottom:0; cursor:pointer; }
  .hr-line input { width:22px; height:22px; accent-color:var(--accent); flex:none; }
  .hr-line span { font-size:14px; color:var(--ink); word-break:keep-all; }
  .hr-what { display:none; margin-top:8px; }
  .highrisk:has(#highrisk:checked) .hr-what { display:block; }
  .hr-head { font-size:13px; font-weight:700; color:var(--ink); }
  .hr-list { margin:4px 0 0; padding-left:18px; font-size:13px; line-height:1.6;
    color:var(--ink); }
  .hr-what .note { font-size:12px; line-height:1.5; margin-top:8px; }
  .rec { margin:2px 0 8px; }
  .rec summary { min-height:36px; display:flex; align-items:center; font-size:12px;
    color:var(--accent); font-weight:700; cursor:pointer; list-style:none;
    padding:0 12px; background:var(--accent-soft); border-radius:999px;
    width:fit-content; }
  .rec summary::-webkit-details-marker { display:none; }
  .recipe { background:var(--bg); border-radius:var(--r-sm); padding:14px 16px;
    margin-top:8px; font-size:14px; }
  .recipe .r-h { font-size:13px; font-weight:700; color:var(--sub);
    margin:12px 0 6px; }
  .recipe .r-h:first-child { margin-top:0; }
  .recipe p { color:var(--ink); font-size:14px; line-height:1.6; word-break:keep-all; }
  /* ---- recipe card (STACK #25, 2026-09-25) --------------------------
     Every rule is scoped to .recipe.rr so the older .rec / .rl / .meal rules
     cannot reach in: .rec summary is a descendant rule and .rl p comes later
     in this sheet. Floors: text >= 12px, taps >= 44px. */
  .recipe.rr { display:grid; grid-template-columns:1fr 1fr; }
  .recipe.rr > .rr-body { grid-column:1 / -1; min-width:0; }
  /* 한 끼 / 이번 주: two radios, each after its label; the pill is a later sibling
     so :checked can move it. No script. */
  .rr-v { position:absolute; opacity:0; width:1px; height:1px; margin:0; pointer-events:none; }
  .rr-track, .rr-pill, .rr-sl { grid-row:1; }
  .rr-track { grid-column:1 / -1; background:var(--well); border-radius:var(--r-cta); z-index:0; }
  .rr-pill { grid-column:1; margin:4px; background:var(--card); border-radius:var(--r-cta);
    box-shadow:var(--shadow); z-index:1; }
  .rr-vw:checked ~ .rr-pill { grid-column:2; }
  .rr-v:focus-visible ~ .rr-pill { outline:2px solid var(--accent); outline-offset:1px; }
  .rr-sl { z-index:2; min-height:calc(var(--tap) + 8px); display:flex; align-items:center;
    justify-content:center; font-size:15px; font-weight:700; color:var(--ink); cursor:pointer; }
  .rr-slm { grid-column:1; } .rr-slw { grid-column:2; }
  .recipe.rr > .rr-sl ~ .rr-body { margin-top:12px; }
  .recipe.rr .rr-wk { display:none; }
  .rr-vw:checked ~ .rr-body .rr-meal { display:none; }
  .rr-vw:checked ~ .rr-body div.rr-wk { display:block; }
  .rr-vw:checked ~ .rr-body span.rr-wk { display:inline; }
  /* header: one line under the photo, so step 1 is on the first screen (STACK #205) */
  .recipe.rr .rr-hl { display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 12px; font-size:13px; color:var(--sub); }
  .recipe.rr .rr-hl b { font-size:14px; color:var(--ink); }
  .recipe.rr .rr-hs { font-weight:700; color:var(--accent); }
  .recipe.rr .rr-alg { display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin-top:6px; }
  .recipe.rr .rr-alg span { font-size:12px; font-weight:700; color:var(--warn); }
  .recipe.rr .rr-alg b { font-size:13px; color:var(--warn); background:var(--warn-soft); border-radius:var(--r-cta); padding:1px 8px; }
  .recipe.rr .rr-bt { margin-top:6px; font-size:13px; color:var(--sub); }
  .recipe.rr .rr-bt b { color:var(--ink); }
  /* css/today.css lays .rr-head out as a grid of tiles; this head is one block */
  .rp-root .rp-body .rr-head.rr-hd { display:block; margin:10px 0; }
  .recipe.rr .r-h { font-size:15px; color:var(--ink); margin:20px 0 8px; }
  .recipe.rr .r-h span { font-weight:400; color:var(--sub); font-size:13px; }
  .recipe.rr .rr-line { font-size:14px; margin-top:6px; }
  .recipe.rr .rr-ratio { font-size:13px; color:var(--sub); }
  /* tier tags: the publisher rides in the title, the rows of 안전 say it in full */
  .recipe.rr .rr-tag { display:inline-block; font-size:12px; font-weight:500; color:var(--sub);
    border:1px solid var(--line); border-radius:6px; padding:0 6px; margin-left:4px; line-height:1.6;
    white-space:nowrap; vertical-align:middle; }
  .recipe.rr .rr-tag.rr-off { color:var(--ok); border-color:var(--accent-soft);
    background:var(--accent-soft); font-weight:700; }
  /* 재료: name and grams, two to a line */
  .recipe.rr ul.rr-ing { display:grid; grid-template-columns:1fr 1fr; gap:0 12px; margin:0; padding:0; list-style:none; }
  .recipe.rr ul.rr-ing li { min-height:28px; display:flex; flex-wrap:wrap; align-items:center; gap:0 6px; font-size:14px; }
  .recipe.rr ul.rr-ing li b { font-size:14px; white-space:nowrap; }
  .recipe.rr .rr-water { display:flex; flex-wrap:wrap; gap:4px 10px; align-items:baseline; margin-top:8px;
    background:var(--rec-water); border-radius:var(--r-sm); padding:8px 12px; font-size:14px; }
  .recipe.rr .rr-water > span { color:var(--sub); font-size:13px; }
  /* 만들기: the day-of checklist. The .me- parts are css/today.css's, which scopes the
     tick and the chip to .me-root; the same values are repeated here for this page. */
  .recipe.rr .me-steps { margin:4px 0 0; padding:0; list-style:none; }
  .recipe.rr .me-tick { position:relative; flex:none; display:grid; place-items:center; width:28px; height:28px; padding:0;
    border-radius:50%; border:2px solid var(--accent-soft); background:#fff; color:var(--accent); font-size:13px; font-weight:700; }
  .recipe.rr .me-on .me-tick { background:var(--accent); border-color:var(--accent); color:#fff; }
  .recipe.rr .me-timer { display:inline-flex; align-items:center; gap:6px; min-height:44px; padding:0 12px 0 6px; border:0;
    border-radius:var(--r-cta); background:var(--accent-soft); color:var(--accent-2); font-size:13px; font-weight:700; white-space:nowrap; }
  .recipe.rr .me-timer.me-run { background:var(--accent); color:#fff; }
  .recipe.rr .rr-from { align-self:center; font-size:13px; color:var(--sub); }
  .recipe.rr p.rr-do { font-size:15px; line-height:1.55; margin:0; }
  .recipe.rr .rr-done { margin-top:6px; line-height:1.45; }
  .recipe.rr .rr-done-h { font-size:12px; font-weight:700; color:var(--accent); margin-right:6px; }
  .recipe.rr .rr-done-t { font-size:15px; font-weight:700; color:var(--ink); word-break:keep-all; }
  .recipe.rr .rr-key { display:flex; flex-wrap:wrap; align-items:baseline; gap:6px 8px; margin-top:6px; }
  .recipe.rr .rr-key > span:first-child { font-size:12px; color:var(--sub); }
  .recipe.rr .rr-key b { font-size:15px; color:var(--ink); }
  .recipe.rr .rr-heat { display:inline-block; margin-right:6px; padding:0 6px; border-radius:6px; background:var(--warn-soft);
    font-size:12px; color:var(--warn); font-weight:700; }
  /* 분량과 보관 · 안전: a heading row that folds, then rows - name left, number right */
  .recipe.rr .rr-fh { display:flex; align-items:center; gap:4px; }
  .recipe.rr .rr-fh .r-h { margin:0; }
  .recipe.rr .rr-fold { margin-left:auto; min-height:var(--tap); min-width:var(--tap); padding:0 2px 0 12px; border:0; background:none;
    color:var(--sub); font-size:13px; font-weight:600; }
  .recipe.rr .rr-fold::after, .recipe.rr .rr-chev { content:""; display:inline-block; flex:none; width:6px; height:6px; margin-left:6px;
    border:solid currentColor; border-width:0 1.5px 1.5px 0; transform:translateY(-2px) rotate(45deg); color:var(--sub); }
  .recipe.rr [aria-expanded="true"]::after, .recipe.rr [aria-expanded="true"] .rr-chev { transform:translateY(1px) rotate(-135deg); }
  .recipe.rr ul.rr-rows { margin:0; padding:0; list-style:none; }
  .recipe.rr .rr-row { display:flex; align-items:center; gap:10px; min-height:44px; padding:6px 0; border-top:1px solid var(--line); }
  .recipe.rr .rr-row:first-child { border-top:0; }
  .recipe.rr .rr-rn { flex:1; min-width:0; font-size:14px; color:var(--ink); }
  .recipe.rr .rr-rn small { display:block; font-size:12px; color:var(--sub); }
  .recipe.rr .rr-row b, .recipe.rr .rr-rowb > b { font-size:17px; font-weight:800; color:var(--ink); text-align:right; word-break:keep-all; }
  .recipe.rr .rr-dont .rr-rn { color:var(--sub); }
  .recipe.rr .rr-ic { flex:none; width:18px; height:18px; fill:none; stroke:var(--warn); stroke-width:1.6; }
  .recipe.rr .rr-srow { display:block; padding:0; }
  .recipe.rr .rr-rowb { display:flex; align-items:center; gap:10px; width:100%; min-height:48px; padding:6px 0; border:0;
    background:none; color:inherit; font:inherit; text-align:left; }
  .recipe.rr .rr-sq { padding:0 0 8px; }
  .recipe.rr .rr-q { margin:6px 0; font-size:13px; line-height:1.55; word-break:keep-all; }
  .recipe.rr .rr-q b { display:block; font-size:13px; font-weight:700; text-align:left; }
  .recipe.rr .rr-q q { display:block; color:var(--ink); quotes:none; }
  .recipe.rr .rr-pub { display:block; font-size:12px; color:var(--sub); }
  .recipe.rr .rr-pub b { display:inline; font-size:12px; }
  /* the running timers: one bar pinned above the tab bar while any runs */
  .recipe.rr .rr-tbar { grid-column:1 / -1; position:sticky; bottom:calc(var(--tabbar-h, 64px) + 8px + env(safe-area-inset-bottom));
    z-index:20; display:flex; flex-wrap:wrap; gap:4px 14px; margin-top:12px; padding:10px 14px; border-radius:var(--r-md);
    background:var(--ink); color:#fff; font-size:14px; box-shadow:var(--shadow); }
  .recipe.rr .rr-tbar[hidden] { display:none; }
  .recipe.rr .rr-tb b { font-weight:700; }
  /* ---- 이번 주 밑준비 (D4) ------------------------------------------ */
  /* Collapsed by default so the day strip keeps its place on a 390px screen. */
  .rec-week { margin-bottom:12px; }
  .rec-week > summary { min-height:var(--tap); display:flex; align-items:center;
    font-size:13px; font-weight:700; color:var(--accent); cursor:pointer;
    list-style:none; padding:0 16px; background:var(--accent-soft);
    border-radius:999px; width:fit-content; }
  .rec-week > summary::-webkit-details-marker { display:none; }
  .rec-week > summary::marker { content:""; }
  .wp-card { background:var(--card); border-radius:var(--r-md); padding:14px 12px;
    margin-top:10px; box-shadow:var(--tile-shadow); }
  .wp-h { display:flex; align-items:baseline; gap:8px; padding:0 4px 8px; }
  .wp-h b { flex:1; font-size:15px; }
  .wp-h span { font-size:12px; color:var(--sub); }
  .wp-r { display:grid; grid-template-columns:54px repeat(7, minmax(0,1fr)) 56px;
    column-gap:3px; align-items:center; min-height:34px; }
  .wp-head span { text-align:center; font-size:12px; font-weight:700; color:var(--sub);
    padding:5px 0; border-radius:8px 8px 0 0; }
  .wp-head span.on { color:var(--warn); background:var(--accent-soft); }
  /* The name wraps rather than clipping: an ingredient the parent has to buy
     must not be shown as "달걀 노...". */
  .wp-n { font-size:12px; font-weight:700; line-height:1.25; word-break:keep-all;
    padding:4px 0; }
  .wp-c { display:flex; align-items:center; justify-content:center; height:34px; }
  .wp-c.on { background:var(--accent-soft); }
  .wp-dot { width:4px; height:4px; border-radius:999px; background:var(--box); }
  .wp-circ { width:22px; height:22px; border-radius:999px; background:var(--rec-grain);
    border:1.5px solid var(--rec-grain-line); display:flex; align-items:center;
    justify-content:center; font-size:12px; font-weight:700; font-style:normal; }
  .wp-circ.sm { width:12px; height:12px; border-width:1px; }
  .wp-cubes { display:flex; flex-wrap:wrap; gap:2px; justify-content:center;
    align-items:center; max-width:28px; }
  .wp-cube { width:12px; height:12px; border-radius:3px;
    border:1px solid rgba(23,25,28,.18); background:var(--rec-veg); }
  .wp-cube.meat { background:var(--rec-meat); }
  .wp-cube.today { background:var(--accent-soft); border-color:var(--pink); }
  .wp-g { text-align:right; font-size:12px; line-height:1.3; }
  .wp-g span { display:block; color:var(--sub); }
  .wp-note { font-size:12px; color:var(--sub); line-height:1.5; padding:0 4px 6px; }
  /* 큐브 칸은 줄 밑 오른쪽 끝이다. 요일 칸과 같은 줄에 서면 390px 에서 한 칸이
     15px 로 줄어 12px 큐브 하나도 못 들어간다(측정: .wp-c 32.6px -> 15px). */
  .wp-cu { display:flex; justify-content:flex-end; padding:2px 4px 8px; }
  .cube-pill { min-height:var(--tap); display:inline-flex; align-items:center;
    padding:0 18px; border-radius:var(--r-cta); border:1.5px solid var(--accent);
    background:var(--card); color:var(--accent); font-family:inherit; font-size:13px;
    font-weight:700; cursor:pointer; }
  /* 색은 어디에 서든 같고, 44px 은 눌리는 것에만 준다 - 장보기 줄의 같은 꼬리표는
     누르는 것이 아니라서 손가락 크기를 가질 이유가 없다. */
  /* 장보기 줄은 `.mid` 가 gap 0 이라 꼬리표가 이름에 닿는다(E3 인계). */
  .mid .cube-tag { margin:2px 0; }
  .cube-tag.warn { background:var(--warn-soft); color:var(--warn); }
  .cube-tag.expired { background:var(--warn-soft); color:var(--warn); font-weight:700; }
  .wp-cu .tag.cube-tag { height:auto; min-height:var(--tap); padding:0 16px;
    border:1.5px solid transparent; font-family:inherit; font-size:13px; cursor:pointer; }
  .wp-cu .tag.cube-tag.expired { border-color:var(--warn); }
  .cube-line { display:flex; align-items:center; gap:14px; }
  .cube-step { width:var(--tap); height:var(--tap); border-radius:14px;
    border:1.5px solid var(--line); background:var(--card); color:var(--ink);
    font-family:inherit; font-size:20px; font-weight:700; line-height:1; cursor:pointer;
    display:inline-flex; align-items:center; justify-content:center; }
  .cube-n { font-size:20px; font-weight:700; min-width:40px; text-align:center; }
  .cube-num { width:100%; min-height:var(--tap); padding:12px 14px;
    border:1.5px solid var(--line); border-radius:var(--r-sm); background:var(--card);
    font-family:inherit; font-size:16px; color:var(--ink); }
  .cube-num:focus { outline:none; border-color:var(--accent); }
  .cube-src { font-size:12px; color:var(--sub); line-height:1.6; margin-top:14px; }
  .cube-src .tier { font-weight:400; color:var(--sub); }
  .cube-drop { min-height:var(--tap); width:100%; border-radius:var(--r-sm);
    border:1.5px solid var(--line); background:var(--card); color:var(--warn);
    font-family:inherit; font-size:15px; font-weight:700; cursor:pointer; }
  .wp-div { height:1px; background:var(--line); margin:4px 0; }
  .wp-legend { display:flex; flex-wrap:wrap; gap:6px 14px; padding:10px 4px 0;
    font-size:12px; color:var(--sub); }
  .wp-legend span { display:flex; align-items:center; gap:6px; }
  .wp-link { min-height:var(--tap); display:flex; align-items:center; padding:0 4px;
    margin-top:2px; border:0; background:none; font-family:inherit; font-size:13px;
    font-weight:700; color:var(--accent); cursor:pointer; }
  .wp-chips { display:flex; flex-wrap:wrap; gap:6px; }
  .wp-chips span { padding:7px 12px; border-radius:999px; background:var(--bg);
    font-size:13px; font-weight:600; }
  .wp-two { display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-bottom:10px; }
  .wp-two div { background:var(--rec-water); border-radius:var(--r-sm); padding:10px 12px; }
  .wp-two span { display:block; font-size:12px; color:var(--sub); }
  .wp-two b { font-size:17px; }
  .wp-src { font-size:12px; color:var(--sub); line-height:1.6; margin-top:10px; }
  .wp-same { display:flex; align-items:center; gap:10px; margin-top:10px;
    padding:12px 14px; border-radius:var(--r-sm); background:var(--food-bg);
    color:var(--ok); font-size:13px; font-weight:600; line-height:1.5; }
  .rec-week .tier.official { color:var(--ok); font-weight:700; font-size:12px; }
  .opt { font-size:12px; font-weight:400; color:var(--sub); background:var(--bg);
    padding:3px 10px; border-radius:999px; margin-left:6px; vertical-align:middle; }
  .grid2 { display:grid; grid-template-columns:1fr 1fr; gap:0 12px; }
  .cu-sum { font-size:13px; font-weight:700; color:var(--ink); margin-top:12px; }
  .cu-ok { background:var(--accent-soft); color:var(--ink); border-radius:var(--r-sm);
    padding:11px 15px; font-size:13px; margin-top:8px; line-height:1.6; }
  .reset-have { min-height:36px; font-size:12px; color:var(--accent); font-weight:700;
    border:1.5px solid var(--accent-soft); background:var(--accent-soft);
    border-radius:999px; padding:0 12px; margin-left:6px; cursor:pointer;
    font-family:inherit; }
  .carried { font-size:12px; font-weight:700; color:var(--warn); margin-top:4px;
    opacity:1; text-decoration:none; }
  .moved { background:var(--warn); color:#fff; border-radius:var(--r-sm);
    padding:16px; margin-bottom:18px; font-size:14px; line-height:1.6; }
  .moved span { display:block; font-size:13px; font-weight:400; opacity:.92;
    margin:6px 0 12px; }
  .moved button { width:100%; min-height:var(--tap); border:none; border-radius:999px;
    background:#fff; color:var(--warn); font-weight:700; font-size:15px;
    font-family:inherit; cursor:pointer; }
  .moved .moved-next { margin-top:8px; background:transparent; color:#fff; border:1.5px solid #fff; }
  .cart-item.got a.buy { display:none; }
  .subs { background:var(--card); border-radius:var(--r-sm); box-shadow:var(--tile-shadow);
    padding:12px 14px; font-size:13px; margin-bottom:8px; line-height:1.6;
    display:flex; flex-direction:column; gap:6px; }
  .subs .subs-h { display:flex; align-items:center; gap:6px; font-size:12px;
    font-weight:700; color:var(--sub); }
  .subs .subs-h svg { width:16px; height:16px; flex:none; }
  .subs b { color:var(--warn); }
  .subs .none { color:var(--warn); font-weight:600; }

  /* ---- 장보기 (2026-09-17, 깐깐함 x 양) -------------------------------
     work\mockup_two_axis_20260917 의 승인된 그림. 돈은 두 축의 결과라 합계가
     첫 카드고, 그 돈을 쓰는 버튼은 탭 바 위 독에 있다. 바닥 둘은 그대로다:
     12px 밑으로 내려가는 글자 없음, 누르는 것은 44px 이상. */
  .pg[data-pg="shop"] { padding-bottom:78px; }
  .card.shop-sum, .card.axes-card, .card.shop-list { padding:16px; }
  .shop-total { display:flex; flex-direction:column; gap:2px; }
  .shop-total .st-k { font-size:12px; color:var(--sub); line-height:16px; }
  .shop-total .st-v { font-size:28px; font-weight:700; line-height:34px; letter-spacing:-.4px; }
  /* 낱말이 들어오는 자리(살 것이 없어요)는 숫자보다 작게 - 같은 크기면 줄이 넘친다. */
  .shop-total.none .st-v { font-size:22px; line-height:30px; }
  .shop-total .st-s { font-size:12px; color:var(--sub); line-height:16px; }
  /* 배송: 무슨 돈인지와 어디서 온 숫자인지. 쪼갠 줄(.st-s)과 같은 바닥 12px 이고
     아낄 돈만 강조색이다 - 그 줄만 부모가 누를 수 있는 것을 말한다. */
  .shop-total .st-d { font-size:12px; color:var(--sub); line-height:16px; }
  .shop-total .st-fee { font-size:12px; color:var(--accent); font-weight:700;
    line-height:16px; margin-top:2px; }
  .card.shop-sum .disclose { margin-top:10px; padding-top:10px; border-top:1px solid var(--line); }
  /* 담기 뒤 돌아온 부모에게 묻는 한 줄(2026-09-22). 카드가 아니라 줄이다 - 단정
     하지 않는 질문이 합계 카드만큼 무거우면 안 된다. 누르는 것은 44px. */
  #cart-relogin .relogin { display:flex; align-items:center; gap:8px; margin-bottom:10px;
    padding:10px 12px; border:1px solid var(--line); border-radius:12px; background:var(--card); }
  #cart-relogin .relogin span { flex:1; font-size:12px; line-height:17px; color:var(--sub); }
  #cart-relogin .relogin-go { min-height:var(--tap); padding:0 14px; border:0; border-radius:10px;
    background:var(--accent); color:#fff; font-size:13px; font-weight:700; }
  /* 장보기의 잔글씨는 판의 12px/17px 다. 앱 기본 .note 는 14px/1.7 이라 같은
     문장이 화면에서 한 단계 크게 읽혔다 (fix round 1, item 8). 바닥은 12px. */
  .card.shop-sum .disclose, .axes-card .note, .pg[data-pg="shop"] > .note {
    font-size:12px; line-height:17px; }
  /* 고르는 기준: 두 줄, 각 줄 세 칸 */
  .axes-card { display:flex; flex-direction:column; gap:12px; }
  .axes-head { font-size:13px; font-weight:700; line-height:18px; }
  .axis { display:flex; flex-direction:column; gap:6px; }
  .axis-name { font-size:13px; font-weight:700; line-height:18px; }
  /* 50 = 누를 자리 44 + 양쪽 3px 테. 38px 알약을 44px 틀에 넣으면 정작 엄지가
     닿는 것이 바닥 밑으로 내려간다. */
  .seg { display:flex; gap:2px; height:50px; padding:3px; background:var(--card);
    border:1px solid var(--line); border-radius:15px; }
  .seg button { flex:1 1 0; min-width:0; display:flex; align-items:center; justify-content:center;
    height:44px; border:none; border-radius:12px; background:none; font-family:inherit;
    font-size:12px; font-weight:600; color:var(--sub); white-space:nowrap;
    letter-spacing:-.3px; cursor:pointer; }
  .seg button.on { background:var(--accent); color:#fff; font-weight:700; }
  /* 고르는 기준의 한 칸 = 알약 + 그 값의 합계. 12px 이 바닥이라 11px 로는 적지
     않는다 (shop.js 가 인라인으로 들고 있던 값을 여기로 옮기는 자리). */
  .seg-opt { flex:1; min-width:0; display:grid; gap:3px; }
  .seg-won { font-size:12px; color:var(--sub); text-align:center; }
  .axes-card .note { margin:0; }
  /* 이 앱의 기준 - 머리글이 보이는 접이. 카드 안 ⓘ 와 달리 제 자리를 차지한다. */
  details.fold.shop-fold { background:var(--card); border-radius:var(--r);
    box-shadow:var(--shadow); margin-bottom:16px; }
  details.fold.shop-fold > summary { position:static; display:flex; align-items:center;
    justify-content:space-between; gap:8px; min-height:48px; padding:0 16px;
    font-size:13px; font-weight:700; color:var(--ink); }
  details.fold.shop-fold[open] > summary { color:var(--ink); }
  details.fold.shop-fold > summary .fold-chev { color:var(--sub); display:flex;
    transition:transform .15s; }
  details.fold.shop-fold > summary .fold-chev svg { width:16px; height:16px; }
  details.fold.shop-fold[open] > summary .fold-chev { transform:rotate(90deg); }
  details.fold.shop-fold > *:not(summary) { margin-top:0; }
  .shop-fold .fold-body { display:flex; flex-direction:column; gap:10px;
    padding:12px 16px 16px; border-top:1px solid var(--line); }
  .shop-fold .fold-body p { font-size:13px; line-height:1.5; }
  .shop-fold .fold-body h4 { font-size:12px; font-weight:700; color:var(--sub);
    line-height:16px; }
  .pref-list { margin:0; padding:0; list-style:none; display:flex; flex-direction:column; gap:4px; }
  .pref-list li { font-size:12px; line-height:17px; color:var(--sub); }
  .pref-list b { color:var(--ink); font-weight:700; }
  /* 목록 */
  .cu-sum { margin:0; }
  .card.shop-list { padding:0 16px; }
  .cart-item { display:flex; align-items:center; gap:12px; min-height:56px; padding:8px 0;
    border-bottom:1px solid var(--line); }
  .cart-item:last-child { border-bottom:none; }
  .cart-item.got { opacity:.42; }
  .cart-item.got .name, .cart-item.got .pr { text-decoration:line-through; }
  .tick { position:relative; display:flex; flex-direction:column; align-items:center;
    justify-content:center; gap:2px; min-width:var(--tap); min-height:var(--tap);
    flex:none; margin:0; cursor:pointer; }
  .tick input { position:absolute; inset:0; width:100%; height:100%; margin:0;
    opacity:0; cursor:pointer; }
  .tick .bx { width:21px; height:21px; border-radius:6px; border:1.5px solid var(--box);
    background:#fff; flex:none; display:flex; align-items:center; justify-content:center;
    color:transparent; }
  .tick .bx svg { width:14px; height:14px; }
  .tick input:checked + .bx { background:var(--ok); border-color:var(--ok); color:#fff; }
  .tick .lb { font-size:12px; line-height:14px; color:var(--sub); }
  .it-row { display:flex; align-items:center; gap:10px; flex:1; min-width:0;
    min-height:var(--tap); padding:0; background:none; border:none; width:100%;
    font-family:inherit; text-align:left; cursor:pointer;
    -webkit-tap-highlight-color:transparent; }
  .it-row.nopick { cursor:default; }
  .it-row .mid { flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
  .r-nmline { display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
  .it-row .name { font-size:15px; font-weight:700; color:var(--ink); line-height:20px; }
  .it-row .pd, .it-row .r-sub { font-size:12px; color:var(--sub); line-height:16px;
    overflow-wrap:anywhere; }
  /* 고른 옵션. 제목 줄 안에 흐르므로 320px 에서도 넘치지 않고 줄로 내려간다.
     크기가 없는 옵션명에는 칩이 아예 안 그려진다(optionChip 이 null). */
  .it-row .pd .opt-chip { display:inline; margin-left:5px; padding:1px 5px;
    border-radius:4px; background:var(--accent-soft); color:var(--accent);
    font-weight:700; }
  .it-row .pr { flex:none; display:flex; flex-direction:column; align-items:flex-end;
    gap:1px; text-align:right; font-size:15px; font-weight:700; color:var(--ink);
    white-space:nowrap; }
  .it-row .pr .packs { font-size:12px; color:var(--sub); font-weight:400; line-height:15px; }
  .r-chev { color:var(--sub); flex:none; display:flex; }
  .r-chev svg { width:16px; height:16px; }
  /* 깐깐함이 무엇으로 갈랐는지를 줄 위에 적는다 - 축을 옮기면 이름과 값만이
     아니라 이 칩이 목록을 따라 바뀐다. 표기가 없으면 칩도 없다. */
  .badge-chip { display:inline-flex; align-items:center; height:20px; padding:0 8px;
    border-radius:999px; background:var(--accent-soft); color:var(--accent);
    font-size:12px; font-weight:700; flex:none; max-width:100%; white-space:nowrap;
    overflow:hidden; text-overflow:ellipsis; }
  .ov-chip { display:inline-flex; align-items:center; height:20px; padding:0 8px;
    border-radius:999px; background:var(--warn-soft); color:var(--warn);
    font-size:12px; font-weight:700; flex:none; }
  /* 독: 담기 버튼과 로그인 줄. 탭 바(z-index 30) 밑에 깔린다. */
  .shop-dock { position:fixed; left:0; right:0; bottom:0; z-index:29; max-width:520px;
    margin:0 auto; padding:10px 16px calc(74px + env(safe-area-inset-bottom));
    background:linear-gradient(180deg, rgba(242,243,245,0) 0%, var(--bg) 26%);
    pointer-events:none; }
  .shop-dock > * { pointer-events:auto; }
  .shop-dock .st-go { width:100%; min-height:52px; border:none; border-radius:var(--r-cta);
    background:var(--accent); color:#fff; font-size:15px; font-weight:700;
    font-family:inherit; cursor:pointer; }
  .shop-dock .st-go:disabled { background:#D5D8DD; color:#fff; cursor:default; }
  .shop-dock .st-fine { font-size:12px; line-height:15px; color:var(--sub); margin-top:6px;
    display:flex; align-items:center; justify-content:center; gap:6px; flex-wrap:wrap; }
  .shop-dock .st-fine a { color:var(--sub); text-decoration:underline; }
  /* R5ShopFail state card */
  .shop-state { border-radius:var(--r-md); padding:20px 18px; text-align:center;
    margin-bottom:16px; }
  .shop-state.warn { background:#FFF3D1; color:#7A4E0B; }
  .shop-state .ss-ico { font-size:32px; margin-bottom:8px; }
  .shop-state .ss-h { font-size:17px; font-weight:700; margin-bottom:6px; }
  .shop-state .ss-p { font-size:14px; line-height:1.6; }
  .shop-state .ss-btn { min-height:var(--tap); padding:0 20px; border:none; margin-top:12px;
    background:var(--accent); color:#fff; border-radius:999px; font-size:14px;
    font-weight:700; cursor:pointer; font-family:inherit; }

  /* ---- 상품 시트 (바닥 시트 틀은 phase 1a 의 것) ----------------------
     문장은 모두 머리글 있는 상자 안에 산다 - 배경에 흩어진 글은 안 읽힌다. */
  .sh .blk { display:flex; flex-direction:column; gap:8px; padding:14px;
    border-radius:18px; background:var(--well); margin-top:12px; }
  .sh .blk > h3 { font-size:13px; font-weight:700; line-height:18px; color:var(--sub); }
  .sh .blk p { font-size:13px; line-height:19px; margin:0; }
  .sh .blk p.muted, .sh .blk .why { color:var(--sub); font-size:12px; line-height:17px; margin:0; }
  .prod-top { display:flex; gap:12px; align-items:flex-start; }
  .prod-main { display:flex; flex-direction:column; gap:6px; flex:1; min-width:0; }
  .prod-top .ic { width:40px; height:40px; border-radius:13px; display:flex;
    align-items:center; justify-content:center; flex:none; }
  .ic.c-곡류 { background:#FFF0D9; color:#A86E12; }
  .ic.c-육류 { background:#FBE3E3; color:#A63434; }
  .ic.c-단백질 { background:#F5EADF; color:#8A5E3B; }
  .ic.c-채소 { background:#E6F5EA; color:#2B7F50; }
  .ic.c-과일 { background:#FDE8F0; color:#C0467A; }
  .ic.c-유제품 { background:#EAF0FF; color:#3563C9; }
  .prod-nm { font-size:17px; font-weight:700; line-height:23px; overflow-wrap:anywhere; }
  .prod-px { font-size:14px; line-height:19px; }
  .prod-unit { font-size:13px; color:var(--sub); line-height:17px; }
  .prod-opt { font-size:13px; color:var(--accent); font-weight:600; line-height:17px;
    overflow-wrap:anywhere; }
  .sh .chips { display:flex; flex-wrap:wrap; gap:6px; }
  .sh .chip { min-height:0; height:26px; padding:0 10px; border:1px solid var(--line);
    border-radius:999px; background:#fff; color:var(--sub); font-size:12px;
    font-weight:600; cursor:default; }
  .sh .chip.tier { background:var(--accent-soft); border-color:var(--accent-soft);
    color:var(--accent); font-weight:700; }
  .prod-cta { display:flex; align-items:center; justify-content:center; min-height:var(--tap);
    border-radius:var(--r-cta); background:var(--accent); color:#fff; font-size:14px;
    font-weight:700; text-decoration:none; }
  /* 고른 순서: 칸을 좁히는 계단. 채워진 동그라미는 상품을 말하는 칸 하나뿐이고,
     성분 칸은 고른 이유가 아니라 잰 사실이라 연한 칸이다. */
  .steps { display:flex; flex-direction:column; }
  .step { display:flex; gap:10px; align-items:flex-start; }
  .step-track { display:flex; flex-direction:column; align-items:center; flex:none;
    width:24px; align-self:stretch; }
  .step-n { width:24px; height:24px; border-radius:999px; background:#fff;
    border:1.5px solid var(--line); display:flex; align-items:center; justify-content:center;
    font-size:12px; font-weight:700; color:var(--sub); flex:none; }
  .step.last .step-n { background:var(--accent); border-color:var(--accent); color:#fff; }
  .step.nutr .step-n { background:var(--accent-soft); border-color:var(--accent-soft);
    color:var(--accent); }
  .step-line { width:1.5px; flex:1; min-height:10px; background:var(--line); }
  .step-body { flex:1; min-width:0; padding-bottom:10px; }
  .step:last-child .step-body { padding-bottom:0; }
  .step-main { font-size:13px; font-weight:600; line-height:19px; overflow-wrap:anywhere; }
  .step.last .step-main { font-weight:700; }
  /* The sub runs on beside the main, the way the approved mockup draws it -
     it is the same sentence's second half, not a second line. */
  .step-sub { font-size:12px; color:var(--sub); line-height:17px;
    margin-top:2px; overflow-wrap:anywhere; }
  /* 아기 몫. 이름은 .share-bar 다 - .bar 는 이 파일에 이미 두 개 있고(식단 막대,
     끼니 카드 막대) 그중 하나가 grid 라 백분율 폭이 0 으로 풀렸다. 같은 이름이
     세 가지를 뜻하면 나중에 쓴 쪽이 이긴다 (fix round 1, item 5). */
  .share-bar { display:block; height:8px; border-radius:999px; background:var(--track); overflow:hidden; }
  .share-bar > span { display:block; height:100%; border-radius:999px; background:var(--accent);
    min-width:4px; }
  /* 재료별 양: 두 칸이 나란히 서고 "전체 설정 따름" 이 그 밑을 다 쓴다 - 한 칸이
     반만 채우고 옆이 비면 셋째 칸이 지워진 자리로 읽힌다. 320px 에서도 다 보인다. */
  .amt-grid { display:grid; grid-template-columns:1fr 1fr; gap:8px; }
  .amt-grid button:last-child { grid-column:1 / -1; }
  .amt-grid button { min-height:var(--tap); border-radius:12px; border:1.5px solid var(--line);
    background:#fff; font-size:13px; font-weight:600; color:var(--sub); padding:0 6px;
    font-family:inherit; cursor:pointer; }
  .amt-grid button.on { background:var(--warn-soft); border-color:var(--warn);
    color:var(--warn); font-weight:700; }
  .have-row { display:flex; align-items:center; justify-content:space-between; gap:8px;
    min-height:var(--tap); }
  .have-row .k { font-size:15px; font-weight:700; }
  .have-btn { display:inline-flex; align-items:center; height:var(--tap); padding:0 18px;
    border-radius:999px; border:1.5px solid var(--line); background:#fff;
    font-size:13px; font-weight:700; font-family:inherit; color:var(--ink); cursor:pointer; }
  .have-btn.on { background:var(--warn-soft); border-color:var(--warn); color:var(--warn); }

  /* R4Confirm confirm sheet content */
  /* 큰 숫자는 이 탭이 담는 금액이지 이번 주 장보기 금액이 아니다 - 이름을 위에 세운다. */
  .cfm-lbl { font-size:12px; color:var(--sub); line-height:16px; margin-top:4px; }
  .cfm-total { font-size:22px; font-weight:700; line-height:30px; }
  /* 옵션 상품은 담기 요청에 못 타므로 따로 선다 - 세는 자리와 다른 자리다. */
  .cfm-opt { background:var(--warn-soft); border-radius:var(--r-sm); padding:12px 14px;
    margin-top:12px; }
  .cfm-opt-h { font-size:13px; font-weight:700; color:var(--warn); line-height:1.5; }
  .cfm-opt .cfm-list li { border-top-color:rgba(163,68,53,.18); }
  .cfm-opt a { color:var(--warn); font-size:13px; }
  .cfm-opt-sum { font-size:13px; font-weight:700; color:var(--warn); line-height:1.5;
    margin-top:10px; padding-top:8px; border-top:1px solid rgba(163,68,53,.18); }
  /* 새 창이 막힌 자리: 같은 일을 부모가 직접 누르는 모양으로 준다. */
  .cfm-fallback { margin-top:8px; }
  .cfm-one { display:flex; align-items:center; min-height:var(--tap); font-size:13px;
    color:var(--accent); font-weight:700; }
  .cfm-list { list-style:none; margin:12px 0 0; padding:0; }
  .cfm-list li { display:flex; gap:8px; align-items:baseline; font-size:14px;
    padding:8px 0; border-top:1px solid var(--line); }
  .cfm-list li b { flex:none; font-weight:700; }
  .cfm-list li span { margin-left:auto; flex:none; color:var(--sub); font-size:13px; }
  /* 가격을 오른쪽으로 미는 규칙(margin-left:auto)을 옵션 이름이 물려받으면 이름이
     가격 자리로 붙는다. 이름은 제목 옆에 남고, 좁아지면 줄어든다. */
  .cfm-list li span.cfm-optname { margin-left:0; flex:0 1 auto; min-width:0;
    color:var(--accent); font-weight:600; white-space:nowrap; overflow:hidden;
    text-overflow:ellipsis; }
  .cfm-more { font-size:13px; color:var(--sub); padding:8px 0; border-top:1px solid var(--line); }
  .cfm-fine { font-size:12px; color:var(--sub); line-height:1.6; margin:12px 0; }
  .cfm-fine a { color:var(--sub); text-decoration:underline; }
  .cfm-go { width:100%; min-height:52px; margin-top:4px; border:none;
    border-radius:var(--r-cta); background:var(--accent); color:#fff; font-size:16px;
    font-weight:700; cursor:pointer; font-family:inherit; }
  /* Disabled before 로그인했어요 (STACK #296) and while 담는 중 (a second tap cannot
     start a second chain), dimmed so the parent can see it is not the button to press now. */
  .cfm-go:disabled { opacity:.55; cursor:default; }

  /* ---- 식단 화면 (2026-09-05) --------------------------------------
     work/app_mockup_20260905.html 의 식단 탭. 같은 두 바닥을 지킵니다:
     12px 밑으로 내려가는 글자 없음, 누르는 것은 44px 이상. */
  /* 탄수 · 단백 · 지방, in the mockup's three bowl colours. Each ring is a
     gradient between the pale and the full tone, which is what the mockup
     calls "three gradient rings after the concept image". */
  :root { --ax-c:#D9B26A; --ax-p:#C97C6A; --ax-f:#7FA9A3;
          --ax-c-lite:#EBD7B2; --ax-p-lite:#E5BEB4; --ax-f-lite:#B9D1CD; }
  .card-h { display:flex; align-items:center; justify-content:space-between;
    gap:10px; margin-bottom:14px; }
  .card-h h2 { margin-bottom:0; }
  .chip-note, .target-pill { font-size:12px; color:var(--sub); background:var(--bg);
    border-radius:999px; padding:5px 11px; white-space:nowrap; }
  #exclude-chip:empty, #empty-chip:empty, #target-pill:empty { padding:0; background:none; }
  .target-pill { color:var(--accent); background:var(--accent-soft); font-weight:700; }

  /* 제외 이유는 경고 색이다 - 회색 본문으로 두면 "이번 주에서 빠졌다"가 안내로 읽힌다 */
  .reason { font-size:13px; font-weight:600; line-height:1.6; color:var(--warn);
    background:var(--warn-soft); border-radius:var(--r-sm);
    padding:11px 15px; margin-bottom:8px; }

  /* 요일 머리줄은 빈 칸이 있을 때만 선다 - 빈 칸 수가 왼쪽, 자동 채우기가 오른쪽 */
  .day-h { display:flex; align-items:center; justify-content:space-between;
    gap:8px; margin:0; }
  #pp-swap .slot-clear { width:100%; margin-top:8px; }

  .bars { margin:9px 0 6px; }
  .bar { display:flex; align-items:center; gap:8px; margin-bottom:4px; }
  .b-l { font-size:12px; color:var(--sub); width:14px; flex:none; }
  .b-t { flex:1; height:8px; background:var(--line); border-radius:999px; overflow:hidden; }
  .b-t i { display:block; height:100%; border-radius:999px; background:var(--ax-c); }
  .b-t i.ax-p { background:var(--ax-p); }
  .b-t i.ax-f { background:var(--ax-f); }
  .b-n { font-size:12px; color:var(--sub); width:52px; text-align:right; flex:none; }
  .rc-miss { font-size:12px; color:var(--accent); margin-bottom:6px; }
  .slot-add { min-height:var(--tap); padding:0 18px; border:1.5px solid var(--accent);
    color:var(--accent); background:var(--card); border-radius:999px; font-size:14px;
    font-weight:700; font-family:inherit; cursor:pointer; }
  .slot-add[disabled] { border-color:var(--line); color:var(--sub); cursor:default; }

  /* ---- 아이 화면 (2026-09-05, 2단계) ------------------------------- */
  .group { font-size:13px; font-weight:700; color:var(--sub); margin:16px 0 8px; }
  .group .tier { font-size:12px; font-weight:500; color:var(--sub);
    background:var(--bg); border-radius:999px; padding:2px 8px; margin-left:4px; }
  #allergy-chips .chip { flex-direction:column; align-items:flex-start;
    justify-content:center; padding:6px 14px; line-height:1.3; }
  #allergy-chips .chip small {
    font-size:12px; color:var(--sub); font-weight:400; }
  #allergy-chips .chip.on small { color:var(--accent); }
  #allergy-chips .chip.dead { border-style:dashed; color:var(--sub); }
  .diff { font-size:12px; color:var(--sub); line-height:1.6; margin:8px 0 0; }
  .sr { position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0);
    white-space:nowrap; }


  /* 탭 셸 - three pages over the same scroll. `.pg` wraps cards where they
     already sit, so with JS off the document is what it was: one long page.
     The bar is fixed, so body already carries 90px of bottom padding. */
  .pg[hidden] { display:none; }
  .tabs { position:fixed; left:0; right:0; bottom:0; z-index:30; display:flex;
    gap:0; max-width:520px; margin:0 auto; padding:6px 0 calc(8px + env(safe-area-inset-bottom));
    background:var(--card); border-top:1px solid var(--line); }
  .tabs[hidden] { display:none; }
  .tab { flex:1; min-height:var(--tap); display:flex; flex-direction:column;
    align-items:center; justify-content:center; gap:3px; border:none; border-radius:0;
    background:transparent; color:var(--sub); font-size:12px; font-weight:700;
    font-family:inherit; cursor:pointer; }
  .tab.on { background:transparent; color:var(--accent); }

  /* ---- 인트로 (D2 2026-09-15) ---------------------------------------- */
  #intro { position:fixed; inset:0; z-index:50; background:var(--bg);
    display:flex; align-items:center; justify-content:center; overflow-y:auto; }
  #intro[hidden] { display:none; }
  .intro5 { display:flex; flex-direction:column; align-items:center;
    justify-content:center; padding:28px 26px; text-align:center; }
  .cluster { position:relative; width:200px; height:150px; margin-bottom:26px; flex:none; }
  .cluster span { position:absolute; border-radius:32px; display:flex;
    align-items:center; justify-content:center;
    box-shadow:0 12px 30px -14px rgba(20,24,30,.35); }
  .intro5 h2 { font-size:28px; line-height:1.35; letter-spacing:-.02em;
    font-weight:700; margin-bottom:12px; color:var(--ink); }
  .intro5 p { font-size:15px; line-height:1.7; color:var(--muted); margin-bottom:26px; }
  .btn-dark { height:52px; border-radius:var(--r-cta); background:var(--accent); color:#FFFFFF;
    font-size:15px; font-weight:700; display:flex; align-items:center;
    justify-content:center; width:100%; max-width:300px; border:none;
    font-family:var(--body); cursor:pointer; }
  .note5 { font-size:12px; line-height:1.6; color:var(--muted); margin-top:20px; }

  /* ---- D2 아이 탭 컴포넌트 (2026-09-15) ------------------------------- */
  .hero { display:flex; align-items:center; gap:16px; padding:20px;
    border-radius:var(--r-lg); background:var(--hero-bg); box-shadow:var(--lift);
    color:var(--hero-ink); margin-bottom:16px; }
  .hero.col { flex-direction:column; align-items:stretch; gap:0; }
  #profile-card { display:flex; flex-direction:column; align-items:stretch; gap:0;
    padding:20px; border-radius:var(--r-lg); background:var(--hero-bg);
    box-shadow:var(--lift); color:var(--hero-ink); margin-bottom:16px; }
  .hctl { display:grid; grid-template-columns:repeat(2,minmax(0,1fr));
    gap:8px; margin-top:16px; }
  .hdate { border-radius:13px; background:#F2F3F5; padding:0 12px;
    display:flex; flex-direction:column; justify-content:center; }
  .hdate label { font-size:12px; color:var(--hero-muted); line-height:1.2;
    margin:8px 0 2px; display:block; font-weight:500; }
  .hdate input[type=date] { border:none; background:transparent; padding:6px 0 8px;
    margin:0; border-radius:0; font-family:var(--body); font-size:16px; font-weight:700;
    color:#17191C; font-variant-numeric:tabular-nums; color-scheme:light; transition:none; }
  .hdate input[type=date]::-webkit-calendar-picker-indicator { opacity:.4 }
  /* Milk block: dark-card styled inputs */
  #milk-block { color:var(--hero-ink); }
  #milk-block label { color:var(--hero-muted); }
  #milk-block .note { color:var(--hero-muted); font-size:12px; }
  #milk-block input[type=number] { background:#F2F3F5; border:1.5px solid transparent;
    color:#17191C; border-radius:10px; padding:10px 12px;
    font-size:16px; font-family:inherit; min-height:44px;
    -moz-appearance:textfield; }
  #milk-block input[type=number]::-webkit-outer-spin-button,
  #milk-block input[type=number]::-webkit-inner-spin-button { -webkit-appearance:none; }
  #milk-block input[type=number]:focus { outline:none; border-color:var(--sel); }
  .milk-row { display:flex; align-items:center; gap:10px; margin-bottom:6px; }
  .milk-unit { font-size:13px; color:var(--hero-muted); }
  #formula-block { border-top:1px solid #ECEEF1; margin-top:10px; padding-top:2px; }
  #formula-block > summary { display:flex; align-items:center; justify-content:space-between;
    font-size:14px; font-weight:600; color:#17191C; cursor:pointer;
    padding:10px 0; list-style:none; }
  #formula-block > summary::-webkit-details-marker { display:none; }
  #formula-block > summary::after { content:"›"; font-size:18px;
    color:var(--hero-muted); transform:rotate(90deg); display:inline-block;
    transition:transform .2s; }
  #formula-block[open] > summary::after { transform:rotate(-90deg); }
  .formula-section { padding:10px 0 4px; }
  .formula-field { margin-bottom:10px; }
  .formula-field label { font-size:12px; color:var(--hero-muted);
    display:block; margin-bottom:4px; }
  .formula-inputs { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; }
  .formula-input-group { display:flex; flex-direction:column; font-size:12px;
    color:var(--hero-muted); cursor:pointer; }
  .formula-input-group .fi-row { display:flex; align-items:center; margin-top:4px; }
  .formula-input-group .fi-row input { width:100%; min-width:0; }
  /* Allergy tile grid */
  #allergy-chips .chip { flex-direction:column; align-items:center; justify-content:flex-start;
    padding:10px 6px 8px; text-align:center; border-radius:16px;
    min-height:72px; font-size:12px; font-weight:600; gap:0; position:relative; }
  #allergy-chips .chip.dead { opacity:.5; }
  .excl-headline { font-size:19px; font-weight:700; letter-spacing:-.02em;
    margin-bottom:16px; }
  .hero .privacy, #profile-card .privacy { margin-top:12px; }
  .hero .privacy-detail summary, #profile-card .privacy-detail summary { color:var(--hero-muted); }
  .hero .privacy span, #profile-card .privacy span { color:var(--hero-muted); }
  .birth-note { font-size:12px; color:var(--hero-muted); line-height:1.6; margin-top:8px; }
  .hgo { height:52px; margin-top:14px; border-radius:var(--r-cta); background:var(--sel);
    color:#FFFFFF; font-size:16px; font-weight:700; display:flex; align-items:center;
    justify-content:center; width:100%; border:none; font-family:var(--body); cursor:pointer; }
  .pnl-card { position:fixed; inset:0; z-index:42; overflow-y:auto;
    background:var(--bg); display:flex; flex-direction:column; }
  .pnl-card[hidden] { display:none; }
  /* A panel is its own screen, so the page behind it goes away. The SHEET is not
     behind it - it is opened FROM it (내 데이터 -> 전부 지우기) and belongs on top.
     Without the two exemptions the confirm button was visibility:hidden, which
     is not hit-testable, so a real tap fell through to .pnl-body and nothing
     happened while E2E's DOM .click() still fired the handler and passed.
     2026-09-18 (1b): the four 아이 panels are bottom sheets now and the 아이
     screen has to stay VISIBLE under their dim, so they carry
     body[data-panel-sheet] and are cut out of this rule. Every other panel -
     장보기's 상품 상세 above all - still covers its screen, and that is another
     round's file. Deleting the rule outright would have changed it silently. */
  body[data-panel-open]:not([data-panel-sheet]) > *:not(.pnl-card):not(.sh):not(.sh-scrim):not(.save-fail) { visibility: hidden; }
  .pnl-nav-bar { display:flex; align-items:center; height:56px; padding:0 18px;
    background:var(--bg); border-bottom:1px solid var(--line); flex:none;
    position:sticky; top:0; z-index:1; }
  .pnl-back { min-height:44px; padding:0 14px; background:none; border:none;
    font-size:15px; font-weight:700; color:var(--accent); font-family:var(--body);
    cursor:pointer; margin-left:-14px; display:flex; align-items:center; gap:6px; }
  .pnl-back svg { width:18px; height:18px; }
  .pnl-title { font-size:17px; font-weight:700; flex:1; text-align:center; }
  .pnl-body { padding:16px 18px 90px; flex:1; }
  .state { display:flex; gap:12px; align-items:flex-start; margin-top:12px;
    padding:16px; border-radius:var(--r-md); }
  .state[hidden] { display:none; }
  .state .si2 { width:40px; height:40px; border-radius:13px; display:flex;
    align-items:center; justify-content:center; flex:none; background:#FFFFFF; }
  .state .si2 svg { width:21px; height:21px; color:currentColor; }
  .state .sh6 { font-size:16px; font-weight:700; line-height:1.35; }
  .state .sp { font-size:13px; line-height:1.6; margin-top:4px; }

  /* 끼니 시트 - the write site for 반응 and 선호. Until 2026-09-06 both were
     collected with two native prompt() calls, which is why state.pref was read
     by the generator and written by nothing. Class names are sheet-scoped
     (sh-*) on purpose: .empty already means two different things in this file
     and a third collision is how a card and a dot ended up sharing a rule. */
  /* Above .pnl-card (42). A sheet is opened FROM a panel - 내 데이터 -> 전부
     지우기 - and at 40/41 its confirm button was drawn under the panel: a real
     tap landed on .pnl-body and nothing happened, while E2E's DOM .click()
     fired the handler and reported a pass (measured 2026-09-18, elementFromPoint
     at the button's centre returned pnl-body on all four panels). */
  .sh-scrim { position:fixed; inset:0; background:rgba(74,63,54,.34); z-index:43; }
  .sh-scrim[hidden], .sh[hidden] { display:none; }
  .sh { position:fixed; left:0; right:0; bottom:0; z-index:44; margin:0 auto;
    max-width:520px; max-height:86vh; overflow-y:auto; background:var(--card);
    border-radius:var(--r) var(--r) 0 0; padding:10px 20px 24px;
    box-shadow:0 -6px 30px rgba(150,110,70,.16); }
  .sh-grip { width:36px; height:4px; border-radius:999px; background:#D5D8DD;
    margin:0 auto 14px; }
  /* 시트를 닫는 길은 하나다 - 머리줄 오른쪽의 닫기 알약. 머리는 제 줄을 갖는다:
     absolute 면 밑의 설명이 알약 아래로 기어들어가 잘리고(2026-09-17 composite),
     float 이면 글은 옆으로 흐르지만 바로 밑의 첫 상자가 알약만큼 좁아진다
     (fix round 1, item 4). 줄이면 둘 다 아니다 - 제목이 알약 옆에 서고 밑은
     전부 제 폭을 갖는다. */
  .sh-head { display:flex; align-items:center; justify-content:space-between;
    gap:8px; margin-bottom:4px; }
  .sh-head > .st5, .sh-head > .sh-cat-h { flex:1; min-width:0; padding-bottom:0; }
  .sh-close { flex:none; min-height:var(--tap);
    display:inline-flex; align-items:center; padding:0 16px; border:none;
    border-radius:999px; background:var(--well); color:var(--ink); font-size:13px;
    font-weight:700; font-family:inherit; cursor:pointer; }
  .sh h2 { font-size:18px; margin-bottom:4px; }
  .sh-sub { color:var(--sub); font-size:13px; margin-bottom:14px; }
  .sh-h { font-size:13px; color:var(--sub); margin:18px 0 8px; }
  .sh-chips { display:flex; flex-wrap:wrap; gap:8px; }
  .sh-chip { min-height:var(--tap); display:inline-flex; align-items:center; padding:0 16px;
    border:1.5px solid var(--line); border-radius:999px; font-size:14px; background:var(--card);
    color:var(--ink); cursor:pointer; font-family:inherit; }
  .sh-chip.on { background:var(--accent-soft); border-color:var(--accent); color:var(--accent);
    font-weight:700; }
  .sh-chip.bad.on { background:var(--warn-soft); border-color:var(--warn); color:var(--warn); }
  .sh-urgent { background:var(--warn-soft); color:var(--warn); font-size:13px; line-height:1.6;
    padding:12px 14px; border-radius:var(--r-sm); margin-top:10px; }
  .sh-acts { display:flex; gap:10px; margin-top:22px; }
  .sh-acts button { flex:1; min-height:var(--tap); border-radius:999px; font-size:15px;
    font-weight:700; font-family:inherit; cursor:pointer; border:1.5px solid var(--accent); }
  .sh-acts .go { background:var(--accent); color:#fff; }
  .sh-acts .go:disabled { background:var(--line); border-color:var(--line); color:var(--sub);
    cursor:default; }
  .sh-acts .off { background:var(--card); color:var(--accent); }
  .sh textarea { width:100%; min-height:76px; padding:12px 14px; border:1.5px solid var(--line);
    border-radius:var(--r-sm); font-size:16px; font-family:inherit; background:var(--bg);
    color:var(--ink); resize:vertical; }
  :focus-visible { outline:3px solid var(--accent); outline-offset:3px; }
  .react-btn, .rec summary, .reset-have, .pick-why > summary,
  .cart-all-list summary { min-height:44px; }
  .band .bd { overflow-wrap:anywhere; }
  .tabs { padding-bottom:calc(10px + env(safe-area-inset-bottom)); }
  body { padding-bottom:calc(100px + env(safe-area-inset-bottom)); }
  @media (max-width:360px) {
    body { --gutter:12px; }
    .card { padding:18px 14px; }
    .band { flex-wrap:wrap; }
    .band a.go { margin-left:auto; }
    /* 320px 에서 세 칸이 쓸 수 있는 폭은 256px 뿐이라 12px 간격으로는 칸이 77px 에
       머문다. 6px 이면 81px - 숫자 네 자리가 잘리지 않는 최소치다. */
    .formula-inputs { gap:6px; }
  }
  /* The u- parts that move are left out: they keep their blueprint 1.8 fade (end of file). */
  @media (prefers-reduced-motion:reduce) {
    *:not(.u-sheet, .u-scrim, .u-toast), *::before, *::after { transition:none !important; animation:none !important; }
  }
  /* CSS5: D2 visual system (2026-09-15) */
  .pillrow{display:flex;gap:6px;flex-wrap:wrap;margin:0 2px 14px}
  .pillrow span{font-size:13px;font-weight:500;padding:5px 12px;border-radius:999px;background:#FFFFFF;box-shadow:var(--tile-shadow)}
  .dd{display:flex;gap:3px}
  .dd i{width:5px;height:5px;border-radius:50%;background:#2BB39A}
  .dd i.m{background:#F5A623}
  .dayh{display:flex;justify-content:space-between;align-items:baseline;margin:16px 4px 8px}
  .dayh b{font-size:17px}
  .dayh span{font-size:13px;color:var(--muted)}
  .meals{display:flex;flex-direction:column;gap:8px}
  .dotleg{display:flex;gap:12px;justify-content:center;margin-top:8px;font-size:12px;color:var(--muted)}
  .dotleg span{display:flex;align-items:center;gap:4px}
  .dotleg i{width:6px;height:6px;border-radius:50%;background:#2BB39A}
  .dotleg i.m{background:#F5A623}
  .btn2{height:52px;border-radius:16px;background:#E9EBEE;color:#9AA0A8;font-size:15px;font-weight:700;display:flex;align-items:center;justify-content:center;gap:8px;margin-top:12px;border:none;cursor:pointer;font-family:inherit;width:100%}
  .btn2 svg{width:18px;height:18px}
  .wr{display:grid;grid-template-columns:28px minmax(0,1fr);gap:10px;padding:9px 14px;border-top:1px solid var(--line)}
  .wr:first-child{border-top:none}
  .wr b{font-size:14px;padding-top:1px}
  .wr div{font-size:12px;line-height:1.55;color:var(--ink)}
  .ban{display:flex;align-items:center;gap:12px;margin-top:12px;padding:14px;border-radius:var(--r-md);background:var(--surface);box-shadow:var(--lift)}
  .ban .bi{width:40px;height:40px;border-radius:13px;display:flex;align-items:center;justify-content:center;flex:none}
  .ban .bi svg{width:21px;height:21px;color:currentColor}
  .ban .bt{flex:1;font-size:15px;font-weight:700}
  .ban .bt small{display:block;font-size:12px;font-weight:500;color:var(--muted)}
  .rowlink{display:flex;align-items:center;gap:12px;margin-top:12px;padding:14px;border-radius:var(--r-md);background:var(--surface);box-shadow:var(--lift);font-size:15px;font-weight:700}
  .rowlink .ri{width:34px;height:34px;border-radius:11px;display:flex;align-items:center;justify-content:center}
  .rowlink .ri svg{width:18px;height:18px;color:currentColor}
  .rowlink span.grow{flex:1}
  .rowlink .chev{display:flex;color:var(--muted)}
  .rowlink .chev svg{width:16px;height:16px}
  .teaser5{display:flex;align-items:center;gap:12px;margin-top:12px;padding:14px;border-radius:var(--r-md);background:var(--hero-bg);color:#FFFFFF}
  .teaser5 .ti2{width:40px;height:40px;border-radius:13px;background:#2B2E33;display:flex;align-items:center;justify-content:center}
  .teaser5 .ti2 svg{width:21px;height:21px;color:#FFB199}
  .teaser5 .tt{flex:1;font-size:15px;font-weight:700}
  .teaser5 .tt small{display:block;font-size:12px;font-weight:500;color:rgba(255,255,255,.62)}
  .teaser5 .tv{font-size:17px;font-weight:700;font-variant-numeric:tabular-nums}
  .rchips{display:flex;gap:6px;flex-wrap:nowrap;overflow:hidden;margin-bottom:12px}
  .rchips span{flex:none;height:36px;padding:0 13px;border-radius:999px;background:#FFFFFF;box-shadow:var(--tile-shadow);font-size:13px;font-weight:500;display:flex;align-items:center}
  .rchips span.on{background:var(--ink);color:#FFFFFF;font-weight:700}
  .rgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
  .rc{padding:12px;border-radius:var(--r-sm);background:var(--surface);box-shadow:var(--tile-shadow);display:flex;flex-direction:column;gap:8px}
  .rc .rn{font-size:14px;font-weight:700;line-height:1.35;min-height:38px}
  .bars{display:flex;flex-direction:column;gap:4px}
  .bar{display:grid;grid-template-columns:14px minmax(0,1fr) 44px;gap:6px;align-items:center;font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums}
  .bar i{display:block;height:5px;border-radius:3px;background:#EEF0F3;position:relative;overflow:hidden}
  .bar i b{position:absolute;left:0;top:0;bottom:0;border-radius:3px}
  .bar em{font-style:normal;text-align:right;color:var(--ink)}
  .rc .rmiss{font-size:12px;font-weight:700;color:#A86E12}
  .rc .put{height:36px;border-radius:12px;background:var(--ink);color:#FFFFFF;font-size:13px;font-weight:700;display:flex;align-items:center;justify-content:center}
  .sh5{font-size:13px;font-weight:700;color:var(--muted);margin:14px 0 8px}
  .schips{display:flex;flex-wrap:wrap;gap:6px}
  .sc{height:40px;padding:0 14px;border-radius:999px;background:#F2F3F5;font-size:14px;font-weight:500;display:flex;align-items:center;border:none;cursor:pointer;font-family:inherit}
  .sc.on{background:var(--ink);color:#FFFFFF;font-weight:700}
  .sc.bad{color:#D93F2B}
  .sc.bad.on{background:#D93F2B;color:#FFFFFF}
  .urgent{margin-top:10px;padding:12px 14px;border-radius:14px;background:var(--warn-soft);color:var(--warn);font-size:13px;line-height:1.55}
  .sh-119:not([hidden]){display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px}
  .sh-call{font-size:22px;font-weight:800;color:var(--warn);text-decoration:none}
  .sh-119 #sh-urgent-why{flex:1;min-width:0;font-weight:700}
  .sh-srcbtn{background:none;border:0;padding:4px 0;font:inherit;font-size:12px;color:var(--sub);cursor:pointer}
  .sh-src{flex-basis:100%;margin:2px 0 0;font-size:12px;color:var(--sub)}
  .sh-src a{color:inherit}
  .sh-note{margin:8px 0 0;font-size:13px;color:var(--ink)}
  .btnrow{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:16px}
  .btnrow.one{grid-template-columns:minmax(0,1fr)}
  .btn-go{height:52px;border-radius:16px;background:var(--sel);color:#FFFFFF;font-size:15px;font-weight:700;display:flex;align-items:center;justify-content:center;border:none;cursor:pointer;font-family:inherit;width:100%}
  .btn-off{height:52px;padding:0 20px;border-radius:16px;background:#F2F3F5;font-size:15px;font-weight:700;display:flex;align-items:center;justify-content:center;border:none;cursor:pointer;font-family:inherit}
  .btn-red{height:52px;border-radius:16px;background:#D93F2B;color:#FFFFFF;font-size:15px;font-weight:700;display:flex;align-items:center;justify-content:center;border:none;cursor:pointer;font-family:inherit;width:100%}
  .sh .st5{font-size:17px;font-weight:800;letter-spacing:-.015em;line-height:1.3}
  .sh .ss{font-size:13px;color:var(--muted);margin-top:4px;line-height:1.55;margin-bottom:4px}
  .state .sa{display:inline-flex;align-items:center;gap:4px;margin-top:10px;min-height:var(--tap);padding:0 14px;border-radius:999px;background:#FFFFFF;font-size:13px;font-weight:700;border:none;cursor:pointer;font-family:inherit}
  .state .sa svg{width:14px;height:14px}
  .toast-area{position:fixed;bottom:calc(var(--tabbar-h) + 76px + env(safe-area-inset-bottom));left:0;right:0;max-width:520px;margin:0 auto;padding:0 var(--gutter);z-index:100;pointer-events:none;display:flex;flex-direction:column;gap:8px;align-items:stretch}
  .toast{display:flex;gap:10px;align-items:center;padding:12px 14px;border-radius:16px;background:var(--ink);color:#FFFFFF;font-size:var(--fs-base);line-height:1.45;box-shadow:0 10px 24px -12px rgba(0,0,0,.45);pointer-events:auto}
  .toast .ti{width:28px;height:28px;border-radius:9px;display:flex;align-items:center;justify-content:center;flex:none}
  .toast .ti svg{width:16px;height:16px;color:currentColor}
  .toast .tm small{display:block;font-size:12px;color:rgba(255,255,255,.62);margin-top:1px}
  #birth-msg,#feed-msg{font-size:12px;font-weight:700;color:#D93F2B;margin:2px 2px 8px;display:none}
  .notice-inline{display:flex;align-items:flex-start;gap:8px;padding:12px 14px;border-radius:var(--r-sm);background:var(--warn-soft);color:var(--warn);font-size:13px;font-weight:600;line-height:1.55;margin:0 0 12px}
  .notice-inline svg{width:18px;height:18px;flex:none;margin-top:1px}

  /* ---- 공통 크롬 (설계 캔버스 2026-09-17) ----------------------------
     화면마다 제 이름을 갖는 타이틀 행, 12px 안내 한 줄, 아이콘 탭 바.
     앱 이름은 인트로에만 남는다. */
  .tbar{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:36px}
  .stage-pill{display:inline-flex;align-items:center;flex:0 0 auto;height:28px;padding:0 12px;border-radius:999px;background:var(--accent-soft);color:var(--accent);font-size:12px;font-weight:700;white-space:nowrap}
  .stage-pill:empty{display:none}
  /* structure v3: ‹ on a page under a tab root, "설정 ›" on the 아이 root (F2 below). */
  .tbar{justify-content:flex-start}
  #page-title{flex:1;min-width:0}
  .tbar-back:not([hidden]),.tbar-set:not([hidden]){display:grid;place-items:center;flex:0 0 auto;
    width:var(--tap);height:var(--tap);margin:0 -6px;border:0;border-radius:50%;background:transparent;
    color:var(--ink);cursor:pointer}
  .tbar-back:not([hidden]){margin-right:-2px}
  .tbar-back svg,.tbar-set svg{width:24px;height:24px}
  /* 장보기에도 단계 알약이 선다 - 사용자가 승인한 그림이 그렇게 그린다
     (mockup_two_axis_20260917 의 a-late-default-390.png, fix round 1 item 7).
     앞 판은 여기서 알약을 지웠다: "그 화면이 말하는 것은 단계가 아니다"였는데,
     승인된 그림이 만 10개월 · 후기 · 무른밥을 그 줄에 그린다. */
  /* 카드가 아닌 묶음 - 바탕 위에 제목 한 줄과 내용이 그대로 선다 (장보기 시트의 .blk) */
  .blk{position:relative;margin-bottom:14px}
  /* 게이지 ⓘ - 설명 줄 전체가 손잡이다. 아이콘 하나만 누르게 두면 44px 이 안 나온다. */
  details.fold.gfold > summary{position:static;padding:0;display:flex;align-items:center;
    justify-content:center;gap:6px;min-height:var(--tap);font-size:12px;color:var(--sub)}
  details.fold.gfold[open] > summary{color:var(--accent)}
  details.fold.gfold > summary svg{width:18px;height:18px;flex:none}
  .autopill{display:inline-flex;align-items:center;min-height:var(--tap);padding:0;border:none;background:none;font-family:inherit;cursor:pointer;flex:none}
  .autopill span{display:inline-flex;align-items:center;gap:4px;height:28px;padding:0 10px 0 12px;border-radius:999px;border:1.5px solid var(--accent);color:var(--accent);font-size:12px;font-weight:700;white-space:nowrap;box-sizing:border-box}
  .autopill svg{width:14px;height:14px;flex:none}
  #banned .excluded{display:flex;align-items:center;justify-content:space-between;gap:10px;min-height:48px;margin:0;padding:0;
    background:none;border:0;border-bottom:1px solid var(--line);border-radius:0;font-size:14px;font-weight:400;color:var(--ink)}
  #banned .excluded b{font-weight:700;white-space:nowrap}
  #banned .excluded > span{font-size:13px;color:var(--sub);text-align:right}
  #banned .excluded.bn-hold{display:block;padding:10px 0;color:var(--warn);font-size:13px;line-height:1.6}
  /* 패널 머리 - 잡이 · 제목 17/700 · 닫기 알약 하나. 뒤로는 없앴다. */
  .pnl-topbar{flex:none;position:sticky;top:0;z-index:1;background:var(--bg);padding:10px 18px 10px}
  .pnl-grip{width:36px;height:4px;border-radius:999px;background:#D5D8DD;margin:0 auto 10px}
  .pnl-head{display:flex;align-items:center;justify-content:space-between;gap:8px}
  .pnl-head .pnl-title{font-size:17px;font-weight:700;flex:1;text-align:left}
  .pnl-close{min-height:var(--tap);display:inline-flex;align-items:center;padding:0 16px;border:none;border-radius:999px;background:var(--well);color:var(--ink);font-size:13px;font-weight:700;font-family:inherit;cursor:pointer;flex:none}

  /* ---- 아이 · 인트로 · 도크 패널 (설계 캔버스 1b, 2026-09-18) ------------
     보드는 work\design_canvas_20260917\boards\A-*. 값은 그 보드의 inline
     style 에서 그대로 왔고, 두 바닥이 보드보다 세다 - 글자 12px · 손가락 44px.
     그래서 보드가 11px 로 그린 라벨과 36px 로 그린 알약은 보드 값을 안 쓴다. */

  /* 인트로 - 타일 셋이 한 줄에 서고 양옆이 가운데 밑으로 기운다 */
  .cluster{display:flex;align-items:center;justify-content:center;gap:0;width:auto;height:140px}
  .cluster span{position:static;flex:none;box-shadow:none}
  .cluster .cl-mid{position:relative;z-index:1;box-shadow:0 10px 30px rgba(20,24,30,.08)}
  .intro5 h2{font-size:26px;line-height:34px;letter-spacing:-.3px}
  .intro5 p{line-height:20px;margin-bottom:28px}
  /* .intro5 p 가 .note5 보다 세서 이 줄은 12px 로 적혀 있고도 15px 로 그려졌다 */
  .intro5 p.note5{font-size:12px;line-height:16px;margin:16px 0 0}

  /* 아이 화면의 카드 - 반지름 16 · 1px 선 · 그림자 없음, 사이는 12 */
  .pg[data-pg="baby"] .card,#profile-card{border-radius:16px;padding:16px;
    border:1px solid var(--line);box-shadow:none;margin-bottom:12px}
  .pg[data-pg="baby"] .state{border-radius:16px;padding:14px 16px;margin-top:0;margin-bottom:12px}
  .pg[data-pg="baby"] .state .sh6{font-size:15px;line-height:20px}
  .pg[data-pg="baby"] .state .si2 svg{width:20px;height:20px}
  /* 생년월일은 남는 폭을 다 쓰고, 수유 셋은 제 폭만 쓴다. 오류 줄은 제 줄로
     내려가야 한다 - 같은 줄에 서면 칸 둘을 옆으로 밀어낸다. */
  .hctl{display:flex;flex-wrap:wrap;align-items:stretch;gap:8px}
  /* 56px 상자 안에 44px 손가락 자리를 같이 넣을 수 있는 길은 하나다 - 입력 칸이
     상자 전체가 되고 라벨이 그 위에 뜨는 것. 라벨을 위에 쌓으면 입력 칸의 44px
     바닥이 그대로 더해져 상자가 70px 아래로 못 내려간다(잰 값 76.4px). */
  .hdate{position:relative;flex:1 1 auto;min-width:0;min-height:56px;
    border-radius:12px;padding:0;display:block}
  .hdate label{position:absolute;top:8px;left:12px;margin:0;line-height:14px;pointer-events:none}
  .hdate input[type=date]{min-height:56px;height:56px;padding:20px 12px 0;line-height:1}
  #birth-msg,#feed-msg{flex:1 0 100%;margin:4px 0 0}
  #profile-card .privacy{margin:12px 0 0}
  .privacy-detail summary{text-underline-offset:2px;display:inline-flex;align-items:center;min-height:var(--tap)}
  /* 펼친 본문은 13px, 요약 줄은 12px - 보드가 그렇게 가른다. 굵은 구절은 잉크로:
     굵기만 바꾸고 색은 그대로면 흐린 글 안에서 강조가 거의 안 보인다. */
  #profile-card .privacy span,#profile-card .birth-note{font-size:13px;line-height:19px}
  #profile-card .birth-note b,#profile-card .privacy span b{color:var(--ink)}
  #milk-block{margin-top:12px}
  #milk-block .milk-row label{margin-bottom:0}
  /* 16px 은 보드의 15px 이 아니다: iOS 는 16px 아래의 입력 칸에 초점이 가면
     화면을 확대한다. 바닥(12px)이 아니라 iOS 쪽 규칙이라 보드가 못 이긴다. */
  #milk-block input[type=number]{width:88px;height:44px;padding:0 12px;border-radius:12px;font-weight:600}
  .hgo{margin-top:12px}
  /* 소아과에 가 보라는 줄만 바탕을 갖는다 - 옆의 설명들과 같은 회색 문단이면
     경고가 설명처럼 읽힌다(ObserveNote 보드). */
  #obs-react-note{background:var(--warn-soft);color:var(--warn);border-radius:10px;
    padding:8px 10px;line-height:17px}
  /* 제외된 재료 = 한 목록. 반응 · 직접 뺌 두 그릇은 자기 지우기 버튼 뜻 때문에
     남고, 화면에는 한 줄 간격으로 이어진다. */
  #reaction-list,#parent-list{display:contents}

  /* 아이 탭의 네 패널 = 어두워진 화면 위의 바닥 시트(규칙 8). 층은 흐림막 41 <
     시트 패널 42 < 시트 흐림막 43 < 시트 44 - 패널에서 연 시트가 패널 위에
     서야 손가락이 닿는다(라운드 8에서 잰 것). */
  .pnl-scrim{position:fixed;inset:0;background:rgba(23,25,28,.45);z-index:41}
  .pnl-scrim[hidden]{display:none}
  .pnl-card.pnl-sheet{top:auto;left:0;right:0;bottom:0;max-width:520px;margin:0 auto;
    max-height:calc(100vh - 56px);overflow-y:auto;background:var(--card);
    border-radius:var(--r) var(--r) 0 0;box-shadow:0 -6px 30px rgba(150,110,70,.16)}
  .pnl-sheet .pnl-topbar{background:var(--card);padding:10px 20px 0}
  .pnl-sheet .pnl-body{padding:14px 20px 24px}
  /* 시트 위에 카드를 또 얹지 않는다 - 보드는 내용이 시트 바탕에 바로 선다.
     카드의 마크업은 그대로 둔다: 내 데이터의 마지막 카드는 증명이 바이트로
     겨누는 자리다(R-L2). */
  .pnl-sheet .pnl-body > .card{background:none;box-shadow:none;border:none;
    border-radius:0;padding:0;margin-bottom:0}
  .pnl-sheet .pnl-body > .card + .card{border-top:1px solid var(--line);
    margin-top:14px;padding-top:14px}
  .pnl-sheet .pnl-body > .card > details.fold > summary{top:0;right:0}
  .pnl-sheet .pnl-body > .card + .card > details.fold > summary{top:14px}
  .hr-line{gap:12px}
  /* 묶음 이름과 그 옆의 알약은 두 조각이다 - 한 줄로 붙여 두면 읽는 쪽도
     innerText 도 한 낱말로 받는다 */
  .group{display:flex;align-items:center;gap:8px;color:var(--ink)}
  .group .tier{height:26px;display:inline-flex;align-items:center;padding:0 11px;margin-left:0}
  /* 검진 - 칸은 선 없는 회색 상자. border 를 0 으로 두지 않는 이유는 초점이
     테두리 색으로 표시되기 때문이다(K1 · K3). */
  .opt{height:26px;display:inline-flex;align-items:center;padding:0 10px}
  .grid2{gap:10px}
  .grid2 > div{display:flex;flex-direction:column;justify-content:flex-end;gap:4px}
  .grid2 label{margin-bottom:0;font-size:12px}
  .grid2 input[type=date],.grid2 input[type=text]{margin-bottom:0;padding:0 12px;
    border-color:var(--well);border-radius:12px;background:var(--well);font-weight:600}
  /* .cu-sum 은 장보기의 #cart-count 도 쓴다 - 여기서 크기를 바꾸면 남의 화면이
     같이 움직인다. 검진 요약은 #cu-read 안에만 있다(shell.js 가 거기 쓴다). */
  #cu-read .cu-sum{font-size:14px}
  #cu-read .cu-ok{border-radius:12px;padding:12px 14px}
  #cu-read .excluded{border-radius:12px;padding:12px 14px;font-weight:400}
  /* 시트 안의 설명은 12px 한 종류다 - 카드가 사라지면서 안쪽 여백도 사라졌고,
     14px 문단은 그 자리에서 제목만큼 무겁게 읽힌다(보드 전부 12px). */
  .pnl-sheet .pnl-body p.note{font-size:12px;line-height:1.5}
  /* 내 데이터 - 알약 셋은 제 폭을 나눠 갖고 글자는 600 */
  .data-row button{padding:0 16px;font-weight:600}
  /* ---- green system (2026-09-23) ------------------------------------
     Values come from work\design_green_20260922\mockup.html lines 11-281 and
     the nine approved frames. This block is last on purpose: it restyles the
     atoms the older sections drew in the orange system, and the two floors
     still win over the mockup - no text under 12px, nothing tappable under
     44px (the mockup draws some chips at 40px and some pills at 32px). */
  .card{border-radius:var(--r-lg);padding:16px;margin-bottom:13px;box-shadow:var(--shadow);
    border:none}
  .card h2{font-size:16px;font-weight:700;gap:8px}
  .tbar{min-height:48px;margin-bottom:8px}
  #page-title{font-size:23px;font-weight:800;letter-spacing:-.02em}
  .sub{font-size:13px;color:var(--sub);margin-bottom:14px}

  /* one green pill for every primary action (rule 2) */
  button.primary,.hgo,.btn-dark,.btn-go,.cfm-go,.shop-dock .st-go,.cta,.btn-red{
    width:100%;max-width:none;height:52px;min-height:52px;padding:0 16px;border:0;
    border-radius:var(--r-cta);background:var(--accent);color:var(--accent-ink,#fff);
    font-family:var(--body);font-size:16px;font-weight:700;display:flex;
    align-items:center;justify-content:center;box-shadow:none;cursor:pointer}
  .btn-off{height:52px;border-radius:var(--r-cta);background:var(--card);
    border:1px solid var(--line);color:var(--ink)}
  .btn2{height:52px;border-radius:var(--r-cta);background:var(--well);color:var(--sub)}
  .shop-dock .st-go:disabled{background:var(--line);color:var(--card)}
  .hgo:disabled,.hgo[data-boot]{background:var(--line);color:var(--card);cursor:default}
  [data-boot]{pointer-events:none}

  .pill{display:inline-flex;align-items:center;justify-content:center;gap:6px;
    min-height:var(--tap);height:var(--tap);padding:0 20px;border-radius:var(--r-cta);
    background:var(--card);border:1px solid var(--line);font-family:inherit;
    font-size:14px;font-weight:600;color:var(--ink);cursor:pointer}
  .pill:empty{display:none}

  .chip{min-height:var(--tap);padding:0 18px;border:1px solid var(--line);
    border-radius:var(--r-cta);background:var(--card);font-size:14px;font-weight:500;
    color:var(--ink);justify-content:center}
  .chip.on{background:var(--accent);border-color:var(--accent);color:var(--accent-ink,#fff);
    font-weight:700}
  /* The allergy chips carry one point colour, green (user 2026-09-26): a chip
     taken out is the soft accent, not the solid accent of a selection, and not
     the warn tones - twelve tints and a terracotta "on" read as twelve alarms. */
  #allergy-chips .chip.on{background:var(--accent-soft);border-color:var(--accent);
    color:var(--accent)}
  #exclude-chip:empty,#empty-chip:empty,#target-pill:empty{border:none}

  .tag{display:inline-flex;align-items:center;height:24px;padding:0 10px;
    border-radius:var(--r-cta);background:var(--accent-soft);color:var(--accent);
    font-size:12px;font-weight:600;white-space:nowrap}
  .tag.line{background:transparent;border:1px solid var(--line);color:var(--sub);
    font-weight:500}
  .stage-pill,.target-pill,.badge-chip{background:var(--accent-soft);color:var(--accent)}
  .sh-pill,.opt,.group .tier{background:transparent;border:1px solid var(--line);
    color:var(--sub);font-weight:500}
  .ov-chip{background:var(--warn-soft);color:var(--warn)}

  /* ---- intro ---- */
  #intro{background:var(--bg)}
  .intro5{padding:0 26px;text-align:center}
  /* The PNG ships on its own near-#F1EEE7 ground, which reads as a faint square
     on --bg. The radial mask fades that ground out well outside the bowl. */
  .mascot{width:160px;height:160px;display:block;margin:0 auto 12px;
    -webkit-mask-image:radial-gradient(circle at 50% 50%, #000 58%, transparent 74%);
    mask-image:radial-gradient(circle at 50% 50%, #000 58%, transparent 74%)}
  .intro5 .wordmark{margin:0 0 26px;font-size:30px;font-weight:700;letter-spacing:-.02em;
    color:var(--accent);line-height:1.2}
  .intro5 h2{margin:0;font-size:26px;line-height:1.4;font-weight:700;letter-spacing:-.02em;
    color:var(--ink)}
  .intro5 .btn-dark{margin-top:36px;max-width:300px}

  /* ---- 아이 ---- */
  .pg[data-pg="baby"] .card,#profile-card{border:none;border-radius:var(--r-lg);
    padding:16px;box-shadow:var(--shadow);margin-bottom:13px}
  .hctl{display:flex;flex-direction:column;align-items:stretch;gap:0}
  .hdate{flex:none;border:none;border-bottom:1px solid var(--line);border-radius:0;
    background:none;min-height:auto;padding-bottom:12px;margin-bottom:14px}
  .hdate label{position:static;font-size:12px;font-weight:600;color:var(--sub);
    margin-bottom:6px;line-height:1.3}
  .hdate input[type=date]{height:var(--tap);min-height:var(--tap);padding:0 14px;
    border:1px solid var(--line);border-radius:14px;background:var(--well);
    font-size:16px;font-weight:600;color:var(--ink);line-height:1.2}
  .milk-pill{margin-top:12px;align-self:flex-start}
  /* 수유 형태 칩과 수유량 알약을 한 줄에 (사용자 지시, 2026-09-24): 칩 묶음은
     안에서 줄바꿈하지 않고 필요하면 통째로 줄어들고, 알약은 줄 끝에 붙는다
     (margin-left:auto). 폭이 모자라면 알약만 다음 줄로 내려가고, 같은 auto
     마진이 그 줄에서도 알약을 오른쪽 끝에 붙여 둔다. 44px 손가락 바닥은
     .chip/.pill 의 min-height:var(--tap) 그대로 - 여기서는 건드리지 않는다. */
  .feed-line{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px}
  .milk-pill{margin:0 0 0 auto;align-self:center;flex:0 0 auto}
  #go{margin:0 0 2px}
  .notice,.legal{margin:2px 0 14px;font-size:12px;line-height:1.6;color:var(--sub);
    text-align:center}
  #milk-block input[type=number]{background:var(--well);border:1px solid var(--line);
    border-radius:14px;height:var(--tap)}

  /* ---- tab bar (blueprint 1.1, F2 2026-10-02): text only, the lit tab bold, each tab
     --tabbar-h tall; the 식단 dot shows while next week's prep is due (.u-due) ---- */
  .tabs{align-items:stretch;min-height:0;padding:0 8px env(safe-area-inset-bottom);
    background:rgba(255,255,255,.86);border-top:1px solid var(--line);
    -webkit-backdrop-filter:saturate(1.4) blur(14px);backdrop-filter:saturate(1.4) blur(14px);
    box-shadow:0 -1px 0 var(--hair),0 -10px 30px -14px rgba(20,20,20,.18)}
  .tab{position:relative;min-height:var(--tabbar-h);padding:10px 0 14px;justify-content:center;gap:0;
    font-size:14px;font-weight:600;line-height:1.2;color:var(--sub)}
  .tab.on{color:var(--ink);font-weight:700}
  .tab.on::after{content:"";position:absolute;left:50%;bottom:9px;width:18px;height:3px;margin-left:-9px;border-radius:3px;
    background:var(--accent)}
  .u-tabdot{display:none;position:absolute;top:9px;left:calc(50% + 15px);width:7px;height:7px;
    border-radius:50%;background:var(--heart)}
  .tab.u-due .u-tabdot{display:block}
  body{padding-bottom:calc(var(--tabbar-h) + 28px + env(safe-area-inset-bottom))}

  /* ---- scrim + sheets ---- */
  .pnl-scrim{background:rgba(31,42,36,.34)}
  .sh-scrim{background:rgba(31,42,36,.34)}
  .pnl-card.pnl-sheet,.sh{border-radius:var(--r-lg) var(--r-lg) 0 0;background:var(--card);
    box-shadow:0 -6px 24px rgba(31,42,36,.14)}
  .pnl-grip,.sh-grip{width:44px;height:4px;border-radius:2px;background:var(--line);
    margin:0 auto 12px}
  .pnl-head,.sh-head{margin-bottom:16px}
  .pnl-head .pnl-title,.sh h2{font-size:18px;font-weight:700}
  .pnl-close,.sh-close{background:none;padding:0 4px;color:var(--accent);font-size:14px;
    font-weight:600}

  /* ---- 식단 ---- */
  .drink-note{margin:12px 0 0;font-size:12px;color:var(--sub);word-break:keep-all}
  .drink-note .tier, .state .tier{font-weight:400;color:var(--sub)}
  .td-nm .finger-tag, #week .m-name .finger-tag{margin-left:6px;vertical-align:middle}
  .sectitle{margin:0 0 6px;font-size:16px;font-weight:700}
  .autopill span{border-color:var(--accent);color:var(--accent)}
  .switchrow{display:flex;align-items:center;justify-content:space-between;gap:12px;
    background:var(--card);border-radius:var(--r-cta);box-shadow:var(--shadow);
    min-height:var(--tap);padding:8px 8px 8px 18px;margin-bottom:14px;border:none;
    font-family:inherit;width:100%}
  .switchrow span{font-size:14px;font-weight:600;color:var(--ink)}
  /* the switch is a <button role="switch"> carrying .on, so "off" is the
     absence of that class, not a class on the row */
  /* the switch is the only thing the sheet listens to on this row, so the
     button takes the 44px floor and the mockup's 52x30 track is drawn inside it */
  .knob{position:relative;width:52px;height:var(--tap);min-height:var(--tap);
    flex:none;border:none;padding:0;background:none;cursor:pointer;
    font-family:inherit}
  .knob::before{content:"";position:absolute;left:0;right:0;top:7px;height:30px;
    border-radius:var(--r-cta);background:var(--line)}
  .knob.on::before{background:var(--accent)}
  .knob > i{position:absolute;top:10px;left:3px;width:24px;height:24px;
    border-radius:50%;background:#fff;transition:left .15s}
  .knob.on > i{left:25px}
  .rc-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
  .rc-grid .tile{background:var(--card);border-radius:var(--r-lg);box-shadow:var(--shadow);
    overflow:hidden;border:none;padding:0;min-height:var(--tap);text-align:left;
    font-family:inherit;cursor:pointer;display:block;width:100%}
  .rc-grid .tile img{display:block;width:100%;height:78px;object-fit:cover}
  .rc-grid .tile .ph{height:78px;display:grid;place-items:center;background:var(--well);
    color:var(--box)}
  .rc-grid .tile .ph svg{width:36px;height:36px}
  .rc-grid .tile .ph{display:grid}
  .rc-grid .tile .cap{display:block;padding:9px 13px 11px}
  .rc-grid .tile[disabled]{cursor:default}
  .rc-grid .tile .cap b{display:block;font-size:15px;font-weight:700;color:var(--ink)}
  .rc-grid .tile .cap span{display:block;font-size:12px;color:var(--sub);margin-top:2px}
  .rc-grid .tile.soon{box-shadow:none;background:rgba(255,255,255,.5)}
  .rc-grid .tile.soon .cap b{color:var(--sub);font-weight:600}
  .rl{display:flex;gap:12px;align-items:center;background:var(--card);
    border-radius:var(--r-lg);box-shadow:var(--shadow);padding:10px;margin-bottom:10px}
  .rl img{width:72px;height:72px;border-radius:var(--r-md);object-fit:cover;flex:none}
  .rl .ph{width:72px;height:72px;border-radius:var(--r-md);flex:none;display:grid;
    place-items:center;background:var(--well);color:var(--box)}
  .rl .ph svg{width:32px;height:32px}
  .rl .txt{flex:1;min-width:0;display:flex;flex-direction:column}
  .rl h3{margin:0;font-size:15px;font-weight:700;word-break:keep-all;overflow-wrap:normal}
  .rl p{margin:5px 0 0;font-size:12px;color:var(--sub);word-break:keep-all;
    overflow-wrap:normal}
  .rl .slot-add{align-self:flex-end;margin-top:9px;min-height:var(--tap);padding:0 14px;
    border:none;border-radius:var(--r-cta);background:var(--accent-soft);color:var(--accent);
    font-size:12px;font-weight:700}
  .rl .slot-add[disabled]{background:var(--well);color:var(--sub)}
  /* The row's recipe (tier 2) takes a line of its own under the photo and the
     name, so the card keeps its full 272px drawing width. */
  .rl{flex-wrap:wrap}
  .rl > .rec{flex:1 0 100%;margin:0}
  .rl > .rec > summary{min-height:var(--tap)}
  .wk{display:flex;align-items:center;gap:7px;font-size:13px;font-weight:700;
    color:var(--accent);margin:0 0 10px 2px}
  .wk i{width:7px;height:7px;border-radius:50%;background:var(--accent);flex:none}
  .rl-ph{width:72px;height:72px;border-radius:var(--r-md);flex:none;display:grid;
    place-items:center;background:var(--well);color:var(--box)}
  .rl-ph svg{width:32px;height:32px}
  .rc-grid .tile .ph svg,.tile .ph svg{width:36px;height:36px}
  /* the back arrow is a control of its own, so it carries the tap floor rather
     than borrowing one from whatever pill happens to sit beside it */
  .cat-back{min-width:var(--tap);min-height:var(--tap);display:inline-flex;
    align-items:center;justify-content:center;margin-left:-10px;border:none;
    background:none;font-family:inherit;font-size:24px;line-height:1;
    color:var(--accent);cursor:pointer}
  .cat-back[hidden]{display:none}
  #cat-title{flex:1;min-width:0}
  /* the catalog fold's handle is a tap target, so it carries the same pill as
     the recipe fold rather than the 13px link it used to be */
  .rc-more > summary{min-height:var(--tap);display:inline-flex;
    align-items:center;padding:0 16px;border-radius:var(--r-cta);background:var(--accent-soft);
    color:var(--accent);font-size:13px;font-weight:700;list-style:none;cursor:pointer;
    width:fit-content}
  .rc-more > summary::-webkit-details-marker{display:none}
  .rc-more > summary::marker{content:""}
  .rec-week > summary,.rec summary{background:var(--accent-soft);color:var(--accent)}

  /* ---- 장보기 ---- */
  .total{font-size:34px;font-weight:700;letter-spacing:-.02em;margin:2px 0 4px;
    line-height:1.2;color:var(--ink)}
  .shop-total .st-v{font-size:34px;line-height:1.2;letter-spacing:-.02em}
  .shop-total .st-fee{color:var(--accent)}
  /* .pick is also a modifier on .it-row (a tappable cart row), and the card
     shape drawn on that one nests a card inside a card */
  .pick:not(.it-row){background:var(--card);border-radius:var(--r-lg);box-shadow:var(--shadow);
    padding:15px 16px;margin-bottom:11px;border-bottom:none}
  .pick .top{display:flex;align-items:center;gap:10px;margin-bottom:8px}
  .pick .ing{font-size:16px;font-weight:700;flex:1;min-width:0}
  .box-check{width:24px;height:24px;border-radius:8px;flex:none;background:var(--accent);
    color:#fff;display:grid;place-items:center;border-color:var(--accent)}
  .box-check svg{width:16px;height:16px}
  .tick input:not(:checked) + .box-check{background:var(--card);color:transparent;
    border:1px solid var(--box)}
  .pick .pname{margin:0;font-size:13px;color:var(--sub);line-height:1.5;
    word-break:keep-all;overflow-wrap:normal}
  .prow{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
    margin-top:10px}
  .prow .price{font-size:19px;font-weight:700;color:var(--ink)}
  .prow .unit{font-size:12px;color:var(--sub)}
  .disclosure{margin:14px 0 0;font-size:12px;color:var(--sub);line-height:1.5;
    word-break:keep-all}
  .axis{margin-bottom:16px;gap:8px}
  .axis-name{font-size:13px;font-weight:600;color:var(--sub);margin-bottom:0}
  .seg{display:flex;gap:6px;height:auto;padding:0;background:none;border:none;
    border-radius:0}
  .seg button,.seg span{flex:1;min-width:0;height:var(--tap);min-height:var(--tap);
    border-radius:var(--r-cta);background:var(--card);border:1px solid var(--line);
    display:grid;place-items:center;font-size:13px;font-weight:600;color:var(--sub);
    white-space:nowrap;padding:0 6px}
  .seg button.on,.seg span.on{background:var(--accent);border-color:var(--accent);
    color:#fff;font-weight:700}
  .preview{border-top:1px solid var(--line);padding-top:14px;margin-top:4px}
  .preview .lead{font-size:13px;color:var(--sub);margin:0 0 10px}
  .preview .row{display:flex;align-items:baseline;justify-content:space-between;
    gap:10px;padding:7px 0}
  .preview .row span{font-size:14px;font-weight:600}
  .preview .row b{font-size:17px;font-weight:700}
  .preview .row.up b{color:var(--warn)}
  .preview .row.down b{color:var(--accent)}
  /* The dock is a sheet that stops above the tab bar, not a fade over the page.
     sticky, not fixed: an opaque sheet at a fixed offset covers whatever the
     page's bottom padding failed to clear, and that padding would have to be a
     constant guessed from the dock's current contents. Sticky keeps a box of
     its own size at the end of the list, so nothing can end up under it. */
  .shop-dock{position:sticky;bottom:calc(86px + env(safe-area-inset-bottom));
    margin-top:14px;padding:10px 16px 20px;background:var(--card);
    border-radius:var(--r-lg) var(--r-lg) 0 0;box-shadow:0 -6px 24px rgba(31,42,36,.10);
    pointer-events:auto}
  .shop-dock .st-fine{color:var(--sub)}
  /* a link is a tap target even when it is one word under a button */
  .shop-dock .st-fine a{display:inline-flex;align-items:center;justify-content:center;
    min-height:var(--tap);padding:0 10px}
  .shop-dock .dock-head{display:flex;align-items:center;justify-content:flex-end;
    gap:10px;margin-bottom:14px}
  .pg[data-pg="shop"]{padding-bottom:0}

  /* ---- 장보기 rows, after D3 (2026-09-23) --------------------------------
     Four of the mockup's class names could not be put on these elements:
     rubric C2/C4 read `class="badge-chip"`, `class="name"`, `class="pd"` and
     `class="packs"` byte for byte. The live class is styled as the mockup's
     role instead, and no rule here requires .tag / .ing / .pname / .unit. */
  /* §7 3/3 (C-1c): ONE card of two-line rows - checkbox, ingredient over product,
     price on the right; a count over one sits under the price, its ± is in the
     상품 바꾸기 sheet (C-3b). */
  .card.shop-list{background:var(--card);box-shadow:var(--shadow);border-radius:var(--r-lg);
    padding:2px 14px;margin-bottom:12px}
  .card.shop-list:has(> #cart:empty):has(> #cart-skel[hidden]){display:none}
  .cart-item.pick{position:relative;display:flex;align-items:flex-start;gap:6px;padding:10px 0;
    margin:0;background:none;box-shadow:none;border-radius:0;border-bottom:1px solid var(--line)}
  .cart-item.pick:last-child{border-bottom:0}
  .cart-item.pick > .it-row{display:flex;align-items:flex-start;gap:10px;flex:1;min-width:0;
    min-height:0;padding:0;text-align:left}
  .cart-item.pick .mid{display:block;gap:0;flex:1;min-width:0}
  /* the tick is a <label> around an <input>, so it cannot live inside the row
     <button>; it is the row's first cell, its box centred on the name line */
  .cart-item.pick > .tick{position:relative;flex:none;flex-direction:row;
    justify-content:center;width:var(--tap);min-width:var(--tap);height:var(--tap);
    min-height:var(--tap);gap:0;margin:-12px 0 -12px -10px}
  /* the approved frame draws a checkbox beside the name and no 있음 word. The
     word stays in the DOM - the input's aria-label is not the only thing that
     may read it - and leaves the picture. */
  .cart-item.pick .tick .lb{position:absolute;width:1px;height:1px;overflow:hidden;
    clip:rect(0 0 0 0);white-space:nowrap}
  .cart-item.pick .tick .bx.box-check{width:24px;height:24px;border-radius:8px;
    border:1.5px solid var(--box);background:var(--card);color:transparent}
  .cart-item.pick .tick input:checked + .bx.box-check{background:var(--accent);
    border-color:var(--accent);color:#fff}
  .cart-item.pick .tick .bx.box-check svg{width:16px;height:16px}
  .cart-item.pick .r-nmline.top{display:flex;align-items:center;flex-wrap:nowrap;
    gap:6px;min-height:20px;padding:0;margin:0}
  .cart-item.pick .name{font-size:15px;font-weight:700;flex:0 1 auto;min-width:0;
    line-height:20px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .cart-item.pick .badge-chip{flex:none;height:20px;padding:0 8px;font-size:12px;
    font-weight:600}
  .cart-item.pick .pd{font-size:13px;color:var(--sub);line-height:18px;margin-top:2px;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .cart-item.pick .opt-chip.tag.line,.cart-item.pick .ov-chip.tag.line{
    display:inline-flex;align-items:center;height:24px;margin-left:5px;padding:0 10px;
    border-radius:var(--r-cta);background:transparent;border:1px solid var(--line);
    color:var(--sub);font-size:12px;font-weight:500}
  .cart-item.pick .pr.prow{display:block;margin:0;flex:none;white-space:nowrap}
  .cart-item.pick .pr.prow .price{font-size:15px;line-height:20px;font-weight:700;color:var(--ink)}
  .cart-item.pick .pr.prow .packs{display:block;text-align:right}
  .cart-item.pick .r-sub{font-size:12px;color:var(--sub);line-height:1.5}
  .cart-item.pick.opt-only :is(.r-nmline.top,.pd){padding-right:124px}
  .cart-item.pick > .opt-go{position:absolute;top:4px;right:0;display:inline-flex;align-items:center;min-height:32px;
    padding:0 10px;border-radius:999px;background:#F6EBCF;
    color:#7A5A0A;border:1.5px solid #E6D3A0;font-size:12px;font-weight:700;
    white-space:nowrap;text-decoration:none}
  .shop-total .pill{align-self:flex-start;margin-top:14px}

  /* ---- 고르는 기준 sheet -------------------------------------------------
     #shop-axes is LENT to the sheet, not copied, so the card has to stop
     reading as a card while it is standing in one. */
  .axes-card:empty{display:none}
  /* the property toggle shop.js uses cannot fire when a week is refused from
     outside shop.js; this closes on the pill's presence, which the browser
     re-evaluates live, and stops matching once the card is in the sheet */
  .pg[data-pg="shop"]:has(#shop-crit) > #shop-axes{display:none}
  .crit #shop-axes{box-shadow:none;padding:0;background:none;border-radius:0;
    margin-bottom:0}
  .sh-head .axes-head{flex:1;min-width:0;font-size:18px;font-weight:700}
  .crit .preview p{font-size:12px;line-height:17px;color:var(--sub);margin:0 0 6px}
  .crit .preview p:last-child{margin-bottom:0}
  .crit .preview .st-fee{color:var(--accent);font-weight:700}
  .prod-cta{border-radius:var(--r-cta);min-height:52px;background:var(--accent)}
  .sh .chip.tier{background:var(--accent-soft);border-color:var(--accent-soft);
    color:var(--accent)}
  /* The 44px hit area these chips used to carry went with the role: the only
     span.chip inside a sheet is the 상품 상세 tag row (.prod-main), and
     syncChipAccess no longer calls those buttons. They are tags again. */
  .amt-grid button.on,.have-btn.on{background:var(--accent-soft);border-color:var(--accent);
    color:var(--accent)}
  .rs-i{background:var(--accent-soft);color:var(--accent)}
  .rs-t{color:var(--accent)}
  .sc.on,.rchips span.on,.rc .put{background:var(--accent);color:#fff}
  .dd i,.dotleg i{background:var(--accent)}
  .dd i.m,.dotleg i.m{background:var(--carb)}
  #pnl-data .note.ver{font-size:13px}

  /* ---- Motion (2026-09-23) ---------------------------------------------
     Only where a value changes, and all of it off under the global
     prefers-reduced-motion rule above. */
  .rl.tapped{transform:scale(.96);opacity:.35;
    transition:transform 150ms ease-out,opacity 150ms ease-out}
  @keyframes sheet-in{from{opacity:0;transform:translateY(16px)}}
  @keyframes sheet-out{to{opacity:0;transform:translateY(16px)}}
  .sh.opening,.pnl-card.opening{animation:sheet-in 220ms cubic-bezier(.2,.8,.2,1)}
  .sh.closing,.pnl-card.closing{animation:sheet-out 160ms cubic-bezier(.2,.8,.2,1) forwards}
  .sh.closing.late{animation-delay:150ms}
  @keyframes mascot-float{50%{transform:translateY(-4px)}}
  .mascot{animation:mascot-float 3s ease-in-out infinite}
  .chip{transition:scale 180ms var(--mo-spring),background 120ms ease,color 120ms ease,
    border-color 120ms ease}
  /* 담기 keeps its busy class under reduced motion, so the dots have to READ as
     dots standing still - the pulse is the only thing the media rule takes. */
  @keyframes cfm-dots{to{opacity:.4}}
  .cfm-go.busy::after{content:"\00B7\00B7\00B7";margin-left:6px;letter-spacing:2px;
    animation:cfm-dots 300ms ease-in-out infinite alternate}
  /* shop.js takes .done off after the new word's animationend (800ms fallback, ~1s after the press), first fading this ✓ out and closing its room with the Web Animations API on ::after */
  @keyframes cfm-tick{from{opacity:0;transform:scale(.6)}}
  .cfm-go.done::after{content:"\2713";display:inline-block;margin-left:6px;
    animation:cfm-tick 180ms ease-out}

  /* ---- Save-failure line: the one place a failed save says so (shell.js saveFailShow
     writes #np-status). It sits outside every .pg so it shows on whichever page is open
     (Codex wave 10: inside the diary page it was display:none everywhere else), at the
     toast-area's height above the tab bar. The sheet carries its own (.sh-fail). */
  .save-fail{position:fixed;left:16px;right:16px;max-width:488px;margin:0 auto;z-index:31;
    bottom:calc(var(--tabbar-h) + 76px + env(safe-area-inset-bottom));padding:10px 14px;border-radius:12px;
    background:var(--warn-soft);box-shadow:0 2px 10px rgba(0,0,0,.12);
    font-size:13px;font-weight:700;color:var(--warn);text-align:center}
  /* 장보기's sticky dock, the cook timer stack and the prep steps' .nx-dock (no tab bar) sit
     at the bottom with a height set by their content, so no bottom offset is sure to clear
     them: on those pages the line sits at the top instead. */
  body:has(.pg[data-pg="shop"]:not([hidden]), .pg[data-pg="cook"]:not([hidden]),
    .pg[data-pg="plan"]:not([hidden])) .save-fail{
    top:calc(8px + env(safe-area-inset-top));bottom:auto}
  /* Over an open panel (a write refused inside it must still say so): above the scrim (41)
     and the panel (42), under a .sh opened from it (44, it has .sh-fail). A bottom sheet leaves the
     top 56px to the scrim, so the line sits there; a full-screen panel's nav bar is at the
     top, so it sits at the bottom, over the 90px its .pnl-body keeps free. The id outranks
     the shop/cook rule. */
  body[data-panel-open] #np-status{z-index:43}
  body[data-panel-sheet] #np-status{top:calc(8px + env(safe-area-inset-top));bottom:auto}
  body[data-panel-open]:not([data-panel-sheet]) #np-status{top:auto;bottom:calc(16px + env(safe-area-inset-bottom))}
  /* While the line shows, the page can scroll its last row clear of it (its offset + the
     line's 41px + a gap), as the tab-bar padding does for the tab bar. */
  body:has(#np-status:not([hidden])){padding-bottom:calc(var(--tabbar-h) + 128px + env(safe-area-inset-bottom))}
  .sh-fail{margin:8px 0 0;font-size:13px;font-weight:700;color:var(--warn);text-align:center}
  /* ---- Loop renewal (R2, 2026-09-26) -----------------------------------------
     Tokens and components ported from the approved loop mockup. Every class
     carries an area prefix - pp- 한 주 준비, td- 오늘, kd- 아이, ck- 요리 모드,
     ob- 처음 시작, mo- 모션 - because 60 mockup names (card, chip, seg, ring,
     toast, top ...) already mean something else in this sheet. A primitive
     used by several areas is ONE rule listing each area's name, never a seventh
     prefix. Mockup sizes under 12px are raised to 12px and tappables to
     var(--tap): the two floors at the top of this file. The mockup's
     absolute-in-phone boxes are fixed here, inside the 520px column and above
     the tab bar. Motion itself is round R9; only its tokens are here. */
  :root {
    --mo-out:cubic-bezier(.2,.8,.2,1); --mo-in:cubic-bezier(.4,0,1,1); --mo-inout:cubic-bezier(.4,0,.2,1);
    --mo-spring:cubic-bezier(.3,1.3,.5,1);
    --mo-t1:120ms; --mo-t2:220ms; --mo-t3:320ms; --mo-t4:600ms;
    /* multiplies every travel distance, so reduced motion keeps the fades */
    --mo-shift:1;
  }
  @media (prefers-reduced-motion:reduce) {
    :root { --mo-spring:var(--mo-out); --mo-shift:0; }
  }

  /* full-screen hosts */
  .ob-screen{position:fixed;inset:0;z-index:48;max-width:520px;margin:0 auto;overflow-y:auto;
    background:var(--bg);padding:22px 16px 100px}
  .ob-screen[hidden]{display:none}
  .pg[data-pg="cook"]{padding-bottom:204px}
  .pg[data-pg="plan"]{padding-bottom:170px}

  /* shared primitives */
  .pp-ic,.td-ic,.kd-ic,.ck-ic,.ob-ic{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:1.8;
    stroke-linecap:round;stroke-linejoin:round;flex:0 0 auto}
  .pp-sp,.td-sp,.kd-sp,.ck-sp,.ob-sp{flex:1}
  .pp-hero,.td-hero,.kd-hero,.ck-hero,.ob-hero{font-size:25px;font-weight:700;letter-spacing:-.6px;line-height:1.28;margin:0}
  .pp-sub,.td-sub,.kd-sub,.ck-sub,.ob-sub{font-size:13px;color:var(--sub)}
  .pp-lbl,.td-lbl,.kd-lbl,.ck-lbl,.ob-lbl{font-size:12px;color:var(--sub);font-weight:600;display:flex;align-items:center;gap:6px}
  .pp-card,.td-card,.kd-card,.ck-card,.ob-card{background:var(--card);border-radius:var(--r-lg);box-shadow:var(--shadow);
    padding:16px;margin-bottom:12px}
  .pp-card.pp-t,.td-card.td-t,.kd-card.kd-t,.ck-card.ck-t,.ob-card.ob-t{padding:12px 14px}
  .pp-cta,.td-cta,.kd-cta,.ck-cta,.ob-cta{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;
    min-height:54px;border-radius:999px;background:var(--accent);color:#fff;font-weight:700;font-size:16px;border:0;
    font-family:inherit;cursor:pointer}
  .pp-cta.pp-fix,.td-cta.td-fix,.kd-cta.kd-fix,.ck-cta.ck-fix{position:fixed;left:16px;right:16px;
    bottom:calc(98px + env(safe-area-inset-bottom));z-index:29;max-width:488px;width:auto;margin:0 auto;
    box-shadow:0 8px 20px rgba(63,125,91,.28)}
  .pp-cta.pp-off,.td-cta.td-off,.kd-cta.kd-off,.ck-cta.ck-off,.ob-cta.ob-off{background:#C9CFCB;box-shadow:none}
  .pp-ghost,.td-ghost,.kd-ghost,.ck-ghost{display:inline-flex;align-items:center;justify-content:center;gap:6px;
    min-height:var(--tap);border-radius:999px;background:var(--card);border:1px solid var(--line);color:var(--ink);
    font-weight:600;font-size:13.5px;font-family:inherit;padding:0 14px;cursor:pointer}
  .pp-ghost.pp-sm,.td-ghost.td-sm,.kd-ghost.kd-sm,.ck-ghost.ck-sm{font-size:12.5px;padding:0 12px}
  .pp-ghost.pp-warn,.td-ghost.td-warn,.kd-ghost.kd-warn,.ck-ghost.ck-warn{color:var(--warn);border-color:#E6BFA9}
  .pp-ghost.pp-wide,.td-ghost.td-wide,.kd-ghost.kd-wide,.ck-ghost.ck-wide{width:100%;margin-top:10px}
  .pp-top,.kd-top,.ck-top{display:flex;align-items:center;gap:8px;margin-bottom:14px}
  .pp-av,.kd-av,.ck-av{width:34px;height:34px;border-radius:50%;background:var(--card);box-shadow:var(--shadow);
    overflow:hidden;display:grid;place-items:center;flex:0 0 auto}
  .pp-av img,.kd-av img,.ck-av img{width:40px;height:40px;object-fit:cover}
  .pp-badge,.td-badge,.kd-badge,.ck-badge,.ob-badge{background:var(--accent-soft);color:#24553C;border-radius:999px;
    font-size:12px;font-weight:700;padding:5px 11px}
  .pp-dt,.ck-dt{font-size:12px;color:var(--sub)}
  .pp-hrow,.ck-hrow{display:flex;align-items:center;gap:8px;margin-bottom:12px}
  .pp-hrow .pp-dt{display:block;margin-top:2px}
  .pp-sht,.td-sht,.kd-sht,.ck-sht{font-size:20px;font-weight:700;margin:0 0 4px;letter-spacing:-.3px}
  .pp-shs,.td-shs,.kd-shs,.ck-shs{font-size:13px;color:var(--sub);margin:0 0 14px}
  .td-chips,.kd-chips,.ob-chips{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:14px}
  .td-chip,.kd-chip,.ob-chip{min-height:var(--tap);padding:0 14px 0 6px;border-radius:999px;border:1px solid var(--line);
    background:#fff;display:inline-flex;align-items:center;font-size:14px;gap:4px;color:var(--ink);font-family:inherit;cursor:pointer}
  .td-chip.td-t,.kd-chip.kd-t,.ob-chip.ob-t{padding:0 14px}
  .td-chip img,.kd-chip img,.ob-chip img{width:32px;height:32px}
  .td-chip.td-on,.kd-chip.kd-on,.ob-chip.ob-on{background:var(--accent-soft);border-color:var(--accent-soft);font-weight:700}
  .td-chip.td-bad,.kd-chip.kd-bad,.ob-chip.ob-bad{color:var(--warn);border-color:#E6BFA9}
  .td-chip.td-bad.td-on,.kd-chip.kd-bad.kd-on,.ob-chip.ob-bad.ob-on{background:var(--warn-soft)}
  .pp-empty,.td-empty,.ck-empty,.ob-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;
    gap:6px;min-height:430px;text-align:center}
  .pp-empty img,.td-empty img,.ck-empty img,.ob-empty img{width:150px;height:150px;border-radius:50%;object-fit:cover;box-shadow:var(--shadow)}
  .pp-empty b,.td-empty b,.ck-empty b,.ob-empty b{font-size:24px;margin-top:10px}
  .pp-empty span,.td-empty span,.ck-empty span,.ob-empty span{font-size:14px;color:var(--sub)}
  .pp-toast,.td-toast{background:#1F2A24;color:#fff;border-radius:16px;padding:11px 14px;font-size:12.5px;
    display:flex;align-items:center;gap:8px;margin-bottom:14px}
  .pp-toast .pp-ic,.td-toast .td-ic{color:#BFE0CC;width:16px;height:16px}
  .pp-toast span,.td-toast span{color:#C9D3CD}
  .pp-cb,.kd-cb,.ob-cb{width:24px;height:24px;border-radius:7px;border:1.5px solid #CFC9BE;display:grid;place-items:center;flex:0 0 auto}
  .pp-cb.pp-on,.kd-cb.kd-on,.ob-cb.ob-on{background:var(--accent);border-color:var(--accent);color:#fff}
  .pp-cb svg,.kd-cb svg,.ob-cb svg{width:15px;height:15px;stroke-width:2.6}
  .kd-notice,.ob-notice{font-size:12px;color:var(--sub);line-height:1.5;text-align:center;margin:0}
  .td-urgent,.kd-urgent{background:var(--warn-soft);color:#6E3A20;border-radius:var(--r-md);padding:12px 14px;
    font-size:13px;line-height:1.55;margin-bottom:14px}
  .ck-st-row,.kd-st-row,.ob-st-row,.pp-st-row{display:flex;align-items:center;justify-content:space-between;gap:8px;
    padding:11px 0;border-bottom:1px solid var(--line);font-size:14px}
  .td-st-num,.kd-st-num{display:flex;align-items:center;justify-content:center;gap:22px;margin:12px 0}
  .td-st-num b,.kd-st-num b{font-size:42px;letter-spacing:-1px;min-width:80px;text-align:center}
  .td-st-num button,.kd-st-num button{width:var(--tap);height:var(--tap);border-radius:50%;border:1px solid var(--line);
    display:grid;place-items:center;font-size:22px;color:var(--sub);background:#fff;font-family:inherit;cursor:pointer}
  .td-stt,.ck-stt{width:36px;height:36px;border-radius:50%;background:var(--accent-soft);color:var(--accent);display:grid;place-items:center}
  .td-stt svg,.ck-stt svg{width:18px;height:18px;stroke-width:2.6}
  .td-procs,.ck-procs{margin:0 0 10px;padding:0;list-style:none;counter-reset:pr;background:var(--card);
    border-radius:var(--r-md);box-shadow:var(--shadow)}
  .td-procs li,.ck-procs li{counter-increment:pr;display:flex;gap:10px;align-items:flex-start;font-size:14px;line-height:1.5;
    padding:10px 14px;border-bottom:1px solid var(--line)}
  .td-procs li:last-child,.ck-procs li:last-child{border-bottom:0}
  .td-procs li::before,.ck-procs li::before{content:counter(pr);flex:0 0 22px;height:22px;border-radius:50%;
    background:var(--accent-soft);color:var(--accent);font-size:12px;font-weight:700;display:grid;place-items:center;margin-top:1px}
  .td-procs.td-sm,.ck-procs.ck-sm{box-shadow:none;background:var(--bg)}
  .td-procs.td-sm li,.ck-procs.ck-sm li{font-size:13px;padding:8px 12px}
  .td-keyb,.ck-keyb{display:flex;gap:10px;align-items:flex-start;background:var(--warn-soft);border-radius:var(--r-md);
    padding:10px 12px;font-size:13px;line-height:1.5;color:#6E3A20}
  .td-kl,.ck-kl{flex:0 0 auto;font-size:12px;font-weight:700;background:var(--warn);color:#fff;border-radius:999px;
    padding:2px 8px;margin-top:1px}
  .pp-tc,.ck-tc{background:var(--card);border-radius:var(--r-lg);box-shadow:var(--shadow);padding:10px 12px;
    margin-bottom:10px;display:flex;align-items:center;gap:12px}
  .pp-th,.ck-th{display:flex;flex-direction:column;align-items:center;width:84px;flex:0 0 auto}
  .pp-th img,.ck-th img{width:76px;height:62px;object-fit:contain}
  .pp-th b,.ck-th b{font-size:12.5px}
  .pp-tq,.ck-tq{display:flex;align-items:center;flex-wrap:wrap;gap:4px;font-size:13px;font-weight:600}
  .pp-tq span,.ck-tq span{background:var(--bg);border-radius:999px;padding:5px 10px}
  .pp-tq svg,.ck-tq svg{width:14px;height:14px;color:#B8B2A6}


  /* 한 주 준비: ① 다음 주 밥상 · ③ 다음 주 식단 · ④ 바꾸기 창 */
  .pp-buybar{display:flex;align-items:center;gap:10px}
  .pp-buybar .pp-big{font-size:22px;font-weight:700;letter-spacing:-.4px}
  /* C2 다음 주 준비: the step bar (‹ = the previous step, V3 hatches a skipped 1/3),
     the 2/3 head. */
  .pp-stepbar{display:flex;align-items:center;gap:8px;margin:0 0 12px;font-size:12px;color:var(--sub);white-space:nowrap}
  .pp-sb-bk{width:36px;height:36px;flex:none;border:0;border-radius:50%;background:var(--card);box-shadow:var(--shadow);
    font-family:inherit;font-size:18px;color:var(--ink);cursor:pointer}
  .pp-sbar{flex:1;display:flex;gap:6px}
  .pp-sbar span{flex:1;height:6px;border-radius:3px;background:#E1DCD2}
  .pp-sbar span.on{background:var(--accent)}
  .pp-sbar span.skip{background:repeating-linear-gradient(90deg,#E1DCD2 0 4px,#fff 4px 8px)}
  .pp-h5{font-size:16px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .pp-phead{display:flex;align-items:center;gap:6px;margin-bottom:8px}
  .pp-phead > b{font-size:17px;white-space:nowrap}
  .pp-pill{font-size:12px;font-weight:700;color:var(--accent);background:var(--accent-soft);border-radius:999px;
    padding:2px 8px;white-space:nowrap}
  .pp-card.pp-rows{padding:2px 14px}
  .pp-gline{margin-top:6px;font-size:12px;color:var(--sub);text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .pp-days,.td-days{display:flex;gap:6px;margin-bottom:12px}
  .pp-days button,.td-days button{position:relative;flex:1;min-height:52px;border:0;border-radius:16px;background:var(--card);
    display:flex;flex-direction:column;align-items:center;justify-content:center;font-family:inherit;font-size:13px;
    font-weight:600;color:var(--ink);box-shadow:var(--shadow);cursor:pointer}
  .pp-days small,.td-days small{font-size:12px;color:var(--sub);font-weight:500}
  .pp-days .pp-on,.td-days .td-on{background:var(--accent);color:#fff}
  .pp-days .pp-on small,.td-days .td-on small{color:#D6EADF}
  .td-days .td-past{background:var(--accent-soft)}
  .td-days .td-past small{color:var(--accent);font-weight:700}
  .pp-mrow,.td-mrow{display:flex;align-items:center;gap:12px;background:var(--card);border-radius:var(--r-md);
    box-shadow:var(--shadow);padding:10px;margin-bottom:10px}
  .pp-mrow img.pp-p,.td-mrow img.td-p{width:72px;height:72px;border-radius:14px;object-fit:cover}
  .pp-mrow .pp-nm,.td-mrow .td-nm{font-size:14.5px;font-weight:700;line-height:1.35}
  .pp-mrow .pp-k,.td-mrow .td-k{font-size:12px;color:var(--sub);margin-bottom:2px}
  .pp-mrow .pp-k em{font-style:normal;background:var(--accent);color:#fff;border-radius:999px;font-size:12px;font-weight:700;
    padding:1px 7px;margin-left:4px}
  .td-mrow.td-done1{opacity:.75}
  .pp-pips{display:flex;gap:2px;margin-top:5px}
  .pp-pips img{width:22px;height:22px}
  .pp-swap,.td-swap{width:var(--tap);height:var(--tap);border-radius:50%;border:0;background:var(--accent-soft);color:var(--accent);
    display:grid;place-items:center;flex:0 0 auto;cursor:pointer}
  .pp-lockb,.td-lockb{width:var(--tap);height:var(--tap);border-radius:50%;border:0;background:transparent;display:grid;
    place-items:center;color:#B8B2A6;flex:0 0 auto;cursor:pointer}
  .pp-lockb.pp-on,.td-lockb.td-on{background:var(--ink);color:#fff}
  .pp-lockb svg,.td-lockb svg{width:18px;height:18px}
  .pp-snkbox,.td-snkbox{width:72px;height:72px;border-radius:14px;background:var(--bg);display:grid;place-items:center;flex:0 0 auto}
  .pp-snkbox img,.td-snkbox img{width:54px;height:54px}
  .pp-carousel{display:flex;align-items:center;justify-content:center;gap:8px;margin:0 -16px}
  .pp-cc{border-radius:20px;overflow:hidden;flex:0 0 auto}
  .pp-cc.pp-side{width:56px;height:150px;opacity:.5}
  .pp-cc.pp-side img{width:100%;height:100%;object-fit:cover}
  .pp-cc.pp-main{width:240px;background:var(--bg)}
  .pp-cc.pp-main img{width:240px;height:160px;object-fit:cover;display:block}
  .pp-cn{font-size:14px;font-weight:700;padding:10px 12px}
  /* C5 swap sheet: V1 two lines everywhere (the card, 지금, the list rows), nowrap with ellipsis */
  .pp-cn b,.pp-nowtx b,.pp-pick-tx b{display:block;font-size:14px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .pp-cn em,.pp-nowtx em,.pp-pick-tx em{display:block;font-style:normal;font-weight:500;font-size:12px;color:#7A8480;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .pp-now{display:flex;align-items:center;gap:10px;background:var(--bg);border-radius:16px;padding:8px 12px;margin:4px 0 0}
  .pp-now .pp-lbl{flex:none}
  .pp-nowtx,.pp-pick-tx{min-width:0;flex:1}
  .pp-none{font-size:14px;color:var(--sub);text-align:center;margin:18px 0 4px}
  #pp-swap .pp-more{margin-top:8px}
  .pp-chips{display:flex;gap:6px;margin:4px 0 10px;overflow-x:auto}
  .pp-chip{flex:none;min-height:36px;padding:0 12px;border-radius:999px;border:1.5px solid var(--line);background:#fff;
    font:inherit;font-size:13px;font-weight:650;color:var(--ink);white-space:nowrap;cursor:pointer}
  .pp-chip.pp-on{border-color:var(--accent);color:var(--accent)}
  .pp-chip:disabled{color:#B7B2A8;cursor:default}
  .pp-picks{padding:2px 14px}
  .pp-pick{display:flex;align-items:center;gap:8px;min-height:60px;border-bottom:1px solid var(--line)}
  .pp-pick:last-child{border-bottom:0}
  .pp-pick .td-tag{flex:none}
  .pp-pick .pp-ghost{flex:none}
  .pp-cdots{display:flex;justify-content:center;gap:5px;margin-top:10px}
  .pp-cdots i{width:6px;height:6px;border-radius:50%;background:#D5D0C6}
  .pp-cdots i.pp-on{background:var(--ink);width:16px;border-radius:3px}

  /* 한 주 준비: ② 장보기 (팩 수 ± and ②-1 · ②-3; the rows themselves are the live ones) */
  .pp-stepper{display:inline-flex;align-items:center;border:1px solid var(--line);border-radius:999px;min-height:var(--tap)}
  .pp-stepper button{width:var(--tap);min-height:var(--tap);border:0;background:transparent;display:grid;place-items:center;
    color:var(--sub);font-family:inherit;font-size:16px;cursor:pointer}
  .pp-stepper b{min-width:34px;text-align:center;font-size:13px}
  .pp-st-opts{display:flex;background:var(--bg);border-radius:999px;padding:3px}
  .pp-st-opts button{min-height:var(--tap);font-family:inherit;font-size:12px;padding:0 9px;border:0;border-radius:999px;
    background:transparent;color:var(--sub);white-space:nowrap;cursor:pointer}
  .pp-st-opts button.pp-on{background:#fff;color:var(--ink);font-weight:700;box-shadow:var(--shadow)}
  .pp-ps-card{background:var(--bg);border-radius:var(--r-md);padding:12px}
  .pp-ps-lbl{font-size:12px;font-weight:700;color:var(--sub);margin:14px 0 8px}
  .pp-ps-funnel{display:flex;align-items:flex-end;gap:6px}
  .pp-ps-f{flex:1;text-align:center}
  .pp-ps-f i{display:block;background:var(--accent-soft);border-radius:8px 8px 4px 4px;margin:0 auto 4px}
  .pp-ps-f.pp-on i{background:var(--accent)}
  .pp-ps-f b{font-size:18px;display:block}
  .pp-ps-f span{font-size:12px;color:var(--sub);display:block;line-height:1.3}
  .pp-ps-share{height:8px;border-radius:4px;background:var(--line);position:relative;margin:2px 0 6px}
  .pp-ps-share i{position:absolute;left:0;top:0;bottom:0;background:var(--accent);border-radius:4px}
  .pp-ps-relog{display:flex;align-items:center;justify-content:center;gap:8px;margin-top:10px;font-size:12.5px;color:var(--sub)}
  /* 한 주 준비: ② 장보기 - R5 (팩 수 ± · 담음 · 두 알약 · 확인 창 고지 · 불러오기 실패) */
  .cart-item.pick .pp-stepper button{width:32px}
  .cart-item.pick .pp-stepper b{min-width:30px}
  .pp-stepper button:disabled{color:var(--line);cursor:default}
  .pp-stepper b .packs{font-size:13px;color:var(--ink);font-weight:700}
  .cart-item.pick.pp-had{padding-top:6px;padding-bottom:6px;opacity:.6}
  .cart-item.pick.pp-had .r-nmline.top{padding-left:0;padding-right:0;margin-bottom:0}
  .pp-got{margin-left:auto}
  .pp-pills{display:flex;align-items:center;justify-content:center;gap:8px;margin-top:10px;flex-wrap:wrap}
  .pp-pills .pill,.pp-pills .tag{flex:1;min-width:0;justify-content:center;min-height:var(--tap);text-decoration:none}
  .shop-dock a.st-go{display:flex;align-items:center;justify-content:center;text-decoration:none}
  /* V5 · C29 · C34 · C32: the verb and its numbers, the handed-off line, the stale date. */
  .shop-dock .st-go:has(.st-sm){display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px}
  .st-go .st-sm{font-size:12px;font-weight:500;opacity:.85;white-space:nowrap}
  .shop-dock a.st-go.ghost{background:var(--card);color:var(--accent);border:1.5px solid var(--accent)}
  .st-done{min-height:44px;display:flex;align-items:center;justify-content:center;margin-bottom:6px;border-radius:var(--r-cta);
    background:var(--accent-soft);color:var(--accent);font-weight:700;white-space:nowrap}
  .st-s .st-old{color:#B7791F;font-weight:700}
  .pp-cfm-note{font-size:12px;color:var(--sub);line-height:1.6;margin:12px 0 0}
  .pp-cfm-note + .pp-cfm-note{margin-top:4px}
  /* 3/3 로딩 (products.json on its way) and 상품 0 (수집 실패 / 빈 파일) */
  .cart-skel:not([hidden]){display:flex;flex-direction:column;gap:14px;padding:16px 0}
  .cart-skel i{display:block;height:14px;border-radius:7px;background:#D9D4CA;opacity:.6}
  .cart-skel i:nth-child(2){width:78%}.cart-skel i:nth-child(3){width:56%}
  .shop-total.loading .st-v{color:var(--sub)}
  .shop-dock .st-go:disabled{background:#D9D4CA;color:#fff;border-color:#D9D4CA}
  .shop-empty{display:flex;flex-direction:column;align-items:center;text-align:center;gap:2px;
    padding:32px 16px 16px;color:var(--sub);font-size:13px;line-height:1.5}
  .shop-empty b{font-size:18px;color:var(--ink);margin-bottom:2px}
  .shop-empty .st-go{align-self:stretch;margin-top:18px;display:flex;align-items:center;justify-content:center;
    min-height:var(--tap);border-radius:var(--r-cta);background:var(--card);color:var(--accent);
    border:1.5px solid var(--accent);font-weight:700;text-decoration:none}
  .shop-fail .st-go + .st-go{margin-top:8px}
  .pg[data-pg="shop"]:has(.shop-empty, .shop-total.loading) > #shop-axes{display:none}
  .cfm-prog{margin:8px 0 0;font-size:13px;font-weight:700;color:var(--accent)}
  .shop-dock .pp-ps-relog{justify-content:space-between;text-align:left}
  .shop-dock .pp-ps-relog button{flex:none;white-space:nowrap}
  .shop-sum:has(> #cart-all:empty){display:none}
  .shop-dock:empty{display:none}

  /* 한 주 준비: ⑤ 재료 만들기 · 후기/완료기 밑준비 */
  .pp-deal{display:flex;align-items:center;justify-content:center;gap:10px;background:var(--card);border-radius:var(--r-lg);
    box-shadow:var(--shadow);padding:22px 12px;margin-bottom:12px}
  .pp-dq{flex:1;display:flex;flex-direction:column;align-items:center;text-align:center}
  .pp-di{width:48px;height:48px;border-radius:50%;background:var(--accent-soft);color:var(--accent);display:grid;
    place-items:center;margin-bottom:8px}
  .pp-di svg{width:26px;height:26px}
  .pp-dq b{font-size:40px;letter-spacing:-1.4px;line-height:1}
  .pp-dq b small{font-size:16px;letter-spacing:0;margin-left:2px}
  .pp-dq span{font-size:12.5px;color:var(--sub);margin-top:4px}
  .pp-arrow{width:28px;height:28px;color:#B8B2A6}
  .pp-board{padding:16px 10px 14px}
  .pp-track{display:grid;grid-template-columns:repeat(3,1fr);position:relative}
  .pp-track::before{content:"";position:absolute;left:16%;right:16%;top:49px;border-top:2px dashed #C9DCCF}
  .pp-stage{display:flex;flex-direction:column;align-items:center;text-align:center;position:relative}
  .pp-stage .pp-art{width:56px;height:56px;border-radius:50%;background:var(--accent-soft);color:var(--accent);display:grid;
    place-items:center;box-shadow:0 0 0 5px #fff}
  .pp-stage .pp-art svg{width:28px;height:28px;stroke-width:1.6}
  .pp-stage b{font-size:14px;margin-top:8px}
  .pp-stage .pp-tm{font-size:12.5px;font-weight:700;color:var(--ink);margin-bottom:6px}
  .pp-tl{font-size:12px;color:var(--ink);background:var(--bg);border-radius:999px;padding:3px 9px;margin-top:6px}
  .pp-guards{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-top:12px;padding-top:12px;border-top:1px solid var(--line)}
  .pp-guards div{text-align:center;font-size:12px;line-height:1.5;color:var(--ink)}
  .pp-guards svg{display:block;margin:0 auto 3px;width:16px;height:16px;color:var(--warn)}
  .pp-guards em{font-style:normal;color:var(--warn);font-weight:700}
  .pp-tools3{margin-top:12px}
  .pp-tools3 .pp-tlh{display:block;font-size:12px;font-weight:700;color:var(--sub);margin:0 0 6px 4px}
  .pp-tools3 div{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;text-align:center}
  .pp-tools3 .pp-tl{padding:4px 6px;margin-top:0;white-space:nowrap}
  .pp-freshrow{display:flex;align-items:center;gap:8px;background:var(--card);border-radius:var(--r-md);box-shadow:var(--shadow);
    padding:8px 12px;font-size:13px}
  .pp-freshrow img{width:30px;height:30px}
  .pp-fl2{font-size:12px;font-weight:700;background:var(--accent-soft);color:#24553C;border-radius:999px;padding:2px 8px}
  .pp-fl3{margin-left:auto;font-size:12px;color:var(--sub)}

  /* 요리 모드 (⑥ ⑦) */
  .ck-prog{display:flex;gap:4px;margin:4px 0 20px}
  .ck-prog i{flex:1;height:5px;border-radius:3px;background:var(--line)}
  .ck-prog i.ck-on{background:var(--accent)}
  .ck-sthead{display:flex;align-items:center;gap:12px;margin:-4px 0 10px}
  .ck-sthead img{width:110px;height:92px;object-fit:contain;flex:0 0 auto}
  .ck-sttitle{font-size:22px;font-weight:800;letter-spacing:-.015em;line-height:1.3}
  .ck-cube-trio{display:flex;align-items:center;width:110px;flex:0 0 auto}
  .ck-cube-trio img{width:44px;height:44px;margin-right:-10px}
  .ck-cube-counts{display:flex;flex-wrap:wrap;gap:5px;margin-top:10px}
  .ck-cube-counts span{display:inline-flex;align-items:center;gap:2px;background:var(--card);box-shadow:var(--shadow);
    border-radius:999px;padding:2px 9px 2px 2px;font-size:12.5px;font-weight:700}
  .ck-cube-counts img{width:24px;height:24px}
  /* B5 cook mode is a mode (blueprint §5): no tab bar, so ‹ + CTA sit on the bottom edge
     and the timers stack above them. */
  .ck-navrow{position:fixed;left:16px;right:16px;bottom:calc(16px + env(safe-area-inset-bottom));z-index:29;
    max-width:488px;margin:0 auto;display:flex;gap:10px;align-items:center}
  .ck-navrow .ck-ghost{width:52px;min-height:52px;padding:0;flex:0 0 auto;border-radius:50%}
  .ck-tstack{position:fixed;left:16px;right:16px;bottom:calc(80px + env(safe-area-inset-bottom));z-index:29;
    max-width:488px;margin:0 auto;display:flex;flex-direction:column;gap:6px}
  .ck-tsr{position:relative;display:flex;align-items:center;gap:6px;width:100%;background:#fff;color:var(--ink);
    border:1.5px solid #CFE3D6;border-radius:999px;padding:0 16px;min-height:var(--tap);font:inherit;font-size:14px;
    white-space:nowrap;text-align:left;cursor:pointer}
  .ck-tsr svg{width:18px;height:18px;flex:none}
  .ck-tsr .ck-sp{min-width:0;overflow:hidden;text-overflow:ellipsis}
  .ck-tsr b{font-size:17px;font-variant-numeric:tabular-nums}
  .ck-tsr.ck-done{background:var(--accent);border-color:var(--accent);color:#fff;font-weight:700}
  .ck-numrow{display:flex;align-items:center;justify-content:center;gap:16px;margin:14px 0}
  .ck-numrow b{font-size:30px;font-weight:800;min-width:96px;text-align:center;font-variant-numeric:tabular-nums}
  .ck-numrow button{min-width:var(--tap);min-height:var(--tap);padding:0 14px;border-radius:999px;background:#fff;
    border:1.5px solid var(--line);font:inherit;font-size:16px;color:var(--ink);white-space:nowrap;cursor:pointer}
  /* ⑦: two columns of name + − N + tiles */
  .ck-cgrid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .ck-cg{background:var(--card);border-radius:14px;box-shadow:var(--shadow);padding:10px;text-align:center;min-width:0}
  .ck-cg b{display:block;font-size:13px;margin:0 0 6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* R8: ⑤ tool cards · ⑥ step · ⑦ 다 만들었어요 · E1 알림 */
  .ck-tsr.ck-done::after{pointer-events:none}
  .pp-th .ck-ic{width:40px;height:40px;margin:6px 0 4px;color:var(--accent);stroke-width:1.4}
  .ck-stic{width:50px;height:50px;border-radius:16px;background:#F3F1EA;color:var(--accent);display:grid;place-items:center;flex:none}
  .ck-stic .ck-ic{width:22px;height:22px}
  .ck-sthx{min-width:0}
  /* C24 step-1 chips (blueprint §5 1/9): a kept food is the soft green chip, a skipped one plain. */
  .ck-skip{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 10px}
  .ck-chip,.ck-skiph{min-height:var(--tap);max-width:100%;border:1.5px solid var(--line);border-radius:999px;padding:0 12px;
    background:transparent;color:var(--ink);font:inherit;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .ck-chip.ck-on{background:var(--accent-soft);border-color:var(--accent-soft);color:var(--accent);font-weight:700}
  .ck-chip:disabled{opacity:.55}
  .ck-skiph{display:inline-flex;align-items:center;color:var(--sub)}
  .ck-sthead .ck-sub{display:block;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .ck-pub{display:inline-block;font-size:12px;color:var(--sub);background:var(--bg);border-radius:999px;padding:0 7px;
    margin-left:2px;white-space:nowrap}
  .ck-keyb .ck-pub{background:rgba(255,255,255,.6);color:#6E3A20}
  .ck-made{text-align:center;margin:0 0 12px}
  .ck-made img{width:84px;height:84px;border-radius:50%;object-fit:cover;box-shadow:var(--shadow);display:block;margin:0 auto 6px}
  .ck-made .ck-sub{margin:4px 0 0}
  .ck-cst{display:flex;align-items:center;justify-content:space-between;background:var(--bg);border-radius:999px}
  .ck-cst button{width:var(--tap);min-height:var(--tap);border:0;background:transparent;font:inherit;font-size:17px;
    color:var(--sub);cursor:pointer}
  .ck-cst span{font-size:15px;font-weight:700;min-width:22px;text-align:center;font-variant-numeric:tabular-nums}
  .ck-navrow .ck-cta{flex:1;width:auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* cook mode keeps its own flat look (DU4 4): the design-up floor and surfaces stop here */
  body.ck-mode{--bg:#FFFFFF;--well:#F4F4F2;--line:#ECECEC;--shadow:none;--lift:none;--tile-shadow:none;background:var(--bg)}
  body.ck-mode .tbar{min-height:44px;margin-bottom:2px}
  body.ck-mode .tabs,body.ck-mode .stage-pill{display:none}
  .tbar-back .tbar-x,body.ck-mode .tbar-back svg:first-child{display:none}
  body.ck-mode .tbar-back .tbar-x{display:block;width:18px;height:18px}
  body.ck-mode .tbar-back:not([hidden]){width:36px;height:36px;margin:0 4px 0 0;background:#fff;box-shadow:var(--shadow)}
  body.ck-mode #page-title{font-size:17px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
    font-variant-numeric:tabular-nums}
  .tbar-snd:not([hidden]){display:inline-flex;align-items:center;gap:4px;flex:none;min-height:var(--tap);padding:0 12px;
    border:0;border-radius:999px;background:#fff;color:var(--accent);font:inherit;font-size:12px;font-weight:700;
    white-space:nowrap;cursor:pointer}
  .tbar-snd svg{width:16px;height:16px}
  .tbar-snd.off{color:var(--sub);text-decoration:line-through}
  .pp-empty .pp-ghost{margin-top:10px}

  /* 오늘 (structure v3 B2, blueprint §2 · §3): 지금 할 일 card, V1 rows, 부엌 · 관찰 lines, 끼니 상세 */
  .td-now{display:flex;align-items:center;gap:12px;width:100%;background:#fff;color:var(--ink);border:0;border-left:4px solid var(--accent);
    border-radius:20px;padding:14px 16px;margin:0 0 12px;box-shadow:0 2px 14px rgba(31,42,36,.06);font:inherit;text-align:left;cursor:pointer}
  .td-nic{width:44px;height:44px;border-radius:14px;background:#F3F1EA;color:var(--accent);display:flex;align-items:center;justify-content:center;flex:none}
  .td-nic svg,.td-lic svg{display:block}
  .td-now .td-tx{flex:1;min-width:0}
  .td-now small{display:block;font-size:12px;color:#7A8480;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .td-now b{display:block;font-size:18px;font-weight:800;letter-spacing:-0.015em;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .td-now em{display:block;font-style:normal;font-size:12px;color:#7A8480;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .td-go{flex:none;background:var(--accent);color:#fff;border-radius:999px;padding:8px 12px;font-weight:700;font-size:12px;white-space:nowrap}
  .td-now-q{border-left-color:#D9D4CA}
  .td-now-q .td-nic{color:var(--sub)}
  .td-now-q .td-go{background:#fff;color:var(--accent);border:1.5px solid var(--accent)}
  .td-now-warn{border-left-color:#C9A24A}
  .td-now-warn .td-nic{background:#FBF1D6;color:#7A5A0A}
  .td-now-warn .td-go{background:#C9A24A}
  .td-now-red{border-left-color:#C9705B}
  .td-now-red .td-nic{background:#F6E3DD;color:#A3321D}
  .td-now-red .td-go{background:#C9705B}
  .td-list{background:var(--card);border-radius:var(--r-lg);box-shadow:var(--shadow);padding:2px 14px;margin-bottom:12px}
  .td-m2{display:flex;align-items:center;gap:10px;width:100%;padding:10px 0;border:0;border-bottom:1px solid var(--line);background:none;
    font:inherit;color:inherit;text-align:left;cursor:pointer}
  .td-m2:last-child{border-bottom:0}
  .td-th{width:64px;height:64px;border-radius:8px;object-fit:cover;flex:none}
  .td-slot{width:64px;height:64px;border-radius:8px;flex:none;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:13px}
  .td-slot.s1{background:#F6EBCF;color:#7A5A0A}
  .td-slot.s2{background:#DDEFEA;color:#2F6B5C}
  .td-slot.s3{background:#E3E7F5;color:#3F4F8C}
  .td-slot.sn{background:#F8E3DA;color:#9A4A33}
  .td-m2 .td-tx{flex:1;min-width:0}
  .td-m2 .td-tx b{display:block;font-size:15px;font-weight:700;letter-spacing:-0.01em;line-height:1.7;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .td-m2 .td-tx em{display:block;font-style:normal;color:#7A8480;font-size:12px;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .td-m2 .td-tx em u{text-decoration:none;color:var(--accent);font-weight:700}
  .td-m2 .td-tx em i{font-style:normal;color:var(--accent);font-weight:700}
  .td-m2 .td-tx em s{text-decoration:none;color:#A3321D;font-weight:700}
  .td-tag{display:inline-block;margin-right:5px;padding:0 6px;font-size:12px;line-height:1.3;border-radius:999px;background:#fff;color:var(--accent);
    border:1.5px solid var(--accent);font-weight:650;vertical-align:middle;position:relative;top:-1px;white-space:nowrap}
  .td-chev{color:#B7B2A8;font-size:18px;flex:none}
  .td-line{display:flex;align-items:center;gap:10px;width:100%;background:#fff;border:0;border-radius:18px;padding:12px 14px;margin:0 0 10px;
    font:inherit;font-size:14px;font-weight:700;color:var(--ink);text-align:left;white-space:nowrap;box-shadow:0 2px 14px rgba(31,42,36,.06);cursor:pointer}
  .td-lic{width:34px;height:34px;border-radius:10px;background:#F3F1EA;color:var(--accent);display:flex;align-items:center;justify-content:center;flex:none}
  .td-ls{color:#7A8480;font-weight:450;font-size:12px;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0}
  .td-line-amber{border-left:4px solid #E3C97F}
  .td-line-amber .td-lic{background:#F6EBCF;color:#7A5A0A}
  .td-meal .td-mh{cursor:default;border-bottom:0;padding:0 0 6px}
  .td-meal .td-mh .td-tx b{font-size:18px}
  .td-mh .td-tx em u,.td-mh .td-tx em i{text-decoration:none;font-style:normal;color:var(--accent);font-weight:700}
  .td-tags{display:flex;gap:6px;flex-wrap:nowrap;overflow:hidden;margin-bottom:10px}
  .td-tags span{display:inline-flex;align-items:center;gap:2px;font-size:12px;background:#F3F1EA;padding:5px 9px;border-radius:999px;white-space:nowrap}
  .td-tags svg{width:16px;height:16px}
  .td-lbl{display:block;font-size:12px;font-weight:600;letter-spacing:.06em;color:#8A928E;margin:12px 0 6px}
  .td-ah2 .td-lbl{margin:0}
  .td-foot{font-size:12px;color:var(--sub);margin:6px 0 0}
  .td-foot-c{text-align:center;margin:0 0 12px}
  .td-foot-l{margin:8px 0 0}
  .td-meal .td-rec > summary em{font-style:normal;color:var(--accent);font-weight:500;font-size:13px;margin-left:auto;white-space:nowrap}
  .td-meal .td-rec > summary::after{margin-left:6px}
  .td-rec > summary .td-fc,.td-rec[open] > summary .td-fo,.td-rec[open] > summary em{display:none}
  .td-rec[open] > summary .td-fc{display:inline}
  .td-meal .td-rec[open] > summary::after{margin-left:auto}
  .td-ghost2{display:block;width:100%;background:#fff;color:var(--accent);border:1.5px solid var(--accent);border-radius:999px;padding:15px;margin:0 0 12px;
    font:inherit;font-weight:700;font-size:16px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer}
  .td-kv{display:flex;justify-content:space-between;align-items:center;gap:8px;font-size:14px;padding:10px 0;border-bottom:1px solid var(--line)}
  .td-kv > span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .td-kv b{font-weight:700;white-space:nowrap}
  .mt-pick{position:relative}
  .mt-pick select{position:absolute;inset:0;opacity:0;width:100%;cursor:pointer}
  #sh-memo{width:100%;font:inherit}
  .td-ah2 .td-lg{white-space:nowrap}
  .td-meal .td-amt button.td-on{background:var(--accent);border-color:var(--accent);color:#fff}
  .td-meal .td-amt button.td-on[data-amt="skip"]{background:#F6E3DD;border-color:#F6E3DD;color:#A3321D}
  .td-meal{background:var(--card);border-radius:var(--r-lg);box-shadow:var(--shadow);overflow:hidden;margin-bottom:10px}
  .td-meal .td-body{padding:12px 14px 14px}
  .td-pull2{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:10px}
  .td-pull2 span{display:inline-flex;align-items:center;gap:3px;background:var(--bg);border-radius:999px;padding:2px 10px 2px 3px;
    font-size:12px;font-weight:600}
  .td-pull2 img{width:24px;height:24px}
  .td-pull2 .td-tm2{margin-left:auto;background:var(--ink);color:#fff;padding:3px 10px}
  /* STACK #51 K4: 만드는 법 is one closed line under the record */
  .td-rec{margin-top:12px;border-top:1px solid var(--line)}
  .td-rec > summary{min-height:var(--tap);display:flex;align-items:center;font-size:14px;font-weight:700;
    cursor:pointer;list-style:none}
  .td-rec > summary::-webkit-details-marker{display:none}
  .td-rec > summary::after{content:"›";margin-left:auto;color:var(--sub);font-weight:400}
  .td-rec[open] > summary::after{transform:rotate(90deg)}
  .td-ah{font-size:12px;font-weight:700;color:var(--sub);margin:0 0 6px}
  .td-ah2{display:flex;align-items:center}
  .td-ah2 .td-lg{width:var(--tap);text-align:center;font-size:12px;font-weight:500;margin-left:6px}
  .td-amt{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-bottom:12px}
  .td-amt button{min-height:var(--tap);border-radius:999px;border:1px solid var(--line);display:flex;align-items:center;
    justify-content:center;gap:4px;font-family:inherit;font-size:13.5px;background:#fff;color:var(--ink);cursor:pointer}
  .td-amt button.td-on{background:var(--accent-soft);border-color:var(--accent-soft);font-weight:700}
  .td-amt svg{width:14px;height:14px}
  .td-pr2{display:flex;align-items:center;gap:8px;padding:5px 0}
  .td-pr2 img{width:34px;height:34px}
  .td-pr2 .td-sp{font-size:14px}
  .td-pb{width:var(--tap);min-height:var(--tap);margin-left:6px;border-radius:999px;border:1px solid var(--line);display:grid;
    place-items:center;color:#B8B2A6;font-weight:700;background:#fff;cursor:pointer}
  .td-pb svg{width:16px;height:16px}
  .td-pb.td-h.td-on{background:#F5E1DB;border-color:#F5E1DB;color:#B8614E}
  .td-pb.td-x.td-on{background:var(--ink);color:#fff;border-color:var(--ink)}
  .td-pb.td-w{color:#D9B8A6}
  .td-pb.td-w.td-on{background:var(--warn);color:#fff;border-color:var(--warn)}
  .kd-dv{width:var(--tap);height:var(--tap);border-radius:50%;border:1px solid var(--line);background:#fff;display:grid;
    place-items:center;font-family:inherit;font-size:20px;color:var(--sub);cursor:pointer}
  /* structure v3: the doors to the pages under a tab root - one row each, name then number */
  .wk-prep{display:flex;align-items:center;gap:8px;width:100%;min-height:var(--tap);padding:12px 14px;
    margin-bottom:8px;background:var(--card);border:0;border-radius:var(--r-md);box-shadow:var(--shadow);
    font-family:inherit;font-size:14px;color:var(--ink);text-align:left;cursor:pointer}
  .wk-prep span{flex:1;font-weight:700}
  .wk-prep svg{width:16px;height:16px;color:var(--sub)}
  .wk-prep{margin-top:14px}
  .wk-prep svg{fill:none;stroke:currentColor;stroke-width:2}
  .pp-to-shop{width:100%;margin:12px 0 0}
  .pp-cta.ck-go{margin:0 0 12px}
  .pp-cta.ck-go{flex-direction:column;gap:2px;min-height:62px;padding:8px 16px}
  .ck-go .ck-s{font-size:12px;font-weight:500;opacity:.88;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
  /* 부엌 (structure v3 B3): 만들 것 card, rows under group heads, freezer head */
  .mk-card{background:#fff;border-radius:var(--r-lg);padding:14px 16px;margin-bottom:12px;box-shadow:var(--shadow)}
  .mk-h{display:flex;justify-content:space-between;align-items:baseline;gap:10px;margin-bottom:10px;white-space:nowrap}
  .mk-h b{font-size:16px}
  .mk-h span{font-size:12px;color:var(--sub)}
  .mk-grp{font-size:12px;font-weight:600;letter-spacing:.06em;color:#8A928E;padding:10px 0 2px}
  .mk-row{display:flex;align-items:center;gap:10px;padding:9px 0;border-bottom:1px solid var(--line);font-size:14px}
  .mk-n{min-width:0;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .mk-n small{display:block;color:var(--sub);font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .mk-pill{margin-left:auto;flex:none;border-radius:999px;padding:8px 13px;font-size:13px;font-weight:700;white-space:nowrap;
    background:var(--accent);border:1.5px solid var(--accent);color:#fff;font-family:inherit;cursor:pointer}
  .mk-pill.mk-done{background:#fff;border-color:#BFE0CC;color:var(--accent);cursor:default}
  .mk-line{display:flex;align-items:center;gap:10px;border:1.5px solid #BFE0CC;border-radius:18px;padding:12px 14px;
    margin:0 0 8px;font-size:14px;white-space:nowrap}
  .mk-line span{color:var(--sub);font-size:12px;overflow:hidden;text-overflow:ellipsis}
  .mk-line .ck-ic{width:20px;height:20px;flex:none;color:var(--accent)}
  .mk-red{background:var(--warn-soft);border-radius:12px;padding:9px 10px;border-bottom:0;margin:4px 0;color:var(--warn)}
  .mk-red > svg{width:20px;height:20px;flex:none}
  .mk-red .mk-n small{color:var(--warn)}
  .mk-pill.mk-drop{background:#fff;border-color:#E7C4B8;color:var(--warn)}
  .mk-pill.mk-out{background:#fff;border-color:var(--line);color:var(--sub)}
  .mk-foot{font-size:12px;color:var(--sub);text-align:center;margin:6px 0 0}
  .mk-link{width:100%;justify-content:center;font-weight:700;color:var(--accent)}
  .pp-cta.ck-go.ck-tone{background:#fff;color:var(--accent);border:1.5px solid var(--accent);box-shadow:none}
  .ck-drop{text-decoration:underline;text-underline-offset:2px}
  .td-shs.td-warn{color:var(--warn);font-weight:700}
  .td-cta.fz-red{background:var(--warn)}
  .td-cta:disabled{background:var(--line);color:#fff;box-shadow:none;cursor:default}
  .mk-opt{padding:10px 0;border-bottom:1px solid var(--line);font-size:14px;line-height:1.45}
  .mk-opt:last-child{border-bottom:0}
  .mk-opt small{display:block;color:var(--sub);font-size:12px}
  .td-rhead,.kd-rhead{display:flex;align-items:center;gap:12px}
  .td-rhead img,.kd-rhead img{width:52px;height:52px}
  .td-new{color:#9A7A1C}
  .td-pub{display:inline-block;font-size:12px;color:#6E3A20;background:rgba(255,255,255,.6);border-radius:999px;padding:0 7px;margin-left:2px;white-space:nowrap}
  .td-fixtoast{position:fixed;left:16px;right:16px;bottom:calc(98px + env(safe-area-inset-bottom));z-index:30;display:flex;align-items:center;gap:8px}
  .td-undo{border:0;background:transparent;font:inherit;font-weight:700;color:#BFE0CC;min-height:var(--tap);padding:0 4px;margin:-11px 0;cursor:pointer}
  .td-rsyms{margin-top:14px}
  .td-rfoot{text-align:center;margin:10px 0 0}

  /* 오늘: ⑪ 냉동실 */

  /* 아이: ⑬ 기록 */
  .kd-watch{display:flex;align-items:center;gap:12px;background:#FBF3DC;border-radius:var(--r-lg);padding:12px 14px;margin-bottom:12px}
  .kd-watch img{width:54px;height:54px}
  .kd-watch b{font-size:16px;display:block}
  .kd-watch span{font-size:12.5px;color:#7A6320}
  .kd-cal{padding:12px 10px}
  .kd-calh{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}
  .kd-calh b{font-size:15px;font-weight:800;letter-spacing:-.02em;white-space:nowrap}
  .kd-calh .kd-sub{font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .kd-wkh{display:grid;grid-template-columns:repeat(7,1fr);text-align:center;font-size:12px;color:var(--sub);margin-bottom:4px}
  .kd-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:3px}
  .kd-cd{min-height:var(--tap);border:0;border-radius:10px;background:var(--bg);display:flex;flex-direction:column;
    align-items:center;padding:3px 0 0;font-family:inherit;color:var(--ink);cursor:pointer}
  .kd-cd .kd-dn{font-size:13px;font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}
  .kd-cd.kd-today{box-shadow:inset 0 0 0 2px var(--accent)}
  .kd-cd.kd-fut{background:#FAF8F4}
  .kd-cd.kd-fut .kd-dn{color:#CCC;font-weight:500}
  .kd-cd.kd-blank{background:transparent}
  .kd-cd.kd-sel{background:var(--accent);box-shadow:none}
  .kd-cd.kd-sel .kd-dn{color:#fff}
  /* blueprint §8 dots: green meal · yellow first food · red reaction · grey shopping · blue cooking */
  .kd-dts{display:flex;gap:2px;height:6px;margin-top:3px;font-style:normal}
  .kd-dt{display:inline-block;width:5px;height:5px;border-radius:50%;background:var(--accent)}
  .kd-dt.kd-dy{background:#E3C97F}
  .kd-dt.kd-dr{background:var(--warn)}
  .kd-dt.kd-ds{background:#B7B2A8}
  .kd-dt.kd-dc{background:#7C8FCB}
  .kd-cd.kd-sel .kd-dt{background:#fff}
  .kd-leg{display:flex;gap:8px;align-items:center;justify-content:center;margin-top:8px;font-size:12px;color:var(--sub);white-space:nowrap}
  .kd-leg[hidden]{display:none}
  .kd-leg span{display:inline-flex;align-items:center;gap:3px}
  .kd-fold{display:block;width:100%;min-height:var(--tap);margin:0 0 -10px;border:0;background:transparent;cursor:pointer}
  .kd-fold::after{content:"";display:block;width:36px;height:4px;border-radius:2px;background:#D9D4CA;margin:0 auto}
  .kd-dayp{background:var(--card);border-radius:var(--r-lg);box-shadow:var(--shadow);padding:10px 14px;margin-bottom:10px}
  .kd-dph{display:flex;align-items:center;margin-bottom:6px}
  .kd-dph b{font-size:15px}
  .kd-dpr{display:flex;align-items:center;gap:8px;padding:5px 0;border-top:1px solid var(--line)}
  .kd-dk{font-size:12px;font-weight:700;color:var(--sub);width:30px;flex:0 0 auto}
  .kd-dpi{display:flex;gap:2px}
  .kd-dpi img,.kd-dpr img{width:32px;height:32px}
  .kd-dpr.kd-rx b{font-size:13.5px;color:#6E3A20}
  .kd-mstat{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
  .kd-mstat > button{background:var(--card);border:0;border-radius:var(--r-md);box-shadow:inset 0 0 0 1.5px var(--accent-soft),var(--shadow);
    padding:10px;text-align:center;font-family:inherit;color:var(--ink);cursor:pointer}
  .kd-mstat b{display:block;font-size:22px;letter-spacing:-.5px;font-variant-numeric:tabular-nums}
  .kd-mstat b small{font-size:12px}
  .kd-mstat span{font-size:12px;color:var(--sub)}
  .kd-mstat em{display:block;font-style:normal;font-size:12px;color:var(--sub);margin-top:2px}
  /* 아이 · 기록 (R11): the day row opens ⑨ on a day of this week; a date tap fades
     only the panel under the calendar (mockup 13: 150ms), the squares keep their nodes. */
  .kd-mstat b.kd-warn,.kd-shn.kd-warn{color:var(--warn)}
  .kd-cd:disabled{cursor:default}
  .kd-dv:disabled{opacity:.3;cursor:default}
  .kd-dph.kd-open{width:100%;min-height:var(--tap);border:0;background:transparent;padding:0;gap:6px;
    font-family:inherit;color:inherit;text-align:left;cursor:pointer}
  .kd-dph .kd-ic{width:16px;height:16px;color:#B8B2A6}
  .kd-dpi{flex:0 0 auto}
  .kd-dpn{min-width:0;font-size:13px;font-weight:600;word-break:keep-all}
  .kd-none{margin:0 0 4px}
  .kd-watch > b{flex:1;min-width:0}
  /* STACK #51 K3: one row per food under observation, each with 반응 기록 */
  .kd-watch.kd-wl{flex-direction:column;align-items:stretch;gap:0;padding:10px 14px}
  .kd-wh{display:flex;align-items:center;gap:8px;padding:2px 0 6px}
  .kd-wh b{font-size:15px}
  .kd-wr{display:flex;align-items:center;gap:10px;padding:8px 0;border-top:1px solid rgba(122,99,32,.15)}
  .kd-wr img{width:34px;height:34px}
  .kd-wr b{font-size:15px}
  .kd-wr .kd-sp span{display:block}

  /* 아이: ⑬-a · b · c 숫자 창 */
  .kd-shh{display:flex;align-items:center;gap:8px}
  .kd-shn{font-size:22px}
  .kd-frg{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;margin-top:12px}
  .kd-frr{background:var(--bg);border-radius:14px;padding:6px 4px;text-align:center}
  .kd-frr img{width:40px;height:40px}
  .kd-frr b{display:block;font-size:12px}
  .kd-frr span{font-size:12px;color:var(--sub)}
  .kd-cum{display:flex;align-items:center;gap:8px;margin-top:8px;font-size:12.5px;color:var(--sub)}
  .kd-cum b{color:var(--ink)}
  .kd-cum > i{flex:1;height:5px;border-radius:3px;background:var(--line);position:relative;display:block}
  .kd-cum > i > i{position:absolute;left:0;top:0;bottom:0;border-radius:3px;background:var(--accent);display:block}
  .kd-nextup{display:flex;align-items:center;gap:8px;margin-top:12px;padding-top:10px;border-top:1px solid var(--line)}
  .kd-nextup img{width:30px;height:30px}
  .kd-mlr{display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:1px solid var(--line)}
  .kd-mlr img{width:48px;height:48px;border-radius:12px;object-fit:cover}
  .kd-mlr b{display:block;font-size:14px}
  .kd-mst{font-size:12px;font-weight:700;border-radius:999px;padding:4px 10px}
  .kd-mst.kd-no{background:var(--ink);color:#fff}
  .kd-mst.kd-half{background:var(--accent-soft);color:#24553C}
  .kd-rxc{background:var(--warn-soft);border-radius:var(--r-md);padding:12px;margin-top:12px}
  .kd-rxh{display:flex;align-items:center;gap:10px}
  .kd-rxh img{width:44px;height:44px}
  .kd-rxh b{display:block;font-size:16px}
  .kd-rxs{display:flex;align-items:center;gap:8px;margin:10px 0}
  .kd-rxo{font-size:12.5px;font-weight:700;color:#6E3A20}
  .kd-rxa{display:flex;align-items:center}
  .kd-frm{margin:14px 0 0}
  .kd-frg.kd-old{opacity:.7;margin-top:6px}
  button.kd-mlr{width:100%;border:0;border-bottom:1px solid var(--line);background:transparent;
    font-family:inherit;color:inherit;text-align:left;cursor:pointer}
  .kd-mlr .kd-sub,.kd-rxh .kd-sub{display:block}
  .kd-nextup{flex-wrap:wrap}

  /* 아이: ⑬-1 설정 and its sheets */
  .kd-set{background:var(--card);border-radius:var(--r-lg);box-shadow:var(--shadow);padding:2px 14px;margin-bottom:10px}
  .kd-sr{display:flex;align-items:center;gap:8px;min-height:var(--tap);padding:12px 0;border-bottom:1px solid var(--line);font-size:14px}
  .kd-sr:last-child{border-bottom:0}
  .kd-sr .kd-sk{font-weight:700}
  .kd-sr .kd-sv{margin-left:auto;color:var(--sub);font-size:13px}
  .kd-sr svg{width:16px;height:16px;color:#B8B2A6}
  .kd-sr.kd-col{flex-direction:column;align-items:stretch}
  .kd-srh{display:flex;align-items:center}
  .kd-outs{display:grid;gap:6px;margin-top:8px}
  .kd-out{display:flex;align-items:center;gap:8px;background:var(--bg);border-radius:14px;padding:6px 10px;font-size:13.5px}
  .kd-out img{width:30px;height:30px}
  .kd-out i{font-style:normal;font-size:12px;border-radius:999px;padding:1px 7px;background:#fff;color:var(--sub)}
  .kd-out.kd-w i{background:var(--warn);color:#fff}
  .kd-out b{margin-left:auto;font-size:12.5px;color:var(--accent)}
  .kd-st-date{display:flex;gap:8px;justify-content:center;margin:14px 0 6px}
  .kd-st-date div{background:var(--bg);border-radius:14px;padding:10px 16px;font-size:24px;font-weight:700}
  .kd-st-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
  .kd-st-ing{background:var(--bg);border:0;border-radius:14px;padding:5px 2px 6px;text-align:center;font-family:inherit;
    font-size:12px;color:var(--ink);cursor:pointer}
  .kd-st-ing img{width:40px;height:40px;display:block;margin:0 auto}
  .kd-st-ing.kd-on{background:var(--warn-soft);color:#6E3A20;font-weight:700;box-shadow:inset 0 0 0 1.5px #E6BFA9}
  .kd-st-ck{display:flex;align-items:flex-start;gap:10px;font-size:13.5px;line-height:1.45;margin:4px 0 14px}
  .kd-st-in{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .kd-st-f{background:var(--bg);border-radius:14px;padding:8px 12px}
  .kd-st-f span{font-size:12px;color:var(--sub);display:block}
  .kd-st-f b{font-size:18px}
  .kd-st-f b small{font-size:12px;color:var(--sub);font-weight:600}
  .kd-st-pick{display:flex;align-items:center;gap:12px;width:100%;border:1.5px solid var(--line);border-radius:var(--r-md);
    background:transparent;padding:12px 14px;margin-top:8px;font-family:inherit;color:var(--ink);text-align:left;cursor:pointer}
  .kd-st-pick b{display:block;font-size:15px}
  .kd-st-pick span{font-size:12px;color:var(--sub)}
  .kd-st-pick.kd-on{border-color:var(--accent);background:var(--accent-soft)}
  .kd-st-rd{width:20px;height:20px;border-radius:50%;border:2px solid #CFC9BE;flex:0 0 auto}
  .kd-st-pick.kd-on .kd-st-rd{border:6px solid var(--accent);background:#fff}
  .kd-st-def{font-size:12px;font-weight:700;color:#24553C;background:#fff;border-radius:999px;padding:2px 8px}

  /* 처음 시작 (② 아기 정보; ① is #intro) */
  .ob-intro{display:flex;flex-direction:column;align-items:center;gap:18px;padding-top:70px}
  .ob-intro img{width:170px;height:170px;border-radius:50%;object-fit:cover;box-shadow:var(--shadow)}
  .ob-mark{font-size:16px;font-weight:700;color:var(--accent);letter-spacing:.5px}
  .ob-field{background:var(--card);border-radius:var(--r-md);box-shadow:var(--shadow);padding:12px 14px;margin-bottom:10px}
  .ob-field .ob-k{font-size:12px;color:var(--sub);font-weight:600;margin-bottom:8px}
  .ob-field .ob-v{font-size:19px;font-weight:700;display:flex;align-items:center;gap:8px}
  .ob-foot{position:fixed;left:16px;right:16px;bottom:calc(18px + env(safe-area-inset-bottom));max-width:488px;margin:0 auto}
  .ob-chk{display:flex;align-items:center;gap:10px;min-height:var(--tap);padding:13px 0;border-bottom:1px solid var(--line);
    font-size:14.5px;line-height:1.4}
  .ob-chk:last-child{border-bottom:0}
  .ob-when{display:flex;flex-direction:column;align-items:center;background:var(--card);border-radius:var(--r-md);
    box-shadow:var(--shadow);padding:12px 26px;margin-top:14px}
  .ob-when b{font-size:30px;margin:0;letter-spacing:-.8px}
  .ob-when span{font-size:12px}
  /* ---- 아이 · 설정 list (R6, mockup 13-1 13-7 13-11) -------------------------
     Once the tab bar is up the list replaces the onboarding form and its
     notice line; before that (body.shell-off) the form is the whole page and the
     list is not drawn. The first .notice stays the one e2e reads on the first screen. */
  body:not(.shell-off) #profile-card,
  body:not(.shell-off) .pg[data-pg="baby"] > .notice,body:not(.shell-off) #go{display:none}
  body.shell-off #kd-settings{display:none}
  .kd-set{background:var(--card);border-radius:var(--r-lg);box-shadow:var(--shadow);padding:0 16px;margin-bottom:12px}
  .kd-sr{display:flex;align-items:center;gap:8px;width:100%;min-height:52px;padding:0;border:0;
    border-bottom:1px solid var(--line);background:transparent;font-family:inherit;font-size:15px;color:var(--ink);
    text-align:left;cursor:pointer}
  .kd-set > .kd-sr:last-child,.kd-set > .kd-col:last-child{border-bottom:0}
  .kd-sk{flex:0 0 auto;font-weight:600}
  .kd-sv{flex:1;min-width:0;text-align:right;color:var(--sub);font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .kd-sr > .kd-ic{width:16px;height:16px;color:#B8B2A6}
  .kd-col{display:block;cursor:default;padding:4px 0 12px}
  .kd-srh{display:flex;align-items:center;gap:8px;min-height:44px}
  .kd-add{width:var(--tap);height:var(--tap);border:0;border-radius:50%;background:transparent;color:var(--accent);
    display:grid;place-items:center;margin-right:-12px;cursor:pointer}
  .kd-add .kd-ic{width:20px;height:20px}
  .kd-outs{display:flex;flex-direction:column;gap:8px}
  .kd-out{display:flex;align-items:center;gap:8px;min-height:var(--tap);padding:0 4px 0 14px;border-radius:14px;
    background:var(--bg);font-size:15px;font-weight:600}
  .kd-out .kd-why{font-size:12px;font-weight:600;color:var(--sub);flex:1}
  .kd-out.kd-w{background:var(--warn-soft)}
  .kd-out.kd-w .kd-why{color:var(--warn)}
  .kd-undo{min-height:var(--tap);padding:0 12px;border:1px solid var(--line);border-radius:999px;background:var(--card);
    font-family:inherit;font-size:12.5px;font-weight:600;color:var(--ink);cursor:pointer}
  #kd-settings .kd-notice{margin-top:14px}
  .kd-def{font-size:12px;font-weight:700;color:#24553C;background:var(--card);border-radius:999px;padding:3px 9px}
  #kd-birth .kd-cta{margin-top:14px}
  #kd-restore .kd-cta{margin-top:4px}
  .kd-date{width:100%;min-height:52px;font-size:17px;text-align:center}
  .kd-age{text-align:center;margin:10px 0 0;min-height:26px}
  #kd-data-archive{margin-top:6px}
  .kd-set > .kd-sr:has(+ .kd-dline){border-bottom:0}
  .kd-dline{margin:-6px 0 0;padding:0 0 12px;font-size:12px;color:var(--sub)}

  /* ---- 아이 · 기록 and 설정 sheets (structure v3 round C-2, blueprint §8 §9) ---------

  /* 아이 · observation banner: head row with the leaf icon, the chips below */
  #kd-watch .kd-watch.kd-wl{background:#fff;border-left:4px solid #E3C97F;padding:10px 14px;gap:8px}
  #kd-watch .kd-wh{display:flex;align-items:center;gap:8px;min-width:0}
  #kd-watch .kd-wh b{display:flex;align-items:center;gap:6px;font-size:14px;white-space:nowrap}
  #kd-watch .kd-wh .kd-sub{font-size:12px;color:#7A5A0A;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .kd-lic{width:20px;height:20px;flex:none;vertical-align:-.22em}

  /* 아이 · day detail rows: key left, value right, the reaction row in the reaction colour */
  .kd-dayp .kd-dph .kd-sub{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
  .kd-dayp .kd-dpr{justify-content:space-between;min-height:40px}
  .kd-dayp .kd-dpr .kd-dk{display:flex;align-items:center;gap:6px;flex:none;width:auto;white-space:nowrap}
  .kd-dayp .kd-dpr .kd-dpn{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:right}
  .kd-dayp .kd-dpr.kd-rx .kd-dpn{color:var(--warn);text-align:left}

  /* 아이 · number tiles: value over label, no arrow; 반응 0 is grey */
  .kd-mstat > button span{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .kd-mstat > button.kd-zero b{color:#B8B2A6}

  /* 관찰 전체 sheet rows */
  .kd-obr{display:flex;align-items:center;gap:10px;min-height:52px;border-bottom:1px solid var(--line)}
  .kd-obr b{display:block;font-size:15px}
  .kd-obr .kd-sub{display:block;font-size:12.5px}

  /* 처음 먹은 재료 sheet chips (name + date, ⚠ on a reacted food) */
  .kd-fcs{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0}
  .kd-fc{display:inline-flex;align-items:center;gap:4px;min-height:32px;padding:0 10px;border-radius:999px;background:var(--bg);font-size:13px;font-weight:700;white-space:nowrap}
  .kd-fc i{font-style:normal;font-weight:500;font-size:12px;color:var(--sub)}
  .kd-fc em{font-style:normal;color:var(--warn)}
  .kd-fcs.kd-old .kd-fc{opacity:.6}
  .kd-nextup{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:12px}

  /* 다 먹음 sheet rows (day · slot, items, state, ›) */
  .kd-mlr{display:flex;align-items:center;gap:10px;width:100%;min-height:52px;padding:6px 0;border:0;border-bottom:1px solid var(--line);background:none;font:inherit;text-align:left}
  .kd-mlr .kd-sp{min-width:0}
  .kd-mlr .kd-sp b{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .kd-mlr > .kd-ic{width:16px;height:16px;color:#B8B2A6;flex:none}

  /* 반응 전체 cards: name + symptom pill, date line, 취소 · 다시 넣기 */
  .kd-rxc .kd-rxh{display:flex;align-items:center;gap:8px}
  .kd-rxc .kd-rxh b{font-size:15px}
  .kd-rxc .kd-rxl{margin-top:6px}
  .kd-rxc .kd-rxa{display:flex;gap:8px;justify-content:flex-end;margin-top:8px}
  .kd-rxf{margin-top:12px}

  /* 설정 · list rows (value column ellipsis at 60 %, §7.5) */
  #kd-settings .kd-sv{max-width:60%}

  /* 생년월일 sheet: three number fields */
  .kd-ymd{display:grid;grid-template-columns:1.4fr 1fr 1fr;gap:8px;margin-bottom:12px}
  .kd-ymdf{display:flex;align-items:baseline;justify-content:center;gap:4px;min-height:56px;border:1px solid var(--line);border-radius:14px;padding:0 10px;background:#fff}
  .kd-ymdf:focus-within{border-color:var(--accent)}
  .kd-ymdf input{width:100%;min-width:0;border:0;background:none;font:inherit;font-size:22px;font-weight:800;text-align:right;font-variant-numeric:tabular-nums;padding:0;outline:none}
  .kd-ymdf small{font-size:13px;color:var(--sub)}
  .kd-kv{display:flex;justify-content:space-between;align-items:center;padding:10px 0;border-bottom:1px solid var(--line);font-size:14px}
  .kd-bad{color:var(--warn);font-size:13px;margin:8px 0 0}
  .kd-cta.kd-cta2{flex-direction:column;gap:0;margin-top:12px}
  .kd-cta2 .kd-cs{font-size:12px;font-weight:500;opacity:.85}
  .kd-cta:disabled{background:#D9D4CA;color:#fff;box-shadow:none}

  /* 내 데이터: the privacy policy fold */
  .dt-policy summary{list-style:none;font-size:14px;font-weight:700;cursor:pointer}
  .dt-policy summary em{font-style:normal;font-weight:400;font-size:13px;color:var(--sub);margin-left:6px}
  .dt-policy summary::after{content:" ›"}

  /* wipe confirm: the red fill (the shared button rule paints it green) */
  #sh .btn-red{background:var(--warn);color:#fff}

  /* 반응 기록 (C09): the 언제 row is a button drawn as a kv row; the 언제 view's seven days share one row */
  .sh-when{width:100%;background:none;border:0;border-bottom:1px solid var(--line);font:inherit;color:inherit;text-align:left;cursor:pointer}
  .sh-week{margin-top:10px;flex-wrap:nowrap}
  .sh-week .sh-chip{flex:1;min-width:0;padding:0;justify-content:center}
  .sh-chip:disabled{opacity:.4;cursor:default}

  /* ---- Motion system (R9, 2026-09-27) ----------------------------------------
     M1-M12 of the approved loop mockup (section 모션). Only transform, scale and
     opacity travel; a colour moves only where a state changes colour. The global
     prefers-reduced-motion rule near the top turns every one of these off. Most
     of the app is painted by innerHTML, so a motion that must play ONCE is keyed
     on a class the script adds at that moment (work\loop_apply\R9\js_patch.md):
     keyed on the markup alone it would replay on every repaint. */
  @keyframes mo-fade-in{from{opacity:0}}
  @keyframes mo-fade-out{to{opacity:0}}
  /* A page that grows past the window grows a desktop scrollbar, and the centred
     column then jumps 7.5px sideways in one frame (measured at 1180, #47). Phones
     draw overlay scrollbars, so this reserves nothing there. */
  html{scrollbar-gutter:stable}

  /* M1 press: 96% while held, spring back on release. `scale` is its own
     property, so it never fights a transform a control already carries. */
  :where(button,[role="button"],.chip,a.pill,a.cfm-one,a.st-go,summary){
    transition:scale 180ms var(--mo-spring)}
  :where(button,[role="button"],.chip,a.pill,a.cfm-one,a.st-go,summary):active:not(:disabled){
    scale:.96;transition-duration:90ms;transition-timing-function:var(--mo-out)}

  /* M2 selection pill: one ::before per control slides to the lit button.
     The index comes from :has(), so without :has() the lit buttons keep their
     own backgrounds (the rules above) and nothing slides. */
  @supports selector(:has(*)) {
    .pp-dayrail,.td-amt{position:relative;isolation:isolate;
      --mo-pad:4px;--mo-gap:0px;--mo-n:1;--mo-k:0}
    .pp-dayrail::before,.td-amt::before{content:"";
      position:absolute;z-index:0;top:var(--mo-pad);bottom:var(--mo-pad);left:var(--mo-pad);
      width:calc((100% - 2 * var(--mo-pad) - (var(--mo-n) - 1) * var(--mo-gap)) / var(--mo-n));
      border-radius:999px;background:var(--accent-soft);pointer-events:none;
      transform:translateX(calc(var(--mo-k) * (100% + var(--mo-gap))));transition:transform 240ms var(--mo-out)}
    .pp-dayrail > button,.td-amt > button{position:relative;
      z-index:1;transition:scale 180ms var(--mo-spring),color 160ms var(--mo-out)}
    .td-amt{--mo-pad:0px;--mo-gap:6px;--mo-n:3}
    .pp-dayrail::before,.td-amt::before{opacity:0}
    .pp-dayrail:has(> .pp-on)::before,.td-amt:has(> .td-on)::before{opacity:1}
    .pp-dayrail:has(> :nth-child(2).pp-on),.td-amt:has(> :nth-child(2).td-on){--mo-k:1}
    .pp-dayrail:has(> :nth-child(3).pp-on),.td-amt:has(> :nth-child(3).td-on){--mo-k:2}
    .pp-dayrail button.pp-on,.td-amt button,.td-amt button.td-on{background:transparent}
  }

  /* M3 ♡ ✕ ⚠: ♡ pops with six dots (box-shadows of one pseudo, so reduced
     motion - no animation - leaves them at opacity 0), ✕ fills, ⚠ opens M4. */
  @keyframes mo-pop{45%{transform:scale(1.3)}}
  @keyframes mo-burst{from{opacity:1;transform:scale(.4)}to{opacity:0;transform:scale(1.2)}}
  .td-pb{position:relative;transition:scale 180ms var(--mo-spring),background-color 160ms var(--mo-out),
    color 160ms var(--mo-out),border-color 160ms var(--mo-out)}
  .td-pb.td-h.td-on svg{animation:mo-pop 300ms var(--mo-spring)}
  .td-pb.td-h::after{content:"";position:absolute;left:50%;top:50%;width:5px;height:5px;margin:-2.5px;
    border-radius:50%;opacity:0;pointer-events:none;box-shadow:0 -16px #E27A76,14px -8px #E27A76,
    14px 8px #E27A76,0 16px #E27A76,-14px 8px #E27A76,-14px -8px #E27A76}
  .td-pb.td-h.td-on::after{animation:mo-burst 420ms var(--mo-out)}

  /* M4 bottom sheets (blueprint 1.4, F2 2026-10-02): up and down in .38s on
     --ease-sheet, no overshoot; the scrim fades .25s. Full-screen panels keep
     sheet-in above. */
  @keyframes mo-sheet-up{from{transform:translateY(105%)}}
  @keyframes mo-sheet-down{to{transform:translateY(105%)}}
  .sh.opening,.pnl-card.pnl-sheet.opening{animation:mo-sheet-up .38s var(--ease-sheet)}
  .sh.closing,.pnl-card.pnl-sheet.closing{animation:mo-sheet-down .38s var(--ease-sheet) forwards}
  .sh-scrim:not([hidden]),.pnl-scrim:not([hidden]){animation:mo-fade-in .25s var(--mo-out)}
  .sh-scrim:has(+ .sh.closing){animation:mo-fade-out .25s var(--mo-in) forwards}
  .sh-scrim:has(+ .sh.closing.late){animation-delay:150ms}

  /* M5 timer done: white to green 400ms on the same node, one ring. [data-mo-still]
     (rows repainted already done) is a script mark; it is an attribute so the row's
     class stays "ck-tsr ck-done". */
  @keyframes mo-ring{from{opacity:.7;transform:none}to{opacity:0;transform:scale(1.06,1.5)}}
  @keyframes mo-pop-in{from{opacity:0;transform:scale(.6)}}
  .ck-tsr{transition:background-color 400ms var(--mo-out)}
  .ck-tsr.ck-done::after{content:"";position:absolute;inset:0;border-radius:inherit;
    box-shadow:0 0 0 3px var(--accent);opacity:0;animation:mo-ring 700ms var(--mo-out)}
  .ck-tsr[data-mo-still],.ck-tsr[data-mo-still]::after{animation:none}

  /* M6 step change: the new step comes in 24px from the right, blocks 30ms
     apart; the lit progress bar fills over its grey track; a timer just started
     drops in while its space opens over 220ms. The stack is bottom-anchored, so a
     row that claimed its height at once would push every row above it up in one
     frame; the -6px margin cancels the flex gap until the row has height. */
  @keyframes mo-step-in{from{opacity:0;transform:translateX(24px)}}
  @keyframes mo-bar{from{background-size:0 100%}}
  @keyframes mo-drop{from{opacity:0;transform:translateY(34px) scale(.92)}}
  @keyframes mo-row-open{from{min-height:0;max-height:0;margin-top:-6px}to{max-height:var(--tap)}}
  #ck-step > .ck-sthead,#ck-step > .ck-skip,#ck-step > .ck-procs,#ck-step > .ck-keyb{animation:mo-step-in 260ms var(--mo-out) backwards}
  #ck-step > .ck-procs{animation-delay:30ms}
  #ck-step > .ck-keyb{animation-delay:60ms}
  .ck-prog i.ck-on:not(:has(+ .ck-on)){background:var(--line) linear-gradient(var(--accent),var(--accent)) no-repeat 0 0/100% 100%;
    animation:mo-bar 300ms var(--mo-out)}
  .ck-tsr.mo-new{animation:mo-drop 280ms var(--mo-out),mo-row-open var(--mo-t2) var(--mo-out)}

  /* M8 담기: the button's word crossfades when shop.js swaps it; after the chain
     (.mo-chain from the script) the 담음 rows tick one after another, 60ms apart. */
  @keyframes mo-xfade{from{opacity:var(--mo-x0,.35)}}
  @keyframes mo-check{from{opacity:0;transform:scale(.4)}}
  .cfm-go.busy > .mo-word,.cfm-go.done > .mo-word{animation:mo-xfade 150ms var(--mo-out)}
  /* goWord fading the old word out and swapping after it (#47 shop_patch): the new
     word then rises from 0. Both classes come only from that patch. */
  .cfm-go > .mo-word.mo-word-in{--mo-x0:0}
  .cfm-go > .mo-word.mo-out{animation:mo-fade-out 150ms var(--mo-in) forwards}
  .mo-chain .pp-had .pp-cb svg{animation:mo-check 200ms var(--mo-spring) backwards;
    animation-delay:calc(var(--mo-i,0) * 60ms)}
  .mo-chain .pp-had .pp-got{animation:mo-fade-in 200ms var(--mo-out) backwards;
    animation-delay:calc(var(--mo-i,0) * 60ms + 60ms)}

  /* M10 toast: up 200ms, out 160ms (.mo-bye), and on an undo toast (.mo-life,
     --mo-life = its lifetime) a line shrinking to nothing. .mo-in is the same
     entrance for an inline block the script shows once. */
  @keyframes mo-rise-in{from{opacity:0;transform:translateY(16px)}}
  @keyframes mo-sink-out{to{opacity:0;transform:translateY(8px)}}
  @keyframes mo-shrink{to{transform:scaleX(0)}}
  .toast,.mo-in{animation:mo-rise-in 200ms var(--mo-out)}
  /* the ③ undo line sits above the day chips and meal rows: its space opens over
     220ms so they slide down instead of dropping 80px in one frame */
  @keyframes mo-open-toast{from{max-height:0;padding-top:0;padding-bottom:0;margin-bottom:0}to{max-height:80px}}
  .pp-toast.mo-in{overflow:hidden;animation:mo-rise-in 200ms var(--mo-out),mo-open-toast var(--mo-t2) var(--mo-out)}
  .mo-bye{animation:mo-sink-out 160ms var(--mo-in) forwards}
  .mo-life{position:relative;overflow:hidden}
  .mo-life::after{content:"";position:absolute;left:0;right:0;bottom:0;height:3px;background:#BFE0CC;
    transform-origin:left;pointer-events:none;animation:mo-shrink var(--mo-life,4s) linear forwards}

  /* M11 다 만들었어요, once (.mo-play from the script): the bowl bounces, the cube
     tiles rise 30ms apart after it. */
  @keyframes mo-bounce{35%{transform:translateY(-12px) scale(1.04)}65%{transform:scale(.97)}}
  @keyframes mo-rise{from{opacity:0;transform:translateY(10px) scale(.85)}}
  .ck-made.mo-play{animation:mo-fade-in 200ms var(--mo-out)}
  .ck-made.mo-play img{animation:mo-bounce 500ms var(--mo-out)}
  .ck-made.mo-play + .ck-cgrid > .ck-cg{animation:mo-rise 260ms var(--mo-out) backwards;
    animation-delay:calc(var(--mo-i,0) * 30ms + 200ms)}
  .ck-cgrid > :nth-child(2),.pp-had:nth-child(2 of .pp-had){--mo-i:1}
  .ck-cgrid > :nth-child(3),.pp-had:nth-child(3 of .pp-had){--mo-i:2}
  .ck-cgrid > :nth-child(4),.pp-had:nth-child(4 of .pp-had){--mo-i:3}
  .ck-cgrid > :nth-child(5),.pp-had:nth-child(5 of .pp-had){--mo-i:4}
  .ck-cgrid > :nth-child(6),.pp-had:nth-child(6 of .pp-had){--mo-i:5}
  .ck-cgrid > :nth-child(7),.pp-had:nth-child(7 of .pp-had){--mo-i:6}
  .ck-cgrid > :nth-child(8),.pp-had:nth-child(8 of .pp-had){--mo-i:7}
  .ck-cgrid > :nth-child(9),.pp-had:nth-child(9 of .pp-had){--mo-i:8}
  .ck-cgrid > :nth-child(10),.pp-had:nth-child(10 of .pp-had){--mo-i:9}
  .ck-cgrid > :nth-child(n+11),.pp-had:nth-child(n+11 of .pp-had){--mo-i:10}

  /* M12 tabs: the page fades in 220ms on --mo-in (a slow first frame cannot skip it) - a tab is a
     place, so nothing slides sideways. Opacity only: .pg holds fixed bars. */
  .pg:not([hidden]){animation:mo-fade-in 220ms var(--mo-in)}
  /* the leaving page fades out before the swap (.mo-leave from showPage, #47 shell_patch) */
  .pg.mo-leave:not([hidden]){animation:mo-fade-out 150ms var(--mo-in) forwards}

  /* ---- Motion round #48 / #49 (2026-09-28) -----------------------------------
     M13-M23 and the ④ cell colours. Every rule is keyed on a class or markup the
     script adds (contract: work\motion_round_20260927\A48css\CLASSES.md), so none
     of it shows until a JS lane puts it there. A ghost is an id-less, inert clone
     of what was on screen, laid over the new state while it fades; the reduced
     motion block at the end hides every ghost, so no end state waits on one. */
  @keyframes mo-ghost-out{to{opacity:0;translate:calc(var(--mo-gx,0px) * var(--mo-shift)) 0}}
  .mo-ghost{position:absolute;margin:0;z-index:1;pointer-events:none;
    animation:mo-ghost-out var(--mo-d,140ms) var(--mo-in) forwards;animation-delay:calc(var(--mo-i,0) * 60ms)}
  :is(.mo-ghost,.mo-page-ghost,.mo-day-ghost) *,:is(.mo-ghost,.mo-page-ghost,.mo-day-ghost) *::before,
  :is(.mo-ghost,.mo-page-ghost,.mo-day-ghost) *::after{animation:none !important;transition:none !important}
  .mo-ghost button{visibility:hidden}
  :is(#ck-step,#pp-plan .wk-row):has(> .mo-ghost){position:relative}

  /* M6 이전: the step comes in from the left, and the bar does not refill */
  @keyframes mo-step-back{from{opacity:0;transform:translateX(-24px)}}
  #ck-step.mo-back > .ck-sthead,#ck-step.mo-back > .ck-skip,#ck-step.mo-back > .ck-procs,#ck-step.mo-back > .ck-keyb{animation-name:mo-step-back}
  .ck-prog.mo-back i.ck-on:not(:has(+ .ck-on)){animation:none}
  /* a step painted by a push (M14) is still: the page itself is moving */
  #ck-step.mo-still > *,.ck-prog.mo-still i.ck-on:not(:has(+ .ck-on)){animation:none}

  /* M13 meal swipe: one row of 240px cards that follows the finger (--mo-dx) and
     rests on card --mo-i. --mo-near (0 side, 1 centred) sets a card's scale and
     opacity; .mo-c holds 1 at rest, the script writes it per card mid-drag. */
  .pp-carousel.mo-track{display:block;overflow:hidden;touch-action:pan-y;user-select:none;-webkit-user-select:none}
  .mo-track > .mo-track-row{display:flex;align-items:center;gap:8px;padding:0 calc(50% - 120px);
    translate:calc(var(--mo-i,0) * -248px + var(--mo-dx,0px)) 0}
  .mo-track-row > .pp-cc{--mo-near:0;flex:0 0 240px;width:240px;height:auto;background:var(--bg);
    opacity:calc(.5 + .5 * var(--mo-near));scale:calc(.82 + .18 * var(--mo-near))}
  .mo-track-row > .pp-cc.mo-c{--mo-near:1}
  .mo-track-row > .pp-cc:active:not(:disabled){scale:calc(.82 + .18 * var(--mo-near))}
  .mo-track-row img{width:240px;height:160px;object-fit:cover;display:block;pointer-events:none;-webkit-user-drag:none}
  .mo-track.mo-settle > .mo-track-row{transition:translate var(--mo-t3) var(--mo-spring)}
  .mo-track.mo-settle .pp-cc{transition:scale var(--mo-t3) var(--mo-spring),opacity var(--mo-t3) var(--mo-out)}
  .pp-cdots.mo-dots i{transition:width var(--mo-t3) var(--mo-spring),background-color var(--mo-t2) var(--mo-out)}

  /* M14 push / pop: the new page comes 24px from the side with a fade. It moves by
     its margins, not a transform - a transform would re-anchor the page's fixed bars.
     The old page is a fixed-layer ghost; its own fixed bars ride with it. */
  @keyframes mo-page-in{from{opacity:0;margin-left:calc(24px * var(--mo-shift));margin-right:calc(-24px * var(--mo-shift))}}
  @keyframes mo-page-back{from{opacity:0;margin-left:calc(-24px * var(--mo-shift));margin-right:calc(24px * var(--mo-shift))}}
  @keyframes mo-page-out{to{opacity:0;translate:calc(-24px * var(--mo-shift)) 0}}
  @keyframes mo-page-out-back{to{opacity:0;translate:calc(24px * var(--mo-shift)) 0}}
  /* body clips the 24px, so the page never overflows the viewport (a phone would widen
     its layout viewport and every fixed bar would jump); html must not be visible, or
     body's overflow would pass to the viewport instead */
  html:has(.pg.mo-push-in:not([hidden]),.pg.mo-pop-in:not([hidden])),
  html:has(.pg.mo-push-in:not([hidden]),.pg.mo-pop-in:not([hidden])) > body{overflow-x:clip}
  .pg.mo-push-in:not([hidden]){animation:mo-page-in var(--mo-t3) var(--mo-out)}
  .pg.mo-pop-in:not([hidden]){animation:mo-page-back var(--mo-t2) var(--mo-in)}
  .mo-page-ghost{position:fixed;inset:0;z-index:29;overflow:hidden;pointer-events:none;will-change:transform,opacity}
  .mo-page-ghost > *{position:absolute;left:var(--mo-x,0px);top:var(--mo-y,0px);width:var(--mo-w,100%);margin:0}
  .mo-page-ghost.mo-push-out{animation:mo-page-out var(--mo-t3) var(--mo-out) forwards}
  .mo-page-ghost.mo-pop-out{animation:mo-page-out-back var(--mo-t2) var(--mo-in) forwards}

  /* M15 have-check, V6: a checked row stays whole at 0.55 with its price struck (the
     count and total drop); .mo-fold keeps the grid the unchecked row is drawn in.
     .mo-had / .mo-unhad are the moment of the tick. The total rolls once: the new
     figure is the element's own text, the old one its ::before one line up, and the
     clip-path follows the roll so only the box's own line ever shows. */
  @keyframes mo-dim-in{from{opacity:1}}
  @keyframes mo-dim-out{from{opacity:.55}}
  @keyframes mo-check-fill{from{background-color:var(--card);border-color:var(--box)}}
  @keyframes mo-draw{from{clip-path:inset(0 100% 0 0)}}
  .mo-fold{display:grid;grid-template-rows:1fr}
  .mo-fold > *{min-height:0;overflow:hidden}
  .cart-item.pick.got:has(.mo-fold){opacity:.55}
  .cart-item.got.mo-had{animation:mo-dim-in var(--mo-t2) var(--mo-out)}
  .cart-item.got.mo-had .mo-fold > *{animation:mo-dim-in var(--mo-t2) var(--mo-in)}
  .cart-item.got.mo-had .tick .bx{animation:mo-check-fill var(--mo-t1) var(--mo-out)}
  .cart-item.got.mo-had .tick .bx svg{animation:mo-draw var(--mo-t1) var(--mo-out)}
  .cart-item.mo-unhad:not(.got){animation:mo-dim-out var(--mo-t2) var(--mo-out)}
  .cart-item.mo-unhad:not(.got) .mo-fold > *{animation:mo-fade-in var(--mo-t2) var(--mo-out)}
  @keyframes mo-roll-a{from{translate:0 calc(100% * var(--mo-shift));clip-path:inset(-100% 0 100% 0)}}
  @keyframes mo-roll-old{from{opacity:1}to{opacity:0}}
  .mo-roll-a{position:relative;display:inline-block;vertical-align:bottom;clip-path:inset(0);
    animation:mo-roll-a 200ms var(--mo-out)}
  .mo-roll-a::before{content:attr(data-mo-old);position:absolute;left:0;right:0;bottom:100%;text-align:inherit;white-space:nowrap;opacity:0;
    animation:mo-roll-old 200ms var(--mo-out)}
  /* the money digits keep one 999,999-wide box, so 원 never steps when the digit count changes */
  .st-v .won-roll{display:inline-block;font-variant-numeric:tabular-nums;min-width:7ch;text-align:right}
  .kd-badge > .mo-roll-a{vertical-align:baseline}

  /* M17 date step: the days sit on one strip - the new day's blocks come a page
     (their width + 12px) from the pressed side while a ghost of the old day leaves
     the other way. The host clips (clip, not hidden, so the sticky ring bar holds).
     The label keeps a centred box of its own and cross-fades; arrows fade at a limit. */
  @keyframes mo-day-in-next{from{translate:calc((100% + 12px) * var(--mo-shift)) 0}}
  @keyframes mo-day-in-prev{from{translate:calc((-100% - 12px) * var(--mo-shift)) 0}}
  @keyframes mo-day-out-next{to{translate:calc((-100% - 12px) * var(--mo-shift)) 0}}
  @keyframes mo-day-out-prev{to{translate:calc((100% + 12px) * var(--mo-shift)) 0}}
  .mo-day-clip{position:relative;overflow-x:clip}
  .mo-day-next{animation:mo-day-in-next var(--mo-t3) var(--mo-out)}
  .mo-day-prev{animation:mo-day-in-prev var(--mo-t3) var(--mo-out)}
  .mo-day-ghost{position:absolute;margin:0;pointer-events:none}
  .mo-day-ghost.mo-day-next{animation:mo-day-out-next var(--mo-t3) var(--mo-out) forwards}
  .mo-day-ghost.mo-day-prev{animation:mo-day-out-prev var(--mo-t3) var(--mo-out) forwards}

  /* M19 lock: the icon drops 3px with a pop, the row's ring goes to ink in 160ms
     (an unlock runs it back). Both ends are written as two-layer lists (a transparent
     ring) so the shadow interpolates instead of flipping. Regenerate: .mo-regen
     rows (--mo-i = order, 60ms apart) fade their photo and name in over a ghost of
     the old row, then 새로 pops. */
  @keyframes mo-shackle{from{translate:0 calc(-3px * var(--mo-shift));scale:1.2}}
  @keyframes mo-ink-on{from{box-shadow:inset 0 0 0 2px transparent,var(--shadow)}}
  @keyframes mo-ink-off{from{box-shadow:inset 0 0 0 2px var(--ink),var(--shadow)}to{box-shadow:inset 0 0 0 2px transparent,var(--shadow)}}
  @keyframes mo-lockb-on{from{scale:.6}}
  @keyframes mo-lockb-off{from{background-color:var(--ink);color:#fff}to{background-color:var(--ink);color:#fff;scale:.3}}
  :is(.pp-mrow,.td-mrow).mo-lock :is(.pp-lockb.pp-on,.td-lockb.td-on){animation:mo-lockb-on var(--mo-t2) var(--mo-spring)}
  :is(.pp-mrow,.td-mrow).mo-lock :is(.pp-lockb.pp-on,.td-lockb.td-on) svg{animation:mo-shackle var(--mo-t2) var(--mo-spring)}
  :is(.pp-mrow,.td-mrow).mo-lock :is(.pp-lockb:not(.pp-on),.td-lockb:not(.td-on)){animation:mo-lockb-off 160ms var(--mo-in)}
  :is(#pp-plan .wk-row,.td-mrow).mo-ghost{inset:0;background:transparent;box-shadow:none}
  #pp-plan .wk-row.mo-regen > .wk-open{animation:mo-fade-in 140ms var(--mo-out) backwards;
    animation-delay:calc(var(--mo-i,0) * 60ms)}


  @media (prefers-reduced-motion:reduce) {
    :where(button,[role="button"],.chip,a.pill,a.cfm-one,a.st-go,summary):active:not(:disabled){scale:none}
    .mo-life::after{display:none}
    .mo-ghost,.mo-page-ghost,.mo-day-ghost,.mo-roll-a::before{display:none}
  }

  /* ---- Shared parts (renewal F2, 2026-10-02) ----------------------------------
     Tokens and u- parts every rebuilt screen stands on: blueprint 1.1-1.9
     (work\today_tab_20261001\index.html), values and names from
     work\renewal_20261002\CONTRACT_shell.md 7. Screens add their own rules in
     app\css\<screen>.css and never redefine a token here. The button reset and
     keep-all are scoped (C9) so screens not rebuilt yet keep their look. */
  :root {
    --faint:#9E9E9E; --accent-2:#11634A; --amber:#9A6A14; --amber-soft:#FBF1D9;
    --g-grain:var(--carb); --g-prot:var(--prot); --g-veg:var(--fat); --g-fruit:var(--peach);
    --rx-ring:#E0645A; --rx-num:#C0392B; --rx-sel:#FFB4AC;
    --memo:#FFF3C4; --memo-ink:#7A5A12; --heart:#E27A76;
    --fr-body:#DDEEE4; --fr-door:#EEF7F1; --fr-back:#E3F0E8; --fr-in:#FBFCF8; --fr-cold:#E7F1F7; --fr-bowl:#F3B9A0;
    --tog-off:#D3D3D3; --danger:#B04A3E; --danger-line:#E5B4AC;
    --fs-s:12px; --fs-m:12.5px; --fs-base:13.5px; --fs-body:14.5px; --fs-lead:16px;
    --fs-title:18px; --fs-h2:22px; --fs-h1:24px; --ls-title:-.3px;
    --r-sheet:26px; --ease-sheet:cubic-bezier(.2,.9,.25,1); --scrim:rgba(20,20,20,.45);
    --sheet-shadow:0 -8px 30px rgba(20,20,20,.18);
    --gutter:14px; --tabbar-h:48px;
  }
  :where(.u-screen,.u-sheet,#tbar,#tabs) button,:where(.u-screen,.u-sheet) input{font:inherit;color:inherit;
    -webkit-tap-highlight-color:transparent}
  .u-screen,.u-sheet,#tbar,#tabs{word-break:keep-all;overflow-wrap:break-word}
  .u-nw{white-space:nowrap}
  .u-1l{display:block;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .u-2l{display:-webkit-box;min-width:0;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
  .u-fix{flex:none}
  .u-num{font-variant-numeric:tabular-nums}
  /* 44px hit around a control drawn smaller (✕ ‹ −/+ switches); the drawing keeps its size. */
  .u-hit{position:relative}
  .u-hit::before{content:"";position:absolute;left:50%;top:50%;width:max(100%,44px);height:max(100%,44px);
    transform:translate(-50%,-50%)}

  /* header (blueprint 1.1): title 22/800, the date beside 오늘, one thing on the right */
  #page-title{flex:0 1 auto;min-width:0;font-size:var(--fs-h2);font-weight:700;letter-spacing:var(--ls-title)}
  .tbar-date{flex:none;font-size:var(--fs-base);font-weight:500;color:var(--sub);margin-top:6px}
  #stage-badge,#tbar-snd{margin-left:auto}
  /* 오늘 at 320: the title never wraps; a long stage pill drops under it instead */
  .tbar[data-pg="today"]{flex-wrap:wrap}
  .tbar[data-pg="today"] #page-title{flex:none;white-space:nowrap}
  .stage-pill[hidden]{display:none}
  /* the stage and the gear are white surfaces on the floor (DU1) */
  .stage-pill.u-pill{height:30px;padding:0 12px;background:var(--card);color:var(--sub);font-weight:600;box-shadow:var(--ring),var(--shadow-s)}
  #tbar-set:not([hidden]){display:inline-flex;align-items:center;width:auto;height:auto;min-height:var(--tap);
    margin:0 0 0 auto;padding:0 2px;border-radius:999px;background:var(--card);box-shadow:var(--ring),var(--shadow-s);
    font-size:var(--fs-base);font-weight:700;color:var(--accent-2);
    white-space:nowrap}

  .u-card{background:var(--card);border-radius:var(--r);box-shadow:var(--shadow);padding:14px;margin-bottom:12px}
  .u-status{display:flex;align-items:center;gap:12px;background:var(--card);border-radius:var(--r);box-shadow:var(--shadow);
    padding:14px;margin-bottom:12px;border-left:4px solid var(--accent)}
  .u-status.u-warn{border-left-color:var(--warn)}
  .u-status.u-next{border-left-color:var(--box)}
  .u-status-ic{flex:none;display:grid;place-items:center;width:36px;height:36px;border-radius:50%;
    background:var(--well);color:var(--accent)}
  .u-warn .u-status-ic{background:var(--warn-soft);color:var(--warn)}
  .u-status-tx{flex:1;min-width:0}
  .u-status-k{display:block;font-size:var(--fs-s);font-weight:600;color:var(--sub)}
  .u-status-l{display:block;font-size:var(--fs-lead);font-weight:800;letter-spacing:var(--ls-title);line-height:1.35}
  .u-status-s{display:block;font-size:var(--fs-s);color:var(--sub);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .u-status-go{flex:none;display:inline-flex;align-items:center;min-height:var(--tap);padding:0 14px;border:0;
    border-radius:999px;background:var(--accent);color:#fff;font-size:var(--fs-m);font-weight:800;white-space:nowrap;cursor:pointer}
  .u-warn .u-status-go{background:var(--warn)}
  .u-next .u-status-go{background:var(--card);color:var(--accent);border:1.5px solid var(--accent)}
  .u-cta,.u-ghost{display:flex;align-items:center;justify-content:center;width:100%;min-height:48px;padding:15px 0;
    border-radius:999px;font-size:var(--fs-body);font-weight:700;line-height:1.2;text-align:center;cursor:pointer}
  .u-cta{border:0;background:var(--accent);color:#fff}
  .u-cta:disabled{background:var(--line);color:var(--sub);cursor:default}
  .u-ghost{border:1.5px solid var(--accent);background:var(--card);color:var(--accent)}
  .u-ghost.u-danger{border-color:var(--danger-line);color:var(--danger)}
  .u-link{display:inline-flex;align-items:center;min-height:var(--tap);padding:0 4px;border:0;background:none;
    color:var(--sub);font-size:var(--fs-m);font-weight:700;text-decoration:underline;text-underline-offset:3px;cursor:pointer}
  .u-tog-row{display:flex;align-items:center;gap:12px;width:100%;min-height:var(--tap);cursor:pointer}
  .u-tog{position:relative;flex:none;width:44px;height:26px;padding:0;border:0;border-radius:999px;
    background:var(--tog-off);cursor:pointer;transition:background-color .2s var(--mo-out)}
  .u-tog::after{content:"";position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:50%;background:#fff;
    box-shadow:0 1px 3px rgba(20,20,20,.2);transition:transform .2s var(--mo-out)}
  .u-tog[aria-checked="true"]{background:var(--accent)}
  .u-tog[aria-checked="true"]::after{transform:translateX(18px)}
  .u-pill{display:inline-flex;align-items:center;flex:none;padding:5px 10px;border-radius:999px;background:var(--accent-soft);
    color:var(--accent-2);font-size:var(--fs-s);font-weight:700;line-height:1.4;white-space:nowrap}
  .u-pill[hidden]{display:none}
  .u-tile{flex:none;width:50px;height:50px;border-radius:12px;object-fit:cover;background:var(--well)}
  .u-tile.u-name{display:grid;place-items:center;padding:4px;background:var(--g,var(--well));color:var(--ink);
    font-size:var(--fs-s);font-weight:700;line-height:1.2;text-align:center;word-break:keep-all;overflow:hidden}
  .u-bowl{display:block;object-fit:contain;mix-blend-mode:multiply}
  @keyframes u-pop{40%{transform:scale(1.15)}70%{transform:scale(.97)}}
  .u-pop{animation:u-pop .4s var(--mo-out)}
  .u-cube{position:relative;display:inline-block;flex:none;width:20px;height:20px;border-radius:6px;
    background:var(--g,var(--g-grain));box-shadow:inset 0 -3px 0 rgba(20,20,20,.14)}
  .u-cube::after{content:"";position:absolute;top:3px;left:3px;width:30%;height:22%;border-radius:2px;
    background:rgba(255,255,255,.7)}
  .u-cube.u-s{width:16px;height:16px;border-radius:4px}
  .u-cube.u-xs{width:11px;height:11px;border-radius:3px;box-shadow:inset 0 -2px 0 rgba(20,20,20,.14)}
  .u-cube.u-move{background:transparent;border:1.5px dashed var(--g,var(--sub));box-shadow:none}
  .u-cube.u-move::after{display:none}

  /* sheets (blueprint 1.4): #sh and every .pnl-card.u-sheet */
  .u-scrim{background:var(--scrim)}
  #sh.u-sheet,.pnl-card.u-sheet{max-height:92%;overflow-y:auto;background:var(--card);
    border-radius:var(--r-sheet) var(--r-sheet) 0 0;box-shadow:var(--sheet-shadow)}
  /* #sh's head (title + close; the grip above it is not part of this rule, see U20
     RESULT.md) is not a dedicated element (shell.js openSheet builds it from .sh-grip
     and .sh-head inline) - a long receipt pushes it off the top of the scrolling sheet
     and leaves the only close (the X) unreachable without scrolling back up (U20).
     .pnl-card.u-sheet panels are a separate family, not reached by this #sh-scoped rule
     - not measured here, see U20 RESULT.md. top:-10px, not 0: #sh's own padding-top
     (.sh, 10px) sits ABOVE position:sticky's padding-edge anchor, so top:0 left a 10px
     strip at the sheet's true visual top where the scrolled body still showed through
     (measured in a real screenshot, not just computed rects) - top:-10px pulls the
     stuck position up to flush with #sh's actual edge. */
  #sh .sh-head{position:sticky;top:-10px;z-index:1;padding-top:8px;background:var(--card)}
  .u-grip{position:relative;width:40px;height:4px;margin:0 auto 10px;border-radius:999px;background:var(--line);
    touch-action:none;cursor:grab}
  .u-grip::before{content:"";position:absolute;left:-40px;right:-40px;top:-12px;bottom:-12px}
  .u-sheet .pnl-head,.u-sheet .sh-head{display:flex;align-items:center;gap:8px;margin-bottom:12px}
  .u-sheet .u-sheet-t{flex:1;min-width:0;margin:0;padding:0;font-size:var(--fs-title);font-weight:700;
    letter-spacing:var(--ls-title);line-height:1.3;text-align:left}
  .u-sheet-t:focus{outline:none}
  .u-x{flex:none;display:grid;place-items:center;width:32px;height:32px;min-height:0;padding:0;border:0;
    border-radius:50%;background:var(--well);color:var(--ink);cursor:pointer}
  .u-x svg{width:14px;height:14px}

  /* toast (blueprint 1.4): ink, white 13.5, radius 16, 76px over the tab bar, the white undo pill */
  @keyframes u-rise{from{opacity:0;transform:translateY(20px)}}
  .u-toast{justify-content:space-between;gap:12px;animation:u-rise .25s var(--mo-out)}
  .u-toast.mo-bye{animation:mo-sink-out 160ms var(--mo-in) forwards}
  .u-toast-t{flex:1;min-width:0}
  .u-undo{flex:none;min-height:32px;padding:0 12px;border:0;border-radius:999px;background:#fff;color:var(--ink);
    font:inherit;font-size:var(--fs-m);font-weight:800;white-space:nowrap;cursor:pointer}

  /* reduced motion (blueprint 1.8): sheets and toasts fade only; the global rule above
     stops everything else, the switch knob and the bowl pop included */
  @media (prefers-reduced-motion:reduce) {
    :is(#sh,.pnl-card).u-sheet.opening{animation:mo-fade-in .25s var(--mo-out)}
    :is(#sh,.pnl-card).u-sheet.closing{animation:mo-fade-out .25s var(--mo-in) forwards}
    .u-toast{animation:mo-fade-in .25s var(--mo-out)}
    .u-toast.mo-bye{animation:mo-fade-out 160ms var(--mo-in) forwards}
  }

  /* tab switch D: shared axis X, the entering half (margins, not a transform - fixed bars) */
  html:has(.pg.mo-tab-r:not([hidden]),.pg.mo-tab-l:not([hidden])),
  html:has(.pg.mo-tab-r:not([hidden]),.pg.mo-tab-l:not([hidden])) > body{overflow-x:clip}
  .pg.mo-tab-r:not([hidden]){animation:mo-page-in 160ms var(--mo-out)}
  .pg.mo-tab-l:not([hidden]){animation:mo-page-back 160ms var(--mo-out)}

  /* 오류 신고 (#345, work\report_button_20261014\variant1.html as measured there; DECISIONS B3-B4; #348 character-free
     restyle to nochar\variant2.html, DECISIONS B11-B12): floating above the tab bar on 오늘 and 식단 at the dock tier
     (29), so every scrim and sheet covers it. The page pads so its last row scrolls clear. 말풍선 아이콘 필: the bubble
     icon takes --ink, the label's own colour, not --accent (B12, "이모티콘 색이 너무 초록이야"). Measured at 320/360/390
     (nochar\built_walk.js): the pill keeps its icon and label down to 320 px, no narrow-width fallback needed. */
  .rb-fab{position:fixed;z-index:29;right:max(var(--gutter),calc(50vw - 260px + var(--gutter)));
    bottom:calc(var(--tabbar-h) + 14px + env(safe-area-inset-bottom));display:inline-flex;align-items:center;
    justify-content:center;gap:6px;min-width:var(--tap);min-height:var(--tap);margin:0;padding:0;border:0;
    background:none;color:var(--ink);font:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}
  .pg[data-pg="today"]:has(> .rb-fab),.pg[data-pg="menu"]:has(> .rb-fab){padding-bottom:56px}
  .rb-n2{height:44px;padding:0 17px 0 14px;border-radius:var(--r-cta);background:var(--card);box-shadow:var(--lift);
    font-size:var(--fs-base);font-weight:700;letter-spacing:var(--ls-title)}
  .rb-n2 svg{width:19px;height:19px;flex:none}
  .rb-n2 .rb-say-line{fill:none;stroke:currentColor;stroke-width:1.6;stroke-linejoin:round}
  .rb-n2 .rb-say-mark{stroke:currentColor;stroke-width:1.8;stroke-linecap:round}
  .rb-n2 .rb-say-dot{fill:currentColor}
  /* its sheet: a chat composer (input + 보내기); once sent, the message as a bubble and 보냈어요 under it */
  .rb-chat{display:flex;flex-direction:column;gap:12px}
  .rb-log{display:flex;flex-direction:column;align-items:flex-end;gap:6px}
  .rb-log:empty{display:none}
  .rb-chat .rb-bubble{max-width:85%;margin:0;padding:10px 14px;border-radius:18px 18px 4px 18px;background:var(--accent);
    color:#fff;font-size:var(--fs-body);line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere}
  .rb-chat .rb-sent{margin:0;font-size:var(--fs-s);font-weight:600;color:var(--sub)}
  .rb-compose{display:flex;align-items:flex-end;gap:8px}
  .rb-chat .rb-input{flex:1;width:auto;min-width:0;height:var(--tap);min-height:var(--tap);max-height:140px;margin:0;
    padding:9px 16px;box-sizing:border-box;border:1.5px solid var(--line);border-radius:22px;background:var(--well);
    font:inherit;font-size:16px;line-height:1.4;color:var(--ink);resize:none;overflow-y:auto}
  .rb-chat .rb-input:focus{outline:none;border-color:var(--accent);background:var(--card)}
  .rb-chat .rb-send{flex:none;min-width:var(--tap);min-height:var(--tap);padding:0 18px;border:0;border-radius:var(--r-cta);
    background:var(--accent);color:#fff;font:inherit;font-size:var(--fs-base);font-weight:700;cursor:pointer}
  .rb-chat .rb-send:disabled{background:var(--well);color:var(--faint);cursor:default}
  .rb-chat .rb-fail{margin:0}
