/* The shopper run's own styles (docs/game-design/build-spec.md). Here: the portion dial (step 3 of the build), step 4's deal card, the call,
   the goal strip, the Challenges block and the lines a shopper run adds to cards that exist, and step 5's Sunday card and My bests. Loaded
   after css/home.css, so a rule here can adjust the plate card. Everything is ink on white, or the violet of the neutral bars: no tick, no
   red, no green. */

/* ---------------- the portion dial (js/doors.js dialHTML) ----------------
   Shopper runs only, on the plate card while a door is open: "Portion", three buttons (Small, Medium, Large), then the plate's kcal.
   The card is ink, so the dial is the readout's own tones on it: the muted label, a hairline pill for each size, and the violet of the
   readings' bars for the size that is on. Nothing here is a verdict: no tick, no good or bad colour. */
.dp-por { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px; min-width: 0; }
.dp-por-l { font: 700 11px var(--f-mono); text-transform: uppercase; letter-spacing: 0.06em; color: #B0B5E2; white-space: nowrap; }
.dp-por-set { display: inline-flex; gap: 4px; }
.dp-por-b { position: relative; border: 1px solid rgba(255,255,255,0.28); border-radius: 999px; background: rgba(255,255,255,0.07); color: #fff; font: 700 12.5px/1.45 var(--f-body); padding: 2px 12px; white-space: nowrap; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.dp-por-b::before { content: ""; position: absolute; inset: -10px -2px; }   /* the tap target is taller than the pill (about 44px): nothing else to press sits in the rows above and below it */
.dp-por-b.on { background: #A9B1F5; border-color: #A9B1F5; color: var(--ink); cursor: default; }
.dp-por-b:disabled { opacity: 0.6; cursor: default; }
@media (hover: hover) { .dp-por-b:not(.on):not(:disabled):hover { border-color: #fff; background: rgba(255,255,255,0.14); } }
.dp-por-k { font-size: 12.5px; color: #C9CCF0; white-space: nowrap; }
@media (forced-colors: active) { .dp-por-b { border-color: ButtonText; } .dp-por-b.on { background: Highlight; color: HighlightText; border-color: Highlight; forced-color-adjust: none; } }
/* a desktop or a tablet: the dial and the plate it sizes share one row (the dial, then the chips), so the card is no taller than it is without
   the dial and the doors keep their height */
@media (min-width: 761px) and (min-height: 521px) {
  .d-plate.has-dial .dp-main { grid-template-columns: auto minmax(0, 1fr); column-gap: 14px; }
  .d-plate.has-dial .dp-main > * { grid-column: 1 / -1; }
  .d-plate.has-dial .dp-main > .dp-por { grid-column: 1; align-self: start; }
  .d-plate.has-dial .dp-main > .dp-chips { grid-column: 2; align-self: start; }
}
/* a phone: the door's blurb gives its row to the dial (the blurb is still the door's tooltip, and a typical plate keeps "· typical" beside its name) */
@media (max-width: 760px) {
  .d-plate.has-dial .dp-sub { display: none; }
  .dp-por { gap: 3px 8px; }
  .dp-por-l { font-size: 10.5px; }
  .dp-por-b { font-size: 12px; padding: 2px 11px; }
  .dp-por-k { font-size: 11.5px; }
}
/* a phone on its side: the card is a narrow column beside the hall, so the dial takes the phone's sizes; under about 830 px wide the three
   buttons and the kcal need the whole row, and the word "Portion" steps aside (the group keeps that name for a screen reader) */
@media (orientation: landscape) and (max-height: 520px) {
  .dp-por { gap: 3px 8px; }
  .dp-por-l { font-size: 10.5px; }
  .dp-por-b { font-size: 12px; padding: 1px 11px; }
  .dp-por-k { font-size: 11.5px; }
}
@media (orientation: landscape) and (max-height: 520px) and (max-width: 830px), (max-width: 345px) { .dp-por-l { display: none; } }

/* ---------------- a shopper run's cards ---------------- */
.m-day.run-eyebrow { color: var(--ink-3); }   /* the line over a card's head is the brand red elsewhere; a shopper run's is ink */
.dl-small { margin: 10px 0 0; font-size: 11.5px; line-height: 1.35; color: var(--muted); }

/* ---------------- the Challenges panel (js/campaign.js openMenu): the shopper block, then the four cards under their own heading ---------------- */
.run-new { background: var(--card); border: 1px solid var(--line); border-radius: 14px; padding: 12px 14px 14px; margin: 12px 0 18px; }
.run-new h3, .run-old-h { margin: 0 0 8px; font: 15px var(--f-display); letter-spacing: 0.02em; text-wrap: balance; }
.run-old-h { margin-bottom: 4px; }
.run-new-opts { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 10px 18px; }
.run-new-opts > div { display: grid; gap: 5px; justify-items: start; align-content: start; min-width: 0; font-size: 13px; line-height: 1.3; color: var(--ink-3); }   /* a button, and its one line under it */
.run-new-opts .btn { min-width: 128px; }
/* the one question before a ranked run is left: it takes the place of the button that was pressed */
.run-ask { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; background: #EEF0FA; border: 1px solid #C5CAE9; border-radius: 10px; padding: 8px 10px; font-size: 13px; line-height: 1.35; color: var(--ink); }
.run-ask > span { flex: 1 1 100%; }   /* the question on its own line, the two answers under it */
.run-new-opts .run-ask { justify-self: stretch; }

/* ---------------- the deal card (js/campaign.js openDeal): a .morning card ---------------- */
.deal .m-head { margin-bottom: 8px; }
.dl-lede { margin: 2px 0 0; font-size: 14.5px; }
.dl-who { display: flex; align-items: center; gap: 12px; background: var(--paper); border-radius: 12px; padding: 8px 12px; margin-bottom: 10px; }
.dl-who .buddy-md { width: 88px; height: 88px; }
.deal .dl-who h2 { margin: 0 0 2px; }
.dl-facts { margin: 0; font-size: 13.5px; text-wrap: pretty; }
.dl-made { margin: 3px 0 0; font-size: 12.5px; color: var(--muted); }
.dl-week { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; margin-bottom: 10px; font-size: 13px; }
.dl-l { font-weight: 700; }
.dl-days { flex: 0 1 auto; min-width: 0; max-width: 100%; display: grid; grid-template-columns: repeat(7, minmax(0, 40px)); gap: 4px; }   /* seven cells that give way together on a narrow phone */
.dl-day { display: grid; justify-items: center; gap: 1px; min-width: 0; padding: 3px 0 4px; border: 1px solid var(--line); border-radius: 8px; background: #fff; cursor: default; }
.dl-day i { font: 600 9.5px var(--f-mono); letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }
.dl-day b { font-size: 20px; line-height: 1.2; font-weight: 400; }
.dl-band { margin: 0 0 10px; font-size: 14px; text-wrap: pretty; }
.dl-band b { font-family: var(--f-mono); }
.dl-rule { margin: 0 0 6px; font-size: 13px; line-height: 1.4; color: var(--ink-3); text-wrap: pretty; }
/* ---- the call: a large number between a minus and a plus, what it pays beside it, and a slider under it ---- */
.dl-call { border: 1.5px solid var(--ink); border-radius: 12px; padding: 10px 14px 6px; margin-bottom: 10px; background: #fff; }
.cl-l { font-weight: 700; font-size: 14px; margin-bottom: 6px; }
.cl-row { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; }
.cl-step { flex: none; width: 44px; height: 44px; padding: 0; border-radius: 50%; border: 1.5px solid var(--ink); background: #fff; color: var(--ink); font: 700 24px/1 var(--f-mono); display: grid; place-items: center; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.cl-step:disabled { opacity: 0.35; cursor: default; }
@media (hover: hover) { .cl-step:not(:disabled):hover { background: #EEF0FA; } }
.cl-n { min-width: 3.3ch; text-align: center; font: 700 40px/1 var(--f-mono); letter-spacing: -0.02em; color: var(--ink); }
.cl-pays { flex: 1 1 104px; min-width: 0; margin-left: 4px; font-size: 13.5px; line-height: 1.25; color: var(--ink-3); }   /* beside the number; on a phone it takes two lines there */
.cl-pays b { font-size: 18px; color: var(--ink); }
/* The slider runs from one point above autopilot to the top plan. The rail behind it and the marks under it run from autopilot itself (the
   rail's left end) to the top plan (its right end): the slider starts one step in, so a mark sits exactly under the place the thumb has at
   that number, however wide the band is. --span is the band's width in points, --p a mark's place on it (0 to 1), --t the thumb's width. */
.cl-slide { --t: 28px; position: relative; margin-top: 4px; padding-bottom: 40px; }
.cl-slide::before { content: ""; position: absolute; left: calc(var(--t) / 2); right: calc(var(--t) / 2); top: 14px; height: 8px; border-radius: 999px; background: #E1E5EF; }
.cl-slide input[type=range] { -webkit-appearance: none; appearance: none; position: relative; display: block; box-sizing: border-box; height: 36px; padding: 0; margin: 0 0 0 calc((100% - var(--t)) / var(--span)); width: calc(100% - (100% - var(--t)) / var(--span)); background: none; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.cl-slide input[type=range]::-webkit-slider-runnable-track { height: 8px; background: none; }
.cl-slide input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; box-sizing: border-box; width: var(--t); height: var(--t); margin-top: calc(4px - var(--t) / 2); border-radius: 50%; background: #3E4690; border: 3px solid #fff; box-shadow: 0 0 0 1.5px var(--ink); }
.cl-slide input[type=range]::-moz-range-track { height: 8px; background: none; }
.cl-slide input[type=range]::-moz-range-thumb { box-sizing: border-box; width: var(--t); height: var(--t); border-radius: 50%; background: #3E4690; border: 3px solid #fff; box-shadow: 0 0 0 1.5px var(--ink); }
.cl-slide input[type=range]:focus-visible { outline: none; }
.cl-slide input[type=range]:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 1.5px var(--ink), 0 0 0 5px rgba(62, 70, 144, 0.35); }
.cl-slide input[type=range]:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 1.5px var(--ink), 0 0 0 5px rgba(62, 70, 144, 0.35); }
.cl-slide input[type=range]:disabled { opacity: 0.5; cursor: default; }
.cl-marks { position: absolute; left: 0; right: 0; top: 30px; height: 46px; pointer-events: none; }
.cl-mark { position: absolute; top: 0; left: calc(var(--t) / 2 + (100% - var(--t)) * var(--p)); width: 0; }
.cl-mark i { position: absolute; left: -1px; top: 0; width: 2px; height: 9px; border-radius: 1px; background: var(--ink); }
.cl-mark > span { position: absolute; top: 11px; display: grid; font: 10.5px/1.2 var(--f-mono); color: var(--ink-3); white-space: nowrap; }
.cl-mark b { font-size: 12.5px; color: var(--ink); }
.cl-mark.a > span { left: calc(var(--t) / -2); justify-items: start; }
.cl-mark.m > span { left: 0; transform: translateX(-50%); justify-items: center; }
.cl-mark.z > span { right: calc(var(--t) / -2); justify-items: end; }
@media (forced-colors: active) { .cl-slide::before { background: GrayText; } .cl-slide input[type=range]::-webkit-slider-thumb { background: Highlight; } .cl-mark i { background: CanvasText; } }
@media (max-width: 760px) {
  .dl-who { padding: 6px 10px; gap: 10px; }
  .dl-who .buddy-md { width: 72px; height: 72px; }
  .dl-call { padding: 8px 12px 4px; }
  .cl-n { font-size: 36px; }
}

/* ---------------- the goal strip (#goalStrip, js/campaign.js goalStrip) ----------------
   Between the hall and the plate card, in a shopper run from Start Monday to Sunday night: the call, and today's energy against resting
   energy. Two parts that may wrap; a piece between two dots stays whole. Ink on white, and nothing in it changes colour. */
.goal-strip { flex: none; position: relative; z-index: 1; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 20px; padding: 3px 16px 4px; background: #fff; color: var(--ink); border-top: 2px solid var(--ink); font-size: 12.5px; line-height: 1.4; }
.goal-strip[hidden] { display: none; }
.gs-part { min-width: 0; }
.gs-bit { white-space: nowrap; }
.goal-strip b, .run-goal b { font: 700 1em var(--f-mono); }
.goal-strip i, .run-goal i { font-style: normal; color: var(--muted); }
@media (max-width: 760px) { .goal-strip { padding: 2px 10px 3px; gap: 0 12px; font-size: 11px; line-height: 1.3; } }
/* The strip's height comes out of the charts under the stage, not out of the hall, so the doors keep the height they have without it (the
   shares are css/home.css's own for each window: 59%, 64% on a laptop, 70% on a phone; a phone on its side keeps its 60%). */
@media (min-width: 761px) and (min-height: 521px) {
  body.view-doors.has-strip .stage { flex-basis: calc(59% + 27px); }
  body.view-doors.has-strip .vitals { flex-basis: calc(41% - 27px); }
}
@media (min-width: 761px) and (min-height: 521px) and (max-height: 1000px) {
  body.view-doors.has-strip .stage { flex-basis: calc(64% + 27px); }
  body.view-doors.has-strip .vitals { flex-basis: calc(36% - 27px); }
}
@media (max-width: 760px) and (min-height: 521px), (max-width: 760px) and (orientation: portrait) {   /* a phone held upright (not one on its side, whatever its width) */
  body.view-doors.has-strip .stage, body.view-doors.has-strip.has-typ .stage { flex-basis: calc(70% + 34px); }
  body.view-doors.has-strip .vitals, body.view-doors.has-strip.has-typ .vitals { flex-basis: calc(30% - 34px); }
}
/* A phone on its side: .doors is a row there (the hall, then the plate card beside it), so the strip would become a middle column. It gets
   a row of its own across the top instead: the same two columns under it, as a grid. */
@media (orientation: landscape) and (max-height: 520px) {
  body.view-doors.has-strip .doors { display: grid; grid-template-columns: minmax(0, 56fr) minmax(0, 44fr); grid-template-rows: auto minmax(0, 1fr); }
  body.view-doors.has-strip .goal-strip { grid-column: 1 / -1; grid-row: 1; padding: 1px 12px 2px; gap: 0 14px; font-size: 11px; line-height: 1.3; border-top: 0; border-bottom: 1px solid var(--ink); }
  body.view-doors.has-strip .hall { grid-column: 1; grid-row: 2; }
  body.view-doors.has-strip .d-plate { grid-column: 2; grid-row: 2; }
}
/* the same line on the morning card and in the Goals panel, in place of goal rows */
.run-goal { background: var(--card); border: 1px solid var(--line); border-radius: 10px; padding: 8px 10px; font-size: 13.5px; line-height: 1.4; }

/* ---------------- 10 PM asked because the day is under resting energy ----------------
   The title then reads "Late night · 10:00 PM · today is under resting energy", which is wider than a phone: in a shopper run the hall's
   title may wrap (every other title is short and stays on its one line). */
body.has-strip .hall .hall-head { min-width: 0; }
body.has-strip .hall .hall-title { min-width: 0; white-space: normal; text-wrap: balance; }

/* ---------------- the day report's line: eaten against resting energy ---------------- */
.run-day { margin: -4px 0 12px; padding: 8px 10px; border: 1px solid #C8CCD8; border-radius: 8px; background: #fff; font-size: 12.5px; line-height: 1.4; text-wrap: pretty; }

/* ---------------- the Sunday card (js/campaign.js endShopperRun) ----------------
   An info sheet. The run score is the largest thing on it: ink on a white box with an ink border (the call on the deal card has the same box),
   the sum in plain words under it, and, for a ranked run that is not counted, the reason as a plain fact in a hairline box. The shopper's
   drawing sits beside the sentence about its outline. Nothing here changes colour; no tick, no red, no green. */
.sd-head { padding-right: 36px; }   /* the line over the title is long: it stops short of the close button */
.sd-score { background: #fff; border: 1.5px solid var(--ink); border-radius: 12px; padding: 10px 14px 12px; margin: -6px 0 10px; }
.sd-n { margin: 0; line-height: 1.1; }
.sd-l { font-weight: 700; font-size: 15px; margin-right: 6px; }
.sd-v { font-size: 44px; font-weight: 700; letter-spacing: -0.02em; color: var(--ink); }
.sd-how { margin: 6px 0 0; font-size: 13.5px; line-height: 1.4; color: var(--ink-3); text-wrap: pretty; max-width: 66ch; }
.sd-sum { white-space: nowrap; }   /* the sum stays on one line: it moves down as a whole when the sentence wraps */
.sd-off { margin: 0 0 10px; padding: 8px 10px; border: 1px solid #C8CCD8; border-radius: 8px; background: #fff; font-size: 13px; line-height: 1.4; text-wrap: pretty; }
.sd-who { display: flex; align-items: center; gap: 12px; background: #fff; border: 1px solid var(--line); border-radius: 12px; padding: 8px 12px; margin: 0 0 12px; }
.sd-who .buddy-md { width: 88px; height: 88px; }
.sd-who b { font: 17px var(--f-display); letter-spacing: 0.02em; }
.sd-who p { margin: 3px 0 0; font-size: 13.5px; line-height: 1.4; text-wrap: pretty; }
.sd-labs { margin-top: 12px; }
.sd-labs th:not(:first-child) { text-align: right; }
.sd-link { margin: 10px 0 0; }
.sd-link .link-btn { color: var(--ink); }   /* a link in ink: the app's link colour is the brand red, and nothing this build adds is red */
@media (hover: hover) { .sd-link .link-btn:hover { color: var(--ink-3); } }
@media (max-width: 560px) {
  .sd-v { font-size: 40px; }
  .sd-who { gap: 10px; padding: 6px 10px; }
  .sd-who .buddy-md { width: 72px; height: 72px; }
}

/* ---------------- My bests (js/campaign.js openBests) ----------------
   One row for each ranked run: place, who, the call and where the week ended, the date, the run score. Rows that are not counted follow under
   their own heading, with the reason in a few words in place of a place. Ink on white; no weight, no size, nothing that judges. */
.bst-list { list-style: none; margin: 0 0 14px; padding: 0; display: grid; gap: 6px; }
.bst-h { margin: 18px 0 6px; font: 15px var(--f-display); letter-spacing: 0.02em; }
.bst-none { margin: 0 0 12px; color: var(--ink-3); }
.bst { display: grid; grid-template-columns: 2.2rem minmax(0, 1.1fr) minmax(0, 1.5fr) auto 5.5rem; align-items: center; gap: 2px 14px; background: #fff; border: 1px solid var(--line); border-radius: 10px; padding: 8px 12px; }
.bst-n { font: 700 18px var(--f-mono); text-align: center; color: var(--ink); }
.bst-off .bst-n { font-weight: 400; color: var(--muted); }
.bst-who { display: grid; min-width: 0; }
.bst-who b { font-size: 15px; overflow-wrap: anywhere; }
.bst-who small { font-size: 12px; color: var(--muted); }
.bst-call { display: grid; min-width: 0; font: 13px/1.35 var(--f-mono); color: var(--ink-3); }
.bst-call em { font: normal 13px/1.35 var(--f-body); color: var(--ink); }
.bst-date { font-size: 12.5px; color: var(--muted); white-space: nowrap; }
.bst-score { display: grid; justify-items: end; }
.bst-score b { font: 700 22px/1.1 var(--f-mono); color: var(--ink); }
.bst-score small { font: 10.5px var(--f-mono); color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; }
@media (max-width: 560px) {
  .bst { grid-template-columns: 1.8rem minmax(0, 1fr) auto; grid-template-areas: "n who score" ". call date"; gap: 2px 10px; }
  .bst-n { grid-area: n; }
  .bst-who { grid-area: who; }
  .bst-score { grid-area: score; }
  .bst-call { grid-area: call; }
  .bst-date { grid-area: date; text-align: right; align-self: end; }
}

/* ============================================================================================================
   THE QUICK RUN (js/campaign.js: quick, quickBody, goalStrip, showPayoff, showDayLine; the owner's direction of Oct 9: "fast dopamine during game play",
   "a more forced interactive mode with fewer options")
   A shopper run from the deal card to Sunday night plays one decision at a time with a payoff after each. body.quick-run is on while one is live.
   Nothing is removed from the page or the code: Your Week, the stories and the aisle show all of it.
   ============================================================================================================ */

/* ---------------- fewer options ----------------
   Hidden: the swap-foods button (and, in js/doors.js, the S key that opened the swap view), Shuffle, the "typical" boxes, the plate card's peak line, door
   blurb, the two readings (insulin load, nutrient density, with their notes) and the "Gives" and absorption notes, the monitor button, the charts under the
   doors, the aisle's tabs and search. Skip is hidden except where it is "Go to bed" (the 10 PM stop) or the only way on (no door sells anything here). The
   portion dial is hidden except at 10 PM when the day so far is under the shopper's resting energy (the card says is-under then); its logic is untouched.
   What stays: the four doors and their signs, the card's door name, the food chips and Eat, the temptation and workout cards, the goal strip. */
body.quick-run .vitals,
body.quick-run .dr-typ,
body.quick-run #btnMonitor,
body.quick-run .aisle-head,
body.quick-run #dSwap,
body.quick-run #dShuffle,
body.quick-run .d-plate .dp-fx > :not(.dp-pk),
body.quick-run .d-plate .dp-sub,
body.quick-run .d-plate .rdo,
body.quick-run .d-plate .dp-nut2 { display: none !important; }
/* Skip stays visible in a quick run (owner, Oct 10): skipping a meal is a real choice with a willpower cost and a hungrier afternoon. */
body.quick-run .d-plate .dp-skip { font-size: .85em; opacity: .85; }
body.quick-run .d-plate:not(.is-under) .dp-por { display: none !important; }

/* With the charts gone the hall has the height: on a wide, tall screen the doors are drawn a quarter larger (the skin draws everything in --u). */
@media (min-width: 1180px) and (min-height: 760px) {
  body.quick-run .hall { --u: 1.62px; }
  body.quick-run .hall .door { max-width: 252px; max-height: 410px; }
}

/* ---------------- the goal strip: a progress bar ----------------
   Mito HP now against the call, across the span from autopilot (left end) to the top plan (right end): the fill is where Mito HP is, the tick is the
   call. Ink on a light track; nothing here changes colour, no red, no green. The words: today's weekday, "Beat 481 by Sunday night", Mito HP now. */
body.quick-run .goal-strip { display: block; padding: 5px 16px 7px; font-size: 13px; line-height: 1.35; }
.gq-top { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 14px; min-width: 0; }
.gq-day { font: 700 11.5px var(--f-mono); letter-spacing: 0.07em; text-transform: uppercase; color: var(--ink-3); }
.gq-beat { font-weight: 700; }
.gq-beat b, .gq-now b { font-family: var(--f-mono); }
.gq-now { margin-left: auto; color: var(--ink-3); white-space: nowrap; }
.gq-now b { color: var(--ink); }
.gq-bar { display: flex; align-items: center; gap: 8px; margin-top: 4px; }
.gq-end { flex: none; font: 10.5px/1 var(--f-mono); color: var(--muted); }
.gq-track { position: relative; flex: 1; height: 8px; border-radius: 999px; background: #E1E5EF; }
.gq-fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 999px; background: #3E4690; transition: width 0.5s ease; }
.gq-tick { position: absolute; top: -4px; bottom: -4px; width: 2px; margin-left: -1px; border-radius: 1px; background: var(--ink); text-decoration: none; }
.gq-off { margin-top: 3px; font-size: 11.5px; color: var(--ink-3); }
.run-goal.run-bar { padding: 8px 12px 9px; }
@media (max-width: 760px) {
  body.quick-run .goal-strip { padding: 3px 10px 5px; font-size: 12px; }
  .gq-top { gap: 0 10px; }
  .gq-day { font-size: 10.5px; }
  .gq-bar { margin-top: 3px; gap: 6px; }
  .gq-end { font-size: 10px; }
  .gq-off { font-size: 11px; }
}
@media (prefers-reduced-motion: reduce) { .gq-fill { transition: none; } }

/* ---------------- the hall in a quick run: pops, the one-time hint, a little more door ----------------
   The charts the pops used to sit on are hidden, so a pop (a crash, the flicker of the lights) shows under the hall's sign. The hint is a small
   bubble above the doors on Monday's breakfast, until a door has been peeked; js/doors.js places it. */
.q-pops, .q-hint { display: none; }
body.quick-run .q-pops { display: flex; position: absolute; left: 50%; top: 44px; z-index: 4; transform: translateX(-50%); flex-direction: column; align-items: center; gap: 3px; pointer-events: none; max-width: calc(100% - 20px); }
body.quick-run .q-pops .spop { white-space: normal; text-align: center; }
body.quick-run .hall[data-hint] .q-hint { display: block; position: absolute; left: 50%; top: 22%; z-index: 4; transform: translateX(-50%); pointer-events: none; padding: 6px 18px 7px; border-radius: 999px; background: var(--ink); color: #fff; font: 15px/1.1 var(--f-display); letter-spacing: 0.04em; white-space: nowrap; box-shadow: 0 6px 18px rgba(10,12,40,0.35); animation: qBob 1.2s ease-in-out infinite; }
body.quick-run .hall[data-hint] .q-hint::after { content: ""; position: absolute; left: 50%; bottom: -7px; margin-left: -7px; border: 7px solid transparent; border-bottom: 0; border-top-color: var(--ink); }
@keyframes qBob { 50% { transform: translate(-50%, 6px); } }
@media (prefers-reduced-motion: reduce) { body.quick-run .hall[data-hint] .q-hint { animation: none; } }

/* ---------------- the payoff card (js/campaign.js showPayoff) ----------------
   Over the hall for about a second after a plate, a temptation or a workout. The whole overlay is one button: a tap anywhere goes on. The peak and its
   word are the Spike or Flat reveal's (.j-peak, .j-word, the reel), in ink: "blunted it", "fed it" or "as usual", laid out hidden and shown when the reel lands. */
.moment.payoff-moment { padding: 0; place-items: stretch; overflow: hidden; background: rgba(23,26,58,0.36); }
.moment.payoff-moment .moment-card { width: 100%; height: 100%; animation: none; }
@media (max-width: 760px) { .moment.payoff-moment { position: fixed; inset: 0; z-index: 40; } }
.payoff { all: unset; box-sizing: border-box; display: grid; place-items: center; width: 100%; height: 100%; padding: 14px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.payoff:focus-visible .po-card { outline: 3px solid var(--tag); outline-offset: 3px; }
.po-card { display: grid; gap: 7px; justify-items: center; min-width: min(300px, 86vw); max-width: min(440px, 92vw); padding: 14px 26px 18px; background: #fff; color: var(--ink); border-radius: 20px; box-shadow: 0 18px 50px rgba(10,12,40,0.4); text-align: center; font: 15px/1.35 var(--f-body); animation: dcIn 0.22s ease; }
.po-title { font: 14.5px/1.25 var(--f-display); letter-spacing: 0.02em; text-wrap: balance; }
.po-peak { display: flex; align-items: center; justify-content: center; gap: 4px 14px; flex-wrap: wrap; margin: 2px 0; }
.payoff .j-peak, .payoff .j-peak.over { font-size: 54px; min-width: 0; color: var(--ink); }
.payoff .j-peak.words { font-size: 30px; }
.payoff .j-word { font-size: 26px; text-align: left; color: var(--ink); }
.payoff .po-vs { visibility: hidden; } .payoff .po-vs.on { visibility: visible; }
.po-row { display: flex; align-items: baseline; justify-content: center; gap: 4px 9px; flex-wrap: wrap; font-size: 14px; color: var(--ink-3); }
.po-n { font-size: 26px; line-height: 1.1; color: var(--ink); }
.po-combo .po-n { font-size: 22px; }
@media (max-width: 760px) {
  .po-card { padding: 12px 20px 16px; }
  .payoff .j-peak, .payoff .j-peak.over { font-size: 46px; }
  .payoff .j-word { font-size: 23px; }
}

/* ---------------- the day's one line (js/campaign.js showDayLine) ---------------- */
.dayline-moment .moment-card { width: min(520px, 100%); }
.dayline { display: grid; gap: 14px; justify-items: center; text-align: center; background: #fff; border-radius: 18px; padding: 20px 22px 18px; box-shadow: 0 18px 50px rgba(10,12,40,0.4); }
.dy-sum { margin: 0; font-size: 17px; line-height: 1.45; text-wrap: balance; }
.dy-sum b.mono { font-size: 21px; }
.dayline .btn { min-width: 180px; }

/* ---------------- the deal card, shrunk (js/campaign.js openDeal) ----------------
   The shopper, one line, the call as "Beat 481 by Sunday night", what reaching it pays, Start Monday. "Set your own target" opens the minus, plus and
   slider (.dl-set); the (i) opens the week's twists, the rule in full, the ranked run's rule and the small print (.dl-more). */
.deal .dl-target { display: grid; gap: 4px; justify-items: start; border: 1.5px solid var(--ink); border-radius: 12px; background: #fff; padding: 10px 14px 8px; margin: 0 0 10px; }
.dl-beat { margin: 0; font: 19px/1.2 var(--f-display); letter-spacing: 0.02em; }
.dl-beat b { font: 700 38px/1 var(--f-mono); letter-spacing: -0.02em; margin: 0 3px; vertical-align: -3px; }
.dl-rule1 { margin: 0; font-size: 13.5px; line-height: 1.45; color: var(--ink-3); text-wrap: pretty; }
.dl-rule1 b { font-size: 14.5px; color: var(--ink); }
.dl-i { position: relative; display: inline-grid; place-items: center; width: 21px; height: 21px; margin-left: 3px; padding: 0; border: 1.5px solid var(--ink-3); border-radius: 50%; background: #fff; color: var(--ink-3); font: italic 700 13px/1 Georgia, "Times New Roman", serif; vertical-align: -4px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.dl-i::before { content: ""; position: absolute; inset: -12px; }   /* the tap target is about 45px */
.dl-i[aria-expanded="true"] { background: var(--ink); border-color: var(--ink); color: #fff; }
.dl-edit { padding: 2px 0 4px; font-size: 13px; }
.dl-edit[aria-expanded="true"] { color: var(--ink); }
.dl-set, .dl-more { margin: 0 0 8px; }
.dl-more { padding: 8px 12px 10px; border: 1px solid var(--line); border-radius: 10px; background: var(--paper); }
.dl-more .dl-week { margin-bottom: 8px; }
.dl-more .dl-small { margin: 4px 0 0; }
.dl-beat { text-wrap: balance; }
@media (max-width: 760px) {
  .dl-beat { font-size: 16px; }
  .dl-beat b { font-size: 33px; vertical-align: -2px; }
}

/* ---------------- the opening (js/campaign.js openDeal): the deal card as three screens on one card ----------------
   1 the shopper drawn big, who they are and the job; 2 the stakes (Mito HP, how a plate moves it, the call and the goal strip's bar, the (i)); 3 the first move.
   Ink on white, nothing in it changes colour. */
.deal-moment .moment-card { width: min(520px, 100%); }
.deal { text-align: center; }
.deal .m-head { text-align: center; }
.deal .m-actions { flex-direction: column; align-items: center; gap: 6px; margin-top: 14px; }
.deal .m-actions .btn.big { width: min(100%, 320px); }
.op-stage { display: grid; place-items: center; margin: 0 0 2px; }
.buddy-xl { width: 200px; height: 200px; flex: none; -webkit-mask-image: radial-gradient(closest-side, #000 94%, transparent 100%); mask-image: radial-gradient(closest-side, #000 94%, transparent 100%); }   /* the halo is a soft disc, not a box */
.deal .op-meet { margin: 4px 0 4px; font: 30px/1.15 var(--f-display); letter-spacing: 0.01em; text-wrap: balance; }
.op-job { margin: 0; font-size: 17px; line-height: 1.35; color: var(--ink-3); text-wrap: balance; }
.op-stakes { display: grid; gap: 6px; margin: 2px 0 12px; }
.op-mito { margin: 0; font: 26px/1.2 var(--f-display); letter-spacing: 0.01em; text-wrap: balance; }
.op-mito b { font: 700 40px/1 var(--f-mono); letter-spacing: -0.02em; margin: 0 2px; vertical-align: -3px; }
.op-how { margin: 0; font-size: 16px; line-height: 1.4; color: var(--ink-3); text-wrap: balance; }
.deal .op-target { justify-items: stretch; gap: 8px; text-align: center; }
.deal .op-target .dl-beat { text-align: center; }
.op-target .gq-bar { margin-top: 0; }
.op-tools { display: flex; justify-content: center; margin: 4px 0 6px; }
.op-tools .dl-i { margin: 0; }
.deal .dl-more { text-align: left; margin-top: 4px; }
.deal .dl-more .dl-facts { margin: 0 0 6px; }
.deal .dl-more .dl-rule1 { margin: 0 0 4px; }
.deal .dl-more .dl-set { margin: 4px 0 8px; }
.deal .op-made { margin: 6px 0 0; font-size: 11.5px; line-height: 1.35; color: var(--muted); text-wrap: balance; }
.op-first { display: grid; gap: 10px; margin: 18px 0 6px; }
.op-tap { margin: 0; font: 28px/1.2 var(--f-display); letter-spacing: 0.01em; text-wrap: balance; }
.op-eat { margin: 0; font-size: 18px; line-height: 1.35; color: var(--ink-3); text-wrap: balance; }
@media (max-width: 760px) {
  .buddy-xl { width: 168px; height: 168px; }
  .deal .op-meet { font-size: 26px; }
  .op-job { font-size: 16px; }
  .op-mito { font-size: 23px; }
  .op-mito b { font-size: 36px; }
  .op-how { font-size: 15px; }
  .op-tap { font-size: 24px; }
  .op-eat { font-size: 16px; }
  .op-first { margin: 12px 0 4px; }
}
@media (max-height: 640px) { .buddy-xl { width: 120px; height: 120px; } }

/* the first two payoff cards carry one more line, once each (js/campaign.js showPayoff) */
.po-tip { font-size: 14px; line-height: 1.3; color: var(--ink-3); }

/* ---------------- click to edit the food (js/doors.js swapChip, setOpt) ----------------
   A food chip on the quick plate card is a button: a tap opens the swap view on that food (a small ⇄ says so). Walk after and Veggies first are two small
   toggles under the chips, in white and ink (no colour for on or off). While the swap view is open the aisle's tabs and search show, which the quick run
   hides everywhere else. */
body.quick-run.swapping .aisle-head { display: flex !important; }
.d-plate .dp-chip-swap { display: inline-flex; align-items: center; gap: 6px; border: 0; font-family: inherit; line-height: 1.25; text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.d-plate .dp-chip-swap .dp-sw { flex: none; font-size: 11px; line-height: 1; color: var(--ink-3); }
.d-plate .dp-chip-swap:hover { background: #E4E7F6; }
.d-plate .dp-chip-swap:focus-visible, .d-plate .dp-tog:focus-visible { outline: 3px solid var(--tag); outline-offset: 2px; }
.d-plate .dp-chip-swap:disabled { cursor: default; }
body.quick-run .d-plate .dp-chip-swap { padding: 6px 12px; min-height: 32px; }
.dp-opts { display: flex; flex-wrap: wrap; gap: 6px; }
.d-plate .dp-tog { border: 1px solid rgba(255,255,255,0.5); background: transparent; color: #fff; border-radius: 999px; padding: 6px 12px; min-height: 32px; font: 700 12.5px/1.2 var(--f-body); cursor: pointer; -webkit-tap-highlight-color: transparent; }
.d-plate .dp-tog.on { background: #fff; border-color: #fff; color: var(--ink); }
.d-plate .dp-tog:disabled { cursor: default; opacity: 0.7; }
